diff --git a/src/Makefile.local b/src/Makefile.local index 2490e20..1b57344 100644 --- a/src/Makefile.local +++ b/src/Makefile.local @@ -10,7 +10,7 @@ # settings, so we can avoid changing the main one for all of # our local setups. # -# Version: @(#)Makefile.local 1.0.8 2018/04/23 +# Version: @(#)Makefile.local 1.0.9 2018/09/15 # # Author: Fred N. van Kempen, # @@ -65,10 +65,14 @@ STUFF := # Add feature selections here. # -DANSI_CFG forces the config file to ANSI encoding -# -DENABLE_PCI_LOG=n enables logging for that module, sets level n +# -DENABLE_BUS_LOG=n enables logging for that module, sets level n # -DENABLE_KEYBOARD_LOG=n enables logging for that module, sets level n +# -DENABLE_MOUSE_LOG=n enables logging for that module, sets level n +# -DENABLE_GAME_LOG=n enables logging for that module, sets level n +# -DENABLE_PARALLEL_LOG=n enables logging for that module, sets level n # -DENABLE_SERIAL_LOG=n enables logging for that module, sets level n # -DENABLE_FDC_LOG=n enables logging for that module, sets level n +# -DENABLE_FDD_LOG=n enables logging for that module, sets level n # -DENABLE_D86F_LOG=n enables logging for that module, sets level n # -DENABLE_HDC_LOG=n enables logging for that module, sets level n # -DENABLE_HDD_LOG=n enables logging for that module, sets level n @@ -76,15 +80,15 @@ STUFF := # -DENABLE_CDROM_LOG=n enables logging for that module, sets level n # -DENABLE_CDROM_IMAGE_LOG=n enables logging for that module, sets level n # -DENABLE_CDROM_IOCTL_LOG=n enables logging for that module, sets level n -# -DENABLE_SOUND_EMU8K_LOG=n enables logging for that module, sets level n -# -DENABLE_SOUND_MPU401_LOG=n enables logging for that module, sets level n +# -DENABLE_SOUND_LOG=n enables logging for that module, sets level n +# -DENABLE_SOUND_MIDI_LOG=n enables logging for that module, sets level n # -DENABLE_SOUND_DEV_LOG=n enables logging for that module, sets level n -# -DENABLE_NIC_LOG=n enables logging for that module, sets level n -# -DENABLE_SCSI_BUS_LOG=n enables logging for that module, sets level n +# -DENABLE_NETWORK_LOG=n enables logging for that module, sets level n +# -DENABLE_NETWORK_DEV_LOG=n enables logging for that module, sets level n +# -DENABLE_SCSI_LOG=n enables logging for that module, sets level n # -DENABLE_SCSI_DISK_LOG=n enables logging for that module, sets level n # -DENABLE_SCSI_DEV_LOG=n enables logging for that module, sets level n -# -DENABLE_SCSI_X54X_LOG=n enables logging for that module, sets level n -# -DENABLE_VOODOO_LOG=n enables logging for that module, sets level n +# -DENABLE_VIDEO_LOG=n enables logging for that module, sets level n EXTRAS := diff --git a/src/config.c b/src/config.c index 49e936e..d359f1b 100644 --- a/src/config.c +++ b/src/config.c @@ -12,7 +12,7 @@ * it on Windows XP, and possibly also Vista. Use the * -DANSI_CFG for use on these systems. * - * Version: @(#)config.c 1.0.33 2018/09/03 + * Version: @(#)config.c 1.0.34 2018/10/05 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -41,7 +41,6 @@ * Boston, MA 02111-1307 * USA. */ -#include #include #include #include @@ -66,9 +65,10 @@ #include "devices/disk/hdd.h" #include "devices/disk/hdc.h" #include "devices/disk/hdc_ide.h" -#include "devices/disk/zip.h" -#include "devices/cdrom/cdrom.h" #include "devices/scsi/scsi.h" +#include "devices/scsi/scsi_device.h" +#include "devices/cdrom/cdrom.h" +#include "devices/disk/zip.h" #include "devices/network/network.h" #include "devices/sound/sound.h" #include "devices/sound/midi.h" @@ -200,7 +200,7 @@ delete_section_if_empty(const char *cat) static section_t * create_section(const char *name) { - section_t *ns = malloc(sizeof(section_t)); + section_t *ns = (section_t *)mem_alloc(sizeof(section_t)); memset(ns, 0x00, sizeof(section_t)); strncpy(ns->name, name, sizeof(ns->name)); @@ -213,7 +213,7 @@ create_section(const char *name) static entry_t * create_entry(section_t *section, const char *name) { - entry_t *ne = malloc(sizeof(entry_t)); + entry_t *ne = (entry_t *)mem_alloc(sizeof(entry_t)); memset(ne, 0x00, sizeof(entry_t)); strncpy(ne->name, name, sizeof(ne->name)); @@ -277,8 +277,6 @@ load_general(const char *cat) rctrl_is_lalt = config_get_int(cat, "rctrl_is_lalt", 0); - update_icons = config_get_int(cat, "update_icons", 1); - window_remember = config_get_int(cat, "window_remember", 0); if (window_remember) { p = config_get_string(cat, "window_coordinates", "0, 0, 0, 0"); @@ -292,7 +290,7 @@ load_general(const char *cat) sound_gain = config_get_int(cat, "sound_gain", 0); - lang_id = config_get_hex16(cat, "language", lang_id); + language = config_get_hex16(cat, "language", emu_lang_id); } @@ -364,11 +362,6 @@ save_general(const char *cat) else config_set_int(cat, "rctrl_is_lalt", rctrl_is_lalt); - if (update_icons == 1) - config_delete_var(cat, "update_icons"); - else - config_set_int(cat, "update_icons", update_icons); - if (window_remember) { config_set_int(cat, "window_remember", window_remember); @@ -384,10 +377,10 @@ save_general(const char *cat) else config_delete_var(cat, "sound_gain"); - if (lang_id == 0x0409) + if (emu_lang_id == 0x0409) config_delete_var(cat, "language"); else - config_set_hex16(cat, "language", lang_id); + config_set_hex16(cat, "language", emu_lang_id); delete_section_if_empty(cat); } @@ -401,17 +394,16 @@ load_machine(const char *cat) p = config_get_string(cat, "machine", NULL); if (p != NULL) - machine = machine_get_machine_from_internal_name(p); + machine = machine_get_from_internal_name(p); else machine = -1; - romset = machine_getromset(); cpu_manufacturer = config_get_int(cat, "cpu_manufacturer", 0); cpu = config_get_int(cat, "cpu", 0); cpu_waitstates = config_get_int(cat, "cpu_waitstates", 0); mem_size = config_get_int(cat, "mem_size", 4096); - if (mem_size < (((machines[machine].flags & MACHINE_AT) && + if ((uint32_t)mem_size < (((machines[machine].flags & MACHINE_AT) && (machines[machine].ram_granularity < 128)) ? machines[machine].min_ram*1024 : machines[machine].min_ram)) mem_size = (((machines[machine].flags & MACHINE_AT) && (machines[machine].ram_granularity < 128)) ? machines[machine].min_ram*1024 : machines[machine].min_ram); if (mem_size > 1048576) @@ -421,7 +413,12 @@ load_machine(const char *cat) enable_external_fpu = !!config_get_int(cat, "cpu_enable_fpu", 0); - enable_sync = !!config_get_int(cat, "enable_sync", 1); + time_sync = !!config_get_int(cat, "enable_sync", -1); + if (time_sync != -1) { + /* FIXME: remove this after 12/01/2018 --FvK */ + config_delete_var(cat, "enable_sync"); + } else + time_sync = !!config_get_int(cat, "time_sync", TIME_SYNC_DISABLED); } @@ -458,10 +455,10 @@ save_machine(const char *cat) else config_set_int(cat, "cpu_enable_fpu", enable_external_fpu); - if (enable_sync == 1) - config_delete_var(cat, "enable_sync"); + if (time_sync == TIME_SYNC_DISABLED) + config_delete_var(cat, "time_sync"); else - config_set_int(cat, "enable_sync", enable_sync); + config_set_int(cat, "time_sync", time_sync); delete_section_if_empty(cat); } @@ -475,7 +472,6 @@ load_video(const char *cat) if (machines[machine].fixed_vidcard) { config_delete_var(cat, "video_card"); - config_delete_var(cat, "voodoo"); video_card = VID_INTERNAL; } else { p = config_get_string(cat, "video_card", NULL); @@ -486,11 +482,12 @@ load_video(const char *cat) p = "none"; } video_card = video_get_video_from_internal_name(p); - - video_speed = config_get_int(cat, "video_speed", -1); - - voodoo_enabled = !!config_get_int(cat, "voodoo", 0); } + + /*FXME: remove by 12/01/2018 --FvK */ + config_delete_var(cat, "video_speed"); + + voodoo_enabled = !!config_get_int(cat, "voodoo", 0); } @@ -498,13 +495,7 @@ load_video(const char *cat) static void save_video(const char *cat) { - config_set_string(cat, "video_card", - video_get_internal_name(video_old_to_new(video_card))); - - if (video_speed == 3) - config_delete_var(cat, "video_speed"); - else - config_set_int(cat, "video_speed", video_speed); + config_set_string(cat, "video_card", video_get_internal_name(video_card)); if (voodoo_enabled == 0) config_delete_var(cat, "voodoo"); @@ -625,11 +616,11 @@ load_sound(const char *cat) mpu401_standalone_enable = !!config_get_int(cat, "mpu401_standalone", 0); - p = config_get_string(cat, "opl3_type", "dbopl"); + p = config_get_string(cat, "opl_type", "dbopl"); if (!strcmp(p, "nukedopl") || !strcmp(p, "1")) - opl3_type = 1; + opl_type = 1; else - opl3_type = 0; + opl_type = 0; p = config_get_string(cat, "sound_type", "float"); if (!strcmp(p, "float") || !strcmp(p, "1")) @@ -660,10 +651,10 @@ save_sound(const char *cat) else config_set_int(cat, "mpu401_standalone", mpu401_standalone_enable); - if (opl3_type == 0) - config_delete_var(cat, "opl3_type"); + if (opl_type == 0) + config_delete_var(cat, "opl_type"); else - config_set_string(cat, "opl3_type", (opl3_type == 1) ? "nukedopl" : "dbopl"); + config_set_string(cat, "opl_type", (opl_type == 1) ? "nukedopl" : "dbopl"); if (sound_is_float == 1) config_delete_var(cat, "sound_type"); @@ -819,7 +810,7 @@ save_ports(const char *cat) static void load_other(const char *cat) { - char temp[512], *p; + char temp[128], *p; int c; p = config_get_string(cat, "scsi_card", "none"); @@ -834,11 +825,8 @@ load_other(const char *cat) } hdc_type = hdc_get_from_internal_name(p); - for (c = 2; c < 4; c++) { - sprintf(temp, "ide_%02i", c + 1); - p = config_get_string(cat, temp, "0, 00"); - sscanf(p, "%i, %02i", &ide_enable[c], &ide_irq[c]); - } + ide_ter_enabled = !!config_get_int(cat, "ide_ter", 0); + ide_qua_enabled = !!config_get_int(cat, "ide_qua", 0); bugger_enabled = !!config_get_int(cat, "bugger_enabled", 0); @@ -862,7 +850,7 @@ load_other(const char *cat) static void save_other(const char *cat) { - char temp[512], tmp2[512]; + char temp[512]; int c; if (scsi_card == 0) @@ -873,14 +861,15 @@ save_other(const char *cat) config_set_string(cat, "hdc", hdc_get_internal_name(hdc_type)); - for (c = 2; c < 4; c++) { - sprintf(temp, "ide_%02i", c+1); - sprintf(tmp2, "%i, %02i", !!ide_enable[c], ide_irq[c]); - if (ide_enable[c] == 0) - config_delete_var(cat, temp); - else - config_set_string(cat, temp, tmp2); - } + if (ide_ter_enabled == 0) + config_delete_var(cat, "ide_ter"); + else + config_set_int(cat, "ide_ter", ide_ter_enabled); + + if (ide_qua_enabled == 0) + config_delete_var(cat, "ide_qua"); + else + config_set_int(cat, "ide_qua", ide_qua_enabled); if (bugger_enabled == 0) config_delete_var(cat, "bugger_enabled"); @@ -906,51 +895,26 @@ save_other(const char *cat) } -static int -tally_char(const char *str, char c) -{ - int tally; - - tally = 0; - if (str != NULL) { - while (*str) - if (*str++ == c) tally++; - } - - return(tally); -} - - /* Load "Hard Disks" section. */ static void load_disks(const char *cat) { - char temp[512], tmp2[512]; - char s[512]; - int c; - char *p; + char temp[512], tmp2[512], s[512]; + uint32_t max_spt, max_hpc, max_tracks; + uint32_t board = 0, dev = 0; wchar_t *wp; - int max_spt, max_hpc, max_tracks; - int board = 0, dev = 0; + char *p; + int c; for (c = 0; c < HDD_NUM; c++) { sprintf(temp, "hdd_%02i_parameters", c+1); p = config_get_string(cat, temp, "0, 0, 0, 0, none"); - if (tally_char(p, ',') == 3) { - sscanf(p, "%u, %u, %u, %s", - (int *)&hdd[c].spt, - (int *)&hdd[c].hpc, - (int *)&hdd[c].tracks, s); - hdd[c].wp = 0; - } else { - sscanf(p, "%u, %u, %u, %d, %s", - (int *)&hdd[c].spt, - (int *)&hdd[c].hpc, - (int *)&hdd[c].tracks, - (int *)&hdd[c].wp, s); - } - hdd[c].bus = hdd_string_to_bus(s, 0); + sscanf(p, "%u, %u, %u, %i, %s", + (unsigned *)&hdd[c].spt, (unsigned *)&hdd[c].hpc, + (unsigned *)&hdd[c].tracks, (int *)&hdd[c].wp, s); + + hdd[c].bus = hdd_string_to_bus(s); switch(hdd[c].bus) { case HDD_BUS_DISABLED: default: @@ -969,15 +933,13 @@ load_disks(const char *cat) max_tracks = 1023; break; - case HDD_BUS_IDE_PIO_ONLY: - case HDD_BUS_IDE_PIO_AND_DMA: + case HDD_BUS_IDE: max_spt = 63; max_hpc = 16; max_tracks = 266305; break; case HDD_BUS_SCSI: - case HDD_BUS_SCSI_REMOVABLE: max_spt = 99; max_hpc = 255; max_tracks = 266305; @@ -1009,8 +971,7 @@ load_disks(const char *cat) /* IDE */ sprintf(temp, "hdd_%02i_ide_channel", c+1); - if ((hdd[c].bus == HDD_BUS_IDE_PIO_ONLY) || - (hdd[c].bus == HDD_BUS_IDE_PIO_AND_DMA)) { + if (hdd[c].bus == HDD_BUS_IDE) { sprintf(tmp2, "%01u:%01u", c>>1, c&1); p = config_get_string(cat, temp, tmp2); sscanf(p, "%01u:%01u", &board, &dev); @@ -1026,8 +987,7 @@ load_disks(const char *cat) /* SCSI */ sprintf(temp, "hdd_%02i_scsi_location", c+1); - if ((hdd[c].bus == HDD_BUS_SCSI) || - (hdd[c].bus == HDD_BUS_SCSI_REMOVABLE)) { + if (hdd[c].bus == HDD_BUS_SCSI) { sprintf(tmp2, "%02u:%02u", c, 0); p = config_get_string(cat, temp, tmp2); @@ -1079,8 +1039,8 @@ save_disks(const char *cat) for (c = 0; c < HDD_NUM; c++) { sprintf(temp, "hdd_%02i_parameters", c+1); if (hdd_is_valid(c)) { - str = hdd_bus_to_string(hdd[c].bus, 0); - sprintf(tmp2, "%u, %u, %u, %d, %s", + str = hdd_bus_to_string(hdd[c].bus); + sprintf(tmp2, "%u, %u, %u, %i, %s", hdd[c].spt, hdd[c].hpc, hdd[c].tracks, hdd[c].wp, str); config_set_string(cat, temp, tmp2); } else { @@ -1100,18 +1060,21 @@ save_disks(const char *cat) config_delete_var(cat, temp); sprintf(temp, "hdd_%02i_ide_channel", c+1); - if (! hdd_is_valid(c) || ((hdd[c].bus != HDD_BUS_IDE_PIO_ONLY) && (hdd[c].bus != HDD_BUS_IDE_PIO_AND_DMA))) { + if (!hdd_is_valid(c) || (hdd[c].bus != HDD_BUS_IDE)) { config_delete_var(cat, temp); } else { - sprintf(tmp2, "%01u:%01u", hdd[c].id.ide_channel >> 1, hdd[c].id.ide_channel & 1); + sprintf(tmp2, "%01u:%01u", + hdd[c].id.ide_channel >> 1, + hdd[c].id.ide_channel & 1); config_set_string(cat, temp, tmp2); } sprintf(temp, "hdd_%02i_scsi_location", c+1); - if (! hdd_is_valid(c) || ((hdd[c].bus != HDD_BUS_SCSI) && (hdd[c].bus != HDD_BUS_SCSI_REMOVABLE))) { + if (!hdd_is_valid(c) || (hdd[c].bus != HDD_BUS_SCSI)) { config_delete_var(cat, temp); } else { - sprintf(tmp2, "%02u:%02u", hdd[c].id.scsi.id, hdd[c].id.scsi.lun); + sprintf(tmp2, "%02i:%02i", + hdd[c].id.scsi.id, hdd[c].id.scsi.lun); config_set_string(cat, temp, tmp2); } @@ -1246,8 +1209,8 @@ load_removable(const char *cat) sprintf(temp, "cdrom_%02i_parameters", c+1); p = config_get_string(cat, temp, "0, none"); - sscanf(p, "%01u, %s", &cdrom_drives[c].sound_on, s); - cdrom_drives[c].bus_type = hdd_string_to_bus(s, 1); + sscanf(p, "%01u, %s", (int *)&cdrom_drives[c].sound_on, s); + cdrom_drives[c].bus_type = cdrom_string_to_bus(s); sprintf(temp, "cdrom_%02i_speed", c+1); cdrom_drives[c].speed_idx = config_get_int(cat, temp, cdrom_speed_idx(CDROM_SPEED_DEFAULT)); @@ -1256,20 +1219,13 @@ load_removable(const char *cat) cdrom_drives[c].ide_channel = cdrom_drives[c].scsi_device_id = c + 2; sprintf(temp, "cdrom_%02i_ide_channel", c+1); - if ((cdrom_drives[c].bus_type == CDROM_BUS_ATAPI_PIO_ONLY) || - (cdrom_drives[c].bus_type == CDROM_BUS_ATAPI_PIO_AND_DMA)) { + if (cdrom_drives[c].bus_type == CDROM_BUS_ATAPI) { sprintf(tmp2, "%01u:%01u", (c+2)>>1, (c+2)&1); p = config_get_string(cat, temp, tmp2); - if (! strstr(p, ":")) { - sscanf(p, "%i", (int *)&cdrom_drives[c].ide_channel); - cdrom_drives[c].ide_channel &= 7; - } else { - sscanf(p, "%01u:%01u", &board, &dev); - - board &= 3; - dev &= 1; - cdrom_drives[c].ide_channel = (board<<1)+dev; - } + sscanf(p, "%01u:%01u", &board, &dev); + board &= 3; + dev &= 1; + cdrom_drives[c].ide_channel = (board<<1)+dev; if (cdrom_drives[c].ide_channel > 7) cdrom_drives[c].ide_channel = 7; @@ -1279,8 +1235,8 @@ load_removable(const char *cat) sprintf(tmp2, "%02u:%02u", c+2, 0); p = config_get_string(cat, temp, tmp2); sscanf(p, "%02u:%02u", - &cdrom_drives[c].scsi_device_id, - &cdrom_drives[c].scsi_device_lun); + (int *)&cdrom_drives[c].scsi_device_id, + (int *)&cdrom_drives[c].scsi_device_lun); if (cdrom_drives[c].scsi_device_id > 15) cdrom_drives[c].scsi_device_id = 15; @@ -1329,15 +1285,14 @@ load_removable(const char *cat) for (c = 0; c < ZIP_NUM; c++) { sprintf(temp, "zip_%02i_parameters", c+1); p = config_get_string(cat, temp, "0, none"); - sscanf(p, "%01u, %s", &zip_drives[c].is_250, s); - zip_drives[c].bus_type = hdd_string_to_bus(s, 1); + sscanf(p, "%01u, %s", (unsigned *)&zip_drives[c].is_250, s); + zip_drives[c].bus_type = zip_string_to_bus(s); /* Default values, needed for proper operation of the Settings dialog. */ zip_drives[c].ide_channel = zip_drives[c].scsi_device_id = c + 2; sprintf(temp, "zip_%02i_ide_channel", c+1); - if ((zip_drives[c].bus_type == ZIP_BUS_ATAPI_PIO_ONLY) || - (zip_drives[c].bus_type == ZIP_BUS_ATAPI_PIO_AND_DMA)) { + if (zip_drives[c].bus_type == ZIP_BUS_ATAPI) { sprintf(tmp2, "%01u:%01u", (c+2)>>1, (c+2)&1); p = config_get_string(cat, temp, tmp2); sscanf(p, "%01u:%01u", &board, &dev); @@ -1354,8 +1309,8 @@ load_removable(const char *cat) sprintf(tmp2, "%02u:%02u", c+2, 0); p = config_get_string(cat, temp, tmp2); sscanf(p, "%02u:%02u", - &zip_drives[c].scsi_device_id, - &zip_drives[c].scsi_device_lun); + (unsigned *)&zip_drives[c].scsi_device_id, + (unsigned *)&zip_drives[c].scsi_device_lun); if (zip_drives[c].scsi_device_id > 15) zip_drives[c].scsi_device_id = 15; @@ -1425,13 +1380,12 @@ save_removable(const char *cat) config_delete_var(cat, temp); } else { sprintf(tmp2, "%u, %s", cdrom_drives[c].sound_on, - hdd_bus_to_string(cdrom_drives[c].bus_type, 1)); + cdrom_bus_to_string(cdrom_drives[c].bus_type)); config_set_string(cat, temp, tmp2); } sprintf(temp, "cdrom_%02i_ide_channel", c+1); - if ((cdrom_drives[c].bus_type != CDROM_BUS_ATAPI_PIO_ONLY) && - (cdrom_drives[c].bus_type != CDROM_BUS_ATAPI_PIO_AND_DMA)) { + if (cdrom_drives[c].bus_type != CDROM_BUS_ATAPI) { config_delete_var(cat, temp); } else { sprintf(tmp2, "%01u:%01u", cdrom_drives[c].ide_channel>>1, @@ -1463,13 +1417,12 @@ save_removable(const char *cat) config_delete_var(cat, temp); } else { sprintf(tmp2, "%u, %s", zip_drives[c].is_250, - hdd_bus_to_string(zip_drives[c].bus_type, 1)); + zip_bus_to_string(zip_drives[c].bus_type)); config_set_string(cat, temp, tmp2); } sprintf(temp, "zip_%02i_ide_channel", c+1); - if ((zip_drives[c].bus_type != ZIP_BUS_ATAPI_PIO_ONLY) && - (zip_drives[c].bus_type != ZIP_BUS_ATAPI_PIO_AND_DMA)) { + if (zip_drives[c].bus_type != ZIP_BUS_ATAPI) { config_delete_var(cat, temp); } else { sprintf(tmp2, "%01u:%01u", zip_drives[c].ide_channel>>1, @@ -1529,7 +1482,7 @@ config_default(void) scale = 1; video_card = VID_CGA; vid_api = vidapi_from_internal_name("default");; - enable_sync = 1; + time_sync = TIME_SYNC_ENABLED; joystick_type = 0; hdc_type = 0; @@ -1566,7 +1519,7 @@ config_read(const wchar_t *fn) #endif if (f == NULL) return(0); - sec = malloc(sizeof(section_t)); + sec = (section_t *)mem_alloc(sizeof(section_t)); memset(sec, 0x00, sizeof(section_t)); memset(&config_head, 0x00, sizeof(list_t)); list_add(&sec->list, &config_head); @@ -1602,7 +1555,7 @@ config_read(const wchar_t *fn) if (buff[c] != L']') continue; /* Create a new section and insert it. */ - ns = malloc(sizeof(section_t)); + ns = (section_t *)mem_alloc(sizeof(section_t)); memset(ns, 0x00, sizeof(section_t)); strncpy(ns->name, sname, sizeof(ns->name)); list_add(&ns->list, &config_head); @@ -1632,7 +1585,7 @@ config_read(const wchar_t *fn) d = c; /* Allocate a new variable entry.. */ - ne = malloc(sizeof(entry_t)); + ne = (entry_t *)mem_alloc(sizeof(entry_t)); memset(ne, 0x00, sizeof(entry_t)); strncpy(ne->name, ename, sizeof(ne->name)); wcsncpy(ne->wdata, &buff[d], sizeof_w(ne->wdata)); @@ -1724,7 +1677,7 @@ config_load(void) /* Mark the configuration as changed. */ config_changed = 1; } else { - pclog("CONFIG: file not present or invalid, using defaults!\n"); + ERRLOG("CONFIG: file not present or invalid, using defaults!\n"); config_default(); @@ -1761,11 +1714,11 @@ config_dump(void) entry_t *ent; if (sec->name && sec->name[0]) - pclog("[%s]\n", sec->name); + INFO("[%s]\n", sec->name); ent = (entry_t *)sec->entry_head.next; while (ent != NULL) { - pclog("%s = %ls\n", ent->name, ent->wdata); + INFO("%s = %ls\n", ent->name, ent->wdata); ent = (entry_t *)ent->list.next; } @@ -1818,7 +1771,7 @@ config_get_hex16(const char *cat, const char *name, int def) { section_t *section; entry_t *entry; - int value; + unsigned int value; section = find_section(cat); if (section == NULL) @@ -1830,7 +1783,7 @@ config_get_hex16(const char *cat, const char *name, int def) sscanf(entry->data, "%04X", &value); - return(value); + return((int)value); } @@ -1839,7 +1792,7 @@ config_get_hex20(const char *cat, const char *name, int def) { section_t *section; entry_t *entry; - int value; + unsigned int value; section = find_section(cat); if (section == NULL) @@ -1851,7 +1804,7 @@ config_get_hex20(const char *cat, const char *name, int def) sscanf(entry->data, "%05X", &value); - return(value); + return((int)value); } @@ -1860,7 +1813,7 @@ config_get_mac(const char *cat, const char *name, int def) { section_t *section; entry_t *entry; - int val0 = 0, val1 = 0, val2 = 0; + unsigned int val0 = 0, val1 = 0, val2 = 0; section = find_section(cat); if (section == NULL) @@ -1872,7 +1825,7 @@ config_get_mac(const char *cat, const char *name, int def) sscanf(entry->data, "%02x:%02x:%02x", &val0, &val1, &val2); - return((val0 << 16) + (val1 << 8) + val2); + return((int)((val0 << 16) + (val1 << 8) + val2)); } diff --git a/src/cpu/386.c b/src/cpu/386.c index b2c0142..313d98b 100644 --- a/src/cpu/386.c +++ b/src/cpu/386.c @@ -6,9 +6,9 @@ * * This file is part of the VARCem Project. * - * Implementation of the CPU. + * Implementation of 80286+ CPU interpreter. * - * Version: @(#)386.c 1.0.4 2018/05/06 + * Version: @(#)386.c 1.0.5 2018/09/19 * * Authors: Sarah Walker, * Miran Grca, @@ -59,171 +59,66 @@ #define CPU_BLOCK_END() -extern int codegen_flags_changed; -extern int nmi_enable; - -int inscounts[256]; -uint32_t oldpc2; - -int trap; - -uint16_t flags,eflags; -uint32_t oldds,oldss,olddslimit,oldsslimit,olddslimitw,oldsslimitw; - -x86seg gdt,ldt,idt,tr; -x86seg _cs,_ds,_es,_ss,_fs,_gs; -x86seg _oldds; +extern int codegen_flags_changed; +extern int nmi_enable; +extern int cpl_override; +extern int fpucount; +extern int oddeven; +extern int xout; +uint16_t flags,eflags; +uint32_t oldds,oldss,olddslimit,oldsslimit,olddslimitw,oldsslimitw; +x86seg gdt,ldt,idt,tr; +x86seg _cs,_ds,_es,_ss,_fs,_gs; +x86seg _oldds; +uint32_t cr2, cr3, cr4; +uint32_t dr[8]; +int timetolive = 0; -extern int cpl_override; +/* Also in 386_dynarec.c: */ +cpu_state_t cpu_state; +int inscounts[256]; +uint32_t oldpc2; +uint32_t oldcs2; +uint32_t oxpc; +int trap; +int inttype; +int optype; +int cgate32; +uint16_t rds; +uint16_t ea_rseg; +uint32_t *eal_r, *eal_w; +uint16_t *mod1add[2][8]; +uint32_t *mod1seg[8]; -extern int fpucount; -uint16_t rds; -uint16_t ea_rseg; - -int cgate32; - -uint32_t cr2, cr3, cr4; -uint32_t dr[8]; - -uint32_t rmdat32; -#define rmdat rmdat32 +uint32_t rmdat32; +#define rmdat rmdat32 #define fetchdat rmdat32 -uint32_t backupregs[16]; -extern int oddeven; -int timetolive = 0; -int inttype; +//static int oldi; +//static uint32_t backupregs[16]; +//static uint32_t oldecx; -uint32_t oldcs2; -uint32_t oldecx; +#define fetch_ea_16(dat) \ + cpu_state.pc++; \ + cpu_mod = (dat >> 6) & 3; \ + cpu_reg = (dat >> 3) & 7; cpu_rm = dat & 7; \ + if (cpu_mod != 3) { \ + fetch_ea_16_long(dat); \ + if (cpu_state.abrt) return 0; \ + } -uint32_t *eal_r, *eal_w; - -uint16_t *mod1add[2][8]; -uint32_t *mod1seg[8]; - -#if 0 -static __inline void fetch_ea_32_long(uint32_t rmdat) -{ - eal_r = eal_w = NULL; - easeg = cpu_state.ea_seg->base; - ea_rseg = cpu_state.ea_seg->seg; - if (cpu_rm == 4) - { - uint8_t sib = rmdat >> 8; - - switch (cpu_mod) - { - case 0: - cpu_state.eaaddr = cpu_state.regs[sib & 7].l; - cpu_state.pc++; - break; - case 1: - cpu_state.pc++; - cpu_state.eaaddr = ((uint32_t)(int8_t)getbyte()) + cpu_state.regs[sib & 7].l; - /* pc++; */ - break; - case 2: - cpu_state.eaaddr = (fastreadl(cs + cpu_state.pc + 1)) + cpu_state.regs[sib & 7].l; - cpu_state.pc += 5; - break; - } - /*SIB byte present*/ - if ((sib & 7) == 5 && !cpu_mod) - cpu_state.eaaddr = getlong(); - else if ((sib & 6) == 4 && !cpu_state.ssegs) - { - easeg = ss; - ea_rseg = SS; - cpu_state.ea_seg = &_ss; - } - if (((sib >> 3) & 7) != 4) - cpu_state.eaaddr += cpu_state.regs[(sib >> 3) & 7].l << (sib >> 6); - } - else - { - cpu_state.eaaddr = cpu_state.regs[cpu_rm].l; - if (cpu_mod) - { - if (cpu_rm == 5 && !cpu_state.ssegs) - { - easeg = ss; - ea_rseg = SS; - cpu_state.ea_seg = &_ss; - } - if (cpu_mod == 1) - { - cpu_state.eaaddr += ((uint32_t)(int8_t)(rmdat >> 8)); - cpu_state.pc++; - } - else - { - cpu_state.eaaddr += getlong(); - } - } - else if (cpu_rm == 5) - { - cpu_state.eaaddr = getlong(); - } - } - if (easeg != 0xFFFFFFFF && ((easeg + cpu_state.eaaddr) & 0xFFF) <= 0xFFC) - { - uint32_t addr = easeg + cpu_state.eaaddr; - if ( readlookup2[addr >> 12] != -1) - eal_r = (uint32_t *)(readlookup2[addr >> 12] + addr); - if (writelookup2[addr >> 12] != -1) - eal_w = (uint32_t *)(writelookup2[addr >> 12] + addr); - } -} - -static __inline void fetch_ea_16_long(uint32_t rmdat) -{ - eal_r = eal_w = NULL; - easeg = cpu_state.ea_seg->base; - ea_rseg = cpu_state.ea_seg->seg; - if (!cpu_mod && cpu_rm == 6) - { - cpu_state.eaaddr = getword(); - } - else - { - switch (cpu_mod) - { - case 0: - cpu_state.eaaddr = 0; - break; - case 1: - cpu_state.eaaddr = (uint16_t)(int8_t)(rmdat >> 8); cpu_state.pc++; - break; - case 2: - cpu_state.eaaddr = getword(); - break; - } - cpu_state.eaaddr += (*mod1add[0][cpu_rm]) + (*mod1add[1][cpu_rm]); - if (mod1seg[cpu_rm] == &ss && !cpu_state.ssegs) - { - easeg = ss; - ea_rseg = SS; - cpu_state.ea_seg = &_ss; - } - cpu_state.eaaddr &= 0xFFFF; - } - if (easeg != 0xFFFFFFFF && ((easeg + cpu_state.eaaddr) & 0xFFF) <= 0xFFC) - { - uint32_t addr = easeg + cpu_state.eaaddr; - if ( readlookup2[addr >> 12] != -1) - eal_r = (uint32_t *)(readlookup2[addr >> 12] + addr); - if (writelookup2[addr >> 12] != -1) - eal_w = (uint32_t *)(writelookup2[addr >> 12] + addr); - } -} -#endif - -#define fetch_ea_16(rmdat) cpu_state.pc++; cpu_mod=(rmdat >> 6) & 3; cpu_reg=(rmdat >> 3) & 7; cpu_rm = rmdat & 7; if (cpu_mod != 3) { fetch_ea_16_long(rmdat); if (cpu_state.abrt) return 0; } -#define fetch_ea_32(rmdat) cpu_state.pc++; cpu_mod=(rmdat >> 6) & 3; cpu_reg=(rmdat >> 3) & 7; cpu_rm = rmdat & 7; if (cpu_mod != 3) { fetch_ea_32_long(rmdat); } if (cpu_state.abrt) return 0 +#define fetch_ea_32(dat) \ + cpu_state.pc++; \ + cpu_mod = (dat >> 6) & 3; \ + cpu_reg = (dat >> 3) & 7; \ + cpu_rm = dat & 7; \ + if (cpu_mod != 3) { \ + fetch_ea_32_long(dat); \ + } \ + if (cpu_state.abrt) return 0 #include "x86_flags.h" @@ -231,208 +126,164 @@ static __inline void fetch_ea_16_long(uint32_t rmdat) #define getwordf() ((uint16_t)(fetchdat)); cpu_state.pc+=2 #define getbyte2f() ((uint8_t)(fetchdat>>8)); cpu_state.pc++ #define getword2f() ((uint16_t)(fetchdat>>8)); cpu_state.pc+=2 -extern int xout; - -int oldi; - -uint32_t testr[9]; -extern int dontprint; #undef NOTRM -#define NOTRM if (!(msw & 1) || (eflags & VM_FLAG))\ - { \ +#define NOTRM if (!(msw & 1) || (eflags & VM_FLAG)) {\ x86_int(6); \ return 0; \ } #define OP_TABLE(name) ops_ ## name -#define CLOCK_CYCLES(c) cycles -= (c) -#define CLOCK_CYCLES_ALWAYS(c) cycles -= (c) +#define CLOCK_CYCLES(c) cycles -= (c) +#define CLOCK_CYCLES_ALWAYS(c) cycles -= (c) + #include "x86_ops.h" + #undef NOTRM -#define NOTRM if (!(msw & 1) || (eflags & VM_FLAG))\ - { \ +#define NOTRM if (!(msw & 1) || (eflags & VM_FLAG)) {\ x86_int(6); \ break; \ } -void exec386(int cycs) + +void +exec386(int cycs) { - uint8_t temp; - uint32_t addr; - int tempi; - int64_t cycdiff; - int oldcyc; + int64_t cycdiff; + uint32_t addr; + uint8_t temp; + int oldcyc; + int tempi; - cycles+=cycs; - /* output=3; */ - while (cycles>0) - { - int64_t cycle_period = (timer_count >> TIMER_SHIFT) + 1; - - x86_was_reset = 0; - cycdiff=0; - oldcyc=cycles; - timer_start_period(cycles << TIMER_SHIFT); - /* pclog("%i %02X\n", ins, ram[8]); */ - while (cycdiff < cycle_period) - { - /* testr[0]=EAX; testr[1]=EBX; testr[2]=ECX; testr[3]=EDX; - testr[4]=ESI; testr[5]=EDI; testr[6]=EBP; testr[7]=ESP;*/ -/* testr[8]=flags;*/ - /* oldcs2=oldcs; */ - /* oldpc2=oldpc; */ - oldcs=CS; - cpu_state.oldpc = cpu_state.pc; - oldcpl=CPL; - cpu_state.op32 = use32; + cycles += cycs; + while (cycles > 0) { + int64_t cycle_period = (timer_count >> TIMER_SHIFT) + 1; + + x86_was_reset = 0; + cycdiff = 0; + oldcyc = cycles; + timer_start_period(cycles << TIMER_SHIFT); + + while (cycdiff < cycle_period) { + oldcs = CS; + cpu_state.oldpc = cpu_state.pc; + oldcpl = CPL; + cpu_state.op32 = use32; x86_was_reset = 0; - -dontprint=0; - cpu_state.ea_seg = &_ds; - cpu_state.ssegs = 0; - - fetchdat = fastreadl(cs + cpu_state.pc); + cpu_state.ea_seg = &_ds; + cpu_state.ssegs = 0; - if (!cpu_state.abrt) - { - trap = flags & T_FLAG; - opcode = fetchdat & 0xFF; - fetchdat >>= 8; + fetchdat = fastreadl(cs + cpu_state.pc); - if (output == 3) - { - pclog("%04X(%06X):%04X : %08X %08X %08X %08X %04X %04X %04X(%08X) %04X %04X %04X(%08X) %08X %08X %08X SP=%04X:%08X %02X %04X %i %08X %08X %i %i %02X %02X %02X %02X %02X %f %02X%02X %02X%02X %02X%02X %02X\n",CS,cs,cpu_state.pc,EAX,EBX,ECX,EDX,CS,DS,ES,es,FS,GS,SS,ss,EDI,ESI,EBP,SS,ESP,opcode,flags,ins,0, ldt.base, CPL, stack32, pic.pend, pic.mask, pic.mask2, pic2.pend, pic2.mask, pit.c[0], ram[0xB270+0x3F5], ram[0xB270+0x3F4], ram[0xB270+0x3F7], ram[0xB270+0x3F6], ram[0xB270+0x3F9], ram[0xB270+0x3F8], ram[0x4430+0x0D49]); - } - cpu_state.pc++; - x86_opcodes[(opcode | cpu_state.op32) & 0x3ff](fetchdat); + if (! cpu_state.abrt) { + trap = flags & T_FLAG; + opcode = fetchdat & 0xff; + fetchdat >>= 8; + +#if 0 + DEBUG("%04X(%06X):%04X:\n %08X %08X %08X %08X\n %04X %04X %04X(%08X) %04X %04X %04X(%08X) %08X %08X %08X SP=%04X:%08X\n OPCODE=%02X FLAGS=%04X ins=%i (%08X) ldt=%08X CPL=%i %i %02X %02X %02X %02X %02X %f %02X%02X %02X%02X %02X%02X %02X\n",CS,cs,cpu_state.pc,EAX,EBX,ECX,EDX,CS,DS,ES,es,FS,GS,SS,ss,EDI,ESI,EBP,SS,ESP,opcode,flags,ins,0, ldt.base, CPL, stack32, pic.pend, pic.mask, pic.mask2, pic2.pend, pic2.mask, pit.c[0], ram[0xB270+0x3F5], ram[0xB270+0x3F4], ram[0xB270+0x3F7], ram[0xB270+0x3F6], ram[0xB270+0x3F9], ram[0xB270+0x3F8], ram[0x4430+0x0D49]); +#endif + + cpu_state.pc++; + x86_opcodes[(opcode | cpu_state.op32) & 0x3ff](fetchdat); if (x86_was_reset) break; - if(x86_was_reset) break; - } + } - if (!use32) cpu_state.pc &= 0xffff; + if (! use32) cpu_state.pc &= 0xffff; - if (cpu_state.abrt) - { - flags_rebuild(); - /* pclog("Abort\n"); */ - /* if (CS == 0x228) pclog("Abort at %04X:%04X - %i %i %i\n",CS,pc,notpresent,nullseg,cpu_state.abrt); */ -/* if (testr[0]!=EAX) pclog("EAX corrupted %08X\n",pc); - if (testr[1]!=EBX) pclog("EBX corrupted %08X\n",pc); - if (testr[2]!=ECX) pclog("ECX corrupted %08X\n",pc); - if (testr[3]!=EDX) pclog("EDX corrupted %08X\n",pc); - if (testr[4]!=ESI) pclog("ESI corrupted %08X\n",pc); - if (testr[5]!=EDI) pclog("EDI corrupted %08X\n",pc); - if (testr[6]!=EBP) pclog("EBP corrupted %08X\n",pc); - if (testr[7]!=ESP) pclog("ESP corrupted %08X\n",pc);*/ -/* if (testr[8]!=flags) pclog("FLAGS corrupted %08X\n",pc);*/ - tempi = cpu_state.abrt; - cpu_state.abrt = 0; - x86_doabrt(tempi); - if (cpu_state.abrt) - { - cpu_state.abrt = 0; - CS = oldcs; - cpu_state.pc = cpu_state.oldpc; - pclog("Double fault %i\n", ins); - pmodeint(8, 0); - if (cpu_state.abrt) - { - cpu_state.abrt = 0; - softresetx86(); + if (cpu_state.abrt) { + flags_rebuild(); +#if 0 + DEBUG("Abort\n"); + if (CS == 0x228) + DEBUG("Abort at %04X:%04X - %i\n", + CS,cpu_state.pc,cpu_state.abrt); +#endif + + tempi = cpu_state.abrt; + cpu_state.abrt = 0; + x86_doabrt(tempi); + if (cpu_state.abrt) { + cpu_state.abrt = 0; + CS = oldcs; + cpu_state.pc = cpu_state.oldpc; + INFO("CPU: double fault %i\n", ins); + pmodeint(8, 0); + if (cpu_state.abrt) { + cpu_state.abrt = 0; + softresetx86(); cpu_set_edx(); - pclog("Triple fault - reset\n"); - } - } - } - cycdiff=oldcyc-cycles; + INFO("CPU: triple fault - reset\n"); + } + } + } - if (trap) - { - flags_rebuild(); - /* oldpc=pc; */ - /* oldcs=CS; */ - if (msw&1) - { - pmodeint(1,0); - } - else - { - writememw(ss,(SP-2)&0xFFFF,flags); - writememw(ss,(SP-4)&0xFFFF,CS); - writememw(ss,(SP-6)&0xFFFF,cpu_state.pc); - SP-=6; - addr = (1 << 2) + idt.base; - flags&=~I_FLAG; - flags&=~T_FLAG; - cpu_state.pc=readmemw(0,addr); - loadcs(readmemw(0,addr+2)); - } - } - else if (nmi && nmi_enable) - { - cpu_state.oldpc = cpu_state.pc; - oldcs = CS; - /* pclog("NMI\n"); */ - x86_int(2); - nmi_enable = 0; - if (nmi_auto_clear) - { - nmi_auto_clear = 0; - nmi = 0; - } - } - else if ((flags&I_FLAG) && pic_intpending) - { - temp=picinterrupt(); - if (temp!=0xFF) - { - /* if (temp == 0x54) pclog("Take int 54\n"); */ - /* if (output) output=3; */ - /* if (temp == 0xd) pclog("Hardware int %02X %i %04X(%08X):%08X\n",temp,ins, CS,cs,pc); */ - /* if (temp==0x54) output=3; */ - flags_rebuild(); - if (msw&1) - { - pmodeint(temp,0); - } - else - { - writememw(ss,(SP-2)&0xFFFF,flags); - writememw(ss,(SP-4)&0xFFFF,CS); - writememw(ss,(SP-6)&0xFFFF,cpu_state.pc); - SP-=6; - addr = (temp << 2) + idt.base; - flags&=~I_FLAG; - flags&=~T_FLAG; - oxpc=cpu_state.pc; - cpu_state.pc=readmemw(0,addr); - loadcs(readmemw(0,addr+2)); - /* if (temp==0x76) pclog("INT to %04X:%04X\n",CS,pc); */ - } - /* pclog("Now at %04X(%08X):%08X\n", CS, cs, pc); */ - } - } + cycdiff = oldcyc - cycles; - ins++; - insc++; + if (trap) { + flags_rebuild(); - if (timetolive) - { - timetolive--; - if (!timetolive) - fatal("Life expired\n"); - } - } + if (msw & 1) { + pmodeint(1, 0); + } else { + writememw(ss, (SP-2) & 0xFFFF, flags); + writememw(ss, (SP-4) & 0xFFFF, CS); + writememw(ss, (SP-6) & 0xFFFF, cpu_state.pc); + SP -= 6; + addr = (1 << 2) + idt.base; + flags &= ~I_FLAG; + flags &= ~T_FLAG; + cpu_state.pc = readmemw(0, addr); + loadcs(readmemw(0, addr+2)); + } + } else if (nmi && nmi_enable) { + cpu_state.oldpc = cpu_state.pc; + oldcs = CS; + x86_int(2); + nmi_enable = 0; + if (nmi_auto_clear) { + nmi_auto_clear = 0; + nmi = 0; + } + } else if ((flags & I_FLAG) && pic_intpending) { + temp = picinterrupt(); + if (temp != 0xFF) { + flags_rebuild(); + + if (msw & 1) { + pmodeint(temp, 0); + } else { + writememw(ss, (SP-2) & 0xFFFF, flags); + writememw(ss, (SP-4) & 0xFFFF, CS); + writememw(ss, (SP-6) & 0xFFFF, cpu_state.pc); + SP -= 6; + addr = (temp << 2) + idt.base; + flags &= ~I_FLAG; + flags &= ~T_FLAG; + oxpc = cpu_state.pc; + cpu_state.pc = readmemw(0, addr); + loadcs(readmemw(0, addr+2)); + } + } + } + + ins++; + + if (timetolive) { + timetolive--; + if (!timetolive) + fatal("Life expired\n"); + } + } - tsc += cycdiff; - - timer_end_period(cycles << TIMER_SHIFT); - } + tsc += cycdiff; + + timer_end_period(cycles << TIMER_SHIFT); + } } diff --git a/src/cpu/386_common.h b/src/cpu/386_common.h index f011b48..15a149b 100644 --- a/src/cpu/386_common.h +++ b/src/cpu/386_common.h @@ -36,6 +36,7 @@ */ extern uint16_t ea_rseg; + #undef readmemb #undef writememb @@ -132,8 +133,7 @@ extern uint16_t ea_rseg; - -static __inline uint8_t fastreadb(uint32_t a) +static INLINE uint8_t fastreadb(uint32_t a) { uint8_t *t; @@ -147,7 +147,7 @@ static __inline uint8_t fastreadb(uint32_t a) return *((uint8_t *)&pccache2[a]); } -static __inline uint16_t fastreadw(uint32_t a) +static INLINE uint16_t fastreadw(uint32_t a) { uint8_t *t; uint16_t val; @@ -167,7 +167,7 @@ static __inline uint16_t fastreadw(uint32_t a) return *((uint16_t *)&pccache2[a]); } -static __inline uint32_t fastreadl(uint32_t a) +static INLINE uint32_t fastreadl(uint32_t a) { uint8_t *t; uint32_t val; @@ -189,25 +189,25 @@ static __inline uint32_t fastreadl(uint32_t a) return val; } -static __inline uint8_t getbyte() +static INLINE uint8_t getbyte() { cpu_state.pc++; return fastreadb(cs + (cpu_state.pc - 1)); } -static __inline uint16_t getword() +static INLINE uint16_t getword() { cpu_state.pc+=2; return fastreadw(cs+(cpu_state.pc-2)); } -static __inline uint32_t getlong() +static INLINE uint32_t getlong() { cpu_state.pc+=4; return fastreadl(cs+(cpu_state.pc-4)); } -static __inline uint64_t getquad() +static INLINE uint64_t getquad() { cpu_state.pc+=8; return fastreadl(cs+(cpu_state.pc-8)) | ((uint64_t)fastreadl(cs+(cpu_state.pc-4)) << 32); @@ -215,7 +215,7 @@ static __inline uint64_t getquad() -static __inline uint8_t geteab() +static INLINE uint8_t geteab() { if (cpu_mod == 3) return (cpu_rm & 4) ? cpu_state.regs[cpu_rm & 3].b.h : cpu_state.regs[cpu_rm&3].b.l; @@ -224,7 +224,7 @@ static __inline uint8_t geteab() return readmemb(easeg, cpu_state.eaaddr); } -static __inline uint16_t geteaw() +static INLINE uint16_t geteaw() { if (cpu_mod == 3) return cpu_state.regs[cpu_rm].w; @@ -234,7 +234,7 @@ static __inline uint16_t geteaw() return readmemw(easeg, cpu_state.eaaddr); } -static __inline uint32_t geteal() +static INLINE uint32_t geteal() { if (cpu_mod == 3) return cpu_state.regs[cpu_rm].l; @@ -244,28 +244,28 @@ static __inline uint32_t geteal() return readmeml(easeg, cpu_state.eaaddr); } -static __inline uint64_t geteaq() +static INLINE uint64_t geteaq() { return readmemq(easeg, cpu_state.eaaddr); } -static __inline uint8_t geteab_mem() +static INLINE uint8_t geteab_mem() { if (eal_r) return *(uint8_t *)eal_r; return readmemb(easeg,cpu_state.eaaddr); } -static __inline uint16_t geteaw_mem() +static INLINE uint16_t geteaw_mem() { if (eal_r) return *(uint16_t *)eal_r; return readmemw(easeg,cpu_state.eaaddr); } -static __inline uint32_t geteal_mem() +static INLINE uint32_t geteal_mem() { if (eal_r) return *eal_r; return readmeml(easeg,cpu_state.eaaddr); } -static __inline void seteaq(uint64_t v) +static INLINE void seteaq(uint64_t v) { writememql(easeg, cpu_state.eaaddr, v); } diff --git a/src/cpu/386_dynarec.c b/src/cpu/386_dynarec.c index dd9166c..0b5b113 100644 --- a/src/cpu/386_dynarec.c +++ b/src/cpu/386_dynarec.c @@ -8,7 +8,7 @@ * * Implementation of the CPU's dynamic recompiler. * - * Version: @(#)386_dynarec.c 1.0.4 2018/05/09 + * Version: @(#)386_dynarec.c 1.0.5 2018/10/05 * * Authors: Sarah Walker, * Miran Grca, @@ -53,8 +53,6 @@ #include "../devices/system/nmi.h" #include "../devices/system/pic.h" #include "../timer.h" -//#include "../devices/floppy/fdd.h" -//#include "../devices/floppy/fdc.h" #ifdef USE_DYNAREC #include "codegen.h" #endif @@ -63,49 +61,45 @@ #define CPU_BLOCK_END() cpu_block_end = 1 -uint32_t cpu_cur_status = 0; - -int cpu_reps, cpu_reps_latched; -int cpu_notreps, cpu_notreps_latched; - -int inrecomp = 0; -int cpu_recomp_blocks, cpu_recomp_full_ins, cpu_new_blocks; -int cpu_recomp_blocks_latched, cpu_recomp_ins_latched, cpu_recomp_full_ins_latched, cpu_new_blocks_latched; - -int cpu_block_end = 0; - -int nmi_enable = 1; - -int inscounts[256]; -uint32_t oldpc2; - -int trap; +/* Also in 386.c: */ +cpu_state_t cpu_state; +int inscounts[256]; +uint32_t oldpc2; +uint32_t oldcs2; +uint32_t oxpc; +int trap; +int inttype; +int optype; +int cgate32; +uint16_t rds; +uint16_t ea_rseg; +uint32_t *eal_r, *eal_w; +uint16_t *mod1add[2][8]; +uint32_t *mod1seg[8]; +uint32_t cpu_cur_status = 0; +int cpu_reps, cpu_reps_latched; +int cpu_notreps, cpu_notreps_latched; +int cpu_recomp_blocks, cpu_recomp_full_ins, cpu_new_blocks; +int cpu_recomp_blocks_latched, cpu_recomp_ins_latched, + cpu_recomp_full_ins_latched, cpu_new_blocks_latched; + +int inrecomp = 0; +int cpu_block_end = 0; +int nmi_enable = 1; int cpl_override=0; - int fpucount=0; -uint16_t rds; -uint16_t ea_rseg; +int oddeven=0; -int cgate32; uint32_t rmdat32; -uint32_t backupregs[16]; -int oddeven=0; -int inttype; +//static uint32_t backupregs[16]; +//static uint32_t oldecx; -uint32_t oldcs2; -uint32_t oldecx; - -uint32_t *eal_r, *eal_w; - -uint16_t *mod1add[2][8]; -uint32_t *mod1seg[8]; - -static __inline void fetch_ea_32_long(uint32_t rmdat) +static INLINE void fetch_ea_32_long(uint32_t rmdat) { eal_r = eal_w = NULL; easeg = cpu_state.ea_seg->base; @@ -178,7 +172,7 @@ static __inline void fetch_ea_32_long(uint32_t rmdat) cpu_state.last_ea = cpu_state.eaaddr; } -static __inline void fetch_ea_16_long(uint32_t rmdat) +static INLINE void fetch_ea_16_long(uint32_t rmdat) { eal_r = eal_w = NULL; easeg = cpu_state.ea_seg->base; @@ -246,7 +240,7 @@ void x86_int(uint32_t num) cpu_state.abrt = 0; softresetx86(); cpu_set_edx(); - pclog("Triple fault in real mode - reset\n"); + INFO("CPU: triple fault in real mode - reset\n"); } else x86_int(8); @@ -339,9 +333,9 @@ int x86_int_sw_rm(int num) if (cpu_state.abrt) return 1; - writememw(ss,((SP-2)&0xFFFF),flags); if (cpu_state.abrt) {pclog("abrt5\n"); return 1; } + writememw(ss,((SP-2)&0xFFFF),flags); if (cpu_state.abrt) {ERRLOG("abrt5\n"); return 1; } writememw(ss,((SP-4)&0xFFFF),CS); - writememw(ss,((SP-6)&0xFFFF),cpu_state.pc); if (cpu_state.abrt) {pclog("abrt6\n"); return 1; } + writememw(ss,((SP-6)&0xFFFF),cpu_state.pc); if (cpu_state.abrt) {ERRLOG("abrt6\n"); return 1; } SP-=6; eflags &= ~VIF_FLAG; @@ -464,13 +458,6 @@ int checkio(uint32_t port) int xout=0; -#if 0 -#define divexcp() { \ - pclog("Divide exception at %04X(%06X):%04X\n",CS,cs,cpu_state.pc); \ - x86_int(0); \ -} -#endif - #define divexcp() { \ x86_int(0); \ } @@ -628,7 +615,6 @@ void exec386_dynarec(int cycs) CPU_BLOCK_END(); ins++; - insc++; /* if ((cs + pc) == 4) fatal("4\n");*/ @@ -713,7 +699,7 @@ void exec386_dynarec(int cycs) if (valid_block && block->was_recompiled) { - void (*code)() = (void *)&block->data[BLOCK_START]; + void (*code)() = (void (*)())&block->data[BLOCK_START]; codeblock_hash[hash] = block; @@ -722,9 +708,6 @@ inrecomp=1; inrecomp=0; if (!use32) cpu_state.pc &= 0xffff; cpu_recomp_blocks++; -/* ins += codeblock_ins[index]; - insc += codeblock_ins[index];*/ -/* pclog("Exit block now %04X:%04X\n", CS, pc);*/ } else if (valid_block && !cpu_state.abrt) { @@ -788,7 +771,6 @@ inrecomp=0; } ins++; - insc++; } if (!cpu_state.abrt && !x86_was_reset) @@ -859,7 +841,6 @@ inrecomp=0; } ins++; - insc++; } if (!cpu_state.abrt && !x86_was_reset) @@ -884,14 +865,14 @@ inrecomp=0; cpu_state.abrt = 0; CS = oldcs; cpu_state.pc = cpu_state.oldpc; - pclog("Double fault %i\n", ins); + ERRLOG("CPU: double fault %i\n", ins); pmodeint(8, 0); if (cpu_state.abrt) { cpu_state.abrt = 0; softresetx86(); cpu_set_edx(); - pclog("Triple fault - reset\n"); + ERRLOG("CPU: triple fault - reset\n"); } } } @@ -921,7 +902,6 @@ inrecomp=0; { cpu_state.oldpc = cpu_state.pc; oldcs = CS; - pclog("NMI\n"); x86_int(2); nmi_enable = 0; if (nmi_auto_clear) @@ -939,18 +919,10 @@ inrecomp=0; flags_rebuild(); if (msw&1) { - /* if (temp == 0x0E) - { - pclog("Servicing FDC interupt (p)!\n"); - } */ pmodeint(temp,0); } else { - /* if (temp == 0x0E) - { - pclog("Servicing FDC interupt (r)!\n"); - } */ writememw(ss,(SP-2)&0xFFFF,flags); writememw(ss,(SP-4)&0xFFFF,CS); writememw(ss,(SP-6)&0xFFFF,cpu_state.pc); @@ -963,10 +935,6 @@ inrecomp=0; loadcs(readmemw(0,addr+2)); } } - /* else - { - pclog("Servicing pending interrupt 0xFF (!)!\n"); - } */ } } timer_end_period(cycles << TIMER_SHIFT); diff --git a/src/cpu/386_dynarec_ops.c b/src/cpu/386_dynarec_ops.c index b40eddc..a2f0846 100644 --- a/src/cpu/386_dynarec_ops.c +++ b/src/cpu/386_dynarec_ops.c @@ -62,7 +62,7 @@ extern uint16_t *mod1add[2][8]; extern uint32_t *mod1seg[8]; -static __inline void fetch_ea_32_long(uint32_t rmdat) +static INLINE void fetch_ea_32_long(uint32_t rmdat) { eal_r = eal_w = NULL; easeg = cpu_state.ea_seg->base; @@ -78,7 +78,7 @@ static __inline void fetch_ea_32_long(uint32_t rmdat) cpu_state.last_ea = cpu_state.eaaddr; } -static __inline void fetch_ea_16_long(uint32_t rmdat) +static INLINE void fetch_ea_16_long(uint32_t rmdat) { eal_r = eal_w = NULL; easeg = cpu_state.ea_seg->base; diff --git a/src/cpu/386_ops.h b/src/cpu/386_ops.h index 3037906..2912206 100644 --- a/src/cpu/386_ops.h +++ b/src/cpu/386_ops.h @@ -8,7 +8,7 @@ * * 286/386+ instruction handlers list. * - * Version: @(#)386_ops.h 1.0.2 2018/05/05 + * Version: @(#)386_ops.h 1.0.3 2018/10/05 * * Authors: Fred N. van Kempen, * Sarah Walker, @@ -52,7 +52,7 @@ } \ } while (0) -static __inline void PUSH_W(uint16_t val) +static INLINE void PUSH_W(uint16_t val) { if (stack32) { @@ -68,7 +68,7 @@ static __inline void PUSH_W(uint16_t val) } } -static __inline void PUSH_L(uint32_t val) +static INLINE void PUSH_L(uint32_t val) { if (stack32) { @@ -84,7 +84,7 @@ static __inline void PUSH_L(uint32_t val) } } -static __inline uint16_t POP_W() +static INLINE uint16_t POP_W() { uint16_t ret; if (stack32) @@ -102,7 +102,7 @@ static __inline uint16_t POP_W() return ret; } -static __inline uint32_t POP_L() +static INLINE uint32_t POP_L() { uint32_t ret; if (stack32) @@ -120,7 +120,7 @@ static __inline uint32_t POP_L() return ret; } -static __inline uint16_t POP_W_seg(uint32_t seg) +static INLINE uint16_t POP_W_seg(uint32_t seg) { uint16_t ret; if (stack32) @@ -138,7 +138,7 @@ static __inline uint16_t POP_W_seg(uint32_t seg) return ret; } -static __inline uint32_t POP_L_seg(uint32_t seg) +static INLINE uint32_t POP_L_seg(uint32_t seg) { uint32_t ret; if (stack32) @@ -162,7 +162,7 @@ static int ILLEGAL(uint32_t fetchdat) { cpu_state.pc = cpu_state.oldpc; - pclog("Illegal instruction %08X (%02X)\n", fetchdat, fopcode); + ERRLOG("CPU: illegal instruction %08X (%02X)\n", fetchdat, fopcode); x86illegal(); return 0; } diff --git a/src/cpu/808x.c b/src/cpu/808x.c index 8b90f1c..72752f3 100644 --- a/src/cpu/808x.c +++ b/src/cpu/808x.c @@ -18,7 +18,7 @@ * 2 clocks - fetch opcode 1 2 clocks - execute * 2 clocks - fetch opcode 2 etc * - * Version: @(#)808x.c 1.0.6 2018/09/22 + * Version: @(#)808x.c 1.0.6 2018/10/05 * * Authors: Sarah Walker, * Miran Grca, @@ -58,9 +58,6 @@ #include "../mem.h" #include "../rom.h" #include "../timer.h" -#include "../device.h" /* for scsi.h */ -#include "../devices/input/keyboard.h" /* its WRONG to have this in here!! --FvK */ -#include "../devices/scsi/scsi.h" /* its WRONG to have this in here!! --FvK */ #include "../plat.h" @@ -87,6 +84,9 @@ uint8_t prefetchqueue[6]; uint16_t prefetchpc; int prefetchw = 0; +int use32; +int stack32; + #undef readmemb uint8_t @@ -177,7 +177,7 @@ writememl(uint32_t s, uint32_t a, uint32_t v) } -static __inline uint8_t +static INLINE uint8_t FETCH(void) { uint8_t temp; @@ -214,7 +214,7 @@ FETCH(void) } -static __inline void +static INLINE void FETCHADD(int c) { int d; @@ -242,7 +242,7 @@ FETCHADD(int c) } -static __inline void +static INLINE void FETCHCLEAR(void) { prefetchpc=cpu_state.pc; @@ -279,9 +279,6 @@ FETCHCOMPLETE(void) void refreshread(void) { -#if 0 - pclog("Refreshread\n"); -#endif FETCHCOMPLETE(); memcycs += 4; @@ -313,13 +310,13 @@ r16(/r) AX CX DX BX SP BP SI DI r32(/r) EAX ECX EDX EBX ESP EBP ESI EDI /digit (Opcode) 0 1 2 3 4 5 6 7 REG = 000 001 010 011 100 101 110 111 - ����Address +Address disp8 denotes an 8-bit displacement following the ModR/M byte, to be sign-extended and added to the index. disp16 denotes a 16-bit displacement following the ModR/M byte, to be added to the index. Default segment register is SS for the effective addresses containing a BP index, DS for other effective addresses. - �Ŀ �Mod R/M� ���������ModR/M Values in Hexadecimal�������Ŀ +Mod R/M Values in Hexadecimal [BX + SI] 000 00 08 10 18 20 28 30 38 [BX + DI] 001 01 09 11 19 21 29 31 39 @@ -392,7 +389,7 @@ uint32_t *mod1seg[8]; int slowrm[8]; -void makemod1table() +void makemod1table(void) { mod1add[0][0]=&BX; mod1add[0][1]=&BX; mod1add[0][2]=&BP; mod1add[0][3]=&BP; mod1add[0][4]=&SI; mod1add[0][5]=&DI; mod1add[0][6]=&BP; mod1add[0][7]=&BX; @@ -403,7 +400,7 @@ void makemod1table() mod1seg[4]=&ds; mod1seg[5]=&ds; mod1seg[6]=&ss; mod1seg[7]=&ds; } -static void fetcheal() +static void fetcheal(void) { if (!cpu_mod && cpu_rm==6) { cpu_state.eaaddr=getword(); easeg=ds; FETCHADD(6); } else @@ -434,14 +431,14 @@ static void fetcheal() cpu_state.last_ea = cpu_state.eaaddr; } -static __inline uint8_t geteab() +static INLINE uint8_t geteab(void) { if (cpu_mod == 3) return (cpu_rm & 4) ? cpu_state.regs[cpu_rm & 3].b.h : cpu_state.regs[cpu_rm & 3].b.l; return readmemb(easeg+cpu_state.eaaddr); } -static __inline uint16_t geteaw() +static INLINE uint16_t geteaw(void) { if (cpu_mod == 3) return cpu_state.regs[cpu_rm].w; @@ -449,7 +446,7 @@ static __inline uint16_t geteaw() } #if 0 -static __inline uint16_t geteaw2() +static INLINE uint16_t geteaw2(void) { if (cpu_mod == 3) return cpu_state.regs[cpu_rm].w; @@ -457,7 +454,7 @@ static __inline uint16_t geteaw2() } #endif -static __inline void seteab(uint8_t val) +static INLINE void seteab(uint8_t val) { if (cpu_mod == 3) { @@ -472,7 +469,7 @@ static __inline void seteab(uint8_t val) } } -static __inline void seteaw(uint16_t val) +static INLINE void seteaw(uint16_t val) { if (cpu_mod == 3) cpu_state.regs[cpu_rm].w = val; @@ -494,7 +491,7 @@ static __inline void seteaw(uint16_t val) uint8_t znptable8[256]; uint16_t znptable16[65536]; -void makeznptable() +void makeznptable(void) { int c,d; for (c=0;c<256;c++) @@ -516,7 +513,7 @@ void makeznptable() { znptable8[c]=P_FLAG; } - if (c == 0xb1) pclog("znp8 b1 = %i %02X\n", d, znptable8[c]); + if (c == 0xb1) DEBUG("znp8 b1 = %i %02X\n", d, znptable8[c]); if (!c) znptable8[c]|=Z_FLAG; if (c&0x80) znptable8[c]|=N_FLAG; } @@ -535,8 +532,8 @@ void makeznptable() znptable16[c]=0; else znptable16[c]=P_FLAG; - if (c == 0xb1) pclog("znp16 b1 = %i %02X\n", d, znptable16[c]); - if (c == 0x65b1) pclog("znp16 65b1 = %i %02X\n", d, znptable16[c]); + if (c == 0xb1) DEBUG("znp16 b1 = %i %02X\n", d, znptable16[c]); + if (c == 0x65b1) DEBUG("znp16 65b1 = %i %02X\n", d, znptable16[c]); if (!c) znptable16[c]|=Z_FLAG; if (c&0x8000) znptable16[c]|=N_FLAG; } @@ -563,70 +560,71 @@ void dumpregs(int force) (void)plat_chdir(usr_path); nopageerrors=1; f=fopen("ram.dmp","wb"); - if (!f) return; - fwrite(ram,mem_size*1024,1,f); - fclose(f); - pclog("Dumping rram.dmp\n"); + if (f != NULL) { + fwrite(ram,mem_size*1024,1,f); + fclose(f); + } + ERRLOG("Dumping rram.dmp\n"); f=fopen("rram.dmp","wb"); - if (!f) return; - for (c=0;c<0x1000000;c++) putc(readmemb(c),f); - fclose(f); - pclog("Dumping rram4.dmp\n"); + if (f != NULL) { + for (c=0;c<0x1000000;c++) putc(readmemb(c),f); + fclose(f); + } + ERRLOG("Dumping rram4.dmp\n"); f=fopen("rram4.dmp","wb"); - if (!f) return; - for (c=0;c<0x0050000;c++) - { - cpu_state.abrt = 0; - putc(readmemb386l(0,c+0x80000000),f); - } - fclose(f); - pclog("Dumping done\n"); + if (f != NULL) { + for (c=0;c<0x0050000;c++) { + cpu_state.abrt = 0; + putc(readmemb386l(0,c+0x80000000),f); + } + fclose(f); + } + ERRLOG("Dumping done\n"); #endif if (is386) - pclog("EAX=%08X EBX=%08X ECX=%08X EDX=%08X\nEDI=%08X ESI=%08X EBP=%08X ESP=%08X\n",EAX,EBX,ECX,EDX,EDI,ESI,EBP,ESP); + ERRLOG("EAX=%08X EBX=%08X ECX=%08X EDX=%08X\nEDI=%08X ESI=%08X EBP=%08X ESP=%08X\n",EAX,EBX,ECX,EDX,EDI,ESI,EBP,ESP); else - pclog("AX=%04X BX=%04X CX=%04X DX=%04X DI=%04X SI=%04X BP=%04X SP=%04X\n",AX,BX,CX,DX,DI,SI,BP,SP); - pclog("PC=%04X CS=%04X DS=%04X ES=%04X SS=%04X FLAGS=%04X\n",cpu_state.pc,CS,DS,ES,SS,flags); - pclog("%04X:%04X %04X:%04X\n",oldcs,cpu_state.oldpc, oldcs2, oldpc2); - pclog("%i ins\n",ins); + ERRLOG("AX=%04X BX=%04X CX=%04X DX=%04X DI=%04X SI=%04X BP=%04X SP=%04X\n",AX,BX,CX,DX,DI,SI,BP,SP); + ERRLOG("PC=%04X CS=%04X DS=%04X ES=%04X SS=%04X FLAGS=%04X\n",cpu_state.pc,CS,DS,ES,SS,flags); + ERRLOG("%04X:%04X %04X:%04X\n",oldcs,cpu_state.oldpc, oldcs2, oldpc2); + ERRLOG("%i ins\n",ins); if (is386) - pclog("In %s mode\n",(msw&1)?((eflags&VM_FLAG)?"V86":"protected"):"real"); + ERRLOG("In %s mode\n",(msw&1)?((eflags&VM_FLAG)?"V86":"protected"):"real"); else - pclog("In %s mode\n",(msw&1)?"protected":"real"); - pclog("CS : base=%06X limit=%08X access=%02X limit_low=%08X limit_high=%08X\n",cs,_cs.limit,_cs.access, _cs.limit_low, _cs.limit_high); - pclog("DS : base=%06X limit=%08X access=%02X limit_low=%08X limit_high=%08X\n",ds,_ds.limit,_ds.access, _ds.limit_low, _ds.limit_high); - pclog("ES : base=%06X limit=%08X access=%02X limit_low=%08X limit_high=%08X\n",es,_es.limit,_es.access, _es.limit_low, _es.limit_high); + ERRLOG("In %s mode\n",(msw&1)?"protected":"real"); + ERRLOG("CS : base=%06X limit=%08X access=%02X limit_low=%08X limit_high=%08X\n",cs,_cs.limit,_cs.access, _cs.limit_low, _cs.limit_high); + ERRLOG("DS : base=%06X limit=%08X access=%02X limit_low=%08X limit_high=%08X\n",ds,_ds.limit,_ds.access, _ds.limit_low, _ds.limit_high); + ERRLOG("ES : base=%06X limit=%08X access=%02X limit_low=%08X limit_high=%08X\n",es,_es.limit,_es.access, _es.limit_low, _es.limit_high); if (is386) { - pclog("FS : base=%06X limit=%08X access=%02X limit_low=%08X limit_high=%08X\n",seg_fs,_fs.limit,_fs.access, _fs.limit_low, _fs.limit_high); - pclog("GS : base=%06X limit=%08X access=%02X limit_low=%08X limit_high=%08X\n",gs,_gs.limit,_gs.access, _gs.limit_low, _gs.limit_high); + ERRLOG("FS : base=%06X limit=%08X access=%02X limit_low=%08X limit_high=%08X\n",seg_fs,_fs.limit,_fs.access, _fs.limit_low, _fs.limit_high); + ERRLOG("GS : base=%06X limit=%08X access=%02X limit_low=%08X limit_high=%08X\n",gs,_gs.limit,_gs.access, _gs.limit_low, _gs.limit_high); } - pclog("SS : base=%06X limit=%08X access=%02X limit_low=%08X limit_high=%08X\n",ss,_ss.limit,_ss.access, _ss.limit_low, _ss.limit_high); - pclog("GDT : base=%06X limit=%04X\n",gdt.base,gdt.limit); - pclog("LDT : base=%06X limit=%04X\n",ldt.base,ldt.limit); - pclog("IDT : base=%06X limit=%04X\n",idt.base,idt.limit); - pclog("TR : base=%06X limit=%04X\n", tr.base, tr.limit); + ERRLOG("SS : base=%06X limit=%08X access=%02X limit_low=%08X limit_high=%08X\n",ss,_ss.limit,_ss.access, _ss.limit_low, _ss.limit_high); + ERRLOG("GDT : base=%06X limit=%04X\n",gdt.base,gdt.limit); + ERRLOG("LDT : base=%06X limit=%04X\n",ldt.base,ldt.limit); + ERRLOG("IDT : base=%06X limit=%04X\n",idt.base,idt.limit); + ERRLOG("TR : base=%06X limit=%04X\n", tr.base, tr.limit); if (is386) { - pclog("386 in %s mode stack in %s mode\n",(use32)?"32-bit":"16-bit",(stack32)?"32-bit":"16-bit"); - pclog("CR0=%08X CR2=%08X CR3=%08X CR4=%08x\n",cr0,cr2,cr3, cr4); + ERRLOG("386 in %s mode stack in %s mode\n",(use32)?"32-bit":"16-bit",(stack32)?"32-bit":"16-bit"); + ERRLOG("CR0=%08X CR2=%08X CR3=%08X CR4=%08x\n",cr0,cr2,cr3, cr4); } - pclog("Entries in readlookup : %i writelookup : %i\n",readlnum,writelnum); for (c=0;c<1024*1024;c++) { if (readlookup2[c]!=0xFFFFFFFF) d++; if (writelookup2[c]!=0xFFFFFFFF) e++; } - pclog("Entries in readlookup : %i writelookup : %i\n",d,e); + ERRLOG("Entries in readlookup : %i writelookup : %i\n",d,e); x87_dumpregs(); indump = 0; } int resets = 0; int x86_was_reset = 0; -void resetx86() +void resetx86(void) { - pclog("x86 reset\n"); + INFO("CPU: x86 reset\n"); resets++; ins = 0; use32=0; @@ -638,7 +636,7 @@ void resetx86() cr0 = 1 << 30; else cr0 = 0; - cpu_cache_int_enabled = 0; + cpu_cache_int_enabled = cpu_cache_ext_enabled = 0; cpu_update_waitstates(); cr4 = 0; eflags=0; @@ -675,17 +673,21 @@ void resetx86() #endif x86_was_reset = 1; port_92_clear_reset(); - scsi_card_reset(); } -void softresetx86() +void softresetx86(void) { use32=0; stack32=0; cpu_cur_status = 0; msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 19) | (1 << 21); msw=0; - cr0=0; + if (is486) + cr0 = 1 << 30; + else + cr0 = 0; + cpu_cache_int_enabled = 0; + cpu_update_waitstates(); cr4 = 0; eflags=0; cgate32=0; @@ -707,7 +709,6 @@ void softresetx86() x86seg_reset(); x86_was_reset = 1; port_92_clear_reset(); - scsi_card_reset(); } static void setznp8(uint8_t val) @@ -831,7 +832,7 @@ static void setsbc16(uint16_t a, uint16_t b) } int current_diff = 0; -void clockhardware() +void clockhardware(void) { int diff = cycdiff - cycles - current_diff; @@ -885,19 +886,70 @@ void rep(int fv) cycles-=2; goto startrep; break; - case 0x6E: /*REP OUTSB*/ - if (c>0) - { - temp2=readmemb(ds+SI); - outb(DX,temp2); - if (flags&D_FLAG) SI--; - else SI++; - c--; - cycles-=5; - } - if (c>0) { firstrepcycle=0; cpu_state.pc=ipc; if (cpu_state.ssegs) cpu_state.ssegs++; FETCHCLEAR(); } - else firstrepcycle=1; + case 0x6C: /*186+ REP INSB*/ + if (is_nec) + { + if (c>0) + { + temp2=inb(DX); + writememb(ds+SI, temp2); + if (flags&D_FLAG) SI--; + else SI++; + c--; + cycles-=5; + } + if (c>0) { firstrepcycle=0; cpu_state.pc=ipc; if (cpu_state.ssegs) cpu_state.ssegs++; FETCHCLEAR(); } + else firstrepcycle=1; + } + break; + case 0x6D: /*186+ REP INSW*/ + if (is_nec) + { + if (c>0) + { + tempw2=inw(DX); + writememw(ds, SI, tempw2); + if (flags&D_FLAG) SI-=2; + else SI+=2; + c--; + cycles-=5; + } + if (c>0) { firstrepcycle=0; cpu_state.pc=ipc; if (cpu_state.ssegs) cpu_state.ssegs++; FETCHCLEAR(); } + else firstrepcycle=1; + } break; + case 0x6E: /*186+ REP OUTSB*/ + if (is_nec) + { + if (c>0) + { + temp2=readmemb(ds+SI); + outb(DX,temp2); + if (flags&D_FLAG) SI--; + else SI++; + c--; + cycles-=5; + } + if (c>0) { firstrepcycle=0; cpu_state.pc=ipc; if (cpu_state.ssegs) cpu_state.ssegs++; FETCHCLEAR(); } + else firstrepcycle=1; + } + break; + case 0x6F: /*186+ REP OUTSW*/ + if (is_nec) + { + if (c>0) + { + tempw2=readmemw(ds,SI); + outw(DX,tempw2); + if (flags&D_FLAG) SI-=2; + else SI+=2; + c--; + cycles-=5; + } + if (c>0) { firstrepcycle=0; cpu_state.pc=ipc; if (cpu_state.ssegs) cpu_state.ssegs++; FETCHCLEAR(); } + else firstrepcycle=1; + } + break; case 0xA4: /*REP MOVSB*/ while (c>0 && !IRQTEST) { @@ -1059,2271 +1111,2723 @@ void rep(int fv) int inhlt=0; uint16_t lastpc,lastcs; -int firstrepcycle; int skipnextprint=0; - int instime=0; -void execx86(int cycs) + + +void +execx86(int cycs) { - uint8_t temp = 0,temp2; - uint16_t addr,tempw,tempw2,tempw3,tempw4; - int8_t offset; - int tempws; - uint32_t templ; - unsigned int c; - int tempi; - int trap; + uint8_t temp = 0,temp2; + uint16_t addr,tempw,tempw2,tempw3,tempw4; + int8_t offset; + int tempws; + uint32_t templ; + unsigned int c; + int tempi; + int trap; - cycles+=cycs; - while (cycles>0) - { - cycdiff=cycles; - timer_start_period(cycles*xt_cpu_multi); - current_diff = 0; - cycles-=nextcyc; - nextcyc=0; - fetchclocks=0; - oldcs=CS; - cpu_state.oldpc=cpu_state.pc; - opcodestart: - opcode=FETCH(); - tempc=flags&C_FLAG; - trap=flags&T_FLAG; - cpu_state.pc--; - if (output) - { - if (!skipnextprint) pclog("%04X:%04X : %04X %04X %04X %04X %04X %04X %04X %04X %04X %04X %04X %04X %02X %04X %i %p %02X\n",cs,cpu_state.pc,AX,BX,CX,DX,CS,DS,ES,SS,DI,SI,BP,SP,opcode,flags, ins, ram, ram[0x1a925]); - skipnextprint=0; - } - cpu_state.pc++; - inhlt=0; - switch (opcode) - { - case 0x00: /*ADD 8,reg*/ - fetchea(); - temp=geteab(); - setadd8(temp,getr8(cpu_reg)); - temp+=getr8(cpu_reg); - seteab(temp); - cycles-=((cpu_mod==3)?3:24); - break; - case 0x01: /*ADD 16,reg*/ - fetchea(); - tempw=geteaw(); - setadd16(tempw, cpu_state.regs[cpu_reg].w); - tempw += cpu_state.regs[cpu_reg].w; - seteaw(tempw); - cycles-=((cpu_mod==3)?3:24); - break; - case 0x02: /*ADD cpu_reg,8*/ - fetchea(); - temp=geteab(); - setadd8(getr8(cpu_reg),temp); - setr8(cpu_reg,getr8(cpu_reg)+temp); - cycles-=((cpu_mod==3)?3:13); - break; - case 0x03: /*ADD cpu_reg,16*/ - fetchea(); - tempw=geteaw(); - setadd16(cpu_state.regs[cpu_reg].w,tempw); - cpu_state.regs[cpu_reg].w+=tempw; - cycles-=((cpu_mod==3)?3:13); - break; - case 0x04: /*ADD AL,#8*/ - temp=FETCH(); - setadd8(AL,temp); - AL+=temp; - cycles-=4; - break; - case 0x05: /*ADD AX,#16*/ - tempw=getword(); - setadd16(AX,tempw); - AX+=tempw; - cycles-=4; - break; + cycles += cycs; + while (cycles > 0) { + cycdiff=cycles; + timer_start_period(cycles*xt_cpu_multi); + current_diff = 0; + cycles-=nextcyc; + nextcyc=0; + fetchclocks=0; + oldcs=CS; + cpu_state.oldpc=cpu_state.pc; - case 0x06: /*PUSH ES*/ - if (cpu_state.ssegs) ss=oldss; - writememw(ss,((SP-2)&0xFFFF),ES); - SP-=2; +opcodestart: + opcode=FETCH(); + tempc=flags&C_FLAG; + trap=flags&T_FLAG; + cpu_state.pc--; + +#if 0 + DEBUG("%04X:%04X : %04X %04X %04X %04X %04X %04X %04X %04X %04X %04X %04X %04X %02X %04X %i %p %02X\n",cs,cpu_state.pc,AX,BX,CX,DX,CS,DS,ES,SS,DI,SI,BP,SP,opcode,flags, ins, ram, ram[0x1a925]); +#endif + + cpu_state.pc++; + inhlt=0; + switch (opcode) { + case 0x00: /*ADD 8,reg*/ + fetchea(); + temp=geteab(); + setadd8(temp,getr8(cpu_reg)); + temp+=getr8(cpu_reg); + seteab(temp); + cycles-=((cpu_mod==3)?3:24); + break; + + case 0x01: /*ADD 16,reg*/ + fetchea(); + tempw=geteaw(); + setadd16(tempw, cpu_state.regs[cpu_reg].w); + tempw += cpu_state.regs[cpu_reg].w; + seteaw(tempw); + cycles-=((cpu_mod==3)?3:24); + break; + + case 0x02: /*ADD cpu_reg,8*/ + fetchea(); + temp=geteab(); + setadd8(getr8(cpu_reg),temp); + setr8(cpu_reg,getr8(cpu_reg)+temp); + cycles-=((cpu_mod==3)?3:13); + break; + + case 0x03: /*ADD cpu_reg,16*/ + fetchea(); + tempw=geteaw(); + setadd16(cpu_state.regs[cpu_reg].w,tempw); + cpu_state.regs[cpu_reg].w+=tempw; + cycles-=((cpu_mod==3)?3:13); + break; + + case 0x04: /*ADD AL,#8*/ + temp=FETCH(); + setadd8(AL,temp); + AL+=temp; + cycles-=4; + break; + + case 0x05: /*ADD AX,#16*/ + tempw=getword(); + setadd16(AX,tempw); + AX+=tempw; + cycles-=4; + break; + + case 0x06: /*PUSH ES*/ + if (cpu_state.ssegs) ss=oldss; + writememw(ss,((SP-2)&0xFFFF),ES); + SP-=2; cpu_state.last_ea = SP; - cycles-=14; - break; - case 0x07: /*POP ES*/ - if (cpu_state.ssegs) ss=oldss; - tempw=readmemw(ss,SP); - loadseg(tempw,&_es); - SP+=2; + cycles-=14; + break; + + case 0x07: /*POP ES*/ + if (cpu_state.ssegs) ss=oldss; + tempw=readmemw(ss,SP); + loadseg(tempw,&_es); + SP+=2; cpu_state.last_ea = SP; - cycles-=12; - break; + cycles-=12; + break; - case 0x08: /*OR 8,reg*/ - fetchea(); - temp=geteab(); - temp|=getr8(cpu_reg); - setznp8(temp); - flags&=~(C_FLAG|V_FLAG|A_FLAG); - seteab(temp); - cycles-=((cpu_mod==3)?3:24); - break; - case 0x09: /*OR 16,reg*/ - fetchea(); - tempw=geteaw(); - tempw|=cpu_state.regs[cpu_reg].w; - setznp16(tempw); - flags&=~(C_FLAG|V_FLAG|A_FLAG); - seteaw(tempw); - cycles-=((cpu_mod==3)?3:24); - break; - case 0x0A: /*OR cpu_reg,8*/ - fetchea(); - temp=geteab(); - temp|=getr8(cpu_reg); - setznp8(temp); - flags&=~(C_FLAG|V_FLAG|A_FLAG); - setr8(cpu_reg,temp); - cycles-=((cpu_mod==3)?3:13); - break; - case 0x0B: /*OR reg,16*/ - fetchea(); - tempw=geteaw(); - tempw|=cpu_state.regs[cpu_reg].w; - setznp16(tempw); - flags&=~(C_FLAG|V_FLAG|A_FLAG); - cpu_state.regs[cpu_reg].w=tempw; - cycles-=((cpu_mod==3)?3:13); - break; - case 0x0C: /*OR AL,#8*/ - AL|=FETCH(); - setznp8(AL); - flags&=~(C_FLAG|V_FLAG|A_FLAG); - cycles-=4; - break; - case 0x0D: /*OR AX,#16*/ - AX|=getword(); - setznp16(AX); - flags&=~(C_FLAG|V_FLAG|A_FLAG); - cycles-=4; - break; + case 0x08: /*OR 8,reg*/ + fetchea(); + temp=geteab(); + temp|=getr8(cpu_reg); + setznp8(temp); + flags&=~(C_FLAG|V_FLAG|A_FLAG); + seteab(temp); + cycles-=((cpu_mod==3)?3:24); + break; - case 0x0E: /*PUSH CS*/ - if (cpu_state.ssegs) ss=oldss; - writememw(ss,((SP-2)&0xFFFF),CS); - SP-=2; + case 0x09: /*OR 16,reg*/ + fetchea(); + tempw=geteaw(); + tempw|=cpu_state.regs[cpu_reg].w; + setznp16(tempw); + flags&=~(C_FLAG|V_FLAG|A_FLAG); + seteaw(tempw); + cycles-=((cpu_mod==3)?3:24); + break; + + case 0x0A: /*OR cpu_reg,8*/ + fetchea(); + temp=geteab(); + temp|=getr8(cpu_reg); + setznp8(temp); + flags&=~(C_FLAG|V_FLAG|A_FLAG); + setr8(cpu_reg,temp); + cycles-=((cpu_mod==3)?3:13); + break; + + case 0x0B: /*OR reg,16*/ + fetchea(); + tempw=geteaw(); + tempw|=cpu_state.regs[cpu_reg].w; + setznp16(tempw); + flags&=~(C_FLAG|V_FLAG|A_FLAG); + cpu_state.regs[cpu_reg].w=tempw; + cycles-=((cpu_mod==3)?3:13); + break; + + case 0x0C: /*OR AL,#8*/ + AL|=FETCH(); + setznp8(AL); + flags&=~(C_FLAG|V_FLAG|A_FLAG); + cycles-=4; + break; + + case 0x0D: /*OR AX,#16*/ + AX|=getword(); + setznp16(AX); + flags&=~(C_FLAG|V_FLAG|A_FLAG); + cycles-=4; + break; + + case 0x0E: /*PUSH CS*/ + if (cpu_state.ssegs) ss=oldss; + writememw(ss,((SP-2)&0xFFFF),CS); + SP-=2; cpu_state.last_ea = SP; - cycles-=14; - break; - case 0x0F: /*POP CS - 8088/8086 only*/ - if (cpu_state.ssegs) ss=oldss; - tempw=readmemw(ss,SP); - loadseg(tempw,&_cs); - SP+=2; + cycles-=14; + break; + + case 0x0F: /*0F handler for NEC V20 soon */ + if (! is_nec) { /*POP CS - 8088/8086 only*/ + if (cpu_state.ssegs) ss=oldss; + tempw=readmemw(ss,SP); + loadseg(tempw,&_cs); + SP+=2; + cpu_state.last_ea = SP; + cycles-=12; + } + break; + + case 0x10: /*ADC 8,reg*/ + fetchea(); + temp=geteab(); + temp2=getr8(cpu_reg); + setadc8(temp,temp2); + temp+=temp2+tempc; + seteab(temp); + cycles-=((cpu_mod==3)?3:24); + break; + + case 0x11: /*ADC 16,reg*/ + fetchea(); + tempw=geteaw(); + tempw2=cpu_state.regs[cpu_reg].w; + setadc16(tempw,tempw2); + tempw+=tempw2+tempc; + seteaw(tempw); + cycles-=((cpu_mod==3)?3:24); + break; + + case 0x12: /*ADC cpu_reg,8*/ + fetchea(); + temp=geteab(); + setadc8(getr8(cpu_reg),temp); + setr8(cpu_reg,getr8(cpu_reg)+temp+tempc); + cycles-=((cpu_mod==3)?3:13); + break; + + case 0x13: /*ADC cpu_reg,16*/ + fetchea(); + tempw=geteaw(); + setadc16(cpu_state.regs[cpu_reg].w,tempw); + cpu_state.regs[cpu_reg].w+=tempw+tempc; + cycles-=((cpu_mod==3)?3:13); + break; + + case 0x14: /*ADC AL,#8*/ + tempw=FETCH(); + setadc8(AL,tempw & 0xff); + AL+=tempw+tempc; + cycles-=4; + break; + + case 0x15: /*ADC AX,#16*/ + tempw=getword(); + setadc16(AX,tempw); + AX+=tempw+tempc; + cycles-=4; + break; + + case 0x16: /*PUSH SS*/ + if (cpu_state.ssegs) ss=oldss; + writememw(ss,((SP-2)&0xFFFF),SS); + SP-=2; + cycles-=14; cpu_state.last_ea = SP; - cycles-=12; - break; + break; - case 0x10: /*ADC 8,reg*/ - fetchea(); - temp=geteab(); - temp2=getr8(cpu_reg); - setadc8(temp,temp2); - temp+=temp2+tempc; - seteab(temp); - cycles-=((cpu_mod==3)?3:24); - break; - case 0x11: /*ADC 16,reg*/ - fetchea(); - tempw=geteaw(); - tempw2=cpu_state.regs[cpu_reg].w; - setadc16(tempw,tempw2); - tempw+=tempw2+tempc; - seteaw(tempw); - cycles-=((cpu_mod==3)?3:24); - break; - case 0x12: /*ADC cpu_reg,8*/ - fetchea(); - temp=geteab(); - setadc8(getr8(cpu_reg),temp); - setr8(cpu_reg,getr8(cpu_reg)+temp+tempc); - cycles-=((cpu_mod==3)?3:13); - break; - case 0x13: /*ADC cpu_reg,16*/ - fetchea(); - tempw=geteaw(); - setadc16(cpu_state.regs[cpu_reg].w,tempw); - cpu_state.regs[cpu_reg].w+=tempw+tempc; - cycles-=((cpu_mod==3)?3:13); - break; - case 0x14: /*ADC AL,#8*/ - tempw=FETCH(); - setadc8(AL,tempw & 0xff); - AL+=tempw+tempc; - cycles-=4; - break; - case 0x15: /*ADC AX,#16*/ - tempw=getword(); - setadc16(AX,tempw); - AX+=tempw+tempc; - cycles-=4; - break; - - case 0x16: /*PUSH SS*/ - if (cpu_state.ssegs) ss=oldss; - writememw(ss,((SP-2)&0xFFFF),SS); - SP-=2; - cycles-=14; + case 0x17: /*POP SS*/ + if (cpu_state.ssegs) ss=oldss; + tempw=readmemw(ss,SP); + loadseg(tempw,&_ss); + SP+=2; cpu_state.last_ea = SP; - break; - case 0x17: /*POP SS*/ - if (cpu_state.ssegs) ss=oldss; - tempw=readmemw(ss,SP); - loadseg(tempw,&_ss); - SP+=2; + noint=1; + cycles-=12; + break; + + case 0x18: /*SBB 8,reg*/ + fetchea(); + temp=geteab(); + temp2=getr8(cpu_reg); + setsbc8(temp,temp2); + temp-=(temp2+tempc); + seteab(temp); + cycles-=((cpu_mod==3)?3:24); + break; + + case 0x19: /*SBB 16,reg*/ + fetchea(); + tempw=geteaw(); + tempw2=cpu_state.regs[cpu_reg].w; + setsbc16(tempw,tempw2); + tempw-=(tempw2+tempc); + seteaw(tempw); + cycles-=((cpu_mod==3)?3:24); + break; + + case 0x1A: /*SBB cpu_reg,8*/ + fetchea(); + temp=geteab(); + setsbc8(getr8(cpu_reg),temp); + setr8(cpu_reg,getr8(cpu_reg)-(temp+tempc)); + cycles-=((cpu_mod==3)?3:13); + break; + + case 0x1B: /*SBB cpu_reg,16*/ + fetchea(); + tempw=geteaw(); + tempw2=cpu_state.regs[cpu_reg].w; + setsbc16(tempw2,tempw); + tempw2-=(tempw+tempc); + cpu_state.regs[cpu_reg].w=tempw2; + cycles-=((cpu_mod==3)?3:13); + break; + + case 0x1C: /*SBB AL,#8*/ + temp=FETCH(); + setsbc8(AL,temp); + AL-=(temp+tempc); + cycles-=4; + break; + + case 0x1D: /*SBB AX,#16*/ + tempw=getword(); + setsbc16(AX,tempw); + AX-=(tempw+tempc); + cycles-=4; + break; + + case 0x1E: /*PUSH DS*/ + if (cpu_state.ssegs) ss=oldss; + writememw(ss,((SP-2)&0xFFFF),DS); + SP-=2; cpu_state.last_ea = SP; - noint=1; - cycles-=12; - break; + cycles-=14; + break; - case 0x18: /*SBB 8,reg*/ - fetchea(); - temp=geteab(); - temp2=getr8(cpu_reg); - setsbc8(temp,temp2); - temp-=(temp2+tempc); - seteab(temp); - cycles-=((cpu_mod==3)?3:24); - break; - case 0x19: /*SBB 16,reg*/ - fetchea(); - tempw=geteaw(); - tempw2=cpu_state.regs[cpu_reg].w; - setsbc16(tempw,tempw2); - tempw-=(tempw2+tempc); - seteaw(tempw); - cycles-=((cpu_mod==3)?3:24); - break; - case 0x1A: /*SBB cpu_reg,8*/ - fetchea(); - temp=geteab(); - setsbc8(getr8(cpu_reg),temp); - setr8(cpu_reg,getr8(cpu_reg)-(temp+tempc)); - cycles-=((cpu_mod==3)?3:13); - break; - case 0x1B: /*SBB cpu_reg,16*/ - fetchea(); - tempw=geteaw(); - tempw2=cpu_state.regs[cpu_reg].w; - setsbc16(tempw2,tempw); - tempw2-=(tempw+tempc); - cpu_state.regs[cpu_reg].w=tempw2; - cycles-=((cpu_mod==3)?3:13); - break; - case 0x1C: /*SBB AL,#8*/ - temp=FETCH(); - setsbc8(AL,temp); - AL-=(temp+tempc); - cycles-=4; - break; - case 0x1D: /*SBB AX,#16*/ - tempw=getword(); - setsbc16(AX,tempw); - AX-=(tempw+tempc); - cycles-=4; - break; - - case 0x1E: /*PUSH DS*/ - if (cpu_state.ssegs) ss=oldss; - writememw(ss,((SP-2)&0xFFFF),DS); - SP-=2; + case 0x1F: /*POP DS*/ + if (cpu_state.ssegs) ss=oldss; + tempw=readmemw(ss,SP); + loadseg(tempw,&_ds); + if (cpu_state.ssegs) oldds=ds; + SP+=2; cpu_state.last_ea = SP; - cycles-=14; - break; - case 0x1F: /*POP DS*/ - if (cpu_state.ssegs) ss=oldss; - tempw=readmemw(ss,SP); - loadseg(tempw,&_ds); - if (cpu_state.ssegs) oldds=ds; - SP+=2; + cycles-=12; + break; + + case 0x20: /*AND 8,reg*/ + fetchea(); + temp=geteab(); + temp&=getr8(cpu_reg); + setznp8(temp); + flags&=~(C_FLAG|V_FLAG|A_FLAG); + seteab(temp); + cycles-=((cpu_mod==3)?3:24); + break; + + case 0x21: /*AND 16,reg*/ + fetchea(); + tempw=geteaw(); + tempw&=cpu_state.regs[cpu_reg].w; + setznp16(tempw); + flags&=~(C_FLAG|V_FLAG|A_FLAG); + seteaw(tempw); + cycles-=((cpu_mod==3)?3:24); + break; + + case 0x22: /*AND cpu_reg,8*/ + fetchea(); + temp=geteab(); + temp&=getr8(cpu_reg); + setznp8(temp); + flags&=~(C_FLAG|V_FLAG|A_FLAG); + setr8(cpu_reg,temp); + cycles-=((cpu_mod==3)?3:13); + break; + + case 0x23: /*AND cpu_reg,16*/ + fetchea(); + tempw=geteaw(); + tempw&=cpu_state.regs[cpu_reg].w; + setznp16(tempw); + flags&=~(C_FLAG|V_FLAG|A_FLAG); + cpu_state.regs[cpu_reg].w=tempw; + cycles-=((cpu_mod==3)?3:13); + break; + + case 0x24: /*AND AL,#8*/ + AL&=FETCH(); + setznp8(AL); + flags&=~(C_FLAG|V_FLAG|A_FLAG); + cycles-=4; + break; + + case 0x25: /*AND AX,#16*/ + AX&=getword(); + setznp16(AX); + flags&=~(C_FLAG|V_FLAG|A_FLAG); + cycles-=4; + break; + + case 0x26: /*ES:*/ + oldss=ss; + oldds=ds; + ds=ss=es; + cpu_state.ssegs=2; + cycles-=4; + goto opcodestart; + + case 0x27: /*DAA*/ + if ((flags&A_FLAG) || ((AL&0xF)>9)) { + tempi=((uint16_t)AL)+6; + AL+=6; + flags|=A_FLAG; + if (tempi&0x100) flags|=C_FLAG; + } + if ((flags&C_FLAG) || (AL>0x9F)) { + AL+=0x60; + flags|=C_FLAG; + } + setznp8(AL); + cycles-=4; + break; + + case 0x28: /*SUB 8,reg*/ + fetchea(); + temp=geteab(); + setsub8(temp,getr8(cpu_reg)); + temp-=getr8(cpu_reg); + seteab(temp); + cycles-=((cpu_mod==3)?3:24); + break; + + case 0x29: /*SUB 16,reg*/ + fetchea(); + tempw=geteaw(); + setsub16(tempw,cpu_state.regs[cpu_reg].w); + tempw-=cpu_state.regs[cpu_reg].w; + seteaw(tempw); + cycles-=((cpu_mod==3)?3:24); + break; + + case 0x2A: /*SUB cpu_reg,8*/ + fetchea(); + temp=geteab(); + setsub8(getr8(cpu_reg),temp); + setr8(cpu_reg,getr8(cpu_reg)-temp); + cycles-=((cpu_mod==3)?3:13); + break; + + case 0x2B: /*SUB cpu_reg,16*/ + fetchea(); + tempw=geteaw(); + setsub16(cpu_state.regs[cpu_reg].w,tempw); + cpu_state.regs[cpu_reg].w-=tempw; + cycles-=((cpu_mod==3)?3:13); + break; + + case 0x2C: /*SUB AL,#8*/ + temp=FETCH(); + setsub8(AL,temp); + AL-=temp; + cycles-=4; + break; + + case 0x2D: /*SUB AX,#16*/ + tempw=getword(); + setsub16(AX,tempw); + AX-=tempw; + cycles-=4; + break; + + case 0x2E: /*CS:*/ + oldss=ss; + oldds=ds; + ds=ss=cs; + cpu_state.ssegs=2; + cycles-=4; + goto opcodestart; + + case 0x2F: /*DAS*/ + if ((flags&A_FLAG)||((AL&0xF)>9)) { + tempi=((uint16_t)AL)-6; + AL-=6; + flags|=A_FLAG; + if (tempi&0x100) flags|=C_FLAG; + } + if ((flags&C_FLAG)||(AL>0x9F)) { + AL-=0x60; + flags|=C_FLAG; + } + setznp8(AL); + cycles-=4; + break; + + case 0x30: /*XOR 8,reg*/ + fetchea(); + temp=geteab(); + temp^=getr8(cpu_reg); + setznp8(temp); + flags&=~(C_FLAG|V_FLAG|A_FLAG); + seteab(temp); + cycles-=((cpu_mod==3)?3:24); + break; + + case 0x31: /*XOR 16,reg*/ + fetchea(); + tempw=geteaw(); + tempw^=cpu_state.regs[cpu_reg].w; + setznp16(tempw); + flags&=~(C_FLAG|V_FLAG|A_FLAG); + seteaw(tempw); + cycles-=((cpu_mod==3)?3:24); + break; + + case 0x32: /*XOR cpu_reg,8*/ + fetchea(); + temp=geteab(); + temp^=getr8(cpu_reg); + setznp8(temp); + flags&=~(C_FLAG|V_FLAG|A_FLAG); + setr8(cpu_reg,temp); + cycles-=((cpu_mod==3)?3:13); + break; + + case 0x33: /*XOR cpu_reg,16*/ + fetchea(); + tempw=geteaw(); + tempw^=cpu_state.regs[cpu_reg].w; + setznp16(tempw); + flags&=~(C_FLAG|V_FLAG|A_FLAG); + cpu_state.regs[cpu_reg].w=tempw; + cycles-=((cpu_mod==3)?3:13); + break; + + case 0x34: /*XOR AL,#8*/ + AL^=FETCH(); + setznp8(AL); + flags&=~(C_FLAG|V_FLAG|A_FLAG); + cycles-=4; + break; + + case 0x35: /*XOR AX,#16*/ + AX^=getword(); + setznp16(AX); + flags&=~(C_FLAG|V_FLAG|A_FLAG); + cycles-=4; + break; + + case 0x36: /*SS:*/ + oldss=ss; + oldds=ds; + ds=ss=ss; + cpu_state.ssegs=2; + cycles-=4; + goto opcodestart; + + case 0x37: /*AAA*/ + if ((flags&A_FLAG)||((AL&0xF)>9)) { + AL+=6; + AH++; + flags|=(A_FLAG|C_FLAG); + } else + flags&=~(A_FLAG|C_FLAG); + AL&=0xF; + cycles-=8; + break; + + case 0x38: /*CMP 8,reg*/ + fetchea(); + temp=geteab(); + setsub8(temp,getr8(cpu_reg)); + cycles-=((cpu_mod==3)?3:13); + break; + + case 0x39: /*CMP 16,reg*/ + fetchea(); + tempw=geteaw(); + setsub16(tempw,cpu_state.regs[cpu_reg].w); + cycles-=((cpu_mod==3)?3:13); + break; + + case 0x3A: /*CMP cpu_reg,8*/ + fetchea(); + temp=geteab(); + setsub8(getr8(cpu_reg),temp); + cycles-=((cpu_mod==3)?3:13); + break; + + case 0x3B: /*CMP cpu_reg,16*/ + fetchea(); + tempw=geteaw(); + setsub16(cpu_state.regs[cpu_reg].w,tempw); + cycles-=((cpu_mod==3)?3:13); + break; + + case 0x3C: /*CMP AL,#8*/ + temp=FETCH(); + setsub8(AL,temp); + cycles-=4; + break; + + case 0x3D: /*CMP AX,#16*/ + tempw=getword(); + setsub16(AX,tempw); + cycles-=4; + break; + + case 0x3E: /*DS:*/ + oldss=ss; + oldds=ds; + ds=ss=ds; + cpu_state.ssegs=2; + cycles-=4; + goto opcodestart; + + case 0x3F: /*AAS*/ + if ((flags&A_FLAG)||((AL&0xF)>9)) { + AL-=6; + AH--; + flags|=(A_FLAG|C_FLAG); + } else + flags&=~(A_FLAG|C_FLAG); + AL&=0xF; + cycles-=8; + break; + + case 0x40: case 0x41: case 0x42: case 0x43: /*INC r16*/ + case 0x44: case 0x45: case 0x46: case 0x47: + setadd16nc(cpu_state.regs[opcode&7].w,1); + cpu_state.regs[opcode&7].w++; + cycles-=3; + break; + + case 0x48: case 0x49: case 0x4A: case 0x4B: /*DEC r16*/ + case 0x4C: case 0x4D: case 0x4E: case 0x4F: + setsub16nc(cpu_state.regs[opcode&7].w,1); + cpu_state.regs[opcode&7].w--; + cycles-=3; + break; + + case 0x50: case 0x51: case 0x52: case 0x53: /*PUSH r16*/ + case 0x54: case 0x55: case 0x56: case 0x57: + if (cpu_state.ssegs) ss=oldss; + SP-=2; cpu_state.last_ea = SP; - cycles-=12; - break; + writememw(ss,SP,cpu_state.regs[opcode&7].w); + cycles-=15; + break; - case 0x20: /*AND 8,reg*/ - fetchea(); - temp=geteab(); - temp&=getr8(cpu_reg); - setznp8(temp); - flags&=~(C_FLAG|V_FLAG|A_FLAG); - seteab(temp); - cycles-=((cpu_mod==3)?3:24); - break; - case 0x21: /*AND 16,reg*/ - fetchea(); - tempw=geteaw(); - tempw&=cpu_state.regs[cpu_reg].w; - setznp16(tempw); - flags&=~(C_FLAG|V_FLAG|A_FLAG); - seteaw(tempw); - cycles-=((cpu_mod==3)?3:24); - break; - case 0x22: /*AND cpu_reg,8*/ - fetchea(); - temp=geteab(); - temp&=getr8(cpu_reg); - setznp8(temp); - flags&=~(C_FLAG|V_FLAG|A_FLAG); - setr8(cpu_reg,temp); - cycles-=((cpu_mod==3)?3:13); - break; - case 0x23: /*AND cpu_reg,16*/ - fetchea(); - tempw=geteaw(); - tempw&=cpu_state.regs[cpu_reg].w; - setznp16(tempw); - flags&=~(C_FLAG|V_FLAG|A_FLAG); - cpu_state.regs[cpu_reg].w=tempw; - cycles-=((cpu_mod==3)?3:13); - break; - case 0x24: /*AND AL,#8*/ - AL&=FETCH(); - setznp8(AL); - flags&=~(C_FLAG|V_FLAG|A_FLAG); - cycles-=4; - break; - case 0x25: /*AND AX,#16*/ - AX&=getword(); - setznp16(AX); - flags&=~(C_FLAG|V_FLAG|A_FLAG); - cycles-=4; - break; - - case 0x26: /*ES:*/ - oldss=ss; - oldds=ds; - ds=ss=es; - cpu_state.ssegs=2; - cycles-=4; - goto opcodestart; - - case 0x27: /*DAA*/ - if ((flags&A_FLAG) || ((AL&0xF)>9)) - { - tempi=((uint16_t)AL)+6; - AL+=6; - flags|=A_FLAG; - if (tempi&0x100) flags|=C_FLAG; - } - if ((flags&C_FLAG) || (AL>0x9F)) - { - AL+=0x60; - flags|=C_FLAG; - } - setznp8(AL); - cycles-=4; - break; - - case 0x28: /*SUB 8,reg*/ - fetchea(); - temp=geteab(); - setsub8(temp,getr8(cpu_reg)); - temp-=getr8(cpu_reg); - seteab(temp); - cycles-=((cpu_mod==3)?3:24); - break; - case 0x29: /*SUB 16,reg*/ - fetchea(); - tempw=geteaw(); - setsub16(tempw,cpu_state.regs[cpu_reg].w); - tempw-=cpu_state.regs[cpu_reg].w; - seteaw(tempw); - cycles-=((cpu_mod==3)?3:24); - break; - case 0x2A: /*SUB cpu_reg,8*/ - fetchea(); - temp=geteab(); - setsub8(getr8(cpu_reg),temp); - setr8(cpu_reg,getr8(cpu_reg)-temp); - cycles-=((cpu_mod==3)?3:13); - break; - case 0x2B: /*SUB cpu_reg,16*/ - fetchea(); - tempw=geteaw(); - setsub16(cpu_state.regs[cpu_reg].w,tempw); - cpu_state.regs[cpu_reg].w-=tempw; - cycles-=((cpu_mod==3)?3:13); - break; - case 0x2C: /*SUB AL,#8*/ - temp=FETCH(); - setsub8(AL,temp); - AL-=temp; - cycles-=4; - break; - case 0x2D: /*SUB AX,#16*/ - tempw=getword(); - setsub16(AX,tempw); - AX-=tempw; - cycles-=4; - break; - case 0x2E: /*CS:*/ - oldss=ss; - oldds=ds; - ds=ss=cs; - cpu_state.ssegs=2; - cycles-=4; - goto opcodestart; - case 0x2F: /*DAS*/ - if ((flags&A_FLAG)||((AL&0xF)>9)) - { - tempi=((uint16_t)AL)-6; - AL-=6; - flags|=A_FLAG; - if (tempi&0x100) flags|=C_FLAG; - } - if ((flags&C_FLAG)||(AL>0x9F)) - { - AL-=0x60; - flags|=C_FLAG; - } - setznp8(AL); - cycles-=4; - break; - case 0x30: /*XOR 8,reg*/ - fetchea(); - temp=geteab(); - temp^=getr8(cpu_reg); - setznp8(temp); - flags&=~(C_FLAG|V_FLAG|A_FLAG); - seteab(temp); - cycles-=((cpu_mod==3)?3:24); - break; - case 0x31: /*XOR 16,reg*/ - fetchea(); - tempw=geteaw(); - tempw^=cpu_state.regs[cpu_reg].w; - setznp16(tempw); - flags&=~(C_FLAG|V_FLAG|A_FLAG); - seteaw(tempw); - cycles-=((cpu_mod==3)?3:24); - break; - case 0x32: /*XOR cpu_reg,8*/ - fetchea(); - temp=geteab(); - temp^=getr8(cpu_reg); - setznp8(temp); - flags&=~(C_FLAG|V_FLAG|A_FLAG); - setr8(cpu_reg,temp); - cycles-=((cpu_mod==3)?3:13); - break; - case 0x33: /*XOR cpu_reg,16*/ - fetchea(); - tempw=geteaw(); - tempw^=cpu_state.regs[cpu_reg].w; - setznp16(tempw); - flags&=~(C_FLAG|V_FLAG|A_FLAG); - cpu_state.regs[cpu_reg].w=tempw; - cycles-=((cpu_mod==3)?3:13); - break; - case 0x34: /*XOR AL,#8*/ - AL^=FETCH(); - setznp8(AL); - flags&=~(C_FLAG|V_FLAG|A_FLAG); - cycles-=4; - break; - case 0x35: /*XOR AX,#16*/ - AX^=getword(); - setznp16(AX); - flags&=~(C_FLAG|V_FLAG|A_FLAG); - cycles-=4; - break; - - case 0x36: /*SS:*/ - oldss=ss; - oldds=ds; - ds=ss=ss; - cpu_state.ssegs=2; - cycles-=4; - goto opcodestart; - - case 0x37: /*AAA*/ - if ((flags&A_FLAG)||((AL&0xF)>9)) - { - AL+=6; - AH++; - flags|=(A_FLAG|C_FLAG); - } - else - flags&=~(A_FLAG|C_FLAG); - AL&=0xF; - cycles-=8; - break; - - case 0x38: /*CMP 8,reg*/ - fetchea(); - temp=geteab(); - setsub8(temp,getr8(cpu_reg)); - cycles-=((cpu_mod==3)?3:13); - break; - case 0x39: /*CMP 16,reg*/ - fetchea(); - tempw=geteaw(); - setsub16(tempw,cpu_state.regs[cpu_reg].w); - cycles-=((cpu_mod==3)?3:13); - break; - case 0x3A: /*CMP cpu_reg,8*/ - fetchea(); - temp=geteab(); - setsub8(getr8(cpu_reg),temp); - cycles-=((cpu_mod==3)?3:13); - break; - case 0x3B: /*CMP cpu_reg,16*/ - fetchea(); - tempw=geteaw(); - setsub16(cpu_state.regs[cpu_reg].w,tempw); - cycles-=((cpu_mod==3)?3:13); - break; - case 0x3C: /*CMP AL,#8*/ - temp=FETCH(); - setsub8(AL,temp); - cycles-=4; - break; - case 0x3D: /*CMP AX,#16*/ - tempw=getword(); - setsub16(AX,tempw); - cycles-=4; - break; - - case 0x3E: /*DS:*/ - oldss=ss; - oldds=ds; - ds=ss=ds; - cpu_state.ssegs=2; - cycles-=4; - goto opcodestart; - - case 0x3F: /*AAS*/ - if ((flags&A_FLAG)||((AL&0xF)>9)) - { - AL-=6; - AH--; - flags|=(A_FLAG|C_FLAG); - } - else - flags&=~(A_FLAG|C_FLAG); - AL&=0xF; - cycles-=8; - break; - - case 0x40: case 0x41: case 0x42: case 0x43: /*INC r16*/ - case 0x44: case 0x45: case 0x46: case 0x47: - setadd16nc(cpu_state.regs[opcode&7].w,1); - cpu_state.regs[opcode&7].w++; - cycles-=3; - break; - case 0x48: case 0x49: case 0x4A: case 0x4B: /*DEC r16*/ - case 0x4C: case 0x4D: case 0x4E: case 0x4F: - setsub16nc(cpu_state.regs[opcode&7].w,1); - cpu_state.regs[opcode&7].w--; - cycles-=3; - break; - - case 0x50: case 0x51: case 0x52: case 0x53: /*PUSH r16*/ - case 0x54: case 0x55: case 0x56: case 0x57: - if (cpu_state.ssegs) ss=oldss; - SP-=2; + case 0x58: case 0x59: case 0x5A: case 0x5B: /*POP r16*/ + case 0x5C: case 0x5D: case 0x5E: case 0x5F: + if (cpu_state.ssegs) ss=oldss; + SP+=2; cpu_state.last_ea = SP; - writememw(ss,SP,cpu_state.regs[opcode&7].w); - cycles-=15; - break; - case 0x58: case 0x59: case 0x5A: case 0x5B: /*POP r16*/ - case 0x5C: case 0x5D: case 0x5E: case 0x5F: - if (cpu_state.ssegs) ss=oldss; - SP+=2; - cpu_state.last_ea = SP; - cpu_state.regs[opcode&7].w=readmemw(ss,(SP-2)&0xFFFF); - cycles-=12; - break; + cpu_state.regs[opcode&7].w=readmemw(ss,(SP-2)&0xFFFF); + cycles-=12; + break; - - case 0x60: /*JO alias*/ - case 0x70: /*JO*/ - offset=(int8_t)FETCH(); - if (flags&V_FLAG) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); } - cycles-=4; - break; - case 0x61: /*JNO alias*/ - case 0x71: /*JNO*/ - offset=(int8_t)FETCH(); - if (!(flags&V_FLAG)) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); } - cycles-=4; - break; - case 0x62: /*JB alias*/ - case 0x72: /*JB*/ - offset=(int8_t)FETCH(); - if (flags&C_FLAG) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); } - cycles-=4; - break; - case 0x63: /*JNB alias*/ - case 0x73: /*JNB*/ - offset=(int8_t)FETCH(); - if (!(flags&C_FLAG)) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); } - cycles-=4; - break; - case 0x64: /*JE alias*/ - case 0x74: /*JE*/ - offset=(int8_t)FETCH(); - if (flags&Z_FLAG) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); } - cycles-=4; - break; - case 0x65: /*JNE alias*/ - case 0x75: /*JNE*/ - offset=(int8_t)FETCH(); - cycles-=4; - if (!(flags&Z_FLAG)) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); } - break; - case 0x66: /*JBE alias*/ - case 0x76: /*JBE*/ - offset=(int8_t)FETCH(); - if (flags&(C_FLAG|Z_FLAG)) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); } - cycles-=4; - break; - case 0x67: /*JNBE alias*/ - case 0x77: /*JNBE*/ - offset=(int8_t)FETCH(); - if (!(flags&(C_FLAG|Z_FLAG))) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); } - cycles-=4; - break; - case 0x68: /*JS alias*/ - case 0x78: /*JS*/ - offset=(int8_t)FETCH(); - if (flags&N_FLAG) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); } - cycles-=4; - break; - case 0x69: /*JNS alias*/ - case 0x79: /*JNS*/ - offset=(int8_t)FETCH(); - if (!(flags&N_FLAG)) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); } - cycles-=4; - break; - case 0x6A: /*JP alias*/ - case 0x7A: /*JP*/ - offset=(int8_t)FETCH(); - if (flags&P_FLAG) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); } - cycles-=4; - break; - case 0x6B: /*JNP alias*/ - case 0x7B: /*JNP*/ - offset=(int8_t)FETCH(); - if (!(flags&P_FLAG)) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); } - cycles-=4; - break; - case 0x6C: /*JL alias*/ - case 0x7C: /*JL*/ - offset=(int8_t)FETCH(); - temp=(flags&N_FLAG)?1:0; - temp2=(flags&V_FLAG)?1:0; - if (temp!=temp2) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); } - cycles-=4; - break; - case 0x6D: /*JNL alias*/ - case 0x7D: /*JNL*/ - offset=(int8_t)FETCH(); - temp=(flags&N_FLAG)?1:0; - temp2=(flags&V_FLAG)?1:0; - if (temp==temp2) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); } - cycles-=4; - break; - case 0x6E: /*JLE alias*/ - case 0x7E: /*JLE*/ - offset=(int8_t)FETCH(); - temp=(flags&N_FLAG)?1:0; - temp2=(flags&V_FLAG)?1:0; - if ((flags&Z_FLAG) || (temp!=temp2)) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); } - cycles-=4; - break; - case 0x6F: /*JNLE alias*/ - case 0x7F: /*JNLE*/ - offset=(int8_t)FETCH(); - temp=(flags&N_FLAG)?1:0; - temp2=(flags&V_FLAG)?1:0; - if (!((flags&Z_FLAG) || (temp!=temp2))) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); } - cycles-=4; - break; - - case 0x80: case 0x82: - fetchea(); - temp=geteab(); - temp2=FETCH(); - switch (rmdat&0x38) - { - case 0x00: /*ADD b,#8*/ - setadd8(temp,temp2); - seteab(temp+temp2); - cycles-=((cpu_mod==3)?4:23); - break; - case 0x08: /*OR b,#8*/ - temp|=temp2; - setznp8(temp); - flags&=~(C_FLAG|V_FLAG|A_FLAG); - seteab(temp); - cycles-=((cpu_mod==3)?4:23); - break; - case 0x10: /*ADC b,#8*/ - setadc8(temp,temp2); - seteab(temp+temp2+tempc); - cycles-=((cpu_mod==3)?4:23); - break; - case 0x18: /*SBB b,#8*/ - setsbc8(temp,temp2); - seteab(temp-(temp2+tempc)); - cycles-=((cpu_mod==3)?4:23); - break; - case 0x20: /*AND b,#8*/ - temp&=temp2; - setznp8(temp); - flags&=~(C_FLAG|V_FLAG|A_FLAG); - seteab(temp); - cycles-=((cpu_mod==3)?4:23); - break; - case 0x28: /*SUB b,#8*/ - setsub8(temp,temp2); - seteab(temp-temp2); - cycles-=((cpu_mod==3)?4:23); - break; - case 0x30: /*XOR b,#8*/ - temp^=temp2; - setznp8(temp); - flags&=~(C_FLAG|V_FLAG|A_FLAG); - seteab(temp); - cycles-=((cpu_mod==3)?4:23); - break; - case 0x38: /*CMP b,#8*/ - setsub8(temp,temp2); - cycles-=((cpu_mod==3)?4:14); - break; - } - break; - - case 0x81: - fetchea(); - tempw=geteaw(); - tempw2=getword(); - switch (rmdat&0x38) - { - case 0x00: /*ADD w,#16*/ - setadd16(tempw,tempw2); - tempw+=tempw2; - seteaw(tempw); - cycles-=((cpu_mod==3)?4:23); - break; - case 0x08: /*OR w,#16*/ - tempw|=tempw2; - setznp16(tempw); - flags&=~(C_FLAG|V_FLAG|A_FLAG); - seteaw(tempw); - cycles-=((cpu_mod==3)?4:23); - break; - case 0x10: /*ADC w,#16*/ - setadc16(tempw,tempw2); - tempw+=tempw2+tempc; - seteaw(tempw); - cycles-=((cpu_mod==3)?4:23); - break; - case 0x20: /*AND w,#16*/ - tempw&=tempw2; - setznp16(tempw); - flags&=~(C_FLAG|V_FLAG|A_FLAG); - seteaw(tempw); - cycles-=((cpu_mod==3)?4:23); - break; - case 0x18: /*SBB w,#16*/ - setsbc16(tempw,tempw2); - seteaw(tempw-(tempw2+tempc)); - cycles-=((cpu_mod==3)?4:23); - break; - case 0x28: /*SUB w,#16*/ - setsub16(tempw,tempw2); - tempw-=tempw2; - seteaw(tempw); - cycles-=((cpu_mod==3)?4:23); - break; - case 0x30: /*XOR w,#16*/ - tempw^=tempw2; - setznp16(tempw); - flags&=~(C_FLAG|V_FLAG|A_FLAG); - seteaw(tempw); - cycles-=((cpu_mod==3)?4:23); - break; - case 0x38: /*CMP w,#16*/ - setsub16(tempw,tempw2); - cycles-=((cpu_mod==3)?4:14); - break; - } - break; - - case 0x83: - fetchea(); - tempw=geteaw(); - tempw2=FETCH(); - if (tempw2&0x80) tempw2|=0xFF00; - switch (rmdat&0x38) - { - case 0x00: /*ADD w,#8*/ - setadd16(tempw,tempw2); - tempw+=tempw2; - seteaw(tempw); - cycles-=((cpu_mod==3)?4:23); - break; - case 0x08: /*OR w,#8*/ - tempw|=tempw2; - setznp16(tempw); - seteaw(tempw); - flags&=~(C_FLAG|A_FLAG|V_FLAG); - cycles-=((cpu_mod==3)?4:23); - break; - case 0x10: /*ADC w,#8*/ - setadc16(tempw,tempw2); - tempw+=tempw2+tempc; - seteaw(tempw); - cycles-=((cpu_mod==3)?4:23); - break; - case 0x18: /*SBB w,#8*/ - setsbc16(tempw,tempw2); - tempw-=(tempw2+tempc); - seteaw(tempw); - cycles-=((cpu_mod==3)?4:23); - break; - case 0x20: /*AND w,#8*/ - tempw&=tempw2; - setznp16(tempw); - seteaw(tempw); - cycles-=((cpu_mod==3)?4:23); - flags&=~(C_FLAG|A_FLAG|V_FLAG); - break; - case 0x28: /*SUB w,#8*/ - setsub16(tempw,tempw2); - tempw-=tempw2; - seteaw(tempw); - cycles-=((cpu_mod==3)?4:23); - break; - case 0x30: /*XOR w,#8*/ - tempw^=tempw2; - setznp16(tempw); - seteaw(tempw); - cycles-=((cpu_mod==3)?4:23); - flags&=~(C_FLAG|A_FLAG|V_FLAG); - break; - case 0x38: /*CMP w,#8*/ - setsub16(tempw,tempw2); - cycles-=((cpu_mod==3)?4:14); - break; - } - break; - - case 0x84: /*TEST b,reg*/ - fetchea(); - temp=geteab(); - temp2=getr8(cpu_reg); - setznp8(temp&temp2); - flags&=~(C_FLAG|V_FLAG|A_FLAG); - cycles-=((cpu_mod==3)?3:13); - break; - case 0x85: /*TEST w,reg*/ - fetchea(); - tempw=geteaw(); - tempw2=cpu_state.regs[cpu_reg].w; - setznp16(tempw&tempw2); - flags&=~(C_FLAG|V_FLAG|A_FLAG); - cycles-=((cpu_mod==3)?3:13); - break; - case 0x86: /*XCHG b,reg*/ - fetchea(); - temp=geteab(); - seteab(getr8(cpu_reg)); - setr8(cpu_reg,temp); - cycles-=((cpu_mod==3)?4:25); - break; - case 0x87: /*XCHG w,reg*/ - fetchea(); - tempw=geteaw(); - seteaw(cpu_state.regs[cpu_reg].w); - cpu_state.regs[cpu_reg].w=tempw; - cycles-=((cpu_mod==3)?4:25); - break; - - case 0x88: /*MOV b,reg*/ - fetchea(); - seteab(getr8(cpu_reg)); - cycles-=((cpu_mod==3)?2:13); - break; - case 0x89: /*MOV w,reg*/ - fetchea(); - seteaw(cpu_state.regs[cpu_reg].w); - cycles-=((cpu_mod==3)?2:13); - break; - case 0x8A: /*MOV cpu_reg,b*/ - fetchea(); - temp=geteab(); - setr8(cpu_reg,temp); - cycles-=((cpu_mod==3)?2:12); - break; - case 0x8B: /*MOV cpu_reg,w*/ - fetchea(); - tempw=geteaw(); - cpu_state.regs[cpu_reg].w=tempw; - cycles-=((cpu_mod==3)?2:12); - break; - - case 0x8C: /*MOV w,sreg*/ - fetchea(); - switch (rmdat&0x38) - { - case 0x00: /*ES*/ - seteaw(ES); - break; - case 0x08: /*CS*/ - seteaw(CS); - break; - case 0x18: /*DS*/ - if (cpu_state.ssegs) ds=oldds; - seteaw(DS); - break; - case 0x10: /*SS*/ - if (cpu_state.ssegs) ss=oldss; - seteaw(SS); - break; - } - cycles-=((cpu_mod==3)?2:13); - break; - - case 0x8D: /*LEA*/ - fetchea(); - cpu_state.regs[cpu_reg].w=(cpu_mod == 3)?cpu_state.last_ea:cpu_state.eaaddr; - cycles-=2; - break; - - case 0x8E: /*MOV sreg,w*/ - fetchea(); - switch (rmdat&0x38) - { - case 0x00: /*ES*/ - tempw=geteaw(); - loadseg(tempw,&_es); - break; - case 0x08: /*CS - 8088/8086 only*/ - tempw=geteaw(); - loadseg(tempw,&_cs); - break; - case 0x18: /*DS*/ - tempw=geteaw(); - loadseg(tempw,&_ds); - if (cpu_state.ssegs) oldds=ds; - break; - case 0x10: /*SS*/ - tempw=geteaw(); - loadseg(tempw,&_ss); - if (cpu_state.ssegs) oldss=ss; - break; - } - cycles-=((cpu_mod==3)?2:12); - skipnextprint=1; - noint=1; - break; - - case 0x8F: /*POPW*/ - fetchea(); - if (cpu_state.ssegs) ss=oldss; - tempw=readmemw(ss,SP); - SP+=2; - cpu_state.last_ea = SP; - seteaw(tempw); - cycles-=25; - break; - - case 0x90: /*NOP*/ - cycles-=3; - break; - - case 0x91: case 0x92: case 0x93: /*XCHG AX*/ - case 0x94: case 0x95: case 0x96: case 0x97: - tempw=AX; - AX=cpu_state.regs[opcode&7].w; - cpu_state.regs[opcode&7].w=tempw; - cycles-=3; - break; - - case 0x98: /*CBW*/ - AH=(AL&0x80)?0xFF:0; - cycles-=2; - break; - case 0x99: /*CWD*/ - DX=(AX&0x8000)?0xFFFF:0; - cycles-=5; - break; - case 0x9A: /*CALL FAR*/ - tempw=getword(); - tempw2=getword(); - tempw3=CS; - tempw4=cpu_state.pc; - if (cpu_state.ssegs) ss=oldss; - cpu_state.pc=tempw; - loadcs(tempw2); - writememw(ss,(SP-2)&0xFFFF,tempw3); - writememw(ss,(SP-4)&0xFFFF,tempw4); - SP-=4; - cpu_state.last_ea = SP; - cycles-=36; - FETCHCLEAR(); - break; - case 0x9B: /*WAIT*/ - cycles-=4; - break; - case 0x9C: /*PUSHF*/ - if (cpu_state.ssegs) ss=oldss; - writememw(ss,((SP-2)&0xFFFF),flags|0xF000); - SP-=2; - cpu_state.last_ea = SP; - cycles-=14; - break; - case 0x9D: /*POPF*/ - if (cpu_state.ssegs) ss=oldss; - flags=readmemw(ss,SP)&0xFFF; - SP+=2; - cpu_state.last_ea = SP; - cycles-=12; - break; - case 0x9E: /*SAHF*/ - flags=(flags&0xFF00)|AH; - cycles-=4; - break; - case 0x9F: /*LAHF*/ - AH=flags&0xFF; - cycles-=4; - break; - - case 0xA0: /*MOV AL,(w)*/ - addr=getword(); - AL=readmemb(ds+addr); - cycles-=14; - break; - case 0xA1: /*MOV AX,(w)*/ - addr=getword(); - AX=readmemw(ds,addr); - cycles-=14; - break; - case 0xA2: /*MOV (w),AL*/ - addr=getword(); - writememb(ds+addr,AL); - cycles-=14; - break; - case 0xA3: /*MOV (w),AX*/ - addr=getword(); - writememw(ds,addr,AX); - cycles-=14; - break; - - case 0xA4: /*MOVSB*/ - temp=readmemb(ds+SI); - writememb(es+DI,temp); - if (flags&D_FLAG) { DI--; SI--; } - else { DI++; SI++; } - cycles-=18; - break; - case 0xA5: /*MOVSW*/ - tempw=readmemw(ds,SI); - writememw(es,DI,tempw); - if (flags&D_FLAG) { DI-=2; SI-=2; } - else { DI+=2; SI+=2; } - cycles-=18; - break; - case 0xA6: /*CMPSB*/ - temp =readmemb(ds+SI); - temp2=readmemb(es+DI); - setsub8(temp,temp2); - if (flags&D_FLAG) { DI--; SI--; } - else { DI++; SI++; } - cycles-=30; - break; - case 0xA7: /*CMPSW*/ - tempw =readmemw(ds,SI); - tempw2=readmemw(es,DI); - setsub16(tempw,tempw2); - if (flags&D_FLAG) { DI-=2; SI-=2; } - else { DI+=2; SI+=2; } - cycles-=30; - break; - case 0xA8: /*TEST AL,#8*/ - temp=FETCH(); - setznp8(AL&temp); - flags&=~(C_FLAG|V_FLAG|A_FLAG); - cycles-=5; - break; - case 0xA9: /*TEST AX,#16*/ - tempw=getword(); - setznp16(AX&tempw); - flags&=~(C_FLAG|V_FLAG|A_FLAG); - cycles-=5; - break; - case 0xAA: /*STOSB*/ - writememb(es+DI,AL); - if (flags&D_FLAG) DI--; - else DI++; - cycles-=11; - break; - case 0xAB: /*STOSW*/ - writememw(es,DI,AX); - if (flags&D_FLAG) DI-=2; - else DI+=2; - cycles-=11; - break; - case 0xAC: /*LODSB*/ - AL=readmemb(ds+SI); - if (flags&D_FLAG) SI--; - else SI++; - cycles-=16; - break; - case 0xAD: /*LODSW*/ - AX=readmemw(ds,SI); - if (flags&D_FLAG) SI-=2; - else SI+=2; - cycles-=16; - break; - case 0xAE: /*SCASB*/ - temp=readmemb(es+DI); - setsub8(AL,temp); - if (flags&D_FLAG) DI--; - else DI++; - cycles-=19; - break; - case 0xAF: /*SCASW*/ - tempw=readmemw(es,DI); - setsub16(AX,tempw); - if (flags&D_FLAG) DI-=2; - else DI+=2; - cycles-=19; - break; - - case 0xB0: /*MOV AL,#8*/ - AL=FETCH(); - cycles-=4; - break; - case 0xB1: /*MOV CL,#8*/ - CL=FETCH(); - cycles-=4; - break; - case 0xB2: /*MOV DL,#8*/ - DL=FETCH(); - cycles-=4; - break; - case 0xB3: /*MOV BL,#8*/ - BL=FETCH(); - cycles-=4; - break; - case 0xB4: /*MOV AH,#8*/ - AH=FETCH(); - cycles-=4; - break; - case 0xB5: /*MOV CH,#8*/ - CH=FETCH(); - cycles-=4; - break; - case 0xB6: /*MOV DH,#8*/ - DH=FETCH(); - cycles-=4; - break; - case 0xB7: /*MOV BH,#8*/ - BH=FETCH(); - cycles-=4; - break; - case 0xB8: case 0xB9: case 0xBA: case 0xBB: /*MOV cpu_reg,#16*/ - case 0xBC: case 0xBD: case 0xBE: case 0xBF: - cpu_state.regs[opcode&7].w=getword(); - cycles-=4; - break; - - case 0xC0: /*RET alias*/ - case 0xC2: /*RET*/ - tempw=getword(); - if (cpu_state.ssegs) ss=oldss; - cpu_state.pc=readmemw(ss,SP); - SP+=2+tempw; - cycles-=24; - FETCHCLEAR(); - break; - case 0xC1: /*RET alias*/ - case 0xC3: /*RET*/ - if (cpu_state.ssegs) ss=oldss; - cpu_state.pc=readmemw(ss,SP); - SP+=2; - cycles-=20; - FETCHCLEAR(); - break; - case 0xC4: /*LES*/ - fetchea(); - cpu_state.regs[cpu_reg].w=readmemw(easeg,cpu_state.eaaddr); - tempw=readmemw(easeg,(cpu_state.eaaddr+2)&0xFFFF); - loadseg(tempw,&_es); - cycles-=24; - break; - case 0xC5: /*LDS*/ - fetchea(); - cpu_state.regs[cpu_reg].w=readmemw(easeg,cpu_state.eaaddr); - tempw=readmemw(easeg,(cpu_state.eaaddr+2)&0xFFFF); - loadseg(tempw,&_ds); - if (cpu_state.ssegs) oldds=ds; - cycles-=24; - break; - case 0xC6: /*MOV b,#8*/ - fetchea(); - temp=FETCH(); - seteab(temp); - cycles-=((cpu_mod==3)?4:14); - break; - case 0xC7: /*MOV w,#16*/ - fetchea(); - tempw=getword(); - seteaw(tempw); - cycles-=((cpu_mod==3)?4:14); - break; - - case 0xC8: /*RETF alias*/ - case 0xCA: /*RETF*/ - tempw=getword(); - if (cpu_state.ssegs) ss=oldss; - cpu_state.pc=readmemw(ss,SP); - loadcs(readmemw(ss,SP+2)); - SP+=4; - SP+=tempw; - cycles-=33; - FETCHCLEAR(); - break; - case 0xC9: /*RETF alias*/ - case 0xCB: /*RETF*/ - if (cpu_state.ssegs) ss=oldss; - cpu_state.pc=readmemw(ss,SP); - loadcs(readmemw(ss,SP+2)); - SP+=4; - cycles-=34; - FETCHCLEAR(); - break; - case 0xCC: /*INT 3*/ - if (cpu_state.ssegs) ss=oldss; - writememw(ss,((SP-2)&0xFFFF),flags|0xF000); - writememw(ss,((SP-4)&0xFFFF),CS); - writememw(ss,((SP-6)&0xFFFF),cpu_state.pc); - SP-=6; - addr=3<<2; - flags&=~I_FLAG; - flags&=~T_FLAG; - cpu_state.pc=readmemw(0,addr); - loadcs(readmemw(0,addr+2)); - FETCHCLEAR(); - cycles-=72; - break; - case 0xCD: /*INT*/ - lastpc=cpu_state.pc; - lastcs=CS; - temp=FETCH(); - - if (cpu_state.ssegs) ss=oldss; - writememw(ss,((SP-2)&0xFFFF),flags|0xF000); - writememw(ss,((SP-4)&0xFFFF),CS); - writememw(ss,((SP-6)&0xFFFF),cpu_state.pc); - flags&=~T_FLAG; - SP-=6; - addr=temp<<2; - cpu_state.pc=readmemw(0,addr); - - loadcs(readmemw(0,addr+2)); - FETCHCLEAR(); - - cycles-=71; - break; - case 0xCF: /*IRET*/ - if (cpu_state.ssegs) ss=oldss; - tempw=CS; - tempw2=cpu_state.pc; - cpu_state.pc=readmemw(ss,SP); - loadcs(readmemw(ss,((SP+2)&0xFFFF))); - flags=readmemw(ss,((SP+4)&0xFFFF))&0xFFF; - SP+=6; - cycles-=44; - FETCHCLEAR(); - nmi_enable = 1; - break; - case 0xD0: - fetchea(); - temp=geteab(); - switch (rmdat&0x38) - { - case 0x00: /*ROL b,1*/ - if (temp&0x80) flags|=C_FLAG; - else flags&=~C_FLAG; - temp<<=1; - if (flags&C_FLAG) temp|=1; - seteab(temp); - if ((flags&C_FLAG)^(temp>>7)) flags|=V_FLAG; - else flags&=~V_FLAG; - cycles-=((cpu_mod==3)?2:23); - break; - case 0x08: /*ROR b,1*/ - if (temp&1) flags|=C_FLAG; - else flags&=~C_FLAG; - temp>>=1; - if (flags&C_FLAG) temp|=0x80; - seteab(temp); - if ((temp^(temp>>1))&0x40) flags|=V_FLAG; - else flags&=~V_FLAG; - cycles-=((cpu_mod==3)?2:23); - break; - case 0x10: /*RCL b,1*/ - temp2=flags&C_FLAG; - if (temp&0x80) flags|=C_FLAG; - else flags&=~C_FLAG; - temp<<=1; - if (temp2) temp|=1; - seteab(temp); - if ((flags&C_FLAG)^(temp>>7)) flags|=V_FLAG; - else flags&=~V_FLAG; - cycles-=((cpu_mod==3)?2:23); - break; - case 0x18: /*RCR b,1*/ - temp2=flags&C_FLAG; - if (temp&1) flags|=C_FLAG; - else flags&=~C_FLAG; - temp>>=1; - if (temp2) temp|=0x80; - seteab(temp); - if ((temp^(temp>>1))&0x40) flags|=V_FLAG; - else flags&=~V_FLAG; - cycles-=((cpu_mod==3)?2:23); - break; - case 0x20: case 0x30: /*SHL b,1*/ - if (temp&0x80) flags|=C_FLAG; - else flags&=~C_FLAG; - if ((temp^(temp<<1))&0x80) flags|=V_FLAG; - else flags&=~V_FLAG; - temp<<=1; - seteab(temp); - setznp8(temp); - cycles-=((cpu_mod==3)?2:23); - flags|=A_FLAG; - break; - case 0x28: /*SHR b,1*/ - if (temp&1) flags|=C_FLAG; - else flags&=~C_FLAG; - if (temp&0x80) flags|=V_FLAG; - else flags&=~V_FLAG; - temp>>=1; - seteab(temp); - setznp8(temp); - cycles-=((cpu_mod==3)?2:23); - flags|=A_FLAG; - break; - case 0x38: /*SAR b,1*/ - if (temp&1) flags|=C_FLAG; - else flags&=~C_FLAG; - temp>>=1; - if (temp&0x40) temp|=0x80; - seteab(temp); - setznp8(temp); - cycles-=((cpu_mod==3)?2:23); - flags|=A_FLAG; - flags&=~V_FLAG; - break; - } - break; - - case 0xD1: - fetchea(); - tempw=geteaw(); - switch (rmdat&0x38) - { - case 0x00: /*ROL w,1*/ - if (tempw&0x8000) flags|=C_FLAG; - else flags&=~C_FLAG; - tempw<<=1; - if (flags&C_FLAG) tempw|=1; - seteaw(tempw); - if ((flags&C_FLAG)^(tempw>>15)) flags|=V_FLAG; - else flags&=~V_FLAG; - cycles-=((cpu_mod==3)?2:23); - break; - case 0x08: /*ROR w,1*/ - if (tempw&1) flags|=C_FLAG; - else flags&=~C_FLAG; - tempw>>=1; - if (flags&C_FLAG) tempw|=0x8000; - seteaw(tempw); - if ((tempw^(tempw>>1))&0x4000) flags|=V_FLAG; - else flags&=~V_FLAG; - cycles-=((cpu_mod==3)?2:23); - break; - case 0x10: /*RCL w,1*/ - temp2=flags&C_FLAG; - if (tempw&0x8000) flags|=C_FLAG; - else flags&=~C_FLAG; - tempw<<=1; - if (temp2) tempw|=1; - seteaw(tempw); - if ((flags&C_FLAG)^(tempw>>15)) flags|=V_FLAG; - else flags&=~V_FLAG; - cycles-=((cpu_mod==3)?2:23); - break; - case 0x18: /*RCR w,1*/ - temp2=flags&C_FLAG; - if (tempw&1) flags|=C_FLAG; - else flags&=~C_FLAG; - tempw>>=1; - if (temp2) tempw|=0x8000; - seteaw(tempw); - if ((tempw^(tempw>>1))&0x4000) flags|=V_FLAG; - else flags&=~V_FLAG; - cycles-=((cpu_mod==3)?2:23); - break; - case 0x20: case 0x30: /*SHL w,1*/ - if (tempw&0x8000) flags|=C_FLAG; - else flags&=~C_FLAG; - if ((tempw^(tempw<<1))&0x8000) flags|=V_FLAG; - else flags&=~V_FLAG; - tempw<<=1; - seteaw(tempw); - setznp16(tempw); - cycles-=((cpu_mod==3)?2:23); - flags|=A_FLAG; - break; - case 0x28: /*SHR w,1*/ - if (tempw&1) flags|=C_FLAG; - else flags&=~C_FLAG; - if (tempw&0x8000) flags|=V_FLAG; - else flags&=~V_FLAG; - tempw>>=1; - seteaw(tempw); - setznp16(tempw); - cycles-=((cpu_mod==3)?2:23); - flags|=A_FLAG; - break; - - case 0x38: /*SAR w,1*/ - if (tempw&1) flags|=C_FLAG; - else flags&=~C_FLAG; - tempw>>=1; - if (tempw&0x4000) tempw|=0x8000; - seteaw(tempw); - setznp16(tempw); - cycles-=((cpu_mod==3)?2:23); - flags|=A_FLAG; - flags&=~V_FLAG; - break; - } - break; - - case 0xD2: - fetchea(); - temp=geteab(); - c=CL; - if (!c) break; - switch (rmdat&0x38) - { - case 0x00: /*ROL b,CL*/ - temp2=(temp&0x80)?1:0; - if (!c) - { - cycles-=((cpu_mod==3)?8:28); - break; + case 0x60: + if (is_nec) { /*186+ PUSHA*/ + writememw(ss, ((SP - 2) & 0xFFFF), AX); + writememw(ss, ((SP - 4) & 0xFFFF), CX); + writememw(ss, ((SP - 6) & 0xFFFF), DX); + writememw(ss, ((SP - 8) & 0xFFFF), BX); + writememw(ss, ((SP - 10) & 0xFFFF), SP); + writememw(ss, ((SP - 12) & 0xFFFF), BP); + writememw(ss, ((SP - 14) & 0xFFFF), SI); + writememw(ss, ((SP - 16) & 0xFFFF), DI); + cycles-=18; + break; + } else { /*JO alias*/ + offset=(int8_t)FETCH(); + if (flags&V_FLAG) { + cpu_state.pc+=offset; + cycles-=12; + FETCHCLEAR(); } - while (c>0) - { - temp2=(temp&0x80)?1:0; - temp=(temp<<1)|temp2; - c--; - cycles-=4; - } - if (temp2) flags|=C_FLAG; - else flags&=~C_FLAG; - seteab(temp); - if ((flags&C_FLAG)^(temp>>7)) flags|=V_FLAG; - else flags&=~V_FLAG; - cycles-=((cpu_mod==3)?8:28); - break; - case 0x08: /*ROR b,CL*/ - temp2=temp&1; - if (!c) + cycles-=4; + } + break; + + case 0x61: + if (is_nec) { /*186+ POPA*/ + DI = readmemw(ss, ((SP) & 0xFFFF)); + SI = readmemw(ss, ((SP + 2) & 0xFFFF)); + BP = readmemw(ss, ((SP + 4) & 0xFFFF)); + BX = readmemw(ss, ((SP + 8) & 0xFFFF)); + DX = readmemw(ss, ((SP + 10) & 0xFFFF)); + CX = readmemw(ss, ((SP + 12) & 0xFFFF)); + AX = readmemw(ss, ((SP + 14) & 0xFFFF)); + SP += 16; + cycles-=24; + break; + } else { /*JNO alias*/ + offset=(int8_t)FETCH(); + if (!(flags&V_FLAG)) { + cpu_state.pc+=offset; + cycles-=12; + FETCHCLEAR(); + } + cycles-=4; + } + break; + + case 0x62: + if (is_nec) { /*186+ BOUND*/ + int16_t low, high; + + low = geteaw(); + high = readmemw(easeg,cpu_state.eaaddr); + + if (((int16_t)cpu_state.regs[cpu_reg].w < low) || ((int16_t)cpu_state.regs[cpu_reg].w > high)) { + writememw(ss,(SP-2)&0xFFFF,flags|0xF000); + writememw(ss,(SP-4)&0xFFFF,CS); + writememw(ss,(SP-6)&0xFFFF,cpu_state.pc); + SP-=6; + flags&=~I_FLAG; + flags&=~T_FLAG; + cpu_state.pc=readmemw(0,0x14); + loadcs(readmemw(0,0x14+2)); + FETCHCLEAR(); + return; + } + cycles-=10; + break; + } else { /*JB alias*/ + offset=(int8_t)FETCH(); + if (flags&C_FLAG) { + cpu_state.pc+=offset; + cycles-=12; + FETCHCLEAR(); + } + cycles-=4; + } + break; + + case 0x70: /*JO*/ + offset=(int8_t)FETCH(); + if (flags&V_FLAG) { + cpu_state.pc+=offset; + cycles-=12; + FETCHCLEAR(); + } + cycles-=4; + break; + + case 0x71: /*JNO*/ + offset=(int8_t)FETCH(); + if (!(flags&V_FLAG)) { + cpu_state.pc+=offset; + cycles-=12; + FETCHCLEAR(); + } + cycles-=4; + break; + + case 0x72: /*JB*/ + offset=(int8_t)FETCH(); + if (flags&C_FLAG) { + cpu_state.pc+=offset; + cycles-=12; + FETCHCLEAR(); + } + cycles-=4; + break; + + case 0x63: /*JNB alias*/ + case 0x73: /*JNB*/ + offset=(int8_t)FETCH(); + if (!(flags&C_FLAG)) { + cpu_state.pc+=offset; + cycles-=12; + FETCHCLEAR(); + } + cycles-=4; + break; + + case 0x64: /*JE alias*/ + case 0x74: /*JE*/ + offset=(int8_t)FETCH(); + if (flags&Z_FLAG) { + cpu_state.pc+=offset; + cycles-=12; + FETCHCLEAR(); + } + cycles-=4; + break; + + case 0x65: /*JNE alias*/ + case 0x75: /*JNE*/ + offset=(int8_t)FETCH(); + cycles-=4; + if (!(flags&Z_FLAG)) { + cpu_state.pc+=offset; + cycles-=12; + FETCHCLEAR(); + } + break; + + case 0x66: /*JBE alias*/ + case 0x76: /*JBE*/ + offset=(int8_t)FETCH(); + if (flags&(C_FLAG|Z_FLAG)) { + cpu_state.pc+=offset; + cycles-=12; + FETCHCLEAR(); + } + cycles-=4; + break; + + case 0x67: /*JNBE alias*/ + case 0x77: /*JNBE*/ + offset=(int8_t)FETCH(); + if (!(flags&(C_FLAG|Z_FLAG))) { + cpu_state.pc+=offset; + cycles-=12; + FETCHCLEAR(); + } + cycles-=4; + break; + + case 0x68: + if (is_nec) { /*186+ PUSH imm*/ + tempw = getword(); + cpu_state.pc = tempw; + cycles-=2; + FETCHCLEAR(); + return; + } else { /*JS alias*/ + offset=(int8_t)FETCH(); + if (flags&N_FLAG) { + cpu_state.pc+=offset; + cycles-=12; + FETCHCLEAR(); + } + cycles-=4; + } + break; + + case 0x78: /*JS*/ + offset=(int8_t)FETCH(); + if (flags&N_FLAG) { + cpu_state.pc+=offset; + cycles-=12; + FETCHCLEAR(); + } + cycles-=4; + break; + + case 0x69: + if (is_nec) { /*186+ IMUL*/ + tempw = geteaw(); + tempw2 = getword(); + + templ = ((int)tempw) * ((int)tempw2); + if ((templ >> 15) != 0 && (templ >> 15) != -1) + flags |= C_FLAG | V_FLAG; + else + flags &= ~(C_FLAG | V_FLAG); + cpu_state.regs[cpu_reg].w = templ & 0xffff; + cycles-=((cpu_mod==3)?14:17); + FETCHCLEAR(); + } else { /*JNS alias*/ + offset=(int8_t)FETCH(); + if (!(flags&N_FLAG)) { + cpu_state.pc+=offset; + cycles-=12; + FETCHCLEAR(); + } + cycles-=4; + } + break; + + case 0x79: /*JNS*/ + offset=(int8_t)FETCH(); + if (!(flags&N_FLAG)) { + cpu_state.pc+=offset; + cycles-=12; + FETCHCLEAR(); + } + cycles-=4; + break; + + case 0x6A: + if (is_nec) { /*186+ PUSH imm8*/ + temp = (int8_t)FETCH(); + cpu_state.pc = temp; + cycles-=2; + FETCHCLEAR(); + return; + } else { /*JP alias*/ + offset=(int8_t)FETCH(); + if (flags&P_FLAG) { + cpu_state.pc+=offset; + cycles-=12; + FETCHCLEAR(); + } + cycles-=4; + } + break; + + case 0x7A: /*JP*/ + offset=(int8_t)FETCH(); + if (flags&P_FLAG) { + cpu_state.pc+=offset; + cycles-=12; + FETCHCLEAR(); + } + cycles-=4; + break; + + case 0x6B: + if (is_nec) { /*186+ IMUL byte*/ + tempw = geteaw(); + tempw2 = (int8_t)FETCH(); + if (tempw2 & 0x80) tempw2 |= 0xff00; + + templ = ((int)tempw) * ((int)tempw2); + if ((templ >> 15) != 0 && (templ >> 15) != -1) + flags |= C_FLAG | V_FLAG; + else + flags &= ~(C_FLAG | V_FLAG); + cpu_state.regs[cpu_reg].w = templ & 0xffff; + cycles-=((cpu_mod==3)?14:17); + FETCHCLEAR(); + } else { /*JNP alias*/ + offset=(int8_t)FETCH(); + if (!(flags&P_FLAG)) { + cpu_state.pc+=offset; + cycles-=12; + FETCHCLEAR(); + } + cycles-=4; + } + break; + + case 0x7B: /*JNP*/ + offset=(int8_t)FETCH(); + if (!(flags&P_FLAG)) { + cpu_state.pc+=offset; + cycles-=12; + FETCHCLEAR(); + } + cycles-=4; + break; + + case 0x6C: /*JL alias*/ + case 0x7C: /*JL*/ + offset=(int8_t)FETCH(); + temp=(flags&N_FLAG)?1:0; + temp2=(flags&V_FLAG)?1:0; + if (temp!=temp2) { + cpu_state.pc+=offset; + cycles-=12; + FETCHCLEAR(); + } + cycles-=4; + break; + + case 0x6D: /*JNL alias*/ + case 0x7D: /*JNL*/ + offset=(int8_t)FETCH(); + temp=(flags&N_FLAG)?1:0; + temp2=(flags&V_FLAG)?1:0; + if (temp==temp2) { + cpu_state.pc+=offset; + cycles-=12; + FETCHCLEAR(); + } + cycles-=4; + break; + + case 0x6E: /*JLE alias*/ + case 0x7E: /*JLE*/ + offset=(int8_t)FETCH(); + temp=(flags&N_FLAG)?1:0; + temp2=(flags&V_FLAG)?1:0; + if ((flags&Z_FLAG) || (temp!=temp2)) { + cpu_state.pc+=offset; + cycles-=12; + FETCHCLEAR(); + } + cycles-=4; + break; + + case 0x6F: /*JNLE alias*/ + case 0x7F: /*JNLE*/ + offset=(int8_t)FETCH(); + temp=(flags&N_FLAG)?1:0; + temp2=(flags&V_FLAG)?1:0; + if (!((flags&Z_FLAG) || (temp!=temp2))) { + cpu_state.pc+=offset; + cycles-=12; + FETCHCLEAR(); + } + cycles-=4; + break; + + case 0x80: case 0x82: + fetchea(); + temp=geteab(); + temp2=FETCH(); + switch (rmdat&0x38) { + case 0x00: /*ADD b,#8*/ + setadd8(temp,temp2); + seteab(temp+temp2); + cycles-=((cpu_mod==3)?4:23); + break; + + case 0x08: /*OR b,#8*/ + temp|=temp2; + setznp8(temp); + flags&=~(C_FLAG|V_FLAG|A_FLAG); + seteab(temp); + cycles-=((cpu_mod==3)?4:23); + break; + + case 0x10: /*ADC b,#8*/ + setadc8(temp,temp2); + seteab(temp+temp2+tempc); + cycles-=((cpu_mod==3)?4:23); + break; + + case 0x18: /*SBB b,#8*/ + setsbc8(temp,temp2); + seteab(temp-(temp2+tempc)); + cycles-=((cpu_mod==3)?4:23); + break; + + case 0x20: /*AND b,#8*/ + temp&=temp2; + setznp8(temp); + flags&=~(C_FLAG|V_FLAG|A_FLAG); + seteab(temp); + cycles-=((cpu_mod==3)?4:23); + break; + + case 0x28: /*SUB b,#8*/ + setsub8(temp,temp2); + seteab(temp-temp2); + cycles-=((cpu_mod==3)?4:23); + break; + + case 0x30: /*XOR b,#8*/ + temp^=temp2; + setznp8(temp); + flags&=~(C_FLAG|V_FLAG|A_FLAG); + seteab(temp); + cycles-=((cpu_mod==3)?4:23); + break; + + case 0x38: /*CMP b,#8*/ + setsub8(temp,temp2); + cycles-=((cpu_mod==3)?4:14); + break; + } + break; + + case 0x81: + fetchea(); + tempw=geteaw(); + tempw2=getword(); + switch (rmdat&0x38) { + case 0x00: /*ADD w,#16*/ + setadd16(tempw,tempw2); + tempw+=tempw2; + seteaw(tempw); + cycles-=((cpu_mod==3)?4:23); + break; + + case 0x08: /*OR w,#16*/ + tempw|=tempw2; + setznp16(tempw); + flags&=~(C_FLAG|V_FLAG|A_FLAG); + seteaw(tempw); + cycles-=((cpu_mod==3)?4:23); + break; + + case 0x10: /*ADC w,#16*/ + setadc16(tempw,tempw2); + tempw+=tempw2+tempc; + seteaw(tempw); + cycles-=((cpu_mod==3)?4:23); + break; + + case 0x20: /*AND w,#16*/ + tempw&=tempw2; + setznp16(tempw); + flags&=~(C_FLAG|V_FLAG|A_FLAG); + seteaw(tempw); + cycles-=((cpu_mod==3)?4:23); + break; + + case 0x18: /*SBB w,#16*/ + setsbc16(tempw,tempw2); + seteaw(tempw-(tempw2+tempc)); + cycles-=((cpu_mod==3)?4:23); + break; + + case 0x28: /*SUB w,#16*/ + setsub16(tempw,tempw2); + tempw-=tempw2; + seteaw(tempw); + cycles-=((cpu_mod==3)?4:23); + break; + + case 0x30: /*XOR w,#16*/ + tempw^=tempw2; + setznp16(tempw); + flags&=~(C_FLAG|V_FLAG|A_FLAG); + seteaw(tempw); + cycles-=((cpu_mod==3)?4:23); + break; + + case 0x38: /*CMP w,#16*/ + setsub16(tempw,tempw2); + cycles-=((cpu_mod==3)?4:14); + break; + } + break; + + case 0x83: + fetchea(); + tempw=geteaw(); + tempw2=FETCH(); + if (tempw2&0x80) tempw2|=0xFF00; + switch (rmdat&0x38) { + case 0x00: /*ADD w,#8*/ + setadd16(tempw,tempw2); + tempw+=tempw2; + seteaw(tempw); + cycles-=((cpu_mod==3)?4:23); + break; + + case 0x08: /*OR w,#8*/ + tempw|=tempw2; + setznp16(tempw); + seteaw(tempw); + flags&=~(C_FLAG|A_FLAG|V_FLAG); + cycles-=((cpu_mod==3)?4:23); + break; + + case 0x10: /*ADC w,#8*/ + setadc16(tempw,tempw2); + tempw+=tempw2+tempc; + seteaw(tempw); + cycles-=((cpu_mod==3)?4:23); + break; + + case 0x18: /*SBB w,#8*/ + setsbc16(tempw,tempw2); + tempw-=(tempw2+tempc); + seteaw(tempw); + cycles-=((cpu_mod==3)?4:23); + break; + + case 0x20: /*AND w,#8*/ + tempw&=tempw2; + setznp16(tempw); + seteaw(tempw); + cycles-=((cpu_mod==3)?4:23); + flags&=~(C_FLAG|A_FLAG|V_FLAG); + break; + + case 0x28: /*SUB w,#8*/ + setsub16(tempw,tempw2); + tempw-=tempw2; + seteaw(tempw); + cycles-=((cpu_mod==3)?4:23); + break; + + case 0x30: /*XOR w,#8*/ + tempw^=tempw2; + setznp16(tempw); + seteaw(tempw); + cycles-=((cpu_mod==3)?4:23); + flags&=~(C_FLAG|A_FLAG|V_FLAG); + break; + + case 0x38: /*CMP w,#8*/ + setsub16(tempw,tempw2); + cycles-=((cpu_mod==3)?4:14); + break; + } + break; + + case 0x84: /*TEST b,reg*/ + fetchea(); + temp=geteab(); + temp2=getr8(cpu_reg); + setznp8(temp&temp2); + flags&=~(C_FLAG|V_FLAG|A_FLAG); + cycles-=((cpu_mod==3)?3:13); + break; + + case 0x85: /*TEST w,reg*/ + fetchea(); + tempw=geteaw(); + tempw2=cpu_state.regs[cpu_reg].w; + setznp16(tempw&tempw2); + flags&=~(C_FLAG|V_FLAG|A_FLAG); + cycles-=((cpu_mod==3)?3:13); + break; + + case 0x86: /*XCHG b,reg*/ + fetchea(); + temp=geteab(); + seteab(getr8(cpu_reg)); + setr8(cpu_reg,temp); + cycles-=((cpu_mod==3)?4:25); + break; + + case 0x87: /*XCHG w,reg*/ + fetchea(); + tempw=geteaw(); + seteaw(cpu_state.regs[cpu_reg].w); + cpu_state.regs[cpu_reg].w=tempw; + cycles-=((cpu_mod==3)?4:25); + break; + + case 0x88: /*MOV b,reg*/ + fetchea(); + seteab(getr8(cpu_reg)); + cycles-=((cpu_mod==3)?2:13); + break; + + case 0x89: /*MOV w,reg*/ + fetchea(); + seteaw(cpu_state.regs[cpu_reg].w); + cycles-=((cpu_mod==3)?2:13); + break; + + case 0x8A: /*MOV cpu_reg,b*/ + fetchea(); + temp=geteab(); + setr8(cpu_reg,temp); + cycles-=((cpu_mod==3)?2:12); + break; + + case 0x8B: /*MOV cpu_reg,w*/ + fetchea(); + tempw=geteaw(); + cpu_state.regs[cpu_reg].w=tempw; + cycles-=((cpu_mod==3)?2:12); + break; + + case 0x8C: /*MOV w,sreg*/ + fetchea(); + switch (rmdat&0x38) { + case 0x00: /*ES*/ + seteaw(ES); + break; + + case 0x08: /*CS*/ + seteaw(CS); + break; + + case 0x18: /*DS*/ + if (cpu_state.ssegs) ds=oldds; + seteaw(DS); + break; + + case 0x10: /*SS*/ + if (cpu_state.ssegs) ss=oldss; + seteaw(SS); + break; + } + cycles-=((cpu_mod==3)?2:13); + break; + + case 0x8D: /*LEA*/ + fetchea(); + cpu_state.regs[cpu_reg].w=(cpu_mod == 3)?cpu_state.last_ea:cpu_state.eaaddr; + cycles-=2; + break; + + case 0x8E: /*MOV sreg,w*/ + fetchea(); + switch (rmdat&0x38) { + case 0x00: /*ES*/ + tempw=geteaw(); + loadseg(tempw,&_es); + break; + + case 0x08: /*CS - 8088/8086 only*/ + tempw=geteaw(); + loadseg(tempw,&_cs); + break; + + case 0x18: /*DS*/ + tempw=geteaw(); + loadseg(tempw,&_ds); + if (cpu_state.ssegs) oldds=ds; + break; + + case 0x10: /*SS*/ + tempw=geteaw(); + loadseg(tempw,&_ss); + if (cpu_state.ssegs) oldss=ss; + break; + } + cycles-=((cpu_mod==3)?2:12); + skipnextprint=1; + noint=1; + break; + + case 0x8F: /*POPW*/ + fetchea(); + if (cpu_state.ssegs) ss=oldss; + tempw=readmemw(ss,SP); + SP+=2; + cpu_state.last_ea = SP; + seteaw(tempw); + cycles-=25; + break; + + case 0x90: /*NOP*/ + cycles-=3; + break; + + case 0x91: case 0x92: case 0x93: /*XCHG AX*/ + case 0x94: case 0x95: case 0x96: case 0x97: + tempw=AX; + AX=cpu_state.regs[opcode&7].w; + cpu_state.regs[opcode&7].w=tempw; + cycles-=3; + break; + + case 0x98: /*CBW*/ + AH=(AL&0x80)?0xFF:0; + cycles-=2; + break; + + case 0x99: /*CWD*/ + DX=(AX&0x8000)?0xFFFF:0; + cycles-=5; + break; + + case 0x9A: /*CALL FAR*/ + tempw=getword(); + tempw2=getword(); + tempw3=CS; + tempw4=cpu_state.pc; + if (cpu_state.ssegs) ss=oldss; + cpu_state.pc=tempw; + loadcs(tempw2); + writememw(ss,(SP-2)&0xFFFF,tempw3); + writememw(ss,(SP-4)&0xFFFF,tempw4); + SP-=4; + cpu_state.last_ea = SP; + cycles-=36; + FETCHCLEAR(); + break; + + case 0x9B: /*WAIT*/ + cycles-=4; + break; + + case 0x9C: /*PUSHF*/ + if (cpu_state.ssegs) ss=oldss; + writememw(ss,((SP-2)&0xFFFF),flags|0xF000); + SP-=2; + cpu_state.last_ea = SP; + cycles-=14; + break; + + case 0x9D: /*POPF*/ + if (cpu_state.ssegs) ss=oldss; + flags=readmemw(ss,SP)&0xFFF; + SP+=2; + cpu_state.last_ea = SP; + cycles-=12; + break; + + case 0x9E: /*SAHF*/ + flags=(flags&0xFF00)|AH; + cycles-=4; + break; + + case 0x9F: /*LAHF*/ + AH=flags&0xFF; + cycles-=4; + break; + + case 0xA0: /*MOV AL,(w)*/ + addr=getword(); + AL=readmemb(ds+addr); + cycles-=14; + break; + + case 0xA1: /*MOV AX,(w)*/ + addr=getword(); + AX=readmemw(ds,addr); + cycles-=14; + break; + + case 0xA2: /*MOV (w),AL*/ + addr=getword(); + writememb(ds+addr,AL); + cycles-=14; + break; + + case 0xA3: /*MOV (w),AX*/ + addr=getword(); + writememw(ds,addr,AX); + cycles-=14; + break; + + case 0xA4: /*MOVSB*/ + temp=readmemb(ds+SI); + writememb(es+DI,temp); + if (flags&D_FLAG) { DI--; SI--; } + else { DI++; SI++; } + cycles-=18; + break; + + case 0xA5: /*MOVSW*/ + tempw=readmemw(ds,SI); + writememw(es,DI,tempw); + if (flags&D_FLAG) { DI-=2; SI-=2; } + else { DI+=2; SI+=2; } + cycles-=18; + break; + + case 0xA6: /*CMPSB*/ + temp =readmemb(ds+SI); + temp2=readmemb(es+DI); + setsub8(temp,temp2); + if (flags&D_FLAG) { DI--; SI--; } + else { DI++; SI++; } + cycles-=30; + break; + + case 0xA7: /*CMPSW*/ + tempw =readmemw(ds,SI); + tempw2=readmemw(es,DI); + setsub16(tempw,tempw2); + if (flags&D_FLAG) { DI-=2; SI-=2; } + else { DI+=2; SI+=2; } + cycles-=30; + break; + + case 0xA8: /*TEST AL,#8*/ + temp=FETCH(); + setznp8(AL&temp); + flags&=~(C_FLAG|V_FLAG|A_FLAG); + cycles-=5; + break; + + case 0xA9: /*TEST AX,#16*/ + tempw=getword(); + setznp16(AX&tempw); + flags&=~(C_FLAG|V_FLAG|A_FLAG); + cycles-=5; + break; + + case 0xAA: /*STOSB*/ + writememb(es+DI,AL); + if (flags&D_FLAG) DI--; + else DI++; + cycles-=11; + break; + + case 0xAB: /*STOSW*/ + writememw(es,DI,AX); + if (flags&D_FLAG) DI-=2; + else DI+=2; + cycles-=11; + break; + + case 0xAC: /*LODSB*/ + AL=readmemb(ds+SI); + if (flags&D_FLAG) SI--; + else SI++; + cycles-=16; + break; + + case 0xAD: /*LODSW*/ + AX=readmemw(ds,SI); + if (flags&D_FLAG) SI-=2; + else SI+=2; + cycles-=16; + break; + + case 0xAE: /*SCASB*/ + temp=readmemb(es+DI); + setsub8(AL,temp); + if (flags&D_FLAG) DI--; + else DI++; + cycles-=19; + break; + + case 0xAF: /*SCASW*/ + tempw=readmemw(es,DI); + setsub16(AX,tempw); + if (flags&D_FLAG) DI-=2; + else DI+=2; + cycles-=19; + break; + + case 0xB0: /*MOV AL,#8*/ + AL=FETCH(); + cycles-=4; + break; + + case 0xB1: /*MOV CL,#8*/ + CL=FETCH(); + cycles-=4; + break; + + case 0xB2: /*MOV DL,#8*/ + DL=FETCH(); + cycles-=4; + break; + + case 0xB3: /*MOV BL,#8*/ + BL=FETCH(); + cycles-=4; + break; + + case 0xB4: /*MOV AH,#8*/ + AH=FETCH(); + cycles-=4; + break; + + case 0xB5: /*MOV CH,#8*/ + CH=FETCH(); + cycles-=4; + break; + + case 0xB6: /*MOV DH,#8*/ + DH=FETCH(); + cycles-=4; + break; + + case 0xB7: /*MOV BH,#8*/ + BH=FETCH(); + cycles-=4; + break; + + case 0xB8: case 0xB9: case 0xBA: case 0xBB: /*MOV cpu_reg,#16*/ + case 0xBC: case 0xBD: case 0xBE: case 0xBF: + cpu_state.regs[opcode&7].w=getword(); + cycles-=4; + break; + + case 0xC0: /*RET alias*/ + case 0xC2: /*RET*/ + tempw=getword(); + if (cpu_state.ssegs) ss=oldss; + cpu_state.pc=readmemw(ss,SP); + SP+=2+tempw; + cycles-=24; + FETCHCLEAR(); + break; + + case 0xC1: /*RET alias*/ + case 0xC3: /*RET*/ + if (cpu_state.ssegs) ss=oldss; + cpu_state.pc=readmemw(ss,SP); + SP+=2; + cycles-=20; + FETCHCLEAR(); + break; + + case 0xC4: /*LES*/ + fetchea(); + cpu_state.regs[cpu_reg].w=readmemw(easeg,cpu_state.eaaddr); + tempw=readmemw(easeg,(cpu_state.eaaddr+2)&0xFFFF); + loadseg(tempw,&_es); + cycles-=24; + break; + + case 0xC5: /*LDS*/ + fetchea(); + cpu_state.regs[cpu_reg].w=readmemw(easeg,cpu_state.eaaddr); + tempw=readmemw(easeg,(cpu_state.eaaddr+2)&0xFFFF); + loadseg(tempw,&_ds); + if (cpu_state.ssegs) oldds=ds; + cycles-=24; + break; + + case 0xC6: /*MOV b,#8*/ + fetchea(); + temp=FETCH(); + seteab(temp); + cycles-=((cpu_mod==3)?4:14); + break; + + case 0xC7: /*MOV w,#16*/ + fetchea(); + tempw=getword(); + seteaw(tempw); + cycles-=((cpu_mod==3)?4:14); + break; + + case 0xC8: /*186+ ENTER*/ + if (is_nec) { + uint16_t offsetw; + int count; + + offsetw = getword(); + + tempw=readmemw(ss,SP); + tempw2=readmemw(ss,(SP-2)&0xFFFF); + tempw3=CS; + tempw4=cpu_state.pc; + + if (cpu_state.ssegs) ss=oldss; + + count=geteaw(); + + if (count > 0) { + while (--count) { + cpu_state.pc=tempw; + loadcs(tempw2); + cycles-=4; + } + writememw(ss,(SP-2)&0xFFFF,tempw3); + writememw(ss,((SP-4)&0xFFFF),tempw4); + cycles-=5; + } + cpu_state.last_ea = SP; + SP-=offsetw; + cycles-=10; + FETCHCLEAR(); + } else { /*RETF alias*/ + tempw=getword(); + if (cpu_state.ssegs) ss=oldss; + cpu_state.pc=readmemw(ss,SP); + loadcs(readmemw(ss,SP+2)); + SP+=4; + SP+=tempw; + cycles-=33; + FETCHCLEAR(); + } + break; + + case 0xC9: + if (is_nec) { /*186+ LEAVE*/ + if (cpu_state.ssegs) ss=oldss; + cpu_state.regs[opcode&7].w=readmemw(ss,(SP-2)&0xFFFF); + cpu_state.last_ea = SP; + cycles-=4; + } else { /*RETF alias*/ + if (cpu_state.ssegs) ss=oldss; + cpu_state.pc=readmemw(ss,SP); + loadcs(readmemw(ss,SP+2)); + SP+=4; + cycles-=34; + FETCHCLEAR(); + } + break; + + case 0xCA: /*RETF*/ + tempw=getword(); + if (cpu_state.ssegs) ss=oldss; + cpu_state.pc=readmemw(ss,SP); + loadcs(readmemw(ss,SP+2)); + SP+=4; + SP+=tempw; + cycles-=33; + FETCHCLEAR(); + break; + + case 0xCB: /*RETF*/ + if (cpu_state.ssegs) ss=oldss; + cpu_state.pc=readmemw(ss,SP); + loadcs(readmemw(ss,SP+2)); + SP+=4; + cycles-=34; + FETCHCLEAR(); + break; + + case 0xCC: /*INT 3*/ + if (cpu_state.ssegs) ss=oldss; + writememw(ss,((SP-2)&0xFFFF),flags|0xF000); + writememw(ss,((SP-4)&0xFFFF),CS); + writememw(ss,((SP-6)&0xFFFF),cpu_state.pc); + SP-=6; + addr=3<<2; + flags&=~I_FLAG; + flags&=~T_FLAG; + cpu_state.pc=readmemw(0,addr); + loadcs(readmemw(0,addr+2)); + FETCHCLEAR(); + cycles-=72; + break; + + case 0xCD: /*INT*/ + lastpc=cpu_state.pc; + lastcs=CS; + temp=FETCH(); + if (cpu_state.ssegs) ss=oldss; + writememw(ss,((SP-2)&0xFFFF),flags|0xF000); + writememw(ss,((SP-4)&0xFFFF),CS); + writememw(ss,((SP-6)&0xFFFF),cpu_state.pc); + flags&=~T_FLAG; + SP-=6; + addr=temp<<2; + cpu_state.pc=readmemw(0,addr); + loadcs(readmemw(0,addr+2)); + FETCHCLEAR(); + cycles-=71; + break; + + case 0xCF: /*IRET*/ + if (cpu_state.ssegs) ss=oldss; + tempw=CS; + tempw2=cpu_state.pc; + cpu_state.pc=readmemw(ss,SP); + loadcs(readmemw(ss,((SP+2)&0xFFFF))); + flags=readmemw(ss,((SP+4)&0xFFFF))&0xFFF; + SP+=6; + cycles-=44; + FETCHCLEAR(); + nmi_enable = 1; + break; + + case 0xD0: + fetchea(); + temp=geteab(); + switch (rmdat&0x38) { + case 0x00: /*ROL b,1*/ + if (temp&0x80) + flags|=C_FLAG; + else + flags&=~C_FLAG; + temp<<=1; + if (flags&C_FLAG) temp|=1; + seteab(temp); + if ((flags&C_FLAG)^(temp>>7)) + flags|=V_FLAG; + else + flags&=~V_FLAG; + cycles-=((cpu_mod==3)?2:23); + break; + + case 0x08: /*ROR b,1*/ + if (temp&1) + flags|=C_FLAG; + else + flags&=~C_FLAG; + temp>>=1; + if (flags&C_FLAG) temp|=0x80; + seteab(temp); + if ((temp^(temp>>1))&0x40) + flags|=V_FLAG; + else + flags&=~V_FLAG; + cycles-=((cpu_mod==3)?2:23); + break; + + case 0x10: /*RCL b,1*/ + temp2=flags&C_FLAG; + if (temp&0x80) + flags|=C_FLAG; + else + flags&=~C_FLAG; + temp<<=1; + if (temp2) temp|=1; + seteab(temp); + if ((flags&C_FLAG)^(temp>>7)) + flags|=V_FLAG; + else + flags&=~V_FLAG; + cycles-=((cpu_mod==3)?2:23); + break; + + case 0x18: /*RCR b,1*/ + temp2=flags&C_FLAG; + if (temp&1) + flags|=C_FLAG; + else + flags&=~C_FLAG; + temp>>=1; + if (temp2) temp|=0x80; + seteab(temp); + if ((temp^(temp>>1))&0x40) + flags|=V_FLAG; + else + flags&=~V_FLAG; + cycles-=((cpu_mod==3)?2:23); + break; + + case 0x20: case 0x30: /*SHL b,1*/ + if (temp&0x80) + flags|=C_FLAG; + else + flags&=~C_FLAG; + if ((temp^(temp<<1))&0x80) + flags|=V_FLAG; + else + flags&=~V_FLAG; + temp<<=1; + seteab(temp); + setznp8(temp); + cycles-=((cpu_mod==3)?2:23); + flags|=A_FLAG; + break; + + case 0x28: /*SHR b,1*/ + if (temp&1) + flags|=C_FLAG; + else + flags&=~C_FLAG; + if (temp&0x80) + flags|=V_FLAG; + else + flags&=~V_FLAG; + temp>>=1; + seteab(temp); + setznp8(temp); + cycles-=((cpu_mod==3)?2:23); + flags|=A_FLAG; + break; + + case 0x38: /*SAR b,1*/ + if (temp&1) + flags|=C_FLAG; + else + flags&=~C_FLAG; + temp>>=1; + if (temp&0x40) temp|=0x80; + seteab(temp); + setznp8(temp); + cycles-=((cpu_mod==3)?2:23); + flags|=A_FLAG; + flags&=~V_FLAG; + break; + } + break; + + case 0xD1: + fetchea(); + tempw=geteaw(); + switch (rmdat&0x38) { + case 0x00: /*ROL w,1*/ + if (tempw&0x8000) flags|=C_FLAG; + else flags&=~C_FLAG; + tempw<<=1; + if (flags&C_FLAG) tempw|=1; + seteaw(tempw); + if ((flags&C_FLAG)^(tempw>>15)) flags|=V_FLAG; + else flags&=~V_FLAG; + cycles-=((cpu_mod==3)?2:23); + break; + + case 0x08: /*ROR w,1*/ + if (tempw&1) flags|=C_FLAG; + else flags&=~C_FLAG; + tempw>>=1; + if (flags&C_FLAG) tempw|=0x8000; + seteaw(tempw); + if ((tempw^(tempw>>1))&0x4000) flags|=V_FLAG; + else flags&=~V_FLAG; + cycles-=((cpu_mod==3)?2:23); + break; + + case 0x10: /*RCL w,1*/ + temp2=flags&C_FLAG; + if (tempw&0x8000) flags|=C_FLAG; + else flags&=~C_FLAG; + tempw<<=1; + if (temp2) tempw|=1; + seteaw(tempw); + if ((flags&C_FLAG)^(tempw>>15)) flags|=V_FLAG; + else flags&=~V_FLAG; + cycles-=((cpu_mod==3)?2:23); + break; + + case 0x18: /*RCR w,1*/ + temp2=flags&C_FLAG; + if (tempw&1) flags|=C_FLAG; + else flags&=~C_FLAG; + tempw>>=1; + if (temp2) tempw|=0x8000; + seteaw(tempw); + if ((tempw^(tempw>>1))&0x4000) flags|=V_FLAG; + else flags&=~V_FLAG; + cycles-=((cpu_mod==3)?2:23); + break; + + case 0x20: case 0x30: /*SHL w,1*/ + if (tempw&0x8000) flags|=C_FLAG; + else flags&=~C_FLAG; + if ((tempw^(tempw<<1))&0x8000) flags|=V_FLAG; + else flags&=~V_FLAG; + tempw<<=1; + seteaw(tempw); + setznp16(tempw); + cycles-=((cpu_mod==3)?2:23); + flags|=A_FLAG; + break; + + case 0x28: /*SHR w,1*/ + if (tempw&1) flags|=C_FLAG; + else flags&=~C_FLAG; + if (tempw&0x8000) flags|=V_FLAG; + else flags&=~V_FLAG; + tempw>>=1; + seteaw(tempw); + setznp16(tempw); + cycles-=((cpu_mod==3)?2:23); + flags|=A_FLAG; + break; + + case 0x38: /*SAR w,1*/ + if (tempw&1) flags|=C_FLAG; + else flags&=~C_FLAG; + tempw>>=1; + if (tempw&0x4000) tempw|=0x8000; + seteaw(tempw); + setznp16(tempw); + cycles-=((cpu_mod==3)?2:23); + flags|=A_FLAG; + flags&=~V_FLAG; + break; + } + break; + + case 0xD2: + fetchea(); + temp=geteab(); + c=CL; + if (!c) break; + switch (rmdat&0x38) { + case 0x00: /*ROL b,CL*/ + temp2=(temp&0x80)?1:0; + if (!c) { + cycles-=((cpu_mod==3)?8:28); + break; + } + while (c>0) { + temp2=(temp&0x80)?1:0; + temp=(temp<<1)|temp2; + c--; + cycles-=4; + } + if (temp2) flags|=C_FLAG; + else flags&=~C_FLAG; + seteab(temp); + if ((flags&C_FLAG)^(temp>>7)) flags|=V_FLAG; + else flags&=~V_FLAG; cycles-=((cpu_mod==3)?8:28); break; - } - while (c>0) - { - temp2=temp&1; - temp>>=1; - if (temp2) temp|=0x80; - c--; - cycles-=4; - } - if (temp2) flags|=C_FLAG; - else flags&=~C_FLAG; - seteab(temp); - if ((temp^(temp>>1))&0x40) flags|=V_FLAG; - else flags&=~V_FLAG; - cycles-=((cpu_mod==3)?8:28); - break; - case 0x10: /*RCL b,CL*/ - while (c>0) - { - templ=flags&C_FLAG; - temp2=temp&0x80; - temp<<=1; - if (temp2) flags|=C_FLAG; - else flags&=~C_FLAG; - if (templ) temp|=1; - c--; - cycles-=4; - } - seteab(temp); - if ((flags&C_FLAG)^(temp>>7)) flags|=V_FLAG; - else flags&=~V_FLAG; - cycles-=((cpu_mod==3)?8:28); - break; - case 0x18: /*RCR b,CL*/ - while (c>0) - { - templ=flags&C_FLAG; - temp2=temp&1; - temp>>=1; - if (temp2) flags|=C_FLAG; - else flags&=~C_FLAG; - if (templ) temp|=0x80; - c--; - cycles-=4; - } - seteab(temp); - if ((temp^(temp>>1))&0x40) flags|=V_FLAG; - else flags&=~V_FLAG; - cycles-=((cpu_mod==3)?8:28); - break; - case 0x20: case 0x30: /*SHL b,CL*/ - if (c > 8) - { - temp = 0; - flags &= ~C_FLAG; - } - else - { - if ((temp<<(c-1))&0x80) flags|=C_FLAG; - else flags&=~C_FLAG; - temp<<=c; - } - seteab(temp); - setznp8(temp); - cycles-=(c*4); - cycles-=((cpu_mod==3)?8:28); - flags|=A_FLAG; - break; - case 0x28: /*SHR b,CL*/ - if (c > 8) - { - temp = 0; - flags &= ~C_FLAG; - } - else - { - if ((temp>>(c-1))&1) flags|=C_FLAG; - else flags&=~C_FLAG; - temp>>=c; - } - seteab(temp); - setznp8(temp); - cycles-=(c*4); - cycles-=((cpu_mod==3)?8:28); - flags|=A_FLAG; - break; - case 0x38: /*SAR b,CL*/ - if ((temp>>(c-1))&1) flags|=C_FLAG; - else flags&=~C_FLAG; - while (c>0) - { - temp>>=1; - if (temp&0x40) temp|=0x80; - c--; - cycles-=4; - } - seteab(temp); - setznp8(temp); - cycles-=((cpu_mod==3)?8:28); - flags|=A_FLAG; - break; - } - break; - case 0xD3: - fetchea(); - tempw=geteaw(); - c=CL; - if (!c) break; - switch (rmdat&0x38) - { - case 0x00: /*ROL w,CL*/ - while (c>0) - { - temp=(tempw&0x8000)?1:0; - tempw=(tempw<<1)|temp; - c--; - cycles-=4; - } - if (temp) flags|=C_FLAG; - else flags&=~C_FLAG; - seteaw(tempw); - if ((flags&C_FLAG)^(tempw>>15)) flags|=V_FLAG; - else flags&=~V_FLAG; - cycles-=((cpu_mod==3)?8:28); - break; - case 0x08: /*ROR w,CL*/ - tempw2=(tempw&1)?0x8000:0; - if (!c) - { - cycles-=((cpu_mod==3)?8:28); - break; - } - while (c>0) - { - tempw2=(tempw&1)?0x8000:0; - tempw=(tempw>>1)|tempw2; - c--; - cycles-=4; - } - if (tempw2) flags|=C_FLAG; - else flags&=~C_FLAG; - seteaw(tempw); - if ((tempw^(tempw>>1))&0x4000) flags|=V_FLAG; - else flags&=~V_FLAG; - cycles-=((cpu_mod==3)?8:28); - break; - case 0x10: /*RCL w,CL*/ - while (c>0) - { - templ=flags&C_FLAG; - if (tempw&0x8000) flags|=C_FLAG; - else flags&=~C_FLAG; - tempw=(tempw<<1)|templ; - c--; - cycles-=4; - } - if (temp) flags|=C_FLAG; - else flags&=~C_FLAG; - seteaw(tempw); - if ((flags&C_FLAG)^(tempw>>15)) flags|=V_FLAG; - else flags&=~V_FLAG; - cycles-=((cpu_mod==3)?8:28); - break; - case 0x18: /*RCR w,CL*/ - templ=flags&C_FLAG; - tempw2=(templ&1)?0x8000:0; - if (!c) - { - cycles-=((cpu_mod==3)?8:28); + case 0x08: /*ROR b,CL*/ + temp2=temp&1; + if (!c) { + cycles-=((cpu_mod==3)?8:28); + break; + } + while (c>0) { + temp2=temp&1; + temp>>=1; + if (temp2) temp|=0x80; + c--; + cycles-=4; + } + if (temp2) flags|=C_FLAG; + else flags&=~C_FLAG; + seteab(temp); + if ((temp^(temp>>1))&0x40) flags|=V_FLAG; + else flags&=~V_FLAG; + cycles-=((cpu_mod==3)?8:28); break; - } - while (c>0) - { - templ=flags&C_FLAG; - tempw2=(templ&1)?0x8000:0; - if (tempw&1) flags|=C_FLAG; - else flags&=~C_FLAG; - tempw=(tempw>>1)|tempw2; - c--; - cycles-=4; - } - if (tempw2) flags|=C_FLAG; - else flags&=~C_FLAG; - seteaw(tempw); - if ((tempw^(tempw>>1))&0x4000) flags|=V_FLAG; - else flags&=~V_FLAG; - cycles-=((cpu_mod==3)?8:28); - break; - case 0x20: case 0x30: /*SHL w,CL*/ - if (c>16) - { - tempw=0; - flags&=~C_FLAG; - } - else - { - if ((tempw<<(c-1))&0x8000) flags|=C_FLAG; - else flags&=~C_FLAG; - tempw<<=c; - } - seteaw(tempw); - setznp16(tempw); - cycles-=(c*4); - cycles-=((cpu_mod==3)?8:28); - flags|=A_FLAG; - break; + case 0x10: /*RCL b,CL*/ + while (c>0) { + templ=flags&C_FLAG; + temp2=temp&0x80; + temp<<=1; + if (temp2) flags|=C_FLAG; + else flags&=~C_FLAG; + if (templ) temp|=1; + c--; + cycles-=4; + } + seteab(temp); + if ((flags&C_FLAG)^(temp>>7)) flags|=V_FLAG; + else flags&=~V_FLAG; + cycles-=((cpu_mod==3)?8:28); + break; - case 0x28: /*SHR w,CL*/ - if (c > 16) - { - tempw = 0; - flags &= ~C_FLAG; - } - else - { - if ((tempw>>(c-1))&1) flags|=C_FLAG; - else flags&=~C_FLAG; - tempw>>=c; - } - seteaw(tempw); - setznp16(tempw); - cycles-=(c*4); - cycles-=((cpu_mod==3)?8:28); - flags|=A_FLAG; - break; + case 0x18: /*RCR b,CL*/ + while (c>0) { + templ=flags&C_FLAG; + temp2=temp&1; + temp>>=1; + if (temp2) flags|=C_FLAG; + else flags&=~C_FLAG; + if (templ) temp|=0x80; + c--; + cycles-=4; + } + seteab(temp); + if ((temp^(temp>>1))&0x40) flags|=V_FLAG; + else flags&=~V_FLAG; + cycles-=((cpu_mod==3)?8:28); + break; - case 0x38: /*SAR w,CL*/ - tempw2=tempw&0x8000; - if ((tempw>>(c-1))&1) flags|=C_FLAG; - else flags&=~C_FLAG; - while (c>0) - { - tempw=(tempw>>1)|tempw2; - c--; - cycles-=4; - } - seteaw(tempw); - setznp16(tempw); - cycles-=((cpu_mod==3)?8:28); - flags|=A_FLAG; - break; - } - break; + case 0x20: case 0x30: /*SHL b,CL*/ + if (c > 8) { + temp = 0; + flags &= ~C_FLAG; + } else { + if ((temp<<(c-1))&0x80) flags|=C_FLAG; + else flags&=~C_FLAG; + temp<<=c; + } + seteab(temp); + setznp8(temp); + cycles-=(c*4); + cycles-=((cpu_mod==3)?8:28); + flags|=A_FLAG; + break; - case 0xD4: /*AAM*/ - tempws=FETCH(); - AH=AL/tempws; - AL%=tempws; - setznp16(AX); - cycles-=83; - break; - case 0xD5: /*AAD*/ - tempws=FETCH(); - AL=(AH*tempws)+AL; - AH=0; - setznp16(AX); - cycles-=60; - break; - case 0xD6: /*SETALC*/ - AL = (flags & C_FLAG) ? 0xff : 0; - cycles -= 4; - break; - case 0xD7: /*XLAT*/ - addr=BX+AL; + case 0x28: /*SHR b,CL*/ + if (c > 8) { + temp = 0; + flags &= ~C_FLAG; + } else { + if ((temp>>(c-1))&1) flags|=C_FLAG; + else flags&=~C_FLAG; + temp>>=c; + } + seteab(temp); + setznp8(temp); + cycles-=(c*4); + cycles-=((cpu_mod==3)?8:28); + flags|=A_FLAG; + break; + + case 0x38: /*SAR b,CL*/ + if ((temp>>(c-1))&1) flags|=C_FLAG; + else flags&=~C_FLAG; + while (c>0) { + temp>>=1; + if (temp&0x40) temp|=0x80; + c--; + cycles-=4; + } + seteab(temp); + setznp8(temp); + cycles-=((cpu_mod==3)?8:28); + flags|=A_FLAG; + break; + } + break; + + case 0xD3: + fetchea(); + tempw=geteaw(); + c=CL; + if (!c) break; + switch (rmdat&0x38) { + case 0x00: /*ROL w,CL*/ + while (c>0) { + temp=(tempw&0x8000)?1:0; + tempw=(tempw<<1)|temp; + c--; + cycles-=4; + } + if (temp) flags|=C_FLAG; + else flags&=~C_FLAG; + seteaw(tempw); + if ((flags&C_FLAG)^(tempw>>15)) flags|=V_FLAG; + else flags&=~V_FLAG; + cycles-=((cpu_mod==3)?8:28); + break; + + case 0x08: /*ROR w,CL*/ + tempw2=(tempw&1)?0x8000:0; + if (!c) { + cycles-=((cpu_mod==3)?8:28); + break; + } + while (c>0) { + tempw2=(tempw&1)?0x8000:0; + tempw=(tempw>>1)|tempw2; + c--; + cycles-=4; + } + if (tempw2) flags|=C_FLAG; + else flags&=~C_FLAG; + seteaw(tempw); + if ((tempw^(tempw>>1))&0x4000) flags|=V_FLAG; + else flags&=~V_FLAG; + cycles-=((cpu_mod==3)?8:28); + break; + + case 0x10: /*RCL w,CL*/ + while (c>0) { + templ=flags&C_FLAG; + if (tempw&0x8000) flags|=C_FLAG; + else flags&=~C_FLAG; + tempw=(tempw<<1)|templ; + c--; + cycles-=4; + } + if (temp) flags|=C_FLAG; + else flags&=~C_FLAG; + seteaw(tempw); + if ((flags&C_FLAG)^(tempw>>15)) flags|=V_FLAG; + else flags&=~V_FLAG; + cycles-=((cpu_mod==3)?8:28); + break; + + case 0x18: /*RCR w,CL*/ + templ=flags&C_FLAG; + tempw2=(templ&1)?0x8000:0; + if (!c) { + cycles-=((cpu_mod==3)?8:28); + break; + } + while (c>0) { + templ=flags&C_FLAG; + tempw2=(templ&1)?0x8000:0; + if (tempw&1) flags|=C_FLAG; + else flags&=~C_FLAG; + tempw=(tempw>>1)|tempw2; + c--; + cycles-=4; + } + if (tempw2) flags|=C_FLAG; + else flags&=~C_FLAG; + seteaw(tempw); + if ((tempw^(tempw>>1))&0x4000) flags|=V_FLAG; + else flags&=~V_FLAG; + cycles-=((cpu_mod==3)?8:28); + break; + + case 0x20: case 0x30: /*SHL w,CL*/ + if (c>16) { + tempw=0; + flags&=~C_FLAG; + } else { + if ((tempw<<(c-1))&0x8000) flags|=C_FLAG; + else flags&=~C_FLAG; + tempw<<=c; + } + seteaw(tempw); + setznp16(tempw); + cycles-=(c*4); + cycles-=((cpu_mod==3)?8:28); + flags|=A_FLAG; + break; + + case 0x28: /*SHR w,CL*/ + if (c > 16) { + tempw = 0; + flags &= ~C_FLAG; + } else { + if ((tempw>>(c-1))&1) flags|=C_FLAG; + else flags&=~C_FLAG; + tempw>>=c; + } + seteaw(tempw); + setznp16(tempw); + cycles-=(c*4); + cycles-=((cpu_mod==3)?8:28); + flags|=A_FLAG; + break; + + case 0x38: /*SAR w,CL*/ + tempw2=tempw&0x8000; + if ((tempw>>(c-1))&1) flags|=C_FLAG; + else flags&=~C_FLAG; + while (c>0) { + tempw=(tempw>>1)|tempw2; + c--; + cycles-=4; + } + seteaw(tempw); + setznp16(tempw); + cycles-=((cpu_mod==3)?8:28); + flags|=A_FLAG; + break; + } + break; + + case 0xD4: /*AAM*/ + tempws=FETCH(); + AH=AL/tempws; + AL%=tempws; + setznp16(AX); + cycles-=83; + break; + + case 0xD5: /*AAD*/ + tempws=FETCH(); + AL=(AH*tempws)+AL; + AH=0; + setznp16(AX); + cycles-=60; + break; + + case 0xD6: /*SETALC*/ + AL = (flags & C_FLAG) ? 0xff : 0; + cycles -= 4; + break; + + case 0xD7: /*XLAT*/ + addr=BX+AL; cpu_state.last_ea = addr; - AL=readmemb(ds+addr); - cycles-=11; - break; - case 0xD9: case 0xDA: case 0xDB: case 0xDD: /*ESCAPE*/ - case 0xDC: case 0xDE: case 0xDF: case 0xD8: - fetchea(); - geteab(); - break; + AL=readmemb(ds+addr); + cycles-=11; + break; - case 0xE0: /*LOOPNE*/ - offset=(int8_t)FETCH(); - CX--; - if (CX && !(flags&Z_FLAG)) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); } - cycles-=6; - break; - case 0xE1: /*LOOPE*/ - offset=(int8_t)FETCH(); - CX--; - if (CX && (flags&Z_FLAG)) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); } - cycles-=6; - break; - case 0xE2: /*LOOP*/ - offset=(int8_t)FETCH(); - CX--; - if (CX) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); } - cycles-=5; - break; - case 0xE3: /*JCXZ*/ - offset=(int8_t)FETCH(); - if (!CX) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); } - cycles-=6; - break; + case 0xD9: case 0xDA: case 0xDB: case 0xDD: /*ESCAPE*/ + case 0xDC: case 0xDE: case 0xDF: case 0xD8: + fetchea(); + geteab(); + break; - case 0xE4: /*IN AL*/ - temp=FETCH(); - AL=inb(temp); - cycles-=14; - break; - case 0xE5: /*IN AX*/ - temp=FETCH(); - AL=inb(temp); - AH=inb(temp+1); - cycles-=14; - break; - case 0xE6: /*OUT AL*/ - temp=FETCH(); - outb(temp,AL); - cycles-=14; - break; - case 0xE7: /*OUT AX*/ - temp=FETCH(); - outb(temp,AL); - outb(temp+1,AH); - cycles-=14; - break; + case 0xE0: /*LOOPNE*/ + offset=(int8_t)FETCH(); + CX--; + if (CX && !(flags&Z_FLAG)) { + cpu_state.pc+=offset; + cycles-=12; + FETCHCLEAR(); + } + cycles-=6; + break; - case 0xE8: /*CALL rel 16*/ - tempw=getword(); - if (cpu_state.ssegs) ss=oldss; - writememw(ss,((SP-2)&0xFFFF),cpu_state.pc); - SP-=2; + case 0xE1: /*LOOPE*/ + offset=(int8_t)FETCH(); + CX--; + if (CX && (flags&Z_FLAG)) { + cpu_state.pc+=offset; + cycles-=12; + FETCHCLEAR(); + } + cycles-=6; + break; + + case 0xE2: /*LOOP*/ + offset=(int8_t)FETCH(); + CX--; + if (CX) { + cpu_state.pc+=offset; + cycles-=12; + FETCHCLEAR(); + } + cycles-=5; + break; + + case 0xE3: /*JCXZ*/ + offset=(int8_t)FETCH(); + if (!CX) { + cpu_state.pc+=offset; + cycles-=12; + FETCHCLEAR(); + } + cycles-=6; + break; + + case 0xE4: /*IN AL*/ + temp=FETCH(); + AL=inb(temp); + cycles-=14; + break; + + case 0xE5: /*IN AX*/ + temp=FETCH(); + AL=inb(temp); + AH=inb(temp+1); + cycles-=14; + break; + + case 0xE6: /*OUT AL*/ + temp=FETCH(); + outb(temp,AL); + cycles-=14; + break; + + case 0xE7: /*OUT AX*/ + temp=FETCH(); + outb(temp,AL); + outb(temp+1,AH); + cycles-=14; + break; + + case 0xE8: /*CALL rel 16*/ + tempw=getword(); + if (cpu_state.ssegs) ss=oldss; + writememw(ss,((SP-2)&0xFFFF),cpu_state.pc); + SP-=2; cpu_state.last_ea = SP; - cpu_state.pc+=tempw; - cycles-=23; - FETCHCLEAR(); - break; - case 0xE9: /*JMP rel 16*/ - tempw = getword(); - cpu_state.pc += tempw; - cycles-=15; - FETCHCLEAR(); - break; - case 0xEA: /*JMP far*/ - addr=getword(); - tempw=getword(); - cpu_state.pc=addr; - loadcs(tempw); - cycles-=15; - FETCHCLEAR(); - break; - case 0xEB: /*JMP rel*/ - offset=(int8_t)FETCH(); - cpu_state.pc+=offset; - cycles-=15; - FETCHCLEAR(); - break; - case 0xEC: /*IN AL,DX*/ - AL=inb(DX); - cycles-=12; - break; - case 0xED: /*IN AX,DX*/ - AL=inb(DX); - AH=inb(DX+1); - cycles-=12; - break; - case 0xEE: /*OUT DX,AL*/ - outb(DX,AL); - cycles-=12; - break; - case 0xEF: /*OUT DX,AX*/ - outb(DX,AL); - outb(DX+1,AH); - cycles-=12; - break; + cpu_state.pc+=tempw; + cycles-=23; + FETCHCLEAR(); + break; - case 0xF0: /*LOCK*/ - case 0xF1: /*LOCK alias*/ - cycles-=4; - break; + case 0xE9: /*JMP rel 16*/ + tempw = getword(); + cpu_state.pc += tempw; + cycles-=15; + FETCHCLEAR(); + break; - case 0xF2: /*REPNE*/ - rep(0); - break; - case 0xF3: /*REPE*/ - rep(1); - break; + case 0xEA: /*JMP far*/ + addr=getword(); + tempw=getword(); + cpu_state.pc=addr; + loadcs(tempw); + cycles-=15; + FETCHCLEAR(); + break; - case 0xF4: /*HLT*/ - inhlt=1; - cpu_state.pc--; - FETCHCLEAR(); - cycles-=2; - break; - case 0xF5: /*CMC*/ - flags^=C_FLAG; - cycles-=2; - break; + case 0xEB: /*JMP rel*/ + offset=(int8_t)FETCH(); + cpu_state.pc+=offset; + cycles-=15; + FETCHCLEAR(); + break; - case 0xF6: - fetchea(); - temp=geteab(); - switch (rmdat&0x38) - { - case 0x00: /*TEST b,#8*/ + case 0xEC: /*IN AL,DX*/ + AL=inb(DX); + cycles-=12; + break; + case 0xED: /*IN AX,DX*/ + AL=inb(DX); + AH=inb(DX+1); + cycles-=12; + break; + + case 0xEE: /*OUT DX,AL*/ + outb(DX,AL); + cycles-=12; + break; + case 0xEF: /*OUT DX,AX*/ + outb(DX,AL); + outb(DX+1,AH); + cycles-=12; + break; + + case 0xF0: /*LOCK*/ + case 0xF1: /*LOCK alias*/ + cycles-=4; + break; + + case 0xF2: /*REPNE*/ + rep(0); + break; + + case 0xF3: /*REPE*/ + rep(1); + break; + + case 0xF4: /*HLT*/ + inhlt=1; + cpu_state.pc--; + FETCHCLEAR(); + cycles-=2; + break; + + case 0xF5: /*CMC*/ + flags^=C_FLAG; + cycles-=2; + break; + + case 0xF6: + fetchea(); + temp=geteab(); + switch (rmdat&0x38) { + case 0x00: /*TEST b,#8*/ case 0x08: - temp2=FETCH(); - temp&=temp2; - setznp8(temp); - flags&=~(C_FLAG|V_FLAG|A_FLAG); - cycles-=((cpu_mod==3)?5:11); - break; - case 0x10: /*NOT b*/ - temp=~temp; - seteab(temp); - cycles-=((cpu_mod==3)?3:24); - break; - case 0x18: /*NEG b*/ - setsub8(0,temp); - temp=0-temp; - seteab(temp); - cycles-=((cpu_mod==3)?3:24); - break; - case 0x20: /*MUL AL,b*/ - setznp8(AL); - AX=AL*temp; - if (AX) flags&=~Z_FLAG; - else flags|=Z_FLAG; - if (AH) flags|=(C_FLAG|V_FLAG); - else flags&=~(C_FLAG|V_FLAG); - cycles-=70; - break; - case 0x28: /*IMUL AL,b*/ - setznp8(AL); - tempws=(int)((int8_t)AL)*(int)((int8_t)temp); - AX=tempws&0xFFFF; - if (AX) flags&=~Z_FLAG; - else flags|=Z_FLAG; - if (AH) flags|=(C_FLAG|V_FLAG); - else flags&=~(C_FLAG|V_FLAG); - cycles-=80; - break; - case 0x30: /*DIV AL,b*/ - tempw=AX; - if (temp) - { - tempw2=tempw%temp; - AH=tempw2 & 0xff; - tempw/=temp; - AL=tempw&0xFF; - } - else - { - pclog("DIVb BY 0 %04X:%04X\n",cs>>4,cpu_state.pc); - writememw(ss,(SP-2)&0xFFFF,flags|0xF000); - writememw(ss,(SP-4)&0xFFFF,CS); - writememw(ss,(SP-6)&0xFFFF,cpu_state.pc); - SP-=6; - flags&=~I_FLAG; - flags&=~T_FLAG; - cpu_state.pc=readmemw(0,0); - loadcs(readmemw(0,2)); - FETCHCLEAR(); - } - cycles-=80; - break; - case 0x38: /*IDIV AL,b*/ - tempws=(int)AX; - if (temp) - { - tempw2=tempws%(int)((int8_t)temp); - AH=tempw2&0xFF; - tempws/=(int)((int8_t)temp); - AL=tempws&0xFF; - } - else - { - pclog("IDIVb BY 0 %04X:%04X\n",cs>>4,cpu_state.pc); - writememw(ss,(SP-2)&0xFFFF,flags|0xF000); - writememw(ss,(SP-4)&0xFFFF,CS); - writememw(ss,(SP-6)&0xFFFF,cpu_state.pc); - SP-=6; - flags&=~I_FLAG; - flags&=~T_FLAG; - cpu_state.pc=readmemw(0,0); - loadcs(readmemw(0,2)); - FETCHCLEAR(); - } - cycles-=101; - break; - } - break; + temp2=FETCH(); + temp&=temp2; + setznp8(temp); + flags&=~(C_FLAG|V_FLAG|A_FLAG); + cycles-=((cpu_mod==3)?5:11); + break; - case 0xF7: - fetchea(); - tempw=geteaw(); - switch (rmdat&0x38) - { - case 0x00: /*TEST w*/ + case 0x10: /*NOT b*/ + temp=~temp; + seteab(temp); + cycles-=((cpu_mod==3)?3:24); + break; + + case 0x18: /*NEG b*/ + setsub8(0,temp); + temp=0-temp; + seteab(temp); + cycles-=((cpu_mod==3)?3:24); + break; + + case 0x20: /*MUL AL,b*/ + setznp8(AL); + AX=AL*temp; + if (AX) flags&=~Z_FLAG; + else flags|=Z_FLAG; + if (AH) flags|=(C_FLAG|V_FLAG); + else flags&=~(C_FLAG|V_FLAG); + cycles-=70; + break; + + case 0x28: /*IMUL AL,b*/ + setznp8(AL); + tempws=(int)((int8_t)AL)*(int)((int8_t)temp); + AX=tempws&0xFFFF; + if (AX) flags&=~Z_FLAG; + else flags|=Z_FLAG; + if (AH) flags|=(C_FLAG|V_FLAG); + else flags&=~(C_FLAG|V_FLAG); + cycles-=80; + break; + + case 0x30: /*DIV AL,b*/ + tempw=AX; + if (temp) { + tempw2=tempw%temp; + AH=tempw2 & 0xff; + tempw/=temp; + AL=tempw&0xFF; + } else { + ERRLOG("CPU: DIVb BY 0 %04X:%04X\n",cs>>4,cpu_state.pc); + writememw(ss,(SP-2)&0xFFFF,flags|0xF000); + writememw(ss,(SP-4)&0xFFFF,CS); + writememw(ss,(SP-6)&0xFFFF,cpu_state.pc); + SP-=6; + flags&=~I_FLAG; + flags&=~T_FLAG; + cpu_state.pc=readmemw(0,0); + loadcs(readmemw(0,2)); + FETCHCLEAR(); + } + cycles-=80; + break; + + case 0x38: /*IDIV AL,b*/ + tempws=(int)AX; + if (temp) { + tempw2=tempws%(int)((int8_t)temp); + AH=tempw2&0xFF; + tempws/=(int)((int8_t)temp); + AL=tempws&0xFF; + } else { + ERRLOG("CPU: IDIVb BY 0 %04X:%04X\n",cs>>4,cpu_state.pc); + writememw(ss,(SP-2)&0xFFFF,flags|0xF000); + writememw(ss,(SP-4)&0xFFFF,CS); + writememw(ss,(SP-6)&0xFFFF,cpu_state.pc); + SP-=6; + flags&=~I_FLAG; + flags&=~T_FLAG; + cpu_state.pc=readmemw(0,0); + loadcs(readmemw(0,2)); + FETCHCLEAR(); + } + cycles-=101; + break; + } + break; + + case 0xF7: + fetchea(); + tempw=geteaw(); + switch (rmdat&0x38) { + case 0x00: /*TEST w*/ case 0x08: - tempw2=getword(); - setznp16(tempw&tempw2); - flags&=~(C_FLAG|V_FLAG|A_FLAG); - cycles-=((cpu_mod==3)?5:11); - break; - case 0x10: /*NOT w*/ - seteaw(~tempw); - cycles-=((cpu_mod==3)?3:24); - break; - case 0x18: /*NEG w*/ - setsub16(0,tempw); - tempw=0-tempw; - seteaw(tempw); - cycles-=((cpu_mod==3)?3:24); - break; - case 0x20: /*MUL AX,w*/ - setznp16(AX); - templ=AX*tempw; - AX=templ&0xFFFF; - DX=templ>>16; - if (AX|DX) flags&=~Z_FLAG; - else flags|=Z_FLAG; - if (DX) flags|=(C_FLAG|V_FLAG); - else flags&=~(C_FLAG|V_FLAG); - cycles-=118; - break; - case 0x28: /*IMUL AX,w*/ - setznp16(AX); - tempws=(int)((int16_t)AX)*(int)((int16_t)tempw); - if ((tempws>>15) && ((tempws>>15)!=-1)) flags|=(C_FLAG|V_FLAG); - else flags&=~(C_FLAG|V_FLAG); - AX=tempws&0xFFFF; - tempws=(uint16_t)(tempws>>16); - DX=tempws&0xFFFF; - if (AX|DX) flags&=~Z_FLAG; - else flags|=Z_FLAG; - cycles-=128; - break; - case 0x30: /*DIV AX,w*/ - templ=(DX<<16)|AX; - if (tempw) - { - tempw2=templ%tempw; - DX=tempw2; - templ/=tempw; - AX=templ&0xFFFF; - } - else - { - pclog("DIVw BY 0 %04X:%04X\n",cs>>4,cpu_state.pc); - writememw(ss,(SP-2)&0xFFFF,flags|0xF000); - writememw(ss,(SP-4)&0xFFFF,CS); - writememw(ss,(SP-6)&0xFFFF,cpu_state.pc); - SP-=6; - flags&=~I_FLAG; - flags&=~T_FLAG; - cpu_state.pc=readmemw(0,0); - loadcs(readmemw(0,2)); - FETCHCLEAR(); - } - cycles-=144; - break; - case 0x38: /*IDIV AX,w*/ - tempws=(int)((DX<<16)|AX); - if (tempw) - { - tempw2=tempws%(int)((int16_t)tempw); - DX=tempw2; - tempws/=(int)((int16_t)tempw); - AX=tempws&0xFFFF; - } - else - { - pclog("IDIVw BY 0 %04X:%04X\n",cs>>4,cpu_state.pc); - writememw(ss,(SP-2)&0xFFFF,flags|0xF000); - writememw(ss,(SP-4)&0xFFFF,CS); - writememw(ss,(SP-6)&0xFFFF,cpu_state.pc); - SP-=6; - flags&=~I_FLAG; - flags&=~T_FLAG; - cpu_state.pc=readmemw(0,0); - loadcs(readmemw(0,2)); - FETCHCLEAR(); - } - cycles-=165; - break; - } - break; + tempw2=getword(); + setznp16(tempw&tempw2); + flags&=~(C_FLAG|V_FLAG|A_FLAG); + cycles-=((cpu_mod==3)?5:11); + break; - case 0xF8: /*CLC*/ - flags&=~C_FLAG; - cycles-=2; - break; - case 0xF9: /*STC*/ - flags|=C_FLAG; - cycles-=2; - break; - case 0xFA: /*CLI*/ - flags&=~I_FLAG; - cycles-=3; - break; - case 0xFB: /*STI*/ - flags|=I_FLAG; - cycles-=2; - break; - case 0xFC: /*CLD*/ - flags&=~D_FLAG; - cycles-=2; - break; - case 0xFD: /*STD*/ - flags|=D_FLAG; - cycles-=2; - break; + case 0x10: /*NOT w*/ + seteaw(~tempw); + cycles-=((cpu_mod==3)?3:24); + break; - case 0xFE: /*INC/DEC b*/ - fetchea(); - temp=geteab(); - flags&=~V_FLAG; - if (rmdat&0x38) - { - setsub8nc(temp,1); - temp2=temp-1; - if ((temp&0x80) && !(temp2&0x80)) flags|=V_FLAG; - } - else - { - setadd8nc(temp,1); - temp2=temp+1; - if ((temp2&0x80) && !(temp&0x80)) flags|=V_FLAG; - } - seteab(temp2); - cycles-=((cpu_mod==3)?3:23); - break; + case 0x18: /*NEG w*/ + setsub16(0,tempw); + tempw=0-tempw; + seteaw(tempw); + cycles-=((cpu_mod==3)?3:24); + break; - case 0xFF: - fetchea(); - switch (rmdat&0x38) - { - case 0x00: /*INC w*/ - tempw=geteaw(); - setadd16nc(tempw,1); - seteaw(tempw+1); - cycles-=((cpu_mod==3)?3:23); - break; - case 0x08: /*DEC w*/ - tempw=geteaw(); - setsub16nc(tempw,1); - seteaw(tempw-1); - cycles-=((cpu_mod==3)?3:23); - break; - case 0x10: /*CALL*/ - tempw=geteaw(); - if (cpu_state.ssegs) ss=oldss; - writememw(ss,(SP-2)&0xFFFF,cpu_state.pc); - SP-=2; - cpu_state.last_ea = SP; - cpu_state.pc=tempw; - cycles-=((cpu_mod==3)?20:29); - FETCHCLEAR(); - break; - case 0x18: /*CALL far*/ - tempw=readmemw(easeg,cpu_state.eaaddr); - tempw2=readmemw(easeg,(cpu_state.eaaddr+2)&0xFFFF); - tempw3=CS; - tempw4=cpu_state.pc; - if (cpu_state.ssegs) ss=oldss; - cpu_state.pc=tempw; - loadcs(tempw2); - writememw(ss,(SP-2)&0xFFFF,tempw3); - writememw(ss,((SP-4)&0xFFFF),tempw4); - SP-=4; - cpu_state.last_ea = SP; - cycles-=53; - FETCHCLEAR(); - break; - case 0x20: /*JMP*/ - cpu_state.pc=geteaw(); - cycles-=((cpu_mod==3)?11:18); - FETCHCLEAR(); - break; - case 0x28: /*JMP far*/ - cpu_state.pc=readmemw(easeg,cpu_state.eaaddr); - loadcs(readmemw(easeg,(cpu_state.eaaddr+2)&0xFFFF)); - cycles-=24; - FETCHCLEAR(); - break; - case 0x30: /*PUSH w*/ - case 0x38: /*PUSH w alias, reported by reenigne*/ - tempw=geteaw(); - if (cpu_state.ssegs) ss=oldss; - writememw(ss,((SP-2)&0xFFFF),tempw); - SP-=2; - cpu_state.last_ea = SP; - cycles-=((cpu_mod==3)?15:24); - break; - } - break; + case 0x20: /*MUL AX,w*/ + setznp16(AX); + templ=AX*tempw; + AX=templ&0xFFFF; + DX=templ>>16; + if (AX|DX) flags&=~Z_FLAG; + else flags|=Z_FLAG; + if (DX) flags|=(C_FLAG|V_FLAG); + else flags&=~(C_FLAG|V_FLAG); + cycles-=118; + break; - default: - FETCH(); - cycles-=8; - break; - } - cpu_state.pc&=0xFFFF; + case 0x28: /*IMUL AX,w*/ + setznp16(AX); + tempws=(int)((int16_t)AX)*(int)((int16_t)tempw); + if ((tempws>>15) && ((tempws>>15)!=-1)) flags|=(C_FLAG|V_FLAG); + else flags&=~(C_FLAG|V_FLAG); + AX=tempws&0xFFFF; + tempws=(uint16_t)(tempws>>16); + DX=tempws&0xFFFF; + if (AX|DX) flags&=~Z_FLAG; + else flags|=Z_FLAG; + cycles-=128; + break; - if (cpu_state.ssegs) - { - ds=oldds; - ss=oldss; - cpu_state.ssegs=0; - } - - FETCHADD(((cycdiff-cycles)-memcycs)-fetchclocks); - if ((cycdiff-cycles)>4,cpu_state.pc); + writememw(ss,(SP-2)&0xFFFF,flags|0xF000); + writememw(ss,(SP-4)&0xFFFF,CS); + writememw(ss,(SP-6)&0xFFFF,cpu_state.pc); + SP-=6; + flags&=~I_FLAG; + flags&=~T_FLAG; + cpu_state.pc=readmemw(0,0); + loadcs(readmemw(0,2)); + FETCHCLEAR(); + } + cycles-=144; + break; - insc++; - clockhardware(); + case 0x38: /*IDIV AX,w*/ + tempws=(int)((DX<<16)|AX); + if (tempw) { + tempw2=tempws%(int)((int16_t)tempw); + DX=tempw2; + tempws/=(int)((int16_t)tempw); + AX=tempws&0xFFFF; + } else { + ERRLOG("CPU: IDIVw BY 0 %04X:%04X\n",cs>>4,cpu_state.pc); + writememw(ss,(SP-2)&0xFFFF,flags|0xF000); + writememw(ss,(SP-4)&0xFFFF,CS); + writememw(ss,(SP-6)&0xFFFF,cpu_state.pc); + SP-=6; + flags&=~I_FLAG; + flags&=~T_FLAG; + cpu_state.pc=readmemw(0,0); + loadcs(readmemw(0,2)); + FETCHCLEAR(); + } + cycles-=165; + break; + } + break; - if (trap && (flags&T_FLAG) && !noint) - { - writememw(ss,(SP-2)&0xFFFF,flags|0xF000); - writememw(ss,(SP-4)&0xFFFF,CS); - writememw(ss,(SP-6)&0xFFFF,cpu_state.pc); - SP-=6; - addr=1<<2; - flags&=~I_FLAG; - flags&=~T_FLAG; - cpu_state.pc=readmemw(0,addr); - loadcs(readmemw(0,addr+2)); - FETCHCLEAR(); - } - else if (nmi && nmi_enable && nmi_mask) - { - writememw(ss,(SP-2)&0xFFFF,flags|0xF000); - writememw(ss,(SP-4)&0xFFFF,CS); - writememw(ss,(SP-6)&0xFFFF,cpu_state.pc); - SP-=6; - addr=2<<2; - flags&=~I_FLAG; - flags&=~T_FLAG; - cpu_state.pc=readmemw(0,addr); - loadcs(readmemw(0,addr+2)); - FETCHCLEAR(); - nmi_enable = 0; - } - else if (takeint && !cpu_state.ssegs && !noint) - { - temp=picinterrupt(); - if (temp!=0xFF) - { - if (inhlt) cpu_state.pc++; - writememw(ss,(SP-2)&0xFFFF,flags|0xF000); - writememw(ss,(SP-4)&0xFFFF,CS); - writememw(ss,(SP-6)&0xFFFF,cpu_state.pc); - SP-=6; - addr=temp<<2; - flags&=~I_FLAG; - flags&=~T_FLAG; - cpu_state.pc=readmemw(0,addr); - loadcs(readmemw(0,addr+2)); - FETCHCLEAR(); - } - } - takeint = (flags&I_FLAG) && (pic.pend&~pic.mask); + case 0xF8: /*CLC*/ + flags&=~C_FLAG; + cycles-=2; + break; - if (noint) noint=0; - ins++; - } + case 0xF9: /*STC*/ + flags|=C_FLAG; + cycles-=2; + break; + + case 0xFA: /*CLI*/ + flags&=~I_FLAG; + cycles-=3; + break; + + case 0xFB: /*STI*/ + flags|=I_FLAG; + cycles-=2; + break; + + case 0xFC: /*CLD*/ + flags&=~D_FLAG; + cycles-=2; + break; + + case 0xFD: /*STD*/ + flags|=D_FLAG; + cycles-=2; + break; + + case 0xFE: /*INC/DEC b*/ + fetchea(); + temp=geteab(); + flags&=~V_FLAG; + if (rmdat&0x38) { + setsub8nc(temp,1); + temp2=temp-1; + if ((temp&0x80) && !(temp2&0x80)) + flags|=V_FLAG; + } else { + setadd8nc(temp,1); + temp2=temp+1; + if ((temp2&0x80) && !(temp&0x80)) + flags|=V_FLAG; + } + seteab(temp2); + cycles-=((cpu_mod==3)?3:23); + break; + + case 0xFF: + fetchea(); + switch (rmdat&0x38) { + case 0x00: /*INC w*/ + tempw=geteaw(); + setadd16nc(tempw,1); + seteaw(tempw+1); + cycles-=((cpu_mod==3)?3:23); + break; + + case 0x08: /*DEC w*/ + tempw=geteaw(); + setsub16nc(tempw,1); + seteaw(tempw-1); + cycles-=((cpu_mod==3)?3:23); + break; + + case 0x10: /*CALL*/ + tempw=geteaw(); + if (cpu_state.ssegs) ss=oldss; + writememw(ss,(SP-2)&0xFFFF,cpu_state.pc); + SP-=2; + cpu_state.last_ea = SP; + cpu_state.pc=tempw; + cycles-=((cpu_mod==3)?20:29); + FETCHCLEAR(); + break; + + case 0x18: /*CALL far*/ + tempw=readmemw(easeg,cpu_state.eaaddr); + tempw2=readmemw(easeg,(cpu_state.eaaddr+2)&0xFFFF); + tempw3=CS; + tempw4=cpu_state.pc; + if (cpu_state.ssegs) ss=oldss; + cpu_state.pc=tempw; + loadcs(tempw2); + writememw(ss,(SP-2)&0xFFFF,tempw3); + writememw(ss,((SP-4)&0xFFFF),tempw4); + SP-=4; + cpu_state.last_ea = SP; + cycles-=53; + FETCHCLEAR(); + break; + + case 0x20: /*JMP*/ + cpu_state.pc=geteaw(); + cycles-=((cpu_mod==3)?11:18); + FETCHCLEAR(); + break; + + case 0x28: /*JMP far*/ + cpu_state.pc=readmemw(easeg,cpu_state.eaaddr); + loadcs(readmemw(easeg,(cpu_state.eaaddr+2)&0xFFFF)); + cycles-=24; + FETCHCLEAR(); + break; + + case 0x30: /*PUSH w*/ + case 0x38: /*PUSH w alias, reported by reenigne*/ + tempw=geteaw(); + if (cpu_state.ssegs) ss=oldss; + writememw(ss,((SP-2)&0xFFFF),tempw); + SP-=2; + cpu_state.last_ea = SP; + cycles-=((cpu_mod==3)?15:24); + break; + } + break; + + default: + FETCH(); + cycles-=8; + break; + } + cpu_state.pc&=0xFFFF; + + if (cpu_state.ssegs) { + ds=oldds; + ss=oldss; + cpu_state.ssegs=0; + } + + FETCHADD(((cycdiff-cycles)-memcycs)-fetchclocks); + if ((cycdiff-cycles)> 12].head; uint64_t a = __cs | ((uint64_t)phys << 32); @@ -134,7 +134,7 @@ static inline codeblock_t *codeblock_tree_find(uint32_t phys, uint32_t __cs) return block; } -static inline void codeblock_tree_add(codeblock_t *new_block) +static INLINE void codeblock_tree_add(codeblock_t *new_block) { codeblock_t *block = pages[new_block->phys >> 12].head; uint64_t a = new_block->_cs | ((uint64_t)new_block->phys << 32); @@ -168,7 +168,7 @@ static inline void codeblock_tree_add(codeblock_t *new_block) } } -static inline void codeblock_tree_delete(codeblock_t *block) +static INLINE void codeblock_tree_delete(codeblock_t *block) { codeblock_t *parent = block->parent; @@ -347,7 +347,7 @@ extern int block_pos; #define CPU_BLOCK_END() cpu_block_end = 1 -static inline void addbyte(uint8_t val) +static INLINE void addbyte(uint8_t val) { codeblock[block_current].data[block_pos++] = val; if (block_pos >= BLOCK_MAX) @@ -356,7 +356,7 @@ static inline void addbyte(uint8_t val) } } -static inline void addword(uint16_t val) +static INLINE void addword(uint16_t val) { uint16_t *p = (uint16_t *) &codeblock[block_current].data[block_pos]; *p = val; @@ -367,7 +367,7 @@ static inline void addword(uint16_t val) } } -static inline void addlong(uint32_t val) +static INLINE void addlong(uint32_t val) { uint32_t *p = (uint32_t *) &codeblock[block_current].data[block_pos]; *p = val; @@ -378,7 +378,7 @@ static inline void addlong(uint32_t val) } } -static inline void addquad(uint64_t val) +static INLINE void addquad(uint64_t val) { uint64_t *p = (uint64_t *) &codeblock[block_current].data[block_pos]; *p = val; diff --git a/src/cpu/codegen_ops.h b/src/cpu/codegen_ops.h index bbf13b8..9925463 100644 --- a/src/cpu/codegen_ops.h +++ b/src/cpu/codegen_ops.h @@ -8,7 +8,7 @@ * * Definitions for the code generator. * - * Version: @(#)codegen_ops.h 1.0.1 2018/02/14 + * Version: @(#)codegen_ops.h 1.0.2 2018/09/19 * * Authors: Sarah Walker, * Miran Grca, @@ -51,8 +51,8 @@ extern RecompOpFn recomp_opcodes_dc[512]; extern RecompOpFn recomp_opcodes_dd[512]; extern RecompOpFn recomp_opcodes_de[512]; extern RecompOpFn recomp_opcodes_df[512]; -RecompOpFn recomp_opcodes_REPE[512]; -RecompOpFn recomp_opcodes_REPNE[512]; +extern RecompOpFn recomp_opcodes_REPE[512]; +extern RecompOpFn recomp_opcodes_REPNE[512]; #define REG_EAX 0 #define REG_ECX 1 diff --git a/src/cpu/codegen_ops_fpu.h b/src/cpu/codegen_ops_fpu.h index c07c88f..63b0afc 100644 --- a/src/cpu/codegen_ops_fpu.h +++ b/src/cpu/codegen_ops_fpu.h @@ -8,7 +8,7 @@ * * Miscellaneous instructions. * - * Version: @(#)codegen_ops_fpu.h 1.0.1 2018/02/14 + * Version: @(#)codegen_ops_fpu.h 1.0.2 2018/09/04 * * Authors: Sarah Walker, * Miran Grca, @@ -671,5 +671,13 @@ opFLDimm(L2T, 3.3219280948873623) opFLDimm(L2E, 1.4426950408889634); opFLDimm(PI, 3.141592653589793); opFLDimm(EG2, 0.3010299956639812); -opFLDimm(LN2, 0.693147180559945); opFLDimm(Z, 0.0) + + +static uint32_t ropFLDLN2(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + FP_ENTER(); + FP_LOAD_IMM_Q(0x3fe62e42fefa39f0ULL); + + return op_pc; +} diff --git a/src/cpu/codegen_ops_x86-64.h b/src/cpu/codegen_ops_x86-64.h index a9da53c..85f30ce 100644 --- a/src/cpu/codegen_ops_x86-64.h +++ b/src/cpu/codegen_ops_x86-64.h @@ -45,7 +45,7 @@ #define IS_32_ADDR(x) !(((uintptr_t)x) & 0xffffffff00000000) -static inline int find_host_xmm_reg() +static INLINE int find_host_xmm_reg() { int c; for (c = HOST_REG_XMM_START; c < HOST_REG_XMM_END; c++) @@ -58,7 +58,7 @@ static inline int find_host_xmm_reg() fatal("Out of host XMM regs!\n"); return c; } -static inline void call(codeblock_t *block, uintptr_t func) +static INLINE void call(codeblock_t *block, uintptr_t func) { uintptr_t diff = func - (uintptr_t)&block->data[block_pos + 5]; @@ -80,7 +80,7 @@ static inline void call(codeblock_t *block, uintptr_t func) } } -static inline void call_long(uintptr_t func) +static INLINE void call_long(uintptr_t func) { codegen_reg_loaded[0] = codegen_reg_loaded[1] = codegen_reg_loaded[2] = codegen_reg_loaded[3] = 0; codegen_reg_loaded[4] = codegen_reg_loaded[5] = codegen_reg_loaded[6] = codegen_reg_loaded[7] = 0; @@ -92,7 +92,7 @@ static inline void call_long(uintptr_t func) addbyte(0xd0); } -static inline void load_param_1_32(codeblock_t *block, uint32_t param) +static INLINE void load_param_1_32(codeblock_t *block, uint32_t param) { #if WIN64 addbyte(0xb9); /*MOVL $fetchdat,%ecx*/ @@ -101,7 +101,7 @@ static inline void load_param_1_32(codeblock_t *block, uint32_t param) #endif addlong(param); } -static inline void load_param_1_reg_32(int reg) +static INLINE void load_param_1_reg_32(int reg) { #if WIN64 if (reg & 8) @@ -116,7 +116,7 @@ static inline void load_param_1_reg_32(int reg) #endif } #if 0 -static inline void load_param_1_64(codeblock_t *block, uint64_t param) +static INLINE void load_param_1_64(codeblock_t *block, uint64_t param) { addbyte(0x48); #if WIN64 @@ -128,7 +128,7 @@ static inline void load_param_1_64(codeblock_t *block, uint64_t param) } #endif -static inline void load_param_2_32(codeblock_t *block, uint32_t param) +static INLINE void load_param_2_32(codeblock_t *block, uint32_t param) { #if WIN64 addbyte(0xba); /*MOVL $fetchdat,%edx*/ @@ -137,7 +137,7 @@ static inline void load_param_2_32(codeblock_t *block, uint32_t param) #endif addlong(param); } -static inline void load_param_2_reg_32(int reg) +static INLINE void load_param_2_reg_32(int reg) { #if WIN64 if (reg & 8) @@ -151,7 +151,7 @@ static inline void load_param_2_reg_32(int reg) addbyte(0xc0 | REG_ESI | (reg << 3)); #endif } -static inline void load_param_2_64(codeblock_t *block, uint64_t param) +static INLINE void load_param_2_64(codeblock_t *block, uint64_t param) { addbyte(0x48); #if WIN64 @@ -162,7 +162,7 @@ static inline void load_param_2_64(codeblock_t *block, uint64_t param) addquad(param); } -static inline void load_param_3_reg_32(int reg) +static INLINE void load_param_3_reg_32(int reg) { if (reg & 8) { @@ -189,7 +189,7 @@ static inline void load_param_3_reg_32(int reg) #endif } } -static inline void load_param_3_reg_64(int reg) +static INLINE void load_param_3_reg_64(int reg) { if (reg & 8) { @@ -217,7 +217,7 @@ static inline void load_param_3_reg_64(int reg) } } -static inline void CALL_FUNC(uintptr_t func) +static INLINE void CALL_FUNC(uintptr_t func) { codegen_reg_loaded[0] = codegen_reg_loaded[1] = codegen_reg_loaded[2] = codegen_reg_loaded[3] = 0; codegen_reg_loaded[4] = codegen_reg_loaded[5] = codegen_reg_loaded[6] = codegen_reg_loaded[7] = 0; @@ -229,11 +229,11 @@ static inline void CALL_FUNC(uintptr_t func) addbyte(0xd0); } -static inline void RELEASE_REG(int host_reg) +static INLINE void RELEASE_REG(int host_reg) { } -static inline int LOAD_REG_B(int reg) +static INLINE int LOAD_REG_B(int reg) { int host_reg = reg & 3; @@ -252,7 +252,7 @@ static inline int LOAD_REG_B(int reg) return host_reg | 8; } -static inline int LOAD_REG_W(int reg) +static INLINE int LOAD_REG_W(int reg) { int host_reg = reg; @@ -268,7 +268,7 @@ static inline int LOAD_REG_W(int reg) return host_reg | 8; } -static inline int LOAD_REG_L(int reg) +static INLINE int LOAD_REG_L(int reg) { int host_reg = reg; @@ -285,7 +285,7 @@ static inline int LOAD_REG_L(int reg) return host_reg | 8; } -static inline int LOAD_REG_IMM(uint32_t imm) +static INLINE int LOAD_REG_IMM(uint32_t imm) { int host_reg = REG_EBX; @@ -295,7 +295,7 @@ static inline int LOAD_REG_IMM(uint32_t imm) return host_reg; } -static inline void STORE_REG_TARGET_B_RELEASE(int host_reg, int guest_reg) +static INLINE void STORE_REG_TARGET_B_RELEASE(int host_reg, int guest_reg) { int dest_reg = LOAD_REG_L(guest_reg & 3) & 7; @@ -396,7 +396,7 @@ static inline void STORE_REG_TARGET_B_RELEASE(int host_reg, int guest_reg) } } } -static inline void STORE_REG_TARGET_W_RELEASE(int host_reg, int guest_reg) +static INLINE void STORE_REG_TARGET_W_RELEASE(int host_reg, int guest_reg) { int dest_reg = LOAD_REG_L(guest_reg & 7) & 7; @@ -424,7 +424,7 @@ static inline void STORE_REG_TARGET_W_RELEASE(int host_reg, int guest_reg) addbyte(cpu_state_offset(regs[guest_reg & 7].w)); } } -static inline void STORE_REG_TARGET_L_RELEASE(int host_reg, int guest_reg) +static INLINE void STORE_REG_TARGET_L_RELEASE(int host_reg, int guest_reg) { if (host_reg & 8) { @@ -447,7 +447,7 @@ static inline void STORE_REG_TARGET_L_RELEASE(int host_reg, int guest_reg) } } -static inline void STORE_REG_B_RELEASE(int host_reg) +static INLINE void STORE_REG_B_RELEASE(int host_reg) { if (host_reg & 0x10) { @@ -465,7 +465,7 @@ static inline void STORE_REG_B_RELEASE(int host_reg) addbyte(cpu_state_offset(regs[host_reg & 7].b)); } } -static inline void STORE_REG_W_RELEASE(int host_reg) +static INLINE void STORE_REG_W_RELEASE(int host_reg) { addbyte(0x66); /*MOVW [reg],host_reg*/ addbyte(0x44); @@ -473,7 +473,7 @@ static inline void STORE_REG_W_RELEASE(int host_reg) addbyte(0x45 | ((host_reg & 7) << 3)); addbyte(cpu_state_offset(regs[host_reg & 7].w)); } -static inline void STORE_REG_L_RELEASE(int host_reg) +static INLINE void STORE_REG_L_RELEASE(int host_reg) { addbyte(0x44); /*MOVL [reg],host_reg*/ addbyte(0x89); @@ -481,7 +481,7 @@ static inline void STORE_REG_L_RELEASE(int host_reg) addbyte(cpu_state_offset(regs[host_reg & 7].l)); } -static inline void STORE_IMM_REG_B(int reg, uint8_t val) +static INLINE void STORE_IMM_REG_B(int reg, uint8_t val) { if (reg & 4) { @@ -513,7 +513,7 @@ static inline void STORE_IMM_REG_B(int reg, uint8_t val) addbyte(cpu_state_offset(regs[reg & 7].b)); } } -static inline void STORE_IMM_REG_W(int reg, uint16_t val) +static INLINE void STORE_IMM_REG_W(int reg, uint16_t val) { addbyte(0x66); /*MOVW reg, imm*/ addbyte(0x41); @@ -525,7 +525,7 @@ static inline void STORE_IMM_REG_W(int reg, uint16_t val) addbyte(0x45 | (reg << 3)); addbyte(cpu_state_offset(regs[reg & 7].w)); } -static inline void STORE_IMM_REG_L(int reg, uint32_t val) +static INLINE void STORE_IMM_REG_L(int reg, uint32_t val) { addbyte(0x41); /*MOVL reg, imm*/ addbyte(0xb8 | reg); @@ -536,7 +536,7 @@ static inline void STORE_IMM_REG_L(int reg, uint32_t val) addbyte(cpu_state_offset(regs[reg & 7].l)); } -static inline void STORE_IMM_ADDR_L(uintptr_t addr, uint32_t val) +static INLINE void STORE_IMM_ADDR_L(uintptr_t addr, uint32_t val) { if (addr >= (uintptr_t)&cpu_state && addr < ((uintptr_t)&cpu_state)+0x100) { @@ -882,7 +882,7 @@ static x86seg *FETCH_EA_32(x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, u return op_ea_seg; } -static inline x86seg *FETCH_EA(x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc, uint32_t op_32) +static INLINE x86seg *FETCH_EA(x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc, uint32_t op_32) { if (op_32 & 0x200) return FETCH_EA_32(op_ea_seg, fetchdat, op_ssegs, op_pc, 0); @@ -891,7 +891,7 @@ static inline x86seg *FETCH_EA(x86seg *op_ea_seg, uint32_t fetchdat, int op_sseg -static inline void CHECK_SEG_READ(x86seg *seg) +static INLINE void CHECK_SEG_READ(x86seg *seg) { /*Segments always valid in real/V86 mode*/ if (!(cr0 & 1) || (eflags & VM_FLAG)) @@ -927,7 +927,7 @@ static inline void CHECK_SEG_READ(x86seg *seg) seg->checked = 1; } -static inline void CHECK_SEG_WRITE(x86seg *seg) +static INLINE void CHECK_SEG_WRITE(x86seg *seg) { /*Segments always valid in real/V86 mode*/ if (!(cr0 & 1) || (eflags & VM_FLAG)) @@ -963,7 +963,7 @@ static inline void CHECK_SEG_WRITE(x86seg *seg) seg->checked = 1; } -static inline void CHECK_SEG_LIMITS(x86seg *seg, int end_offset) +static INLINE void CHECK_SEG_LIMITS(x86seg *seg, int end_offset) { if ((seg == &_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) return; @@ -1002,7 +1002,7 @@ static inline void CHECK_SEG_LIMITS(x86seg *seg, int end_offset) } } -static inline void MEM_LOAD_ADDR_EA_B(x86seg *seg) +static INLINE void MEM_LOAD_ADDR_EA_B(x86seg *seg) { if ((seg == &_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) { @@ -1075,7 +1075,7 @@ static inline void MEM_LOAD_ADDR_EA_B(x86seg *seg) addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); /*done:*/ } -static inline void MEM_LOAD_ADDR_EA_W(x86seg *seg) +static INLINE void MEM_LOAD_ADDR_EA_W(x86seg *seg) { if ((seg == &_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) { @@ -1154,14 +1154,14 @@ static inline void MEM_LOAD_ADDR_EA_W(x86seg *seg) addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); /*done:*/ } -static inline void MEM_LOAD_ADDR_EA_W_OFFSET(x86seg *seg, int offset) +static INLINE void MEM_LOAD_ADDR_EA_W_OFFSET(x86seg *seg, int offset) { addbyte(0x83); /*ADD EAX, offset*/ addbyte(0xc0); addbyte(offset); MEM_LOAD_ADDR_EA_W(seg); } -static inline void MEM_LOAD_ADDR_EA_L(x86seg *seg) +static INLINE void MEM_LOAD_ADDR_EA_L(x86seg *seg) { if ((seg == &_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) { @@ -1239,7 +1239,7 @@ static inline void MEM_LOAD_ADDR_EA_L(x86seg *seg) addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); /*done:*/ } -static inline void MEM_LOAD_ADDR_EA_Q(x86seg *seg) +static INLINE void MEM_LOAD_ADDR_EA_Q(x86seg *seg) { if ((seg == &_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) { @@ -1319,26 +1319,26 @@ static inline void MEM_LOAD_ADDR_EA_Q(x86seg *seg) /*done:*/ } -static inline void MEM_LOAD_ADDR_IMM_B(x86seg *seg, uint32_t addr) +static INLINE void MEM_LOAD_ADDR_IMM_B(x86seg *seg, uint32_t addr) { addbyte(0xb8); /*MOV EAX, addr*/ addlong(addr); MEM_LOAD_ADDR_EA_B(seg); } -static inline void MEM_LOAD_ADDR_IMM_W(x86seg *seg, uint32_t addr) +static INLINE void MEM_LOAD_ADDR_IMM_W(x86seg *seg, uint32_t addr) { addbyte(0xb8); /*MOV EAX, addr*/ addlong(addr); MEM_LOAD_ADDR_EA_W(seg); } -static inline void MEM_LOAD_ADDR_IMM_L(x86seg *seg, uint32_t addr) +static INLINE void MEM_LOAD_ADDR_IMM_L(x86seg *seg, uint32_t addr) { addbyte(0xb8); /*MOV EAX, addr*/ addlong(addr); MEM_LOAD_ADDR_EA_L(seg); } -static inline void MEM_STORE_ADDR_EA_B(x86seg *seg, int host_reg) +static INLINE void MEM_STORE_ADDR_EA_B(x86seg *seg, int host_reg) { if (host_reg & 0x10) { @@ -1444,7 +1444,7 @@ static inline void MEM_STORE_ADDR_EA_B(x86seg *seg, int host_reg) addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); /*done:*/ } -static inline void MEM_STORE_ADDR_EA_W(x86seg *seg, int host_reg) +static INLINE void MEM_STORE_ADDR_EA_W(x86seg *seg, int host_reg) { if ((seg == &_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) { @@ -1535,7 +1535,7 @@ static inline void MEM_STORE_ADDR_EA_W(x86seg *seg, int host_reg) addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); /*done:*/ } -static inline void MEM_STORE_ADDR_EA_L(x86seg *seg, int host_reg) +static INLINE void MEM_STORE_ADDR_EA_L(x86seg *seg, int host_reg) { if ((seg == &_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) { @@ -1624,7 +1624,7 @@ static inline void MEM_STORE_ADDR_EA_L(x86seg *seg, int host_reg) addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); /*done:*/ } -static inline void MEM_STORE_ADDR_EA_Q(x86seg *seg, int host_reg, int host_reg2) +static INLINE void MEM_STORE_ADDR_EA_Q(x86seg *seg, int host_reg, int host_reg2) { if ((seg == &_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) { @@ -1715,26 +1715,26 @@ static inline void MEM_STORE_ADDR_EA_Q(x86seg *seg, int host_reg, int host_reg2) /*done:*/ } -static inline void MEM_STORE_ADDR_IMM_B(x86seg *seg, uint32_t addr, int host_reg) +static INLINE void MEM_STORE_ADDR_IMM_B(x86seg *seg, uint32_t addr, int host_reg) { addbyte(0xb8); /*MOV EAX, addr*/ addlong(addr); MEM_STORE_ADDR_EA_B(seg, host_reg); } -static inline void MEM_STORE_ADDR_IMM_W(x86seg *seg, uint32_t addr, int host_reg) +static INLINE void MEM_STORE_ADDR_IMM_W(x86seg *seg, uint32_t addr, int host_reg) { addbyte(0xb8); /*MOV EAX, addr*/ addlong(addr); MEM_STORE_ADDR_EA_W(seg, host_reg); } -static inline void MEM_STORE_ADDR_IMM_L(x86seg *seg, uint32_t addr, int host_reg) +static INLINE void MEM_STORE_ADDR_IMM_L(x86seg *seg, uint32_t addr, int host_reg) { addbyte(0xb8); /*MOV EAX, addr*/ addlong(addr); MEM_STORE_ADDR_EA_L(seg, host_reg); } -static inline void STORE_HOST_REG_ADDR_BL(uintptr_t addr, int host_reg) +static INLINE void STORE_HOST_REG_ADDR_BL(uintptr_t addr, int host_reg) { int temp_reg = REG_ECX; @@ -1782,7 +1782,7 @@ static inline void STORE_HOST_REG_ADDR_BL(uintptr_t addr, int host_reg) addbyte(0x06 | (temp_reg << 3)); } } -static inline void STORE_HOST_REG_ADDR_WL(uintptr_t addr, int host_reg) +static INLINE void STORE_HOST_REG_ADDR_WL(uintptr_t addr, int host_reg) { int temp_reg = REG_ECX; @@ -1816,7 +1816,7 @@ static inline void STORE_HOST_REG_ADDR_WL(uintptr_t addr, int host_reg) addbyte(0x06 | (temp_reg << 3)); } } -static inline void STORE_HOST_REG_ADDR_W(uintptr_t addr, int host_reg) +static INLINE void STORE_HOST_REG_ADDR_W(uintptr_t addr, int host_reg) { if (addr >= (uintptr_t)&cpu_state && addr < ((uintptr_t)&cpu_state)+0x100) { @@ -1850,7 +1850,7 @@ static inline void STORE_HOST_REG_ADDR_W(uintptr_t addr, int host_reg) addbyte(0x06 | ((host_reg & 7) << 3)); } } -static inline void STORE_HOST_REG_ADDR(uintptr_t addr, int host_reg) +static INLINE void STORE_HOST_REG_ADDR(uintptr_t addr, int host_reg) { if (addr >= (uintptr_t)&cpu_state && addr < ((uintptr_t)&cpu_state)+0x100) { @@ -1882,7 +1882,7 @@ static inline void STORE_HOST_REG_ADDR(uintptr_t addr, int host_reg) } } -static inline void AND_HOST_REG_B(int dst_reg, int src_reg) +static INLINE void AND_HOST_REG_B(int dst_reg, int src_reg) { if (dst_reg & src_reg & 8) { @@ -2005,7 +2005,7 @@ static inline void AND_HOST_REG_B(int dst_reg, int src_reg) } } } -static inline void AND_HOST_REG_W(int dst_reg, int src_reg) +static INLINE void AND_HOST_REG_W(int dst_reg, int src_reg) { if (dst_reg & src_reg & 8) { @@ -2035,7 +2035,7 @@ static inline void AND_HOST_REG_W(int dst_reg, int src_reg) addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); } } -static inline void AND_HOST_REG_L(int dst_reg, int src_reg) +static INLINE void AND_HOST_REG_L(int dst_reg, int src_reg) { if (dst_reg & src_reg & 8) { @@ -2061,7 +2061,7 @@ static inline void AND_HOST_REG_L(int dst_reg, int src_reg) addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); } } -static inline void AND_HOST_REG_IMM(int host_reg, uint32_t imm) +static INLINE void AND_HOST_REG_IMM(int host_reg, uint32_t imm) { if (host_reg & 0x10) { @@ -2082,7 +2082,7 @@ static inline void AND_HOST_REG_IMM(int host_reg, uint32_t imm) } } -static inline int TEST_HOST_REG_B(int dst_reg, int src_reg) +static INLINE int TEST_HOST_REG_B(int dst_reg, int src_reg) { if (dst_reg & 8) { @@ -2097,7 +2097,7 @@ static inline int TEST_HOST_REG_B(int dst_reg, int src_reg) return dst_reg & ~0x10; } -static inline int TEST_HOST_REG_W(int dst_reg, int src_reg) +static INLINE int TEST_HOST_REG_W(int dst_reg, int src_reg) { if (dst_reg & 8) { @@ -2112,7 +2112,7 @@ static inline int TEST_HOST_REG_W(int dst_reg, int src_reg) return dst_reg; } -static inline int TEST_HOST_REG_L(int dst_reg, int src_reg) +static INLINE int TEST_HOST_REG_L(int dst_reg, int src_reg) { if (dst_reg & 8) { @@ -2127,7 +2127,7 @@ static inline int TEST_HOST_REG_L(int dst_reg, int src_reg) return dst_reg; } -static inline int TEST_HOST_REG_IMM(int host_reg, uint32_t imm) +static INLINE int TEST_HOST_REG_IMM(int host_reg, uint32_t imm) { if (host_reg & 8) { @@ -2153,7 +2153,7 @@ static inline int TEST_HOST_REG_IMM(int host_reg, uint32_t imm) return host_reg; } -static inline void OR_HOST_REG_B(int dst_reg, int src_reg) +static INLINE void OR_HOST_REG_B(int dst_reg, int src_reg) { if (dst_reg & src_reg & 8) { @@ -2275,7 +2275,7 @@ static inline void OR_HOST_REG_B(int dst_reg, int src_reg) } } } -static inline void OR_HOST_REG_W(int dst_reg, int src_reg) +static INLINE void OR_HOST_REG_W(int dst_reg, int src_reg) { if (dst_reg & src_reg & 8) { @@ -2305,7 +2305,7 @@ static inline void OR_HOST_REG_W(int dst_reg, int src_reg) addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); } } -static inline void OR_HOST_REG_L(int dst_reg, int src_reg) +static INLINE void OR_HOST_REG_L(int dst_reg, int src_reg) { if (dst_reg & src_reg & 8) { @@ -2331,7 +2331,7 @@ static inline void OR_HOST_REG_L(int dst_reg, int src_reg) addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); } } -static inline void OR_HOST_REG_IMM(int host_reg, uint32_t imm) +static INLINE void OR_HOST_REG_IMM(int host_reg, uint32_t imm) { if (host_reg & 0x10) { @@ -2356,7 +2356,7 @@ static inline void OR_HOST_REG_IMM(int host_reg, uint32_t imm) } } -static inline void XOR_HOST_REG_B(int dst_reg, int src_reg) +static INLINE void XOR_HOST_REG_B(int dst_reg, int src_reg) { if (dst_reg & src_reg & 8) { @@ -2478,7 +2478,7 @@ static inline void XOR_HOST_REG_B(int dst_reg, int src_reg) } } } -static inline void XOR_HOST_REG_W(int dst_reg, int src_reg) +static INLINE void XOR_HOST_REG_W(int dst_reg, int src_reg) { if (dst_reg & src_reg & 8) { @@ -2508,7 +2508,7 @@ static inline void XOR_HOST_REG_W(int dst_reg, int src_reg) addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); } } -static inline void XOR_HOST_REG_L(int dst_reg, int src_reg) +static INLINE void XOR_HOST_REG_L(int dst_reg, int src_reg) { if (dst_reg & src_reg & 8) { @@ -2534,7 +2534,7 @@ static inline void XOR_HOST_REG_L(int dst_reg, int src_reg) addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); } } -static inline void XOR_HOST_REG_IMM(int host_reg, uint32_t imm) +static INLINE void XOR_HOST_REG_IMM(int host_reg, uint32_t imm) { if (host_reg & 0x10) { @@ -2559,7 +2559,7 @@ static inline void XOR_HOST_REG_IMM(int host_reg, uint32_t imm) } } -static inline void ADD_HOST_REG_B(int dst_reg, int src_reg) +static INLINE void ADD_HOST_REG_B(int dst_reg, int src_reg) { if (dst_reg & src_reg & 8) { @@ -2653,7 +2653,7 @@ static inline void ADD_HOST_REG_B(int dst_reg, int src_reg) else fatal("!(dst_reg & src_reg & 8)\n"); } -static inline void ADD_HOST_REG_W(int dst_reg, int src_reg) +static INLINE void ADD_HOST_REG_W(int dst_reg, int src_reg) { if (dst_reg & src_reg & 8) { @@ -2679,7 +2679,7 @@ static inline void ADD_HOST_REG_W(int dst_reg, int src_reg) else fatal("!(dst_reg & src_reg & 8)\n"); } -static inline void ADD_HOST_REG_L(int dst_reg, int src_reg) +static INLINE void ADD_HOST_REG_L(int dst_reg, int src_reg) { if (dst_reg & src_reg & 8) { @@ -2703,7 +2703,7 @@ static inline void ADD_HOST_REG_L(int dst_reg, int src_reg) fatal("!(dst_reg & src_reg & 8)\n"); } -static inline void SUB_HOST_REG_B(int dst_reg, int src_reg) +static INLINE void SUB_HOST_REG_B(int dst_reg, int src_reg) { if (dst_reg & src_reg & 8) { @@ -2825,7 +2825,7 @@ static inline void SUB_HOST_REG_B(int dst_reg, int src_reg) } } } -static inline void SUB_HOST_REG_W(int dst_reg, int src_reg) +static INLINE void SUB_HOST_REG_W(int dst_reg, int src_reg) { if (dst_reg & src_reg & 8) { @@ -2855,7 +2855,7 @@ static inline void SUB_HOST_REG_W(int dst_reg, int src_reg) addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); } } -static inline void SUB_HOST_REG_L(int dst_reg, int src_reg) +static INLINE void SUB_HOST_REG_L(int dst_reg, int src_reg) { if (dst_reg & src_reg & 8) { @@ -2882,7 +2882,7 @@ static inline void SUB_HOST_REG_L(int dst_reg, int src_reg) } } -static inline int CMP_HOST_REG_B(int dst_reg, int src_reg) +static INLINE int CMP_HOST_REG_B(int dst_reg, int src_reg) { if (dst_reg & 8) { @@ -2897,7 +2897,7 @@ static inline int CMP_HOST_REG_B(int dst_reg, int src_reg) return dst_reg & ~0x10; } -static inline int CMP_HOST_REG_W(int dst_reg, int src_reg) +static INLINE int CMP_HOST_REG_W(int dst_reg, int src_reg) { if (dst_reg & 8) { @@ -2912,7 +2912,7 @@ static inline int CMP_HOST_REG_W(int dst_reg, int src_reg) return dst_reg; } -static inline int CMP_HOST_REG_L(int dst_reg, int src_reg) +static INLINE int CMP_HOST_REG_L(int dst_reg, int src_reg) { if (dst_reg & 8) { @@ -2928,7 +2928,7 @@ static inline int CMP_HOST_REG_L(int dst_reg, int src_reg) return dst_reg; } -static inline void ADD_HOST_REG_IMM_B(int host_reg, uint8_t imm) +static INLINE void ADD_HOST_REG_IMM_B(int host_reg, uint8_t imm) { if (host_reg & 0x10) { @@ -2948,7 +2948,7 @@ static inline void ADD_HOST_REG_IMM_B(int host_reg, uint8_t imm) addbyte(imm); } } -static inline void ADD_HOST_REG_IMM_W(int host_reg, uint16_t imm) +static INLINE void ADD_HOST_REG_IMM_W(int host_reg, uint16_t imm) { addbyte(0x66); /*ADDW host_reg, imm*/ if (host_reg & 8) @@ -2957,7 +2957,7 @@ static inline void ADD_HOST_REG_IMM_W(int host_reg, uint16_t imm) addbyte(0xC0 | (host_reg & 7)); addword(imm); } -static inline void ADD_HOST_REG_IMM(int host_reg, uint32_t imm) +static INLINE void ADD_HOST_REG_IMM(int host_reg, uint32_t imm) { if (host_reg & 8) addbyte(0x41); @@ -2966,7 +2966,7 @@ static inline void ADD_HOST_REG_IMM(int host_reg, uint32_t imm) addlong(imm); } -static inline void SUB_HOST_REG_IMM_B(int host_reg, uint8_t imm) +static INLINE void SUB_HOST_REG_IMM_B(int host_reg, uint8_t imm) { if (host_reg & 0x10) { @@ -2986,7 +2986,7 @@ static inline void SUB_HOST_REG_IMM_B(int host_reg, uint8_t imm) addbyte(imm); } } -static inline void SUB_HOST_REG_IMM_W(int host_reg, uint16_t imm) +static INLINE void SUB_HOST_REG_IMM_W(int host_reg, uint16_t imm) { addbyte(0x66); /*SUBW host_reg, imm*/ if (host_reg & 8) @@ -2995,7 +2995,7 @@ static inline void SUB_HOST_REG_IMM_W(int host_reg, uint16_t imm) addbyte(0xE8 | (host_reg & 7)); addword(imm); } -static inline void SUB_HOST_REG_IMM(int host_reg, uint32_t imm) +static INLINE void SUB_HOST_REG_IMM(int host_reg, uint32_t imm) { if (host_reg & 8) addbyte(0x41); @@ -3004,7 +3004,7 @@ static inline void SUB_HOST_REG_IMM(int host_reg, uint32_t imm) addlong(imm); } -static inline int CMP_HOST_REG_IMM_B(int host_reg, uint8_t imm) +static INLINE int CMP_HOST_REG_IMM_B(int host_reg, uint8_t imm) { if (host_reg & 8) { @@ -3019,7 +3019,7 @@ static inline int CMP_HOST_REG_IMM_B(int host_reg, uint8_t imm) return host_reg; } -static inline int CMP_HOST_REG_IMM_W(int host_reg, uint16_t imm) +static INLINE int CMP_HOST_REG_IMM_W(int host_reg, uint16_t imm) { if (host_reg & 8) { @@ -3034,7 +3034,7 @@ static inline int CMP_HOST_REG_IMM_W(int host_reg, uint16_t imm) return host_reg; } -static inline int CMP_HOST_REG_IMM_L(int host_reg, uint32_t imm) +static INLINE int CMP_HOST_REG_IMM_L(int host_reg, uint32_t imm) { if (host_reg & 8) { @@ -3050,7 +3050,7 @@ static inline int CMP_HOST_REG_IMM_L(int host_reg, uint32_t imm) return host_reg; } -static inline void LOAD_STACK_TO_EA(int off) +static INLINE void LOAD_STACK_TO_EA(int off) { if (stack32) { @@ -3078,7 +3078,7 @@ static inline void LOAD_STACK_TO_EA(int off) } } } -static inline void LOAD_EBP_TO_EA(int off) +static INLINE void LOAD_EBP_TO_EA(int off) { if (stack32) { @@ -3107,7 +3107,7 @@ static inline void LOAD_EBP_TO_EA(int off) } } -static inline void SP_MODIFY(int off) +static INLINE void SP_MODIFY(int off) { if (stack32) { @@ -3147,7 +3147,7 @@ static inline void SP_MODIFY(int off) } } -static inline void TEST_ZERO_JUMP_W(int host_reg, uint32_t new_pc, int taken_cycles) +static INLINE void TEST_ZERO_JUMP_W(int host_reg, uint32_t new_pc, int taken_cycles) { addbyte(0x66); /*CMPW host_reg, 0*/ if (host_reg & 8) @@ -3171,7 +3171,7 @@ static inline void TEST_ZERO_JUMP_W(int host_reg, uint32_t new_pc, int taken_cyc addbyte(0xe9); /*JMP end*/ addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); } -static inline void TEST_ZERO_JUMP_L(int host_reg, uint32_t new_pc, int taken_cycles) +static INLINE void TEST_ZERO_JUMP_L(int host_reg, uint32_t new_pc, int taken_cycles) { if (host_reg & 8) addbyte(0x41); @@ -3195,7 +3195,7 @@ static inline void TEST_ZERO_JUMP_L(int host_reg, uint32_t new_pc, int taken_cyc addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); } -static inline void TEST_NONZERO_JUMP_W(int host_reg, uint32_t new_pc, int taken_cycles) +static INLINE void TEST_NONZERO_JUMP_W(int host_reg, uint32_t new_pc, int taken_cycles) { addbyte(0x66); /*CMPW host_reg, 0*/ if (host_reg & 8) @@ -3219,7 +3219,7 @@ static inline void TEST_NONZERO_JUMP_W(int host_reg, uint32_t new_pc, int taken_ addbyte(0xe9); /*JMP end*/ addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); } -static inline void TEST_NONZERO_JUMP_L(int host_reg, uint32_t new_pc, int taken_cycles) +static INLINE void TEST_NONZERO_JUMP_L(int host_reg, uint32_t new_pc, int taken_cycles) { if (host_reg & 8) addbyte(0x41); @@ -3243,7 +3243,7 @@ static inline void TEST_NONZERO_JUMP_L(int host_reg, uint32_t new_pc, int taken_ addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); } -static inline void BRANCH_COND_BE(int pc_offset, uint32_t op_pc, uint32_t offset, int not) +static INLINE void BRANCH_COND_BE(int pc_offset, uint32_t op_pc, uint32_t offset, int not) { uint8_t *jump1; @@ -3292,7 +3292,7 @@ static inline void BRANCH_COND_BE(int pc_offset, uint32_t op_pc, uint32_t offset *jump1 = (uintptr_t)&codeblock[block_current].data[block_pos] - (uintptr_t)jump1 - 1; } -static inline void BRANCH_COND_L(int pc_offset, uint32_t op_pc, uint32_t offset, int not) +static INLINE void BRANCH_COND_L(int pc_offset, uint32_t op_pc, uint32_t offset, int not) { CALL_FUNC((uintptr_t)NF_SET); addbyte(0x85); /*TEST EAX,EAX*/ @@ -3328,7 +3328,7 @@ static inline void BRANCH_COND_L(int pc_offset, uint32_t op_pc, uint32_t offset, addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); } -static inline void BRANCH_COND_LE(int pc_offset, uint32_t op_pc, uint32_t offset, int not) +static INLINE void BRANCH_COND_LE(int pc_offset, uint32_t op_pc, uint32_t offset, int not) { uint8_t *jump1; if (codegen_flags_changed && cpu_state.flags_op != FLAGS_UNKNOWN) @@ -3386,7 +3386,7 @@ static inline void BRANCH_COND_LE(int pc_offset, uint32_t op_pc, uint32_t offset *jump1 = (uintptr_t)&codeblock[block_current].data[block_pos] - (uintptr_t)jump1 - 1; } -static inline int LOAD_VAR_W(uintptr_t addr) +static INLINE int LOAD_VAR_W(uintptr_t addr) { int host_reg = REG_EBX; @@ -3417,11 +3417,11 @@ static inline int LOAD_VAR_W(uintptr_t addr) return host_reg; } -static inline int LOAD_VAR_WL(uintptr_t addr) +static INLINE int LOAD_VAR_WL(uintptr_t addr) { return LOAD_VAR_W(addr); } -static inline int LOAD_VAR_L(uintptr_t addr) +static INLINE int LOAD_VAR_L(uintptr_t addr) { int host_reg = REG_EBX; @@ -3450,7 +3450,7 @@ static inline int LOAD_VAR_L(uintptr_t addr) return host_reg; } -static inline int COPY_REG(int src_reg) +static INLINE int COPY_REG(int src_reg) { if (src_reg & 8) addbyte(0x44); @@ -3460,7 +3460,7 @@ static inline int COPY_REG(int src_reg) return REG_ECX | (src_reg & 0x10); } -static inline int LOAD_HOST_REG(int host_reg) +static INLINE int LOAD_HOST_REG(int host_reg) { if (host_reg & 8) addbyte(0x44); @@ -3470,7 +3470,7 @@ static inline int LOAD_HOST_REG(int host_reg) return REG_EBX | (host_reg & 0x10); } -static inline int ZERO_EXTEND_W_B(int reg) +static INLINE int ZERO_EXTEND_W_B(int reg) { if (reg & 0x10) { @@ -3492,7 +3492,7 @@ static inline int ZERO_EXTEND_W_B(int reg) return REG_EAX; } -static inline int ZERO_EXTEND_L_B(int reg) +static INLINE int ZERO_EXTEND_L_B(int reg) { if (reg & 0x10) { @@ -3514,7 +3514,7 @@ static inline int ZERO_EXTEND_L_B(int reg) return REG_EAX; } -static inline int ZERO_EXTEND_L_W(int reg) +static INLINE int ZERO_EXTEND_L_W(int reg) { if (reg & 8) addbyte(0x41); @@ -3525,7 +3525,7 @@ static inline int ZERO_EXTEND_L_W(int reg) return REG_EAX; } -static inline int SIGN_EXTEND_W_B(int reg) +static INLINE int SIGN_EXTEND_W_B(int reg) { if (reg & 0x10) { @@ -3547,7 +3547,7 @@ static inline int SIGN_EXTEND_W_B(int reg) return REG_EAX; } -static inline int SIGN_EXTEND_L_B(int reg) +static INLINE int SIGN_EXTEND_L_B(int reg) { if (reg & 0x10) { @@ -3569,7 +3569,7 @@ static inline int SIGN_EXTEND_L_B(int reg) return REG_EAX; } -static inline int SIGN_EXTEND_L_W(int reg) +static INLINE int SIGN_EXTEND_L_W(int reg) { if (reg & 8) addbyte(0x41); @@ -3580,7 +3580,7 @@ static inline int SIGN_EXTEND_L_W(int reg) return REG_EAX; } -static inline void SHL_B_IMM(int reg, int count) +static INLINE void SHL_B_IMM(int reg, int count) { if (reg & 0x10) { @@ -3603,7 +3603,7 @@ static inline void SHL_B_IMM(int reg, int count) addbyte(count); } } -static inline void SHL_W_IMM(int reg, int count) +static INLINE void SHL_W_IMM(int reg, int count) { addbyte(0x66); /*SHL reg, count*/ if (reg & 8) @@ -3612,7 +3612,7 @@ static inline void SHL_W_IMM(int reg, int count) addbyte(0xc0 | (reg & 7) | 0x20); addbyte(count); } -static inline void SHL_L_IMM(int reg, int count) +static INLINE void SHL_L_IMM(int reg, int count) { if (reg & 8) addbyte(0x41); @@ -3620,7 +3620,7 @@ static inline void SHL_L_IMM(int reg, int count) addbyte(0xc0 | (reg & 7) | 0x20); addbyte(count); } -static inline void SHR_B_IMM(int reg, int count) +static INLINE void SHR_B_IMM(int reg, int count) { if (reg & 0x10) { @@ -3643,7 +3643,7 @@ static inline void SHR_B_IMM(int reg, int count) addbyte(count); } } -static inline void SHR_W_IMM(int reg, int count) +static INLINE void SHR_W_IMM(int reg, int count) { addbyte(0x66); /*SHR reg, count*/ if (reg & 8) @@ -3652,7 +3652,7 @@ static inline void SHR_W_IMM(int reg, int count) addbyte(0xc0 | (reg & 7) | 0x28); addbyte(count); } -static inline void SHR_L_IMM(int reg, int count) +static INLINE void SHR_L_IMM(int reg, int count) { if (reg & 8) addbyte(0x41); @@ -3660,7 +3660,7 @@ static inline void SHR_L_IMM(int reg, int count) addbyte(0xc0 | (reg & 7) | 0x28); addbyte(count); } -static inline void SAR_B_IMM(int reg, int count) +static INLINE void SAR_B_IMM(int reg, int count) { if (reg & 0x10) { @@ -3683,7 +3683,7 @@ static inline void SAR_B_IMM(int reg, int count) addbyte(count); } } -static inline void SAR_W_IMM(int reg, int count) +static INLINE void SAR_W_IMM(int reg, int count) { addbyte(0x66); /*SAR reg, count*/ if (reg & 8) @@ -3692,7 +3692,7 @@ static inline void SAR_W_IMM(int reg, int count) addbyte(0xc0 | (reg & 7) | 0x38); addbyte(count); } -static inline void SAR_L_IMM(int reg, int count) +static INLINE void SAR_L_IMM(int reg, int count) { if (reg & 8) addbyte(0x41); @@ -3701,7 +3701,7 @@ static inline void SAR_L_IMM(int reg, int count) addbyte(count); } -static inline void NEG_HOST_REG_B(int reg) +static INLINE void NEG_HOST_REG_B(int reg) { if (reg & 0x10) { @@ -3724,7 +3724,7 @@ static inline void NEG_HOST_REG_B(int reg) addbyte(0xd8 | (reg & 7)); } } -static inline void NEG_HOST_REG_W(int reg) +static INLINE void NEG_HOST_REG_W(int reg) { addbyte(0x66); if (reg & 8) @@ -3732,7 +3732,7 @@ static inline void NEG_HOST_REG_W(int reg) addbyte(0xf7); addbyte(0xd8 | (reg & 7)); } -static inline void NEG_HOST_REG_L(int reg) +static INLINE void NEG_HOST_REG_L(int reg) { if (reg & 8) addbyte(0x41); @@ -3741,7 +3741,7 @@ static inline void NEG_HOST_REG_L(int reg) } -static inline void FP_ENTER() +static INLINE void FP_ENTER() { if (codegen_fpu_entered) return; @@ -3776,7 +3776,7 @@ static inline void FP_ENTER() codegen_fpu_entered = 1; } -static inline void FP_FXCH(int reg) +static INLINE void FP_FXCH(int reg) { addbyte(0x8b); /*MOV EAX, [TOP]*/ addbyte(0x45); @@ -3853,7 +3853,7 @@ static inline void FP_FXCH(int reg) -static inline void FP_FLD(int reg) +static INLINE void FP_FLD(int reg) { addbyte(0x8b); /*MOV EAX, [TOP]*/ addbyte(0x45); @@ -3916,7 +3916,7 @@ static inline void FP_FLD(int reg) addbyte((uint8_t)cpu_state_offset(TOP)); } -static inline void FP_FST(int reg) +static INLINE void FP_FST(int reg) { addbyte(0x8b); /*MOV EAX, [TOP]*/ addbyte(0x45); @@ -3952,7 +3952,7 @@ static inline void FP_FST(int reg) addbyte((uint8_t)cpu_state_offset(tag)); } -static inline void FP_POP() +static INLINE void FP_POP() { addbyte(0x8b); /*MOV EAX, [TOP]*/ addbyte(0x45); @@ -3972,7 +3972,7 @@ static inline void FP_POP() addbyte(0x45); addbyte((uint8_t)cpu_state_offset(TOP)); } -static inline void FP_POP2() +static INLINE void FP_POP2() { addbyte(0x8b); /*MOV EAX, [TOP]*/ addbyte(0x45); @@ -3993,7 +3993,7 @@ static inline void FP_POP2() addbyte((uint8_t)cpu_state_offset(TOP)); } -static inline void FP_LOAD_S() +static INLINE void FP_LOAD_S() { addbyte(0x8b); /*MOV EBX, TOP*/ addbyte(0x5d); @@ -4029,7 +4029,7 @@ static inline void FP_LOAD_S() addbyte(0x1d); addbyte((uint8_t)cpu_state_offset(tag)); } -static inline void FP_LOAD_D() +static INLINE void FP_LOAD_D() { addbyte(0x8b); /*MOV EBX, TOP*/ addbyte(0x5d); @@ -4058,7 +4058,7 @@ static inline void FP_LOAD_D() addbyte((uint8_t)cpu_state_offset(tag)); } -static inline void FP_LOAD_IW() +static INLINE void FP_LOAD_IW() { addbyte(0x8b); /*MOV EBX, TOP*/ addbyte(0x5d); @@ -4093,7 +4093,7 @@ static inline void FP_LOAD_IW() addbyte(0x1d); addbyte((uint8_t)cpu_state_offset(tag)); } -static inline void FP_LOAD_IL() +static INLINE void FP_LOAD_IL() { addbyte(0x8b); /*MOV EBX, TOP*/ addbyte(0x5d); @@ -4125,7 +4125,7 @@ static inline void FP_LOAD_IL() addbyte(0x1d); addbyte((uint8_t)cpu_state_offset(tag)); } -static inline void FP_LOAD_IQ() +static INLINE void FP_LOAD_IQ() { addbyte(0x8b); /*MOV EBX, TOP*/ addbyte(0x5d); @@ -4169,7 +4169,7 @@ static inline void FP_LOAD_IQ() addbyte((uint8_t)cpu_state_offset(tag)); } -static inline void FP_LOAD_IMM_Q(uint64_t v) +static INLINE void FP_LOAD_IMM_Q(uint64_t v) { addbyte(0x8b); /*MOV EBX, TOP*/ addbyte(0x5d); @@ -4200,7 +4200,7 @@ static inline void FP_LOAD_IMM_Q(uint64_t v) addbyte(v ? 0 : 1); } -static inline void FP_FCHS() +static INLINE void FP_FCHS() { addbyte(0x8b); /*MOV EAX, TOP*/ addbyte(0x45); @@ -4228,7 +4228,7 @@ static inline void FP_FCHS() addbyte((uint8_t)cpu_state_offset(ST)); } -static inline int FP_LOAD_REG(int reg) +static INLINE int FP_LOAD_REG(int reg) { addbyte(0x8b); /*MOV EBX, TOP*/ addbyte(0x5d); @@ -4259,7 +4259,7 @@ static inline int FP_LOAD_REG(int reg) return REG_EBX; } -static inline void FP_LOAD_REG_D(int reg, int *host_reg1, int *host_reg2) +static INLINE void FP_LOAD_REG_D(int reg, int *host_reg1, int *host_reg2) { addbyte(0x8b); /*MOV EBX, TOP*/ addbyte(0x5d); @@ -4281,7 +4281,7 @@ static inline void FP_LOAD_REG_D(int reg, int *host_reg1, int *host_reg2) *host_reg1 = REG_EBX; } -static inline int64_t x87_fround(double b) +static INLINE int64_t x87_fround(double b) { int64_t a, c; @@ -4306,7 +4306,7 @@ static inline int64_t x87_fround(double b) return 0; } -static inline int FP_LOAD_REG_INT_W(int reg) +static INLINE int FP_LOAD_REG_INT_W(int reg) { addbyte(0x89); /*MOV EBX, EAX*/ addbyte(0xc3); @@ -4336,7 +4336,7 @@ static inline int FP_LOAD_REG_INT_W(int reg) return REG_EBX; } -static inline int FP_LOAD_REG_INT(int reg) +static INLINE int FP_LOAD_REG_INT(int reg) { addbyte(0x89); /*MOV EBX, EAX*/ addbyte(0xc3); @@ -4366,7 +4366,7 @@ static inline int FP_LOAD_REG_INT(int reg) return REG_EBX; } -static inline void FP_LOAD_REG_INT_Q(int reg, int *host_reg1, int *host_reg2) +static INLINE void FP_LOAD_REG_INT_Q(int reg, int *host_reg1, int *host_reg2) { addbyte(0x89); /*MOV EBX, EAX*/ addbyte(0xc3); @@ -4443,7 +4443,7 @@ static inline void FP_LOAD_REG_INT_Q(int reg, int *host_reg1, int *host_reg2) #define FPU_SUB 2 #define FPU_SUBR 3 -static inline void FP_OP_REG(int op, int dst, int src) +static INLINE void FP_OP_REG(int op, int dst, int src) { addbyte(0x8b); /*MOV EAX, [TOP]*/ addbyte(0x45); @@ -4550,7 +4550,7 @@ static inline void FP_OP_REG(int op, int dst, int src) addbyte((uint8_t)cpu_state_offset(ST)); } -static inline void FP_OP_MEM(int op) +static INLINE void FP_OP_MEM(int op) { addbyte(0x8b); /*MOV EAX, [TOP]*/ addbyte(0x45); @@ -4626,7 +4626,7 @@ static inline void FP_OP_MEM(int op) } } -static inline void FP_OP_S(int op) +static INLINE void FP_OP_S(int op) { addbyte(0x66); /*MOVD XMM1, EAX*/ addbyte(0x0f); @@ -4638,7 +4638,7 @@ static inline void FP_OP_S(int op) addbyte(0xc9); FP_OP_MEM(op); } -static inline void FP_OP_D(int op) +static INLINE void FP_OP_D(int op) { addbyte(0x66); /*MOVQ XMM1, RAX*/ addbyte(0x48); @@ -4680,7 +4680,7 @@ static inline void FP_OP_D(int op) addbyte(0x08); } } -static inline void FP_OP_IW(int op) +static INLINE void FP_OP_IW(int op) { addbyte(0x0f); /*MOVSX EAX, AX*/ addbyte(0xbf); @@ -4691,7 +4691,7 @@ static inline void FP_OP_IW(int op) addbyte(0xc8); FP_OP_MEM(op); } -static inline void FP_OP_IL(int op) +static INLINE void FP_OP_IL(int op) { addbyte(0xf2); /*CVTSI2SD XMM1, EAX*/ addbyte(0x0f); @@ -4705,7 +4705,7 @@ static inline void FP_OP_IL(int op) #define C2 (1<<10) #define C3 (1<<14) -static inline void FP_COMPARE_REG(int dst, int src) +static INLINE void FP_COMPARE_REG(int dst, int src) { addbyte(0x8b); /*MOV EAX, [TOP]*/ addbyte(0x45); @@ -4771,7 +4771,7 @@ static inline void FP_COMPARE_REG(int dst, int src) addbyte((uint8_t)cpu_state_offset(npxs) + 1); } -static inline void FP_COMPARE_MEM() +static INLINE void FP_COMPARE_MEM() { addbyte(0x8b); /*MOV EAX, [TOP]*/ addbyte(0x45); @@ -4803,7 +4803,7 @@ static inline void FP_COMPARE_MEM() addbyte(0x4d); addbyte((uint8_t)cpu_state_offset(npxs) + 1); } -static inline void FP_COMPARE_S() +static INLINE void FP_COMPARE_S() { addbyte(0x66); /*MOVD XMM1, EAX*/ addbyte(0x0f); @@ -4815,7 +4815,7 @@ static inline void FP_COMPARE_S() addbyte(0xc9); FP_COMPARE_MEM(); } -static inline void FP_COMPARE_D() +static INLINE void FP_COMPARE_D() { addbyte(0x66); /*MOVQ XMM1, RAX*/ addbyte(0x48); @@ -4824,7 +4824,7 @@ static inline void FP_COMPARE_D() addbyte(0xc8); FP_COMPARE_MEM(); } -static inline void FP_COMPARE_IW() +static INLINE void FP_COMPARE_IW() { addbyte(0x0f); /*MOVSX EAX, AX*/ addbyte(0xbf); @@ -4835,7 +4835,7 @@ static inline void FP_COMPARE_IW() addbyte(0xc8); FP_COMPARE_MEM(); } -static inline void FP_COMPARE_IL() +static INLINE void FP_COMPARE_IL() { addbyte(0xf2); /*CVTSI2SD XMM1, EAX*/ addbyte(0x0f); @@ -4844,11 +4844,11 @@ static inline void FP_COMPARE_IL() FP_COMPARE_MEM(); } -static inline void UPDATE_NPXC(int reg) +static INLINE void UPDATE_NPXC(int reg) { } -static inline void SET_BITS(uintptr_t addr, uint32_t val) +static INLINE void SET_BITS(uintptr_t addr, uint32_t val) { if (IS_32_ADDR(addr)) { @@ -4889,7 +4889,7 @@ static inline void SET_BITS(uintptr_t addr, uint32_t val) } } -static inline void CLEAR_BITS(uintptr_t addr, uint32_t val) +static INLINE void CLEAR_BITS(uintptr_t addr, uint32_t val) { if (IS_32_ADDR(addr)) { @@ -4933,7 +4933,7 @@ static inline void CLEAR_BITS(uintptr_t addr, uint32_t val) #define LOAD_Q_REG_1 REG_EAX #define LOAD_Q_REG_2 REG_EDX -static inline void MMX_ENTER() +static INLINE void MMX_ENTER() { if (codegen_mmx_entered) return; @@ -4988,7 +4988,7 @@ static inline void MMX_ENTER() extern int mmx_ebx_ecx_loaded; -static inline int LOAD_MMX_D(int guest_reg) +static INLINE int LOAD_MMX_D(int guest_reg) { int host_reg = REG_EBX; @@ -4999,7 +4999,7 @@ static inline int LOAD_MMX_D(int guest_reg) return host_reg; } -static inline void LOAD_MMX_Q(int guest_reg, int *host_reg1, int *host_reg2) +static INLINE void LOAD_MMX_Q(int guest_reg, int *host_reg1, int *host_reg2) { int host_reg = REG_EBX; @@ -5014,7 +5014,7 @@ static inline void LOAD_MMX_Q(int guest_reg, int *host_reg1, int *host_reg2) *host_reg1 = host_reg; } -static inline int LOAD_MMX_Q_MMX(int guest_reg) +static INLINE int LOAD_MMX_Q_MMX(int guest_reg) { int dst_reg = find_host_xmm_reg(); host_reg_xmm_mapping[dst_reg] = 100; @@ -5029,7 +5029,7 @@ static inline int LOAD_MMX_Q_MMX(int guest_reg) return dst_reg; } -static inline int LOAD_INT_TO_MMX(int src_reg1, int src_reg2) +static INLINE int LOAD_INT_TO_MMX(int src_reg1, int src_reg2) { int dst_reg = find_host_xmm_reg(); host_reg_xmm_mapping[dst_reg] = 100; @@ -5046,7 +5046,7 @@ static inline int LOAD_INT_TO_MMX(int src_reg1, int src_reg2) return dst_reg; } -static inline void STORE_MMX_LQ(int guest_reg, int host_reg1) +static INLINE void STORE_MMX_LQ(int guest_reg, int host_reg1) { addbyte(0xC7); /*MOVL [reg],0*/ addbyte(0x44); @@ -5060,7 +5060,7 @@ static inline void STORE_MMX_LQ(int guest_reg, int host_reg1) addbyte(0x25); addbyte((uint8_t)cpu_state_offset(MM[guest_reg].l[0])); } -static inline void STORE_MMX_Q(int guest_reg, int host_reg1, int host_reg2) +static INLINE void STORE_MMX_Q(int guest_reg, int host_reg1, int host_reg2) { if (host_reg1 & 8) addbyte(0x4c); @@ -5071,7 +5071,7 @@ static inline void STORE_MMX_Q(int guest_reg, int host_reg1, int host_reg2) addbyte(0x25); addbyte((uint8_t)cpu_state_offset(MM[guest_reg].l[0])); } -static inline void STORE_MMX_Q_MMX(int guest_reg, int host_reg) +static INLINE void STORE_MMX_Q_MMX(int guest_reg, int host_reg) { addbyte(0x66); /*MOVQ [guest_reg],host_reg*/ addbyte(0x0f); @@ -5082,7 +5082,7 @@ static inline void STORE_MMX_Q_MMX(int guest_reg, int host_reg) } #define MMX_x86_OP(name, opcode) \ -static inline void MMX_ ## name(int dst_reg, int src_reg) \ +static INLINE void MMX_ ## name(int dst_reg, int src_reg) \ { \ addbyte(0x66); /*op dst_reg, src_reg*/ \ addbyte(0x0f); \ @@ -5135,7 +5135,7 @@ MMX_x86_OP(PMULLW, 0xd5); MMX_x86_OP(PMULHW, 0xe5); MMX_x86_OP(PMADDWD, 0xf5); -static inline void MMX_PACKSSWB(int dst_reg, int src_reg) +static INLINE void MMX_PACKSSWB(int dst_reg, int src_reg) { addbyte(0x66); /*PACKSSWB dst_reg, src_reg*/ addbyte(0x0f); @@ -5147,7 +5147,7 @@ static inline void MMX_PACKSSWB(int dst_reg, int src_reg) addbyte(0xc0 | (dst_reg << 3) | dst_reg); addbyte(0x08); } -static inline void MMX_PACKUSWB(int dst_reg, int src_reg) +static INLINE void MMX_PACKUSWB(int dst_reg, int src_reg) { addbyte(0x66); /*PACKUSWB dst_reg, src_reg*/ addbyte(0x0f); @@ -5159,7 +5159,7 @@ static inline void MMX_PACKUSWB(int dst_reg, int src_reg) addbyte(0xc0 | (dst_reg << 3) | dst_reg); addbyte(0x08); } -static inline void MMX_PACKSSDW(int dst_reg, int src_reg) +static INLINE void MMX_PACKSSDW(int dst_reg, int src_reg) { addbyte(0x66); /*PACKSSDW dst_reg, src_reg*/ addbyte(0x0f); @@ -5171,7 +5171,7 @@ static inline void MMX_PACKSSDW(int dst_reg, int src_reg) addbyte(0xc0 | (dst_reg << 3) | dst_reg); addbyte(0x08); } -static inline void MMX_PUNPCKHBW(int dst_reg, int src_reg) +static INLINE void MMX_PUNPCKHBW(int dst_reg, int src_reg) { addbyte(0x66); /*PUNPCKLBW dst_reg, src_reg*/ addbyte(0x0f); @@ -5183,7 +5183,7 @@ static inline void MMX_PUNPCKHBW(int dst_reg, int src_reg) addbyte(0xc0 | (dst_reg << 3) | dst_reg); addbyte(0x0e); } -static inline void MMX_PUNPCKHWD(int dst_reg, int src_reg) +static INLINE void MMX_PUNPCKHWD(int dst_reg, int src_reg) { addbyte(0x66); /*PUNPCKLWD dst_reg, src_reg*/ addbyte(0x0f); @@ -5195,7 +5195,7 @@ static inline void MMX_PUNPCKHWD(int dst_reg, int src_reg) addbyte(0xc0 | (dst_reg << 3) | dst_reg); addbyte(0x0e); } -static inline void MMX_PUNPCKHDQ(int dst_reg, int src_reg) +static INLINE void MMX_PUNPCKHDQ(int dst_reg, int src_reg) { addbyte(0x66); /*PUNPCKLDQ dst_reg, src_reg*/ addbyte(0x0f); @@ -5208,7 +5208,7 @@ static inline void MMX_PUNPCKHDQ(int dst_reg, int src_reg) addbyte(0x0e); } -static inline void MMX_PSRLW_imm(int dst_reg, int amount) +static INLINE void MMX_PSRLW_imm(int dst_reg, int amount) { addbyte(0x66); /*PSRLW dst_reg, amount*/ addbyte(0x0f); @@ -5216,7 +5216,7 @@ static inline void MMX_PSRLW_imm(int dst_reg, int amount) addbyte(0xc0 | dst_reg | 0x10); addbyte(amount); } -static inline void MMX_PSRAW_imm(int dst_reg, int amount) +static INLINE void MMX_PSRAW_imm(int dst_reg, int amount) { addbyte(0x66); /*PSRAW dst_reg, amount*/ addbyte(0x0f); @@ -5224,7 +5224,7 @@ static inline void MMX_PSRAW_imm(int dst_reg, int amount) addbyte(0xc0 | dst_reg | 0x20); addbyte(amount); } -static inline void MMX_PSLLW_imm(int dst_reg, int amount) +static INLINE void MMX_PSLLW_imm(int dst_reg, int amount) { addbyte(0x66); /*PSLLW dst_reg, amount*/ addbyte(0x0f); @@ -5233,7 +5233,7 @@ static inline void MMX_PSLLW_imm(int dst_reg, int amount) addbyte(amount); } -static inline void MMX_PSRLD_imm(int dst_reg, int amount) +static INLINE void MMX_PSRLD_imm(int dst_reg, int amount) { addbyte(0x66); /*PSRLD dst_reg, amount*/ addbyte(0x0f); @@ -5241,7 +5241,7 @@ static inline void MMX_PSRLD_imm(int dst_reg, int amount) addbyte(0xc0 | dst_reg | 0x10); addbyte(amount); } -static inline void MMX_PSRAD_imm(int dst_reg, int amount) +static INLINE void MMX_PSRAD_imm(int dst_reg, int amount) { addbyte(0x66); /*PSRAD dst_reg, amount*/ addbyte(0x0f); @@ -5249,7 +5249,7 @@ static inline void MMX_PSRAD_imm(int dst_reg, int amount) addbyte(0xc0 | dst_reg | 0x20); addbyte(amount); } -static inline void MMX_PSLLD_imm(int dst_reg, int amount) +static INLINE void MMX_PSLLD_imm(int dst_reg, int amount) { addbyte(0x66); /*PSLLD dst_reg, amount*/ addbyte(0x0f); @@ -5258,7 +5258,7 @@ static inline void MMX_PSLLD_imm(int dst_reg, int amount) addbyte(amount); } -static inline void MMX_PSRLQ_imm(int dst_reg, int amount) +static INLINE void MMX_PSRLQ_imm(int dst_reg, int amount) { addbyte(0x66); /*PSRLQ dst_reg, amount*/ addbyte(0x0f); @@ -5266,7 +5266,7 @@ static inline void MMX_PSRLQ_imm(int dst_reg, int amount) addbyte(0xc0 | dst_reg | 0x10); addbyte(amount); } -static inline void MMX_PSRAQ_imm(int dst_reg, int amount) +static INLINE void MMX_PSRAQ_imm(int dst_reg, int amount) { addbyte(0x66); /*PSRAQ dst_reg, amount*/ addbyte(0x0f); @@ -5274,7 +5274,7 @@ static inline void MMX_PSRAQ_imm(int dst_reg, int amount) addbyte(0xc0 | dst_reg | 0x20); addbyte(amount); } -static inline void MMX_PSLLQ_imm(int dst_reg, int amount) +static INLINE void MMX_PSLLQ_imm(int dst_reg, int amount) { addbyte(0x66); /*PSLLQ dst_reg, amount*/ addbyte(0x0f); @@ -5284,14 +5284,14 @@ static inline void MMX_PSLLQ_imm(int dst_reg, int amount) } -static inline void SAVE_EA() +static INLINE void SAVE_EA() { addbyte(0x89); /*MOV [ESP+0x24], EAX*/ addbyte(0x44); addbyte(0x24); addbyte(0x24); } -static inline void LOAD_EA() +static INLINE void LOAD_EA() { addbyte(0x8b); /*MOV EAX, [ESP+0x24]*/ addbyte(0x44); @@ -5301,7 +5301,7 @@ static inline void LOAD_EA() #define MEM_CHECK_WRITE_B MEM_CHECK_WRITE -static inline void MEM_CHECK_WRITE(x86seg *seg) +static INLINE void MEM_CHECK_WRITE(x86seg *seg) { uint8_t *jump1, *jump2, *jump3 = NULL; @@ -5415,7 +5415,7 @@ static inline void MEM_CHECK_WRITE(x86seg *seg) LOAD_EA(); } -static inline void MEM_CHECK_WRITE_W(x86seg *seg) +static INLINE void MEM_CHECK_WRITE_W(x86seg *seg) { uint8_t *jump1, *jump2, *jump3, *jump4 = NULL; int jump_pos; @@ -5564,7 +5564,7 @@ static inline void MEM_CHECK_WRITE_W(x86seg *seg) LOAD_EA(); } -static inline void MEM_CHECK_WRITE_L(x86seg *seg) +static INLINE void MEM_CHECK_WRITE_L(x86seg *seg) { uint8_t *jump1, *jump2, *jump3, *jump4 = NULL; int jump_pos; @@ -5713,7 +5713,7 @@ static inline void MEM_CHECK_WRITE_L(x86seg *seg) LOAD_EA(); } -static inline int MEM_LOAD_ADDR_EA_B_NO_ABRT(x86seg *seg) +static INLINE int MEM_LOAD_ADDR_EA_B_NO_ABRT(x86seg *seg) { if ((seg == &_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) { @@ -5785,7 +5785,7 @@ static inline int MEM_LOAD_ADDR_EA_B_NO_ABRT(x86seg *seg) return REG_ECX; } -static inline int MEM_LOAD_ADDR_EA_W_NO_ABRT(x86seg *seg) +static INLINE int MEM_LOAD_ADDR_EA_W_NO_ABRT(x86seg *seg) { if ((seg == &_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) { @@ -5863,7 +5863,7 @@ static inline int MEM_LOAD_ADDR_EA_W_NO_ABRT(x86seg *seg) return REG_ECX; } -static inline int MEM_LOAD_ADDR_EA_L_NO_ABRT(x86seg *seg) +static INLINE int MEM_LOAD_ADDR_EA_L_NO_ABRT(x86seg *seg) { if ((seg == &_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) { @@ -5941,7 +5941,7 @@ static inline int MEM_LOAD_ADDR_EA_L_NO_ABRT(x86seg *seg) return REG_ECX; } -static inline void MEM_STORE_ADDR_EA_B_NO_ABRT(x86seg *seg, int host_reg) +static INLINE void MEM_STORE_ADDR_EA_B_NO_ABRT(x86seg *seg, int host_reg) { if (host_reg & 0x10) { @@ -6040,7 +6040,7 @@ static inline void MEM_STORE_ADDR_EA_B_NO_ABRT(x86seg *seg, int host_reg) call_long((uintptr_t)writememb386l); /*done:*/ } -static inline void MEM_STORE_ADDR_EA_W_NO_ABRT(x86seg *seg, int host_reg) +static INLINE void MEM_STORE_ADDR_EA_W_NO_ABRT(x86seg *seg, int host_reg) { if ((seg == &_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) { @@ -6124,7 +6124,7 @@ static inline void MEM_STORE_ADDR_EA_W_NO_ABRT(x86seg *seg, int host_reg) call_long((uintptr_t)writememwl); /*done:*/ } -static inline void MEM_STORE_ADDR_EA_L_NO_ABRT(x86seg *seg, int host_reg) +static INLINE void MEM_STORE_ADDR_EA_L_NO_ABRT(x86seg *seg, int host_reg) { if ((seg == &_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) { @@ -6207,7 +6207,7 @@ static inline void MEM_STORE_ADDR_EA_L_NO_ABRT(x86seg *seg, int host_reg) /*done:*/ } -static inline void LOAD_SEG(int host_reg, void *seg) +static INLINE void LOAD_SEG(int host_reg, void *seg) { load_param_2_64(&codeblock[block_current], (uint64_t)seg); load_param_1_reg_32(host_reg); diff --git a/src/cpu/codegen_ops_x86.h b/src/cpu/codegen_ops_x86.h index 9e65016..f4612b7 100644 --- a/src/cpu/codegen_ops_x86.h +++ b/src/cpu/codegen_ops_x86.h @@ -45,7 +45,7 @@ #define HOST_REG_END 4 #define HOST_REG_XMM_START 0 #define HOST_REG_XMM_END 7 -static inline int find_host_reg() +static INLINE int find_host_reg() { int c; for (c = HOST_REG_START; c < HOST_REG_END; c++) @@ -58,7 +58,7 @@ static inline int find_host_reg() fatal("Out of host regs!\n"); return c; } -static inline int find_host_xmm_reg() +static INLINE int find_host_xmm_reg() { int c; for (c = HOST_REG_XMM_START; c < HOST_REG_XMM_END; c++) @@ -73,14 +73,14 @@ static inline int find_host_xmm_reg() } #if 0 -static inline void STORE_IMM_ADDR_B(uintptr_t addr, uint8_t val) +static INLINE void STORE_IMM_ADDR_B(uintptr_t addr, uint8_t val) { addbyte(0xC6); /*MOVB [addr],val*/ addbyte(0x05); addlong(addr); addbyte(val); } -static inline void STORE_IMM_ADDR_W(uintptr_t addr, uint16_t val) +static INLINE void STORE_IMM_ADDR_W(uintptr_t addr, uint16_t val) { addbyte(0x66); /*MOVW [addr],val*/ addbyte(0xC7); @@ -89,7 +89,7 @@ static inline void STORE_IMM_ADDR_W(uintptr_t addr, uint16_t val) addword(val); } #endif -static inline void STORE_IMM_ADDR_L(uintptr_t addr, uint32_t val) +static INLINE void STORE_IMM_ADDR_L(uintptr_t addr, uint32_t val) { if (addr >= (uintptr_t)&cpu_state && addr < ((uintptr_t)&cpu_state)+0x100) { @@ -107,7 +107,7 @@ static inline void STORE_IMM_ADDR_L(uintptr_t addr, uint32_t val) } } -static inline void STORE_IMM_REG_B(int reg, uint8_t val) +static INLINE void STORE_IMM_REG_B(int reg, uint8_t val) { addbyte(0xC6); /*MOVB [addr],val*/ addbyte(0x45); @@ -117,7 +117,7 @@ static inline void STORE_IMM_REG_B(int reg, uint8_t val) addbyte((uint8_t)cpu_state_offset(regs[reg & 3].b.l)); addbyte(val); } -static inline void STORE_IMM_REG_W(int reg, uint16_t val) +static INLINE void STORE_IMM_REG_W(int reg, uint16_t val) { addbyte(0x66); /*MOVW [addr],val*/ addbyte(0xC7); @@ -125,7 +125,7 @@ static inline void STORE_IMM_REG_W(int reg, uint16_t val) addbyte((uint8_t)cpu_state_offset(regs[reg & 7].w)); addword(val); } -static inline void STORE_IMM_REG_L(int reg, uint32_t val) +static INLINE void STORE_IMM_REG_L(int reg, uint32_t val) { addbyte(0xC7); /*MOVL [addr],val*/ addbyte(0x45); @@ -133,7 +133,7 @@ static inline void STORE_IMM_REG_L(int reg, uint32_t val) addlong(val); } -static inline int LOAD_REG_B(int reg) +static INLINE int LOAD_REG_B(int reg) { int host_reg = find_host_reg(); host_reg_mapping[host_reg] = reg; @@ -148,7 +148,7 @@ static inline int LOAD_REG_B(int reg) return host_reg; } -static inline int LOAD_REG_W(int reg) +static INLINE int LOAD_REG_W(int reg) { int host_reg = find_host_reg(); host_reg_mapping[host_reg] = reg; @@ -160,7 +160,7 @@ static inline int LOAD_REG_W(int reg) return host_reg; } -static inline int LOAD_REG_L(int reg) +static INLINE int LOAD_REG_L(int reg) { int host_reg = find_host_reg(); host_reg_mapping[host_reg] = reg; @@ -172,7 +172,7 @@ static inline int LOAD_REG_L(int reg) return host_reg; } -static inline int LOAD_VAR_W(uintptr_t addr) +static INLINE int LOAD_VAR_W(uintptr_t addr) { int host_reg = find_host_reg(); host_reg_mapping[host_reg] = 0; @@ -184,7 +184,7 @@ static inline int LOAD_VAR_W(uintptr_t addr) return host_reg; } -static inline int LOAD_VAR_WL(uintptr_t addr) +static INLINE int LOAD_VAR_WL(uintptr_t addr) { int host_reg = find_host_reg(); host_reg_mapping[host_reg] = 0; @@ -196,7 +196,7 @@ static inline int LOAD_VAR_WL(uintptr_t addr) return host_reg; } -static inline int LOAD_VAR_L(uintptr_t addr) +static INLINE int LOAD_VAR_L(uintptr_t addr) { int host_reg = find_host_reg(); host_reg_mapping[host_reg] = 0; @@ -208,7 +208,7 @@ static inline int LOAD_VAR_L(uintptr_t addr) return host_reg; } -static inline int LOAD_REG_IMM(uint32_t imm) +static INLINE int LOAD_REG_IMM(uint32_t imm) { int host_reg = find_host_reg(); host_reg_mapping[host_reg] = 0; @@ -220,7 +220,7 @@ static inline int LOAD_REG_IMM(uint32_t imm) return host_reg; } -static inline int LOAD_HOST_REG(int host_reg) +static INLINE int LOAD_HOST_REG(int host_reg) { int new_host_reg = find_host_reg(); host_reg_mapping[new_host_reg] = 0; @@ -231,7 +231,7 @@ static inline int LOAD_HOST_REG(int host_reg) return new_host_reg; } -static inline void STORE_REG_B_RELEASE(int host_reg) +static INLINE void STORE_REG_B_RELEASE(int host_reg) { addbyte(0x88); /*MOVB [reg],host_reg*/ addbyte(0x45 | (host_reg << 3)); @@ -241,7 +241,7 @@ static inline void STORE_REG_B_RELEASE(int host_reg) addbyte((uint8_t)cpu_state_offset(regs[host_reg_mapping[host_reg] & 3].b.l)); host_reg_mapping[host_reg] = -1; } -static inline void STORE_REG_W_RELEASE(int host_reg) +static INLINE void STORE_REG_W_RELEASE(int host_reg) { addbyte(0x66); /*MOVW [reg],host_reg*/ addbyte(0x89); @@ -249,7 +249,7 @@ static inline void STORE_REG_W_RELEASE(int host_reg) addbyte((uint8_t)cpu_state_offset(regs[host_reg_mapping[host_reg]].w)); host_reg_mapping[host_reg] = -1; } -static inline void STORE_REG_L_RELEASE(int host_reg) +static INLINE void STORE_REG_L_RELEASE(int host_reg) { addbyte(0x89); /*MOVL [reg],host_reg*/ addbyte(0x45 | (host_reg << 3)); @@ -257,7 +257,7 @@ static inline void STORE_REG_L_RELEASE(int host_reg) host_reg_mapping[host_reg] = -1; } -static inline void STORE_REG_TARGET_B_RELEASE(int host_reg, int guest_reg) +static INLINE void STORE_REG_TARGET_B_RELEASE(int host_reg, int guest_reg) { addbyte(0x88); /*MOVB [guest_reg],host_reg*/ addbyte(0x45 | (host_reg << 3)); @@ -267,7 +267,7 @@ static inline void STORE_REG_TARGET_B_RELEASE(int host_reg, int guest_reg) addbyte((uint8_t)cpu_state_offset(regs[guest_reg & 3].b.l)); host_reg_mapping[host_reg] = -1; } -static inline void STORE_REG_TARGET_W_RELEASE(int host_reg, int guest_reg) +static INLINE void STORE_REG_TARGET_W_RELEASE(int host_reg, int guest_reg) { addbyte(0x66); /*MOVW [guest_reg],host_reg*/ addbyte(0x89); @@ -275,7 +275,7 @@ static inline void STORE_REG_TARGET_W_RELEASE(int host_reg, int guest_reg) addbyte((uint8_t)cpu_state_offset(regs[guest_reg & 7].w)); host_reg_mapping[host_reg] = -1; } -static inline void STORE_REG_TARGET_L_RELEASE(int host_reg, int guest_reg) +static INLINE void STORE_REG_TARGET_L_RELEASE(int host_reg, int guest_reg) { addbyte(0x89); /*MOVL [guest_reg],host_reg*/ addbyte(0x45 | (host_reg << 3)); @@ -283,12 +283,12 @@ static inline void STORE_REG_TARGET_L_RELEASE(int host_reg, int guest_reg) host_reg_mapping[host_reg] = -1; } -static inline void RELEASE_REG(int host_reg) +static INLINE void RELEASE_REG(int host_reg) { host_reg_mapping[host_reg] = -1; } -static inline void STORE_HOST_REG_ADDR_W(uintptr_t addr, int host_reg) +static INLINE void STORE_HOST_REG_ADDR_W(uintptr_t addr, int host_reg) { if (addr >= (uintptr_t)&cpu_state && addr < ((uintptr_t)&cpu_state)+0x100) { @@ -305,7 +305,7 @@ static inline void STORE_HOST_REG_ADDR_W(uintptr_t addr, int host_reg) addlong(addr); } } -static inline void STORE_HOST_REG_ADDR(uintptr_t addr, int host_reg) +static INLINE void STORE_HOST_REG_ADDR(uintptr_t addr, int host_reg) { if (addr >= (uintptr_t)&cpu_state && addr < ((uintptr_t)&cpu_state)+0x100) { @@ -323,29 +323,29 @@ static inline void STORE_HOST_REG_ADDR(uintptr_t addr, int host_reg) #define STORE_HOST_REG_ADDR_BL STORE_HOST_REG_ADDR #define STORE_HOST_REG_ADDR_WL STORE_HOST_REG_ADDR -static inline void ADD_HOST_REG_B(int dst_reg, int src_reg) +static INLINE void ADD_HOST_REG_B(int dst_reg, int src_reg) { addbyte(0x00); /*ADDB dst_reg, src_reg*/ addbyte(0xc0 | dst_reg | (src_reg << 3)); } -static inline void ADD_HOST_REG_W(int dst_reg, int src_reg) +static INLINE void ADD_HOST_REG_W(int dst_reg, int src_reg) { addbyte(0x66); /*ADDW dst_reg, src_reg*/ addbyte(0x01); addbyte(0xc0 | dst_reg | (src_reg << 3)); } -static inline void ADD_HOST_REG_L(int dst_reg, int src_reg) +static INLINE void ADD_HOST_REG_L(int dst_reg, int src_reg) { addbyte(0x01); /*ADDL dst_reg, src_reg*/ addbyte(0xc0 | dst_reg | (src_reg << 3)); } -static inline void ADD_HOST_REG_IMM_B(int host_reg, uint8_t imm) +static INLINE void ADD_HOST_REG_IMM_B(int host_reg, uint8_t imm) { addbyte(0x80); /*ADDB host_reg, imm*/ addbyte(0xC0 | host_reg); addbyte(imm); } -static inline void ADD_HOST_REG_IMM_W(int host_reg, uint16_t imm) +static INLINE void ADD_HOST_REG_IMM_W(int host_reg, uint16_t imm) { if (imm < 0x80 || imm >= 0xff80) { @@ -362,7 +362,7 @@ static inline void ADD_HOST_REG_IMM_W(int host_reg, uint16_t imm) addword(imm); } } -static inline void ADD_HOST_REG_IMM(int host_reg, uint32_t imm) +static INLINE void ADD_HOST_REG_IMM(int host_reg, uint32_t imm) { if (imm < 0x80 || imm >= 0xffffff80) { @@ -380,12 +380,12 @@ static inline void ADD_HOST_REG_IMM(int host_reg, uint32_t imm) #define AND_HOST_REG_B AND_HOST_REG_L #define AND_HOST_REG_W AND_HOST_REG_L -static inline void AND_HOST_REG_L(int dst_reg, int src_reg) +static INLINE void AND_HOST_REG_L(int dst_reg, int src_reg) { addbyte(0x21); /*ANDL dst_reg, src_reg*/ addbyte(0xc0 | dst_reg | (src_reg << 3)); } -static inline void AND_HOST_REG_IMM(int host_reg, uint32_t imm) +static INLINE void AND_HOST_REG_IMM(int host_reg, uint32_t imm) { if (imm < 0x80 || imm >= 0xffffff80) { @@ -400,25 +400,25 @@ static inline void AND_HOST_REG_IMM(int host_reg, uint32_t imm) addlong(imm); } } -static inline int TEST_HOST_REG_B(int dst_reg, int src_reg) +static INLINE int TEST_HOST_REG_B(int dst_reg, int src_reg) { AND_HOST_REG_B(dst_reg, src_reg); return dst_reg; } -static inline int TEST_HOST_REG_W(int dst_reg, int src_reg) +static INLINE int TEST_HOST_REG_W(int dst_reg, int src_reg) { AND_HOST_REG_W(dst_reg, src_reg); return dst_reg; } -static inline int TEST_HOST_REG_L(int dst_reg, int src_reg) +static INLINE int TEST_HOST_REG_L(int dst_reg, int src_reg) { AND_HOST_REG_L(dst_reg, src_reg); return dst_reg; } -static inline int TEST_HOST_REG_IMM(int host_reg, uint32_t imm) +static INLINE int TEST_HOST_REG_IMM(int host_reg, uint32_t imm) { AND_HOST_REG_IMM(host_reg, imm); @@ -427,12 +427,12 @@ static inline int TEST_HOST_REG_IMM(int host_reg, uint32_t imm) #define OR_HOST_REG_B OR_HOST_REG_L #define OR_HOST_REG_W OR_HOST_REG_L -static inline void OR_HOST_REG_L(int dst_reg, int src_reg) +static INLINE void OR_HOST_REG_L(int dst_reg, int src_reg) { addbyte(0x09); /*ORL dst_reg, src_reg*/ addbyte(0xc0 | dst_reg | (src_reg << 3)); } -static inline void OR_HOST_REG_IMM(int host_reg, uint32_t imm) +static INLINE void OR_HOST_REG_IMM(int host_reg, uint32_t imm) { if (imm < 0x80 || imm >= 0xffffff80) { @@ -448,46 +448,46 @@ static inline void OR_HOST_REG_IMM(int host_reg, uint32_t imm) } } -static inline void NEG_HOST_REG_B(int reg) +static INLINE void NEG_HOST_REG_B(int reg) { addbyte(0xf6); addbyte(0xd8 | reg); } -static inline void NEG_HOST_REG_W(int reg) +static INLINE void NEG_HOST_REG_W(int reg) { addbyte(0x66); addbyte(0xf7); addbyte(0xd8 | reg); } -static inline void NEG_HOST_REG_L(int reg) +static INLINE void NEG_HOST_REG_L(int reg) { addbyte(0xf7); addbyte(0xd8 | reg); } -static inline void SUB_HOST_REG_B(int dst_reg, int src_reg) +static INLINE void SUB_HOST_REG_B(int dst_reg, int src_reg) { addbyte(0x28); /*SUBB dst_reg, src_reg*/ addbyte(0xc0 | dst_reg | (src_reg << 3)); } -static inline void SUB_HOST_REG_W(int dst_reg, int src_reg) +static INLINE void SUB_HOST_REG_W(int dst_reg, int src_reg) { addbyte(0x66); /*SUBW dst_reg, src_reg*/ addbyte(0x29); addbyte(0xc0 | dst_reg | (src_reg << 3)); } -static inline void SUB_HOST_REG_L(int dst_reg, int src_reg) +static INLINE void SUB_HOST_REG_L(int dst_reg, int src_reg) { addbyte(0x29); /*SUBL dst_reg, src_reg*/ addbyte(0xc0 | dst_reg | (src_reg << 3)); } -static inline void SUB_HOST_REG_IMM_B(int host_reg, uint8_t imm) +static INLINE void SUB_HOST_REG_IMM_B(int host_reg, uint8_t imm) { addbyte(0x80); /*SUBB host_reg, imm*/ addbyte(0xE8 | host_reg); addbyte(imm); } -static inline void SUB_HOST_REG_IMM_W(int host_reg, uint16_t imm) +static INLINE void SUB_HOST_REG_IMM_W(int host_reg, uint16_t imm) { if (imm < 0x80 || imm >= 0xff80) { @@ -504,7 +504,7 @@ static inline void SUB_HOST_REG_IMM_W(int host_reg, uint16_t imm) addword(imm); } } -static inline void SUB_HOST_REG_IMM(int host_reg, uint32_t imm) +static INLINE void SUB_HOST_REG_IMM(int host_reg, uint32_t imm) { if (imm < 0x80 || imm >= 0xffffff80) { @@ -520,37 +520,37 @@ static inline void SUB_HOST_REG_IMM(int host_reg, uint32_t imm) } } -static inline int CMP_HOST_REG_B(int dst_reg, int src_reg) +static INLINE int CMP_HOST_REG_B(int dst_reg, int src_reg) { SUB_HOST_REG_B(dst_reg, src_reg); return dst_reg; } -static inline int CMP_HOST_REG_W(int dst_reg, int src_reg) +static INLINE int CMP_HOST_REG_W(int dst_reg, int src_reg) { SUB_HOST_REG_W(dst_reg, src_reg); return dst_reg; } -static inline int CMP_HOST_REG_L(int dst_reg, int src_reg) +static INLINE int CMP_HOST_REG_L(int dst_reg, int src_reg) { SUB_HOST_REG_L(dst_reg, src_reg); return dst_reg; } -static inline int CMP_HOST_REG_IMM_B(int host_reg, uint8_t imm) +static INLINE int CMP_HOST_REG_IMM_B(int host_reg, uint8_t imm) { SUB_HOST_REG_IMM_B(host_reg, imm); return host_reg; } -static inline int CMP_HOST_REG_IMM_W(int host_reg, uint16_t imm) +static INLINE int CMP_HOST_REG_IMM_W(int host_reg, uint16_t imm) { SUB_HOST_REG_IMM_W(host_reg, imm); return host_reg; } -static inline int CMP_HOST_REG_IMM_L(int host_reg, uint32_t imm) +static INLINE int CMP_HOST_REG_IMM_L(int host_reg, uint32_t imm) { SUB_HOST_REG_IMM(host_reg, imm); @@ -559,12 +559,12 @@ static inline int CMP_HOST_REG_IMM_L(int host_reg, uint32_t imm) #define XOR_HOST_REG_B XOR_HOST_REG_L #define XOR_HOST_REG_W XOR_HOST_REG_L -static inline void XOR_HOST_REG_L(int dst_reg, int src_reg) +static INLINE void XOR_HOST_REG_L(int dst_reg, int src_reg) { addbyte(0x31); /*XORL dst_reg, src_reg*/ addbyte(0xc0 | dst_reg | (src_reg << 3)); } -static inline void XOR_HOST_REG_IMM(int host_reg, uint32_t imm) +static INLINE void XOR_HOST_REG_IMM(int host_reg, uint32_t imm) { if (imm < 0x80 || imm >= 0xffffff80) { @@ -580,64 +580,64 @@ static inline void XOR_HOST_REG_IMM(int host_reg, uint32_t imm) } } -static inline void CALL_FUNC(uintptr_t dest) +static INLINE void CALL_FUNC(uintptr_t dest) { addbyte(0xE8); /*CALL*/ addlong(((uintptr_t)dest - (uintptr_t)(&codeblock[block_current].data[block_pos + 4]))); } -static inline void SHL_B_IMM(int reg, int count) +static INLINE void SHL_B_IMM(int reg, int count) { addbyte(0xc0); /*SHL reg, count*/ addbyte(0xc0 | reg | 0x20); addbyte(count); } -static inline void SHL_W_IMM(int reg, int count) +static INLINE void SHL_W_IMM(int reg, int count) { addbyte(0x66); /*SHL reg, count*/ addbyte(0xc1); addbyte(0xc0 | reg | 0x20); addbyte(count); } -static inline void SHL_L_IMM(int reg, int count) +static INLINE void SHL_L_IMM(int reg, int count) { addbyte(0xc1); /*SHL reg, count*/ addbyte(0xc0 | reg | 0x20); addbyte(count); } -static inline void SHR_B_IMM(int reg, int count) +static INLINE void SHR_B_IMM(int reg, int count) { addbyte(0xc0); /*SHR reg, count*/ addbyte(0xc0 | reg | 0x28); addbyte(count); } -static inline void SHR_W_IMM(int reg, int count) +static INLINE void SHR_W_IMM(int reg, int count) { addbyte(0x66); /*SHR reg, count*/ addbyte(0xc1); addbyte(0xc0 | reg | 0x28); addbyte(count); } -static inline void SHR_L_IMM(int reg, int count) +static INLINE void SHR_L_IMM(int reg, int count) { addbyte(0xc1); /*SHR reg, count*/ addbyte(0xc0 | reg | 0x28); addbyte(count); } -static inline void SAR_B_IMM(int reg, int count) +static INLINE void SAR_B_IMM(int reg, int count) { addbyte(0xc0); /*SAR reg, count*/ addbyte(0xc0 | reg | 0x38); addbyte(count); } -static inline void SAR_W_IMM(int reg, int count) +static INLINE void SAR_W_IMM(int reg, int count) { addbyte(0x66); /*SAR reg, count*/ addbyte(0xc1); addbyte(0xc0 | reg | 0x38); addbyte(count); } -static inline void SAR_L_IMM(int reg, int count) +static INLINE void SAR_L_IMM(int reg, int count) { addbyte(0xc1); /*SAR reg, count*/ addbyte(0xc0 | reg | 0x38); @@ -645,7 +645,7 @@ static inline void SAR_L_IMM(int reg, int count) } -static inline void CHECK_SEG_READ(x86seg *seg) +static INLINE void CHECK_SEG_READ(x86seg *seg) { /*Segments always valid in real/V86 mode*/ if (!(cr0 & 1) || (eflags & VM_FLAG)) @@ -668,7 +668,7 @@ static inline void CHECK_SEG_READ(x86seg *seg) seg->checked = 1; } -static inline void CHECK_SEG_WRITE(x86seg *seg) +static INLINE void CHECK_SEG_WRITE(x86seg *seg) { /*Segments always valid in real/V86 mode*/ if (!(cr0 & 1) || (eflags & VM_FLAG)) @@ -691,7 +691,7 @@ static inline void CHECK_SEG_WRITE(x86seg *seg) seg->checked = 1; } -static inline void CHECK_SEG_LIMITS(x86seg *seg, int end_offset) +static INLINE void CHECK_SEG_LIMITS(x86seg *seg, int end_offset) { if ((seg == &_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) return; @@ -719,7 +719,7 @@ static inline void CHECK_SEG_LIMITS(x86seg *seg, int end_offset) } } -static inline void MEM_LOAD_ADDR_EA_B(x86seg *seg) +static INLINE void MEM_LOAD_ADDR_EA_B(x86seg *seg) { if ((seg == &_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) { @@ -737,7 +737,7 @@ static inline void MEM_LOAD_ADDR_EA_B(x86seg *seg) host_reg_mapping[0] = 8; } -static inline int MEM_LOAD_ADDR_EA_B_NO_ABRT(x86seg *seg) +static INLINE int MEM_LOAD_ADDR_EA_B_NO_ABRT(x86seg *seg) { if ((seg == &_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) { @@ -757,7 +757,7 @@ static inline int MEM_LOAD_ADDR_EA_B_NO_ABRT(x86seg *seg) return REG_ECX; } -static inline void MEM_LOAD_ADDR_EA_W(x86seg *seg) +static INLINE void MEM_LOAD_ADDR_EA_W(x86seg *seg) { if ((seg == &_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) { @@ -775,7 +775,7 @@ static inline void MEM_LOAD_ADDR_EA_W(x86seg *seg) host_reg_mapping[0] = 8; } -static inline void MEM_LOAD_ADDR_EA_W_OFFSET(x86seg *seg, int offset) +static INLINE void MEM_LOAD_ADDR_EA_W_OFFSET(x86seg *seg, int offset) { if ((seg == &_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) { @@ -796,7 +796,7 @@ static inline void MEM_LOAD_ADDR_EA_W_OFFSET(x86seg *seg, int offset) host_reg_mapping[0] = 8; } -static inline int MEM_LOAD_ADDR_EA_W_NO_ABRT(x86seg *seg) +static INLINE int MEM_LOAD_ADDR_EA_W_NO_ABRT(x86seg *seg) { if ((seg == &_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) { @@ -816,7 +816,7 @@ static inline int MEM_LOAD_ADDR_EA_W_NO_ABRT(x86seg *seg) return REG_ECX; } -static inline void MEM_LOAD_ADDR_EA_L(x86seg *seg) +static INLINE void MEM_LOAD_ADDR_EA_L(x86seg *seg) { if ((seg == &_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) { @@ -835,7 +835,7 @@ static inline void MEM_LOAD_ADDR_EA_L(x86seg *seg) host_reg_mapping[0] = 8; } -static inline int MEM_LOAD_ADDR_EA_L_NO_ABRT(x86seg *seg) +static INLINE int MEM_LOAD_ADDR_EA_L_NO_ABRT(x86seg *seg) { if ((seg == &_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) { @@ -856,7 +856,7 @@ static inline int MEM_LOAD_ADDR_EA_L_NO_ABRT(x86seg *seg) return REG_ECX; } -static inline void MEM_LOAD_ADDR_EA_Q(x86seg *seg) +static INLINE void MEM_LOAD_ADDR_EA_Q(x86seg *seg) { if ((seg == &_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) { @@ -875,26 +875,26 @@ static inline void MEM_LOAD_ADDR_EA_Q(x86seg *seg) host_reg_mapping[0] = 8; } -static inline void MEM_LOAD_ADDR_IMM_B(x86seg *seg, uint32_t addr) +static INLINE void MEM_LOAD_ADDR_IMM_B(x86seg *seg, uint32_t addr) { addbyte(0xb8); /*MOV EAX, addr*/ addlong(addr); MEM_LOAD_ADDR_EA_B(seg); } -static inline void MEM_LOAD_ADDR_IMM_W(x86seg *seg, uint32_t addr) +static INLINE void MEM_LOAD_ADDR_IMM_W(x86seg *seg, uint32_t addr) { addbyte(0xb8); /*MOV EAX, addr*/ addlong(addr); MEM_LOAD_ADDR_EA_W(seg); } -static inline void MEM_LOAD_ADDR_IMM_L(x86seg *seg, uint32_t addr) +static INLINE void MEM_LOAD_ADDR_IMM_L(x86seg *seg, uint32_t addr) { addbyte(0xb8); /*MOV EAX, addr*/ addlong(addr); MEM_LOAD_ADDR_EA_L(seg); } -static inline void MEM_STORE_ADDR_EA_B(x86seg *seg, int host_reg) +static INLINE void MEM_STORE_ADDR_EA_B(x86seg *seg, int host_reg) { if ((seg == &_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) { @@ -915,7 +915,7 @@ static inline void MEM_STORE_ADDR_EA_B(x86seg *seg, int host_reg) addbyte(0xe8); /*CALL mem_store_addr_ea_b*/ addlong(mem_store_addr_ea_b - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); } -static inline void MEM_STORE_ADDR_EA_B_NO_ABRT(x86seg *seg, int host_reg) +static INLINE void MEM_STORE_ADDR_EA_B_NO_ABRT(x86seg *seg, int host_reg) { if ((seg == &_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) { @@ -936,7 +936,7 @@ static inline void MEM_STORE_ADDR_EA_B_NO_ABRT(x86seg *seg, int host_reg) addbyte(0xe8); /*CALL mem_store_addr_ea_b_no_abrt*/ addlong(mem_store_addr_ea_b_no_abrt - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); } -static inline void MEM_STORE_ADDR_EA_W(x86seg *seg, int host_reg) +static INLINE void MEM_STORE_ADDR_EA_W(x86seg *seg, int host_reg) { if ((seg == &_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) { @@ -957,7 +957,7 @@ static inline void MEM_STORE_ADDR_EA_W(x86seg *seg, int host_reg) addbyte(0xe8); /*CALL mem_store_addr_ea_w*/ addlong(mem_store_addr_ea_w - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); } -static inline void MEM_STORE_ADDR_EA_W_NO_ABRT(x86seg *seg, int host_reg) +static INLINE void MEM_STORE_ADDR_EA_W_NO_ABRT(x86seg *seg, int host_reg) { if ((seg == &_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) { @@ -978,7 +978,7 @@ static inline void MEM_STORE_ADDR_EA_W_NO_ABRT(x86seg *seg, int host_reg) addbyte(0xe8); /*CALL mem_store_addr_ea_w_no_abrt*/ addlong(mem_store_addr_ea_w_no_abrt - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); } -static inline void MEM_STORE_ADDR_EA_L(x86seg *seg, int host_reg) +static INLINE void MEM_STORE_ADDR_EA_L(x86seg *seg, int host_reg) { if ((seg == &_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) { @@ -999,7 +999,7 @@ static inline void MEM_STORE_ADDR_EA_L(x86seg *seg, int host_reg) addbyte(0xe8); /*CALL mem_store_addr_ea_l*/ addlong(mem_store_addr_ea_l - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); } -static inline void MEM_STORE_ADDR_EA_L_NO_ABRT(x86seg *seg, int host_reg) +static INLINE void MEM_STORE_ADDR_EA_L_NO_ABRT(x86seg *seg, int host_reg) { if ((seg == &_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) { @@ -1020,7 +1020,7 @@ static inline void MEM_STORE_ADDR_EA_L_NO_ABRT(x86seg *seg, int host_reg) addbyte(0xe8); /*CALL mem_store_addr_ea_l_no_abrt*/ addlong(mem_store_addr_ea_l_no_abrt - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); } -static inline void MEM_STORE_ADDR_EA_Q(x86seg *seg, int host_reg, int host_reg2) +static INLINE void MEM_STORE_ADDR_EA_Q(x86seg *seg, int host_reg, int host_reg2) { if (host_reg != REG_EBX) { @@ -1047,19 +1047,19 @@ static inline void MEM_STORE_ADDR_EA_Q(x86seg *seg, int host_reg, int host_reg2) addlong(mem_store_addr_ea_q - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); } -static inline void MEM_STORE_ADDR_IMM_B(x86seg *seg, uint32_t addr, int host_reg) +static INLINE void MEM_STORE_ADDR_IMM_B(x86seg *seg, uint32_t addr, int host_reg) { addbyte(0xb8); /*MOV EAX, addr*/ addlong(addr); MEM_STORE_ADDR_EA_B(seg, host_reg); } -static inline void MEM_STORE_ADDR_IMM_L(x86seg *seg, uint32_t addr, int host_reg) +static INLINE void MEM_STORE_ADDR_IMM_L(x86seg *seg, uint32_t addr, int host_reg) { addbyte(0xb8); /*MOV EAX, addr*/ addlong(addr); MEM_STORE_ADDR_EA_L(seg, host_reg); } -static inline void MEM_STORE_ADDR_IMM_W(x86seg *seg, uint32_t addr, int host_reg) +static INLINE void MEM_STORE_ADDR_IMM_W(x86seg *seg, uint32_t addr, int host_reg) { addbyte(0xb8); /*MOV EAX, addr*/ addlong(addr); @@ -1067,7 +1067,7 @@ static inline void MEM_STORE_ADDR_IMM_W(x86seg *seg, uint32_t addr, int host_reg } -static inline x86seg *FETCH_EA_16(x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc) +static INLINE x86seg *FETCH_EA_16(x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc) { int mod = (fetchdat >> 6) & 3; int rm = fetchdat & 7; @@ -1129,7 +1129,7 @@ static inline x86seg *FETCH_EA_16(x86seg *op_ea_seg, uint32_t fetchdat, int op_s return op_ea_seg; } -static inline x86seg *FETCH_EA_32(x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc, int stack_offset) +static INLINE x86seg *FETCH_EA_32(x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc, int stack_offset) { uint32_t new_eaaddr; int mod = (fetchdat >> 6) & 3; @@ -1256,7 +1256,7 @@ static inline x86seg *FETCH_EA_32(x86seg *op_ea_seg, uint32_t fetchdat, int op_s return op_ea_seg; } -static inline x86seg *FETCH_EA(x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc, uint32_t op_32) +static INLINE x86seg *FETCH_EA(x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc, uint32_t op_32) { if (op_32 & 0x200) return FETCH_EA_32(op_ea_seg, fetchdat, op_ssegs, op_pc, 0); @@ -1264,7 +1264,7 @@ static inline x86seg *FETCH_EA(x86seg *op_ea_seg, uint32_t fetchdat, int op_sseg } -static inline void LOAD_STACK_TO_EA(int off) +static INLINE void LOAD_STACK_TO_EA(int off) { if (stack32) { @@ -1293,7 +1293,7 @@ static inline void LOAD_STACK_TO_EA(int off) } } -static inline void LOAD_EBP_TO_EA(int off) +static INLINE void LOAD_EBP_TO_EA(int off) { if (stack32) { @@ -1322,7 +1322,7 @@ static inline void LOAD_EBP_TO_EA(int off) } } -static inline void SP_MODIFY(int off) +static INLINE void SP_MODIFY(int off) { if (stack32) { @@ -1363,7 +1363,7 @@ static inline void SP_MODIFY(int off) } -static inline void TEST_ZERO_JUMP_W(int host_reg, uint32_t new_pc, int taken_cycles) +static INLINE void TEST_ZERO_JUMP_W(int host_reg, uint32_t new_pc, int taken_cycles) { addbyte(0x66); /*CMPW host_reg, 0*/ addbyte(0x83); @@ -1385,7 +1385,7 @@ static inline void TEST_ZERO_JUMP_W(int host_reg, uint32_t new_pc, int taken_cyc addbyte(0xe9); /*JMP end*/ addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); } -static inline void TEST_ZERO_JUMP_L(int host_reg, uint32_t new_pc, int taken_cycles) +static INLINE void TEST_ZERO_JUMP_L(int host_reg, uint32_t new_pc, int taken_cycles) { addbyte(0x83); /*CMPW host_reg, 0*/ addbyte(0xc0 | 0x38 | host_reg); @@ -1407,7 +1407,7 @@ static inline void TEST_ZERO_JUMP_L(int host_reg, uint32_t new_pc, int taken_cyc addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); } -static inline void TEST_NONZERO_JUMP_W(int host_reg, uint32_t new_pc, int taken_cycles) +static INLINE void TEST_NONZERO_JUMP_W(int host_reg, uint32_t new_pc, int taken_cycles) { addbyte(0x66); /*CMPW host_reg, 0*/ addbyte(0x83); @@ -1429,7 +1429,7 @@ static inline void TEST_NONZERO_JUMP_W(int host_reg, uint32_t new_pc, int taken_ addbyte(0xe9); /*JMP end*/ addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); } -static inline void TEST_NONZERO_JUMP_L(int host_reg, uint32_t new_pc, int taken_cycles) +static INLINE void TEST_NONZERO_JUMP_L(int host_reg, uint32_t new_pc, int taken_cycles) { addbyte(0x83); /*CMPW host_reg, 0*/ addbyte(0xc0 | 0x38 | host_reg); @@ -1451,7 +1451,7 @@ static inline void TEST_NONZERO_JUMP_L(int host_reg, uint32_t new_pc, int taken_ addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); } -static inline void BRANCH_COND_BE(int pc_offset, uint32_t op_pc, uint32_t offset, int not) +static INLINE void BRANCH_COND_BE(int pc_offset, uint32_t op_pc, uint32_t offset, int not) { switch (codegen_flags_changed ? cpu_state.flags_op : FLAGS_UNKNOWN) { @@ -1539,7 +1539,7 @@ static inline void BRANCH_COND_BE(int pc_offset, uint32_t op_pc, uint32_t offset addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); } -static inline void BRANCH_COND_L(int pc_offset, uint32_t op_pc, uint32_t offset, int not) +static INLINE void BRANCH_COND_L(int pc_offset, uint32_t op_pc, uint32_t offset, int not) { switch (codegen_flags_changed ? cpu_state.flags_op : FLAGS_UNKNOWN) { @@ -1619,7 +1619,7 @@ static inline void BRANCH_COND_L(int pc_offset, uint32_t op_pc, uint32_t offset, addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); } -static inline void BRANCH_COND_LE(int pc_offset, uint32_t op_pc, uint32_t offset, int not) +static INLINE void BRANCH_COND_LE(int pc_offset, uint32_t op_pc, uint32_t offset, int not) { switch (codegen_flags_changed ? cpu_state.flags_op : FLAGS_UNKNOWN) { @@ -1720,7 +1720,7 @@ static inline void BRANCH_COND_LE(int pc_offset, uint32_t op_pc, uint32_t offset } -static inline void FP_ENTER() +static INLINE void FP_ENTER() { if (codegen_fpu_entered) return; @@ -1747,7 +1747,7 @@ static inline void FP_ENTER() codegen_fpu_entered = 1; } -static inline void FP_FLD(int reg) +static INLINE void FP_FLD(int reg) { if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) { @@ -1850,7 +1850,7 @@ static inline void FP_FLD(int reg) } } -static inline void FP_FST(int reg) +static INLINE void FP_FST(int reg) { if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) { @@ -1906,7 +1906,7 @@ static inline void FP_FST(int reg) } } -static inline void FP_FXCH(int reg) +static INLINE void FP_FXCH(int reg) { if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) { @@ -2043,7 +2043,7 @@ static inline void FP_FXCH(int reg) } -static inline void FP_LOAD_S() +static INLINE void FP_LOAD_S() { if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) { @@ -2100,7 +2100,7 @@ static inline void FP_LOAD_S() addbyte((uint8_t)cpu_state_offset(tag[0])); } } -static inline void FP_LOAD_D() +static INLINE void FP_LOAD_D() { if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) { @@ -2161,7 +2161,7 @@ static inline void FP_LOAD_D() addbyte((uint8_t)cpu_state_offset(tag[0])); } } -static inline void FP_LOAD_IW() +static INLINE void FP_LOAD_IW() { if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) { @@ -2221,7 +2221,7 @@ static inline void FP_LOAD_IW() addbyte((uint8_t)cpu_state_offset(tag[0])); } } -static inline void FP_LOAD_IL() +static INLINE void FP_LOAD_IL() { if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) { @@ -2279,7 +2279,7 @@ static inline void FP_LOAD_IL() addbyte((uint8_t)cpu_state_offset(tag[0])); } } -static inline void FP_LOAD_IQ() +static INLINE void FP_LOAD_IQ() { if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) { @@ -2357,7 +2357,7 @@ static inline void FP_LOAD_IQ() } } -static inline void FP_LOAD_IMM_Q(uint64_t v) +static INLINE void FP_LOAD_IMM_Q(uint64_t v) { if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) { @@ -2410,7 +2410,7 @@ static inline void FP_LOAD_IMM_Q(uint64_t v) } } -static inline int FP_LOAD_REG(int reg) +static INLINE int FP_LOAD_REG(int reg) { if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) { @@ -2447,7 +2447,7 @@ static inline int FP_LOAD_REG(int reg) return REG_EBX; } -static inline void FP_LOAD_REG_D(int reg, int *host_reg1, int *host_reg2) +static INLINE void FP_LOAD_REG_D(int reg, int *host_reg1, int *host_reg2) { if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) { @@ -2489,7 +2489,7 @@ static inline void FP_LOAD_REG_D(int reg, int *host_reg1, int *host_reg2) *host_reg2 = REG_ECX; } -static inline int FP_LOAD_REG_INT_W(int reg) +static INLINE int FP_LOAD_REG_INT_W(int reg) { addbyte(0x8b); /*MOV EBX, TOP*/ addbyte(0x5d); @@ -2523,7 +2523,7 @@ static inline int FP_LOAD_REG_INT_W(int reg) return REG_EBX; } -static inline int FP_LOAD_REG_INT(int reg) +static INLINE int FP_LOAD_REG_INT(int reg) { addbyte(0x8b); /*MOV EBX, TOP*/ addbyte(0x5d); @@ -2557,7 +2557,7 @@ static inline int FP_LOAD_REG_INT(int reg) return REG_EBX; } -static inline void FP_LOAD_REG_INT_Q(int reg, int *host_reg1, int *host_reg2) +static INLINE void FP_LOAD_REG_INT_Q(int reg, int *host_reg1, int *host_reg2) { addbyte(0x8b); /*MOV EBX, TOP*/ addbyte(0x5d); @@ -2634,7 +2634,7 @@ static inline void FP_LOAD_REG_INT_Q(int reg, int *host_reg1, int *host_reg2) *host_reg2 = REG_ECX; } -static inline void FP_POP() +static INLINE void FP_POP() { if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) { @@ -2666,7 +2666,7 @@ static inline void FP_POP() addbyte((uint8_t)cpu_state_offset(TOP)); } } -static inline void FP_POP2() +static INLINE void FP_POP2() { if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) { @@ -2710,7 +2710,7 @@ static inline void FP_POP2() #define FPU_SUB 0x20 #define FPU_SUBR 0x28 -static inline void FP_OP_S(int op) +static INLINE void FP_OP_S(int op) { if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) { @@ -2757,7 +2757,7 @@ static inline void FP_OP_S(int op) addbyte((uint8_t)cpu_state_offset(ST)); } } -static inline void FP_OP_D(int op) +static INLINE void FP_OP_D(int op) { if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) { @@ -2836,7 +2836,7 @@ static inline void FP_OP_D(int op) } } } -static inline void FP_OP_IW(int op) +static INLINE void FP_OP_IW(int op) { if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) { @@ -2884,7 +2884,7 @@ static inline void FP_OP_IW(int op) addbyte((uint8_t)cpu_state_offset(ST)); } } -static inline void FP_OP_IL(int op) +static INLINE void FP_OP_IL(int op) { if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) { @@ -2932,7 +2932,7 @@ static inline void FP_OP_IL(int op) } } #if 0 -static inline void FP_OP_IQ(int op) +static INLINE void FP_OP_IQ(int op) { if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) { @@ -2993,7 +2993,7 @@ static inline void FP_OP_IQ(int op) #define C2 (1<<10) #define C3 (1<<14) -static inline void FP_COMPARE_S() +static INLINE void FP_COMPARE_S() { if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) { @@ -3060,7 +3060,7 @@ static inline void FP_COMPARE_S() addbyte((uint8_t)cpu_state_offset(npxs) + 1); } } -static inline void FP_COMPARE_D() +static INLINE void FP_COMPARE_D() { if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) { @@ -3135,7 +3135,7 @@ static inline void FP_COMPARE_D() addbyte((uint8_t)cpu_state_offset(npxs) + 1); } } -static inline void FP_COMPARE_IW() +static INLINE void FP_COMPARE_IW() { if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) { @@ -3203,7 +3203,7 @@ static inline void FP_COMPARE_IW() addbyte((uint8_t)cpu_state_offset(npxs) + 1); } } -static inline void FP_COMPARE_IL() +static INLINE void FP_COMPARE_IL() { if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) { @@ -3271,7 +3271,7 @@ static inline void FP_COMPARE_IL() } } -static inline void FP_OP_REG(int op, int dst, int src) +static INLINE void FP_OP_REG(int op, int dst, int src) { if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) { @@ -3349,7 +3349,7 @@ static inline void FP_OP_REG(int op, int dst, int src) } } -static inline void FP_COMPARE_REG(int dst, int src) +static INLINE void FP_COMPARE_REG(int dst, int src) { if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) { @@ -3440,7 +3440,7 @@ static inline void FP_COMPARE_REG(int dst, int src) } } -static inline void FP_FCHS() +static INLINE void FP_FCHS() { if (codeblock[block_current].flags & CODEBLOCK_STATIC_TOP) { @@ -3481,7 +3481,7 @@ static inline void FP_FCHS() } } -static inline void UPDATE_NPXC(int reg) +static INLINE void UPDATE_NPXC(int reg) { addbyte(0x66); /*AND cpu_state.new_npxc, ~0xc00*/ addbyte(0x81); @@ -3507,21 +3507,21 @@ static inline void UPDATE_NPXC(int reg) addbyte((uint8_t)cpu_state_offset(new_npxc)); } -static inline int ZERO_EXTEND_W_B(int reg) +static INLINE int ZERO_EXTEND_W_B(int reg) { addbyte(0x0f); /*MOVZX regl, regb*/ addbyte(0xb6); addbyte(0xc0 | reg | (reg << 3)); return reg; } -static inline int ZERO_EXTEND_L_B(int reg) +static INLINE int ZERO_EXTEND_L_B(int reg) { addbyte(0x0f); /*MOVZX regl, regb*/ addbyte(0xb6); addbyte(0xc0 | reg | (reg << 3)); return reg; } -static inline int ZERO_EXTEND_L_W(int reg) +static INLINE int ZERO_EXTEND_L_W(int reg) { addbyte(0x0f); /*MOVZX regl, regw*/ addbyte(0xb7); @@ -3529,21 +3529,21 @@ static inline int ZERO_EXTEND_L_W(int reg) return reg; } -static inline int SIGN_EXTEND_W_B(int reg) +static INLINE int SIGN_EXTEND_W_B(int reg) { addbyte(0x0f); /*MOVSX regl, regb*/ addbyte(0xbe); addbyte(0xc0 | reg | (reg << 3)); return reg; } -static inline int SIGN_EXTEND_L_B(int reg) +static INLINE int SIGN_EXTEND_L_B(int reg) { addbyte(0x0f); /*MOVSX regl, regb*/ addbyte(0xbe); addbyte(0xc0 | reg | (reg << 3)); return reg; } -static inline int SIGN_EXTEND_L_W(int reg) +static INLINE int SIGN_EXTEND_L_W(int reg) { addbyte(0x0f); /*MOVSX regl, regw*/ addbyte(0xbf); @@ -3551,12 +3551,12 @@ static inline int SIGN_EXTEND_L_W(int reg) return reg; } -static inline int COPY_REG(int src_reg) +static INLINE int COPY_REG(int src_reg) { return src_reg; } -static inline void SET_BITS(uintptr_t addr, uint32_t val) +static INLINE void SET_BITS(uintptr_t addr, uint32_t val) { if (val & ~0xff) { @@ -3573,7 +3573,7 @@ static inline void SET_BITS(uintptr_t addr, uint32_t val) addbyte(val); } } -static inline void CLEAR_BITS(uintptr_t addr, uint32_t val) +static INLINE void CLEAR_BITS(uintptr_t addr, uint32_t val) { if (val & ~0xff) { @@ -3594,7 +3594,7 @@ static inline void CLEAR_BITS(uintptr_t addr, uint32_t val) #define LOAD_Q_REG_1 REG_EAX #define LOAD_Q_REG_2 REG_EDX -static inline void MMX_ENTER() +static INLINE void MMX_ENTER() { if (codegen_mmx_entered) return; @@ -3639,7 +3639,7 @@ static inline void MMX_ENTER() extern int mmx_ebx_ecx_loaded; -static inline int LOAD_MMX_D(int guest_reg) +static INLINE int LOAD_MMX_D(int guest_reg) { int host_reg = find_host_reg(); host_reg_mapping[host_reg] = 100; @@ -3650,7 +3650,7 @@ static inline int LOAD_MMX_D(int guest_reg) return host_reg; } -static inline void LOAD_MMX_Q(int guest_reg, int *host_reg1, int *host_reg2) +static INLINE void LOAD_MMX_Q(int guest_reg, int *host_reg1, int *host_reg2) { if (!mmx_ebx_ecx_loaded) { @@ -3671,7 +3671,7 @@ static inline void LOAD_MMX_Q(int guest_reg, int *host_reg1, int *host_reg2) addbyte(0x45 | ((*host_reg2) << 3)); addbyte((uint8_t)cpu_state_offset(MM[guest_reg].l[1])); } -static inline int LOAD_MMX_Q_MMX(int guest_reg) +static INLINE int LOAD_MMX_Q_MMX(int guest_reg) { int dst_reg = find_host_xmm_reg(); host_reg_xmm_mapping[dst_reg] = guest_reg; @@ -3685,7 +3685,7 @@ static inline int LOAD_MMX_Q_MMX(int guest_reg) return dst_reg; } -static inline int LOAD_INT_TO_MMX(int src_reg1, int src_reg2) +static INLINE int LOAD_INT_TO_MMX(int src_reg1, int src_reg2) { int dst_reg = find_host_xmm_reg(); host_reg_xmm_mapping[dst_reg] = 100; @@ -3706,7 +3706,7 @@ static inline int LOAD_INT_TO_MMX(int src_reg1, int src_reg2) return dst_reg; } -static inline void STORE_MMX_LQ(int guest_reg, int host_reg1) +static INLINE void STORE_MMX_LQ(int guest_reg, int host_reg1) { addbyte(0xC7); /*MOVL [reg],0*/ addbyte(0x45); @@ -3716,7 +3716,7 @@ static inline void STORE_MMX_LQ(int guest_reg, int host_reg1) addbyte(0x45 | (host_reg1 << 3)); addbyte((uint8_t)cpu_state_offset(MM[guest_reg].l[0])); } -static inline void STORE_MMX_Q(int guest_reg, int host_reg1, int host_reg2) +static INLINE void STORE_MMX_Q(int guest_reg, int host_reg1, int host_reg2) { addbyte(0x89); /*MOVL [reg],host_reg*/ addbyte(0x45 | (host_reg1 << 3)); @@ -3725,7 +3725,7 @@ static inline void STORE_MMX_Q(int guest_reg, int host_reg1, int host_reg2) addbyte(0x45 | (host_reg2 << 3)); addbyte((uint8_t)cpu_state_offset(MM[guest_reg].l[1])); } -static inline void STORE_MMX_Q_MMX(int guest_reg, int host_reg) +static INLINE void STORE_MMX_Q_MMX(int guest_reg, int host_reg) { addbyte(0x66); /*MOVQ [guest_reg],host_reg*/ addbyte(0x0f); @@ -3735,7 +3735,7 @@ static inline void STORE_MMX_Q_MMX(int guest_reg, int host_reg) } #define MMX_x86_OP(name, opcode) \ -static inline void MMX_ ## name(int dst_reg, int src_reg) \ +static INLINE void MMX_ ## name(int dst_reg, int src_reg) \ { \ addbyte(0x66); /*op dst_reg, src_reg*/ \ addbyte(0x0f); \ @@ -3788,7 +3788,7 @@ MMX_x86_OP(PMULLW, 0xd5); MMX_x86_OP(PMULHW, 0xe5); MMX_x86_OP(PMADDWD, 0xf5); -static inline void MMX_PACKSSWB(int dst_reg, int src_reg) +static INLINE void MMX_PACKSSWB(int dst_reg, int src_reg) { addbyte(0x66); /*PACKSSWB dst_reg, src_reg*/ addbyte(0x0f); @@ -3800,7 +3800,7 @@ static inline void MMX_PACKSSWB(int dst_reg, int src_reg) addbyte(0xc0 | (dst_reg << 3) | dst_reg); addbyte(0x08); } -static inline void MMX_PACKUSWB(int dst_reg, int src_reg) +static INLINE void MMX_PACKUSWB(int dst_reg, int src_reg) { addbyte(0x66); /*PACKUSWB dst_reg, src_reg*/ addbyte(0x0f); @@ -3812,7 +3812,7 @@ static inline void MMX_PACKUSWB(int dst_reg, int src_reg) addbyte(0xc0 | (dst_reg << 3) | dst_reg); addbyte(0x08); } -static inline void MMX_PACKSSDW(int dst_reg, int src_reg) +static INLINE void MMX_PACKSSDW(int dst_reg, int src_reg) { addbyte(0x66); /*PACKSSDW dst_reg, src_reg*/ addbyte(0x0f); @@ -3824,7 +3824,7 @@ static inline void MMX_PACKSSDW(int dst_reg, int src_reg) addbyte(0xc0 | (dst_reg << 3) | dst_reg); addbyte(0x08); } -static inline void MMX_PUNPCKHBW(int dst_reg, int src_reg) +static INLINE void MMX_PUNPCKHBW(int dst_reg, int src_reg) { addbyte(0x66); /*PUNPCKLBW dst_reg, src_reg*/ addbyte(0x0f); @@ -3836,7 +3836,7 @@ static inline void MMX_PUNPCKHBW(int dst_reg, int src_reg) addbyte(0xc0 | (dst_reg << 3) | dst_reg); addbyte(0x0e); } -static inline void MMX_PUNPCKHWD(int dst_reg, int src_reg) +static INLINE void MMX_PUNPCKHWD(int dst_reg, int src_reg) { addbyte(0x66); /*PUNPCKLWD dst_reg, src_reg*/ addbyte(0x0f); @@ -3848,7 +3848,7 @@ static inline void MMX_PUNPCKHWD(int dst_reg, int src_reg) addbyte(0xc0 | (dst_reg << 3) | dst_reg); addbyte(0x0e); } -static inline void MMX_PUNPCKHDQ(int dst_reg, int src_reg) +static INLINE void MMX_PUNPCKHDQ(int dst_reg, int src_reg) { addbyte(0x66); /*PUNPCKLDQ dst_reg, src_reg*/ addbyte(0x0f); @@ -3861,7 +3861,7 @@ static inline void MMX_PUNPCKHDQ(int dst_reg, int src_reg) addbyte(0x0e); } -static inline void MMX_PSRLW_imm(int dst_reg, int amount) +static INLINE void MMX_PSRLW_imm(int dst_reg, int amount) { addbyte(0x66); /*PSRLW dst_reg, amount*/ addbyte(0x0f); @@ -3869,7 +3869,7 @@ static inline void MMX_PSRLW_imm(int dst_reg, int amount) addbyte(0xc0 | dst_reg | 0x10); addbyte(amount); } -static inline void MMX_PSRAW_imm(int dst_reg, int amount) +static INLINE void MMX_PSRAW_imm(int dst_reg, int amount) { addbyte(0x66); /*PSRAW dst_reg, amount*/ addbyte(0x0f); @@ -3877,7 +3877,7 @@ static inline void MMX_PSRAW_imm(int dst_reg, int amount) addbyte(0xc0 | dst_reg | 0x20); addbyte(amount); } -static inline void MMX_PSLLW_imm(int dst_reg, int amount) +static INLINE void MMX_PSLLW_imm(int dst_reg, int amount) { addbyte(0x66); /*PSLLW dst_reg, amount*/ addbyte(0x0f); @@ -3886,7 +3886,7 @@ static inline void MMX_PSLLW_imm(int dst_reg, int amount) addbyte(amount); } -static inline void MMX_PSRLD_imm(int dst_reg, int amount) +static INLINE void MMX_PSRLD_imm(int dst_reg, int amount) { addbyte(0x66); /*PSRLD dst_reg, amount*/ addbyte(0x0f); @@ -3894,7 +3894,7 @@ static inline void MMX_PSRLD_imm(int dst_reg, int amount) addbyte(0xc0 | dst_reg | 0x10); addbyte(amount); } -static inline void MMX_PSRAD_imm(int dst_reg, int amount) +static INLINE void MMX_PSRAD_imm(int dst_reg, int amount) { addbyte(0x66); /*PSRAD dst_reg, amount*/ addbyte(0x0f); @@ -3902,7 +3902,7 @@ static inline void MMX_PSRAD_imm(int dst_reg, int amount) addbyte(0xc0 | dst_reg | 0x20); addbyte(amount); } -static inline void MMX_PSLLD_imm(int dst_reg, int amount) +static INLINE void MMX_PSLLD_imm(int dst_reg, int amount) { addbyte(0x66); /*PSLLD dst_reg, amount*/ addbyte(0x0f); @@ -3911,7 +3911,7 @@ static inline void MMX_PSLLD_imm(int dst_reg, int amount) addbyte(amount); } -static inline void MMX_PSRLQ_imm(int dst_reg, int amount) +static INLINE void MMX_PSRLQ_imm(int dst_reg, int amount) { addbyte(0x66); /*PSRLQ dst_reg, amount*/ addbyte(0x0f); @@ -3919,7 +3919,7 @@ static inline void MMX_PSRLQ_imm(int dst_reg, int amount) addbyte(0xc0 | dst_reg | 0x10); addbyte(amount); } -static inline void MMX_PSRAQ_imm(int dst_reg, int amount) +static INLINE void MMX_PSRAQ_imm(int dst_reg, int amount) { addbyte(0x66); /*PSRAQ dst_reg, amount*/ addbyte(0x0f); @@ -3927,7 +3927,7 @@ static inline void MMX_PSRAQ_imm(int dst_reg, int amount) addbyte(0xc0 | dst_reg | 0x20); addbyte(amount); } -static inline void MMX_PSLLQ_imm(int dst_reg, int amount) +static INLINE void MMX_PSLLQ_imm(int dst_reg, int amount) { addbyte(0x66); /*PSLLQ dst_reg, amount*/ addbyte(0x0f); @@ -3937,14 +3937,14 @@ static inline void MMX_PSLLQ_imm(int dst_reg, int amount) } -static inline void SAVE_EA() +static INLINE void SAVE_EA() { addbyte(0x89); /*MOV [ESP+12], EAX*/ addbyte(0x44); addbyte(0x24); addbyte(12); } -static inline void LOAD_EA() +static INLINE void LOAD_EA() { addbyte(0x8b); /*MOV EAX, [ESP+12]*/ addbyte(0x44); @@ -3953,7 +3953,7 @@ static inline void LOAD_EA() } #define MEM_CHECK_WRITE_B MEM_CHECK_WRITE -static inline void MEM_CHECK_WRITE(x86seg *seg) +static INLINE void MEM_CHECK_WRITE(x86seg *seg) { CHECK_SEG_WRITE(seg); if ((seg == &_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) @@ -3971,7 +3971,7 @@ static inline void MEM_CHECK_WRITE(x86seg *seg) addlong(mem_check_write - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); LOAD_EA(); } -static inline void MEM_CHECK_WRITE_W(x86seg *seg) +static INLINE void MEM_CHECK_WRITE_W(x86seg *seg) { CHECK_SEG_WRITE(seg); if ((seg == &_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) @@ -3989,7 +3989,7 @@ static inline void MEM_CHECK_WRITE_W(x86seg *seg) addlong(mem_check_write_w - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); LOAD_EA(); } -static inline void MEM_CHECK_WRITE_L(x86seg *seg) +static INLINE void MEM_CHECK_WRITE_L(x86seg *seg) { CHECK_SEG_WRITE(seg); if ((seg == &_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) @@ -4008,7 +4008,7 @@ static inline void MEM_CHECK_WRITE_L(x86seg *seg) LOAD_EA(); } -static inline void LOAD_SEG(int host_reg, void *seg) +static INLINE void LOAD_SEG(int host_reg, void *seg) { addbyte(0xc7); /*MOV [ESP+4], seg*/ addbyte(0x44); diff --git a/src/cpu/codegen_timing_486.c b/src/cpu/codegen_timing_486.c index 637ef26..7c57aa3 100644 --- a/src/cpu/codegen_timing_486.c +++ b/src/cpu/codegen_timing_486.c @@ -306,7 +306,7 @@ static int timing_count; static uint8_t last_prefix; static uint32_t regmask_modified; -static inline int COUNT(int *c, int op_32) +static INLINE int COUNT(int *c, int op_32) { if ((uintptr_t)c <= 10000) return (int)(uintptr_t)c; diff --git a/src/cpu/codegen_timing_686.c b/src/cpu/codegen_timing_686.c index be55da8..ac085f8 100644 --- a/src/cpu/codegen_timing_686.c +++ b/src/cpu/codegen_timing_686.c @@ -19,7 +19,7 @@ * - FPU queue * - Out of order execution (beyond most simplistic approxx) * - * Version: @(#)codegen_timing_686.c 1.0.1 2018/02/14 + * Version: @(#)codegen_timing_686.c 1.0.2 2018/09/19 * * Authors: Sarah Walker, * Miran Grca, @@ -90,15 +90,16 @@ static int prev_full; static uint32_t prev_opcode; -static uint32_t *prev_timings; +static const uint32_t *prev_timings; static uint32_t prev_op_32; static uint32_t prev_regmask; static uint64_t *prev_deps; static uint32_t prev_fetchdat; +static uint32_t last_regmask_modified; static uint32_t regmask_modified; -static uint32_t opcode_timings[256] = +static const uint32_t opcode_timings[256] = { /* ADD ADD ADD ADD*/ /*00*/ PAIR_XY | CYCLES_RMW, PAIR_XY | CYCLES_RMW, PAIR_XY | CYCLES_RM, PAIR_XY | CYCLES_RM, @@ -234,7 +235,7 @@ static uint32_t opcode_timings[256] = PAIR_XY | CYCLES(7), PAIR_XY | CYCLES(7), PAIR_XY | CYCLES_RMW, INVALID }; -static uint32_t opcode_timings_mod3[256] = +static const uint32_t opcode_timings_mod3[256] = { /* ADD ADD ADD ADD*/ /*00*/ PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, @@ -371,7 +372,7 @@ static uint32_t opcode_timings_mod3[256] = PAIR_XY | CYCLES(7), PAIR_XY | CYCLES(7), PAIR_XY | CYCLES_REG, INVALID }; -static uint32_t opcode_timings_0f[256] = +static const uint32_t opcode_timings_0f[256] = { /*00*/ PAIR_NP | CYCLES(20), PAIR_NP | CYCLES(11), PAIR_NP | CYCLES(11), PAIR_NP | CYCLES(10), INVALID, PAIR_NP | CYCLES(195), PAIR_NP | CYCLES(7), INVALID, @@ -453,7 +454,7 @@ static uint32_t opcode_timings_0f[256] = PAIR_X | CYCLES_RM, PAIR_X | CYCLES_RM, PAIR_X | CYCLES_RM, INVALID, PAIR_X | CYCLES_RM, PAIR_X | CYCLES_RM, PAIR_X | CYCLES_RM, INVALID, }; -static uint32_t opcode_timings_0f_mod3[256] = +static const uint32_t opcode_timings_0f_mod3[256] = { /*00*/ PAIR_NP | CYCLES(20), PAIR_NP | CYCLES(11), PAIR_NP | CYCLES(11), PAIR_NP | CYCLES(10), INVALID, PAIR_NP | CYCLES(195), PAIR_NP | CYCLES(7), INVALID, @@ -535,73 +536,73 @@ static uint32_t opcode_timings_0f_mod3[256] = PAIR_X | CYCLES_REG, PAIR_X | CYCLES_REG, PAIR_X | CYCLES_REG, INVALID, }; -static uint32_t opcode_timings_shift[8] = +static const uint32_t opcode_timings_shift[8] = { PAIR_XY | CYCLES_RMW, PAIR_XY | CYCLES_RMW, PAIR_XY | CYCLES(3), PAIR_XY | CYCLES(4), PAIR_XY | CYCLES_RMW, PAIR_XY | CYCLES_RMW, PAIR_XY | CYCLES_RMW, PAIR_XY | CYCLES_RMW, }; -static uint32_t opcode_timings_shift_mod3[8] = +static const uint32_t opcode_timings_shift_mod3[8] = { PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES(3), PAIR_XY | CYCLES(4), PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, }; -static uint32_t opcode_timings_shift_imm[8] = +static const uint32_t opcode_timings_shift_imm[8] = { PAIR_XY | CYCLES_RMW, PAIR_XY | CYCLES_RMW, PAIR_XY | CYCLES(8), PAIR_XY | CYCLES(9), PAIR_XY | CYCLES_RMW, PAIR_XY | CYCLES_RMW, PAIR_XY | CYCLES_RMW, PAIR_XY | CYCLES_RMW, }; -static uint32_t opcode_timings_shift_imm_mod3[8] = +static const uint32_t opcode_timings_shift_imm_mod3[8] = { PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES(3), PAIR_XY | CYCLES(4), PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, }; -static uint32_t opcode_timings_shift_cl[8] = +static const uint32_t opcode_timings_shift_cl[8] = { PAIR_XY | CYCLES(2), PAIR_XY | CYCLES(2), PAIR_XY | CYCLES(8), PAIR_XY | CYCLES(9), PAIR_XY | CYCLES(2), PAIR_XY | CYCLES(2), PAIR_XY | CYCLES(2), PAIR_XY | CYCLES(2), }; -static uint32_t opcode_timings_shift_cl_mod3[8] = +static const uint32_t opcode_timings_shift_cl_mod3[8] = { PAIR_XY | CYCLES(2), PAIR_XY | CYCLES(2), PAIR_XY | CYCLES(8), PAIR_XY | CYCLES(9), PAIR_XY | CYCLES(2), PAIR_XY | CYCLES(2), PAIR_XY | CYCLES(2), PAIR_XY | CYCLES(2), }; -static uint32_t opcode_timings_f6[8] = +static const uint32_t opcode_timings_f6[8] = { /* TST NOT NEG*/ PAIR_XY | CYCLES_RM, INVALID, PAIR_XY | CYCLES(1), PAIR_XY | CYCLES(1), /* MUL IMUL DIV IDIV*/ PAIR_NP | CYCLES(4), PAIR_NP | CYCLES(4), PAIR_NP | CYCLES(18), PAIR_NP | CYCLES(18) }; -static uint32_t opcode_timings_f6_mod3[8] = +static const uint32_t opcode_timings_f6_mod3[8] = { /* TST NOT NEG*/ PAIR_XY | CYCLES_REG, INVALID, PAIR_XY | CYCLES(1), PAIR_XY | CYCLES(1), /* MUL IMUL DIV IDIV*/ PAIR_NP | CYCLES(4), PAIR_NP | CYCLES(4), PAIR_NP | CYCLES(18), PAIR_NP | CYCLES(18) }; -static uint32_t opcode_timings_f7[8] = +static const uint32_t opcode_timings_f7[8] = { /* TST NOT NEG*/ PAIR_XY | CYCLES_REG, INVALID, PAIR_XY | CYCLES(1), PAIR_XY | CYCLES(1), /* MUL IMUL DIV IDIV*/ PAIR_NP | CYCLES_MULTI(4,10), PAIR_NP | CYCLES_MULTI(4,10), PAIR_NP | CYCLES_MULTI(19,27), PAIR_NP | CYCLES_MULTI(22,30) }; -static uint32_t opcode_timings_f7_mod3[8] = +static const uint32_t opcode_timings_f7_mod3[8] = { /* TST NOT NEG*/ PAIR_XY | CYCLES_REG, INVALID, PAIR_XY | CYCLES(1), PAIR_XY | CYCLES(1), /* MUL IMUL DIV IDIV*/ PAIR_NP | CYCLES_MULTI(4,10), PAIR_NP | CYCLES_MULTI(4,10), PAIR_NP | CYCLES_MULTI(19,27), PAIR_NP | CYCLES_MULTI(22,30) }; -static uint32_t opcode_timings_ff[8] = +static const uint32_t opcode_timings_ff[8] = { /* INC DEC CALL CALL far*/ PAIR_XY | CYCLES_RMW, PAIR_XY | CYCLES_RMW, PAIR_X_BRANCH | CYCLES(3), PAIR_NP | CYCLES(5), /* JMP JMP far PUSH*/ PAIR_X_BRANCH | CYCLES(3), PAIR_NP | CYCLES(5), PAIR_XY | CYCLES(1), INVALID }; -static uint32_t opcode_timings_ff_mod3[8] = +static const uint32_t opcode_timings_ff_mod3[8] = { /* INC DEC CALL CALL far*/ PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_X_BRANCH | CYCLES(1), PAIR_XY | CYCLES(5), @@ -609,14 +610,14 @@ static uint32_t opcode_timings_ff_mod3[8] = PAIR_X_BRANCH | CYCLES(1), PAIR_XY | CYCLES(5), PAIR_XY | CYCLES(2), INVALID }; -static uint32_t opcode_timings_d8[8] = +static const uint32_t opcode_timings_d8[8] = { /* FADDs FMULs FCOMs FCOMPs*/ PAIR_X | CYCLES(7), PAIR_X | CYCLES(6), PAIR_X | CYCLES(4), PAIR_X | CYCLES(4), /* FSUBs FSUBRs FDIVs FDIVRs*/ PAIR_X | CYCLES(7), PAIR_X | CYCLES(7), PAIR_X | CYCLES(34), PAIR_X | CYCLES(34) }; -static uint32_t opcode_timings_d8_mod3[8] = +static const uint32_t opcode_timings_d8_mod3[8] = { /* FADD FMUL FCOM FCOMP*/ PAIR_X | CYCLES(7), PAIR_X | CYCLES(6), PAIR_X | CYCLES(4), PAIR_X | CYCLES(4), @@ -624,14 +625,14 @@ static uint32_t opcode_timings_d8_mod3[8] = PAIR_X | CYCLES(7), PAIR_X | CYCLES(7), PAIR_X | CYCLES(34), PAIR_X | CYCLES(34) }; -static uint32_t opcode_timings_d9[8] = +static const uint32_t opcode_timings_d9[8] = { /* FLDs FSTs FSTPs*/ PAIR_X | CYCLES(2), INVALID, PAIR_X | CYCLES(2), PAIR_X | CYCLES(2), /* FLDENV FLDCW FSTENV FSTCW*/ PAIR_X | CYCLES(30), PAIR_X | CYCLES(4), PAIR_X | CYCLES(24), PAIR_X | CYCLES(5) }; -static uint32_t opcode_timings_d9_mod3[64] = +static const uint32_t opcode_timings_d9_mod3[64] = { /*FLD*/ PAIR_X | CYCLES(2), PAIR_X | CYCLES(2), PAIR_X | CYCLES(2), PAIR_X | CYCLES(2), @@ -663,28 +664,28 @@ static uint32_t opcode_timings_d9_mod3[64] = PAIR_X | CYCLES(20), PAIR_X | CYCLES(14), PAIR_X | CYCLES(140), PAIR_X | CYCLES(141) }; -static uint32_t opcode_timings_da[8] = +static const uint32_t opcode_timings_da[8] = { /* FIADDl FIMULl FICOMl FICOMPl*/ PAIR_X | CYCLES(12), PAIR_X | CYCLES(11), PAIR_X | CYCLES(10), PAIR_X | CYCLES(10), /* FISUBl FISUBRl FIDIVl FIDIVRl*/ PAIR_X | CYCLES(29), PAIR_X | CYCLES(27), PAIR_X | CYCLES(38), PAIR_X | CYCLES(48) }; -static uint32_t opcode_timings_da_mod3[8] = +static const uint32_t opcode_timings_da_mod3[8] = { PAIR_X | CYCLES(4), PAIR_X | CYCLES(4), PAIR_X | CYCLES(4), PAIR_X | CYCLES(4), INVALID, PAIR_X | CYCLES(5), INVALID, INVALID }; -static uint32_t opcode_timings_db[8] = +static const uint32_t opcode_timings_db[8] = { /* FLDil FSTil FSTPil*/ PAIR_X | CYCLES(2), INVALID, PAIR_X | CYCLES(2), PAIR_X | CYCLES(2), /* FLDe FSTPe*/ INVALID, PAIR_X | CYCLES(2), INVALID, PAIR_X | CYCLES(2) }; -static uint32_t opcode_timings_db_mod3[64] = +static const uint32_t opcode_timings_db_mod3[64] = { PAIR_X | CYCLES(4), PAIR_X | CYCLES(4), PAIR_X | CYCLES(4), PAIR_X | CYCLES(4), PAIR_X | CYCLES(4), PAIR_X | CYCLES(4), PAIR_X | CYCLES(4), PAIR_X | CYCLES(4), @@ -713,14 +714,14 @@ static uint32_t opcode_timings_db_mod3[64] = INVALID, INVALID, INVALID, INVALID, }; -static uint32_t opcode_timings_dc[8] = +static const uint32_t opcode_timings_dc[8] = { /* FADDd FMULd FCOMd FCOMPd*/ PAIR_X | CYCLES(7), PAIR_X | CYCLES(7), PAIR_X | CYCLES(7), PAIR_X | CYCLES(7), /* FSUBd FSUBRd FDIVd FDIVRd*/ PAIR_X | CYCLES(7), PAIR_X | CYCLES(7), PAIR_X | CYCLES(34), PAIR_X | CYCLES(34) }; -static uint32_t opcode_timings_dc_mod3[8] = +static const uint32_t opcode_timings_dc_mod3[8] = { /* opFADDr opFMULr*/ PAIR_X | CYCLES(7), PAIR_X | CYCLES(7), INVALID, INVALID, @@ -728,14 +729,14 @@ static uint32_t opcode_timings_dc_mod3[8] = PAIR_X | CYCLES(7), PAIR_X | CYCLES(7), PAIR_X | CYCLES(34), PAIR_X | CYCLES(34) }; -static uint32_t opcode_timings_dd[8] = +static const uint32_t opcode_timings_dd[8] = { /* FLDd FSTd FSTPd*/ PAIR_X | CYCLES(2), INVALID, PAIR_X | CYCLES(2), PAIR_X | CYCLES(2), /* FRSTOR FSAVE FSTSW*/ PAIR_X | CYCLES(72), INVALID, PAIR_X | CYCLES(67), PAIR_X | CYCLES(2) }; -static uint32_t opcode_timings_dd_mod3[8] = +static const uint32_t opcode_timings_dd_mod3[8] = { /* FFFREE FST FSTP*/ PAIR_X | CYCLES(3), INVALID, PAIR_X | CYCLES(2), PAIR_X | CYCLES(2), @@ -743,14 +744,14 @@ static uint32_t opcode_timings_dd_mod3[8] = PAIR_X | CYCLES(4), PAIR_X | CYCLES(4), INVALID, INVALID }; -static uint32_t opcode_timings_de[8] = +static const uint32_t opcode_timings_de[8] = { /* FIADDw FIMULw FICOMw FICOMPw*/ PAIR_X | CYCLES(12), PAIR_X | CYCLES(11), PAIR_X | CYCLES(10), PAIR_X | CYCLES(10), /* FISUBw FISUBRw FIDIVw FIDIVRw*/ PAIR_X | CYCLES(27), PAIR_X | CYCLES(27), PAIR_X | CYCLES(38), PAIR_X | CYCLES(38) }; -static uint32_t opcode_timings_de_mod3[8] = +static const uint32_t opcode_timings_de_mod3[8] = { /* FADD FMUL FCOMPP*/ PAIR_X | CYCLES(7), PAIR_X | CYCLES(7), INVALID, PAIR_X | CYCLES(7), @@ -758,45 +759,47 @@ static uint32_t opcode_timings_de_mod3[8] = PAIR_X | CYCLES(7), PAIR_X | CYCLES(7), PAIR_X | CYCLES(34), PAIR_X | CYCLES(34) }; -static uint32_t opcode_timings_df[8] = +static const uint32_t opcode_timings_df[8] = { /* FILDiw FISTiw FISTPiw*/ PAIR_X | CYCLES(8), INVALID, PAIR_X | CYCLES(10), PAIR_X | CYCLES(13), /* FILDiq FBSTP FISTPiq*/ INVALID, PAIR_X | CYCLES(8), PAIR_X | CYCLES(63), PAIR_X | CYCLES(13) }; -static uint32_t opcode_timings_df_mod3[8] = +static const uint32_t opcode_timings_df_mod3[8] = { INVALID, INVALID, INVALID, INVALID, /* FSTSW AX*/ PAIR_X | CYCLES(6), INVALID, INVALID, INVALID }; -static uint32_t opcode_timings_8x[8] = +static const uint32_t opcode_timings_8x[8] = { PAIR_XY | CYCLES_RMW, PAIR_XY | CYCLES_RMW, PAIR_XY | CYCLES_RMW, PAIR_XY | CYCLES_RMW, PAIR_XY | CYCLES_RMW, PAIR_XY | CYCLES_RMW, PAIR_XY | CYCLES_RMW, PAIR_XY | CYCLES_RM }; -static uint32_t opcode_timings_8x_mod3[8] = +static const uint32_t opcode_timings_8x_mod3[8] = { PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG }; -static uint32_t opcode_timings_81[8] = +static const uint32_t opcode_timings_81[8] = { PAIR_XY | CYCLES_RMW, PAIR_XY | CYCLES_RMW, PAIR_XY | CYCLES_RMW, PAIR_XY | CYCLES_RMW, PAIR_XY | CYCLES_RMW, PAIR_XY | CYCLES_RMW, PAIR_XY | CYCLES_RMW, PAIR_XY | CYCLES_RM }; -static uint32_t opcode_timings_81_mod3[8] = +static const uint32_t opcode_timings_81_mod3[8] = { PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG }; + static int decode_delay; static uint8_t last_prefix; -static inline int COUNT(uint32_t c, int op_32) + +static INLINE int COUNT(uint32_t c, int op_32) { if (c & CYCLES_HAS_MULTI) { @@ -810,20 +813,35 @@ static inline int COUNT(uint32_t c, int op_32) return c & CYCLES_MASK; } -void codegen_timing_686_block_start() + +void codegen_timing_686_block_start(void) { prev_full = decode_delay = 0; - regmask_modified = 0; + regmask_modified = last_regmask_modified = 0; } -void codegen_timing_686_start() + +void codegen_timing_686_start(void) { decode_delay = 0; last_prefix = 0; } + void codegen_timing_686_prefix(uint8_t prefix, uint32_t fetchdat) { + if ((prefix & 0xf8) == 0xd8) + { + last_prefix = prefix; + return; + } + if (prefix == 0x0f && (fetchdat & 0xf0) == 0x80) + { + /*0fh prefix is 'free' when used on conditional jumps*/ + last_prefix = prefix; + return; + } + /*6x86 can decode 1 prefix per instruction per clock with no penalty. If either instruction has more than one prefix then decode is delayed by one cycle for each additional prefix*/ @@ -831,6 +849,7 @@ void codegen_timing_686_prefix(uint8_t prefix, uint32_t fetchdat) last_prefix = prefix; } + static int check_agi(uint64_t *deps, uint8_t opcode, uint32_t fetchdat, int op_32) { uint32_t addr_regmask = get_addr_regmask(deps[opcode], fetchdat, op_32); @@ -838,12 +857,22 @@ static int check_agi(uint64_t *deps, uint8_t opcode, uint32_t fetchdat, int op_3 if (addr_regmask & IMPL_ESP) addr_regmask |= (1 << REG_ESP); - return regmask_modified & addr_regmask; + if (regmask_modified & addr_regmask) + { + regmask_modified = 0; + return 2; + } + + if (last_regmask_modified & addr_regmask) + return 1; + + return 0; } + void codegen_timing_686_opcode(uint8_t opcode, uint32_t fetchdat, int op_32) { - uint32_t *timings; + const uint32_t *timings; uint64_t *deps; int mod3 = ((fetchdat & 0xc0) == 0xc0); int bit8 = !(opcode & 1); @@ -951,6 +980,8 @@ void codegen_timing_686_opcode(uint8_t opcode, uint32_t fetchdat, int op_32) } } + /*One prefix per instruction is free*/ + decode_delay--; if (decode_delay < 0) decode_delay = 0; @@ -962,8 +993,7 @@ void codegen_timing_686_opcode(uint8_t opcode, uint32_t fetchdat, int op_32) if (regmask & IMPL_ESP) regmask |= SRCDEP_ESP | DSTDEP_ESP; - if (check_agi(prev_deps, prev_opcode, prev_fetchdat, prev_op_32)) - agi_stall = 2; + agi_stall = check_agi(prev_deps, prev_opcode, prev_fetchdat, prev_op_32); /*Second instruction in the pair*/ if ((timings[opcode] & PAIR_MASK) == PAIR_NP) @@ -973,6 +1003,7 @@ void codegen_timing_686_opcode(uint8_t opcode, uint32_t fetchdat, int op_32) codegen_block_cycles += COUNT(prev_timings[prev_opcode], prev_op_32) + decode_delay + agi_stall; decode_delay = (-COUNT(prev_timings[prev_opcode], prev_op_32)) + 1 + agi_stall; prev_full = 0; + last_regmask_modified = regmask_modified; regmask_modified = prev_regmask; } else if (((timings[opcode] & PAIR_MASK) == PAIR_X || (timings[opcode] & PAIR_MASK) == PAIR_X_BRANCH) @@ -983,6 +1014,7 @@ void codegen_timing_686_opcode(uint8_t opcode, uint32_t fetchdat, int op_32) codegen_block_cycles += COUNT(prev_timings[prev_opcode], prev_op_32) + decode_delay + agi_stall; decode_delay = (-COUNT(prev_timings[prev_opcode], prev_op_32)) + 1 + agi_stall; prev_full = 0; + last_regmask_modified = regmask_modified; regmask_modified = prev_regmask; } else if (prev_regmask & regmask) @@ -992,6 +1024,7 @@ void codegen_timing_686_opcode(uint8_t opcode, uint32_t fetchdat, int op_32) codegen_block_cycles += COUNT(prev_timings[prev_opcode], prev_op_32) + decode_delay + agi_stall; decode_delay = (-COUNT(prev_timings[prev_opcode], prev_op_32)) + 1 + agi_stall; prev_full = 0; + last_regmask_modified = regmask_modified; regmask_modified = prev_regmask; } else @@ -1003,12 +1036,12 @@ void codegen_timing_686_opcode(uint8_t opcode, uint32_t fetchdat, int op_32) if (!t_pair) fatal("Pairable 0 cycles! %02x %02x\n", opcode, prev_opcode); - if (check_agi(deps, opcode, fetchdat, op_32)) - agi_stall = 2; + agi_stall = check_agi(deps, opcode, fetchdat, op_32); codegen_block_cycles += t_pair + agi_stall; decode_delay = (-t_pair) + 1 + agi_stall; + last_regmask_modified = regmask_modified; regmask_modified = get_dstdep_mask(deps[opcode], fetchdat, bit8) | prev_regmask; prev_full = 0; return; @@ -1021,13 +1054,13 @@ void codegen_timing_686_opcode(uint8_t opcode, uint32_t fetchdat, int op_32) if ((timings[opcode] & PAIR_MASK) == PAIR_NP || (timings[opcode] & PAIR_MASK) == PAIR_X_BRANCH) { /*Instruction not pairable*/ - int agi_stall = 0; - - if (check_agi(deps, opcode, fetchdat, op_32)) - agi_stall = 2; + int agi_stall; + agi_stall = check_agi(deps, opcode, fetchdat, op_32); + codegen_block_cycles += COUNT(timings[opcode], op_32) + decode_delay + agi_stall; decode_delay = (-COUNT(timings[opcode], op_32)) + 1 + agi_stall; + last_regmask_modified = regmask_modified; regmask_modified = get_dstdep_mask(deps[opcode], fetchdat, bit8); } else @@ -1047,7 +1080,8 @@ void codegen_timing_686_opcode(uint8_t opcode, uint32_t fetchdat, int op_32) } } -void codegen_timing_686_block_end() + +void codegen_timing_686_block_end(void) { if (prev_full) { @@ -1057,6 +1091,7 @@ void codegen_timing_686_block_end() } } + codegen_timing_t codegen_timing_686 = { codegen_timing_686_start, diff --git a/src/cpu/codegen_timing_common.c b/src/cpu/codegen_timing_common.c index ca4e25c..f59164e 100644 --- a/src/cpu/codegen_timing_common.c +++ b/src/cpu/codegen_timing_common.c @@ -40,6 +40,7 @@ #include #include "../emu.h" #include "cpu.h" +#include "x86.h" #include "codegen_timing_common.h" diff --git a/src/cpu/codegen_timing_common.h b/src/cpu/codegen_timing_common.h index 5f78518..240744c 100644 --- a/src/cpu/codegen_timing_common.h +++ b/src/cpu/codegen_timing_common.h @@ -151,7 +151,7 @@ extern uint64_t opcode_deps_8x_mod3[8]; -static inline uint32_t get_addr_regmask(uint64_t data, uint32_t fetchdat, int op_32) +static INLINE uint32_t get_addr_regmask(uint64_t data, uint32_t fetchdat, int op_32) { uint32_t addr_regmask = 0; @@ -205,7 +205,7 @@ static inline uint32_t get_addr_regmask(uint64_t data, uint32_t fetchdat, int op return addr_regmask; } -static inline uint32_t get_srcdep_mask(uint64_t data, uint32_t fetchdat, int bit8, int op_32) +static INLINE uint32_t get_srcdep_mask(uint64_t data, uint32_t fetchdat, int bit8, int op_32) { uint32_t mask = 0; if (data & SRCDEP_REG) @@ -233,7 +233,7 @@ static inline uint32_t get_srcdep_mask(uint64_t data, uint32_t fetchdat, int bit return mask; } -static inline uint32_t get_dstdep_mask(uint64_t data, uint32_t fetchdat, int bit8) +static INLINE uint32_t get_dstdep_mask(uint64_t data, uint32_t fetchdat, int bit8) { uint32_t mask = 0; if (data & DSTDEP_REG) diff --git a/src/cpu/codegen_timing_pentium.c b/src/cpu/codegen_timing_pentium.c index 098beca..96883d0 100644 --- a/src/cpu/codegen_timing_pentium.c +++ b/src/cpu/codegen_timing_pentium.c @@ -20,7 +20,7 @@ * - PMMX decode queue * - MMX latencies * - * Version: @(#)codegen_timing_pentium.c 1.0.2 2018/03/09 + * Version: @(#)codegen_timing_pentium.c 1.0.3 2018/09/04 * * Authors: Sarah Walker, * Miran Grca, @@ -132,7 +132,7 @@ static int pair_timings[4][4] = static int u_pipe_full; static uint32_t u_pipe_opcode; -static uint64_t *u_pipe_timings; +static const uint64_t *u_pipe_timings; static uint32_t u_pipe_op_32; static uint32_t u_pipe_regmask; static uint32_t u_pipe_fetchdat; @@ -146,7 +146,7 @@ static uint32_t addr_regmask; static int fpu_latency; static int fpu_st_latency[8]; -static uint64_t opcode_timings[256] = +static const uint64_t opcode_timings[256] = { /* ADD ADD ADD ADD*/ /*00*/ PAIR_UV | CYCLES_RMW, PAIR_UV | CYCLES_RMW, PAIR_UV | CYCLES_RM, PAIR_UV | CYCLES_RM, @@ -282,7 +282,7 @@ static uint64_t opcode_timings[256] = PAIR_NP | CYCLES(2), PAIR_NP | CYCLES(2), PAIR_UV | CYCLES_RMW, INVALID }; -static uint64_t opcode_timings_mod3[256] = +static const uint64_t opcode_timings_mod3[256] = { /* ADD ADD ADD ADD*/ /*00*/ PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, @@ -419,7 +419,7 @@ static uint64_t opcode_timings_mod3[256] = PAIR_NP | CYCLES(2), PAIR_NP | CYCLES(2), PAIR_UV | CYCLES_REG, INVALID }; -static uint64_t opcode_timings_0f[256] = +static const uint64_t opcode_timings_0f[256] = { /*00*/ PAIR_NP | CYCLES(20), PAIR_NP | CYCLES(11), PAIR_NP | CYCLES(11), PAIR_NP | CYCLES(10), INVALID, PAIR_NP | CYCLES(195), PAIR_NP | CYCLES(7), INVALID, @@ -501,7 +501,7 @@ static uint64_t opcode_timings_0f[256] = PAIR_U | CYCLES_RM, PAIR_U | CYCLES_RM, PAIR_U | CYCLES_RM, INVALID, PAIR_U | CYCLES_RM, PAIR_U | CYCLES_RM, PAIR_U | CYCLES_RM, INVALID, }; -static uint64_t opcode_timings_0f_mod3[256] = +static const uint64_t opcode_timings_0f_mod3[256] = { /*00*/ PAIR_NP | CYCLES(20), PAIR_NP | CYCLES(11), PAIR_NP | CYCLES(11), PAIR_NP | CYCLES(10), INVALID, PAIR_NP | CYCLES(195), PAIR_NP | CYCLES(7), INVALID, @@ -584,53 +584,53 @@ static uint64_t opcode_timings_0f_mod3[256] = PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, INVALID, }; -static uint64_t opcode_timings_shift[8] = +static const uint64_t opcode_timings_shift[8] = { PAIR_U | CYCLES_RMW, PAIR_U | CYCLES_RMW, PAIR_U | CYCLES_RMW, PAIR_U | CYCLES_RMW, PAIR_U | CYCLES_RMW, PAIR_U | CYCLES_RMW, PAIR_U | CYCLES_RMW, PAIR_U | CYCLES_RMW, }; -static uint64_t opcode_timings_shift_mod3[8] = +static const uint64_t opcode_timings_shift_mod3[8] = { PAIR_U | CYCLES_REG, PAIR_U | CYCLES_REG, PAIR_U | CYCLES_REG, PAIR_U | CYCLES_REG, PAIR_U | CYCLES_REG, PAIR_U | CYCLES_REG, PAIR_U | CYCLES_REG, PAIR_U | CYCLES_REG, }; -static uint64_t opcode_timings_f6[8] = +static const uint64_t opcode_timings_f6[8] = { /* TST NOT NEG*/ PAIR_UV | CYCLES_RM, INVALID, PAIR_NP | CYCLES(3), PAIR_NP | CYCLES(3), /* MUL IMUL DIV IDIV*/ PAIR_NP | CYCLES(11), PAIR_NP | CYCLES(11), PAIR_NP | CYCLES(17), PAIR_NP | CYCLES(22) }; -static uint64_t opcode_timings_f6_mod3[8] = +static const uint64_t opcode_timings_f6_mod3[8] = { /* TST NOT NEG*/ PAIR_UV | CYCLES_REG, INVALID, PAIR_NP | CYCLES(3), PAIR_NP | CYCLES(3), /* MUL IMUL DIV IDIV*/ PAIR_NP | CYCLES(11), PAIR_NP | CYCLES(11), PAIR_NP | CYCLES(17), PAIR_NP | CYCLES(22) }; -static uint64_t opcode_timings_f7[8] = +static const uint64_t opcode_timings_f7[8] = { /* TST NOT NEG*/ PAIR_UV | CYCLES_RM, INVALID, PAIR_NP | CYCLES(3), PAIR_NP | CYCLES(3), /* MUL IMUL DIV IDIV*/ PAIR_NP | CYCLES_MULTI(11,10), PAIR_NP | CYCLES_MULTI(11,10), PAIR_NP | CYCLES_MULTI(25,41), PAIR_NP | CYCLES_MULTI(30,46) }; -static uint64_t opcode_timings_f7_mod3[8] = +static const uint64_t opcode_timings_f7_mod3[8] = { /* TST NOT NEG*/ PAIR_UV | CYCLES_REG, INVALID, PAIR_NP | CYCLES(3), PAIR_NP | CYCLES(3), /* MUL IMUL DIV IDIV*/ PAIR_NP | CYCLES_MULTI(11,10), PAIR_NP | CYCLES_MULTI(11,10), PAIR_NP | CYCLES_MULTI(25,41), PAIR_NP | CYCLES_MULTI(30,46) }; -static uint64_t opcode_timings_ff[8] = +static const uint64_t opcode_timings_ff[8] = { /* INC DEC CALL CALL far*/ PAIR_UV | CYCLES_RMW, PAIR_UV | CYCLES_RMW, PAIR_NP | CYCLES(4), PAIR_NP | CYCLES(0), /* JMP JMP far PUSH*/ PAIR_NP | CYCLES(2), PAIR_NP | CYCLES(0), PAIR_NP | CYCLES(2), INVALID }; -static uint64_t opcode_timings_ff_mod3[8] = +static const uint64_t opcode_timings_ff_mod3[8] = { /* INC DEC CALL CALL far*/ PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_NP | CYCLES(4), PAIR_NP | CYCLES(0), @@ -638,14 +638,14 @@ static uint64_t opcode_timings_ff_mod3[8] = PAIR_NP | CYCLES(2), PAIR_NP | CYCLES(0), PAIR_NP | CYCLES(2), INVALID }; -static uint64_t opcode_timings_d8[8] = +static const uint64_t opcode_timings_d8[8] = { /* FADDs FMULs FCOMs FCOMPs*/ PAIR_FX | FPU_CYCLES(3,2,2), PAIR_FX | FPU_CYCLES(3,2,2), PAIR_FX | FPU_CYCLES(1,0,0), PAIR_FX | FPU_CYCLES(1,0,0), /* FSUBs FSUBRs FDIVs FDIVRs*/ PAIR_FX | FPU_CYCLES(3,2,2), PAIR_FX | FPU_CYCLES(3,2,2), PAIR_FX | FPU_CYCLES(39,38,2), PAIR_FX | FPU_CYCLES(39,38,2) }; -static uint64_t opcode_timings_d8_mod3[8] = +static const uint64_t opcode_timings_d8_mod3[8] = { /* FADD FMUL FCOM FCOMP*/ PAIR_FX | FPU_CYCLES(3,2,2), PAIR_FX | FPU_CYCLES(3,2,2), PAIR_FX | FPU_CYCLES(1,0,0), PAIR_FX | FPU_CYCLES(1,0,0), @@ -653,14 +653,14 @@ static uint64_t opcode_timings_d8_mod3[8] = PAIR_FX | FPU_CYCLES(3,2,2), PAIR_FX | FPU_CYCLES(3,2,2), PAIR_FX | FPU_CYCLES(39,38,2), PAIR_FX | FPU_CYCLES(39,38,2) }; -static uint64_t opcode_timings_d9[8] = +static const uint64_t opcode_timings_d9[8] = { /* FLDs FSTs FSTPs*/ PAIR_FX | FPU_CYCLES(1,0,0), INVALID, PAIR_NP | FPU_CYCLES(2,0,0), PAIR_NP | FPU_CYCLES(2,0,0), /* FLDENV FLDCW FSTENV FSTCW*/ PAIR_NP | FPU_CYCLES(32,0,0), PAIR_NP | FPU_CYCLES(8,0,0), PAIR_NP | FPU_CYCLES(48,0,0), PAIR_NP | FPU_CYCLES(2,0,0) }; -static uint64_t opcode_timings_d9_mod3[64] = +static const uint64_t opcode_timings_d9_mod3[64] = { /*FLD*/ PAIR_FX | FPU_CYCLES(1,0,0), PAIR_FX | FPU_CYCLES(1,0,0), PAIR_FX | FPU_CYCLES(1,0,0), PAIR_FX | FPU_CYCLES(1,0,0), @@ -692,14 +692,14 @@ static uint64_t opcode_timings_d9_mod3[64] = PAIR_NP | FPU_CYCLES(9,0,0), PAIR_NP | FPU_CYCLES(20,5,0), PAIR_NP | FPU_CYCLES(65,2,2), PAIR_NP | FPU_CYCLES(65,2,2) }; -static uint64_t opcode_timings_da[8] = +static const uint64_t opcode_timings_da[8] = { /* FIADDl FIMULl FICOMl FICOMPl*/ PAIR_NP | FPU_CYCLES(6,2,2), PAIR_NP | FPU_CYCLES(6,2,2), PAIR_NP | FPU_CYCLES(4,0,0), PAIR_NP | FPU_CYCLES(4,0,0), /* FISUBl FISUBRl FIDIVl FIDIVRl*/ PAIR_NP | FPU_CYCLES(6,2,2), PAIR_NP | FPU_CYCLES(6,2,2), PAIR_NP | FPU_CYCLES(42,38,2), PAIR_NP | FPU_CYCLES(42,38,2) }; -static uint64_t opcode_timings_da_mod3[8] = +static const uint64_t opcode_timings_da_mod3[8] = { INVALID, INVALID, INVALID, INVALID, /* FCOMPP*/ @@ -707,14 +707,14 @@ static uint64_t opcode_timings_da_mod3[8] = }; -static uint64_t opcode_timings_db[8] = +static const uint64_t opcode_timings_db[8] = { /* FLDil FSTil FSTPil*/ PAIR_NP | FPU_CYCLES(3,2,2), INVALID, PAIR_NP | FPU_CYCLES(6,0,0), PAIR_NP | FPU_CYCLES(6,0,0), /* FLDe FSTPe*/ INVALID, PAIR_NP | FPU_CYCLES(3,0,0), INVALID, PAIR_NP | FPU_CYCLES(3,0,0) }; -static uint64_t opcode_timings_db_mod3[64] = +static const uint64_t opcode_timings_db_mod3[64] = { INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, @@ -743,14 +743,14 @@ static uint64_t opcode_timings_db_mod3[64] = INVALID, INVALID, INVALID, INVALID, }; -static uint64_t opcode_timings_dc[8] = +static const uint64_t opcode_timings_dc[8] = { /* FADDd FMULd FCOMd FCOMPd*/ PAIR_FX | FPU_CYCLES(3,2,2), PAIR_FX | FPU_CYCLES(3,2,2), PAIR_FX | FPU_CYCLES(1,0,0), PAIR_FX | FPU_CYCLES(1,0,0), /* FSUBd FSUBRd FDIVd FDIVRd*/ PAIR_FX | FPU_CYCLES(3,2,2), PAIR_FX | FPU_CYCLES(3,2,2), PAIR_FX | FPU_CYCLES(39,38,2), PAIR_FX | FPU_CYCLES(39,38,2) }; -static uint64_t opcode_timings_dc_mod3[8] = +static const uint64_t opcode_timings_dc_mod3[8] = { /* opFADDr opFMULr*/ PAIR_FX | FPU_CYCLES(3,2,2), PAIR_FX | FPU_CYCLES(3,2,2), INVALID, INVALID, @@ -758,14 +758,14 @@ static uint64_t opcode_timings_dc_mod3[8] = PAIR_FX | FPU_CYCLES(3,2,2), PAIR_FX | FPU_CYCLES(3,2,2), PAIR_FX | FPU_CYCLES(39,38,2), PAIR_FX | FPU_CYCLES(39,38,2) }; -static uint64_t opcode_timings_dd[8] = +static const uint64_t opcode_timings_dd[8] = { /* FLDd FSTd FSTPd*/ PAIR_FX | FPU_CYCLES(1,0,0), INVALID, PAIR_NP | FPU_CYCLES(2,0,0), PAIR_NP | FPU_CYCLES(2,0,0), /* FRSTOR FSAVE FSTSW*/ PAIR_NP | FPU_CYCLES(70,0,0), INVALID, PAIR_NP | FPU_CYCLES(127,0,0), PAIR_NP | FPU_CYCLES(6,0,0) }; -static uint64_t opcode_timings_dd_mod3[8] = +static const uint64_t opcode_timings_dd_mod3[8] = { /* FFFREE FST FSTP*/ PAIR_NP | FPU_CYCLES(2,0,0), INVALID, PAIR_NP | FPU_CYCLES(1,0,0), PAIR_NP | FPU_CYCLES(1,0,0), @@ -773,14 +773,14 @@ static uint64_t opcode_timings_dd_mod3[8] = PAIR_NP | FPU_CYCLES(1,0,0), PAIR_NP | FPU_CYCLES(1,0,0), INVALID, INVALID }; -static uint64_t opcode_timings_de[8] = +static const uint64_t opcode_timings_de[8] = { /* FIADDw FIMULw FICOMw FICOMPw*/ PAIR_NP | FPU_CYCLES(6,2,2), PAIR_NP | FPU_CYCLES(6,2,2), PAIR_NP | FPU_CYCLES(4,0,0), PAIR_NP | FPU_CYCLES(4,0,0), /* FISUBw FISUBRw FIDIVw FIDIVRw*/ PAIR_NP | FPU_CYCLES(6,2,2), PAIR_NP | FPU_CYCLES(6,2,2), PAIR_NP | FPU_CYCLES(42,38,2), PAIR_NP | FPU_CYCLES(42,38,2) }; -static uint64_t opcode_timings_de_mod3[8] = +static const uint64_t opcode_timings_de_mod3[8] = { /* FADDP FMULP FCOMPP*/ PAIR_FX | FPU_CYCLES(3,2,2), PAIR_FX | FPU_CYCLES(3,2,2), INVALID, PAIR_FX | FPU_CYCLES(1,0,0), @@ -788,46 +788,48 @@ static uint64_t opcode_timings_de_mod3[8] = PAIR_FX | FPU_CYCLES(3,2,2), PAIR_FX | FPU_CYCLES(3,2,2), PAIR_FX | FPU_CYCLES(39,38,2), PAIR_FX | FPU_CYCLES(39,38,2) }; -static uint64_t opcode_timings_df[8] = +static const uint64_t opcode_timings_df[8] = { /* FILDiw FISTiw FISTPiw*/ PAIR_NP | FPU_CYCLES(3,2,2), INVALID, PAIR_NP | FPU_CYCLES(6,0,0), PAIR_NP | FPU_CYCLES(6,0,0), /* FILDiq FBSTP FISTPiq*/ INVALID, PAIR_NP | FPU_CYCLES(3,2,2), PAIR_NP | FPU_CYCLES(148,0,0), PAIR_NP | FPU_CYCLES(6,0,0) }; -static uint64_t opcode_timings_df_mod3[8] = +static const uint64_t opcode_timings_df_mod3[8] = { INVALID, INVALID, INVALID, INVALID, /* FSTSW AX*/ PAIR_NP | FPU_CYCLES(6,0,0), INVALID, INVALID, INVALID }; -static uint64_t opcode_timings_81[8] = +static const uint64_t opcode_timings_81[8] = { PAIR_UV | CYCLES_RMW | CYCLES_IMM1632, PAIR_UV | CYCLES_RMW | CYCLES_IMM1632, PAIR_UV | CYCLES_RMW | CYCLES_IMM1632, PAIR_UV | CYCLES_RMW | CYCLES_IMM1632, PAIR_UV | CYCLES_RMW | CYCLES_IMM1632, PAIR_UV | CYCLES_RMW | CYCLES_IMM1632, PAIR_UV | CYCLES_RMW | CYCLES_IMM1632, PAIR_UV | CYCLES_RM | CYCLES_IMM1632 }; -static uint64_t opcode_timings_81_mod3[8] = +static const uint64_t opcode_timings_81_mod3[8] = { PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG }; -static uint64_t opcode_timings_8x[8] = +static const uint64_t opcode_timings_8x[8] = { PAIR_UV | CYCLES_RMW | CYCLES_IMM8, PAIR_UV | CYCLES_RMW | CYCLES_IMM8, PAIR_UV | CYCLES_RMW | CYCLES_IMM8, PAIR_UV | CYCLES_RMW | CYCLES_IMM8, PAIR_UV | CYCLES_RMW | CYCLES_IMM8, PAIR_UV | CYCLES_RMW | CYCLES_IMM8, PAIR_UV | CYCLES_RMW | CYCLES_IMM8, PAIR_UV | CYCLES_RM | CYCLES_IMM8 }; -static uint64_t opcode_timings_8x_mod3[8] = +static const uint64_t opcode_timings_8x_mod3[8] = { PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG }; + static int decode_delay, decode_delay_offset; static uint8_t last_prefix; static int prefixes; -static inline int COUNT(uint64_t timings, uint64_t deps, int op_32) + +static INLINE int COUNT(uint64_t timings, uint64_t deps, int op_32) { if ((timings & PAIR_FPU) && !(deps & FPU_FXCH)) return FPU_I_LATENCY(timings); @@ -862,6 +864,7 @@ static inline int COUNT(uint64_t timings, uint64_t deps, int op_32) return timings & 0xffffffff; } + static int codegen_fpu_latencies(uint64_t deps, int reg) { int latency = fpu_latency; @@ -876,6 +879,7 @@ static int codegen_fpu_latencies(uint64_t deps, int reg) return latency; } + #define SUB_AND_CLAMP(latency, count) \ latency -= count; \ if (latency < 0) \ @@ -894,7 +898,8 @@ static void codegen_fpu_latency_clock(int count) SUB_AND_CLAMP(fpu_st_latency[7], count); } -static inline int codegen_timing_has_displacement(uint32_t fetchdat, int op_32) + +static INLINE int codegen_timing_has_displacement(uint32_t fetchdat, int op_32) { if (op_32 & 0x200) { @@ -918,9 +923,10 @@ static inline int codegen_timing_has_displacement(uint32_t fetchdat, int op_32) return 0; } + /*The instruction is only of interest here if it's longer than 7 bytes, as that's the limit on Pentium MMX parallel decoding*/ -static inline int codegen_timing_instr_length(uint64_t timing, uint32_t fetchdat, int op_32) +static INLINE int codegen_timing_instr_length(uint64_t timing, uint32_t fetchdat, int op_32) { int len = prefixes; if ((timing & CYCLES_MASK) == CYCLES_RM || (timing & CYCLES_MASK) == CYCLES_RMW) @@ -968,17 +974,20 @@ static inline int codegen_timing_instr_length(uint64_t timing, uint32_t fetchdat return len; } -void codegen_timing_pentium_block_start() + +void codegen_timing_pentium_block_start(void) { u_pipe_full = decode_delay = decode_delay_offset = 0; } -void codegen_timing_pentium_start() + +void codegen_timing_pentium_start(void) { last_prefix = 0; prefixes = 0; } + void codegen_timing_pentium_prefix(uint8_t prefix, uint32_t fetchdat) { prefixes++; @@ -1000,7 +1009,7 @@ void codegen_timing_pentium_prefix(uint8_t prefix, uint32_t fetchdat) last_prefix = prefix; return; } - if (prefix == 0x0f && (opcode & 0xf0) == 0x80) + if (prefix == 0x0f && (fetchdat & 0xf0) == 0x80) { /*On Pentium 0fh prefix is 'free' when used on conditional jumps*/ last_prefix = prefix; @@ -1024,7 +1033,7 @@ static int check_agi(uint64_t *deps, uint8_t opcode, uint32_t fetchdat, int op_3 return (regmask_modified & addr_regmask) & ~REGMASK_IMPL_ESP; } -static void codegen_instruction(uint64_t *timings, uint64_t *deps, uint8_t opcode, uint32_t fetchdat, int decode_delay_offset, int op_32, int exec_delay) +static void codegen_instruction(const uint64_t *timings, uint64_t *deps, uint8_t opcode, uint32_t fetchdat, int decode_delay_offset, int op_32, int exec_delay) { int instr_cycles, latency = 0; @@ -1115,7 +1124,7 @@ static void codegen_instruction(uint64_t *timings, uint64_t *deps, uint8_t opcod void codegen_timing_pentium_opcode(uint8_t opcode, uint32_t fetchdat, int op_32) { - uint64_t *timings; + const uint64_t *timings; uint64_t *deps; int mod3 = ((fetchdat & 0xc0) == 0xc0); int bit8 = !(opcode & 1); diff --git a/src/cpu/codegen_timing_winchip.c b/src/cpu/codegen_timing_winchip.c index d104fe4..7d43320 100644 --- a/src/cpu/codegen_timing_winchip.c +++ b/src/cpu/codegen_timing_winchip.c @@ -306,7 +306,7 @@ static int timing_count; static uint8_t last_prefix; static uint32_t regmask_modified; -static inline int COUNT(int *c, int op_32) +static INLINE int COUNT(int *c, int op_32) { if ((uintptr_t)c <= 10000) return (int)(uintptr_t)c; diff --git a/src/cpu/codegen_x86-64.c b/src/cpu/codegen_x86-64.c index e87b7fc..bf937f6 100644 --- a/src/cpu/codegen_x86-64.c +++ b/src/cpu/codegen_x86-64.c @@ -8,7 +8,7 @@ * * Dynamic Recompiler for Intel x64 systems. * - * Version: @(#)codegen_x86-64.c 1.0.1 2018/02/14 + * Version: @(#)codegen_x86-64.c 1.0.2 2018/09/22 * * Authors: Sarah Walker, * Miran Grca, @@ -111,9 +111,9 @@ void codegen_init() #if WIN64 codeblock = VirtualAlloc(NULL, BLOCK_SIZE * sizeof(codeblock_t), MEM_COMMIT, PAGE_EXECUTE_READWRITE); #else - codeblock = malloc(BLOCK_SIZE * sizeof(codeblock_t)); + codeblock = mem_alloc(BLOCK_SIZE * sizeof(codeblock_t)); #endif - codeblock_hash = malloc(HASH_SIZE * sizeof(codeblock_t *)); + codeblock_hash = mem_alloc(HASH_SIZE * sizeof(codeblock_t *)); memset(codeblock, 0, BLOCK_SIZE * sizeof(codeblock_t)); memset(codeblock_hash, 0, HASH_SIZE * sizeof(codeblock_t *)); @@ -130,7 +130,6 @@ void codegen_init() exit(-1); } #endif -// pclog("Codegen is %p\n", (void *)pages[0xfab12 >> 12].block); } void codegen_reset() @@ -147,20 +146,6 @@ void codegen_reset() void dump_block() { -/* codeblock_t *block = pages[0x119000 >> 12].block; - - pclog("dump_block:\n"); - while (block) - { - uint32_t start_pc = (block->pc & 0xffc) | (block->phys & ~0xfff); - uint32_t end_pc = (block->endpc & 0xffc) | (block->phys & ~0xfff); - pclog(" %p : %08x-%08x %08x-%08x %p %p\n", (void *)block, start_pc, end_pc, block->pc, block->endpc, (void *)block->prev, (void *)block->next); - if (!block->pc) - fatal("Dead PC=0\n"); - - block = block->next; - } - pclog("dump_block done\n");*/ } static void add_to_block_list(codeblock_t *block) @@ -240,7 +225,6 @@ static void remove_from_block_list(codeblock_t *block, uint32_t pc) } else { -// pclog(" pages.block_2=%p 3 %p %p\n", (void *)block->next_2, (void *)block, (void *)pages[block->phys_2 >> 12].block_2); pages[block->phys_2 >> 12].block_2[(block->phys_2 >> 10) & 3] = block->next_2; if (block->next_2) block->next_2->prev_2 = NULL; @@ -306,11 +290,8 @@ void codegen_block_init(uint32_t phys_addr) block_current = (block_current + 1) & BLOCK_MASK; block = &codeblock[block_current]; -// if (block->pc == 0xb00b4ff5) -// pclog("Init target block\n"); if (block->valid != 0) { -// pclog("Reuse block : was %08x now %08x\n", block->pc, cs+pc); delete_block(block); cpu_recomp_reuse++; } @@ -410,8 +391,6 @@ void codegen_block_start_recompile(codeblock_t *block) addbyte(0xBD); addquad(((uintptr_t)&cpu_state) + 128); -// pclog("New block %i for %08X %03x\n", block_current, cs+pc, block_num); - last_op32 = -1; last_ea_seg = NULL; last_ssegs = -1; @@ -471,11 +450,9 @@ void codegen_block_generate_end_mask() start_pc >>= PAGE_MASK_SHIFT; end_pc >>= PAGE_MASK_SHIFT; -// pclog("block_end: %08x %08x\n", start_pc, end_pc); for (; start_pc <= end_pc; start_pc++) { block->page_mask |= ((uint64_t)1 << start_pc); -// pclog(" %08x %llx\n", start_pc, block->page_mask); } pages[block->phys >> 12].code_present_mask[(block->phys >> 10) & 3] |= block->page_mask; @@ -503,7 +480,6 @@ void codegen_block_generate_end_mask() fatal("!page_mask2\n"); if (block->next_2) { -// pclog(" next_2->pc=%08x\n", block->next_2->pc); if (block->next_2->valid == 0) fatal("block->next_2->valid=0 %p\n", (void *)block->next_2); } @@ -512,7 +488,6 @@ void codegen_block_generate_end_mask() } } -// pclog("block_end: %08x %08x %016llx\n", block->pc, block->endpc, block->page_mask); recomp_page = -1; } @@ -578,7 +553,6 @@ void codegen_block_end_recompile(codeblock_t *block) block->next_2 = block->prev_2 = NULL; codegen_block_generate_end_mask(); add_to_block_list(block); -// pclog("End block %i\n", block_num); } void codegen_flush() @@ -633,10 +607,6 @@ int opcode_0f_modrm[256] = void codegen_debug() { - if (output) - { - pclog("At %04x(%08x):%04x %04x(%08x):%04x es=%08x EAX=%08x BX=%04x ECX=%08x BP=%04x EDX=%08x EDI=%08x\n", CS, cs, cpu_state.pc, SS, ss, ESP, es,EAX, BX,ECX,BP, EDX,EDI); - } } static x86seg *codegen_generate_ea_16_long(x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc) @@ -762,7 +732,7 @@ static x86seg *codegen_generate_ea_16_long(x86seg *op_ea_seg, uint32_t fetchdat, } return op_ea_seg; } -//#if 0 + static x86seg *codegen_generate_ea_32_long(x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc, int stack_offset) { uint32_t new_eaaddr; @@ -964,7 +934,7 @@ static x86seg *codegen_generate_ea_32_long(x86seg *op_ea_seg, uint32_t fetchdat, } return op_ea_seg; } -//#endif + void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_pc, uint32_t old_pc) { codeblock_t *block = &codeblock[block_current]; @@ -1158,17 +1128,6 @@ generate_call: addlong(codegen_block_ins); codegen_block_ins = 0; } -#if 0 - if (codegen_block_full_ins) - { - addbyte(0x81); /*ADD $codegen_block_ins,ins*/ - addbyte(0x04); - addbyte(0x25); - addlong((uint32_t)&cpu_recomp_full_ins); - addlong(codegen_block_full_ins); - codegen_block_full_ins = 0; - } -#endif } if ((op_table == x86_dynarec_opcodes_REPNE || op_table == x86_dynarec_opcodes_REPE) && !op_table[opcode | op_32]) @@ -1195,8 +1154,6 @@ generate_call: } op = op_table[((opcode >> opcode_shift) | op_32) & opcode_mask]; -// if (output) -// pclog("Generate call at %08X %02X %08X %02X %08X %08X %08X %08X %08X %02X %02X %02X %02X\n", &codeblock[block_current][block_pos], opcode, new_pc, ram[old_pc], EAX, EBX, ECX, EDX, ESI, ram[0x7bd2+6],ram[0x7bd2+7],ram[0x7bd2+8],ram[0x7bd2+9]); if (op_ssegs != last_ssegs) { last_ssegs = op_ssegs; @@ -1205,7 +1162,7 @@ generate_call: addbyte((uint8_t)cpu_state_offset(ssegs)); addbyte(op_ssegs); } -//#if 0 + if ((!test_modrm || (op_table == x86_dynarec_opcodes && opcode_modrm[opcode]) || (op_table == x86_dynarec_opcodes_0f && opcode_0f_modrm[opcode]))/* && !(op_32 & 0x200)*/) @@ -1231,10 +1188,9 @@ generate_call: op_ea_seg = codegen_generate_ea_32_long(op_ea_seg, fetchdat, op_ssegs, &op_pc, stack_offset); op_pc -= pc_off; } -//#endif + if (op_ea_seg != last_ea_seg) { -// last_ea_seg = op_ea_seg; addbyte(0xC7); /*MOVL $&_ds,(ea_seg)*/ addbyte(0x45); addbyte((uint8_t)cpu_state_offset(ea_seg)); @@ -1271,8 +1227,6 @@ generate_call: addbyte(0x0F); addbyte(0x85); /*JNZ 0*/ addlong((uint32_t)(uintptr_t)&block->data[BLOCK_EXIT_OFFSET] - (uint32_t)(uintptr_t)(&block->data[block_pos + 4])); -// call(block, codegen_debug); - codegen_endpc = (cs + cpu_state.pc) + 8; } diff --git a/src/cpu/codegen_x86.c b/src/cpu/codegen_x86.c index 3fce395..31f2aea 100644 --- a/src/cpu/codegen_x86.c +++ b/src/cpu/codegen_x86.c @@ -8,7 +8,7 @@ * * Dynamic Recompiler for Intel 32-bit systems. * - * Version: @(#)codegen_x86.c 1.0.3 2018/05/05 + * Version: @(#)codegen_x86.c 1.0.4 2018/09/22 * * Authors: Fred N. van Kempen, * Sarah Walker, @@ -62,6 +62,7 @@ #include #endif #if defined _WIN32 +#undef ERROR #include #endif @@ -994,11 +995,6 @@ static uint32_t gen_MEM_CHECK_WRITE() return addr; } -/*static void checkdebug(uint32_t a) -{ - pclog("checkdebug %08x\n", a); -}*/ - static uint32_t gen_MEM_CHECK_WRITE_W() { uint32_t addr = (uint32_t)&codeblock[block_current].data[block_pos]; @@ -1173,11 +1169,11 @@ void codegen_init() #endif #ifdef _WIN32 - codeblock = VirtualAlloc(NULL, (BLOCK_SIZE+1) * sizeof(codeblock_t), MEM_COMMIT, PAGE_EXECUTE_READWRITE); + codeblock = (codeblock_t *)VirtualAlloc(NULL, (BLOCK_SIZE+1) * sizeof(codeblock_t), MEM_COMMIT, PAGE_EXECUTE_READWRITE); #else - codeblock = malloc((BLOCK_SIZE+1) * sizeof(codeblock_t)); + codeblock = (codeblock_t *)mem_alloc((BLOCK_SIZE+1) * sizeof(codeblock_t)); #endif - codeblock_hash = malloc(HASH_SIZE * sizeof(codeblock_t *)); + codeblock_hash = (codeblock_t **)mem_alloc(HASH_SIZE * sizeof(codeblock_t *)); memset(codeblock, 0, (BLOCK_SIZE+1) * sizeof(codeblock_t)); memset(codeblock_hash, 0, HASH_SIZE * sizeof(codeblock_t *)); @@ -1260,20 +1256,6 @@ void codegen_reset() void dump_block() { -/* codeblock_t *block = pages[0x119000 >> 12].block; - - pclog("dump_block:\n"); - while (block) - { - uint32_t start_pc = (block->pc & 0xffc) | (block->phys & ~0xfff); - uint32_t end_pc = (block->endpc & 0xffc) | (block->phys & ~0xfff); - pclog(" %p : %08x-%08x %08x-%08x %p %p\n", (void *)block, start_pc, end_pc, block->pc, block->endpc, (void *)block->prev, (void *)block->next); - if (!block->pc) - fatal("Dead PC=0\n"); - - block = block->next; - } - pclog("dump_block done\n");*/ } static void add_to_block_list(codeblock_t *block) @@ -1619,15 +1601,6 @@ void codegen_block_end_recompile(codeblock_t *block) addbyte((uint8_t)cpu_state_offset(cpu_recomp_ins)); addlong(codegen_block_ins); } -#if 0 - if (codegen_block_full_ins) - { - addbyte(0x81); /*ADD $codegen_block_ins,ins*/ - addbyte(0x05); - addlong((uint32_t)&cpu_recomp_full_ins); - addlong(codegen_block_full_ins); - } -#endif addbyte(0x83); /*ADDL $16,%esp*/ addbyte(0xC4); addbyte(0x10); @@ -1702,10 +1675,6 @@ int opcode_0f_modrm[256] = void codegen_debug() { - if (output) - { - pclog("At %04x(%08x):%04x %04x(%08x):%04x es=%08x EAX=%08x BX=%04x ECX=%08x BP=%04x EDX=%08x EDI=%08x\n", CS, cs, cpu_state.pc, SS, ss, ESP, es,EAX, BX,ECX,BP, EDX,EDI); - } } static x86seg *codegen_generate_ea_16_long(x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc) diff --git a/src/cpu/cpu.c b/src/cpu/cpu.c index 1948588..e2aa48a 100644 --- a/src/cpu/cpu.c +++ b/src/cpu/cpu.c @@ -8,7 +8,7 @@ * * CPU type handler. * - * Version: @(#)cpu.c 1.0.7 2018/05/06 + * Version: @(#)cpu.c 1.0.9 2018/09/13 * * Authors: Fred N. van Kempen, * Sarah Walker, @@ -47,6 +47,7 @@ #include "../device.h" #include "../machines/machine.h" #include "../io.h" +#include "x86.h" #include "x86_ops.h" #include "../mem.h" #include "../devices/system/pci.h" @@ -132,9 +133,11 @@ int cpu_waitstates; int cpu_cache_int_enabled, cpu_cache_ext_enabled; int cpu_pci_speed; -int is286, +int is186, + is286, is386, is486, + is_nec, cpu_iscyrix, israpidcad, is_pentium; @@ -243,13 +246,22 @@ cpu_set(void) CPUID = cpu_s->cpuid_model; cpuspeed = cpu_s->speed; is8086 = (cpu_s->cpu_type > CPU_8088); - is286 = (cpu_s->cpu_type >= CPU_286); + is_nec = (cpu_s->cpu_type == CPU_NEC); + is186 = (cpu_s->cpu_type == CPU_186); + is286 = (cpu_s->cpu_type >= CPU_286); is386 = (cpu_s->cpu_type >= CPU_386SX); israpidcad = (cpu_s->cpu_type == CPU_RAPIDCAD); is486 = (cpu_s->cpu_type >= CPU_i486SX) || (cpu_s->cpu_type == CPU_486SLC || cpu_s->cpu_type == CPU_486DLC || cpu_s->cpu_type == CPU_RAPIDCAD); is_pentium= (cpu_s->cpu_type >= CPU_WINCHIP); hasfpu = (cpu_s->cpu_type >= CPU_i486DX) || (cpu_s->cpu_type == CPU_RAPIDCAD); cpu_iscyrix = (cpu_s->cpu_type == CPU_486SLC || cpu_s->cpu_type == CPU_486DLC || cpu_s->cpu_type == CPU_Cx486S || cpu_s->cpu_type == CPU_Cx486DX || cpu_s->cpu_type == CPU_Cx5x86 || cpu_s->cpu_type == CPU_Cx6x86 || cpu_s->cpu_type == CPU_Cx6x86MX || cpu_s->cpu_type == CPU_Cx6x86L || cpu_s->cpu_type == CPU_CxGX1); +DEBUG("CPU: manuf=%d model=%d, cpuid=%08lx speed=%lu\n", + cpu_manufacturer, cpu_effective, CPUID, cpuspeed); +DEBUG(" 8086=%d nec=%d 186=%d 286=%d 386=%d cad=%d 486=%d pent=%d\n", + is8086, is_nec, is186, is286, is386, israpidcad, is486, is_pentium); +DEBUG(" hasfpu=%d cyrix=%d\n", + hasfpu, cpu_iscyrix); + cpu_16bitbus = (cpu_s->cpu_type == CPU_286 || cpu_s->cpu_type == CPU_386SX || cpu_s->cpu_type == CPU_486SLC); if (cpu_s->multi) cpu_busspeed = cpu_s->rspeed / cpu_s->multi; @@ -287,16 +299,12 @@ cpu_set(void) pci_nonburst_time = 4; pci_burst_time = 1; } - pclog("PCI burst=%i nonburst=%i\n", pci_burst_time, pci_nonburst_time); if (cpu_iscyrix) io_sethandler(0x0022, 0x0002, cyrix_read, NULL, NULL, cyrix_write, NULL, NULL, NULL); else io_removehandler(0x0022, 0x0002, cyrix_read, NULL, NULL, cyrix_write, NULL, NULL, NULL); - pclog("hasfpu - %i\n",hasfpu); - pclog("is486 - %i %i\n",is486,cpu_s->cpu_type); - #ifdef USE_DYNAREC x86_setopcodes(ops_386, ops_386_0f, dynarec_ops_386, dynarec_ops_386_0f); #else @@ -399,6 +407,8 @@ cpu_set(void) { case CPU_8088: case CPU_8086: + case CPU_NEC: + case CPU_186: break; case CPU_286: @@ -1336,7 +1346,7 @@ cpu_CPUID(void) EDX = CPUID_FPU; /*FPU*/ } else - EAX = 0; + EAX = EBX = ECX = EDX = 0; break; case CPU_iDX4: @@ -1354,7 +1364,7 @@ cpu_CPUID(void) EDX = CPUID_FPU | CPUID_VME; } else - EAX = 0; + EAX = EBX = ECX = EDX = 0; break; case CPU_Am486SX: @@ -1371,7 +1381,7 @@ cpu_CPUID(void) EBX = ECX = EDX = 0; /*No FPU*/ } else - EAX = 0; + EAX = EBX = ECX = EDX = 0; break; case CPU_Am486DX: @@ -1389,7 +1399,7 @@ cpu_CPUID(void) EDX = CPUID_FPU; /*FPU*/ } else - EAX = 0; + EAX = EBX = ECX = EDX = 0; break; case CPU_WINCHIP: @@ -1420,7 +1430,7 @@ cpu_CPUID(void) EDX |= CPUID_MMX; } else - EAX = 0; + EAX = EBX = ECX = EDX = 0; break; case CPU_PENTIUM: @@ -1438,7 +1448,7 @@ cpu_CPUID(void) EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_CMPXCHG8B; } else - EAX = 0; + EAX = EBX = ECX = EDX = 0; break; #if defined(DEV_BRANCH) && defined(USE_AMD_K) @@ -1457,7 +1467,7 @@ cpu_CPUID(void) EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR | CPUID_CMPXCHG8B; } else - EAX = 0; + EAX = EBX = ECX = EDX = 0; break; case CPU_5K86: @@ -1509,7 +1519,7 @@ cpu_CPUID(void) EDX = 0x10040120; } else - EAX = 0; + EAX = EBX = ECX = EDX = 0; break; case CPU_K6: @@ -1571,7 +1581,7 @@ cpu_CPUID(void) EDX = 0x444D416E; } else - EAX = 0; + EAX = EBX = ECX = EDX = 0; break; #endif @@ -1590,7 +1600,7 @@ cpu_CPUID(void) EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_CMPXCHG8B | CPUID_MMX; } else - EAX = 0; + EAX = EBX = ECX = EDX = 0; break; @@ -1609,7 +1619,7 @@ cpu_CPUID(void) EDX = CPUID_FPU; } else - EAX = 0; + EAX = EBX = ECX = EDX = 0; break; @@ -1628,7 +1638,7 @@ cpu_CPUID(void) EDX = CPUID_FPU | CPUID_CMPXCHG8B; } else - EAX = 0; + EAX = EBX = ECX = EDX = 0; break; @@ -1647,11 +1657,10 @@ cpu_CPUID(void) EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR | CPUID_CMPXCHG8B; } else - EAX = 0; + EAX = EBX = ECX = EDX = 0; break; - case CPU_Cx6x86MX: if (!EAX) { @@ -1667,7 +1676,7 @@ cpu_CPUID(void) EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR | CPUID_CMPXCHG8B | CPUID_CMOV | CPUID_MMX; } else - EAX = 0; + EAX = EBX = ECX = EDX = 0; break; #ifdef DEV_BRANCH @@ -1690,7 +1699,7 @@ cpu_CPUID(void) { } else - EAX = 0; + EAX = EBX = ECX = EDX = 0; break; /* case CPU_PENTIUM2: @@ -1714,7 +1723,7 @@ cpu_CPUID(void) EDX = 0x0C040843; } else - EAX = 0; + EAX = EBX = ECX = EDX = 0; break; */ case CPU_PENTIUM2D: @@ -1738,7 +1747,7 @@ cpu_CPUID(void) EDX = 0x0C040844; } else - EAX = 0; + EAX = EBX = ECX = EDX = 0; break; #endif #endif @@ -1746,7 +1755,7 @@ cpu_CPUID(void) } } -void cpu_RDMSR() +void cpu_RDMSR(void) { switch (machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].cpu_type) { @@ -1807,9 +1816,6 @@ void cpu_RDMSR() EDX = sfmask >> 32; break; default: -#ifndef RELEASE_BUILD - pclog("Invalid MSR: %08X\n", ECX); -#endif x86gpf(NULL, 0); break; } @@ -1960,9 +1966,6 @@ void cpu_RDMSR() break; default: i686_invalid_rdmsr: -#ifndef RELEASE_BUILD - pclog("Invalid MSR: %08X\n", ECX); -#endif x86gpf(NULL, 0); break; } @@ -1972,7 +1975,7 @@ i686_invalid_rdmsr: } } -void cpu_WRMSR() +void cpu_WRMSR(void) { switch (machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].cpu_type) { @@ -2142,9 +2145,6 @@ void cpu_WRMSR() break; default: i686_invalid_wrmsr: -#ifndef RELEASE_BUILD - pclog("Invalid MSR: %08X\n", ECX); -#endif x86gpf(NULL, 0); break; } @@ -2283,7 +2283,7 @@ cpu_update_waitstates(void) cpu_cycles_write_l = (cpu_16bitbus ? 2 : 1) * cpu_s->mem_write_cycles; } if (is486) - cpu_prefetch_cycles *= 4; + cpu_prefetch_cycles = (cpu_prefetch_cycles * 11) / 16; cpu_mem_prefetch_cycles = cpu_prefetch_cycles; if (cpu_s->rspeed <= 8000000) cpu_rom_prefetch_cycles = cpu_mem_prefetch_cycles; diff --git a/src/cpu/cpu.h b/src/cpu/cpu.h index 4e658ac..e8168c9 100644 --- a/src/cpu/cpu.h +++ b/src/cpu/cpu.h @@ -8,7 +8,7 @@ * * CPU type handler. * - * Version: @(#)cpu.h 1.0.6 2018/03/27 + * Version: @(#)cpu.h 1.0.7 2018/09/19 * * Authors: Sarah Walker, * leilei, @@ -42,39 +42,41 @@ #define CPU_8088 0 /* 808x class CPUs */ #define CPU_8086 1 -#define CPU_286 2 /* 286 class CPUs */ -#define CPU_386SX 3 /* 386 class CPUs */ -#define CPU_386DX 4 -#define CPU_RAPIDCAD 5 -#define CPU_486SLC 6 -#define CPU_486DLC 7 -#define CPU_i486SX 8 /* 486 class CPUs */ -#define CPU_Am486SX 9 -#define CPU_Cx486S 10 -#define CPU_i486DX 11 -#define CPU_Am486DX 12 -#define CPU_Cx486DX 13 -#define CPU_iDX4 14 -#define CPU_Cx5x86 15 -#define CPU_WINCHIP 16 /* 586 class CPUs */ -#define CPU_PENTIUM 17 -#define CPU_PENTIUMMMX 18 -#define CPU_Cx6x86 19 -#define CPU_Cx6x86MX 20 -#define CPU_Cx6x86L 21 -#define CPU_CxGX1 22 +#define CPU_NEC 2 /* NEC V20 or V30 */ +#define CPU_186 3 /* 186 class CPUs */ +#define CPU_286 4 /* 286 class CPUs */ +#define CPU_386SX 5 /* 386 class CPUs */ +#define CPU_386DX 6 +#define CPU_RAPIDCAD 7 +#define CPU_486SLC 8 +#define CPU_486DLC 9 +#define CPU_i486SX 10 /* 486 class CPUs */ +#define CPU_Am486SX 11 +#define CPU_Cx486S 12 +#define CPU_i486DX 13 +#define CPU_Am486DX 14 +#define CPU_Cx486DX 15 +#define CPU_iDX4 16 +#define CPU_Cx5x86 17 +#define CPU_WINCHIP 18 /* 586 class CPUs */ +#define CPU_PENTIUM 19 +#define CPU_PENTIUMMMX 20 +#define CPU_Cx6x86 21 +#define CPU_Cx6x86MX 22 +#define CPU_Cx6x86L 23 +#define CPU_CxGX1 24 #if defined(DEV_BRANCH) && defined(USE_AMD_K) -#define CPU_K5 23 -#define CPU_5K86 24 -#define CPU_K6 25 +#define CPU_K5 25 +#define CPU_5K86 26 +#define CPU_K6 27 #endif #if defined(DEV_BRANCH) && defined(USE_I686) -#define CPU_PENTIUMPRO 26 /* 686 class CPUs */ +#define CPU_PENTIUMPRO 28 /* 686 class CPUs */ #if 0 -# define CPU_PENTIUM2 27 -# define CPU_PENTIUM2D 28 +# define CPU_PENTIUM2 29 +# define CPU_PENTIUM2D 30 #else -# define CPU_PENTIUM2D 27 +# define CPU_PENTIUM2D 29 #endif #endif @@ -82,6 +84,7 @@ #define MANU_AMD 1 #define MANU_CYRIX 2 #define MANU_IDT 3 +#define MANU_NEC 4 #define CPU_SUPPORTS_DYNAREC 1 #define CPU_REQUIRES_DYNAREC 2 @@ -105,6 +108,8 @@ typedef struct { extern CPU cpus_8088[]; extern CPU cpus_8086[]; +extern CPU cpus_nec[]; +extern CPU cpus_186[]; extern CPU cpus_286[]; extern CPU cpus_i386SX[]; extern CPU cpus_i386DX[]; @@ -202,7 +207,7 @@ typedef union { } cr0_t; -struct _cpustate_ { +typedef struct { x86reg regs[8]; uint8_t tag[8]; @@ -249,7 +254,9 @@ struct _cpustate_ { uint16_t old_npxc, new_npxc; uint32_t last_ea; -} cpu_state; +} cpu_state_t; + +extern cpu_state_t cpu_state; /*The flags below must match in both cpu_cur_status and block->status for a block to be valid*/ @@ -315,15 +322,15 @@ COMPILE_TIME_ASSERT(sizeof(cpu_state) <= 128) /* Global variables. */ -extern int cpu_iscyrix; -extern int cpu_16bitbus; -extern int cpu_busspeed; -extern int cpu_multi; -extern int cpu_cyrix_alignment; /*Cyrix 5x86/6x86 only has data misalignment +extern int cpu_iscyrix; +extern int cpu_16bitbus; +extern int cpu_busspeed; +extern int cpu_multi; +extern int cpu_cyrix_alignment; /*Cyrix 5x86/6x86 only has data misalignment penalties when crossing 8-byte boundaries*/ -extern int is8086, is286, is386, is486; -extern int is_rapidcad, is_pentium; +extern int is8086, is186, is286, is386, is486; +extern int is_nec, is_rapidcad, is_pentium; extern int hasfpu; extern int cpu_hasrdtsc; extern int cpu_hasMSR; @@ -338,7 +345,6 @@ extern msr_t msr; extern int cpuspeed; extern int cycles_lost; extern uint8_t opcode; -extern int insc; extern int fpucount; extern float mips,flops; extern int clockrate; diff --git a/src/cpu/cpu_table.c b/src/cpu/cpu_table.c index 0460cd2..9887136 100644 --- a/src/cpu/cpu_table.c +++ b/src/cpu/cpu_table.c @@ -8,7 +8,7 @@ * * Define all known processor types. * - * Version: @(#)cpu_table.c 1.0.4 2018/04/29 + * Version: @(#)cpu_table.c 1.0.5 2018/09/09 * * Authors: Sarah Walker, * Miran Grca, @@ -48,15 +48,11 @@ CPU cpus_8088[] = { /*8088 standard*/ {"8088/4.77", CPU_8088, 0, 4772728, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1}, - {"8088/8", CPU_8088, 1, 8000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1}, -#if 0 {"8088/7.16", CPU_8088, 1, 14318184/2, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1}, -#endif + {"8088/8", CPU_8088, 1, 8000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1}, {"8088/10", CPU_8088, 2, 10000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1}, -#if 0 {"8088/12", CPU_8088, 3, 12000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1}, {"8088/16", CPU_8088, 4, 16000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1}, -#endif {"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0,0,0,0} }; @@ -85,6 +81,30 @@ CPU cpus_8086[] = { {"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0,0,0,0} }; +CPU cpus_nec[] = { + /*NEC V20/30 standard*/ + {"V20/7.16", CPU_NEC, 1, 14318184/2, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1}, + {"V20/8", CPU_NEC, 1, 8000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1}, + {"V20/9.54", CPU_NEC, 1, 4772728*2, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1}, + {"V20/10", CPU_NEC, 2, 10000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1}, + {"V20/12", CPU_NEC, 3, 12000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1}, + {"V20/16", CPU_NEC, 4, 16000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 2}, + {"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0,0,0,0} +}; + +CPU cpus_186[] = { + /*80186 standard*/ + {"80186/7.16", CPU_186, 1, 14318184/2, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1}, + {"80186/8", CPU_186, 1, 8000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1}, + {"80186/9.54", CPU_186, 1, 4772728*2, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1}, + {"80186/10", CPU_186, 2, 10000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1}, + {"80186/12", CPU_186, 3, 12000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1}, + {"80186/16", CPU_186, 4, 16000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 2}, + {"80186/20", CPU_186, 5, 20000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 3}, + {"80186/25", CPU_186, 6, 25000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 3}, + {"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0,0,0,0} +}; + CPU cpus_pc1512[] = { /*8086 Amstrad*/ {"8086/8", CPU_8086, 1, 8000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1}, diff --git a/src/cpu/x86.h b/src/cpu/x86.h index 704bd12..f3aca86 100644 --- a/src/cpu/x86.h +++ b/src/cpu/x86.h @@ -8,7 +8,7 @@ * * Definitions for the X86 architecture. * - * Version: @(#)x86.h 1.0.1 2018/02/14 + * Version: @(#)x86.h 1.0.1 2018/02/19 * * Authors: Sarah Walker, * Miran Grca, @@ -34,25 +34,37 @@ * Boston, MA 02111-1307 * USA. */ -uint16_t oldcs; + + +#ifdef _MSC_VER +# pragma check_stack(off) +# pragma inline_recursion(on) +//# define INLINE __forceinline +# define INLINE __inline +#else +# define INLINE __inline +#endif + + +extern uint16_t oldcs; extern uint32_t rmdat32; -int oldcpl; +extern int oldcpl; extern int nmi_enable; -int tempc; -int output; -int firstrepcycle; +extern int tempc; +extern int output; +extern int firstrepcycle; -uint32_t easeg,ealimit,ealimitw; +extern uint32_t easeg,ealimit,ealimitw; -int skipnextprint; -int inhlt; +extern int skipnextprint; +extern int inhlt; -uint8_t opcode; -int noint; +extern uint8_t opcode; +extern int noint; -uint16_t lastcs,lastpc; +extern uint16_t lastcs,lastpc; extern int timetolive,keyboardtimer; #define setznp168 setznp16 @@ -66,11 +78,11 @@ extern int timetolive,keyboardtimer; #define setr16(r,v) cpu_state.regs[r].w=v #define setr32(r,v) cpu_state.regs[r].l=v -uint8_t znptable8[256]; -uint16_t znptable16[65536]; +extern uint8_t znptable8[256]; +extern uint16_t znptable16[65536]; -int use32; -int stack32; +extern int use32; +extern int stack32; #define fetchea() { rmdat=readmemb(cs+pc); pc++; \ reg=(rmdat>>3)&7; \ @@ -79,13 +91,13 @@ int stack32; if (mod!=3) fetcheal(); } -int optype; +extern int optype; #define JMP 1 #define CALL 2 #define IRET 3 #define OPTYPE_INT 4 -uint32_t oxpc; +extern uint32_t oxpc; extern uint16_t *mod1add[2][8]; extern uint32_t *mod1seg[8]; @@ -121,7 +133,7 @@ enum extern uint32_t abrt_error; -void x86_doabrt(int x86_abrt); +extern void x86_doabrt(int x86_abrt); extern uint8_t opcode2; @@ -130,10 +142,10 @@ extern uint32_t rmdat32; extern int inscounts[256]; -void x86illegal(); +extern void x86illegal(); -void x86seg_reset(); -void x86gpf(char *s, uint16_t error); +extern void x86seg_reset(); +extern void x86gpf(char *s, uint16_t error); extern uint16_t zero; diff --git a/src/cpu/x86_flags.h b/src/cpu/x86_flags.h index 03ec290..d6c9797 100644 --- a/src/cpu/x86_flags.h +++ b/src/cpu/x86_flags.h @@ -72,7 +72,7 @@ enum FLAGS_DEC32 }; -static __inline int ZF_SET() +static INLINE int ZF_SET() { switch (cpu_state.flags_op) { @@ -110,7 +110,7 @@ static __inline int ZF_SET() } } -static __inline int NF_SET() +static INLINE int NF_SET() { switch (cpu_state.flags_op) { @@ -152,7 +152,7 @@ static __inline int NF_SET() } } -static __inline int PF_SET() +static INLINE int PF_SET() { switch (cpu_state.flags_op) { @@ -190,7 +190,7 @@ static __inline int PF_SET() } } -static __inline int VF_SET() +static INLINE int VF_SET() { switch (cpu_state.flags_op) { @@ -244,7 +244,7 @@ static __inline int VF_SET() } } -static __inline int AF_SET() +static INLINE int AF_SET() { switch (cpu_state.flags_op) { @@ -286,7 +286,7 @@ static __inline int AF_SET() } } -static __inline int CF_SET() +static INLINE int CF_SET() { switch (cpu_state.flags_op) { @@ -340,7 +340,7 @@ static __inline int CF_SET() } } -static __inline void flags_rebuild() +static INLINE void flags_rebuild() { if (cpu_state.flags_op != FLAGS_UNKNOWN) { @@ -356,12 +356,12 @@ static __inline void flags_rebuild() } } -static __inline void flags_extract() +static INLINE void flags_extract() { cpu_state.flags_op = FLAGS_UNKNOWN; } -static __inline void flags_rebuild_c() +static INLINE void flags_rebuild_c() { if (cpu_state.flags_op != FLAGS_UNKNOWN) { @@ -372,17 +372,17 @@ static __inline void flags_rebuild_c() } } -static __inline void setznp8(uint8_t val) +static INLINE void setznp8(uint8_t val) { cpu_state.flags_op = FLAGS_ZN8; cpu_state.flags_res = val; } -static __inline void setznp16(uint16_t val) +static INLINE void setznp16(uint16_t val) { cpu_state.flags_op = FLAGS_ZN16; cpu_state.flags_res = val; } -static __inline void setznp32(uint32_t val) +static INLINE void setznp32(uint32_t val) { cpu_state.flags_op = FLAGS_ZN32; cpu_state.flags_res = val; @@ -394,28 +394,28 @@ static __inline void setznp32(uint32_t val) cpu_state.flags_op1 = orig; \ cpu_state.flags_op2 = shift; -static __inline void setadd8(uint8_t a, uint8_t b) +static INLINE void setadd8(uint8_t a, uint8_t b) { cpu_state.flags_op1 = a; cpu_state.flags_op2 = b; cpu_state.flags_res = (a + b) & 0xff; cpu_state.flags_op = FLAGS_ADD8; } -static __inline void setadd16(uint16_t a, uint16_t b) +static INLINE void setadd16(uint16_t a, uint16_t b) { cpu_state.flags_op1 = a; cpu_state.flags_op2 = b; cpu_state.flags_res = (a + b) & 0xffff; cpu_state.flags_op = FLAGS_ADD16; } -static __inline void setadd32(uint32_t a, uint32_t b) +static INLINE void setadd32(uint32_t a, uint32_t b) { cpu_state.flags_op1 = a; cpu_state.flags_op2 = b; cpu_state.flags_res = a + b; cpu_state.flags_op = FLAGS_ADD32; } -static __inline void setadd8nc(uint8_t a, uint8_t b) +static INLINE void setadd8nc(uint8_t a, uint8_t b) { flags_rebuild_c(); cpu_state.flags_op1 = a; @@ -423,7 +423,7 @@ static __inline void setadd8nc(uint8_t a, uint8_t b) cpu_state.flags_res = (a + b) & 0xff; cpu_state.flags_op = FLAGS_INC8; } -static __inline void setadd16nc(uint16_t a, uint16_t b) +static INLINE void setadd16nc(uint16_t a, uint16_t b) { flags_rebuild_c(); cpu_state.flags_op1 = a; @@ -431,7 +431,7 @@ static __inline void setadd16nc(uint16_t a, uint16_t b) cpu_state.flags_res = (a + b) & 0xffff; cpu_state.flags_op = FLAGS_INC16; } -static __inline void setadd32nc(uint32_t a, uint32_t b) +static INLINE void setadd32nc(uint32_t a, uint32_t b) { flags_rebuild_c(); cpu_state.flags_op1 = a; @@ -440,21 +440,21 @@ static __inline void setadd32nc(uint32_t a, uint32_t b) cpu_state.flags_op = FLAGS_INC32; } -static __inline void setsub8(uint8_t a, uint8_t b) +static INLINE void setsub8(uint8_t a, uint8_t b) { cpu_state.flags_op1 = a; cpu_state.flags_op2 = b; cpu_state.flags_res = (a - b) & 0xff; cpu_state.flags_op = FLAGS_SUB8; } -static __inline void setsub16(uint16_t a, uint16_t b) +static INLINE void setsub16(uint16_t a, uint16_t b) { cpu_state.flags_op1 = a; cpu_state.flags_op2 = b; cpu_state.flags_res = (a - b) & 0xffff; cpu_state.flags_op = FLAGS_SUB16; } -static __inline void setsub32(uint32_t a, uint32_t b) +static INLINE void setsub32(uint32_t a, uint32_t b) { cpu_state.flags_op1 = a; cpu_state.flags_op2 = b; @@ -462,7 +462,7 @@ static __inline void setsub32(uint32_t a, uint32_t b) cpu_state.flags_op = FLAGS_SUB32; } -static __inline void setsub8nc(uint8_t a, uint8_t b) +static INLINE void setsub8nc(uint8_t a, uint8_t b) { flags_rebuild_c(); cpu_state.flags_op1 = a; @@ -470,7 +470,7 @@ static __inline void setsub8nc(uint8_t a, uint8_t b) cpu_state.flags_res = (a - b) & 0xff; cpu_state.flags_op = FLAGS_DEC8; } -static __inline void setsub16nc(uint16_t a, uint16_t b) +static INLINE void setsub16nc(uint16_t a, uint16_t b) { flags_rebuild_c(); cpu_state.flags_op1 = a; @@ -478,7 +478,7 @@ static __inline void setsub16nc(uint16_t a, uint16_t b) cpu_state.flags_res = (a - b) & 0xffff; cpu_state.flags_op = FLAGS_DEC16; } -static __inline void setsub32nc(uint32_t a, uint32_t b) +static INLINE void setsub32nc(uint32_t a, uint32_t b) { flags_rebuild_c(); cpu_state.flags_op1 = a; @@ -487,7 +487,7 @@ static __inline void setsub32nc(uint32_t a, uint32_t b) cpu_state.flags_op = FLAGS_DEC32; } -static __inline void setadc8(uint8_t a, uint8_t b) +static INLINE void setadc8(uint8_t a, uint8_t b) { uint16_t c=(uint16_t)a+(uint16_t)b+tempc; cpu_state.flags_op = FLAGS_UNKNOWN; @@ -497,7 +497,7 @@ static __inline void setadc8(uint8_t a, uint8_t b) if (!((a^b)&0x80)&&((a^c)&0x80)) flags|=V_FLAG; if (((a&0xF)+(b&0xF))&0x10) flags|=A_FLAG; } -static __inline void setadc16(uint16_t a, uint16_t b) +static INLINE void setadc16(uint16_t a, uint16_t b) { uint32_t c=(uint32_t)a+(uint32_t)b+tempc; cpu_state.flags_op = FLAGS_UNKNOWN; @@ -508,7 +508,7 @@ static __inline void setadc16(uint16_t a, uint16_t b) if (((a&0xF)+(b&0xF))&0x10) flags|=A_FLAG; } -static __inline void setsbc8(uint8_t a, uint8_t b) +static INLINE void setsbc8(uint8_t a, uint8_t b) { uint16_t c=(uint16_t)a-(((uint16_t)b)+tempc); cpu_state.flags_op = FLAGS_UNKNOWN; @@ -518,7 +518,7 @@ static __inline void setsbc8(uint8_t a, uint8_t b) if ((a^b)&(a^c)&0x80) flags|=V_FLAG; if (((a&0xF)-(b&0xF))&0x10) flags|=A_FLAG; } -static __inline void setsbc16(uint16_t a, uint16_t b) +static INLINE void setsbc16(uint16_t a, uint16_t b) { uint32_t c=(uint32_t)a-(((uint32_t)b)+tempc); cpu_state.flags_op = FLAGS_UNKNOWN; @@ -530,7 +530,7 @@ static __inline void setsbc16(uint16_t a, uint16_t b) if (((a&0xF)-(b&0xF))&0x10) flags|=A_FLAG; } -static __inline void setadc32(uint32_t a, uint32_t b) +static INLINE void setadc32(uint32_t a, uint32_t b) { uint32_t c=(uint32_t)a+(uint32_t)b+tempc; cpu_state.flags_op = FLAGS_UNKNOWN; @@ -541,7 +541,7 @@ static __inline void setadc32(uint32_t a, uint32_t b) if (!((a^b)&0x80000000)&&((a^c)&0x80000000)) flags|=V_FLAG; if (((a&0xF)+(b&0xF)+tempc)&0x10) flags|=A_FLAG; } -static __inline void setsbc32(uint32_t a, uint32_t b) +static INLINE void setsbc32(uint32_t a, uint32_t b) { uint32_t c=(uint32_t)a-(((uint32_t)b)+tempc); cpu_state.flags_op = FLAGS_UNKNOWN; diff --git a/src/cpu/x86_ops_amd.h b/src/cpu/x86_ops_amd.h index 9b73682..1a42f0c 100644 --- a/src/cpu/x86_ops_amd.h +++ b/src/cpu/x86_ops_amd.h @@ -8,7 +8,7 @@ * * AMD SYSCALL and SYSRET CPU Instructions. * - * Version: @(#)x86_ops_amd.h 1.0.1 2018/02/14 + * Version: @(#)x86_ops_amd.h 1.0.2 2018/10/05 * * Author: Miran Grca, * @@ -32,12 +32,17 @@ * Boston, MA 02111-1307 * USA. */ + + +#ifndef HAVE_INTERNAL_ILLEGAL +# define HAVE_INTERNAL_ILLEGAL static int internal_illegal(char *s) { cpu_state.pc = cpu_state.oldpc; x86gpf(s, 0); return cpu_state.abrt; } +#endif /* 0 = Limit 0-15 1 = Base 0-15 @@ -80,7 +85,7 @@ static int opSYSCALL(uint32_t fetchdat) { if (_cs.seg >= ldt.limit) { - pclog("Bigger than LDT limit %04X %04X CS\n",AMD_SYSCALL_SB,ldt.limit); + ERRLOG("CPU: bigger than LDT limit %04X %04X CS\n",AMD_SYSCALL_SB,ldt.limit); x86gpf(NULL, AMD_SYSCALL_SB & ~3); return 1; } @@ -90,7 +95,7 @@ static int opSYSCALL(uint32_t fetchdat) { if (_cs.seg >= gdt.limit) { - pclog("Bigger than GDT limit %04X %04X CS\n",AMD_SYSCALL_SB,gdt.limit); + ERRLOG("CPU: bigger than GDT limit %04X %04X CS\n",AMD_SYSCALL_SB,gdt.limit); x86gpf(NULL, AMD_SYSCALL_SB & ~3); return 1; } @@ -158,7 +163,7 @@ static int opSYSRET(uint32_t fetchdat) { if (_cs.seg >= ldt.limit) { - pclog("Bigger than LDT limit %04X %04X CS\n",AMD_SYSRET_SB,ldt.limit); + ERRLOG("CPU: bigger than LDT limit %04X %04X CS\n",AMD_SYSRET_SB,ldt.limit); x86gpf(NULL, AMD_SYSRET_SB & ~3); return 1; } @@ -168,7 +173,7 @@ static int opSYSRET(uint32_t fetchdat) { if (_cs.seg >= gdt.limit) { - pclog("Bigger than GDT limit %04X %04X CS\n",AMD_SYSRET_SB,gdt.limit); + ERRLOG("CPU: bigger than GDT limit %04X %04X CS\n",AMD_SYSRET_SB,gdt.limit); x86gpf(NULL, AMD_SYSRET_SB & ~3); return 1; } diff --git a/src/cpu/x86_ops_arith.h b/src/cpu/x86_ops_arith.h index 82c248a..caf172a 100644 --- a/src/cpu/x86_ops_arith.h +++ b/src/cpu/x86_ops_arith.h @@ -8,7 +8,7 @@ * * Miscellaneous x86 CPU Instructions. * - * Version: @(#)x86_ops_arith.h 1.0.1 2018/02/14 + * Version: @(#)x86_ops_arith.h 1.0.2 2018/10/05 * * Authors: Sarah Walker, * Miran Grca, diff --git a/src/cpu/x86_ops_bit.h b/src/cpu/x86_ops_bit.h index 66f1df3..8589b0c 100644 --- a/src/cpu/x86_ops_bit.h +++ b/src/cpu/x86_ops_bit.h @@ -8,7 +8,7 @@ * * Miscellaneous x86 CPU Instructions. * - * Version: @(#)x86_ops_bit.h 1.0.1 2018/02/14 + * Version: @(#)x86_ops_bit.h 1.0.2 2018/10/05 * * Authors: Sarah Walker, * Miran Grca, @@ -208,7 +208,7 @@ static int opBA_w_a16(uint32_t fetchdat) break; default: - pclog("Bad 0F BA opcode %02X\n", rmdat & 0x38); + ERRLOG("CPU: bad 0F BA opcode %02X\n", rmdat & 0x38); cpu_state.pc = cpu_state.oldpc; x86illegal(); break; @@ -250,7 +250,7 @@ static int opBA_w_a32(uint32_t fetchdat) break; default: - pclog("Bad 0F BA opcode %02X\n", rmdat & 0x38); + ERRLOG("CPU: bad 0F BA opcode %02X\n", rmdat & 0x38); cpu_state.pc = cpu_state.oldpc; x86illegal(); break; @@ -293,7 +293,7 @@ static int opBA_l_a16(uint32_t fetchdat) break; default: - pclog("Bad 0F BA opcode %02X\n", rmdat & 0x38); + ERRLOG("CPU: bad 0F BA opcode %02X\n", rmdat & 0x38); cpu_state.pc = cpu_state.oldpc; x86illegal(); break; @@ -335,7 +335,7 @@ static int opBA_l_a32(uint32_t fetchdat) break; default: - pclog("Bad 0F BA opcode %02X\n", rmdat & 0x38); + ERRLOG("CPU: bad 0F BA opcode %02X\n", rmdat & 0x38); cpu_state.pc = cpu_state.oldpc; x86illegal(); break; diff --git a/src/cpu/x86_ops_i686.h b/src/cpu/x86_ops_i686.h index 0495f5a..773676c 100644 --- a/src/cpu/x86_ops_i686.h +++ b/src/cpu/x86_ops_i686.h @@ -8,7 +8,7 @@ * * x86 i686 (Pentium Pro/Pentium II) CPU Instructions. * - * Version: @(#)x86_ops_i686.h 1.0.1 2018/02/14 + * Version: @(#)x86_ops_i686.h 1.0.2 2018/10/05 * * Author: Miran Grca, * @@ -33,6 +33,18 @@ * USA. */ + +#ifndef HAVE_INTERNAL_ILLEGAL +# define HAVE_INTERNAL_ILLEGAL +static int internal_illegal(char *s) +{ + cpu_state.pc = cpu_state.oldpc; + x86gpf(s, 0); + return cpu_state.abrt; +} +#endif + + /* 0 = Limit 0-15 1 = Base 0-15 2 = Base 16-23 (bits 0-7), Access rights @@ -59,18 +71,18 @@ static int opSYSENTER(uint32_t fetchdat) uint16_t sysenter_ss_seg_data[4]; #ifdef SYSENTER_LOG - pclog("SYSENTER called\n"); + DEBUG("SYSENTER called\n"); #endif if (!(cr0 & 1)) return internal_illegal("SYSENTER: CPU not in protected mode"); if (!(cs_msr & 0xFFFC)) return internal_illegal("SYSENTER: CS MSR is zero"); #ifdef SYSENTER_LOG - pclog("SYSENTER started:\n"); - pclog("CS (%04X): base=%08X, limit=%08X, access=%02X, seg=%04X, limit_low=%08X, limit_high=%08X, checked=%i\n", CS, _cs.base, _cs.limit, _cs.access, _cs.seg, _cs.limit_low, _cs.limit_high, _cs.checked); - pclog("SS (%04X): base=%08X, limit=%08X, access=%02X, seg=%04X, limit_low=%08X, limit_high=%08X, checked=%i\n", SS, _ss.base, _ss.limit, _ss.access, _ss.seg, _ss.limit_low, _ss.limit_high, _ss.checked); - pclog("Model specific registers: cs_msr=%04X, esp_msr=%08X, eip_msr=%08X\n", cs_msr, esp_msr, eip_msr); - pclog("Other information: eip=%08X esp=%08X eflags=%04X flags=%04X use32=%04X stack32=%i\n", cpu_state.pc, ESP, eflags, flags, use32, stack32); + DEBUG("SYSENTER started:\n"); + DEBUG("CS (%04X): base=%08X, limit=%08X, access=%02X, seg=%04X, limit_low=%08X, limit_high=%08X, checked=%i\n", CS, _cs.base, _cs.limit, _cs.access, _cs.seg, _cs.limit_low, _cs.limit_high, _cs.checked); + DEBUG("SS (%04X): base=%08X, limit=%08X, access=%02X, seg=%04X, limit_low=%08X, limit_high=%08X, checked=%i\n", SS, _ss.base, _ss.limit, _ss.access, _ss.seg, _ss.limit_low, _ss.limit_high, _ss.checked); + DEBUG("Model specific registers: cs_msr=%04X, esp_msr=%08X, eip_msr=%08X\n", cs_msr, esp_msr, eip_msr); + DEBUG("Other information: eip=%08X esp=%08X eflags=%04X flags=%04X use32=%04X stack32=%i\n", cpu_state.pc, ESP, eflags, flags, use32, stack32); #endif if (cpu_state.abrt) return 1; @@ -102,11 +114,11 @@ static int opSYSENTER(uint32_t fetchdat) CPU_BLOCK_END(); #ifdef SYSENTER_LOG - pclog("SYSENTER completed:\n"); - pclog("CS (%04X): base=%08X, limit=%08X, access=%02X, seg=%04X, limit_low=%08X, limit_high=%08X, checked=%i\n", CS, _cs.base, _cs.limit, _cs.access, _cs.seg, _cs.limit_low, _cs.limit_high, _cs.checked); - pclog("SS (%04X): base=%08X, limit=%08X, access=%02X, seg=%04X, limit_low=%08X, limit_high=%08X, checked=%i\n", SS, _ss.base, _ss.limit, _ss.access, _ss.seg, _ss.limit_low, _ss.limit_high, _ss.checked); - pclog("Model specific registers: cs_msr=%04X, esp_msr=%08X, eip_msr=%08X\n", cs_msr, esp_msr, eip_msr); - pclog("Other information: eip=%08X esp=%08X eflags=%04X flags=%04X use32=%04X stack32=%i\n", cpu_state.pc, ESP, eflags, flags, use32, stack32); + DEBUG("SYSENTER completed:\n"); + DEBUG("CS (%04X): base=%08X, limit=%08X, access=%02X, seg=%04X, limit_low=%08X, limit_high=%08X, checked=%i\n", CS, _cs.base, _cs.limit, _cs.access, _cs.seg, _cs.limit_low, _cs.limit_high, _cs.checked); + DEBUG("SS (%04X): base=%08X, limit=%08X, access=%02X, seg=%04X, limit_low=%08X, limit_high=%08X, checked=%i\n", SS, _ss.base, _ss.limit, _ss.access, _ss.seg, _ss.limit_low, _ss.limit_high, _ss.checked); + DEBUG("Model specific registers: cs_msr=%04X, esp_msr=%08X, eip_msr=%08X\n", cs_msr, esp_msr, eip_msr); + DEBUG("Other information: eip=%08X esp=%08X eflags=%04X flags=%04X use32=%04X stack32=%i\n", cpu_state.pc, ESP, eflags, flags, use32, stack32); #endif return 0; @@ -118,7 +130,7 @@ static int opSYSEXIT(uint32_t fetchdat) uint16_t sysexit_ss_seg_data[4]; #ifdef SYSEXIT_LOG - pclog("SYSEXIT called\n"); + DEBUG("SYSEXIT called\n"); #endif if (!(cs_msr & 0xFFFC)) return internal_illegal("SYSEXIT: CS MSR is zero"); @@ -126,11 +138,11 @@ static int opSYSEXIT(uint32_t fetchdat) if (CS & 3) return internal_illegal("SYSEXIT: CPL not 0"); #ifdef SYSEXIT_LOG - pclog("SYSEXIT start:\n"); - pclog("CS (%04X): base=%08X, limit=%08X, access=%02X, seg=%04X, limit_low=%08X, limit_high=%08X, checked=%i\n", CS, _cs.base, _cs.limit, _cs.access, _cs.seg, _cs.limit_low, _cs.limit_high, _cs.checked); - pclog("SS (%04X): base=%08X, limit=%08X, access=%02X, seg=%04X, limit_low=%08X, limit_high=%08X, checked=%i\n", SS, _ss.base, _ss.limit, _ss.access, _ss.seg, _ss.limit_low, _ss.limit_high, _ss.checked); - pclog("Model specific registers: cs_msr=%04X, esp_msr=%08X, eip_msr=%08X\n", cs_msr, esp_msr, eip_msr); - pclog("Other information: eip=%08X esp=%08X eflags=%04X flags=%04X use32=%04X stack32=%i ECX=%08X EDX=%08X\n", cpu_state.pc, ESP, eflags, flags, use32, stack32, ECX, EDX); + DEBUG("SYSEXIT start:\n"); + DEBUG("CS (%04X): base=%08X, limit=%08X, access=%02X, seg=%04X, limit_low=%08X, limit_high=%08X, checked=%i\n", CS, _cs.base, _cs.limit, _cs.access, _cs.seg, _cs.limit_low, _cs.limit_high, _cs.checked); + DEBUG("SS (%04X): base=%08X, limit=%08X, access=%02X, seg=%04X, limit_low=%08X, limit_high=%08X, checked=%i\n", SS, _ss.base, _ss.limit, _ss.access, _ss.seg, _ss.limit_low, _ss.limit_high, _ss.checked); + DEBUG("Model specific registers: cs_msr=%04X, esp_msr=%08X, eip_msr=%08X\n", cs_msr, esp_msr, eip_msr); + DEBUG("Other information: eip=%08X esp=%08X eflags=%04X flags=%04X use32=%04X stack32=%i ECX=%08X EDX=%08X\n", cpu_state.pc, ESP, eflags, flags, use32, stack32, ECX, EDX); #endif if (cpu_state.abrt) return 1; @@ -160,11 +172,11 @@ static int opSYSEXIT(uint32_t fetchdat) CPU_BLOCK_END(); #ifdef SYSEXIT_LOG - pclog("SYSEXIT completed:\n"); - pclog("CS (%04X): base=%08X, limit=%08X, access=%02X, seg=%04X, limit_low=%08X, limit_high=%08X, checked=%i\n", CS, _cs.base, _cs.limit, _cs.access, _cs.seg, _cs.limit_low, _cs.limit_high, _cs.checked); - pclog("SS (%04X): base=%08X, limit=%08X, access=%02X, seg=%04X, limit_low=%08X, limit_high=%08X, checked=%i\n", SS, _ss.base, _ss.limit, _ss.access, _ss.seg, _ss.limit_low, _ss.limit_high, _ss.checked); - pclog("Model specific registers: cs_msr=%04X, esp_msr=%08X, eip_msr=%08X\n", cs_msr, esp_msr, eip_msr); - pclog("Other information: eip=%08X esp=%08X eflags=%04X flags=%04X use32=%04X stack32=%i ECX=%08X EDX=%08X\n", cpu_state.pc, ESP, eflags, flags, use32, stack32, ECX, EDX); + DEBUG("SYSEXIT completed:\n"); + DEBUG("CS (%04X): base=%08X, limit=%08X, access=%02X, seg=%04X, limit_low=%08X, limit_high=%08X, checked=%i\n", CS, _cs.base, _cs.limit, _cs.access, _cs.seg, _cs.limit_low, _cs.limit_high, _cs.checked); + DEBUG("SS (%04X): base=%08X, limit=%08X, access=%02X, seg=%04X, limit_low=%08X, limit_high=%08X, checked=%i\n", SS, _ss.base, _ss.limit, _ss.access, _ss.seg, _ss.limit_low, _ss.limit_high, _ss.checked); + DEBUG("Model specific registers: cs_msr=%04X, esp_msr=%08X, eip_msr=%08X\n", cs_msr, esp_msr, eip_msr); + DEBUG("Other information: eip=%08X esp=%08X eflags=%04X flags=%04X use32=%04X stack32=%i ECX=%08X EDX=%08X\n", cpu_state.pc, ESP, eflags, flags, use32, stack32, ECX, EDX); #endif return 0; @@ -188,7 +200,7 @@ static int opFXSAVESTOR_a16(uint32_t fetchdat) if (cpu_state.eaaddr & 0xf) { - pclog("Effective address %04X not on 16-byte boundary\n", cpu_state.eaaddr); + ERRLOG("CPU: effective address %04X not on 16-byte boundary\n", cpu_state.eaaddr); x86gpf(NULL, 0); return cpu_state.abrt; } @@ -281,7 +293,7 @@ static int opFXSAVESTOR_a16(uint32_t fetchdat) CLOCK_CYCLES((cr0 & 1) ? 34 : 44); - if(cpu_state.abrt) pclog("FXRSTOR: abrt != 0\n"); + if(cpu_state.abrt) ERRLOG("FXRSTOR: abrt != 0\n"); } else { @@ -342,7 +354,7 @@ static int opFXSAVESTOR_a16(uint32_t fetchdat) CLOCK_CYCLES((cr0 & 1) ? 56 : 67); - if(cpu_state.abrt) pclog("FXSAVE: abrt != 0\n"); + if(cpu_state.abrt) ERRLOG("FXSAVE: abrt != 0\n"); } return cpu_state.abrt; @@ -366,7 +378,7 @@ static int opFXSAVESTOR_a32(uint32_t fetchdat) if (cpu_state.eaaddr & 0xf) { - pclog("Effective address %08X not on 16-byte boundary\n", cpu_state.eaaddr); + ERRLOG("CPU: effective address %08X not on 16-byte boundary\n", cpu_state.eaaddr); x86gpf(NULL, 0); return cpu_state.abrt; } @@ -459,7 +471,7 @@ static int opFXSAVESTOR_a32(uint32_t fetchdat) CLOCK_CYCLES((cr0 & 1) ? 34 : 44); - if(cpu_state.abrt) pclog("FXRSTOR: abrt != 0\n"); + if(cpu_state.abrt) ERRLOG("FXRSTOR: abrt != 0\n"); } else { @@ -520,7 +532,7 @@ static int opFXSAVESTOR_a32(uint32_t fetchdat) CLOCK_CYCLES((cr0 & 1) ? 56 : 67); - if(cpu_state.abrt) pclog("FXSAVE: abrt != 0\n"); + if(cpu_state.abrt) ERRLOG("FXSAVE: abrt != 0\n"); } return cpu_state.abrt; diff --git a/src/cpu/x86_ops_misc.h b/src/cpu/x86_ops_misc.h index fe46f5c..9f1960a 100644 --- a/src/cpu/x86_ops_misc.h +++ b/src/cpu/x86_ops_misc.h @@ -8,7 +8,7 @@ * * Miscellaneous x86 CPU Instructions. * - * Version: @(#)x86_ops_misc.h 1.0.1 2018/02/14 + * Version: @(#)x86_ops_misc.h 1.0.2 2018/10/05 * * Authors: Sarah Walker, * Miran Grca, @@ -35,6 +35,7 @@ * USA. */ + static int opCBW(uint32_t fetchdat) { AH = (AL & 0x80) ? 0xff : 0; @@ -42,6 +43,8 @@ static int opCBW(uint32_t fetchdat) PREFETCH_RUN(3, 1, -1, 0,0,0,0, 0); return 0; } + + static int opCWDE(uint32_t fetchdat) { EAX = (AX & 0x8000) ? (0xffff0000 | AX) : AX; @@ -49,6 +52,8 @@ static int opCWDE(uint32_t fetchdat) PREFETCH_RUN(3, 1, -1, 0,0,0,0, 0); return 0; } + + static int opCWD(uint32_t fetchdat) { DX = (AX & 0x8000) ? 0xFFFF : 0; @@ -56,6 +61,8 @@ static int opCWD(uint32_t fetchdat) PREFETCH_RUN(2, 1, -1, 0,0,0,0, 0); return 0; } + + static int opCDQ(uint32_t fetchdat) { EDX = (EAX & 0x80000000) ? 0xffffffff : 0; @@ -64,6 +71,7 @@ static int opCDQ(uint32_t fetchdat) return 0; } + static int opNOP(uint32_t fetchdat) { CLOCK_CYCLES((is486) ? 1 : 3); @@ -71,6 +79,7 @@ static int opNOP(uint32_t fetchdat) return 0; } + static int opSETALC(uint32_t fetchdat) { AL = (CF_SET()) ? 0xff : 0; @@ -80,7 +89,6 @@ static int opSETALC(uint32_t fetchdat) } - static int opF6_a16(uint32_t fetchdat) { int tempws, tempws2 = 0; @@ -89,6 +97,10 @@ static int opF6_a16(uint32_t fetchdat) int8_t temps; fetch_ea_16(fetchdat); + if (cpu_mod != 3) + { + CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr); + } dst = geteab(); if (cpu_state.abrt) return 1; switch (rmdat & 0x38) { @@ -139,6 +151,8 @@ static int opF6_a16(uint32_t fetchdat) { flags_rebuild(); flags |= 0x8D5; /*Not a Cyrix*/ + flags &= ~1; + } } else @@ -146,8 +160,8 @@ static int opF6_a16(uint32_t fetchdat) x86_int(0); return 1; } - CLOCK_CYCLES(is486 ? 16 : 14); - PREFETCH_RUN(is486 ? 16 : 14, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0); + CLOCK_CYCLES((is486 && !cpu_iscyrix) ? 24 : 22); + PREFETCH_RUN((is486 && !cpu_iscyrix) ? 24 : 22, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0); break; case 0x38: /*IDIV AL,b*/ tempws = (int)(int16_t)AX; @@ -161,6 +175,7 @@ static int opF6_a16(uint32_t fetchdat) { flags_rebuild(); flags|=0x8D5; /*Not a Cyrix*/ + flags &= ~1; } } else @@ -173,11 +188,13 @@ static int opF6_a16(uint32_t fetchdat) break; default: - pclog("Bad F6 opcode %02X\n", rmdat & 0x38); + ERRLOG("CPU: bad F6 opcode %02X\n", rmdat & 0x38); x86illegal(); } return 0; } + + static int opF6_a32(uint32_t fetchdat) { int tempws, tempws2 = 0; @@ -236,6 +253,7 @@ static int opF6_a32(uint32_t fetchdat) { flags_rebuild(); flags |= 0x8D5; /*Not a Cyrix*/ + flags &= ~1; } } else @@ -243,8 +261,8 @@ static int opF6_a32(uint32_t fetchdat) x86_int(0); return 1; } - CLOCK_CYCLES(is486 ? 16 : 14); - PREFETCH_RUN(is486 ? 16 : 14, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1); + CLOCK_CYCLES((is486 && !cpu_iscyrix) ? 16 : 14); + PREFETCH_RUN((is486 && !cpu_iscyrix) ? 16 : 14, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1); break; case 0x38: /*IDIV AL,b*/ tempws = (int)(int16_t)AX; @@ -258,6 +276,7 @@ static int opF6_a32(uint32_t fetchdat) { flags_rebuild(); flags|=0x8D5; /*Not a Cyrix*/ + flags &= ~1; } } else @@ -270,14 +289,13 @@ static int opF6_a32(uint32_t fetchdat) break; default: - pclog("Bad F6 opcode %02X\n", rmdat & 0x38); + ERRLOG("CPU: bad F6 opcode %02X\n", rmdat & 0x38); x86illegal(); } return 0; } - static int opF7_w_a16(uint32_t fetchdat) { uint32_t templ, templ2; @@ -365,7 +383,7 @@ static int opF7_w_a16(uint32_t fetchdat) break; default: - pclog("Bad F7 opcode %02X\n", rmdat & 0x38); + ERRLOG("CPU: bad F7 opcode %02X\n", rmdat & 0x38); x86illegal(); } return 0; @@ -457,7 +475,7 @@ static int opF7_w_a32(uint32_t fetchdat) break; default: - pclog("Bad F7 opcode %02X\n", rmdat & 0x38); + ERRLOG("CPU: bad F7 opcode %02X\n", rmdat & 0x38); x86illegal(); } return 0; @@ -528,7 +546,7 @@ static int opF7_l_a16(uint32_t fetchdat) break; default: - pclog("Bad F7 opcode %02X\n", rmdat & 0x38); + ERRLOG("CPU: bad F7 opcode %02X\n", rmdat & 0x38); x86illegal(); } return 0; @@ -598,7 +616,7 @@ static int opF7_l_a32(uint32_t fetchdat) break; default: - pclog("Bad F7 opcode %02X\n", rmdat & 0x38); + ERRLOG("CPU: bad F7 opcode %02X\n", rmdat & 0x38); x86illegal(); } return 0; @@ -725,7 +743,7 @@ static int opCLTS(uint32_t fetchdat) { if ((CPL || (eflags&VM_FLAG)) && (cr0&1)) { - pclog("Can't CLTS\n"); + ERRLOG("CPU: can't CLTS\n"); x86gpf(NULL,0); return 1; } @@ -949,4 +967,3 @@ static int opWRMSR(uint32_t fetchdat) x86illegal(); return 1; } - diff --git a/src/cpu/x86_ops_mmx_shift.h b/src/cpu/x86_ops_mmx_shift.h index 0d7b9f4..08520ab 100644 --- a/src/cpu/x86_ops_mmx_shift.h +++ b/src/cpu/x86_ops_mmx_shift.h @@ -8,7 +8,7 @@ * * Miscellaneous x86 CPU Instructions. * - * Version: @(#)x86_ops_mmx_shift.h 1.0.1 2018/02/14 + * Version: @(#)x86_ops_mmx_shift.h 1.0.2 2018/10/05 * * Authors: Sarah Walker, * Miran Grca, @@ -89,7 +89,7 @@ static int opPSxxW_imm(uint32_t fetchdat) } break; default: - pclog("Bad PSxxW (0F 71) instruction %02X\n", op); + ERRLOG("CPU: bad PSxxW (0F 71) instruction %02X\n", op); cpu_state.pc = cpu_state.oldpc; x86illegal(); return 0; @@ -260,7 +260,7 @@ static int opPSxxD_imm(uint32_t fetchdat) } break; default: - pclog("Bad PSxxD (0F 72) instruction %02X\n", op); + ERRLOG("CPU: bad PSxxD (0F 72) instruction %02X\n", op); cpu_state.pc = cpu_state.oldpc; x86illegal(); return 0; @@ -412,7 +412,7 @@ static int opPSxxQ_imm(uint32_t fetchdat) cpu_state.MM[reg].q <<= shift; break; default: - pclog("Bad PSxxQ (0F 73) instruction %02X\n", op); + ERRLOG("CPU: bad PSxxQ (0F 73) instruction %02X\n", op); cpu_state.pc = cpu_state.oldpc; x86illegal(); return 0; diff --git a/src/cpu/x86_ops_mov_ctrl.h b/src/cpu/x86_ops_mov_ctrl.h index 7178da5..dc09c2f 100644 --- a/src/cpu/x86_ops_mov_ctrl.h +++ b/src/cpu/x86_ops_mov_ctrl.h @@ -8,7 +8,7 @@ * * Miscellaneous x86 CPU Instructions. * - * Version: @(#)x86_ops_mov_ctrl.h 1.0.1 2018/02/14 + * Version: @(#)x86_ops_mov_ctrl.h 1.0.2 2018/10/05 * * Authors: Sarah Walker, * Miran Grca, @@ -39,7 +39,7 @@ static int opMOV_r_CRx_a16(uint32_t fetchdat) { if ((CPL || (eflags&VM_FLAG)) && (cr0&1)) { - pclog("Can't load from CRx\n"); + ERRLOG("CPU: can't load from CRx\n"); x86gpf(NULL, 0); return 1; } @@ -64,7 +64,7 @@ static int opMOV_r_CRx_a16(uint32_t fetchdat) break; } default: - pclog("Bad read of CR%i %i\n",rmdat&7,cpu_reg); + ERRLOG("CPU: bad read of CR%i %i\n",rmdat&7,cpu_reg); cpu_state.pc = cpu_state.oldpc; x86illegal(); break; @@ -77,7 +77,7 @@ static int opMOV_r_CRx_a32(uint32_t fetchdat) { if ((CPL || (eflags&VM_FLAG)) && (cr0&1)) { - pclog("Can't load from CRx\n"); + ERRLOG("CPU: can't load from CRx\n"); x86gpf(NULL, 0); return 1; } @@ -102,7 +102,7 @@ static int opMOV_r_CRx_a32(uint32_t fetchdat) break; } default: - pclog("Bad read of CR%i %i\n",rmdat&7,cpu_reg); + ERRLOG("CPU: bad read of CR%i %i\n",rmdat&7,cpu_reg); cpu_state.pc = cpu_state.oldpc; x86illegal(); break; @@ -116,7 +116,7 @@ static int opMOV_r_DRx_a16(uint32_t fetchdat) { if ((CPL || (eflags&VM_FLAG)) && (cr0&1)) { - pclog("Can't load from DRx\n"); + ERRLOG("CPU: can't load from DRx\n"); x86gpf(NULL, 0); return 1; } @@ -130,7 +130,7 @@ static int opMOV_r_DRx_a32(uint32_t fetchdat) { if ((CPL || (eflags&VM_FLAG)) && (cr0&1)) { - pclog("Can't load from DRx\n"); + ERRLOG("CPU: can't load from DRx\n"); x86gpf(NULL, 0); return 1; } @@ -147,7 +147,7 @@ static int opMOV_CRx_r_a16(uint32_t fetchdat) if ((CPL || (eflags&VM_FLAG)) && (cr0&1)) { - pclog("Can't load CRx\n"); + ERRLOG("CPU: can't load CRx\n"); x86gpf(NULL,0); return 1; } @@ -188,7 +188,7 @@ static int opMOV_CRx_r_a16(uint32_t fetchdat) } default: - pclog("Bad load CR%i\n", cpu_reg); + ERRLOG("CPU: bad load CR%i\n", cpu_reg); cpu_state.pc = cpu_state.oldpc; x86illegal(); break; @@ -203,7 +203,7 @@ static int opMOV_CRx_r_a32(uint32_t fetchdat) if ((CPL || (eflags&VM_FLAG)) && (cr0&1)) { - pclog("Can't load CRx\n"); + ERRLOG("CPU: can't load CRx\n"); x86gpf(NULL,0); return 1; } @@ -244,7 +244,7 @@ static int opMOV_CRx_r_a32(uint32_t fetchdat) } default: - pclog("Bad load CR%i\n", cpu_reg); + ERRLOG("CPU: bad load CR%i\n", cpu_reg); cpu_state.pc = cpu_state.oldpc; x86illegal(); break; @@ -258,7 +258,7 @@ static int opMOV_DRx_r_a16(uint32_t fetchdat) { if ((CPL || (eflags&VM_FLAG)) && (cr0&1)) { - pclog("Can't load DRx\n"); + ERRLOG("CPU: can't load DRx\n"); x86gpf(NULL, 0); return 1; } @@ -272,7 +272,7 @@ static int opMOV_DRx_r_a32(uint32_t fetchdat) { if ((CPL || (eflags&VM_FLAG)) && (cr0&1)) { - pclog("Can't load DRx\n"); + ERRLOG("CPU: can't load DRx\n"); x86gpf(NULL, 0); return 1; } @@ -287,7 +287,7 @@ static int opMOV_r_TRx_a16(uint32_t fetchdat) { if ((CPL || (eflags&VM_FLAG)) && (cr0&1)) { - pclog("Can't load from TRx\n"); + ERRLOG("CPU: can't load from TRx\n"); x86gpf(NULL, 0); return 1; } @@ -301,7 +301,7 @@ static int opMOV_r_TRx_a32(uint32_t fetchdat) { if ((CPL || (eflags&VM_FLAG)) && (cr0&1)) { - pclog("Can't load from TRx\n"); + ERRLOG("CPU: can't load from TRx\n"); x86gpf(NULL, 0); return 1; } @@ -316,7 +316,7 @@ static int opMOV_TRx_r_a16(uint32_t fetchdat) { if ((CPL || (eflags&VM_FLAG)) && (cr0&1)) { - pclog("Can't load TRx\n"); + ERRLOG("CPU: can't load TRx\n"); x86gpf(NULL, 0); return 1; } @@ -329,7 +329,7 @@ static int opMOV_TRx_r_a32(uint32_t fetchdat) { if ((CPL || (eflags&VM_FLAG)) && (cr0&1)) { - pclog("Can't load TRx\n"); + ERRLOG("CPU: can't load TRx\n"); x86gpf(NULL, 0); return 1; } diff --git a/src/cpu/x86_ops_pmode.h b/src/cpu/x86_ops_pmode.h index 471bc15..56f5756 100644 --- a/src/cpu/x86_ops_pmode.h +++ b/src/cpu/x86_ops_pmode.h @@ -8,7 +8,7 @@ * * Miscellaneous x86 CPU Instructions. * - * Version: @(#)x86_ops_pmode.h 1.0.2 2018/05/09 + * Version: @(#)x86_ops_pmode.h 1.0.3 2018/10/05 * * Authors: Sarah Walker, * Miran Grca, @@ -41,7 +41,7 @@ static int opARPL_a16(uint32_t fetchdat) NOTRM fetch_ea_16(fetchdat); - /* pclog("ARPL_a16\n"); */ + /* DEBUG("ARPL_a16\n"); */ temp_seg = geteaw(); if (cpu_state.abrt) return 1; flags_rebuild(); @@ -64,7 +64,7 @@ static int opARPL_a32(uint32_t fetchdat) NOTRM fetch_ea_32(fetchdat); - /* pclog("ARPL_a32\n"); */ + /* DEBUG("ARPL_a32\n"); */ temp_seg = geteaw(); if (cpu_state.abrt) return 1; flags_rebuild(); @@ -196,7 +196,7 @@ static int op0F00_common(uint32_t fetchdat, int ea32) uint16_t desc, sel; uint8_t access; - /* pclog("op0F00 %02X %04X:%04X\n", rmdat & 0x38, CS, pc); */ + /* DEBUG("op0F00 %02X %04X:%04X\n", rmdat & 0x38, CS, pc); */ switch (rmdat & 0x38) { case 0x00: /*SLDT*/ @@ -212,7 +212,7 @@ static int op0F00_common(uint32_t fetchdat, int ea32) case 0x10: /*LLDT*/ if ((CPL || eflags&VM_FLAG) && (cr0&1)) { - pclog("Invalid LLDT!\n"); + ERRLOG("CPU: invalid LLDT!\n"); x86gpf(NULL,0); return 1; } @@ -238,7 +238,7 @@ static int op0F00_common(uint32_t fetchdat, int ea32) case 0x18: /*LTR*/ if ((CPL || eflags&VM_FLAG) && (cr0&1)) { - pclog("Invalid LTR!\n"); + ERRLOG("CPU: invalid LTR!\n"); x86gpf(NULL,0); break; } @@ -304,7 +304,7 @@ static int op0F00_common(uint32_t fetchdat, int ea32) break; default: - pclog("Bad 0F 00 opcode %02X\n", rmdat & 0x38); + ERRLOG("CPU: bad 0F 00 opcode %02X\n", rmdat & 0x38); cpu_state.pc -= 3; x86illegal(); break; @@ -333,7 +333,7 @@ static int op0F01_common(uint32_t fetchdat, int is32, int is286, int ea32) { uint32_t base; uint16_t limit, tempw; - /* pclog("op0F01 %02X %04X:%04X\n", rmdat & 0x38, CS, pc); */ + /* DEBUG("op0F01 %02X %04X:%04X\n", rmdat & 0x38, CS, pc); */ switch (rmdat & 0x38) { case 0x00: /*SGDT*/ @@ -357,14 +357,14 @@ static int op0F01_common(uint32_t fetchdat, int is32, int is286, int ea32) case 0x10: /*LGDT*/ if ((CPL || eflags&VM_FLAG) && (cr0&1)) { - pclog("Invalid LGDT!\n"); + ERRLOG("CPU: invalid LGDT!\n"); x86gpf(NULL,0); break; } - /* pclog("LGDT %08X:%08X\n", easeg, eaaddr); */ + /* DEBUG("LGDT %08X:%08X\n", easeg, eaaddr); */ limit = geteaw(); base = readmeml(0, easeg + cpu_state.eaaddr + 2); if (cpu_state.abrt) return 1; - /* pclog(" %08X %04X\n", base, limit); */ + /* DEBUG(" %08X %04X\n", base, limit); */ gdt.limit = limit; gdt.base = base; if (!is32) gdt.base &= 0xffffff; @@ -374,14 +374,14 @@ static int op0F01_common(uint32_t fetchdat, int is32, int is286, int ea32) case 0x18: /*LIDT*/ if ((CPL || eflags&VM_FLAG) && (cr0&1)) { - pclog("Invalid LIDT!\n"); + ERRLOG("CPU: invalid LIDT!\n"); x86gpf(NULL,0); break; } - /* pclog("LIDT %08X:%08X\n", easeg, eaaddr); */ + /* DEBUG("LIDT %08X:%08X\n", easeg, eaaddr); */ limit = geteaw(); base = readmeml(0, easeg + cpu_state.eaaddr + 2); if (cpu_state.abrt) return 1; - /* pclog(" %08X %04X\n", base, limit); */ + /* DEBUG(" %08X %04X\n", base, limit); */ idt.limit = limit; idt.base = base; if (!is32) idt.base &= 0xffffff; @@ -399,7 +399,7 @@ static int op0F01_common(uint32_t fetchdat, int is32, int is286, int ea32) case 0x30: /*LMSW*/ if ((CPL || eflags&VM_FLAG) && (msw&1)) { - pclog("LMSW - ring not zero!\n"); + ERRLOG("CPU: LMSW - ring not zero!\n"); x86gpf(NULL, 0); break; } @@ -424,7 +424,7 @@ static int op0F01_common(uint32_t fetchdat, int is32, int is286, int ea32) { if ((CPL || eflags&VM_FLAG) && (cr0&1)) { - pclog("Invalid INVLPG!\n"); + ERRLOG("CPU: invalid INVLPG!\n"); x86gpf(NULL, 0); break; } @@ -435,7 +435,7 @@ static int op0F01_common(uint32_t fetchdat, int is32, int is286, int ea32) } default: - pclog("Bad 0F 01 opcode %02X\n", rmdat & 0x38); + ERRLOG("CPU: bad 0F 01 opcode %02X\n", rmdat & 0x38); cpu_state.pc -= 3; x86illegal(); break; diff --git a/src/cpu/x86seg.c b/src/cpu/x86seg.c index d5737e8..fb0d049 100644 --- a/src/cpu/x86seg.c +++ b/src/cpu/x86seg.c @@ -8,7 +8,7 @@ * * x86 CPU segment emulation. * - * Version: @(#)x86seg.c 1.0.3 2018/05/06 + * Version: @(#)x86seg.c 1.0.5 2018/10/05 * * Authors: Sarah Walker, * Miran Grca, @@ -40,6 +40,7 @@ #include #include #include +#define HAVE_STDARG_H #include "../emu.h" #include "cpu.h" #include "../machines/machine.h" @@ -70,23 +71,26 @@ int intgatesize; void taskswitch286(uint16_t seg, uint16_t *segdat, int is32); void taskswitch386(uint16_t seg, uint16_t *segdat); -int output; void pmodeint(int num, int soft); /*NOT PRESENT is INT 0B GPF is INT 0D*/ -FILE *pclogf; -void x86abort(const char *format, ...) + +void +x86abort(const char *fmt, ...) { - va_list ap; - va_start(ap, format); - vfprintf(stdlog, format, ap); - va_end(ap); - fflush(stdlog); - nvr_save(); - dumpregs(1); - fflush(stdlog); - exit(-1); + va_list ap; + + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + + pclog(-1, NULL); + + nvr_save(); + dumpregs(1); + + exit(-1); } uint8_t opcode2; @@ -395,8 +399,10 @@ void loadseg(uint16_t seg, x86seg *s) } else if (s!=&_cs) { - if (output) pclog("Seg data %04X %04X %04X %04X\n", segdat[0], segdat[1], segdat[2], segdat[3]); - if (output) pclog("Seg type %03X\n",segdat[2]&0x1F00); +#if 0 + DEBUG("Seg data %04X %04X %04X %04X\n", segdat[0], segdat[1], segdat[2], segdat[3]); + DEBUG("Seg type %03X\n",segdat[2]&0x1F00); +#endif switch ((segdat[2]>>8)&0x1F) { case 0x10: case 0x11: case 0x12: case 0x13: /*Data segments*/ @@ -484,7 +490,9 @@ void loadcs(uint16_t seg) { uint16_t segdat[4]; uint32_t addr; - if (output) pclog("Load CS %04X\n",seg); +#if 0 + DEBUG("Load CS %04X\n",seg); +#endif if (msw&1 && !(eflags&VM_FLAG)) { if (!(seg&~3)) @@ -560,12 +568,17 @@ void loadcs(uint16_t seg) x86np("Load CS system seg not present\n", seg & 0xfffc); return; } +#if 1 + x86gpf(NULL,seg&~3); + return; +#else switch (segdat[2]&0xF00) { default: x86gpf(NULL,seg&~3); return; } +#endif } } else @@ -618,7 +631,9 @@ void loadcsjmp(uint16_t seg, uint32_t oxpc) segdat[1]=readmemw(0,addr+2); segdat[2]=readmemw(0,addr+4); segdat[3]=readmemw(0,addr+6); cpl_override=0; if (cpu_state.abrt) return; - if (output) pclog("%04X %04X %04X %04X\n",segdat[0],segdat[1],segdat[2],segdat[3]); +#if 0 + DEBUG("%04X %04X %04X %04X\n",segdat[0],segdat[1],segdat[2],segdat[3]); +#endif if (segdat[2]&0x1000) /*Normal code segment*/ { if (!(segdat[2]&0x400)) /*Not conforming*/ @@ -877,11 +892,11 @@ void loadcscall(uint16_t seg) int type; uint16_t tempw; - int csout = output; - if (msw&1 && !(eflags&VM_FLAG)) { - if (csout) pclog("Protected mode CS load! %04X\n",seg); +#if 0 + DEBUG("Protected mode CS load! %04X\n",seg); +#endif if (!(seg&~3)) { x86gpf(NULL,0); @@ -915,7 +930,9 @@ void loadcscall(uint16_t seg) newpc=segdat[0]; if (type&0x800) newpc|=segdat[3]<<16; - if (csout) pclog("Code seg call - %04X - %04X %04X %04X\n",seg,segdat[0],segdat[1],segdat[2]); +#if 0 + DEBUG("Code seg call - %04X - %04X %04X %04X\n",seg,segdat[0],segdat[1],segdat[2]); +#endif if (segdat[2]&0x1000) { if (!(segdat[2]&0x400)) /*Not conforming*/ @@ -960,18 +977,24 @@ void loadcscall(uint16_t seg) CS=seg; do_seg_load(&_cs, segdat); if (CPL==3 && oldcpl!=3) flushmmucache_cr3(); - if (csout) pclog("Complete\n"); +#if 0 + DEBUG("Complete\n"); +#endif cycles -= timing_call_pm; } else { type=segdat[2]&0xF00; - if (csout) pclog("Type %03X\n",type); +#if 0 + DEBUG("Type %03X\n",type); +#endif switch (type) { case 0x400: /*Call gate*/ case 0xC00: /*386 Call gate*/ - if (output) pclog("Callgate %08X\n", cpu_state.pc); +#if 0 + DEBUG("Callgate %08X\n", cpu_state.pc); +#endif cgate32=(type&0x800); cgate16=!cgate32; oldcs=CS; @@ -988,13 +1011,17 @@ void loadcscall(uint16_t seg) } if (!(segdat[2]&0x8000)) { - if (output) pclog("Call gate not present %04X\n",seg); +#if 0 + DEBUG("Call gate not present %04X\n",seg); +#endif x86np("Call gate not present\n", seg & 0xfffc); return; } seg2=segdat[1]; - - if (output) pclog("New address : %04X:%08X\n", seg2, newpc); + +#if 0 + DEBUG("New address : %04X:%08X\n", seg2, newpc); +#endif if (!(seg2&~3)) { @@ -1026,7 +1053,9 @@ void loadcscall(uint16_t seg) segdat[2]=readmemw(0,addr+4); segdat[3]=readmemw(0,addr+6); cpl_override=0; if (cpu_state.abrt) return; - if (output) pclog("Code seg2 call - %04X - %04X %04X %04X\n",seg2,segdat[0],segdat[1],segdat[2]); +#if 0 + DEBUG("Code seg2 call - %04X - %04X %04X %04X\n",seg2,segdat[0],segdat[1],segdat[2]); +#endif if (DPL > CPL) { @@ -1035,7 +1064,9 @@ void loadcscall(uint16_t seg) } if (!(segdat[2]&0x8000)) { - if (output) pclog("Call gate CS not present %04X\n",seg2); +#if 0 + DEBUG("Call gate CS not present %04X\n",seg2); +#endif x86np("Call gate CS not present", seg2 & 0xfffc); return; } @@ -1065,7 +1096,9 @@ void loadcscall(uint16_t seg) } cpl_override=0; if (cpu_state.abrt) return; - if (output) pclog("New stack %04X:%08X\n",newss,newsp); +#if 0 + DEBUG("New stack %04X:%08X\n",newss,newsp); +#endif if (!(newss&~3)) { x86ts(NULL,newss&~3); @@ -1093,12 +1126,16 @@ void loadcscall(uint16_t seg) addr+=gdt.base; } cpl_override=1; - if (output) pclog("Read stack seg\n"); +#if 0 + DEBUG("Read stack seg\n"); +#endif segdat2[0]=readmemw(0,addr); segdat2[1]=readmemw(0,addr+2); segdat2[2]=readmemw(0,addr+4); segdat2[3]=readmemw(0,addr+6); cpl_override=0; if (cpu_state.abrt) return; - if (output) pclog("Read stack seg done!\n"); +#if 0 + DEBUG("Read stack seg done!\n"); +#endif if (((newss & 3) != DPL) || (DPL2 != DPL)) { x86ts(NULL,newss&~3); @@ -1122,7 +1159,9 @@ void loadcscall(uint16_t seg) do_seg_load(&_ss, segdat2); - if (output) pclog("Set access 1\n"); +#if 0 + DEBUG("Set access 1\n"); +#endif #ifdef SEL_ACCESSED cpl_override = 1; @@ -1136,15 +1175,19 @@ void loadcscall(uint16_t seg) set_use32(segdat[3]&0x40); cpu_state.pc=newpc; - if (output) pclog("Set access 2\n"); +#if 0 + DEBUG("Set access 2\n"); +#endif #ifdef CS_ACCESSED cpl_override = 1; writememw(0, oaddr+4, segdat[2] | 0x100); /*Set accessed bit*/ cpl_override = 0; #endif - - if (output) pclog("Type %04X\n",type); + +#if 0 + DEBUG("Type %04X\n",type); +#endif if (type==0xC00) { PUSHL(oldss); @@ -1172,9 +1215,13 @@ void loadcscall(uint16_t seg) } else { - if (output) pclog("Stack %04X\n",SP); +#if 0 + DEBUG("Stack %04X\n",SP); +#endif PUSHW(oldss); - if (output) pclog("Write SS to %04X:%04X\n",SS,SP); +#if 0 + DEBUG("Write SS to %04X:%04X\n",SS,SP); +#endif PUSHW(oldsp2); if (cpu_state.abrt) { @@ -1182,14 +1229,18 @@ void loadcscall(uint16_t seg) ESP = oldsp2; return; } - if (output) pclog("Write SP to %04X:%04X\n",SS,SP); +#if 0 + DEBUG("Write SP to %04X:%04X\n",SS,SP); +#endif if (count) { while (count) { count--; tempw=readmemw(oldssbase,(oldsp&0xFFFF)+(count*2)); - if (output) pclog("PUSH %04X\n",tempw); +#if 0 + DEBUG("PUSH %04X\n",tempw); +#endif PUSHW(tempw); if (cpu_state.abrt) { @@ -1263,7 +1314,9 @@ void pmoderetf(int is32, uint16_t off) uint32_t addr, oaddr; uint16_t segdat[4],segdat2[4],seg,newss; uint32_t oldsp=ESP; - if (output) pclog("RETF %i %04X:%04X %08X %04X\n",is32,CS,cpu_state.pc,cr0,eflags); +#if 0 + DEBUG("RETF %i %04X:%04X %08X %04X\n",is32,CS,cpu_state.pc,cr0,eflags); +#endif if (is32) { newpc=POPL(); @@ -1271,12 +1324,18 @@ void pmoderetf(int is32, uint16_t off) } else { - if (output) pclog("PC read from %04X:%04X\n",SS,SP); +#if 0 + DEBUG("PC read from %04X:%04X\n",SS,SP); +#endif newpc=POPW(); - if (output) pclog("CS read from %04X:%04X\n",SS,SP); +#if 0 + DEBUG("CS read from %04X:%04X\n",SS,SP); +#endif seg=POPW(); if (cpu_state.abrt) return; } - if (output) pclog("Return to %04X:%08X\n",seg,newpc); +#if 0 + DEBUG("Return to %04X:%08X\n",seg,newpc); +#endif if ((seg&3)= IDT.limit\n"); +#if 0 + DEBUG("addr >= IDT.limit\n"); +#endif return; } addr+=idt.base; @@ -1554,10 +1633,12 @@ void pmodeint(int num, int soft) segdat[0]=readmemw(0,addr); segdat[1]=readmemw(2,addr); segdat[2]=readmemw(4,addr); - segdat[3]=readmemw(6,addr); cpl_override=0; if (cpu_state.abrt) { /* pclog("Abrt reading from %08X\n",addr); */ return; } + segdat[3]=readmemw(6,addr); cpl_override=0; if (cpu_state.abrt) { /* ERRLOG("Abrt reading from %08X\n",addr); */ return; } oaddr = addr; - if (output) pclog("Addr %08X seg %04X %04X %04X %04X\n",addr,segdat[0],segdat[1],segdat[2],segdat[3]); +#if 0 + DEBUG("Addr %08X seg %04X %04X %04X %04X\n",addr,segdat[0],segdat[1],segdat[2],segdat[3]); +#endif if (!(segdat[2]&0x1F00)) { x86gpf(NULL,(num*8)+2); @@ -1700,7 +1781,9 @@ void pmodeint(int num, int soft) cpl_override = 0; #endif - if (output) pclog("New stack %04X:%08X\n",SS,ESP); +#if 0 + DEBUG("New stack %04X:%08X\n",SS,ESP); +#endif cpl_override=1; if (type>=0x800) { @@ -1885,7 +1968,7 @@ void pmodeiret(int is32) addr=seg&~7; if (seg&4) { - pclog("TS LDT %04X %04X IRET\n",seg,gdt.limit); + DEBUG("TS LDT %04X %04X IRET\n",seg,gdt.limit); x86ts(NULL,seg&~3); return; } @@ -2049,7 +2132,9 @@ void pmodeiret(int is32) else /*Return to outer level*/ { oaddr = addr; - if (output) pclog("Outer level\n"); +#if 0 + DEBUG("Outer level\n"); +#endif if (is32) { newsp=POPL(); @@ -2061,7 +2146,9 @@ void pmodeiret(int is32) newss=POPW(); if (cpu_state.abrt) { ESP = oldsp; return; } } - if (output) pclog("IRET load stack %04X:%04X\n",newss,newsp); +#if 0 + DEBUG("IRET load stack %04X:%04X\n",newss,newsp); +#endif if (!(newss&~3)) { diff --git a/src/cpu/x87.c b/src/cpu/x87.c index 0034d79..f9e2eeb 100644 --- a/src/cpu/x87.c +++ b/src/cpu/x87.c @@ -8,7 +8,7 @@ * * Implementation of 8087 opcodes. * - * Version: @(#)x87.c 1.0.2 2018/05/06 + * Version: @(#)x87.c 1.0.3 2018/10/05 * * Authors: Sarah Walker, * Miran Grca, @@ -38,7 +38,6 @@ #include #include #include -#define fplog 0 #include #include "../emu.h" #include "cpu.h" @@ -51,7 +50,13 @@ #include "386_common.h" -uint16_t x87_gettag() +uint32_t x87_pc_off, + x87_op_off; +uint16_t x87_pc_seg, + x87_op_seg; + + +uint16_t x87_gettag(void) { uint16_t ret = 0; int c; @@ -79,35 +84,35 @@ void x87_settag(uint16_t new_tag) cpu_state.tag[7] = (new_tag >> 14) & 3; } -void x87_dumpregs() +void x87_dumpregs(void) { if (cpu_state.ismmx) { - pclog("MM0=%016llX\tMM1=%016llX\tMM2=%016llX\tMM3=%016llX\n", cpu_state.MM[0].q, cpu_state.MM[1].q, cpu_state.MM[2].q, cpu_state.MM[3].q); - pclog("MM4=%016llX\tMM5=%016llX\tMM6=%016llX\tMM7=%016llX\n", cpu_state.MM[4].q, cpu_state.MM[5].q, cpu_state.MM[6].q, cpu_state.MM[7].q); + ERRLOG("MM0=%016llX\tMM1=%016llX\tMM2=%016llX\tMM3=%016llX\n", cpu_state.MM[0].q, cpu_state.MM[1].q, cpu_state.MM[2].q, cpu_state.MM[3].q); + ERRLOG("MM4=%016llX\tMM5=%016llX\tMM6=%016llX\tMM7=%016llX\n", cpu_state.MM[4].q, cpu_state.MM[5].q, cpu_state.MM[6].q, cpu_state.MM[7].q); } else { - pclog("ST(0)=%f\tST(1)=%f\tST(2)=%f\tST(3)=%f\t\n",cpu_state.ST[cpu_state.TOP],cpu_state.ST[(cpu_state.TOP+1)&7],cpu_state.ST[(cpu_state.TOP+2)&7],cpu_state.ST[(cpu_state.TOP+3)&7]); - pclog("ST(4)=%f\tST(5)=%f\tST(6)=%f\tST(7)=%f\t\n",cpu_state.ST[(cpu_state.TOP+4)&7],cpu_state.ST[(cpu_state.TOP+5)&7],cpu_state.ST[(cpu_state.TOP+6)&7],cpu_state.ST[(cpu_state.TOP+7)&7]); + ERRLOG("ST(0)=%f\tST(1)=%f\tST(2)=%f\tST(3)=%f\t\n",cpu_state.ST[cpu_state.TOP],cpu_state.ST[(cpu_state.TOP+1)&7],cpu_state.ST[(cpu_state.TOP+2)&7],cpu_state.ST[(cpu_state.TOP+3)&7]); + ERRLOG("ST(4)=%f\tST(5)=%f\tST(6)=%f\tST(7)=%f\t\n",cpu_state.ST[(cpu_state.TOP+4)&7],cpu_state.ST[(cpu_state.TOP+5)&7],cpu_state.ST[(cpu_state.TOP+6)&7],cpu_state.ST[(cpu_state.TOP+7)&7]); } - pclog("Status = %04X Control = %04X Tag = %04X\n", cpu_state.npxs, cpu_state.npxc, x87_gettag()); + ERRLOG("Status = %04X Control = %04X Tag = %04X\n", cpu_state.npxs, cpu_state.npxc, x87_gettag()); } -void x87_print() +void x87_print(void) { if (cpu_state.ismmx) { - pclog("\tMM0=%016llX\tMM1=%016llX\tMM2=%016llX\tMM3=%016llX\t", cpu_state.MM[0].q, cpu_state.MM[1].q, cpu_state.MM[2].q, cpu_state.MM[3].q); - pclog("MM4=%016llX\tMM5=%016llX\tMM6=%016llX\tMM7=%016llX\n", cpu_state.MM[4].q, cpu_state.MM[5].q, cpu_state.MM[6].q, cpu_state.MM[7].q); + ERRLOG("\tMM0=%016llX\tMM1=%016llX\tMM2=%016llX\tMM3=%016llX\t", cpu_state.MM[0].q, cpu_state.MM[1].q, cpu_state.MM[2].q, cpu_state.MM[3].q); + ERRLOG("MM4=%016llX\tMM5=%016llX\tMM6=%016llX\tMM7=%016llX\n", cpu_state.MM[4].q, cpu_state.MM[5].q, cpu_state.MM[6].q, cpu_state.MM[7].q); } else { - pclog("\tST(0)=%.20f\tST(1)=%.20f\tST(2)=%f\tST(3)=%f\t",cpu_state.ST[cpu_state.TOP&7],cpu_state.ST[(cpu_state.TOP+1)&7],cpu_state.ST[(cpu_state.TOP+2)&7],cpu_state.ST[(cpu_state.TOP+3)&7]); - pclog("ST(4)=%f\tST(5)=%f\tST(6)=%f\tST(7)=%f\tTOP=%i CR=%04X SR=%04X TAG=%04X\n",cpu_state.ST[(cpu_state.TOP+4)&7],cpu_state.ST[(cpu_state.TOP+5)&7],cpu_state.ST[(cpu_state.TOP+6)&7],cpu_state.ST[(cpu_state.TOP+7)&7], cpu_state.TOP, cpu_state.npxc, cpu_state.npxs, x87_gettag()); + ERRLOG("\tST(0)=%.20f\tST(1)=%.20f\tST(2)=%f\tST(3)=%f\t",cpu_state.ST[cpu_state.TOP&7],cpu_state.ST[(cpu_state.TOP+1)&7],cpu_state.ST[(cpu_state.TOP+2)&7],cpu_state.ST[(cpu_state.TOP+3)&7]); + ERRLOG("ST(4)=%f\tST(5)=%f\tST(6)=%f\tST(7)=%f\tTOP=%i CR=%04X SR=%04X TAG=%04X\n",cpu_state.ST[(cpu_state.TOP+4)&7],cpu_state.ST[(cpu_state.TOP+5)&7],cpu_state.ST[(cpu_state.TOP+6)&7],cpu_state.ST[(cpu_state.TOP+7)&7], cpu_state.TOP, cpu_state.npxc, cpu_state.npxs, x87_gettag()); } } -void x87_reset() +void x87_reset(void) { } diff --git a/src/cpu/x87.h b/src/cpu/x87.h index d12397f..600644a 100644 --- a/src/cpu/x87.h +++ b/src/cpu/x87.h @@ -8,7 +8,7 @@ * * Definitions for the X87 FPU. * - * Version: @(#)x87.h 1.0.1 2018/02/14 + * Version: @(#)x87.h 1.0.2 2018/09/19 * * Authors: Sarah Walker, * Miran Grca, @@ -35,11 +35,11 @@ * USA. */ -uint32_t x87_pc_off,x87_op_off; -uint16_t x87_pc_seg,x87_op_seg; +extern uint32_t x87_pc_off,x87_op_off; +extern uint16_t x87_pc_seg,x87_op_seg; -uint16_t x87_gettag(); -void x87_settag(uint16_t new_tag); +extern uint16_t x87_gettag(); +extern void x87_settag(uint16_t new_tag); /*Hack for FPU copy. If set then MM[].q contains the 64-bit integer loaded by FILD*/ #define TAG_UINT64 (1 << 2) diff --git a/src/cpu/x87_ops.h b/src/cpu/x87_ops.h index 4d685d0..dd24612 100644 --- a/src/cpu/x87_ops.h +++ b/src/cpu/x87_ops.h @@ -8,7 +8,7 @@ * * x87 FPU instructions core. * - * Version: @(#)x87_ops.h 1.0.5 2018/05/05 + * Version: @(#)x87_ops.h 1.0.6 2018/10/05 * * Authors: Fred N. van Kempen, * Sarah Walker, @@ -66,7 +66,7 @@ static int rounding_modes[4] = {FE_TONEAREST, FE_DOWNWARD, FE_UPWARD, FE_TOWARDZ dst = src1 / (double)src2; \ else \ { \ - pclog("FPU : divide by zero\n"); \ + ERRLOG("FPU : divide by zero\n"); \ picint(1 << 13); \ } \ return 1; \ @@ -74,8 +74,9 @@ static int rounding_modes[4] = {FE_TONEAREST, FE_DOWNWARD, FE_UPWARD, FE_TOWARDZ else \ dst = src1 / (double)src2; \ } while (0) - -static __inline void x87_set_mmx() + + +static INLINE void x87_set_mmx(void) { uint64_t *p; cpu_state.TOP = 0; @@ -84,7 +85,8 @@ static __inline void x87_set_mmx() cpu_state.ismmx = 1; } -static __inline void x87_emms() + +static INLINE void x87_emms(void) { uint64_t *p; p = (uint64_t *)cpu_state.tag; @@ -92,18 +94,37 @@ static __inline void x87_emms() cpu_state.ismmx = 0; } -static __inline void x87_checkexceptions() + +static INLINE void x87_checkexceptions(void) { } -static __inline void x87_push(double i) + +static INLINE void x87_push(double i) { cpu_state.TOP=(cpu_state.TOP-1)&7; cpu_state.ST[cpu_state.TOP] = i; cpu_state.tag[cpu_state.TOP&7] = (i == 0.0) ? 1 : 0; } -static __inline double x87_pop() + +static INLINE void x87_push_u64(uint64_t i) +{ + union + { + double d; + uint64_t ll; + } td; + + td.ll = i; + + cpu_state.TOP=(cpu_state.TOP-1)&7; + cpu_state.ST[cpu_state.TOP] = td.d; + cpu_state.tag[cpu_state.TOP&7] = (td.d == 0.0) ? 1 : 0; +} + + +static INLINE double x87_pop(void) { double t = cpu_state.ST[cpu_state.TOP]; cpu_state.tag[cpu_state.TOP&7] = 3; @@ -111,7 +132,8 @@ static __inline double x87_pop() return t; } -static __inline int64_t x87_fround(double b) + +static INLINE int64_t x87_fround(double b) { int64_t a, c; @@ -136,10 +158,13 @@ static __inline int64_t x87_fround(double b) return (int64_t)0; } } + + #define BIAS80 16383 #define BIAS64 1023 -static __inline double x87_ld80() + +static INLINE double x87_ld80(void) { int64_t exp64; int64_t blah; @@ -177,7 +202,8 @@ static __inline double x87_ld80() return test.eind.d; } -static __inline void x87_st80(double d) + +static INLINE void x87_st80(double d) { int64_t sign80; int64_t exp80; @@ -221,7 +247,8 @@ static __inline void x87_st80(double d) writememw(easeg,cpu_state.eaaddr+8,test.begin); } -static __inline void x87_st_fsave(int reg) + +static INLINE void x87_st_fsave(int reg) { reg = (cpu_state.TOP + reg) & 7; @@ -235,7 +262,8 @@ static __inline void x87_st_fsave(int reg) x87_st80(cpu_state.ST[reg]); } -static __inline void x87_ld_frstor(int reg) + +static INLINE void x87_ld_frstor(int reg) { reg = (cpu_state.TOP + reg) & 7; @@ -251,21 +279,22 @@ static __inline void x87_ld_frstor(int reg) cpu_state.ST[reg] = x87_ld80(); } -static __inline void x87_ldmmx(MMX_REG *r, uint16_t *w4) + +static INLINE void x87_ldmmx(MMX_REG *r, uint16_t *w4) { r->l[0] = readmeml(easeg, cpu_state.eaaddr); r->l[1] = readmeml(easeg, cpu_state.eaaddr + 4); *w4 = readmemw(easeg, cpu_state.eaaddr + 8); } -static __inline void x87_stmmx(MMX_REG r) +static INLINE void x87_stmmx(MMX_REG r) { writememl(easeg, cpu_state.eaaddr, r.l[0]); writememl(easeg, cpu_state.eaaddr + 4, r.l[1]); writememw(easeg, cpu_state.eaaddr + 8, 0xffff); } -static __inline uint16_t x87_compare(double a, double b) +static INLINE uint16_t x87_compare(double a, double b) { #if defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined _WIN32 uint32_t result; @@ -274,7 +303,7 @@ static __inline uint16_t x87_compare(double a, double b) { if (((a == INFINITY) || (a == -INFINITY)) && ((b == INFINITY) || (b == -INFINITY))) { - /* pclog("Comparing infinity\n"); */ + /* DEBUG("Comparing infinity\n"); */ #ifndef _MSC_VER __asm volatile ("" : : : "memory"); @@ -360,7 +389,7 @@ static __inline uint16_t x87_compare(double a, double b) #endif } -static __inline uint16_t x87_ucompare(double a, double b) +static INLINE uint16_t x87_ucompare(double a, double b) { #if defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined _WIN32 uint32_t result; diff --git a/src/cpu/x87_ops_arith.h b/src/cpu/x87_ops_arith.h index 6db8078..5f2c79c 100644 --- a/src/cpu/x87_ops_arith.h +++ b/src/cpu/x87_ops_arith.h @@ -8,7 +8,7 @@ * * Miscellaneous x87 FPU Instructions. * - * Version: @(#)x87_ops_arith.h 1.0.1 2018/02/14 + * Version: @(#)x87_ops_arith.h 1.0.2 2018/10/05 * * Authors: Sarah Walker, * Miran Grca, @@ -148,7 +148,7 @@ static int opFADD(uint32_t fetchdat) { FP_ENTER(); cpu_state.pc++; - if (fplog) pclog("FADD\n"); + DEBUG("FADD\n"); ST(0) = ST(0) + ST(fetchdat & 7); cpu_state.tag[cpu_state.TOP] &= ~TAG_UINT64; CLOCK_CYCLES(8); @@ -158,7 +158,7 @@ static int opFADDr(uint32_t fetchdat) { FP_ENTER(); cpu_state.pc++; - if (fplog) pclog("FADD\n"); + DEBUG("FADD\n"); ST(fetchdat & 7) = ST(fetchdat & 7) + ST(0); cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] &= ~TAG_UINT64; CLOCK_CYCLES(8); @@ -168,7 +168,7 @@ static int opFADDP(uint32_t fetchdat) { FP_ENTER(); cpu_state.pc++; - if (fplog) pclog("FADDP\n"); + DEBUG("FADDP\n"); ST(fetchdat & 7) = ST(fetchdat & 7) + ST(0); cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] &= ~TAG_UINT64; x87_pop(); @@ -180,7 +180,7 @@ static int opFCOM(uint32_t fetchdat) { FP_ENTER(); cpu_state.pc++; - if (fplog) pclog("FCOM\n"); + DEBUG("FCOM\n"); cpu_state.npxs &= ~(C0|C2|C3); if (ST(0) == ST(fetchdat & 7)) cpu_state.npxs |= C3; else if (ST(0) < ST(fetchdat & 7)) cpu_state.npxs |= C0; @@ -192,7 +192,7 @@ static int opFCOMP(uint32_t fetchdat) { FP_ENTER(); cpu_state.pc++; - if (fplog) pclog("FCOMP\n"); + DEBUG("FCOMP\n"); cpu_state.npxs &= ~(C0|C2|C3); cpu_state.npxs |= x87_compare(ST(0), ST(fetchdat & 7)); x87_pop(); @@ -205,7 +205,7 @@ static int opFCOMPP(uint32_t fetchdat) uint64_t *p, *q; FP_ENTER(); cpu_state.pc++; - if (fplog) pclog("FCOMPP\n"); + DEBUG("FCOMPP\n"); cpu_state.npxs &= ~(C0|C2|C3); p = (uint64_t *)&ST(0); q = (uint64_t *)&ST(1); @@ -223,7 +223,7 @@ static int opFUCOMPP(uint32_t fetchdat) { FP_ENTER(); cpu_state.pc++; - if (fplog) pclog("FUCOMPP\n", easeg, cpu_state.eaaddr); + DEBUG("FUCOMPP\n", easeg, cpu_state.eaaddr); cpu_state.npxs &= ~(C0|C2|C3); cpu_state.npxs |= x87_ucompare(ST(0), ST(1)); x87_pop(); @@ -236,7 +236,7 @@ static int opFCOMI(uint32_t fetchdat) { FP_ENTER(); cpu_state.pc++; - if (fplog) pclog("FICOM\n"); + DEBUG("FICOM\n"); flags_rebuild(); flags &= ~(Z_FLAG | P_FLAG | C_FLAG); if (ST(0) == ST(fetchdat & 7)) flags |= Z_FLAG; @@ -248,7 +248,7 @@ static int opFCOMIP(uint32_t fetchdat) { FP_ENTER(); cpu_state.pc++; - if (fplog) pclog("FICOMP\n"); + DEBUG("FICOMP\n"); flags_rebuild(); flags &= ~(Z_FLAG | P_FLAG | C_FLAG); if (ST(0) == ST(fetchdat & 7)) flags |= Z_FLAG; @@ -262,7 +262,7 @@ static int opFDIV(uint32_t fetchdat) { FP_ENTER(); cpu_state.pc++; - if (fplog) pclog("FDIV\n"); + DEBUG("FDIV\n"); x87_div(ST(0), ST(0), ST(fetchdat & 7)); cpu_state.tag[cpu_state.TOP] &= ~TAG_UINT64; CLOCK_CYCLES(73); @@ -272,7 +272,7 @@ static int opFDIVr(uint32_t fetchdat) { FP_ENTER(); cpu_state.pc++; - if (fplog) pclog("FDIV\n"); + DEBUG("FDIV\n"); x87_div(ST(fetchdat & 7), ST(fetchdat & 7), ST(0)); cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] &= ~TAG_UINT64; CLOCK_CYCLES(73); @@ -282,7 +282,7 @@ static int opFDIVP(uint32_t fetchdat) { FP_ENTER(); cpu_state.pc++; - if (fplog) pclog("FDIVP\n"); + DEBUG("FDIVP\n"); x87_div(ST(fetchdat & 7), ST(fetchdat & 7), ST(0)); cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] &= ~TAG_UINT64; x87_pop(); @@ -294,7 +294,7 @@ static int opFDIVR(uint32_t fetchdat) { FP_ENTER(); cpu_state.pc++; - if (fplog) pclog("FDIVR\n"); + DEBUG("FDIVR\n"); x87_div(ST(0), ST(fetchdat&7), ST(0)); cpu_state.tag[cpu_state.TOP] &= ~TAG_UINT64; CLOCK_CYCLES(73); @@ -304,7 +304,7 @@ static int opFDIVRr(uint32_t fetchdat) { FP_ENTER(); cpu_state.pc++; - if (fplog) pclog("FDIVR\n"); + DEBUG("FDIVR\n"); x87_div(ST(fetchdat & 7), ST(0), ST(fetchdat & 7)); cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] &= ~TAG_UINT64; CLOCK_CYCLES(73); @@ -314,7 +314,7 @@ static int opFDIVRP(uint32_t fetchdat) { FP_ENTER(); cpu_state.pc++; - if (fplog) pclog("FDIVR\n"); + DEBUG("FDIVR\n"); x87_div(ST(fetchdat & 7), ST(0), ST(fetchdat & 7)); cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] &= ~TAG_UINT64; x87_pop(); @@ -326,7 +326,7 @@ static int opFMUL(uint32_t fetchdat) { FP_ENTER(); cpu_state.pc++; - if (fplog) pclog("FMUL\n"); + DEBUG("FMUL\n"); ST(0) = ST(0) * ST(fetchdat & 7); cpu_state.tag[cpu_state.TOP] &= ~TAG_UINT64; CLOCK_CYCLES(16); @@ -336,7 +336,7 @@ static int opFMULr(uint32_t fetchdat) { FP_ENTER(); cpu_state.pc++; - if (fplog) pclog("FMUL\n"); + DEBUG("FMUL\n"); ST(fetchdat & 7) = ST(0) * ST(fetchdat & 7); cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] &= ~TAG_UINT64; CLOCK_CYCLES(16); @@ -346,7 +346,7 @@ static int opFMULP(uint32_t fetchdat) { FP_ENTER(); cpu_state.pc++; - if (fplog) pclog("FMULP\n"); + DEBUG("FMULP\n"); ST(fetchdat & 7) = ST(0) * ST(fetchdat & 7); cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] &= ~TAG_UINT64; x87_pop(); @@ -358,7 +358,7 @@ static int opFSUB(uint32_t fetchdat) { FP_ENTER(); cpu_state.pc++; - if (fplog) pclog("FSUB\n"); + DEBUG("FSUB\n"); ST(0) = ST(0) - ST(fetchdat & 7); cpu_state.tag[cpu_state.TOP] &= ~TAG_UINT64; CLOCK_CYCLES(8); @@ -368,7 +368,7 @@ static int opFSUBr(uint32_t fetchdat) { FP_ENTER(); cpu_state.pc++; - if (fplog) pclog("FSUB\n"); + DEBUG("FSUB\n"); ST(fetchdat & 7) = ST(fetchdat & 7) - ST(0); cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] &= ~TAG_UINT64; CLOCK_CYCLES(8); @@ -378,7 +378,7 @@ static int opFSUBP(uint32_t fetchdat) { FP_ENTER(); cpu_state.pc++; - if (fplog) pclog("FSUBP\n"); + DEBUG("FSUBP\n"); ST(fetchdat & 7) = ST(fetchdat & 7) - ST(0); cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] &= ~TAG_UINT64; x87_pop(); @@ -390,7 +390,7 @@ static int opFSUBR(uint32_t fetchdat) { FP_ENTER(); cpu_state.pc++; - if (fplog) pclog("FSUBR\n"); + DEBUG("FSUBR\n"); ST(0) = ST(fetchdat & 7) - ST(0); cpu_state.tag[cpu_state.TOP] &= ~TAG_UINT64; CLOCK_CYCLES(8); @@ -400,7 +400,7 @@ static int opFSUBRr(uint32_t fetchdat) { FP_ENTER(); cpu_state.pc++; - if (fplog) pclog("FSUBR\n"); + DEBUG("FSUBR\n"); ST(fetchdat & 7) = ST(0) - ST(fetchdat & 7); cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] &= ~TAG_UINT64; CLOCK_CYCLES(8); @@ -410,7 +410,7 @@ static int opFSUBRP(uint32_t fetchdat) { FP_ENTER(); cpu_state.pc++; - if (fplog) pclog("FSUBRP\n"); + DEBUG("FSUBRP\n"); ST(fetchdat & 7) = ST(0) - ST(fetchdat & 7); cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] &= ~TAG_UINT64; x87_pop(); @@ -422,7 +422,7 @@ static int opFUCOM(uint32_t fetchdat) { FP_ENTER(); cpu_state.pc++; - if (fplog) pclog("FUCOM\n"); + DEBUG("FUCOM\n"); cpu_state.npxs &= ~(C0|C2|C3); cpu_state.npxs |= x87_ucompare(ST(0), ST(fetchdat & 7)); CLOCK_CYCLES(4); @@ -433,7 +433,7 @@ static int opFUCOMP(uint32_t fetchdat) { FP_ENTER(); cpu_state.pc++; - if (fplog) pclog("FUCOMP\n"); + DEBUG("FUCOMP\n"); cpu_state.npxs &= ~(C0|C2|C3); cpu_state.npxs |= x87_ucompare(ST(0), ST(fetchdat & 7)); x87_pop(); @@ -445,7 +445,7 @@ static int opFUCOMI(uint32_t fetchdat) { FP_ENTER(); cpu_state.pc++; - if (fplog) pclog("FUCOMI\n"); + DEBUG("FUCOMI\n"); flags_rebuild(); flags &= ~(Z_FLAG | P_FLAG | C_FLAG); if (ST(0) == ST(fetchdat & 7)) flags |= Z_FLAG; @@ -457,7 +457,7 @@ static int opFUCOMIP(uint32_t fetchdat) { FP_ENTER(); cpu_state.pc++; - if (fplog) pclog("FUCOMIP\n"); + DEBUG("FUCOMIP\n"); flags_rebuild(); flags &= ~(Z_FLAG | P_FLAG | C_FLAG); if (ST(0) == ST(fetchdat & 7)) flags |= Z_FLAG; diff --git a/src/cpu/x87_ops_loadstore.h b/src/cpu/x87_ops_loadstore.h index e84fcd4..a082aaa 100644 --- a/src/cpu/x87_ops_loadstore.h +++ b/src/cpu/x87_ops_loadstore.h @@ -8,7 +8,7 @@ * * x87 FPU instructions core. * - * Version: @(#)x87_ops_loadstore.h 1.0.1 2018/02/14 + * Version: @(#)x87_ops_loadstore.h 1.0.2 2018/09/13 * * Authors: Sarah Walker, * Miran Grca, @@ -40,9 +40,9 @@ static int opFILDiw_a16(uint32_t fetchdat) int16_t temp; FP_ENTER(); fetch_ea_16(fetchdat); - if (fplog) pclog("FILDw %08X:%08X\n", easeg, cpu_state.eaaddr); + if (fplog) DEBUG("FILDw %08X:%08X\n", easeg, cpu_state.eaaddr); temp = geteaw(); if (cpu_state.abrt) return 1; - if (fplog) pclog(" %f\n", (double)temp); + if (fplog) DEBUG(" %f\n", (double)temp); x87_push((double)temp); CLOCK_CYCLES(13); return 0; @@ -52,9 +52,9 @@ static int opFILDiw_a32(uint32_t fetchdat) int16_t temp; FP_ENTER(); fetch_ea_32(fetchdat); - if (fplog) pclog("FILDw %08X:%08X\n", easeg, cpu_state.eaaddr); + if (fplog) DEBUG("FILDw %08X:%08X\n", easeg, cpu_state.eaaddr); temp = geteaw(); if (cpu_state.abrt) return 1; - if (fplog) pclog(" %f\n", (double)temp); + if (fplog) DEBUG(" %f\n", (double)temp); x87_push((double)temp); CLOCK_CYCLES(13); return 0; @@ -65,7 +65,7 @@ static int opFISTiw_a16(uint32_t fetchdat) int64_t temp64; FP_ENTER(); fetch_ea_16(fetchdat); - if (fplog) pclog("FISTw %08X:%08X\n", easeg, cpu_state.eaaddr); + if (fplog) DEBUG("FISTw %08X:%08X\n", easeg, cpu_state.eaaddr); temp64 = x87_fround(ST(0)); /* if (temp64 > 32767 || temp64 < -32768) fatal("FISTw overflow %i\n", temp64);*/ @@ -78,7 +78,7 @@ static int opFISTiw_a32(uint32_t fetchdat) int64_t temp64; FP_ENTER(); fetch_ea_32(fetchdat); - if (fplog) pclog("FISTw %08X:%08X\n", easeg, cpu_state.eaaddr); + if (fplog) DEBUG("FISTw %08X:%08X\n", easeg, cpu_state.eaaddr); temp64 = x87_fround(ST(0)); /* if (temp64 > 32767 || temp64 < -32768) fatal("FISTw overflow %i\n", temp64);*/ @@ -92,7 +92,7 @@ static int opFISTPiw_a16(uint32_t fetchdat) int64_t temp64; FP_ENTER(); fetch_ea_16(fetchdat); - if (fplog) pclog("FISTw %08X:%08X\n", easeg, cpu_state.eaaddr); + if (fplog) DEBUG("FISTw %08X:%08X\n", easeg, cpu_state.eaaddr); temp64 = x87_fround(ST(0)); /* if (temp64 > 32767 || temp64 < -32768) fatal("FISTw overflow %i\n", temp64);*/ @@ -106,7 +106,7 @@ static int opFISTPiw_a32(uint32_t fetchdat) int64_t temp64; FP_ENTER(); fetch_ea_32(fetchdat); - if (fplog) pclog("FISTw %08X:%08X\n", easeg, cpu_state.eaaddr); + if (fplog) DEBUG("FISTw %08X:%08X\n", easeg, cpu_state.eaaddr); temp64 = x87_fround(ST(0)); /* if (temp64 > 32767 || temp64 < -32768) fatal("FISTw overflow %i\n", temp64);*/ @@ -121,9 +121,9 @@ static int opFILDiq_a16(uint32_t fetchdat) int64_t temp64; FP_ENTER(); fetch_ea_16(fetchdat); - if (fplog) pclog("FILDl %08X:%08X\n", easeg, cpu_state.eaaddr); + if (fplog) DEBUG("FILDl %08X:%08X\n", easeg, cpu_state.eaaddr); temp64 = geteaq(); if (cpu_state.abrt) return 1; - if (fplog) pclog(" %f %08X %08X\n", (double)temp64, readmeml(easeg,cpu_state.eaaddr), readmeml(easeg,cpu_state.eaaddr+4)); + if (fplog) DEBUG(" %f %08X %08X\n", (double)temp64, readmeml(easeg,cpu_state.eaaddr), readmeml(easeg,cpu_state.eaaddr+4)); x87_push((double)temp64); cpu_state.MM[cpu_state.TOP].q = temp64; cpu_state.tag[cpu_state.TOP] |= TAG_UINT64; @@ -136,9 +136,9 @@ static int opFILDiq_a32(uint32_t fetchdat) int64_t temp64; FP_ENTER(); fetch_ea_32(fetchdat); - if (fplog) pclog("FILDl %08X:%08X\n", easeg, cpu_state.eaaddr); + if (fplog) DEBUG("FILDl %08X:%08X\n", easeg, cpu_state.eaaddr); temp64 = geteaq(); if (cpu_state.abrt) return 1; - if (fplog) pclog(" %f %08X %08X\n", (double)temp64, readmeml(easeg,cpu_state.eaaddr), readmeml(easeg,cpu_state.eaaddr+4)); + if (fplog) DEBUG(" %f %08X %08X\n", (double)temp64, readmeml(easeg,cpu_state.eaaddr), readmeml(easeg,cpu_state.eaaddr+4)); x87_push((double)temp64); cpu_state.MM[cpu_state.TOP].q = temp64; cpu_state.tag[cpu_state.TOP] |= TAG_UINT64; @@ -153,7 +153,7 @@ static int FBSTP_a16(uint32_t fetchdat) int c; FP_ENTER(); fetch_ea_16(fetchdat); - if (fplog) pclog("FBSTP %08X:%08X\n", easeg, cpu_state.eaaddr); + if (fplog) DEBUG("FBSTP %08X:%08X\n", easeg, cpu_state.eaaddr); tempd = ST(0); if (tempd < 0.0) tempd = -tempd; @@ -179,7 +179,7 @@ static int FBSTP_a32(uint32_t fetchdat) int c; FP_ENTER(); fetch_ea_32(fetchdat); - if (fplog) pclog("FBSTP %08X:%08X\n", easeg, cpu_state.eaaddr); + if (fplog) DEBUG("FBSTP %08X:%08X\n", easeg, cpu_state.eaaddr); tempd = ST(0); if (tempd < 0.0) tempd = -tempd; @@ -205,7 +205,7 @@ static int FISTPiq_a16(uint32_t fetchdat) int64_t temp64; FP_ENTER(); fetch_ea_16(fetchdat); - if (fplog) pclog("FISTPl %08X:%08X\n", easeg, cpu_state.eaaddr); + if (fplog) DEBUG("FISTPl %08X:%08X\n", easeg, cpu_state.eaaddr); if (cpu_state.tag[cpu_state.TOP] & TAG_UINT64) temp64 = cpu_state.MM[cpu_state.TOP].q; else @@ -220,7 +220,7 @@ static int FISTPiq_a32(uint32_t fetchdat) int64_t temp64; FP_ENTER(); fetch_ea_32(fetchdat); - if (fplog) pclog("FISTPl %08X:%08X\n", easeg, cpu_state.eaaddr); + if (fplog) DEBUG("FISTPl %08X:%08X\n", easeg, cpu_state.eaaddr); if (cpu_state.tag[cpu_state.TOP] & TAG_UINT64) temp64 = cpu_state.MM[cpu_state.TOP].q; else @@ -236,9 +236,9 @@ static int opFILDil_a16(uint32_t fetchdat) int32_t templ; FP_ENTER(); fetch_ea_16(fetchdat); - if (fplog) pclog("FILDs %08X:%08X\n", easeg, cpu_state.eaaddr); + if (fplog) DEBUG("FILDs %08X:%08X\n", easeg, cpu_state.eaaddr); templ = geteal(); if (cpu_state.abrt) return 1; - if (fplog) pclog(" %f %08X %i\n", (double)templ, templ, templ); + if (fplog) DEBUG(" %f %08X %i\n", (double)templ, templ, templ); x87_push((double)templ); CLOCK_CYCLES(9); return 0; @@ -248,9 +248,9 @@ static int opFILDil_a32(uint32_t fetchdat) int32_t templ; FP_ENTER(); fetch_ea_32(fetchdat); - if (fplog) pclog("FILDs %08X:%08X\n", easeg, cpu_state.eaaddr); + if (fplog) DEBUG("FILDs %08X:%08X\n", easeg, cpu_state.eaaddr); templ = geteal(); if (cpu_state.abrt) return 1; - if (fplog) pclog(" %f %08X %i\n", (double)templ, templ, templ); + if (fplog) DEBUG(" %f %08X %i\n", (double)templ, templ, templ); x87_push((double)templ); CLOCK_CYCLES(9); return 0; @@ -261,7 +261,7 @@ static int opFISTil_a16(uint32_t fetchdat) int64_t temp64; FP_ENTER(); fetch_ea_16(fetchdat); - if (fplog) pclog("FISTs %08X:%08X\n", easeg, cpu_state.eaaddr); + if (fplog) DEBUG("FISTs %08X:%08X\n", easeg, cpu_state.eaaddr); temp64 = x87_fround(ST(0)); /* if (temp64 > 2147483647 || temp64 < -2147483647) fatal("FISTl out of range! %i\n", temp64);*/ @@ -274,7 +274,7 @@ static int opFISTil_a32(uint32_t fetchdat) int64_t temp64; FP_ENTER(); fetch_ea_32(fetchdat); - if (fplog) pclog("FISTs %08X:%08X\n", easeg, cpu_state.eaaddr); + if (fplog) DEBUG("FISTs %08X:%08X\n", easeg, cpu_state.eaaddr); temp64 = x87_fround(ST(0)); /* if (temp64 > 2147483647 || temp64 < -2147483647) fatal("FISTl out of range! %i\n", temp64);*/ @@ -288,7 +288,7 @@ static int opFISTPil_a16(uint32_t fetchdat) int64_t temp64; FP_ENTER(); fetch_ea_16(fetchdat); - if (fplog) pclog("FISTs %08X:%08X\n", easeg, cpu_state.eaaddr); + if (fplog) DEBUG("FISTs %08X:%08X\n", easeg, cpu_state.eaaddr); temp64 = x87_fround(ST(0)); /* if (temp64 > 2147483647 || temp64 < -2147483647) fatal("FISTl out of range! %i\n", temp64);*/ @@ -302,7 +302,7 @@ static int opFISTPil_a32(uint32_t fetchdat) int64_t temp64; FP_ENTER(); fetch_ea_32(fetchdat); - if (fplog) pclog("FISTs %08X:%08X\n", easeg, cpu_state.eaaddr); + if (fplog) DEBUG("FISTs %08X:%08X\n", easeg, cpu_state.eaaddr); temp64 = x87_fround(ST(0)); /* if (temp64 > 2147483647 || temp64 < -2147483647) fatal("FISTl out of range! %i\n", temp64);*/ @@ -317,9 +317,9 @@ static int opFLDe_a16(uint32_t fetchdat) double t; FP_ENTER(); fetch_ea_16(fetchdat); - if (fplog) pclog("FLDe %08X:%08X\n", easeg, cpu_state.eaaddr); + if (fplog) DEBUG("FLDe %08X:%08X\n", easeg, cpu_state.eaaddr); t=x87_ld80(); if (cpu_state.abrt) return 1; - if (fplog) pclog(" %f\n", t); + if (fplog) DEBUG(" %f\n", t); x87_push(t); CLOCK_CYCLES(6); return 0; @@ -329,9 +329,9 @@ static int opFLDe_a32(uint32_t fetchdat) double t; FP_ENTER(); fetch_ea_32(fetchdat); - if (fplog) pclog("FLDe %08X:%08X\n", easeg, cpu_state.eaaddr); + if (fplog) DEBUG("FLDe %08X:%08X\n", easeg, cpu_state.eaaddr); t=x87_ld80(); if (cpu_state.abrt) return 1; - if (fplog) pclog(" %f\n", t); + if (fplog) DEBUG(" %f\n", t); x87_push(t); CLOCK_CYCLES(6); return 0; @@ -341,7 +341,7 @@ static int opFSTPe_a16(uint32_t fetchdat) { FP_ENTER(); fetch_ea_16(fetchdat); - if (fplog) pclog("FSTPe %08X:%08X\n", easeg, cpu_state.eaaddr); + if (fplog) DEBUG("FSTPe %08X:%08X\n", easeg, cpu_state.eaaddr); x87_st80(ST(0)); if (cpu_state.abrt) return 1; x87_pop(); CLOCK_CYCLES(6); @@ -351,7 +351,7 @@ static int opFSTPe_a32(uint32_t fetchdat) { FP_ENTER(); fetch_ea_32(fetchdat); - if (fplog) pclog("FSTPe %08X:%08X\n", easeg, cpu_state.eaaddr); + if (fplog) DEBUG("FSTPe %08X:%08X\n", easeg, cpu_state.eaaddr); x87_st80(ST(0)); if (cpu_state.abrt) return 1; x87_pop(); CLOCK_CYCLES(6); @@ -363,9 +363,9 @@ static int opFLDd_a16(uint32_t fetchdat) x87_td t; FP_ENTER(); fetch_ea_16(fetchdat); - if (fplog) pclog("FLDd %08X:%08X\n", easeg, cpu_state.eaaddr); + if (fplog) DEBUG("FLDd %08X:%08X\n", easeg, cpu_state.eaaddr); t.i = geteaq(); if (cpu_state.abrt) return 1; - if (fplog) pclog(" %f\n", t.d); + if (fplog) DEBUG(" %f\n", t.d); x87_push(t.d); CLOCK_CYCLES(3); return 0; @@ -375,9 +375,9 @@ static int opFLDd_a32(uint32_t fetchdat) x87_td t; FP_ENTER(); fetch_ea_32(fetchdat); - if (fplog) pclog("FLDd %08X:%08X\n", easeg, cpu_state.eaaddr); + if (fplog) DEBUG("FLDd %08X:%08X\n", easeg, cpu_state.eaaddr); t.i = geteaq(); if (cpu_state.abrt) return 1; - if (fplog) pclog(" %f\n", t.d); + if (fplog) DEBUG(" %f\n", t.d); x87_push(t.d); CLOCK_CYCLES(3); return 0; @@ -388,7 +388,7 @@ static int opFSTd_a16(uint32_t fetchdat) x87_td t; FP_ENTER(); fetch_ea_16(fetchdat); - if (fplog) pclog("FSTd %08X:%08X\n", easeg, cpu_state.eaaddr); + if (fplog) DEBUG("FSTd %08X:%08X\n", easeg, cpu_state.eaaddr); t.d = ST(0); seteaq(t.i); CLOCK_CYCLES(8); @@ -399,7 +399,7 @@ static int opFSTd_a32(uint32_t fetchdat) x87_td t; FP_ENTER(); fetch_ea_32(fetchdat); - if (fplog) pclog("FSTd %08X:%08X\n", easeg, cpu_state.eaaddr); + if (fplog) DEBUG("FSTd %08X:%08X\n", easeg, cpu_state.eaaddr); t.d = ST(0); seteaq(t.i); CLOCK_CYCLES(8); @@ -412,7 +412,7 @@ static int opFSTPd_a16(uint32_t fetchdat) FP_ENTER(); fetch_ea_16(fetchdat); CHECK_WRITE(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 7); - if (fplog) pclog("FSTd %08X:%08X\n", easeg, cpu_state.eaaddr); + if (fplog) DEBUG("FSTd %08X:%08X\n", easeg, cpu_state.eaaddr); t.d = ST(0); seteaq(t.i); if (cpu_state.abrt) return 1; x87_pop(); @@ -425,7 +425,7 @@ static int opFSTPd_a32(uint32_t fetchdat) FP_ENTER(); fetch_ea_32(fetchdat); CHECK_WRITE(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 7); - if (fplog) pclog("FSTd %08X:%08X\n", easeg, cpu_state.eaaddr); + if (fplog) DEBUG("FSTd %08X:%08X\n", easeg, cpu_state.eaaddr); t.d = ST(0); seteaq(t.i); if (cpu_state.abrt) return 1; x87_pop(); @@ -438,9 +438,9 @@ static int opFLDs_a16(uint32_t fetchdat) x87_ts ts; FP_ENTER(); fetch_ea_16(fetchdat); - if (fplog) pclog("FLDs %08X:%08X\n", easeg, cpu_state.eaaddr); + if (fplog) DEBUG("FLDs %08X:%08X\n", easeg, cpu_state.eaaddr); ts.i = geteal(); if (cpu_state.abrt) return 1; - if (fplog) pclog(" %f\n", ts.s); + if (fplog) DEBUG(" %f\n", ts.s); x87_push((double)ts.s); CLOCK_CYCLES(3); return 0; @@ -450,9 +450,9 @@ static int opFLDs_a32(uint32_t fetchdat) x87_ts ts; FP_ENTER(); fetch_ea_32(fetchdat); - if (fplog) pclog("FLDs %08X:%08X\n", easeg, cpu_state.eaaddr); + if (fplog) DEBUG("FLDs %08X:%08X\n", easeg, cpu_state.eaaddr); ts.i = geteal(); if (cpu_state.abrt) return 1; - if (fplog) pclog(" %f\n", ts.s); + if (fplog) DEBUG(" %f\n", ts.s); x87_push((double)ts.s); CLOCK_CYCLES(3); return 0; @@ -463,7 +463,7 @@ static int opFSTs_a16(uint32_t fetchdat) x87_ts ts; FP_ENTER(); fetch_ea_16(fetchdat); - if (fplog) pclog("FSTs %08X:%08X\n", easeg, cpu_state.eaaddr); + if (fplog) DEBUG("FSTs %08X:%08X\n", easeg, cpu_state.eaaddr); ts.s = (float)ST(0); seteal(ts.i); CLOCK_CYCLES(7); @@ -474,7 +474,7 @@ static int opFSTs_a32(uint32_t fetchdat) x87_ts ts; FP_ENTER(); fetch_ea_32(fetchdat); - if (fplog) pclog("FSTs %08X:%08X\n", easeg, cpu_state.eaaddr); + if (fplog) DEBUG("FSTs %08X:%08X\n", easeg, cpu_state.eaaddr); ts.s = (float)ST(0); seteal(ts.i); CLOCK_CYCLES(7); @@ -486,7 +486,7 @@ static int opFSTPs_a16(uint32_t fetchdat) x87_ts ts; FP_ENTER(); fetch_ea_16(fetchdat); - if (fplog) pclog("FSTs %08X:%08X\n", easeg, cpu_state.eaaddr); + if (fplog) DEBUG("FSTs %08X:%08X\n", easeg, cpu_state.eaaddr); ts.s = (float)ST(0); seteal(ts.i); if (cpu_state.abrt) return 1; x87_pop(); @@ -498,7 +498,7 @@ static int opFSTPs_a32(uint32_t fetchdat) x87_ts ts; FP_ENTER(); fetch_ea_32(fetchdat); - if (fplog) pclog("FSTs %08X:%08X\n", easeg, cpu_state.eaaddr); + if (fplog) DEBUG("FSTs %08X:%08X\n", easeg, cpu_state.eaaddr); ts.s = (float)ST(0); seteal(ts.i); if (cpu_state.abrt) return 1; x87_pop(); diff --git a/src/cpu/x87_ops_misc.h b/src/cpu/x87_ops_misc.h index a087be1..fe34810 100644 --- a/src/cpu/x87_ops_misc.h +++ b/src/cpu/x87_ops_misc.h @@ -8,7 +8,7 @@ * * Miscellaneous x87 FPU Instructions. * - * Version: @(#)x87_ops_loadstore.h 1.0.1 2018/02/14 + * Version: @(#)x87_ops_misc.h 1.0.2 2018/09/04 * * Authors: Sarah Walker, * Miran Grca, @@ -39,7 +39,7 @@ static int opFSTSW_AX(uint32_t fetchdat) { FP_ENTER(); cpu_state.pc++; - if (fplog) pclog("FSTSW\n"); + if (fplog) DEBUG("FSTSW\n"); AX = cpu_state.npxs; CLOCK_CYCLES(3); return 0; @@ -85,7 +85,7 @@ static int opFFREE(uint32_t fetchdat) { FP_ENTER(); cpu_state.pc++; - if (fplog) pclog("FFREE\n"); + if (fplog) DEBUG("FFREE\n"); cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = 3; CLOCK_CYCLES(3); return 0; @@ -95,7 +95,7 @@ static int opFFREEP(uint32_t fetchdat) { FP_ENTER(); cpu_state.pc++; - if (fplog) pclog("FFREE\n"); + if (fplog) DEBUG("FFREE\n"); cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = 3; if (cpu_state.abrt) return 1; x87_pop(); CLOCK_CYCLES(3); @@ -106,7 +106,7 @@ static int opFST(uint32_t fetchdat) { FP_ENTER(); cpu_state.pc++; - if (fplog) pclog("FST\n"); + if (fplog) DEBUG("FST\n"); ST(fetchdat & 7) = ST(0); cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = cpu_state.tag[cpu_state.TOP & 7]; CLOCK_CYCLES(3); @@ -117,7 +117,7 @@ static int opFSTP(uint32_t fetchdat) { FP_ENTER(); cpu_state.pc++; - if (fplog) pclog("FSTP\n"); + if (fplog) DEBUG("FSTP\n"); ST(fetchdat & 7) = ST(0); cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = cpu_state.tag[cpu_state.TOP & 7]; x87_pop(); @@ -172,7 +172,7 @@ static int FSTOR() cpu_state.ismmx = 1; CLOCK_CYCLES((cr0 & 1) ? 34 : 44); - if (fplog) pclog("FRSTOR %08X:%08X %i %i %04X\n", easeg, cpu_state.eaaddr, cpu_state.ismmx, cpu_state.TOP, x87_gettag()); + if (fplog) DEBUG("FRSTOR %08X:%08X %i %i %04X\n", easeg, cpu_state.eaaddr, cpu_state.ismmx, cpu_state.TOP, x87_gettag()); return cpu_state.abrt; } static int opFSTOR_a16(uint32_t fetchdat) @@ -195,7 +195,7 @@ static int FSAVE() uint64_t *p; FP_ENTER(); - if (fplog) pclog("FSAVE %08X:%08X %i\n", easeg, cpu_state.eaaddr, cpu_state.ismmx); + if (fplog) DEBUG("FSAVE %08X:%08X %i\n", easeg, cpu_state.eaaddr, cpu_state.ismmx); cpu_state.npxs = (cpu_state.npxs & ~(7 << 11)) | (cpu_state.TOP << 11); switch ((cr0 & 1) | (cpu_state.op32 & 0x100)) @@ -357,7 +357,7 @@ static int opFSTSW_a16(uint32_t fetchdat) { FP_ENTER(); fetch_ea_16(fetchdat); - if (fplog) pclog("FSTSW %08X:%08X\n", easeg, cpu_state.eaaddr); + if (fplog) DEBUG("FSTSW %08X:%08X\n", easeg, cpu_state.eaaddr); seteaw((cpu_state.npxs & 0xC7FF) | (cpu_state.TOP << 11)); CLOCK_CYCLES(3); return cpu_state.abrt; @@ -366,7 +366,7 @@ static int opFSTSW_a32(uint32_t fetchdat) { FP_ENTER(); fetch_ea_32(fetchdat); - if (fplog) pclog("FSTSW %08X:%08X\n", easeg, cpu_state.eaaddr); + if (fplog) DEBUG("FSTSW %08X:%08X\n", easeg, cpu_state.eaaddr); seteaw((cpu_state.npxs & 0xC7FF) | (cpu_state.TOP << 11)); CLOCK_CYCLES(3); return cpu_state.abrt; @@ -380,7 +380,7 @@ static int opFLD(uint32_t fetchdat) FP_ENTER(); cpu_state.pc++; - if (fplog) pclog("FLD %f\n", ST(fetchdat & 7)); + if (fplog) DEBUG("FLD %f\n", ST(fetchdat & 7)); old_tag = cpu_state.tag[(cpu_state.TOP + fetchdat) & 7]; old_i64 = cpu_state.MM[(cpu_state.TOP + fetchdat) & 7].q; x87_push(ST(fetchdat&7)); @@ -397,7 +397,7 @@ static int opFXCH(uint32_t fetchdat) uint64_t old_i64; FP_ENTER(); cpu_state.pc++; - if (fplog) pclog("FXCH\n"); + if (fplog) DEBUG("FXCH\n"); td = ST(0); ST(0) = ST(fetchdat&7); ST(fetchdat&7) = td; @@ -416,7 +416,7 @@ static int opFCHS(uint32_t fetchdat) { FP_ENTER(); cpu_state.pc++; - if (fplog) pclog("FCHS\n"); + if (fplog) DEBUG("FCHS\n"); ST(0) = -ST(0); cpu_state.tag[cpu_state.TOP] &= ~TAG_UINT64; CLOCK_CYCLES(6); @@ -427,7 +427,7 @@ static int opFABS(uint32_t fetchdat) { FP_ENTER(); cpu_state.pc++; - if (fplog) pclog("FABS %f\n", ST(0)); + if (fplog) DEBUG("FABS %f\n", ST(0)); ST(0) = fabs(ST(0)); cpu_state.tag[cpu_state.TOP] &= ~TAG_UINT64; CLOCK_CYCLES(3); @@ -438,7 +438,7 @@ static int opFTST(uint32_t fetchdat) { FP_ENTER(); cpu_state.pc++; - if (fplog) pclog("FTST\n"); + if (fplog) DEBUG("FTST\n"); cpu_state.npxs &= ~(C0|C2|C3); if (ST(0) == 0.0) cpu_state.npxs |= C3; else if (ST(0) < 0.0) cpu_state.npxs |= C0; @@ -450,7 +450,7 @@ static int opFXAM(uint32_t fetchdat) { FP_ENTER(); cpu_state.pc++; - if (fplog) pclog("FXAM %i %f\n", cpu_state.tag[cpu_state.TOP&7], ST(0)); + if (fplog) DEBUG("FXAM %i %f\n", cpu_state.tag[cpu_state.TOP&7], ST(0)); cpu_state.npxs &= ~(C0|C1|C2|C3); if (cpu_state.tag[cpu_state.TOP&7] == 3) cpu_state.npxs |= (C0|C3); else if (ST(0) == 0.0) cpu_state.npxs |= C3; @@ -464,7 +464,7 @@ static int opFLD1(uint32_t fetchdat) { FP_ENTER(); cpu_state.pc++; - if (fplog) pclog("FLD1\n"); + if (fplog) DEBUG("FLD1\n"); x87_push(1.0); CLOCK_CYCLES(4); return 0; @@ -474,7 +474,7 @@ static int opFLDL2T(uint32_t fetchdat) { FP_ENTER(); cpu_state.pc++; - if (fplog) pclog("FLDL2T\n"); + if (fplog) DEBUG("FLDL2T\n"); x87_push(3.3219280948873623); CLOCK_CYCLES(8); return 0; @@ -484,7 +484,7 @@ static int opFLDL2E(uint32_t fetchdat) { FP_ENTER(); cpu_state.pc++; - if (fplog) pclog("FLDL2E\n"); + if (fplog) DEBUG("FLDL2E\n"); x87_push(1.4426950408889634); CLOCK_CYCLES(8); return 0; @@ -494,7 +494,7 @@ static int opFLDPI(uint32_t fetchdat) { FP_ENTER(); cpu_state.pc++; - if (fplog) pclog("FLDPI\n"); + if (fplog) DEBUG("FLDPI\n"); x87_push(3.141592653589793); CLOCK_CYCLES(8); return 0; @@ -504,7 +504,7 @@ static int opFLDEG2(uint32_t fetchdat) { FP_ENTER(); cpu_state.pc++; - if (fplog) pclog("FLDEG2\n"); + if (fplog) DEBUG("FLDEG2\n"); x87_push(0.3010299956639812); CLOCK_CYCLES(8); return 0; @@ -514,8 +514,8 @@ static int opFLDLN2(uint32_t fetchdat) { FP_ENTER(); cpu_state.pc++; - if (fplog) pclog("FLDLN2\n"); - x87_push(0.693147180559945); + if (fplog) DEBUG("FLDLN2\n"); + x87_push_u64(0x3fe62e42fefa39f0ULL); CLOCK_CYCLES(8); return 0; } @@ -524,7 +524,7 @@ static int opFLDZ(uint32_t fetchdat) { FP_ENTER(); cpu_state.pc++; - if (fplog) pclog("FLDZ\n"); + if (fplog) DEBUG("FLDZ\n"); x87_push(0.0); cpu_state.tag[cpu_state.TOP&7] = 1; CLOCK_CYCLES(4); @@ -535,7 +535,7 @@ static int opF2XM1(uint32_t fetchdat) { FP_ENTER(); cpu_state.pc++; - if (fplog) pclog("F2XM1\n"); + if (fplog) DEBUG("F2XM1\n"); ST(0) = pow(2.0, ST(0)) - 1.0; cpu_state.tag[cpu_state.TOP] &= ~TAG_UINT64; CLOCK_CYCLES(200); @@ -546,7 +546,7 @@ static int opFYL2X(uint32_t fetchdat) { FP_ENTER(); cpu_state.pc++; - if (fplog) pclog("FYL2X\n"); + if (fplog) DEBUG("FYL2X\n"); ST(1) = ST(1) * (log(ST(0)) / log(2.0)); cpu_state.tag[(cpu_state.TOP + 1) & 7] &= ~TAG_UINT64; x87_pop(); @@ -558,7 +558,7 @@ static int opFYL2XP1(uint32_t fetchdat) { FP_ENTER(); cpu_state.pc++; - if (fplog) pclog("FYL2XP1\n"); + if (fplog) DEBUG("FYL2XP1\n"); ST(1) = ST(1) * (log1p(ST(0)) / log(2.0)); cpu_state.tag[(cpu_state.TOP + 1) & 7] &= ~TAG_UINT64; x87_pop(); @@ -570,7 +570,7 @@ static int opFPTAN(uint32_t fetchdat) { FP_ENTER(); cpu_state.pc++; - if (fplog) pclog("FPTAN\n"); + if (fplog) DEBUG("FPTAN\n"); ST(0) = tan(ST(0)); cpu_state.tag[cpu_state.TOP] &= ~TAG_UINT64; x87_push(1.0); @@ -583,7 +583,7 @@ static int opFPATAN(uint32_t fetchdat) { FP_ENTER(); cpu_state.pc++; - if (fplog) pclog("FPATAN\n"); + if (fplog) DEBUG("FPATAN\n"); ST(1) = atan2(ST(1), ST(0)); cpu_state.tag[(cpu_state.TOP + 1) & 7] &= ~TAG_UINT64; x87_pop(); @@ -595,7 +595,7 @@ static int opFDECSTP(uint32_t fetchdat) { FP_ENTER(); cpu_state.pc++; - if (fplog) pclog("FDECSTP\n"); + if (fplog) DEBUG("FDECSTP\n"); cpu_state.TOP = (cpu_state.TOP - 1) & 7; CLOCK_CYCLES(4); return 0; @@ -605,7 +605,7 @@ static int opFINCSTP(uint32_t fetchdat) { FP_ENTER(); cpu_state.pc++; - if (fplog) pclog("FDECSTP\n"); + if (fplog) DEBUG("FDECSTP\n"); cpu_state.TOP = (cpu_state.TOP + 1) & 7; CLOCK_CYCLES(4); return 0; @@ -616,11 +616,11 @@ static int opFPREM(uint32_t fetchdat) int64_t temp64; FP_ENTER(); cpu_state.pc++; - if (fplog) pclog("FPREM %f %f ", ST(0), ST(1)); + if (fplog) DEBUG("FPREM %f %f ", ST(0), ST(1)); temp64 = (int64_t)(ST(0) / ST(1)); ST(0) = ST(0) - (ST(1) * (double)temp64); cpu_state.tag[cpu_state.TOP] &= ~TAG_UINT64; - if (fplog) pclog("%f\n", ST(0)); + if (fplog) DEBUG("%f\n", ST(0)); cpu_state.npxs &= ~(C0|C1|C2|C3); if (temp64 & 4) cpu_state.npxs|=C0; if (temp64 & 2) cpu_state.npxs|=C3; @@ -633,11 +633,11 @@ static int opFPREM1(uint32_t fetchdat) int64_t temp64; FP_ENTER(); cpu_state.pc++; - if (fplog) pclog("FPREM1 %f %f ", ST(0), ST(1)); + if (fplog) DEBUG("FPREM1 %f %f ", ST(0), ST(1)); temp64 = (int64_t)(ST(0) / ST(1)); ST(0) = ST(0) - (ST(1) * (double)temp64); cpu_state.tag[cpu_state.TOP] &= ~TAG_UINT64; - if (fplog) pclog("%f\n", ST(0)); + if (fplog) DEBUG("%f\n", ST(0)); cpu_state.npxs &= ~(C0|C1|C2|C3); if (temp64 & 4) cpu_state.npxs|=C0; if (temp64 & 2) cpu_state.npxs|=C3; @@ -650,7 +650,7 @@ static int opFSQRT(uint32_t fetchdat) { FP_ENTER(); cpu_state.pc++; - if (fplog) pclog("FSQRT\n"); + if (fplog) DEBUG("FSQRT\n"); ST(0) = sqrt(ST(0)); cpu_state.tag[cpu_state.TOP] &= ~TAG_UINT64; CLOCK_CYCLES(83); @@ -662,7 +662,7 @@ static int opFSINCOS(uint32_t fetchdat) double td; FP_ENTER(); cpu_state.pc++; - if (fplog) pclog("FSINCOS\n"); + if (fplog) DEBUG("FSINCOS\n"); td = ST(0); ST(0) = sin(td); cpu_state.tag[cpu_state.TOP] &= ~TAG_UINT64; @@ -676,10 +676,10 @@ static int opFRNDINT(uint32_t fetchdat) { FP_ENTER(); cpu_state.pc++; - if (fplog) pclog("FRNDINT %g ", ST(0)); + if (fplog) DEBUG("FRNDINT %g ", ST(0)); ST(0) = (double)x87_fround(ST(0)); cpu_state.tag[cpu_state.TOP] &= ~TAG_UINT64; - if (fplog) pclog("%g\n", ST(0)); + if (fplog) DEBUG("%g\n", ST(0)); CLOCK_CYCLES(21); return 0; } @@ -689,7 +689,7 @@ static int opFSCALE(uint32_t fetchdat) int64_t temp64; FP_ENTER(); cpu_state.pc++; - if (fplog) pclog("FSCALE\n"); + if (fplog) DEBUG("FSCALE\n"); temp64 = (int64_t)ST(1); ST(0) = ST(0) * pow(2.0, (double)temp64); cpu_state.tag[cpu_state.TOP] &= ~TAG_UINT64; @@ -701,7 +701,7 @@ static int opFSIN(uint32_t fetchdat) { FP_ENTER(); cpu_state.pc++; - if (fplog) pclog("FSIN\n"); + if (fplog) DEBUG("FSIN\n"); ST(0) = sin(ST(0)); cpu_state.tag[cpu_state.TOP] &= ~TAG_UINT64; cpu_state.npxs &= ~C2; @@ -713,7 +713,7 @@ static int opFCOS(uint32_t fetchdat) { FP_ENTER(); cpu_state.pc++; - if (fplog) pclog("FCOS\n"); + if (fplog) DEBUG("FCOS\n"); ST(0) = cos(ST(0)); cpu_state.tag[cpu_state.TOP] &= ~TAG_UINT64; cpu_state.npxs &= ~C2; @@ -725,7 +725,7 @@ static int opFCOS(uint32_t fetchdat) static int FLDENV() { FP_ENTER(); - if (fplog) pclog("FLDENV %08X:%08X\n", easeg, cpu_state.eaaddr); + if (fplog) DEBUG("FLDENV %08X:%08X\n", easeg, cpu_state.eaaddr); switch ((cr0 & 1) | (cpu_state.op32 & 0x100)) { case 0x000: /*16-bit real mode*/ @@ -769,7 +769,7 @@ static int opFLDCW_a16(uint32_t fetchdat) uint16_t tempw; FP_ENTER(); fetch_ea_16(fetchdat); - if (fplog) pclog("FLDCW %08X:%08X\n", easeg, cpu_state.eaaddr); + if (fplog) DEBUG("FLDCW %08X:%08X\n", easeg, cpu_state.eaaddr); tempw = geteaw(); if (cpu_state.abrt) return 1; cpu_state.npxc = tempw; @@ -782,7 +782,7 @@ static int opFLDCW_a32(uint32_t fetchdat) uint16_t tempw; FP_ENTER(); fetch_ea_32(fetchdat); - if (fplog) pclog("FLDCW %08X:%08X\n", easeg, cpu_state.eaaddr); + if (fplog) DEBUG("FLDCW %08X:%08X\n", easeg, cpu_state.eaaddr); tempw = geteaw(); if (cpu_state.abrt) return 1; cpu_state.npxc = tempw; @@ -794,7 +794,7 @@ static int opFLDCW_a32(uint32_t fetchdat) static int FSTENV() { FP_ENTER(); - if (fplog) pclog("FSTENV %08X:%08X\n", easeg, cpu_state.eaaddr); + if (fplog) DEBUG("FSTENV %08X:%08X\n", easeg, cpu_state.eaaddr); switch ((cr0 & 1) | (cpu_state.op32 & 0x100)) { case 0x000: /*16-bit real mode*/ @@ -854,7 +854,7 @@ static int opFSTCW_a16(uint32_t fetchdat) { FP_ENTER(); fetch_ea_16(fetchdat); - if (fplog) pclog("FSTCW %08X:%08X\n", easeg, cpu_state.eaaddr); + if (fplog) DEBUG("FSTCW %08X:%08X\n", easeg, cpu_state.eaaddr); seteaw(cpu_state.npxc); CLOCK_CYCLES(3); return cpu_state.abrt; @@ -863,7 +863,7 @@ static int opFSTCW_a32(uint32_t fetchdat) { FP_ENTER(); fetch_ea_32(fetchdat); - if (fplog) pclog("FSTCW %08X:%08X\n", easeg, cpu_state.eaaddr); + if (fplog) DEBUG("FSTCW %08X:%08X\n", easeg, cpu_state.eaaddr); seteaw(cpu_state.npxc); CLOCK_CYCLES(3); return cpu_state.abrt; @@ -874,7 +874,7 @@ static int opFSTCW_a32(uint32_t fetchdat) { \ FP_ENTER(); \ cpu_state.pc++; \ - if (fplog) pclog("FCMOV %f\n", ST(fetchdat & 7)); \ + if (fplog) DEBUG("FCMOV %f\n", ST(fetchdat & 7)); \ if (cond_ ## condition) \ { \ cpu_state.tag[cpu_state.TOP] = cpu_state.tag[(cpu_state.TOP + fetchdat) & 7]; \ diff --git a/src/device.c b/src/device.c index a40d669..348b866 100644 --- a/src/device.c +++ b/src/device.c @@ -9,7 +9,7 @@ * Implementation of the generic device interface to handle * all devices attached to the emulator. * - * Version: @(#)device.c 1.0.14 2018/04/02 + * Version: @(#)device.c 1.0.15 2018/10/05 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -44,7 +44,6 @@ #include #include "emu.h" #include "config.h" -#include "cpu/cpu.h" #include "device.h" #include "machines/machine.h" #include "devices/sound/sound.h" @@ -101,7 +100,7 @@ device_clone(const device_t *master) /* If not found, add this master to the list. */ if (ptr == NULL) { - ptr = (clonedev_t *)malloc(sizeof(clonedev_t)); + ptr = (clonedev_t *)mem_alloc(sizeof(clonedev_t)); memset(ptr, 0x00, sizeof(clonedev_t)); if (clones != NULL) { for (cl = clones; cl->next != NULL; cl = cl->next) @@ -113,7 +112,7 @@ device_clone(const device_t *master) } /* Create a new device. */ - dev = (device_t *)malloc(sizeof(device_t)); + dev = (device_t *)mem_alloc(sizeof(device_t)); /* Copy the master info. */ memcpy(dev, ptr->master, sizeof(device_t)); @@ -123,7 +122,7 @@ device_clone(const device_t *master) sprintf(temp, "%s #%i", ptr->master->name, ptr->count); else strcpy(temp, ptr->master->name); - sp = (char *)malloc(strlen(temp) + 1); + sp = (char *)mem_alloc(strlen(temp) + 1); strcpy(sp, temp); dev->name = (const char *)sp; @@ -135,13 +134,12 @@ void * device_add(const device_t *d) { wchar_t temp[1024]; - wchar_t devname[64]; void *priv = NULL; int c; - for (c = 0; c < 256; c++) { + for (c = 0; c < DEVICE_MAX; c++) { if (devices[c] == (device_t *)d) { - pclog("DEVICE: device already exists!\n"); + ERRLOG("DEVICE: device already exists!\n"); return(NULL); } if (devices[c] == NULL) break; @@ -156,30 +154,34 @@ device_add(const device_t *d) * reports... we warn them... */ if (d->flags & DEVICE_UNSTABLE) { - mbstowcs(devname, d->name, sizeof_w(devname)); - swprintf(temp, sizeof_w(temp), get_string(IDS_MSG_UNSTABL), devname); + swprintf(temp, sizeof_w(temp), + get_string(IDS_MSG_UNSTABL), d->name); /* Show the messagebox, and abort if 'No' was selected. */ if (ui_msgbox(MBX_WARNING, temp) == 1) return(0); /* OK, they are fine with it. Log this! */ - pclog("UNSTABLE: device '%s' is unstable, user agreed!\n", d->name); + INFO("DEVICE: device '%s' is unstable, user agreed!\n", d->name); } device_current = (device_t *)d; + devices[c] = (device_t *)d; + if (d->init != NULL) { priv = d->init(d); if (priv == NULL) { if (d->name) - pclog("DEVICE: device '%s' init failed\n", d->name); + ERRLOG("DEVICE: device '%s' init failed\n", d->name); else - pclog("DEVICE: device init failed\n"); + ERRLOG("DEVICE: device init failed\n"); + + devices[c] = NULL; + return(NULL); } } - devices[c] = (device_t *)d; device_priv[c] = priv; return(priv); @@ -192,15 +194,15 @@ device_add_ex(const device_t *d, void *priv) { int c; - for (c = 0; c < 256; c++) { + for (c = 0; c < DEVICE_MAX; c++) { if (devices[c] == (device_t *)d) { - fatal("device_add: device already exists!\n"); + fatal("DEVICE: device already exists!\n"); break; } if (devices[c] == NULL) break; } if (c >= DEVICE_MAX) - fatal("device_add: too many devices\n"); + fatal("DEVICE: too many devices\n"); device_current = (device_t *)d; @@ -218,20 +220,26 @@ device_close_all(void) if (devices[c] != NULL) { if (devices[c]->close != NULL) devices[c]->close(device_priv[c]); - devices[c] = device_priv[c] = NULL; + devices[c] = NULL; + device_priv[c] = NULL; } } } void -device_reset_all(void) +device_reset_all(int flags) { int c; for (c = 0; c < DEVICE_MAX; c++) { if (devices[c] != NULL) { - if (devices[c]->reset != NULL) + if (devices[c]->reset == NULL) continue; + + if (flags != DEVICE_ALL) { + if (devices[c]->flags & flags) + devices[c]->reset(device_priv[c]); + } else devices[c]->reset(device_priv[c]); } } @@ -254,14 +262,63 @@ device_get_priv(const device_t *d) } +/* Return name of the bus required by this device. */ +const char * +device_get_bus_name(const device_t *d) +{ + const char *s = "unknown"; + + if (d != NULL) switch(d->flags & DEVICE_BUS_MASK) { + case DEVICE_ISA: + s = "ISA"; + break; + + case DEVICE_CBUS: + s = "CBUS"; + break; + + case DEVICE_MCA: + s = "MCA"; + break; + + case DEVICE_EISA: + s = "EISA"; + break; + + case DEVICE_VLB: + s = "VLB"; + break; + + case DEVICE_PCI: + s = "PCI"; + break; + + case DEVICE_AGP: + s = "AGP"; + break; + + default: + break; + } + + return(s); +} + + int device_available(const device_t *d) { + int (*func)(void); + + if (d == NULL) return(1); + #ifdef RELEASE_BUILD if (d->flags & DEVICE_NOT_WORKING) return(0); #endif - if (d->available != NULL) - return(d->available()); + if (d->dev_available != NULL) { + func = d->dev_available; + return(func()); + } return(1); } @@ -297,20 +354,6 @@ device_force_redraw(void) } -void -device_add_status_info(char *s, int max_len) -{ - int c; - - for (c = 0; c < DEVICE_MAX; c++) { - if (devices[c] != NULL) { - if (devices[c]->add_status_info != NULL) - devices[c]->add_status_info(s, max_len, device_priv[c]); - } - } -} - - const char * device_get_config_string(const char *s) { diff --git a/src/device.h b/src/device.h index 387041f..916f239 100644 --- a/src/device.h +++ b/src/device.h @@ -8,7 +8,7 @@ * * Definitions for the device handler. * - * Version: @(#)device.h 1.0.7 2018/08/20 + * Version: @(#)device.h 1.0.8 2018/09/19 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -53,17 +53,20 @@ enum { - DEVICE_UNSTABLE = 1, /* unstable device, be cautious */ - DEVICE_AT = 2, /* requires an AT-compatible system */ - DEVICE_PS2 = 4, /* requires a PS/1 or PS/2 system */ - DEVICE_ISA = 8, /* requires the ISA bus */ - DEVICE_CBUS = 0x10, /* requires the C-BUS bus */ - DEVICE_MCA = 0x20, /* requires the MCA bus */ - DEVICE_EISA = 0x40, /* requires the EISA bus */ - DEVICE_VLB = 0x80, /* requires the PCI bus */ - DEVICE_PCI = 0x100, /* requires the VLB bus */ - DEVICE_AGP = 0x200 /* requires the AGP bus */ + DEVICE_ALL = 0x0000, /* any/all device */ + DEVICE_UNSTABLE = 0x0001, /* unstable device, be cautious */ + DEVICE_AT = 0x0002, /* requires an AT-compatible system */ + DEVICE_PS2 = 0x0004, /* requires a PS/1 or PS/2 system */ + DEVICE_ISA = 0x0100, /* requires the ISA bus */ + DEVICE_CBUS = 0x0200, /* requires the C-BUS bus */ + DEVICE_MCA = 0x0400, /* requires the MCA bus */ + DEVICE_EISA = 0x0800, /* requires the EISA bus */ + DEVICE_VLB = 0x1000, /* requires the PCI bus */ + DEVICE_PCI = 0x2000, /* requires the VLB bus */ + DEVICE_AGP = 0x4000 /* requires the AGP bus */ }; +#define DEVICE_SYS_MASK 0x0006 +#define DEVICE_BUS_MASK 0xff00 typedef struct { @@ -101,11 +104,14 @@ typedef struct _device_ { void *(*init)(const struct _device_ *); void (*close)(void *priv); void (*reset)(void *priv); - int (*available)(/*void*/); + void *u1_reuse; +#define ms_poll u1_reuse +#define dev_available u1_reuse void (*speed_changed)(void *priv); void (*force_redraw)(void *priv); - void (*add_status_info)(char *s, int max_len, void *priv); - + const void *u2_reuse; +#define vid_timing u2_reuse +#define mca_reslist u2_reuse const device_config_t *config; } device_t; @@ -115,16 +121,16 @@ extern "C" { #endif extern void device_init(void); -extern const device_t * device_clone(const device_t *master); +extern const device_t *device_clone(const device_t *master); extern void *device_add(const device_t *); extern void device_add_ex(const device_t *d, void *priv); extern void device_close_all(void); -extern void device_reset_all(void); +extern void device_reset_all(int flags); extern void *device_get_priv(const device_t *); +extern const char *device_get_bus_name(const device_t *); extern int device_available(const device_t *); extern void device_speed_changed(void); extern void device_force_redraw(void); -extern void device_add_status_info(char *s, int max_len); extern int device_is_valid(const device_t *, int machine_flags); diff --git a/src/devices/cdrom/cdrom.c b/src/devices/cdrom/cdrom.c index 112f999..7aaf775 100644 --- a/src/devices/cdrom/cdrom.c +++ b/src/devices/cdrom/cdrom.c @@ -9,7 +9,7 @@ * Implementation of the CD-ROM drive with SCSI(-like) * commands, for both ATAPI and SCSI usage. * - * Version: @(#)cdrom.c 1.0.16 2018/09/21 + * Version: @(#)cdrom.c 1.0.16 2018/10/05 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -45,6 +45,7 @@ #include #include #define HAVE_STDARG_H +#define dbglog cdrom_log #include "../../emu.h" #include "../../version.h" #include "../../timer.h" @@ -53,9 +54,10 @@ #include "../../ui/ui.h" #include "../../plat.h" #include "../system/intel_piix.h" -#include "../scsi/scsi.h" #include "../disk/hdc.h" #include "../disk/hdc_ide.h" +#include "../scsi/scsi_device.h" +#include "../sound/sound.h" #include "cdrom.h" #include "cdrom_image.h" #include "cdrom_null.h" @@ -64,8 +66,8 @@ /* Bits of 'status' */ #define ERR_STAT 0x01 #define DRQ_STAT 0x08 /* Data request */ -#define DSC_STAT 0x10 -#define SERVICE_STAT 0x10 +#define DSC_STAT 0x10 +#define SERVICE_STAT 0x10 #define READY_STAT 0x40 #define BUSY_STAT 0x80 @@ -73,3254 +75,3168 @@ #define ABRT_ERR 0x04 /* Command aborted */ #define MCR_ERR 0x08 /* Media change request */ +#define MIN_SEEK 2000 +#define MAX_SEEK 333333 + +#define cdbufferb dev->buffer + + cdrom_t *cdrom[CDROM_NUM]; cdrom_image_t cdrom_image[CDROM_NUM]; -#ifdef USE_CDROM_IOCTL -cdrom_ioctl_t cdrom_ioctl[CDROM_NUM]; -#endif cdrom_drive_t cdrom_drives[CDROM_NUM]; -uint8_t atapi_cdrom_drives[8] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; -uint8_t scsi_cdrom_drives[16][8] = { { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } }; - - -/* - * List of usable CD-ROM speeds (from Wikipedia): - * - * Speed KiB/s Mbit/s RPM - * 1× 150 1.2288 200–500 - * 2× 300 2.4576 400-1,000 - * 4× 600 4.9152 800–2,000 - * 6x ? ? ? - * 8× 1,200 9.8304 1,600–4,000 - * 10× 1,500 12.288 2,000–5,000 - * 12× 1,800 14.7456 2,400–6,000 - * 16x ? ? ? - * 20× 1,200–3,000 up to 24.576 4,000 (CAV) - * 24x ? ? ? - * 32× 1,920–4,800 up to 39.3216 6,400 (CAV) - * 36× 2,160–5,400 up to 44.2368 7,200 (CAV) - * 40× 2,400–6,000 up to 49.152 8,000 (CAV) - * 44x ? ? ? - * 48× 2,880–7,200 up to 58.9824 9,600 (CAV) - * 52× 3,120–7,800 up to 63.8976 10,400 (CAV) - * 56× 3,360–8,400 up to 68.8128 11,200 (CAV) - * 72× 6,750–10,800 up to 88.4736 2,000 (multi-beam) - * - * We discard the latter two ones. - */ -const cdrom_speed_t cdrom_speeds[] = { - { 1, 140.0, 1446.0 }, - { 2, 160.0, 1000.0 }, - { 4, 112.0, 675.0 }, - { 6, 112.0, 675.0 }, - { 8, 112.0, 675.0 }, - { 10, 112.0, 675.0 }, - { 12, 75.0, 400.0 }, - { 16, 58.0, 350.0 }, - { 20, 50.0, 300.0 }, - { 24, 45.0, 270.0 }, - { 32, 45.0, 270.0 }, - { 36, 50.0, 300.0 }, - { 40, 50.0, 300.0 }, - { 44, 50.0, 300.0 }, - { 48, 50.0, 300.0 }, - { 52, 45.0, 270.0 }, - { -1, 0.0, 0.0 }, +uint8_t atapi_cdrom_drives[8] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff +}; +uint8_t scsi_cdrom_drives[16][8] = { + { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, + { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, + { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, + { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, + { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, + { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, + { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, + { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, + { 0xfF, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, + { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, + { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, + { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, + { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, + { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, + { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, + { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff } }; #pragma pack(push,1) -typedef struct -{ - uint8_t opcode; - uint8_t polled; - uint8_t reserved2[2]; - uint8_t class; - uint8_t reserved3[2]; - uint16_t len; - uint8_t control; +typedef struct { + uint8_t opcode; + uint8_t polled; + uint8_t reserved2[2]; + uint8_t opc_class; + uint8_t reserved3[2]; + uint16_t len; + uint8_t control; } gesn_cdb_t; #pragma pack(pop) #pragma pack(push,1) -typedef struct -{ - uint16_t len; - uint8_t notification_class; - uint8_t supported_events; +typedef struct { + uint16_t len; + uint8_t notification_class; + uint8_t supported_events; } gesn_event_header_t; #pragma pack(pop) /* Table of all SCSI commands and their flags, needed for the new disc change / not ready handler. */ -const uint8_t cdrom_command_flags[0x100] = -{ - IMPLEMENTED | CHECK_READY | NONDATA, - IMPLEMENTED | ALLOW_UA | NONDATA | SCSI_ONLY, - 0, - IMPLEMENTED | ALLOW_UA, - 0, 0, 0, 0, - IMPLEMENTED | CHECK_READY, - 0, 0, - IMPLEMENTED | CHECK_READY | NONDATA, - 0, 0, 0, 0, 0, 0, - IMPLEMENTED | ALLOW_UA, - IMPLEMENTED | CHECK_READY | NONDATA | SCSI_ONLY, - 0, - IMPLEMENTED, - 0, 0, 0, 0, - IMPLEMENTED, - IMPLEMENTED | CHECK_READY, - 0, 0, - IMPLEMENTED | CHECK_READY, - 0, 0, 0, 0, 0, 0, - IMPLEMENTED | CHECK_READY, - 0, 0, - IMPLEMENTED | CHECK_READY, - 0, 0, - IMPLEMENTED | CHECK_READY | NONDATA, - 0, 0, 0, - IMPLEMENTED | CHECK_READY | NONDATA | SCSI_ONLY, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, - IMPLEMENTED | CHECK_READY, - IMPLEMENTED | CHECK_READY, /* Read TOC - can get through UNIT_ATTENTION, per VIDE-CDD.SYS - NOTE: The ATAPI reference says otherwise, but I think this is a question of - interpreting things right - the UNIT ATTENTION condition we have here - is a tradition from not ready to ready, by definition the drive - eventually becomes ready, make the condition go away. */ - IMPLEMENTED | CHECK_READY, - IMPLEMENTED | CHECK_READY, - IMPLEMENTED | ALLOW_UA, - IMPLEMENTED | CHECK_READY, - IMPLEMENTED | CHECK_READY, - 0, - IMPLEMENTED | ALLOW_UA, - IMPLEMENTED | CHECK_READY, - 0, 0, - IMPLEMENTED | CHECK_READY, - 0, 0, - IMPLEMENTED | CHECK_READY, - IMPLEMENTED | CHECK_READY, - 0, 0, - IMPLEMENTED, - 0, 0, 0, 0, - IMPLEMENTED, - 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, - IMPLEMENTED | CHECK_READY, - 0, 0, - IMPLEMENTED | CHECK_READY, - 0, 0, 0, 0, - IMPLEMENTED | CHECK_READY, - 0, - IMPLEMENTED | CHECK_READY | NONDATA | SCSI_ONLY, - 0, 0, 0, 0, - IMPLEMENTED | CHECK_READY | ATAPI_ONLY, - 0, 0, 0, - IMPLEMENTED | CHECK_READY | ATAPI_ONLY, - IMPLEMENTED | CHECK_READY, - IMPLEMENTED | CHECK_READY, - IMPLEMENTED, - IMPLEMENTED | CHECK_READY, - IMPLEMENTED, - IMPLEMENTED | CHECK_READY, - IMPLEMENTED | CHECK_READY, - 0, 0, - IMPLEMENTED | CHECK_READY | SCSI_ONLY, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - IMPLEMENTED | CHECK_READY | SCSI_ONLY, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - IMPLEMENTED | SCSI_ONLY, - 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +static const uint8_t cdrom_command_flags[0x100] = { + IMPLEMENTED | CHECK_READY | NONDATA, /* 0x00 */ + IMPLEMENTED | ALLOW_UA | NONDATA | SCSI_ONLY, /* 0x01 */ + 0, /* 0x02 */ + IMPLEMENTED | ALLOW_UA, /* 0x03 */ + 0, 0, 0, 0, /* 0x04-0x07 */ + IMPLEMENTED | CHECK_READY, /* 0x08 */ + 0, 0, /* 0x09-0x0A */ + IMPLEMENTED | CHECK_READY | NONDATA, /* 0x0B */ + 0, 0, 0, 0, 0, 0, /* 0x0C-0x11 */ + IMPLEMENTED | ALLOW_UA, /* 0x12 */ + IMPLEMENTED | CHECK_READY | NONDATA | SCSI_ONLY, /* 0x13 */ + 0, /* 0x14 */ + IMPLEMENTED, /* 0x15 */ + 0, 0, 0, 0, /* 0x16-0x19 */ + IMPLEMENTED, /* 0x1A */ + IMPLEMENTED | CHECK_READY, /* 0x1B */ + 0, 0, /* 0x1C-0x1D */ + IMPLEMENTED | CHECK_READY, /* 0x1E */ + 0, 0, 0, 0, 0, 0, /* 0x1F-0x24 */ + IMPLEMENTED | CHECK_READY, /* 0x25 */ + 0, 0, /* 0x26-0x27 */ + IMPLEMENTED | CHECK_READY, /* 0x28 */ + 0, 0, /* 0x29-0x2A */ + IMPLEMENTED | CHECK_READY | NONDATA, /* 0x2B */ + 0, 0, 0, /* 0x2C-0x2E */ + IMPLEMENTED | CHECK_READY | NONDATA | SCSI_ONLY, /* 0x2F */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x30-0x3F */ + 0, 0, /* 0x40-0x41 */ + IMPLEMENTED | CHECK_READY, /* 0x42 */ + IMPLEMENTED | CHECK_READY, /* 0x43 - Read TOC - can get through UNIT_ATTENTION, per VIDE-CDD.SYS + NOTE: The ATAPI reference says otherwise, but I think this is a question of + interpreting things right - the UNIT ATTENTION condition we have here + is a tradition from not ready to ready, by definition the drive + eventually becomes ready, make the condition go away. */ + IMPLEMENTED | CHECK_READY, /* 0x44 */ + IMPLEMENTED | CHECK_READY, /* 0x45 */ + IMPLEMENTED | ALLOW_UA, /* 0x46 */ + IMPLEMENTED | CHECK_READY, /* 0x47 */ + IMPLEMENTED | CHECK_READY, /* 0x48 */ + 0, /* 0x49 */ + IMPLEMENTED | ALLOW_UA, /* 0x4A */ + IMPLEMENTED | CHECK_READY, /* 0x4B */ + 0, 0, /* 0x4C-0x4D */ + IMPLEMENTED | CHECK_READY, /* 0x4E */ + 0, 0, /* 0x4F-0x50 */ + IMPLEMENTED | CHECK_READY, /* 0x51 */ + IMPLEMENTED | CHECK_READY, /* 0x52 */ + 0, 0, /* 0x53-0x54 */ + IMPLEMENTED, /* 0x55 */ + 0, 0, 0, 0, /* 0x56-0x59 */ + IMPLEMENTED, /* 0x5A */ + 0, 0, 0, 0, 0, /* 0x5B-0x5F */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x60-0x6F */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x70-0x7F */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x80-0x8F */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x90-0x9F */ + 0, 0, 0, 0, 0, /* 0xA0-0xA4 */ + IMPLEMENTED | CHECK_READY, /* 0xA5 */ + 0, 0, /* 0xA6-0xA7 */ + IMPLEMENTED | CHECK_READY, /* 0xA8 */ + 0, 0, 0, 0, /* 0xA9-0xAC */ + IMPLEMENTED | CHECK_READY, /* 0xAD */ + 0, /* 0xAE */ + IMPLEMENTED | CHECK_READY | NONDATA | SCSI_ONLY, /* 0xAF */ + 0, 0, 0, 0, /* 0xB0-0xB3 */ + IMPLEMENTED | CHECK_READY | ATAPI_ONLY, /* 0xB4 */ + 0, 0, 0, /* 0xB5-0xB7 */ + IMPLEMENTED | CHECK_READY | ATAPI_ONLY, /* 0xB8 */ + IMPLEMENTED | CHECK_READY, /* 0xB9 */ + IMPLEMENTED | CHECK_READY, /* 0xBA */ + IMPLEMENTED, /* 0xBB */ + IMPLEMENTED | CHECK_READY, /* 0xBC */ + IMPLEMENTED, /* 0xBD */ + IMPLEMENTED | CHECK_READY, /* 0xBE */ + IMPLEMENTED | CHECK_READY, /* 0xBF */ + 0, 0, /* 0xC0-0xC1 */ + IMPLEMENTED | CHECK_READY | SCSI_ONLY, /* 0xC2 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xC3-0xCC */ + IMPLEMENTED | CHECK_READY | SCSI_ONLY, /* 0xCD */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xCE-0xD9 */ + IMPLEMENTED | SCSI_ONLY, /* 0xDA */ + 0, 0, 0, 0, 0, /* 0xDB-0xDF */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xE0-0xEF */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* 0xF0-0xFF */ }; -uint64_t cdrom_mode_sense_page_flags = (1LL << GPMODE_R_W_ERROR_PAGE) | (1LL << GPMODE_CDROM_PAGE) | (1LL << GPMODE_CDROM_AUDIO_PAGE) | (1LL << GPMODE_CAPABILITIES_PAGE) | (1LL << GPMODE_ALL_PAGES); +static const uint64_t cdrom_mode_sense_page_flags = (GPMODEP_R_W_ERROR_PAGE | + GPMODEP_CDROM_PAGE | + GPMODEP_CDROM_AUDIO_PAGE | + GPMODEP_CAPABILITIES_PAGE | + GPMODEP_ALL_PAGES); -static const mode_sense_pages_t cdrom_mode_sense_pages_default = -{ { - { 0, 0 }, - { GPMODE_R_W_ERROR_PAGE, 6, 0, 5, 0, 0, 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { GPMODE_CDROM_PAGE, 6, 0, 1, 0, 60, 0, 75 }, - { 0x8E, 0xE, 4, 0, 0, 0, 0, 75, 1, 0xFF, 2, 0xFF, 0, 0, 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { GPMODE_CAPABILITIES_PAGE, 0x12, 0, 0, 1, 0, 0, 0, 0x02, 0xC2, 1, 0, 0, 0, 0x02, 0xC2, 0, 0, 0, 0 } -} }; +static const mode_sense_pages_t cdrom_mode_sense_pages_default = { + { + { 0, 0 }, + { GPMODE_R_W_ERROR_PAGE, 6, 0, 5, 0, 0, 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { GPMODE_CDROM_PAGE, 6, 0, 1, 0, 60, 0, 75 }, + { 0x8E, 0xE, 4, 0, 0, 0, 0, 75, 1, 255, 2, 255, 0, 0, 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { GPMODE_CAPABILITIES_PAGE, 0x12, 0, 0, 1, 0, 0, 0, 2, 0xC2, 1, 0, 0, 0, 2, 0xC2, 0, 0, 0, 0 } +} }; static const mode_sense_pages_t cdrom_mode_sense_pages_default_scsi = -{ { - { 0, 0 }, - { GPMODE_R_W_ERROR_PAGE, 6, 0, 5, 0, 0, 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { GPMODE_CDROM_PAGE, 6, 0, 1, 0, 60, 0, 75 }, - { 0x8E, 0xE, 5, 4, 0,0x80,0, 75, 1, 0xFF, 2, 0xFF, 0, 0, 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { GPMODE_CAPABILITIES_PAGE, 0x12, 0, 0, 1, 0, 0, 0, 0x02, 0xC2, 1, 0, 0, 0, 0x02, 0xC2, 0, 0, 0, 0 } -} }; +{ { + { 0, 0 }, + { GPMODE_R_W_ERROR_PAGE, 6, 0, 5, 0, 0, 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { GPMODE_CDROM_PAGE, 6, 0, 1, 0, 60, 0, 75 }, + { 0x8E, 0xE, 5, 4, 0,128, 0, 75, 1, 255, 2, 255, 0, 0, 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { GPMODE_CAPABILITIES_PAGE, 0x12, 0, 0, 1, 0, 0, 0, 2, 0xC2, 1, 0, 0, 0, 2, 0xC2, 0, 0, 0, 0 } +} }; static const mode_sense_pages_t cdrom_mode_sense_pages_changeable = -{ { - { 0, 0 }, - { GPMODE_R_W_ERROR_PAGE, 6, 0, 5, 0, 0, 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { GPMODE_CDROM_PAGE, 6, 0, 1, 0, 60, 0, 75 }, - { 0x8E, 0xE, 5, 4, 0,0x80,0, 75, 1, 0xFF, 2, 0xFF, 0, 0, 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { GPMODE_CAPABILITIES_PAGE, 0x12, 0, 0, 1, 0, 0, 0, 0x02, 0xC2, 1, 0, 0, 0, 0x02, 0xC2, 0, 0, 0, 0 } -} }; +{ { + { 0, 0 }, + { GPMODE_R_W_ERROR_PAGE, 6, 0, 5, 0, 0, 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { GPMODE_CDROM_PAGE, 6, 0, 1, 0, 60, 0, 75 }, + { 0x8E, 0xE, 5, 4, 0,128, 0, 75, 1, 255, 2, 255, 0, 0, 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { GPMODE_CAPABILITIES_PAGE, 0x12, 0, 0, 1, 0, 0, 0, 2, 0xC2, 1, 0, 0, 0, 2, 0xC2, 0, 0, 0, 0 } +} }; -static mode_sense_pages_t cdrom_mode_sense_pages_saved[CDROM_NUM]; +uint8_t cdrom_read_capacity_cdb[12] = {0x25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; static gesn_cdb_t *gesn_cdb; static gesn_event_header_t *gesn_event_header; +static void cdrom_command_complete(cdrom_t *dev); + +static void cdrom_mode_sense_load(cdrom_t *dev); + +static void cdrom_init(cdrom_t *dev); +void cdrom_phase_callback(cdrom_t *dev); + + #ifdef ENABLE_CDROM_LOG -int cdrom_do_log = ENABLE_CDROM_LOG; +int cdrom_do_log = ENABLE_CDROM_LOG; #endif -static void -cdrom_log(const char *format, ...) +void +cdrom_log(int level, const char *fmt, ...) { #ifdef ENABLE_CDROM_LOG - va_list ap; + va_list ap; - if (cdrom_do_log) - { - va_start(ap, format); - pclog_ex(format, ap); - va_end(ap); - } + if (cdrom_do_log >= level) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } #endif } int -cdrom_speed_idx(int realspeed) +find_cdrom_for_channel(uint8_t channel) { - int idx; + uint8_t i = 0; - for (idx = 0; cdrom_speeds[idx].speed > 0; idx++) - if (cdrom_speeds[idx].speed == realspeed) - return(idx); - - return(-1); + for (i = 0; i < CDROM_NUM; i++) { + if ((cdrom_drives[i].bus_type == CDROM_BUS_ATAPI) && (cdrom_drives[i].ide_channel == channel)) + return i; + } + return 0xff; } -int find_cdrom_for_channel(uint8_t channel) +void +build_atapi_cdrom_map(void) { - uint8_t i = 0; + uint8_t i = 0; - for (i = 0; i < CDROM_NUM; i++) { - if (((cdrom_drives[i].bus_type == CDROM_BUS_ATAPI_PIO_ONLY) || (cdrom_drives[i].bus_type == CDROM_BUS_ATAPI_PIO_AND_DMA)) && (cdrom_drives[i].ide_channel == channel)) - return i; - } - return 0xff; + memset(atapi_cdrom_drives, 0xff, 8); + + for (i = 0; i < 8; i++) + atapi_cdrom_drives[i] = find_cdrom_for_channel(i); } -void cdrom_init(int id, int cdb_len_setting); -void build_atapi_cdrom_map(void) +int +find_cdrom_for_scsi_id(uint8_t scsi_id, uint8_t scsi_lun) { - uint8_t i = 0; + uint8_t i = 0; - memset(atapi_cdrom_drives, 0xff, 8); - - for (i = 0; i < 8; i++) { - atapi_cdrom_drives[i] = find_cdrom_for_channel(i); - if (atapi_cdrom_drives[i] != 0xff) - cdrom_init(atapi_cdrom_drives[i], 12); - } + for (i = 0; i < CDROM_NUM; i++) { + if ((cdrom_drives[i].bus_type == CDROM_BUS_SCSI) && (cdrom_drives[i].scsi_device_id == scsi_id) && (cdrom_drives[i].scsi_device_lun == scsi_lun)) + return i; + } + return 0xff; } -int find_cdrom_for_scsi_id(uint8_t scsi_id, uint8_t scsi_lun) -{ - uint8_t i = 0; - for (i = 0; i < CDROM_NUM; i++) { - if ((cdrom_drives[i].bus_type == CDROM_BUS_SCSI) && (cdrom_drives[i].scsi_device_id == scsi_id) && (cdrom_drives[i].scsi_device_lun == scsi_lun)) - return i; - } - return 0xff; +void +build_scsi_cdrom_map(void) +{ + uint8_t i = 0; + uint8_t j = 0; + + for (i = 0; i < 16; i++) + memset(scsi_cdrom_drives[i], 0xff, 8); + + for (i = 0; i < 16; i++) { + for (j = 0; j < 8; j++) + scsi_cdrom_drives[i][j] = find_cdrom_for_scsi_id(i, j); + } } -void build_scsi_cdrom_map(void) + +static void +cdrom_set_callback(cdrom_t *dev) { - uint8_t i = 0; - uint8_t j = 0; - - for (i = 0; i < 16; i++) - memset(scsi_cdrom_drives[i], 0xff, 8); - - for (i = 0; i < 16; i++) { - for (j = 0; j < 8; j++) { - scsi_cdrom_drives[i][j] = find_cdrom_for_scsi_id(i, j); - if (scsi_cdrom_drives[i][j] != 0xff) - cdrom_init(scsi_cdrom_drives[i][j], 12); - } - } + if (dev && dev->drv && (dev->drv->bus_type != CDROM_BUS_SCSI)) + ide_set_callback(dev->drv->ide_channel >> 1, dev->callback); } -void cdrom_set_callback(uint8_t id) + +void +cdrom_set_signature(cdrom_t *dev) { - if (cdrom_drives[id].bus_type != CDROM_BUS_SCSI) - ide_set_callback(cdrom_drives[id].ide_channel, cdrom[id]->callback); + if (!dev) + return; + dev->phase = 1; + dev->request_length = 0xEB14; } -void cdrom_set_cdb_len(int id, int cdb_len) + +static void +cdrom_init(cdrom_t *dev) { - cdrom[id]->cdb_len = cdb_len; + if (!dev) + return; + + /* Tell the cdrom_t struct what cdrom_drives element corresponds to it. */ + dev->drv = &(cdrom_drives[dev->id]); + + /* Do a reset (which will also rezero it). */ + cdrom_reset(dev); + + /* Configure the drive. */ + dev->requested_blocks = 1; + + dev->drv->bus_mode = 0; + if (dev->drv->bus_type >= CDROM_BUS_ATAPI) + dev->drv->bus_mode |= 2; + if (dev->drv->bus_type < CDROM_BUS_SCSI) + dev->drv->bus_mode |= 1; + DEBUG("CD-ROM %i: Bus type %i, bus mode %i\n", dev->id, dev->drv->bus_type, dev->drv->bus_mode); + dev->cdb_len = 12; + + dev->sense[0] = 0xf0; + dev->sense[7] = 10; + dev->status = READY_STAT | DSC_STAT; + dev->pos = 0; + dev->packet_status = 0xff; + cdrom_sense_key = cdrom_asc = cdrom_ascq = dev->unit_attention = 0; + dev->cur_speed = dev->drv->speed_idx; + cdrom_mode_sense_load(dev); } -void cdrom_reset_cdb_len(int id) + +static int +cdrom_supports_pio(cdrom_t *dev) { - cdrom[id]->cdb_len = cdrom[id]->cdb_len_setting ? 16 : 12; + return (dev->drv->bus_mode & 1); } -void cdrom_set_signature(int id) -{ - cdrom_t *dev; - if (id >= CDROM_NUM) - return; - dev = cdrom[id]; - dev->phase = 1; - dev->request_length = 0xEB14; +static int +cdrom_supports_dma(cdrom_t *dev) +{ + return (dev->drv->bus_mode & 2); } -void cdrom_destroy_drives(void) -{ - int i; - - for (i = 0; i < CDROM_NUM; i++) { - if (cdrom[i] != NULL) { - free(cdrom[i]); - cdrom[i] = NULL; - } - } -} - -void cdrom_init(int id, int cdb_len_setting) -{ - cdrom_t *dev; - uint8_t *trcbuf; - uint32_t tcap; - - if (id >= CDROM_NUM) - return; - dev = cdrom[id]; - tcap = dev->cdrom_capacity; - trcbuf = (uint8_t *) malloc(16); - memcpy(trcbuf, dev->rcbuf, 16); - memset(dev, 0x00, sizeof(cdrom_t)); - memcpy(dev->rcbuf, trcbuf, 16); - free(trcbuf); - dev->cdrom_capacity = tcap; - dev->requested_blocks = 1; - if (cdb_len_setting <= 1) - dev->cdb_len_setting = cdb_len_setting; - cdrom_reset_cdb_len(id); - dev->cd_status = CD_STATUS_EMPTY; - dev->sense[0] = 0xf0; - dev->sense[7] = 10; - cdrom_drives[id].bus_mode = 0; - if (cdrom_drives[id].bus_type >= CDROM_BUS_ATAPI_PIO_AND_DMA) - cdrom_drives[id].bus_mode |= 2; - if (cdrom_drives[id].bus_type < CDROM_BUS_SCSI) - cdrom_drives[id].bus_mode |= 1; - cdrom_log("CD-ROM %i: Bus type %i, bus mode %i\n", id, cdrom_drives[id].bus_type, cdrom_drives[id].bus_mode); - if (cdrom_drives[id].bus_type < CDROM_BUS_SCSI) - cdrom_set_signature(id); - dev->status = READY_STAT | DSC_STAT; - dev->pos = 0; - dev->packet_status = 0xff; - cdrom_sense_key = cdrom_asc = cdrom_ascq = dev->unit_attention = 0; - dev->cdb_len_setting = 0; - dev->cdb_len = 12; - dev->cur_speed = cdrom_drives[id].speed_idx; -} - -int cdrom_supports_pio(int id) -{ - return (cdrom_drives[id].bus_mode & 1); -} - -int cdrom_supports_dma(int id) -{ - return (cdrom_drives[id].bus_mode & 2); -} /* Returns: 0 for none, 1 for PIO, 2 for DMA. */ -int cdrom_current_mode(int id) +static int +cdrom_current_mode(cdrom_t *dev) { - cdrom_t *dev = cdrom[id]; - - if (!cdrom_supports_pio(id) && !cdrom_supports_dma(id)) - return 0; - if (cdrom_supports_pio(id) && !cdrom_supports_dma(id)) { - cdrom_log("CD-ROM %i: Drive does not support DMA, setting to PIO\n", id); - return 1; - } - if (!cdrom_supports_pio(id) && cdrom_supports_dma(id)) - return 2; - if (cdrom_supports_pio(id) && cdrom_supports_dma(id)) { - cdrom_log("CD-ROM %i: Drive supports both, setting to %s\n", id, (dev->features & 1) ? "DMA" : "PIO", id); - return (dev->features & 1) ? 2 : 1; - } - + if (!cdrom_supports_pio(dev) && !cdrom_supports_dma(dev)) return 0; + if (cdrom_supports_pio(dev) && !cdrom_supports_dma(dev)) { + DEBUG("CD-ROM %i: Drive does not support DMA, setting to PIO\n", dev->id); + return 1; + } + if (!cdrom_supports_pio(dev) && cdrom_supports_dma(dev)) + return 2; + if (cdrom_supports_pio(dev) && cdrom_supports_dma(dev)) { + DEBUG("CD-ROM %i: Drive supports both, setting to %s\n", dev->id, + (dev->features & 1) ? "DMA" : "PIO", + dev->id); + return (dev->features & 1) ? 2 : 1; + } + + return 0; } + /* Translates ATAPI status (ERR_STAT flag) to SCSI status. */ -int cdrom_CDROM_PHASE_to_scsi(uint8_t id) +int +cdrom_CDROM_PHASE_to_scsi(cdrom_t *dev) { - cdrom_t *dev = cdrom[id]; - - if (dev->status & ERR_STAT) - return SCSI_STATUS_CHECK_CONDITION; - else - return SCSI_STATUS_OK; + if (dev->status & ERR_STAT) + return SCSI_STATUS_CHECK_CONDITION; + else + return SCSI_STATUS_OK; } + /* Translates ATAPI phase (DRQ, I/O, C/D) to SCSI phase (MSG, C/D, I/O). */ -int cdrom_atapi_phase_to_scsi(uint8_t id) +int +cdrom_atapi_phase_to_scsi(cdrom_t *dev) { - cdrom_t *dev = cdrom[id]; - - if (dev->status & 8) { - switch (dev->phase & 3) { - case 0: - return 0; - case 1: - return 2; - case 2: - return 1; - case 3: - return 7; - } - } else { - if ((dev->phase & 3) == 3) - return 3; - else - return 4; - } - - return 0; -} - -int cdrom_lba_to_msf_accurate(int lba) -{ - int temp_pos; - int m, s, f; - - temp_pos = lba + 150; - f = temp_pos % 75; - temp_pos -= f; - temp_pos /= 75; - s = temp_pos % 60; - temp_pos -= s; - temp_pos /= 60; - m = temp_pos; - - return ((m << 16) | (s << 8) | f); -} - -uint32_t cdrom_mode_sense_get_channel(uint8_t id, int channel) -{ - return cdrom_mode_sense_pages_saved[id].pages[GPMODE_CDROM_AUDIO_PAGE][channel ? 10 : 8]; -} - -uint32_t cdrom_mode_sense_get_volume(uint8_t id, int channel) -{ - return cdrom_mode_sense_pages_saved[id].pages[GPMODE_CDROM_AUDIO_PAGE][channel ? 11 : 9]; -} - -void cdrom_mode_sense_load(uint8_t id) -{ - FILE *f; - wchar_t file_name[512]; - int i; - memset(&cdrom_mode_sense_pages_saved[id], 0, sizeof(mode_sense_pages_t)); - for (i = 0; i < 0x3f; i++) { - if (cdrom_mode_sense_pages_default.pages[i][1] != 0) { - if (cdrom_drives[id].bus_type == CDROM_BUS_SCSI) - memcpy(cdrom_mode_sense_pages_saved[id].pages[i], cdrom_mode_sense_pages_default_scsi.pages[i], cdrom_mode_sense_pages_default_scsi.pages[i][1] + 2); - else - memcpy(cdrom_mode_sense_pages_saved[id].pages[i], cdrom_mode_sense_pages_default.pages[i], cdrom_mode_sense_pages_default.pages[i][1] + 2); - } - } - memset(file_name, 0, 512 * sizeof(wchar_t)); - if (cdrom_drives[id].bus_type == CDROM_BUS_SCSI) - swprintf(file_name, 512, L"scsi_cdrom_%02i_mode_sense_bin", id); - else - swprintf(file_name, 512, L"cdrom_%02i_mode_sense_bin", id); - f = plat_fopen(nvr_path(file_name), L"rb"); - if (f) { - fread(cdrom_mode_sense_pages_saved[id].pages[GPMODE_CDROM_AUDIO_PAGE], 1, 0x10, f); - fclose(f); - } -} - -void cdrom_mode_sense_save(uint8_t id) -{ - FILE *f; - wchar_t file_name[512]; - memset(file_name, 0, 512 * sizeof(wchar_t)); - if (cdrom_drives[id].bus_type == CDROM_BUS_SCSI) - swprintf(file_name, 512, L"scsi_cdrom_%02i_mode_sense_bin", id); - else - swprintf(file_name, 512, L"cdrom_%02i_mode_sense_bin", id); - f = plat_fopen(nvr_path(file_name), L"wb"); - if (f) { - fwrite(cdrom_mode_sense_pages_saved[id].pages[GPMODE_CDROM_AUDIO_PAGE], 1, 0x10, f); - fclose(f); - } -} - -static void cdrom_command_complete(uint8_t id); - -uint8_t cdrom_read_capacity_cdb[12] = {0x25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - -static int cdrom_pass_through(uint8_t id, uint32_t *len, uint8_t *cdb, uint8_t *buffer); - -int cdrom_read_capacity(uint8_t id, uint8_t *cdb, uint8_t *buffer, uint32_t *len) -{ - int ret = 0; - int size = 0; - - if (cdrom_drives[id].handler->pass_through) { - ret = cdrom_pass_through(id, len, cdb, buffer); - if (!ret) + if (dev->status & 8) { + switch (dev->phase & 3) { + case 0: return 0; - if (*len == 65534) - *len = 8; - } else { - size = cdrom_drives[id].handler->size(id) - 1; /* IMPORTANT: What's returned is the last LBA block. */ - memset(buffer, 0, 8); - buffer[0] = (size >> 24) & 0xff; - buffer[1] = (size >> 16) & 0xff; - buffer[2] = (size >> 8) & 0xff; - buffer[3] = size & 0xff; - buffer[6] = 8; /* 2048 = 0x0800 */ - *len = 8; + case 1: + return 2; + case 2: + return 1; + case 3: + return 7; } - return 1; + } else { + if ((dev->phase & 3) == 3) + return 3; + else + return 4; + } + + return 0; } + +int +cdrom_lba_to_msf_accurate(int lba) +{ + int temp_pos; + int m, s, f; + + temp_pos = lba + 150; + f = temp_pos % 75; + temp_pos -= f; + temp_pos /= 75; + s = temp_pos % 60; + temp_pos -= s; + temp_pos /= 60; + m = temp_pos; + + return ((m << 16) | (s << 8) | f); +} + + +uint32_t +cdrom_mode_sense_get_channel(cdrom_t *dev, int channel) +{ + return dev->ms_pages_saved.pages[GPMODE_CDROM_AUDIO_PAGE][channel ? 10 : 8]; +} + + +uint32_t +cdrom_mode_sense_get_volume(cdrom_t *dev, int channel) +{ + return dev->ms_pages_saved.pages[GPMODE_CDROM_AUDIO_PAGE][channel ? 11 : 9]; +} + + +static void +cdrom_mode_sense_load(cdrom_t *dev) +{ + FILE *f; + wchar_t file_name[512]; + int i; + + memset(&dev->ms_pages_saved, 0, sizeof(mode_sense_pages_t)); + for (i = 0; i < 0x3f; i++) { + if (cdrom_mode_sense_pages_default.pages[i][1] != 0) { + if (dev->drv->bus_type == CDROM_BUS_SCSI) + memcpy(dev->ms_pages_saved.pages[i], + cdrom_mode_sense_pages_default_scsi.pages[i], + cdrom_mode_sense_pages_default_scsi.pages[i][1] + 2); + else + memcpy(dev->ms_pages_saved.pages[i], + cdrom_mode_sense_pages_default.pages[i], + cdrom_mode_sense_pages_default.pages[i][1] + 2); + } + } + memset(file_name, 0, 512 * sizeof(wchar_t)); + if (dev->drv->bus_type == CDROM_BUS_SCSI) + swprintf(file_name, 512, L"scsi_cdrom_%02i_mode_sense_bin", dev->id); + else + swprintf(file_name, 512, L"cdrom_%02i_mode_sense_bin", dev->id); + f = plat_fopen(nvr_path(file_name), L"rb"); + if (f) { + fread(dev->ms_pages_saved.pages[GPMODE_CDROM_AUDIO_PAGE], 1, 0x10, f); + fclose(f); + } +} + + +static void +cdrom_mode_sense_save(cdrom_t *dev) +{ + FILE *f; + wchar_t file_name[512]; + + memset(file_name, 0, 512 * sizeof(wchar_t)); + if (dev->drv->bus_type == CDROM_BUS_SCSI) + swprintf(file_name, 512, L"scsi_cdrom_%02i_mode_sense_bin", dev->id); + else + swprintf(file_name, 512, L"cdrom_%02i_mode_sense_bin", dev->id); + f = plat_fopen(nvr_path(file_name), L"wb"); + if (f) { + fwrite(dev->ms_pages_saved.pages[GPMODE_CDROM_AUDIO_PAGE], 1, 0x10, f); + fclose(f); + } +} + + +int +cdrom_read_capacity(cdrom_t *dev, uint8_t *cdb, uint8_t *buffer, uint32_t *len) +{ + int size = 0; + + size = dev->handler->size(dev->id) - 1; /* IMPORTANT: What's returned is the last LBA block. */ + memset(buffer, 0, 8); + buffer[0] = (size >> 24) & 0xff; + buffer[1] = (size >> 16) & 0xff; + buffer[2] = (size >> 8) & 0xff; + buffer[3] = size & 0xff; + buffer[6] = 8; /* 2048 = 0x0800 */ + *len = 8; + + return 1; +} + + /*SCSI Mode Sense 6/10*/ -uint8_t cdrom_mode_sense_read(uint8_t id, uint8_t page_control, uint8_t page, uint8_t pos) +static uint8_t +cdrom_mode_sense_read(cdrom_t *dev, uint8_t page_control, uint8_t page, uint8_t pos) { - switch (page_control) { - case 0: - case 3: - return cdrom_mode_sense_pages_saved[id].pages[page][pos]; - break; - case 1: - return cdrom_mode_sense_pages_changeable.pages[page][pos]; - break; - case 2: - if (cdrom_drives[id].bus_type == CDROM_BUS_SCSI) - return cdrom_mode_sense_pages_default_scsi.pages[page][pos]; - else - return cdrom_mode_sense_pages_default.pages[page][pos]; - break; - } + switch (page_control) { + case 0: + case 3: + return dev->ms_pages_saved.pages[page][pos]; + break; + case 1: + return cdrom_mode_sense_pages_changeable.pages[page][pos]; + break; + case 2: + if (dev->drv->bus_type == CDROM_BUS_SCSI) + return cdrom_mode_sense_pages_default_scsi.pages[page][pos]; + else + return cdrom_mode_sense_pages_default.pages[page][pos]; + break; + } - return 0; + return 0; } -uint32_t cdrom_mode_sense(uint8_t id, uint8_t *buf, uint32_t pos, uint8_t type, uint8_t block_descriptor_len) + +static uint32_t +cdrom_mode_sense(cdrom_t *dev, uint8_t *buf, uint32_t pos, uint8_t type, uint8_t block_descriptor_len) { - cdrom_t *dev = cdrom[id]; - uint8_t page_control = (type >> 6) & 3; + uint8_t page_control = (type >> 6) & 3; + int i = 0, j = 0; - int i = 0; - int j = 0; + uint8_t msplen; - uint8_t msplen; + type &= 0x3f; - type &= 0x3f; + if (block_descriptor_len) { + buf[pos++] = 1; /* Density code. */ + buf[pos++] = 0; /* Number of blocks (0 = all). */ + buf[pos++] = 0; + buf[pos++] = 0; + buf[pos++] = 0; /* Reserved. */ + buf[pos++] = 0; /* Block length (0x800 = 2048 bytes). */ + buf[pos++] = 8; + buf[pos++] = 0; + } - if (block_descriptor_len) { - buf[pos++] = 1; /* Density code. */ - buf[pos++] = 0; /* Number of blocks (0 = all). */ - buf[pos++] = 0; - buf[pos++] = 0; - buf[pos++] = 0; /* Reserved. */ - buf[pos++] = 0; /* Block length (0x800 = 2048 bytes). */ - buf[pos++] = 8; - buf[pos++] = 0; - } - - for (i = 0; i < 0x40; i++) { - if ((type == GPMODE_ALL_PAGES) || (type == i)) { - if (cdrom_mode_sense_page_flags & (1LL << dev->current_page_code)) { - buf[pos++] = cdrom_mode_sense_read(id, page_control, i, 0); - msplen = cdrom_mode_sense_read(id, page_control, i, 1); - buf[pos++] = msplen; - cdrom_log("CD-ROM %i: MODE SENSE: Page [%02X] length %i\n", id, i, msplen); - for (j = 0; j < msplen; j++) { - if ((i == GPMODE_CAPABILITIES_PAGE) && (j >= 6) && (j <= 7)) { - if (j & 1) - buf[pos++] = ((cdrom_speeds[cdrom_drives[id].speed_idx].speed * 176) & 0xff); - else - buf[pos++] = ((cdrom_speeds[cdrom_drives[id].speed_idx].speed * 176) >> 8); - } else if ((i == GPMODE_CAPABILITIES_PAGE) && (j >= 12) && (j <= 13)) { - if (j & 1) - buf[pos++] = ((cdrom_speeds[dev->cur_speed].speed * 176) & 0xff); - else - buf[pos++] = ((cdrom_speeds[dev->cur_speed].speed * 176) >> 8); - } else - buf[pos++] = cdrom_mode_sense_read(id, page_control, i, 2 + j); - } + for (i = 0; i < 0x40; i++) { + if ((type == GPMODE_ALL_PAGES) || (type == i)) { + if (cdrom_mode_sense_page_flags & (1LL << dev->current_page_code)) { + buf[pos++] = cdrom_mode_sense_read(dev, page_control, i, 0); + msplen = cdrom_mode_sense_read(dev, page_control, i, 1); + buf[pos++] = msplen; + DEBUG("CD-ROM %i: MODE SENSE: Page [%02X] length %i\n", dev->id, i, msplen); + for (j = 0; j < msplen; j++) { + if ((i == GPMODE_CAPABILITIES_PAGE) && (j >= 6) && (j <= 7)) { + if (j & 1) + buf[pos++] = ((cdrom_speeds[dev->drv->speed_idx].speed * 176) & 0xff); + else + buf[pos++] = ((cdrom_speeds[dev->drv->speed_idx].speed * 176) >> 8); + } else if ((i == GPMODE_CAPABILITIES_PAGE) && (j >= 12) && (j <= 13)) { + if (j & 1) + buf[pos++] = ((cdrom_speeds[dev->cur_speed].speed * 176) & 0xff); + else + buf[pos++] = ((cdrom_speeds[dev->cur_speed].speed * 176) >> 8); + } else + buf[pos++] = cdrom_mode_sense_read(dev, page_control, i, 2 + j); } } } + } - return pos; + return pos; } -void cdrom_update_request_length(uint8_t id, uint32_t len, uint32_t block_len) + +static void +cdrom_update_request_length(cdrom_t *dev, int len, int block_len) { - cdrom_t *dev = cdrom[id]; - uint32_t min_len = 0; - uint32_t bt; + int32_t bt, min_len = 0; - dev->max_transfer_len = dev->request_length; + dev->max_transfer_len = dev->request_length; - /* For media access commands, make sure the requested DRQ length matches the block length. */ - switch (dev->current_cdb[0]) { + /* For media access commands, make sure the requested DRQ length matches the block length. */ + switch (dev->current_cdb[0]) { + case 0x08: + case 0x28: + case 0xa8: + case 0xb9: + case 0xbe: + /* Make sure total length is not bigger than sum of the lengths of + all the requested blocks. */ + bt = (dev->requested_blocks * block_len); + if (len > bt) + len = bt; + + min_len = block_len; + + if (len <= block_len) { + /* Total length is less or equal to block length. */ + if (dev->max_transfer_len < block_len) { + /* Transfer a minimum of (block size) bytes. */ + dev->max_transfer_len = block_len; + dev->packet_len = block_len; + break; + } + } + default: + dev->packet_len = len; + break; + } + + /* If the DRQ length is odd, and the total remaining length is bigger, make sure it's even. */ + if ((dev->max_transfer_len & 1) && (dev->max_transfer_len < len)) + dev->max_transfer_len &= 0xfffe; + /* If the DRQ length is smaller or equal in size to the total remaining length, set it to that. */ + if (!dev->max_transfer_len) + dev->max_transfer_len = 65534; + + if ((len <= dev->max_transfer_len) && (len >= min_len)) + dev->request_length = dev->max_transfer_len = len; + else if (len > dev->max_transfer_len) + dev->request_length = dev->max_transfer_len; + + return; +} + + +#if 0 +static double +cdrom_get_short_seek(cdrom_t *dev) +{ + switch(dev->cur_speed) { + case 0: + fatal("CD-ROM %i: 0x speed\n", dev->id); + return 0.0; + case 1: + return 240.0; + case 2: + return 160.0; + case 3: + return 150.0; + case 4: case 5: case 6: case 7: case 8: + case 9: case 10: case 11: + return 112.0; + case 12: case 13: case 14: case 15: + return 75.0; + case 16: case 17: case 18: case 19: + return 58.0; + case 20: case 21: case 22: case 23: + case 40: case 41: case 42: case 43: + case 44: case 45: case 46: case 47: + case 48: + return 50.0; + default: + /* 24-32, 52+ */ + return 45.0; + } +} + + +static double +cdrom_get_long_seek(cdrom_t *dev) +{ + switch(dev->cur_speed) { + case 0: + fatal("CD-ROM %i: 0x speed\n", dev->id); + return 0.0; + case 1: + return 1446.0; + case 2: + return 1000.0; + case 3: + return 900.0; + case 4: case 5: case 6: case 7: case 8: + case 9: case 10: case 11: + return 675.0; + case 12: case 13: case 14: case 15: + return 400.0; + case 16: case 17: case 18: case 19: + return 350.0; + case 20: case 21: case 22: case 23: + case 40: case 41: case 42: case 43: + case 44: case 45: case 46: case 47: + case 48: + return 300.0; + default: + /* 24-32, 52+ */ + return 270.0; + } +} +#endif + + +static double +cdrom_seek_time(cdrom_t *dev) +{ + uint32_t diff = dev->seek_diff; + double sd = (double) (MAX_SEEK - MIN_SEEK); + + if (diff < MIN_SEEK) + return 0.0; + if (diff > MAX_SEEK) + diff = MAX_SEEK; + + diff -= MIN_SEEK; + +#if 1 + return cdrom_speeds[dev->cur_speed].seek1 + + ((cdrom_speeds[dev->cur_speed].seek2 * ((double) diff)) / sd); +#else + return cdrom_get_short_seek(dev) + ((cdrom_get_long_seek(dev) * ((double) diff)) / sd); +#endif +} + + +static double +cdrom_bus_speed(cdrom_t *dev) +{ + if (dev->drv->bus_type == CDROM_BUS_SCSI) { + dev->callback = -1LL; /* Speed depends on SCSI controller */ + return 0.0; + } else { + if (cdrom_current_mode(dev) == 2) + return 66666666.666666666666666; /* 66 MB/s MDMA-2 speed */ + else + return 8333333.333333333333333; /* 8.3 MB/s PIO-2 speed */ + } +} + + +static void +cdrom_command_bus(cdrom_t *dev) +{ + dev->status = BUSY_STAT; + dev->phase = 1; + dev->pos = 0; + dev->callback = 1LL * CDROM_TIME; + cdrom_set_callback(dev); +} + + +static void +cdrom_command_common(cdrom_t *dev) +{ + double bytes_per_second, period; + double dusec; + + dev->status = BUSY_STAT; + dev->phase = 1; + dev->pos = 0; + dev->callback = 0LL; + + DEBUG("CD-ROM %i: Current speed: %ix\n", + dev->id, cdrom_speeds[dev->cur_speed].speed); + + if (dev->packet_status == CDROM_PHASE_COMPLETE) { + cdrom_phase_callback(dev); + dev->callback = 0LL; + } else { + switch(dev->current_cdb[0]) { + case GPCMD_REZERO_UNIT: + case 0x0b: + case 0x2b: + /* Seek time is in us. */ + period = cdrom_seek_time(dev); + DEBUG("CD-ROM %i: Seek period: %" PRIu64 " us\n", + dev->id, (int64_t) period); + period = period * ((double) TIMER_USEC); + dev->callback += ((int64_t) period); + cdrom_set_callback(dev); + return; case 0x08: case 0x28: case 0xa8: + /* Seek time is in us. */ + period = cdrom_seek_time(dev); + DEBUG("CD-ROM %i: Seek period: %" PRIu64 " us\n", + dev->id, (int64_t) period); + period = period * ((double) TIMER_USEC); + dev->callback += ((int64_t) period); + /*FALLTHROUGH*/ + case 0x25: + case 0x42: + case 0x43: + case 0x44: + case 0x51: + case 0x52: + case 0xad: + case 0xb8: case 0xb9: case 0xbe: - /* Make sure total length is not bigger than sum - * of the lengths of all the requested blocks. */ - bt = (dev->requested_blocks * block_len); - if (len > bt) - len = bt; - - min_len = block_len; - - if (len <= block_len) { - /* Total length is less or equal to block length. */ - if (dev->max_transfer_len < block_len) { - /* Transfer a minimum of (block size) bytes. */ - dev->max_transfer_len = block_len; - dev->packet_len = block_len; - break; - } - } - + if (dev->current_cdb[0] == 0x42) + dev->callback += 200LL * CDROM_TIME; + /* Account for seek time. */ + bytes_per_second = 176.0 * 1024.0; + bytes_per_second *= (double) cdrom_speeds[dev->cur_speed].speed; + break; default: - dev->packet_len = len; + bytes_per_second = cdrom_bus_speed(dev); + if (bytes_per_second == 0.0) { + dev->callback = -1LL; /* Speed depends on SCSI controller */ + return; + } break; } - /* If the DRQ length is odd, and the total remaining length is bigger, make sure it's even. */ - if ((dev->max_transfer_len & 1) && (dev->max_transfer_len < len)) - dev->max_transfer_len &= 0xfffe; - /* If the DRQ length is smaller or equal in size to the total remaining length, set it to that. */ - if (!dev->max_transfer_len) - dev->max_transfer_len = 65534; - if ((len <= dev->max_transfer_len) && (len >= min_len)) { - dev->request_length = dev->max_transfer_len = len; - } + period = 1000000.0 / bytes_per_second; + DEBUG("CD-ROM %i: Byte transfer period: %" PRIu64 " us\n", dev->id, (int64_t) period); + period = period * (double) (dev->packet_len); + DEBUG("CD-ROM %i: Sector transfer period: %" PRIu64 " us\n", dev->id, (int64_t) period); + dusec = period * ((double) TIMER_USEC); + dev->callback += ((int64_t) dusec); + } + cdrom_set_callback(dev); } -#define MIN_SEEK 2000 -#define MAX_SEEK 333333 - -static double cdrom_seek_time(uint8_t id) +static void +cdrom_command_complete(cdrom_t *dev) { - cdrom_t *dev = cdrom[id]; - - uint32_t diff = dev->seek_diff; - double sd = (double) (MAX_SEEK - MIN_SEEK); - - if (diff < MIN_SEEK) - return 0.0; - if (diff > MAX_SEEK) - diff = MAX_SEEK; - - diff -= MIN_SEEK; - - return cdrom_speeds[dev->cur_speed].seek1 + - ((cdrom_speeds[dev->cur_speed].seek2 * ((double) diff)) / sd); + dev->packet_status = CDROM_PHASE_COMPLETE; + cdrom_command_common(dev); } -static double cdrom_bus_speed(uint8_t id) + +static void +cdrom_command_read(cdrom_t *dev) { - cdrom_t *dev = cdrom[id]; - - if (cdrom_drives[id].bus_type == CDROM_BUS_SCSI) { - dev->callback = -1LL; /* Speed depends on SCSI controller */ - return 0.0; - } else if (cdrom_drives[id].bus_type == CDROM_BUS_ATAPI_PIO_AND_DMA) { - if (cdrom_current_mode(id) == 2) - return 66666666.666666666666666; /* 66 MB/s MDMA-2 speed */ - else - return 8333333.333333333333333; /* 8.3 MB/s PIO-2 speed */ - } else - return 3333333.333333333333333; /* 3.3 MB/s PIO-0 speed */ + dev->packet_status = CDROM_PHASE_DATA_IN; + cdrom_command_common(dev); + dev->total_read = 0; } -static void cdrom_command_bus(uint8_t id) + +static void +cdrom_command_read_dma(cdrom_t *dev) { - cdrom_t *dev = cdrom[id]; - - dev->status = BUSY_STAT; - dev->phase = 1; - dev->pos = 0; - dev->callback = 1LL * CDROM_TIME; - cdrom_set_callback(id); + dev->packet_status = CDROM_PHASE_DATA_IN_DMA; + cdrom_command_common(dev); + dev->total_read = 0; } -static void cdrom_command_common(uint8_t id) + +static void +cdrom_command_write(cdrom_t *dev) { - cdrom_t *dev = cdrom[id]; - double bytes_per_second, period; - double dusec; - - dev->status = BUSY_STAT; - dev->phase = 1; - dev->pos = 0; - dev->callback = 0LL; - - cdrom_log("CD-ROM %i: Current speed: %ix\n", id, dev->cur_speed); - - if (dev->packet_status == CDROM_PHASE_COMPLETE) { - cdrom_phase_callback(id); - dev->callback = 0LL; - } else { - switch(dev->current_cdb[0]) { - case GPCMD_REZERO_UNIT: - case 0x0b: - case 0x2b: - /* Seek time is in us. */ - period = cdrom_seek_time(id) * ((double) TIMER_USEC); - dev->callback += ((int64_t) period); - cdrom_set_callback(id); - cdrom_log("CD-ROM %i: Seek period: %" PRIu64 " us\n", id, (int64_t)cdrom_seek_time(id)); - return; - case 0x08: - case 0x28: - case 0xa8: - /* Seek time is in us. */ - period = cdrom_seek_time(id) * ((double) TIMER_USEC); - dev->callback += ((int64_t) period); - cdrom_log("CD-ROM %i: Seek period: %" PRIu64 " us\n", id, (int64_t)cdrom_seek_time(id)); - case 0x25: - case 0x42: - case 0x43: - case 0x44: - case 0x51: - case 0x52: - case 0xad: - case 0xb8: - case 0xb9: - case 0xbe: - bytes_per_second = 176.0 * 1024.0; - bytes_per_second *= (double)cdrom_speeds[dev->cur_speed].speed; - break; - default: - bytes_per_second = cdrom_bus_speed(id); - if (bytes_per_second == 0.0) { - dev->callback = -1LL; /* Speed depends on SCSI controller */ - return; - } - break; - } - - period = 1000000.0 / bytes_per_second; - cdrom_log("CD-ROM %i: Byte transfer period: %" PRIu64 " us\n", id, (int64_t)period); - period = period * (double) (dev->packet_len); - cdrom_log("CD-ROM %i: Sector transfer period: %" PRIu64 " us\n", id, (int64_t)period); - dusec = period * ((double) TIMER_USEC); - dev->callback += ((int64_t) dusec); - } - cdrom_set_callback(id); + dev->packet_status = CDROM_PHASE_DATA_OUT; + cdrom_command_common(dev); } -static void cdrom_command_complete(uint8_t id) + +static void cdrom_command_write_dma(cdrom_t *dev) { - cdrom_t *dev = cdrom[id]; - - dev->packet_status = CDROM_PHASE_COMPLETE; - cdrom_command_common(id); + dev->packet_status = CDROM_PHASE_DATA_OUT_DMA; + cdrom_command_common(dev); } -static void cdrom_command_read(uint8_t id) -{ - cdrom_t *dev = cdrom[id]; - - dev->packet_status = CDROM_PHASE_DATA_IN; - cdrom_command_common(id); - dev->total_read = 0; -} - -static void cdrom_command_read_dma(uint8_t id) -{ - cdrom_t *dev = cdrom[id]; - - dev->packet_status = CDROM_PHASE_DATA_IN_DMA; - cdrom_command_common(id); - dev->total_read = 0; -} - -static void cdrom_command_write(uint8_t id) -{ - cdrom_t *dev = cdrom[id]; - - dev->packet_status = CDROM_PHASE_DATA_OUT; - cdrom_command_common(id); -} - -static void cdrom_command_write_dma(uint8_t id) -{ - cdrom_t *dev = cdrom[id]; - - dev->packet_status = CDROM_PHASE_DATA_OUT_DMA; - cdrom_command_common(id); -} /* id = Current CD-ROM device ID; len = Total transfer length; block_len = Length of a single block (why does it matter?!); alloc_len = Allocated transfer length; direction = Transfer direction (0 = read from host, 1 = write to host). */ -static void cdrom_data_command_finish(uint8_t id, int len, int block_len, int alloc_len, int direction) +static void cdrom_data_command_finish(cdrom_t *dev, int len, int block_len, int alloc_len, int direction) { - cdrom_t *dev = cdrom[id]; + DEBUG("CD-ROM %i: Finishing command (%02X): %i, %i, %i, %i, %i\n", + dev->id, dev->current_cdb[0], len, block_len, alloc_len, direction, dev->request_length); + dev->pos = 0; + if (alloc_len >= 0) { + if (alloc_len < len) + len = alloc_len; + } + if ((len == 0) || (cdrom_current_mode(dev) == 0)) { + if (dev->drv->bus_type != CDROM_BUS_SCSI) + dev->packet_len = 0; - cdrom_log("CD-ROM %i: Finishing command (%02X): %i, %i, %i, %i, %i\n", id, dev->current_cdb[0], len, block_len, alloc_len, direction, dev->request_length); - dev->pos=0; - if (alloc_len >= 0) { - if (alloc_len < len) { - len = alloc_len; - } + cdrom_command_complete(dev); + } else { + if (cdrom_current_mode(dev) == 2) { + if (dev->drv->bus_type != CDROM_BUS_SCSI) + dev->packet_len = alloc_len; + + if (direction == 0) + cdrom_command_read_dma(dev); + else + cdrom_command_write_dma(dev); + } else { + cdrom_update_request_length(dev, len, block_len); + if (direction == 0) + cdrom_command_read(dev); + else + cdrom_command_write(dev); } - if ((len == 0) || (cdrom_current_mode(id) == 0)) { - if (cdrom_drives[id].bus_type != CDROM_BUS_SCSI) { - dev->packet_len = 0; - } - cdrom_command_complete(id); - } - else { - if (cdrom_current_mode(id) == 2) { - if (cdrom_drives[id].bus_type != CDROM_BUS_SCSI) { - dev->packet_len = alloc_len; - } + } - if (direction == 0) - cdrom_command_read_dma(id); - else - cdrom_command_write_dma(id); - } - else { - cdrom_update_request_length(id, len, block_len); - if (direction == 0) - cdrom_command_read(id); - else - cdrom_command_write(id); - } - } - - cdrom_log("CD-ROM %i: Status: %i, cylinder %i, packet length: %i, position: %i, phase: %i\n", id, dev->packet_status, dev->request_length, dev->packet_len, dev->pos, dev->phase); + DEBUG("CD-ROM %i: Status: %i, cylinder %i, packet length: %i, position: %i, phase: %i\n", + dev->id, dev->packet_status, dev->request_length, dev->packet_len, dev->pos, dev->phase); } -static void cdrom_sense_clear(int id, int command) -{ - cdrom_t *dev = cdrom[id]; - dev->previous_command = command; - cdrom_sense_key = cdrom_asc = cdrom_ascq = 0; +static void +cdrom_sense_clear(cdrom_t *dev, int command) +{ + dev->previous_command = command; + cdrom_sense_key = cdrom_asc = cdrom_ascq = 0; } -static void cdrom_set_phase(uint8_t id, uint8_t phase) + +static void +cdrom_set_phase(cdrom_t *dev, uint8_t phase) { - uint8_t scsi_id = cdrom_drives[id].scsi_device_id; - uint8_t scsi_lun = cdrom_drives[id].scsi_device_lun; + uint8_t scsi_id = dev->drv->scsi_device_id; + uint8_t scsi_lun = dev->drv->scsi_device_lun; - if (cdrom_drives[id].bus_type != CDROM_BUS_SCSI) - return; + if (dev->drv->bus_type != CDROM_BUS_SCSI) + return; - SCSIDevices[scsi_id][scsi_lun].Phase = phase; + SCSIDevices[scsi_id][scsi_lun].Phase = phase; } -static void cdrom_cmd_error(uint8_t id) -{ - cdrom_t *dev = cdrom[id]; - cdrom_set_phase(id, SCSI_PHASE_STATUS); - dev->error = ((cdrom_sense_key & 0xf) << 4) | ABRT_ERR; - if (dev->unit_attention) - dev->error |= MCR_ERR; - dev->status = READY_STAT | ERR_STAT; - dev->phase = 3; - dev->pos = 0; - dev->packet_status = 0x80; - dev->callback = 50LL * CDROM_TIME; - cdrom_set_callback(id); - cdrom_log("CD-ROM %i: ERROR: %02X/%02X/%02X\n", id, cdrom_sense_key, cdrom_asc, cdrom_ascq); +static void +cdrom_cmd_error(cdrom_t *dev) +{ + cdrom_set_phase(dev, SCSI_PHASE_STATUS); + dev->error = ((cdrom_sense_key & 0xf) << 4) | ABRT_ERR; + if (dev->unit_attention) + dev->error |= MCR_ERR; + dev->status = READY_STAT | ERR_STAT; + dev->phase = 3; + dev->pos = 0; + dev->packet_status = 0x80; + dev->callback = 50LL * CDROM_TIME; + cdrom_set_callback(dev); + DEBUG("CD-ROM %i: ERROR: %02X/%02X/%02X\n", dev->id, cdrom_sense_key, cdrom_asc, cdrom_ascq); } -static void cdrom_unit_attention(uint8_t id) -{ - cdrom_t *dev = cdrom[id]; - cdrom_set_phase(id, SCSI_PHASE_STATUS); - dev->error = (SENSE_UNIT_ATTENTION << 4) | ABRT_ERR; - if (dev->unit_attention) - dev->error |= MCR_ERR; - dev->status = READY_STAT | ERR_STAT; - dev->phase = 3; - dev->pos = 0; - dev->packet_status = 0x80; - dev->callback = 50LL * CDROM_TIME; - cdrom_set_callback(id); - cdrom_log("CD-ROM %i: UNIT ATTENTION\n", id); +static void +cdrom_unit_attention(cdrom_t *dev) +{ + cdrom_set_phase(dev, SCSI_PHASE_STATUS); + dev->error = (SENSE_UNIT_ATTENTION << 4) | ABRT_ERR; + if (dev->unit_attention) + dev->error |= MCR_ERR; + dev->status = READY_STAT | ERR_STAT; + dev->phase = 3; + dev->pos = 0; + dev->packet_status = 0x80; + dev->callback = 50LL * CDROM_TIME; + cdrom_set_callback(dev); + DEBUG("CD-ROM %i: UNIT ATTENTION\n", dev->id); } -static void cdrom_not_ready(uint8_t id) + +static void +cdrom_bus_master_error(cdrom_t *dev) { - cdrom_sense_key = SENSE_NOT_READY; - cdrom_asc = ASC_MEDIUM_NOT_PRESENT; - cdrom_ascq = 0; - cdrom_cmd_error(id); + cdrom_sense_key = cdrom_asc = cdrom_ascq = 0; + cdrom_cmd_error(dev); } -static void cdrom_invalid_lun(uint8_t id) + +static void +cdrom_not_ready(cdrom_t *dev) { - cdrom_sense_key = SENSE_ILLEGAL_REQUEST; - cdrom_asc = ASC_INV_LUN; - cdrom_ascq = 0; - cdrom_cmd_error(id); + cdrom_sense_key = SENSE_NOT_READY; + cdrom_asc = ASC_MEDIUM_NOT_PRESENT; + cdrom_ascq = 0; + cdrom_cmd_error(dev); } -static void cdrom_illegal_opcode(uint8_t id) + +static void +cdrom_invalid_lun(cdrom_t *dev) { - cdrom_sense_key = SENSE_ILLEGAL_REQUEST; - cdrom_asc = ASC_ILLEGAL_OPCODE; - cdrom_ascq = 0; - cdrom_cmd_error(id); + cdrom_sense_key = SENSE_ILLEGAL_REQUEST; + cdrom_asc = ASC_INV_LUN; + cdrom_ascq = 0; + cdrom_cmd_error(dev); } -static void cdrom_lba_out_of_range(uint8_t id) + +static void +cdrom_illegal_opcode(cdrom_t *dev) { - cdrom_sense_key = SENSE_ILLEGAL_REQUEST; - cdrom_asc = ASC_LBA_OUT_OF_RANGE; - cdrom_ascq = 0; - cdrom_cmd_error(id); + cdrom_sense_key = SENSE_ILLEGAL_REQUEST; + cdrom_asc = ASC_ILLEGAL_OPCODE; + cdrom_ascq = 0; + cdrom_cmd_error(dev); } -static void cdrom_invalid_field(uint8_t id) -{ - cdrom_t *dev = cdrom[id]; - cdrom_sense_key = SENSE_ILLEGAL_REQUEST; - cdrom_asc = ASC_INV_FIELD_IN_CMD_PACKET; - cdrom_ascq = 0; - cdrom_cmd_error(id); - dev->status = 0x53; +static void +cdrom_lba_out_of_range(cdrom_t *dev) +{ + cdrom_sense_key = SENSE_ILLEGAL_REQUEST; + cdrom_asc = ASC_LBA_OUT_OF_RANGE; + cdrom_ascq = 0; + cdrom_cmd_error(dev); } -static void cdrom_invalid_field_pl(uint8_t id) -{ - cdrom_t *dev = cdrom[id]; - cdrom_sense_key = SENSE_ILLEGAL_REQUEST; - cdrom_asc = ASC_INV_FIELD_IN_PARAMETER_LIST; - cdrom_ascq = 0; - cdrom_cmd_error(id); - dev->status = 0x53; +static void +cdrom_invalid_field(cdrom_t *dev) +{ + cdrom_sense_key = SENSE_ILLEGAL_REQUEST; + cdrom_asc = ASC_INV_FIELD_IN_CMD_PACKET; + cdrom_ascq = 0; + cdrom_cmd_error(dev); + dev->status = 0x53; } -static void cdrom_illegal_mode(uint8_t id) + +static void +cdrom_invalid_field_pl(cdrom_t *dev) { - cdrom_sense_key = SENSE_ILLEGAL_REQUEST; - cdrom_asc = ASC_ILLEGAL_MODE_FOR_THIS_TRACK; - cdrom_ascq = 0; - cdrom_cmd_error(id); + cdrom_sense_key = SENSE_ILLEGAL_REQUEST; + cdrom_asc = ASC_INV_FIELD_IN_PARAMETER_LIST; + cdrom_ascq = 0; + cdrom_cmd_error(dev); + dev->status = 0x53; } -static void cdrom_incompatible_format(uint8_t id) + +static void +cdrom_illegal_mode(cdrom_t *dev) { - cdrom_sense_key = SENSE_ILLEGAL_REQUEST; - cdrom_asc = ASC_INCOMPATIBLE_FORMAT; - cdrom_ascq = 2; - cdrom_cmd_error(id); + cdrom_sense_key = SENSE_ILLEGAL_REQUEST; + cdrom_asc = ASC_ILLEGAL_MODE_FOR_THIS_TRACK; + cdrom_ascq = 0; + cdrom_cmd_error(dev); } -static void cdrom_data_phase_error(uint8_t id) + +static void +cdrom_incompatible_format(cdrom_t *dev) { - cdrom_sense_key = SENSE_ILLEGAL_REQUEST; - cdrom_asc = ASC_DATA_PHASE_ERROR; - cdrom_ascq = 0; - cdrom_cmd_error(id); + cdrom_sense_key = SENSE_ILLEGAL_REQUEST; + cdrom_asc = ASC_INCOMPATIBLE_FORMAT; + cdrom_ascq = 2; + cdrom_cmd_error(dev); } -static int cdrom_pass_through(uint8_t id, uint32_t *len, uint8_t *cdb, uint8_t *buffer) + +static void +cdrom_data_phase_error(cdrom_t *dev) { - int ret = 0; - uint8_t temp_cdb[16]; + cdrom_sense_key = SENSE_ILLEGAL_REQUEST; + cdrom_asc = ASC_DATA_PHASE_ERROR; + cdrom_ascq = 0; + cdrom_cmd_error(dev); +} - memset(temp_cdb, 0, 16); - if (cdb[0] == 8) { - temp_cdb[0] = 0x28; - temp_cdb[8] = cdb[4]; - temp_cdb[3] = cdb[1]; - temp_cdb[4] = cdb[2]; - temp_cdb[5] = cdb[3]; - } else - memcpy(temp_cdb, cdb, 16); +void +cdrom_update_cdb(uint8_t *cdb, int lba_pos, int number_of_blocks) +{ + int temp = 0; - ret = cdrom_drives[id].handler->pass_through(id, temp_cdb, buffer, len); - cdrom_log("CD-ROM %i: Data from pass through: %02X %02X %02X %02X %02X %02X %02X %02X\n", id, buffer[0], buffer[1], buffer[2], buffer[3], buffer[4], buffer[5], buffer[6], buffer[7]); - cdrom_log("CD-ROM %i: Returned value: %i\n", id, ret); + switch(cdb[0]) { + case GPCMD_READ_6: + cdb[1] = (lba_pos >> 16) & 0xff; + cdb[2] = (lba_pos >> 8) & 0xff; + cdb[3] = lba_pos & 0xff; + break; + + case GPCMD_READ_10: + cdb[2] = (lba_pos >> 24) & 0xff; + cdb[3] = (lba_pos >> 16) & 0xff; + cdb[4] = (lba_pos >> 8) & 0xff; + cdb[5] = lba_pos & 0xff; + cdb[7] = (number_of_blocks >> 8) & 0xff; + cdb[8] = number_of_blocks & 0xff; + break; + + case GPCMD_READ_12: + cdb[2] = (lba_pos >> 24) & 0xff; + cdb[3] = (lba_pos >> 16) & 0xff; + cdb[4] = (lba_pos >> 8) & 0xff; + cdb[5] = lba_pos & 0xff; + cdb[6] = (number_of_blocks >> 24) & 0xff; + cdb[7] = (number_of_blocks >> 16) & 0xff; + cdb[8] = (number_of_blocks >> 8) & 0xff; + cdb[9] = number_of_blocks & 0xff; + break; + + case GPCMD_READ_CD_MSF: + temp = cdrom_lba_to_msf_accurate(lba_pos); + cdb[3] = (temp >> 16) & 0xff; + cdb[4] = (temp >> 8) & 0xff; + cdb[5] = temp & 0xff; + + temp = cdrom_lba_to_msf_accurate(lba_pos + number_of_blocks - 1); + cdb[6] = (temp >> 16) & 0xff; + cdb[7] = (temp >> 8) & 0xff; + cdb[8] = temp & 0xff; + break; + + case GPCMD_READ_CD: + cdb[2] = (lba_pos >> 24) & 0xff; + cdb[3] = (lba_pos >> 16) & 0xff; + cdb[4] = (lba_pos >> 8) & 0xff; + cdb[5] = lba_pos & 0xff; + cdb[6] = (number_of_blocks >> 16) & 0xff; + cdb[7] = (number_of_blocks >> 8) & 0xff; + cdb[8] = number_of_blocks & 0xff; + break; + } +} + + +static int +cdrom_read_data(cdrom_t *dev, int msf, int type, int flags, int32_t *len) +{ + int ret = 0; + uint32_t cdsize = 0; + + int i = 0; + int temp_len = 0; + + cdsize = dev->handler->size(dev->id); + + if (dev->sector_pos >= cdsize) { + DEBUG("CD-ROM %i: Trying to read from beyond the end of disc (%i >= %i)\n", dev->id, + dev->sector_pos, cdsize); + cdrom_lba_out_of_range(dev); + return 0; + } + + if ((dev->sector_pos + dev->sector_len - 1) >= cdsize) { + DEBUG("CD-ROM %i: Trying to read to beyond the end of disc (%i >= %i)\n", dev->id, + (dev->sector_pos + dev->sector_len - 1), cdsize); + cdrom_lba_out_of_range(dev); + return 0; + } + + dev->old_len = 0; + *len = 0; + + for (i = 0; i < dev->requested_blocks; i++) { + ret = dev->handler->readsector_raw(dev->id, cdbufferb + dev->data_pos, dev->sector_pos + i, + msf, type, flags, &temp_len); + + dev->data_pos += temp_len; + dev->old_len += temp_len; + + *len += temp_len; if (!ret) { - /* Command failed with OS error code, return illegal opcode. */ - cdrom_log("CD-ROM %i: Command failed with OS error code, return illegal opcode.\n", id); - cdrom_illegal_opcode(id); + cdrom_illegal_mode(dev); return 0; - } else { - if ((cdrom_sense_key != 0) || (cdrom_asc != 0) || (cdrom_ascq != 0)) { - /* Command failed with sense, error with that sense. */ - cdrom_log("CD-ROM %i: Command failed with sense, error with that sense (%02X/%02X/%02X).\n", id, cdrom_sense_key, cdrom_asc, cdrom_ascq); - cdrom_cmd_error(id); - return 0; - } else { - /* Command was performed successfully. */ - cdrom_log("CD-ROM %i: Command was performed successfully.\n", id); - return 1; - } } + } + + return 1; } -void cdrom_update_cdb(uint8_t *cdb, int lba_pos, int number_of_blocks) + +static int +cdrom_read_blocks(cdrom_t *dev, int32_t *len, int first_batch) { - int temp = 0; + int ret = 0, msf = 0; + int type = 0, flags = 0; - switch(cdb[0]) { - case GPCMD_READ_6: - cdb[1] = (lba_pos >> 16) & 0xff; - cdb[2] = (lba_pos >> 8) & 0xff; - cdb[3] = lba_pos & 0xff; - break; + if (dev->current_cdb[0] == 0xb9) + msf = 1; - case GPCMD_READ_10: - cdb[2] = (lba_pos >> 24) & 0xff; - cdb[3] = (lba_pos >> 16) & 0xff; - cdb[4] = (lba_pos >> 8) & 0xff; - cdb[5] = lba_pos & 0xff; - cdb[7] = (number_of_blocks >> 8) & 0xff; - cdb[8] = number_of_blocks & 0xff; - break; + if ((dev->current_cdb[0] == 0xb9) || (dev->current_cdb[0] == 0xbe)) { + type = (dev->current_cdb[1] >> 2) & 7; + flags = dev->current_cdb[9] | (((uint32_t) dev->current_cdb[10]) << 8); + } else { + type = 8; + flags = 0x10; + } - case GPCMD_READ_12: - cdb[2] = (lba_pos >> 24) & 0xff; - cdb[3] = (lba_pos >> 16) & 0xff; - cdb[4] = (lba_pos >> 8) & 0xff; - cdb[5] = lba_pos & 0xff; - cdb[6] = (number_of_blocks >> 24) & 0xff; - cdb[7] = (number_of_blocks >> 16) & 0xff; - cdb[8] = (number_of_blocks >> 8) & 0xff; - cdb[9] = number_of_blocks & 0xff; - break; + dev->data_pos = 0; - case GPCMD_READ_CD_MSF: - temp = cdrom_lba_to_msf_accurate(lba_pos); - cdb[3] = (temp >> 16) & 0xff; - cdb[4] = (temp >> 8) & 0xff; - cdb[5] = temp & 0xff; + if (!dev->sector_len) { + cdrom_command_complete(dev); + return -1; + } - temp = cdrom_lba_to_msf_accurate(lba_pos + number_of_blocks - 1); - cdb[6] = (temp >> 16) & 0xff; - cdb[7] = (temp >> 8) & 0xff; - cdb[8] = temp & 0xff; - break; + DEBUG("Reading %i blocks starting from %i...\n", dev->requested_blocks, dev->sector_pos); - case GPCMD_READ_CD: - cdb[2] = (lba_pos >> 24) & 0xff; - cdb[3] = (lba_pos >> 16) & 0xff; - cdb[4] = (lba_pos >> 8) & 0xff; - cdb[5] = lba_pos & 0xff; - cdb[6] = (number_of_blocks >> 16) & 0xff; - cdb[7] = (number_of_blocks >> 8) & 0xff; - cdb[8] = number_of_blocks & 0xff; - break; - } + cdrom_update_cdb(dev->current_cdb, dev->sector_pos, dev->requested_blocks); + + ret = cdrom_read_data(dev, msf, type, flags, len); + + DEBUG("Read %i bytes of blocks...\n", *len); + + if (!ret || ((dev->old_len != *len) && !first_batch)) { + if ((dev->old_len != *len) && !first_batch) + cdrom_illegal_mode(dev); + + return 0; + } + + dev->sector_pos += dev->requested_blocks; + dev->sector_len -= dev->requested_blocks; + + return 1; } -#define cdbufferb dev->buffer -int cdrom_read_data(uint8_t id, int msf, int type, int flags, uint32_t *len) -{ - cdrom_t *dev = cdrom[id]; - int ret = 0; - uint32_t cdsize = 0; - - int i = 0; - int temp_len = 0; - - int last_valid_data_pos = 0; - - cdsize = cdrom_drives[id].handler->size(id); - - if (dev->sector_pos >= cdsize) { - cdrom_log("CD-ROM %i: Trying to read from beyond the end of disc (%i >= %i)\n", id, dev->sector_pos, cdsize); - cdrom_lba_out_of_range(id); - return 0; - } - - if ((dev->sector_pos + dev->sector_len - 1) >= cdsize) { - cdrom_log("CD-ROM %i: Trying to read to beyond the end of disc (%i >= %i)\n", id, (dev->sector_pos + dev->sector_len - 1), cdsize); - cdrom_lba_out_of_range(id); - return 0; - } - - if (cdrom_drives[id].handler->pass_through) { - ret = cdrom_pass_through(id, len, dev->current_cdb, cdbufferb + dev->data_pos); - dev->data_pos += *len; - - if (!ret) - return 0; - - dev->old_len = *len; - } else { - dev->old_len = 0; - *len = 0; - - for (i = 0; i < dev->requested_blocks; i++) { - ret = cdrom_drives[id].handler->readsector_raw(id, cdbufferb + dev->data_pos, dev->sector_pos + i, msf, type, flags, &temp_len); - - last_valid_data_pos = dev->data_pos; - - dev->data_pos += temp_len; - dev->old_len += temp_len; - - *len += temp_len; - - if (!ret) { - cdrom_illegal_mode(id); - return 0; - } - } - - cdrom_log("CD-ROM %i: Data from raw sector read: %02X %02X %02X %02X %02X %02X %02X %02X\n", id, cdbufferb[last_valid_data_pos + 0], cdbufferb[last_valid_data_pos + 1], cdbufferb[last_valid_data_pos + 2], cdbufferb[last_valid_data_pos + 3], cdbufferb[last_valid_data_pos + 4], cdbufferb[last_valid_data_pos + 5], cdbufferb[last_valid_data_pos + 6], cdbufferb[last_valid_data_pos + 7]); - } - - return 1; -} - -int cdrom_read_blocks(uint8_t id, uint32_t *len, int first_batch) -{ - cdrom_t *dev = cdrom[id]; - int ret = 0; - - int msf = 0; - - int type = 0; - int flags = 0; - - if (dev->current_cdb[0] == 0xb9) - msf = 1; - - if ((dev->current_cdb[0] == 0xb9) || (dev->current_cdb[0] == 0xbe)) { - type = (dev->current_cdb[1] >> 2) & 7; - flags = dev->current_cdb[9] | (((uint32_t) dev->current_cdb[10]) << 8); - } else { - type = 8; - flags = 0x10; - } - - dev->data_pos = 0; - - if (!dev->sector_len) { - cdrom_command_complete(id); - return -1; - } - - cdrom_log("Reading %i blocks starting from %i...\n", dev->requested_blocks, dev->sector_pos); - - cdrom_update_cdb(dev->current_cdb, dev->sector_pos, dev->requested_blocks); - - ret = cdrom_read_data(id, msf, type, flags, len); - - cdrom_log("Read %i bytes of blocks...\n", *len); - - if (!ret || ((dev->old_len != *len) && !first_batch)) { - if ((dev->old_len != *len) && !first_batch) - cdrom_illegal_mode(id); - - return 0; - } - - dev->sector_pos += dev->requested_blocks; - dev->sector_len -= dev->requested_blocks; - - return 1; -} - -/*SCSI Get Configuration*/ /*SCSI Read DVD Structure*/ -static int cdrom_read_dvd_structure(uint8_t id, int format, const uint8_t *packet, uint8_t *buf) +static int +cdrom_read_dvd_structure(cdrom_t *dev, int format, const uint8_t *packet, uint8_t *buf) { - int layer = packet[6]; - uint64_t total_sectors; + int layer = packet[6]; + uint64_t total_sectors; - switch (format) { - case 0x00: /* Physical format information */ - total_sectors = (uint64_t) cdrom_drives[id].handler->size(id); + switch (format) { + case 0x00: /* Physical format information */ + total_sectors = (uint64_t) dev->handler->size(dev->id); - if (layer != 0) { - cdrom_invalid_field(id); - return 0; - } - - total_sectors >>= 2; - if (total_sectors == 0) { - /* return -ASC_MEDIUM_NOT_PRESENT; */ - cdrom_not_ready(id); - return 0; - } - - buf[4] = 1; /* DVD-ROM, part version 1 */ - buf[5] = 0xf; /* 120mm disc, minimum rate unspecified */ - buf[6] = 1; /* one layer, read-only (per MMC-2 spec) */ - buf[7] = 0; /* default densities */ - - /* FIXME: 0x30000 per spec? */ - buf[8] = buf[9] = buf[10] = buf[11] = 0; /* start sector */ - buf[12] = (total_sectors >> 24) & 0xff; /* end sector */ - buf[13] = (total_sectors >> 16) & 0xff; - buf[14] = (total_sectors >> 8) & 0xff; - buf[15] = total_sectors & 0xff; - - buf[16] = (total_sectors >> 24) & 0xff; /* l0 end sector */ - buf[17] = (total_sectors >> 16) & 0xff; - buf[18] = (total_sectors >> 8) & 0xff; - buf[19] = total_sectors & 0xff; - - /* Size of buffer, not including 2 byte size field */ - buf[0] = ((2048 +2 ) >> 8) & 0xff; - buf[1] = (2048 + 2) & 0xff; - - /* 2k data + 4 byte header */ - return (2048 + 4); - - case 0x01: /* DVD copyright information */ - buf[4] = 0; /* no copyright data */ - buf[5] = 0; /* no region restrictions */ - - /* Size of buffer, not including 2 byte size field */ - buf[0] = ((4 + 2) >> 8) & 0xff; - buf[1] = (4 + 2) & 0xff; - - /* 4 byte header + 4 byte data */ - return (4 + 4); - - case 0x03: /* BCA information - invalid field for no BCA info */ - cdrom_invalid_field(id); + if (layer != 0) { + cdrom_invalid_field(dev); return 0; + } - case 0x04: /* DVD disc manufacturing information */ - /* Size of buffer, not including 2 byte size field */ - buf[0] = ((2048 + 2) >> 8) & 0xff; - buf[1] = (2048 + 2) & 0xff; - - /* 2k data + 4 byte header */ - return (2048 + 4); - - case 0xff: - /* - * This lists all the command capabilities above. Add new ones - * in order and update the length and buffer return values. - */ - - buf[4] = 0x00; /* Physical format */ - buf[5] = 0x40; /* Not writable, is readable */ - buf[6] = ((2048 + 4) >> 8) & 0xff; - buf[7] = (2048 + 4) & 0xff; - - buf[8] = 0x01; /* Copyright info */ - buf[9] = 0x40; /* Not writable, is readable */ - buf[10] = ((4 + 4) >> 8) & 0xff; - buf[11] = (4 + 4) & 0xff; - - buf[12] = 0x03; /* BCA info */ - buf[13] = 0x40; /* Not writable, is readable */ - buf[14] = ((188 + 4) >> 8) & 0xff; - buf[15] = (188 + 4) & 0xff; - - buf[16] = 0x04; /* Manufacturing info */ - buf[17] = 0x40; /* Not writable, is readable */ - buf[18] = ((2048 + 4) >> 8) & 0xff; - buf[19] = (2048 + 4) & 0xff; - - /* Size of buffer, not including 2 byte size field */ - buf[6] = ((16 + 2) >> 8) & 0xff; - buf[7] = (16 + 2) & 0xff; - - /* data written + 4 byte header */ - return (16 + 4); - - default: /* TODO: formats beyond DVD-ROM requires */ - cdrom_invalid_field(id); + total_sectors >>= 2; + if (total_sectors == 0) { + /* return -ASC_MEDIUM_NOT_PRESENT; */ + cdrom_not_ready(dev); return 0; - } + } + + buf[4] = 1; /* DVD-ROM, part version 1 */ + buf[5] = 0xf; /* 120mm disc, minimum rate unspecified */ + buf[6] = 1; /* one layer, read-only (per MMC-2 spec) */ + buf[7] = 0; /* default densities */ + + /* FIXME: 0x30000 per spec? */ + buf[8] = buf[9] = buf[10] = buf[11] = 0; /* start sector */ + buf[12] = (total_sectors >> 24) & 0xff; /* end sector */ + buf[13] = (total_sectors >> 16) & 0xff; + buf[14] = (total_sectors >> 8) & 0xff; + buf[15] = total_sectors & 0xff; + + buf[16] = (total_sectors >> 24) & 0xff; /* l0 end sector */ + buf[17] = (total_sectors >> 16) & 0xff; + buf[18] = (total_sectors >> 8) & 0xff; + buf[19] = total_sectors & 0xff; + + /* Size of buffer, not including 2 byte size field */ + buf[0] = ((2048 +2 ) >> 8) & 0xff; + buf[1] = (2048 + 2) & 0xff; + + /* 2k data + 4 byte header */ + return (2048 + 4); + + case 0x01: /* DVD copyright information */ + buf[4] = 0; /* no copyright data */ + buf[5] = 0; /* no region restrictions */ + + /* Size of buffer, not including 2 byte size field */ + buf[0] = ((4 + 2) >> 8) & 0xff; + buf[1] = (4 + 2) & 0xff; + + /* 4 byte header + 4 byte data */ + return (4 + 4); + + case 0x03: /* BCA information - invalid field for no BCA info */ + cdrom_invalid_field(dev); + return 0; + + case 0x04: /* DVD disc manufacturing information */ + /* Size of buffer, not including 2 byte size field */ + buf[0] = ((2048 + 2) >> 8) & 0xff; + buf[1] = (2048 + 2) & 0xff; + + /* 2k data + 4 byte header */ + return (2048 + 4); + + case 0xff: + /* + * This lists all the command capabilities above. Add new ones + * in order and update the length and buffer return values. + */ + + buf[4] = 0x00; /* Physical format */ + buf[5] = 0x40; /* Not writable, is readable */ + buf[6] = ((2048 + 4) >> 8) & 0xff; + buf[7] = (2048 + 4) & 0xff; + + buf[8] = 0x01; /* Copyright info */ + buf[9] = 0x40; /* Not writable, is readable */ + buf[10] = ((4 + 4) >> 8) & 0xff; + buf[11] = (4 + 4) & 0xff; + + buf[12] = 0x03; /* BCA info */ + buf[13] = 0x40; /* Not writable, is readable */ + buf[14] = ((188 + 4) >> 8) & 0xff; + buf[15] = (188 + 4) & 0xff; + + buf[16] = 0x04; /* Manufacturing info */ + buf[17] = 0x40; /* Not writable, is readable */ + buf[18] = ((2048 + 4) >> 8) & 0xff; + buf[19] = (2048 + 4) & 0xff; + + /* Size of buffer, not including 2 byte size field */ + buf[6] = ((16 + 2) >> 8) & 0xff; + buf[7] = (16 + 2) & 0xff; + + /* data written + 4 byte header */ + return (16 + 4); + + default: /* TODO: formats beyond DVD-ROM requires */ + cdrom_invalid_field(dev); + return 0; + } } -void cdrom_insert(uint8_t id) + +void +cdrom_insert(cdrom_t *dev) { - cdrom_t *dev = cdrom[id]; - - dev->unit_attention = 1; - - cdrom_log("CD-ROM %i: Media insert\n", id); + dev->unit_attention = 1; + DEBUG("CD-ROM %i: Media insert\n", dev->id); } + /*SCSI Sense Initialization*/ -void cdrom_sense_code_ok(uint8_t id) +void +cdrom_sense_code_ok(uint8_t id) { - cdrom_sense_key = SENSE_NONE; - cdrom_asc = 0; - cdrom_ascq = 0; + cdrom_t *dev = cdrom[id]; + + cdrom_sense_key = SENSE_NONE; + cdrom_asc = 0; + cdrom_ascq = 0; } -int cdrom_pre_execution_check(uint8_t id, uint8_t *cdb) + +static int +cdrom_pre_execution_check(cdrom_t *dev, uint8_t *cdb) { - cdrom_t *dev = cdrom[id]; + int ready = 0, status = 0; - int ready = 0; - - if (cdrom_drives[id].bus_type == CDROM_BUS_SCSI) { - if (((dev->request_length >> 5) & 7) != cdrom_drives[id].scsi_device_lun) { - cdrom_log("CD-ROM %i: Attempting to execute a unknown command targeted at SCSI LUN %i\n", id, ((dev->request_length >> 5) & 7)); - cdrom_invalid_lun(id); - return 0; - } - } - - if (!(cdrom_command_flags[cdb[0]] & IMPLEMENTED)) { - cdrom_log("CD-ROM %i: Attempting to execute unknown command %02X over %s\n", id, cdb[0], (cdrom_drives[id].bus_type == CDROM_BUS_SCSI) ? "SCSI" : ((cdrom_drives[id].bus_type == CDROM_BUS_ATAPI_PIO_AND_DMA) ? "ATAPI PIO/DMA" : "ATAPI PIO")); - - cdrom_illegal_opcode(id); + if (dev->drv->bus_type == CDROM_BUS_SCSI) { + if (((dev->request_length >> 5) & 7) != dev->drv->scsi_device_lun) { + DEBUG("CD-ROM %i: Attempting to execute a unknown command targeted at SCSI LUN %i\n", + dev->id, ((dev->request_length >> 5) & 7)); + cdrom_invalid_lun(dev); return 0; } + } - if ((cdrom_drives[id].bus_type < CDROM_BUS_SCSI) && (cdrom_command_flags[cdb[0]] & SCSI_ONLY)) { - cdrom_log("CD-ROM %i: Attempting to execute SCSI-only command %02X over ATAPI\n", id, cdb[0]); - cdrom_illegal_opcode(id); - return 0; - } + if (!(cdrom_command_flags[cdb[0]] & IMPLEMENTED)) { + DEBUG("CD-ROM %i: Attempting to execute unknown command %02X over %s\n", dev->id, cdb[0], + (dev->drv->bus_type == CDROM_BUS_SCSI) ? "SCSI" : "ATAPI"); - if ((cdrom_drives[id].bus_type == CDROM_BUS_SCSI) && (cdrom_command_flags[cdb[0]] & ATAPI_ONLY)) { - cdrom_log("CD-ROM %i: Attempting to execute ATAPI-only command %02X over SCSI\n", id, cdb[0]); - cdrom_illegal_opcode(id); - return 0; - } + cdrom_illegal_opcode(dev); + return 0; + } - if ((cdrom_drives[id].handler->status(id) == CD_STATUS_PLAYING) || (cdrom_drives[id].handler->status(id) == CD_STATUS_PAUSED)) { - ready = 1; - goto skip_ready_check; - } + if ((dev->drv->bus_type < CDROM_BUS_SCSI) && (cdrom_command_flags[cdb[0]] & SCSI_ONLY)) { + DEBUG("CD-ROM %i: Attempting to execute SCSI-only command %02X over ATAPI\n", dev->id, cdb[0]); + cdrom_illegal_opcode(dev); + return 0; + } - if (cdrom_drives[id].handler->medium_changed(id)) - cdrom_insert(id); + if ((dev->drv->bus_type == CDROM_BUS_SCSI) && (cdrom_command_flags[cdb[0]] & ATAPI_ONLY)) { + DEBUG("CD-ROM %i: Attempting to execute ATAPI-only command %02X over SCSI\n", dev->id, cdb[0]); + cdrom_illegal_opcode(dev); + return 0; + } - ready = cdrom_drives[id].handler->ready(id); + status = dev->handler->status(dev->id); + + if ((status == CD_STATUS_PLAYING) || (status == CD_STATUS_PAUSED)) { + ready = 1; + goto skip_ready_check; + } + + if (dev->handler->medium_changed(dev->id)) + cdrom_insert(dev); + + ready = dev->handler->ready(dev->id); skip_ready_check: + /* If the drive is not ready, there is no reason to keep the + UNIT ATTENTION condition present, as we only use it to mark + disc changes. */ + if (!ready && dev->unit_attention) + dev->unit_attention = 0; + + /* If the UNIT ATTENTION condition is set and the command does not allow + execution under it, error out and report the condition. */ + if (dev->unit_attention == 1) { + /* Only increment the unit attention phase if the command can not pass through it. */ + if (!(cdrom_command_flags[cdb[0]] & ALLOW_UA)) { + /* DEBUG("CD-ROM %i: Unit attention now 2\n", dev->id); */ + dev->unit_attention++; + DEBUG("CD-ROM %i: UNIT ATTENTION: Command %02X not allowed to pass through\n", dev->id, cdb[0]); + cdrom_unit_attention(dev); + return 0; + } + } else if (dev->unit_attention == 2) { + if (cdb[0] != GPCMD_REQUEST_SENSE) { + /* DEBUG("CD-ROM %i: Unit attention now 0\n", dev->id); */ + dev->unit_attention = 0; + } + } + + /* Unless the command is REQUEST SENSE, clear the sense. This will *NOT* + the UNIT ATTENTION condition if it's set. */ + if (cdb[0] != GPCMD_REQUEST_SENSE) + cdrom_sense_clear(dev, cdb[0]); + + /* Next it's time for NOT READY. */ + if (!ready) + dev->media_status = MEC_MEDIA_REMOVAL; + else + dev->media_status = (dev->unit_attention) ? MEC_NEW_MEDIA : MEC_NO_CHANGE; + + if ((cdrom_command_flags[cdb[0]] & CHECK_READY) && !ready) { + DEBUG("CD-ROM %i: Not ready (%02X)\n", dev->id, cdb[0]); + cdrom_not_ready(dev); + return 0; + } + + DEBUG("CD-ROM %i: Continuing with command %02X\n", dev->id, cdb[0]); + + return 1; +} + + +static void +cdrom_seek(cdrom_t *dev, uint32_t pos) +{ + /* DEBUG("CD-ROM %i: Seek %08X\n", dev->id, pos); */ + dev->seek_pos = pos; + if (dev->handler && dev->handler->stop) + dev->handler->stop(dev->id); +} + + +static void +cdrom_rezero(cdrom_t *dev) +{ + if (dev->handler && dev->handler->stop) + dev->handler->stop(dev->id); + dev->sector_pos = dev->sector_len = 0; + cdrom_seek(dev, 0); +} + + +void +cdrom_reset(cdrom_t *dev) +{ + if (!dev) + return; + + cdrom_rezero(dev); + dev->status = 0; + dev->callback = 0LL; + cdrom_set_callback(dev); + dev->packet_status = 0xff; + dev->unit_attention = 0xff; +} + + +static int +cdrom_playing_completed(cdrom_t *dev) +{ + dev->prev_status = dev->cd_status; + dev->cd_status = dev->handler->status(dev->id); + if (((dev->prev_status == CD_STATUS_PLAYING) || (dev->prev_status == CD_STATUS_PAUSED)) && ((dev->cd_status != CD_STATUS_PLAYING) && (dev->cd_status != CD_STATUS_PAUSED))) + return 1; + else + return 0; +} + + +static void +cdrom_request_sense(cdrom_t *dev, uint8_t *buffer, uint8_t alloc_length) +{ + /*Will return 18 bytes of 0*/ + if (alloc_length != 0) { + memset(buffer, 0, alloc_length); + memcpy(buffer, dev->sense, alloc_length); + } + + buffer[0] = 0x70; + + if ((cdrom_sense_key > 0) && ((dev->cd_status < CD_STATUS_PLAYING) || + (dev->cd_status == CD_STATUS_STOPPED)) && cdrom_playing_completed(dev)) { + buffer[2]=SENSE_ILLEGAL_REQUEST; + buffer[12]=ASC_AUDIO_PLAY_OPERATION; + buffer[13]=ASCQ_AUDIO_PLAY_OPERATION_COMPLETED; + } else if ((cdrom_sense_key == 0) && (dev->cd_status >= CD_STATUS_PLAYING) && + (dev->cd_status != CD_STATUS_STOPPED)) { + buffer[2]=SENSE_ILLEGAL_REQUEST; + buffer[12]=ASC_AUDIO_PLAY_OPERATION; + buffer[13]=(dev->cd_status == CD_STATUS_PLAYING) ? ASCQ_AUDIO_PLAY_OPERATION_IN_PROGRESS : ASCQ_AUDIO_PLAY_OPERATION_PAUSED; + } else { + if (dev->unit_attention && (cdrom_sense_key == 0)) { + buffer[2]=SENSE_UNIT_ATTENTION; + buffer[12]=ASC_MEDIUM_MAY_HAVE_CHANGED; + buffer[13]=0; + } + } + + DEBUG("CD-ROM %i: Reporting sense: %02X %02X %02X\n", dev->id, buffer[2], buffer[12], buffer[13]); + + if (buffer[2] == SENSE_UNIT_ATTENTION) { + /* If the last remaining sense is unit attention, clear + that condition. */ + dev->unit_attention = 0; + } + + /* Clear the sense stuff as per the spec. */ + cdrom_sense_clear(dev, GPCMD_REQUEST_SENSE); +} + + +void +cdrom_request_sense_for_scsi(cdrom_t *dev, uint8_t *buffer, uint8_t alloc_length) +{ + int ready = 0; + + if (dev->handler->medium_changed(dev->id)) + cdrom_insert(dev); + + ready = dev->handler->ready(dev->id); + + if (!ready && dev->unit_attention) { /* If the drive is not ready, there is no reason to keep the UNIT ATTENTION condition present, as we only use it to mark disc changes. */ - if (!ready && dev->unit_attention) - dev->unit_attention = 0; - - /* If the UNIT ATTENTION condition is set and the command does not allow - execution under it, error out and report the condition. */ - if (dev->unit_attention == 1) { - /* Only increment the unit attention phase if the command can not pass through it. */ - if (!(cdrom_command_flags[cdb[0]] & ALLOW_UA)) { - /* cdrom_log("CD-ROM %i: Unit attention now 2\n", id); */ - dev->unit_attention++; - cdrom_log("CD-ROM %i: UNIT ATTENTION: Command %02X not allowed to pass through\n", id, cdb[0]); - cdrom_unit_attention(id); - return 0; - } - } - else if (dev->unit_attention == 2) { - if (cdb[0] != GPCMD_REQUEST_SENSE) { - /* cdrom_log("CD-ROM %i: Unit attention now 0\n", id); */ - dev->unit_attention = 0; - } - } - - /* Unless the command is REQUEST SENSE, clear the sense. This will *NOT* - the UNIT ATTENTION condition if it's set. */ - if (cdb[0] != GPCMD_REQUEST_SENSE) - cdrom_sense_clear(id, cdb[0]); - - /* Next it's time for NOT READY. */ - if (!ready) - dev->media_status = MEC_MEDIA_REMOVAL; - else - dev->media_status = (dev->unit_attention) ? MEC_NEW_MEDIA : MEC_NO_CHANGE; - - if ((cdrom_command_flags[cdb[0]] & CHECK_READY) && !ready) { - cdrom_log("CD-ROM %i: Not ready (%02X)\n", id, cdb[0]); - cdrom_not_ready(id); - return 0; - } - - cdrom_log("CD-ROM %i: Continuing with command %02X\n", id, cdb[0]); - - return 1; -} - -void cdrom_clear_callback(uint8_t channel) -{ - uint8_t id = atapi_cdrom_drives[channel]; - cdrom_t *dev; - - if (id < CDROM_NUM) - { - dev = cdrom[id]; - dev->callback = 0LL; - cdrom_set_callback(id); - } -} - -static void cdrom_seek(uint8_t id, uint32_t pos) -{ - cdrom_t *dev = cdrom[id]; - - /* cdrom_log("CD-ROM %i: Seek %08X\n", id, pos); */ - dev->seek_pos = pos; - if (cdrom_drives[id].handler->stop) - cdrom_drives[id].handler->stop(id); -} - -static void cdrom_rezero(uint8_t id) -{ - cdrom_t *dev = cdrom[id]; - - if (cdrom_drives[id].handler->stop) - cdrom_drives[id].handler->stop(id); - dev->sector_pos = dev->sector_len = 0; - cdrom_seek(id, 0); -} - -void cdrom_reset(uint8_t id) -{ - cdrom_t *dev = cdrom[id]; - - if (!dev) - return; - - cdrom_rezero(id); - dev->status = 0; - dev->callback = 0LL; - cdrom_set_callback(id); - dev->packet_status = 0xff; dev->unit_attention = 0; + } + + /* Do *NOT* advance the unit attention phase. */ + cdrom_request_sense(dev, buffer, alloc_length); } -int cdrom_playing_completed(uint8_t id) + +static void +cdrom_set_buf_len(cdrom_t *dev, int32_t *BufLen, int32_t *src_len) { - cdrom_t *dev = cdrom[id]; - - dev->prev_status = dev->cd_status; - dev->cd_status = cdrom_drives[id].handler->status(id); - if (((dev->prev_status == CD_STATUS_PLAYING) || (dev->prev_status == CD_STATUS_PAUSED)) && ((dev->cd_status != CD_STATUS_PLAYING) && (dev->cd_status != CD_STATUS_PAUSED))) - return 1; - else - return 0; -} - -void cdrom_request_sense(uint8_t id, uint8_t *buffer, uint8_t alloc_length) -{ - cdrom_t *dev = cdrom[id]; - - /*Will return 18 bytes of 0*/ - if (alloc_length != 0) { - memset(buffer, 0, alloc_length); - memcpy(buffer, dev->sense, alloc_length); - } - - buffer[0] = 0x70; - - if ((cdrom_sense_key > 0) && ((dev->cd_status < CD_STATUS_PLAYING) || (dev->cd_status == CD_STATUS_STOPPED)) && cdrom_playing_completed(id)) { - buffer[2]=SENSE_ILLEGAL_REQUEST; - buffer[12]=ASC_AUDIO_PLAY_OPERATION; - buffer[13]=ASCQ_AUDIO_PLAY_OPERATION_COMPLETED; - } - else if ((cdrom_sense_key == 0) && (dev->cd_status >= CD_STATUS_PLAYING) && (dev->cd_status != CD_STATUS_STOPPED)) { - buffer[2]=SENSE_ILLEGAL_REQUEST; - buffer[12]=ASC_AUDIO_PLAY_OPERATION; - buffer[13]=(dev->cd_status == CD_STATUS_PLAYING) ? ASCQ_AUDIO_PLAY_OPERATION_IN_PROGRESS : ASCQ_AUDIO_PLAY_OPERATION_PAUSED; - } + if (dev->drv->bus_type == CDROM_BUS_SCSI) { + if (*BufLen == -1) + *BufLen = *src_len; else { - if (dev->unit_attention && (cdrom_sense_key == 0)) { - buffer[2]=SENSE_UNIT_ATTENTION; - buffer[12]=ASC_MEDIUM_MAY_HAVE_CHANGED; - buffer[13]=0; + *BufLen = MIN(*src_len, *BufLen); + *src_len = *BufLen; + } + DEBUG("CD-ROM %i: Actual transfer length: %i\n", dev->id, *BufLen); + } +} + + +static void +cdrom_buf_alloc(cdrom_t *dev, uint32_t len) +{ + DEBUG("CD-ROM %i: Allocated buffer length: %i\n", dev->id, len); + cdbufferb = (uint8_t *) mem_alloc(len); +} + + +static void +cdrom_buf_free(cdrom_t *dev) +{ + if (cdbufferb) { + DEBUG("CD-ROM %i: Freeing buffer...\n", dev->id); + free(cdbufferb); + cdbufferb = NULL; + } +} + + +void +cdrom_command(cdrom_t *dev, uint8_t *cdb) +{ + int len, max_len, used_len, alloc_length, msf; + int pos = 0, i= 0, size_idx, idx = 0; + uint32_t feature; + unsigned preamble_len; + int toc_format, block_desc = 0; + int ret, format = 0; + int real_pos, track = 0; + char device_identify[9] = { 'E', 'M', 'U', '_', 'C', 'D', '0', '0', 0 }; + char device_identify_ex[15] = { 'E', 'M', 'U', '_', 'C', 'D', '0', '0', ' ', 'v', '1', '.', '0', '0', 0 }; + int32_t blen = 0, *BufLen; + uint8_t *b; + uint32_t profiles[2] = { MMC_PROFILE_CD_ROM, MMC_PROFILE_DVD_ROM }; + + if (dev->drv->bus_type == CDROM_BUS_SCSI) { + BufLen = &SCSIDevices[dev->drv->scsi_device_id][dev->drv->scsi_device_lun].BufferLength; + dev->status &= ~ERR_STAT; + } else { + BufLen = &blen; + dev->error = 0; + } + + dev->packet_len = 0; + dev->request_pos = 0; + + device_identify[7] = dev->id + 0x30; + + device_identify_ex[7] = dev->id + 0x30; + device_identify_ex[10] = EMU_VERSION[0]; + device_identify_ex[12] = EMU_VERSION[2]; + device_identify_ex[13] = EMU_VERSION[3]; + + dev->data_pos = 0; + + memcpy(dev->current_cdb, cdb, dev->cdb_len); + + dev->cd_status = dev->handler->status(dev->id); + + if (cdb[0] != 0) { + DEBUG("CD-ROM %i: Command 0x%02X, Sense Key %02X, Asc %02X, Ascq %02X, Unit attention: %i\n", + dev->id, cdb[0], cdrom_sense_key, cdrom_asc, cdrom_ascq, dev->unit_attention); + DEBUG("CD-ROM %i: Request length: %04X\n", dev->id, dev->request_length); + + DEBUG("CD-ROM %i: CDB: %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n", dev->id, + cdb[0], cdb[1], cdb[2], cdb[3], cdb[4], cdb[5], cdb[6], + cdb[7], cdb[8], cdb[9], cdb[10], cdb[11]); + } + + msf = cdb[1] & 2; + dev->sector_len = 0; + + cdrom_set_phase(dev, SCSI_PHASE_STATUS); + + /* This handles the Not Ready/Unit Attention check if it has to be handled at this point. */ + if (cdrom_pre_execution_check(dev, cdb) == 0) + return; + + switch (cdb[0]) { + case GPCMD_TEST_UNIT_READY: + cdrom_set_phase(dev, SCSI_PHASE_STATUS); + cdrom_command_complete(dev); + break; + + case GPCMD_REZERO_UNIT: + if (dev->handler->stop) + dev->handler->stop(dev->id); + dev->sector_pos = dev->sector_len = 0; + dev->seek_diff = dev->seek_pos; + cdrom_seek(dev, 0); + cdrom_set_phase(dev, SCSI_PHASE_STATUS); + break; + + case GPCMD_REQUEST_SENSE: + /* If there's a unit attention condition and there's a buffered not ready, a standalone REQUEST SENSE + should forget about the not ready, and report unit attention straight away. */ + cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); + max_len = cdb[4]; + cdrom_buf_alloc(dev, 256); + cdrom_set_buf_len(dev, BufLen, &max_len); + cdrom_request_sense(dev, cdbufferb, max_len); + cdrom_data_command_finish(dev, 18, 18, cdb[4], 0); + break; + + case GPCMD_SET_SPEED: + case GPCMD_SET_SPEED_ALT: + len = (cdb[3] | (cdb[2] << 8)) / 176; + dev->cur_speed = cdrom_speed_idx(len); + if (dev->cur_speed > dev->drv->speed_idx) + dev->cur_speed = dev->drv->speed_idx; + cdrom_set_phase(dev, SCSI_PHASE_STATUS); + cdrom_command_complete(dev); + break; + + case GPCMD_MECHANISM_STATUS: + cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); + len = (cdb[7] << 16) | (cdb[8] << 8) | cdb[9]; + + cdrom_buf_alloc(dev, 8); + + cdrom_set_buf_len(dev, BufLen, &len); + + memset(cdbufferb, 0, 8); + cdbufferb[5] = 1; + + cdrom_data_command_finish(dev, 8, 8, len, 0); + break; + + case GPCMD_READ_TOC_PMA_ATIP: + cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); + + max_len = cdb[7]; + max_len <<= 8; + max_len |= cdb[8]; + + cdrom_buf_alloc(dev, 65536); + + toc_format = cdb[2] & 0xf; + + if (toc_format == 0) + toc_format = (cdb[9] >> 6) & 3; + + switch (toc_format) { + case 0: /*Normal*/ + len = dev->handler->readtoc(dev->id, cdbufferb, cdb[6], msf, max_len, + 0); + break; + case 1: /*Multi session*/ + len = dev->handler->readtoc_session(dev->id, cdbufferb, msf, max_len); + cdbufferb[0] = 0; cdbufferb[1] = 0xA; + break; + case 2: /*Raw*/ + len = dev->handler->readtoc_raw(dev->id, cdbufferb, max_len); + break; + default: + cdrom_invalid_field(dev); + cdrom_buf_free(dev); + return; } - } - cdrom_log("CD-ROM %i: Reporting sense: %02X %02X %02X\n", id, buffer[2], buffer[12], buffer[13]); + if (len > max_len) { + len = max_len; - if (buffer[2] == SENSE_UNIT_ATTENTION) { - /* If the last remaining sense is unit attention, clear - that condition. */ - dev->unit_attention = 0; - } - - /* Clear the sense stuff as per the spec. */ - cdrom_sense_clear(id, GPCMD_REQUEST_SENSE); -} - -void cdrom_request_sense_for_scsi(uint8_t id, uint8_t *buffer, uint8_t alloc_length) -{ - cdrom_t *dev = cdrom[id]; - - int ready = 0; - - if (cdrom_drives[id].handler->medium_changed(id)) - cdrom_insert(id); - - ready = cdrom_drives[id].handler->ready(id); - - if (!ready && dev->unit_attention) { - /* If the drive is not ready, there is no reason to keep the - UNIT ATTENTION condition present, as we only use it to mark - disc changes. */ - dev->unit_attention = 0; - } - - /* Do *NOT* advance the unit attention phase. */ - - cdrom_request_sense(id, buffer, alloc_length); -} - -void cdrom_set_buf_len(uint8_t id, int32_t *BufLen, uint32_t *src_len) -{ - if (cdrom_drives[id].bus_type == CDROM_BUS_SCSI) { - if (*BufLen == -1) - *BufLen = *src_len; - else { - *BufLen = MIN((int)*src_len, *BufLen); - *src_len = *BufLen; + cdbufferb[0] = ((len - 2) >> 8) & 0xff; + cdbufferb[1] = (len - 2) & 0xff; } - cdrom_log("CD-ROM %i: Actual transfer length: %i\n", id, *BufLen); - } -} -void cdrom_buf_alloc(uint8_t id, uint32_t len) -{ - cdrom_t *dev = cdrom[id]; + cdrom_set_buf_len(dev, BufLen, &len); - cdrom_log("CD-ROM %i: Allocated buffer length: %i\n", id, len); - cdbufferb = (uint8_t *) malloc(len); -} + if (len >= 8) { + DEBUG("CD-ROM %i: TOC: %02X %02X %02X %02X %02X %02X %02X %02X\n", dev->id, + cdbufferb[0], cdbufferb[1], cdbufferb[2], cdbufferb[3], + cdbufferb[4], cdbufferb[5], cdbufferb[6], cdbufferb[7]); + } -void cdrom_buf_free(uint8_t id) -{ - cdrom_t *dev = cdrom[id]; + if (len >= 16) { + DEBUG(" %02X %02X %02X %02X %02X %02X %02X %02X\n", + cdbufferb[8], cdbufferb[9], cdbufferb[10], cdbufferb[11], + cdbufferb[12], cdbufferb[13], cdbufferb[14], cdbufferb[15]); + } - if (cdbufferb) { - cdrom_log("CD-ROM %i: Freeing buffer...\n", id); - free(cdbufferb); - cdbufferb = NULL; - } -} + if (len >= 24) { + DEBUG(" %02X %02X %02X %02X %02X %02X %02X %02X\n", + cdbufferb[16], cdbufferb[17], cdbufferb[18], cdbufferb[19], + cdbufferb[20], cdbufferb[21], cdbufferb[22], cdbufferb[23]); + } -void cdrom_command(uint8_t id, uint8_t *cdb) -{ - cdrom_t *dev = cdrom[id]; + if (len >= 32) { + DEBUG(" %02X %02X %02X %02X %02X %02X %02X %02X\n", + cdbufferb[24], cdbufferb[25], cdbufferb[26], cdbufferb[27], + cdbufferb[28], cdbufferb[29], cdbufferb[30], cdbufferb[31]); + } - uint32_t len; - int msf; - int pos=0; - uint32_t max_len; - uint32_t feature; - uint32_t used_len; - unsigned idx = 0; - unsigned size_idx; - unsigned preamble_len; - int toc_format; - uint32_t alloc_length; - int block_desc = 0; - int format = 0; - int ret; - int real_pos; - int track = 0; - char device_identify[9] = { 'E', 'M', 'U', '_', 'C', 'D', '0', '0', 0 }; - char device_identify_ex[15] = { 'E', 'M', 'U', '_', 'C', 'D', '0', '0', ' ', 'v', '1', '.', '0', '0', 0 }; - int32_t blen = 0; - int32_t *BufLen; - uint8_t *b; - uint32_t profiles[2] = { MMC_PROFILE_CD_ROM, MMC_PROFILE_DVD_ROM }; - uint32_t i = 0; + if (len >= 36) { + DEBUG(" %02X %02X %02X %02X\n", + cdbufferb[32], cdbufferb[33], cdbufferb[34], cdbufferb[35]); + } - if (cdrom_drives[id].bus_type == CDROM_BUS_SCSI) { - BufLen = &SCSIDevices[cdrom_drives[id].scsi_device_id][cdrom_drives[id].scsi_device_lun].BufferLength; - dev->status &= ~ERR_STAT; - } else { - BufLen = &blen; - dev->error = 0; - } - - dev->packet_len = 0; - dev->request_pos = 0; - - device_identify[7] = id + 0x30; - - device_identify_ex[7] = id + 0x30; - device_identify_ex[10] = EMU_VERSION[0]; - device_identify_ex[12] = EMU_VERSION[2]; - device_identify_ex[13] = EMU_VERSION[3]; - - dev->data_pos = 0; - - memcpy(dev->current_cdb, cdb, dev->cdb_len); - - dev->cd_status = cdrom_drives[id].handler->status(id); - - if (cdb[0] != 0) { - cdrom_log("CD-ROM %i: Command 0x%02X, Sense Key %02X, Asc %02X, Ascq %02X, Unit attention: %i\n", id, cdb[0], cdrom_sense_key, cdrom_asc, cdrom_ascq, dev->unit_attention); - cdrom_log("CD-ROM %i: Request length: %04X\n", id, dev->request_length); - - cdrom_log("CD-ROM %i: CDB: %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n", id, - cdb[0], cdb[1], cdb[2], cdb[3], cdb[4], cdb[5], cdb[6], cdb[7], - cdb[8], cdb[9], cdb[10], cdb[11]); - } - - msf = cdb[1] & 2; - dev->sector_len = 0; - - cdrom_set_phase(id, SCSI_PHASE_STATUS); - - /* This handles the Not Ready/Unit Attention check if it has to be handled at this point. */ - if (cdrom_pre_execution_check(id, cdb) == 0) + cdrom_data_command_finish(dev, len, len, len, 0); + /* DEBUG("CD-ROM %i: READ_TOC_PMA_ATIP format %02X, length %i (%i)\n", dev->id, + toc_format, ide->cylinder, cdbufferb[1]); */ return; - switch (cdb[0]) { - case GPCMD_TEST_UNIT_READY: - cdrom_set_phase(id, SCSI_PHASE_STATUS); - cdrom_command_complete(id); - break; + case GPCMD_READ_CD_OLD: + /* IMPORTANT: Convert the command to new read CD + for pass through purposes. */ + dev->current_cdb[0] = 0xbe; + case GPCMD_READ_6: + case GPCMD_READ_10: + case GPCMD_READ_12: + case GPCMD_READ_CD: + case GPCMD_READ_CD_MSF: + cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); + alloc_length = 2048; - case GPCMD_REZERO_UNIT: - if (cdrom_drives[id].handler->stop) - cdrom_drives[id].handler->stop(id); - dev->sector_pos = dev->sector_len = 0; - dev->seek_diff = dev->seek_pos; - cdrom_seek(id, 0); - cdrom_set_phase(id, SCSI_PHASE_STATUS); - break; - - case GPCMD_REQUEST_SENSE: - /* If there's a unit attention condition and there's a buffered not ready, a standalone REQUEST SENSE - should forget about the not ready, and report unit attention straight away. */ - cdrom_set_phase(id, SCSI_PHASE_DATA_IN); - max_len = cdb[4]; - cdrom_buf_alloc(id, 256); - cdrom_set_buf_len(id, BufLen, &max_len); - cdrom_request_sense(id, cdbufferb, max_len); - cdrom_data_command_finish(id, 18, 18, cdb[4], 0); - break; - - case GPCMD_SET_SPEED: - case GPCMD_SET_SPEED_ALT: - len = (cdb[3] | (cdb[2] << 8)) / 176; - dev->cur_speed = cdrom_speed_idx(len); - if (dev->cur_speed > cdrom_drives[id].speed_idx) - dev->cur_speed = cdrom_drives[id].speed_idx; - cdrom_set_phase(id, SCSI_PHASE_STATUS); - cdrom_command_complete(id); - break; - - case GPCMD_MECHANISM_STATUS: - cdrom_set_phase(id, SCSI_PHASE_DATA_IN); - len = (cdb[7] << 16) | (cdb[8] << 8) | cdb[9]; - - cdrom_buf_alloc(id, 8); - - cdrom_set_buf_len(id, BufLen, &len); - - memset(cdbufferb, 0, 8); - cdbufferb[5] = 1; - - cdrom_data_command_finish(id, 8, 8, len, 0); - break; - - case GPCMD_READ_TOC_PMA_ATIP: - dev->toctimes++; - - cdrom_set_phase(id, SCSI_PHASE_DATA_IN); - - max_len = cdb[7]; - max_len <<= 8; - max_len |= cdb[8]; - - cdrom_buf_alloc(id, 65536); - - if (cdrom_drives[id].handler->pass_through) { - ret = cdrom_pass_through(id, &len, dev->current_cdb, cdbufferb); - if (!ret) { - cdrom_sense_key = cdrom_asc = cdrom_ascq = 0; - goto cdrom_readtoc_fallback; - } - alloc_length = cdbufferb[0]; - alloc_length <<= 8; - alloc_length |= cdbufferb[1]; - alloc_length += 2; - len = MIN(alloc_length, len); - - cdrom_set_buf_len(id, BufLen, &len); - } else { -cdrom_readtoc_fallback: - toc_format = cdb[2] & 0xf; - - if (toc_format == 0) - toc_format = (cdb[9] >> 6) & 3; - - switch (toc_format) { - case 0: /*Normal*/ - len = cdrom_drives[id].handler->readtoc(id, cdbufferb, cdb[6], msf, max_len, 0); - break; - case 1: /*Multi session*/ - len = cdrom_drives[id].handler->readtoc_session(id, cdbufferb, msf, max_len); - cdbufferb[0] = 0; cdbufferb[1] = 0xA; - break; - case 2: /*Raw*/ - len = cdrom_drives[id].handler->readtoc_raw(id, cdbufferb, max_len); - break; - default: - cdrom_invalid_field(id); - cdrom_buf_free(id); - return; - } - } - - if (len > max_len) { - len = max_len; - - cdbufferb[0] = ((len - 2) >> 8) & 0xff; - cdbufferb[1] = (len - 2) & 0xff; - } - - cdrom_set_buf_len(id, BufLen, &len); - - if (len >= 8) { - cdrom_log("CD-ROM %i: TOC: %02X %02X %02X %02X %02X %02X %02X %02X\n", id, - cdbufferb[0], cdbufferb[1], cdbufferb[2], cdbufferb[3], - cdbufferb[4], cdbufferb[5], cdbufferb[6], cdbufferb[7]); - } - - if (len >= 16) { - cdrom_log(" %02X %02X %02X %02X %02X %02X %02X %02X\n", - cdbufferb[8], cdbufferb[9], cdbufferb[10], cdbufferb[11], - cdbufferb[12], cdbufferb[13], cdbufferb[14], cdbufferb[15]); - } - - if (len >= 24) { - cdrom_log(" %02X %02X %02X %02X %02X %02X %02X %02X\n", - cdbufferb[16], cdbufferb[17], cdbufferb[18], cdbufferb[19], - cdbufferb[20], cdbufferb[21], cdbufferb[22], cdbufferb[23]); - } - - if (len >= 32) { - cdrom_log(" %02X %02X %02X %02X %02X %02X %02X %02X\n", - cdbufferb[24], cdbufferb[25], cdbufferb[26], cdbufferb[27], - cdbufferb[28], cdbufferb[29], cdbufferb[30], cdbufferb[31]); - } - - if (len >= 36) { - cdrom_log(" %02X %02X %02X %02X\n", - cdbufferb[32], cdbufferb[33], cdbufferb[34], cdbufferb[35]); - } - - cdrom_data_command_finish(id, len, len, len, 0); - /* cdrom_log("CD-ROM %i: READ_TOC_PMA_ATIP format %02X, length %i (%i)\n", id, toc_format, ide->cylinder, cdbufferb[1]); */ - return; - - case GPCMD_READ_CD_OLD: - dev->current_cdb[0] = 0xbe; /* IMPORTANT: Convert the command to new read CD for pass through purposes. */ - case GPCMD_READ_6: - case GPCMD_READ_10: - case GPCMD_READ_12: - case GPCMD_READ_CD: - case GPCMD_READ_CD_MSF: - cdrom_set_phase(id, SCSI_PHASE_DATA_IN); - alloc_length = 2048; - - switch(cdb[0]) { - case GPCMD_READ_6: - dev->sector_len = cdb[4]; - dev->sector_pos = ((((uint32_t) cdb[1]) & 0x1f) << 16) | (((uint32_t) cdb[2]) << 8) | ((uint32_t) cdb[3]); - msf = 0; - break; - case GPCMD_READ_10: - dev->sector_len = (cdb[7] << 8) | cdb[8]; - dev->sector_pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; - cdrom_log("CD-ROM %i: Length: %i, LBA: %i\n", id, dev->sector_len, dev->sector_pos); - msf = 0; - break; - case GPCMD_READ_12: - dev->sector_len = (((uint32_t) cdb[6]) << 24) | (((uint32_t) cdb[7]) << 16) | (((uint32_t) cdb[8]) << 8) | ((uint32_t) cdb[9]); - dev->sector_pos = (((uint32_t) cdb[2]) << 24) | (((uint32_t) cdb[3]) << 16) | (((uint32_t) cdb[4]) << 8) | ((uint32_t) cdb[5]); - cdrom_log("CD-ROM %i: Length: %i, LBA: %i\n", id, dev->sector_len, dev->sector_pos); - msf = 0; - break; - case GPCMD_READ_CD_MSF: - /* cdrom_log("CD-ROM %i: Read CD MSF: Start MSF %02X%02X%02X End MSF %02X%02X%02X Flags %02X\n", id, cdb[3], cdb[4], cdb[5], cdb[6], cdb[7], cdb[8], cdb[9]); */ - alloc_length = 2856; - dev->sector_len = MSFtoLBA(cdb[6], cdb[7], cdb[8]); - dev->sector_pos = MSFtoLBA(cdb[3], cdb[4], cdb[5]); - - dev->sector_len -= dev->sector_pos; - dev->sector_len++; - msf = 1; - break; - case GPCMD_READ_CD_OLD: - case GPCMD_READ_CD: - /* cdrom_log("CD-ROM %i: Read CD: Start LBA %02X%02X%02X%02X Length %02X%02X%02X Flags %02X\n", id, cdb[2], cdb[3], cdb[4], cdb[5], cdb[6], cdb[7], cdb[8], cdb[9]); */ - alloc_length = 2856; - dev->sector_len = (cdb[6] << 16) | (cdb[7] << 8) | cdb[8]; - dev->sector_pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; - - msf = 0; - break; - } - - dev->seek_diff = ABS((int) (pos - dev->seek_pos)); - dev->seek_pos = dev->sector_pos; - - if (!dev->sector_len) { - cdrom_set_phase(id, SCSI_PHASE_STATUS); - /* cdrom_log("CD-ROM %i: All done - callback set\n", id); */ - dev->packet_status = CDROM_PHASE_COMPLETE; - dev->callback = 20LL * CDROM_TIME; - cdrom_set_callback(id); + switch(cdb[0]) { + case GPCMD_READ_6: + dev->sector_len = cdb[4]; + dev->sector_pos = ((((uint32_t) cdb[1]) & 0x1f) << 16) | (((uint32_t) cdb[2]) << 8) | ((uint32_t) cdb[3]); + msf = 0; break; - } + case GPCMD_READ_10: + dev->sector_len = (cdb[7] << 8) | cdb[8]; + dev->sector_pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; + DEBUG("CD-ROM %i: Length: %i, LBA: %i\n", dev->id, dev->sector_len, dev->sector_pos); + msf = 0; + break; + case GPCMD_READ_12: + dev->sector_len = (((uint32_t) cdb[6]) << 24) | (((uint32_t) cdb[7]) << 16) | (((uint32_t) cdb[8]) << 8) | ((uint32_t) cdb[9]); + dev->sector_pos = (((uint32_t) cdb[2]) << 24) | (((uint32_t) cdb[3]) << 16) | (((uint32_t) cdb[4]) << 8) | ((uint32_t) cdb[5]); + DEBUG("CD-ROM %i: Length: %i, LBA: %i\n", dev->id, dev->sector_len, dev->sector_pos); + msf = 0; + break; + case GPCMD_READ_CD_MSF: + alloc_length = 2856; + dev->sector_len = MSFtoLBA(cdb[6], cdb[7], cdb[8]); + dev->sector_pos = MSFtoLBA(cdb[3], cdb[4], cdb[5]); - max_len = dev->sector_len; - dev->requested_blocks = max_len; /* If we're reading all blocks in one go for DMA, why not also for PIO, it should NOT - matter anyway, this step should be identical and only the way the read dat is - transferred to the host should be different. */ + dev->sector_len -= dev->sector_pos; + dev->sector_len++; + msf = 1; + break; + case GPCMD_READ_CD_OLD: + case GPCMD_READ_CD: + alloc_length = 2856; + dev->sector_len = (cdb[6] << 16) | (cdb[7] << 8) | cdb[8]; + dev->sector_pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; - dev->packet_len = max_len * alloc_length; - cdrom_buf_alloc(id, dev->packet_len); + msf = 0; + break; + } - ret = cdrom_read_blocks(id, &alloc_length, 1); - if (ret <= 0) { - cdrom_buf_free(id); - return; - } + dev->seek_diff = ABS((int) (pos - dev->seek_pos)); + dev->seek_pos = dev->sector_pos; - dev->requested_blocks = max_len; - dev->packet_len = alloc_length; + if (!dev->sector_len) { + cdrom_set_phase(dev, SCSI_PHASE_STATUS); + /* DEBUG("CD-ROM %i: All done - callback set\n", dev->id); */ + dev->packet_status = CDROM_PHASE_COMPLETE; + dev->callback = 20LL * CDROM_TIME; + cdrom_set_callback(dev); + break; + } - cdrom_set_buf_len(id, BufLen, &dev->packet_len); + max_len = dev->sector_len; + dev->requested_blocks = max_len; /* If we're reading all blocks in one go for DMA, why not also for PIO, it should NOT + matter anyway, this step should be identical and only the way the read dat is + transferred to the host should be different. */ - cdrom_data_command_finish(id, alloc_length, alloc_length / dev->requested_blocks, alloc_length, 0); + dev->packet_len = max_len * alloc_length; + cdrom_buf_alloc(dev, dev->packet_len); - dev->all_blocks_total = dev->block_total; - if (dev->packet_status != CDROM_PHASE_COMPLETE) - ui_sb_icon_update(SB_CDROM | id, 1); - else - ui_sb_icon_update(SB_CDROM | id, 0); + ret = cdrom_read_blocks(dev, &alloc_length, 1); + if (ret <= 0) { + cdrom_buf_free(dev); return; + } - case GPCMD_READ_HEADER: - cdrom_set_phase(id, SCSI_PHASE_DATA_IN); + dev->requested_blocks = max_len; + dev->packet_len = alloc_length; - alloc_length = ((cdb[7] << 8) | cdb[8]); - cdrom_buf_alloc(id, 8); + cdrom_set_buf_len(dev, BufLen, (int32_t *) &dev->packet_len); - if (cdrom_drives[id].handler->pass_through) { - ret = cdrom_pass_through(id, &len, dev->current_cdb, cdbufferb); - if (!ret) { - cdrom_buf_free(id); - return; - } - } else { - dev->sector_len = 1; - dev->sector_pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4]<<8) | cdb[5]; - if (msf) - real_pos = cdrom_lba_to_msf_accurate(dev->sector_pos); - else - real_pos = dev->sector_pos; - cdbufferb[0] = 1; /*2048 bytes user data*/ - cdbufferb[1] = cdbufferb[2] = cdbufferb[3] = 0; - cdbufferb[4] = (real_pos >> 24); - cdbufferb[5] = ((real_pos >> 16) & 0xff); - cdbufferb[6] = ((real_pos >> 8) & 0xff); - cdbufferb[7] = real_pos & 0xff; + cdrom_data_command_finish(dev, alloc_length, alloc_length / dev->requested_blocks, + alloc_length, 0); - len = 8; - } + dev->all_blocks_total = dev->block_total; + if (dev->packet_status != CDROM_PHASE_COMPLETE) + ui_sb_icon_update(SB_CDROM | dev->id, 1); + else + ui_sb_icon_update(SB_CDROM | dev->id, 0); + return; + case GPCMD_READ_HEADER: + cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); + + alloc_length = ((cdb[7] << 8) | cdb[8]); + cdrom_buf_alloc(dev, 8); + + dev->sector_len = 1; + dev->sector_pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4]<<8) | cdb[5]; + if (msf) + real_pos = cdrom_lba_to_msf_accurate(dev->sector_pos); + else + real_pos = dev->sector_pos; + cdbufferb[0] = 1; /*2048 bytes user data*/ + cdbufferb[1] = cdbufferb[2] = cdbufferb[3] = 0; + cdbufferb[4] = (real_pos >> 24); + cdbufferb[5] = ((real_pos >> 16) & 0xff); + cdbufferb[6] = ((real_pos >> 8) & 0xff); + cdbufferb[7] = real_pos & 0xff; + + len = 8; + len = MIN(len, alloc_length); + + cdrom_set_buf_len(dev, BufLen, &len); + + cdrom_data_command_finish(dev, len, len, len, 0); + return; + + case GPCMD_MODE_SENSE_6: + case GPCMD_MODE_SENSE_10: + cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); + + if (dev->drv->bus_type == CDROM_BUS_SCSI) + block_desc = ((cdb[1] >> 3) & 1) ? 0 : 1; + else + block_desc = 0; + + if (cdb[0] == GPCMD_MODE_SENSE_6) { + len = cdb[4]; + cdrom_buf_alloc(dev, 256); + } else { + len = (cdb[8] | (cdb[7] << 8)); + cdrom_buf_alloc(dev, 65536); + } + + dev->current_page_code = cdb[2] & 0x3F; + + if (!(cdrom_mode_sense_page_flags & (1LL << dev->current_page_code))) { + cdrom_invalid_field(dev); + cdrom_buf_free(dev); + return; + } + + memset(cdbufferb, 0, len); + alloc_length = len; + + if (cdb[0] == GPCMD_MODE_SENSE_6) { + len = cdrom_mode_sense(dev, cdbufferb, 4, cdb[2], block_desc); len = MIN(len, alloc_length); + cdbufferb[0] = len - 1; + cdbufferb[1] = dev->handler->media_type_id(dev->id); + if (block_desc) + cdbufferb[3] = 8; + } else { + len = cdrom_mode_sense(dev, cdbufferb, 8, cdb[2], block_desc); + len = MIN(len, alloc_length); + cdbufferb[0]=(len - 2) >> 8; + cdbufferb[1]=(len - 2) & 255; + cdbufferb[2] = dev->handler->media_type_id(dev->id); + if (block_desc) { + cdbufferb[6] = 0; + cdbufferb[7] = 8; + } + } - cdrom_set_buf_len(id, BufLen, &len); + cdrom_set_buf_len(dev, BufLen, &len); - cdrom_data_command_finish(id, len, len, len, 0); + DEBUG("CD-ROM %i: Reading mode page: %02X...\n", dev->id, cdb[2]); + + cdrom_data_command_finish(dev, len, len, alloc_length, 0); + return; + + case GPCMD_MODE_SELECT_6: + case GPCMD_MODE_SELECT_10: + cdrom_set_phase(dev, SCSI_PHASE_DATA_OUT); + + if (cdb[0] == GPCMD_MODE_SELECT_6) { + len = cdb[4]; + cdrom_buf_alloc(dev, 256); + } else { + len = (cdb[7] << 8) | cdb[8]; + cdrom_buf_alloc(dev, 65536); + } + + cdrom_set_buf_len(dev, BufLen, &len); + + dev->total_length = len; + dev->do_page_save = cdb[1] & 1; + + dev->current_page_pos = 0; + + cdrom_data_command_finish(dev, len, len, len, 1); + return; + + case GPCMD_GET_CONFIGURATION: + cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); + + /* XXX: could result in alignment problems in some architectures */ + feature = (cdb[2] << 8) | cdb[3]; + max_len = (cdb[7] << 8) | cdb[8]; + + /* only feature 0 is supported */ + if ((cdb[2] != 0) || (cdb[3] > 2)) { + cdrom_invalid_field(dev); + cdrom_buf_free(dev); return; + } - case GPCMD_MODE_SENSE_6: - case GPCMD_MODE_SENSE_10: - cdrom_set_phase(id, SCSI_PHASE_DATA_IN); - - if (cdrom_drives[id].bus_type == CDROM_BUS_SCSI) - block_desc = ((cdb[1] >> 3) & 1) ? 0 : 1; - else - block_desc = 0; + cdrom_buf_alloc(dev, 65536); + memset(cdbufferb, 0, max_len); - if (cdb[0] == GPCMD_MODE_SENSE_6) { - len = cdb[4]; - cdrom_buf_alloc(id, 256); + alloc_length = 0; + b = cdbufferb; + + /* + * the number of sectors from the media tells us which profile + * to use as current. 0 means there is no media + */ + if (dev->handler->ready(dev->id)) { + len = dev->handler->size(dev->id); + if (len > CD_MAX_SECTORS) { + b[6] = (MMC_PROFILE_DVD_ROM >> 8) & 0xff; + b[7] = MMC_PROFILE_DVD_ROM & 0xff; + ret = 1; } else { - len = (cdb[8] | (cdb[7] << 8)); - cdrom_buf_alloc(id, 65536); + b[6] = (MMC_PROFILE_CD_ROM >> 8) & 0xff; + b[7] = MMC_PROFILE_CD_ROM & 0xff; + ret = 0; } + } else + ret = 2; - dev->current_page_code = cdb[2] & 0x3F; + alloc_length = 8; + b += 8; - if (!(cdrom_mode_sense_page_flags & (1LL << dev->current_page_code))) { - cdrom_invalid_field(id); - cdrom_buf_free(id); - return; - } - - memset(cdbufferb, 0, len); - alloc_length = len; + if ((feature == 0) || ((cdb[1] & 3) < 2)) { + b[2] = (0 << 2) | 0x02 | 0x01; /* persistent and current */ + b[3] = 8; - if (cdb[0] == GPCMD_MODE_SENSE_6) { - len = cdrom_mode_sense(id, cdbufferb, 4, cdb[2], block_desc); - len = MIN(len, alloc_length); - cdbufferb[0] = len - 1; - cdbufferb[1] = cdrom_drives[id].handler->media_type_id(id); - if (block_desc) - cdbufferb[3] = 8; - } else { - len = cdrom_mode_sense(id, cdbufferb, 8, cdb[2], block_desc); - len = MIN(len, alloc_length); - cdbufferb[0]=(len - 2) >> 8; - cdbufferb[1]=(len - 2) & 255; - cdbufferb[2] = cdrom_drives[id].handler->media_type_id(id); - if (block_desc) { - cdbufferb[6] = 0; - cdbufferb[7] = 8; - } - } + alloc_length += 4; + b += 4; - cdrom_set_buf_len(id, BufLen, &len); + for (i = 0; i < 2; i++) { + b[0] = (profiles[i] >> 8) & 0xff; + b[1] = profiles[i] & 0xff; - cdrom_log("CD-ROM %i: Reading mode page: %02X...\n", id, cdb[2]); - - cdrom_data_command_finish(id, len, len, alloc_length, 0); - return; - - case GPCMD_MODE_SELECT_6: - case GPCMD_MODE_SELECT_10: - cdrom_set_phase(id, SCSI_PHASE_DATA_OUT); - - if (cdb[0] == GPCMD_MODE_SELECT_6) { - len = cdb[4]; - cdrom_buf_alloc(id, 256); - } else { - len = (cdb[7] << 8) | cdb[8]; - cdrom_buf_alloc(id, 65536); - } - - cdrom_set_buf_len(id, BufLen, &len); - - dev->total_length = len; - dev->do_page_save = cdb[1] & 1; - - dev->current_page_pos = 0; - - cdrom_data_command_finish(id, len, len, len, 1); - return; - - case GPCMD_GET_CONFIGURATION: - cdrom_set_phase(id, SCSI_PHASE_DATA_IN); - - /* XXX: could result in alignment problems in some architectures */ - feature = (cdb[2] << 8) | cdb[3]; - max_len = (cdb[7] << 8) | cdb[8]; - - /* only feature 0 is supported */ - if ((cdb[2] != 0) || (cdb[3] > 2)) { - cdrom_invalid_field(id); - cdrom_buf_free(id); - return; - } - - cdrom_buf_alloc(id, 65536); - memset(cdbufferb, 0, max_len); - - alloc_length = 0; - b = cdbufferb; - - /* - * the number of sectors from the media tells us which profile - * to use as current. 0 means there is no media - */ - if (cdrom_drives[id].handler->ready(id)) { - len = cdrom_drives[id].handler->size(id); - if (len > CD_MAX_SECTORS) { - b[6] = (MMC_PROFILE_DVD_ROM >> 8) & 0xff; - b[7] = MMC_PROFILE_DVD_ROM & 0xff; - ret = 1; - } else { - b[6] = (MMC_PROFILE_CD_ROM >> 8) & 0xff; - b[7] = MMC_PROFILE_CD_ROM & 0xff; - ret = 0; - } - } else { - ret = 2; - } - - alloc_length = 8; - b += 8; - - if ((feature == 0) || ((cdb[1] & 3) < 2)) { - b[2] = (0 << 2) | 0x02 | 0x01; /* persistent and current */ - b[3] = 8; + if (ret == i) + b[2] |= 1; alloc_length += 4; b += 4; - - for (i = 0; i < 2; i++) { - b[0] = (profiles[i] >> 8) & 0xff; - b[1] = profiles[i] & 0xff; - - if (ret == i) - b[2] |= 1; - - alloc_length += 4; - b += 4; - } } - if ((feature == 1) || ((cdb[1] & 3) < 2)) { - b[1] = 1; - b[2] = (2 << 2) | 0x02 | 0x01; /* persistent and current */ - b[3] = 8; + } + if ((feature == 1) || ((cdb[1] & 3) < 2)) { + b[1] = 1; + b[2] = (2 << 2) | 0x02 | 0x01; /* persistent and current */ + b[3] = 8; - if (cdrom_drives[id].bus_type == CDROM_BUS_SCSI) - b[7] = 1; - else - b[7] = 2; - b[8] = 1; + if (dev->drv->bus_type == CDROM_BUS_SCSI) + b[7] = 1; + else + b[7] = 2; + b[8] = 1; - alloc_length += 12; - b += 12; - } - if ((feature == 2) || ((cdb[1] & 3) < 2)) { - b[1] = 2; - b[2] = (1 << 2) | 0x02 | 0x01; /* persistent and current */ - b[3] = 4; + alloc_length += 12; + b += 12; + } + if ((feature == 2) || ((cdb[1] & 3) < 2)) { + b[1] = 2; + b[2] = (1 << 2) | 0x02 | 0x01; /* persistent and current */ + b[3] = 4; - b[4] = 2; + b[4] = 2; - alloc_length += 8; - b += 8; - } + alloc_length += 8; + b += 8; + } - cdbufferb[0] = ((alloc_length - 4) >> 24) & 0xff; - cdbufferb[1] = ((alloc_length - 4) >> 16) & 0xff; - cdbufferb[2] = ((alloc_length - 4) >> 8) & 0xff; - cdbufferb[3] = (alloc_length - 4) & 0xff; + cdbufferb[0] = ((alloc_length - 4) >> 24) & 0xff; + cdbufferb[1] = ((alloc_length - 4) >> 16) & 0xff; + cdbufferb[2] = ((alloc_length - 4) >> 8) & 0xff; + cdbufferb[3] = (alloc_length - 4) & 0xff; - alloc_length = MIN(alloc_length, max_len); + alloc_length = MIN(alloc_length, max_len); - cdrom_set_buf_len(id, BufLen, &alloc_length); + cdrom_set_buf_len(dev, BufLen, &alloc_length); - cdrom_data_command_finish(id, alloc_length, alloc_length, alloc_length, 0); - break; + cdrom_data_command_finish(dev, alloc_length, alloc_length, alloc_length, 0); + break; - case GPCMD_GET_EVENT_STATUS_NOTIFICATION: - cdrom_set_phase(id, SCSI_PHASE_DATA_IN); + case GPCMD_GET_EVENT_STATUS_NOTIFICATION: + cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); - cdrom_buf_alloc(id, 8 + sizeof(gesn_event_header_t)); + cdrom_buf_alloc(dev, 8 + sizeof(gesn_event_header_t)); + + gesn_cdb = (gesn_cdb_t *) cdb; + gesn_event_header = (gesn_event_header_t *) cdbufferb; + + /* It is fine by the MMC spec to not support async mode operations. */ + if (!(gesn_cdb->polled & 0x01)) { + /* asynchronous mode */ + /* Only polling is supported, asynchronous mode is not. */ + cdrom_invalid_field(dev); + cdrom_buf_free(dev); + return; + } + + /* + * These are the supported events. + * + * We currently only support requests of the 'media' type. + * Notification class requests and supported event classes are bitmasks, + * but they are built from the same values as the "notification class" + * field. + */ + gesn_event_header->supported_events = 1 << GESN_MEDIA; + + /* + * We use |= below to set the class field; other bits in this byte + * are reserved now but this is useful to do if we have to use the + * reserved fields later. + */ + gesn_event_header->notification_class = 0; + + /* + * Responses to requests are to be based on request priority. The + * notification_class_request_type enum above specifies the + * priority: upper elements are higher prio than lower ones. + */ + if (gesn_cdb->opc_class & (1 << GESN_MEDIA)) { + gesn_event_header->notification_class |= GESN_MEDIA; + + cdbufferb[4] = dev->media_status; /* Bits 7-4 = Reserved, Bits 4-1 = Media Status */ + cdbufferb[5] = 1; /* Power Status (1 = Active) */ + cdbufferb[6] = 0; + cdbufferb[7] = 0; + used_len = 8; + } else { + gesn_event_header->notification_class = 0x80; /* No event available */ + used_len = sizeof(*gesn_event_header); + } + gesn_event_header->len = used_len - sizeof(*gesn_event_header); + + memcpy(cdbufferb, gesn_event_header, 4); + + cdrom_set_buf_len(dev, BufLen, &used_len); + + cdrom_data_command_finish(dev, used_len, used_len, used_len, 0); + break; + + case GPCMD_READ_DISC_INFORMATION: + cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); - gesn_cdb = (void *) cdb; - gesn_event_header = (void *) cdbufferb; + max_len = cdb[7]; + max_len <<= 8; + max_len |= cdb[8]; - /* It is fine by the MMC spec to not support async mode operations. */ - if (!(gesn_cdb->polled & 0x01)) { - /* asynchronous mode */ - /* Only polling is supported, asynchronous mode is not. */ - cdrom_invalid_field(id); - cdrom_buf_free(id); + cdrom_buf_alloc(dev, 65536); + + memset(cdbufferb, 0, 34); + memset(cdbufferb, 1, 9); + cdbufferb[0] = 0; + cdbufferb[1] = 32; + cdbufferb[2] = 0xe; /* last session complete, disc finalized */ + cdbufferb[7] = 0x20; /* unrestricted use */ + cdbufferb[8] = 0x00; /* CD-ROM */ + + len=34; + len = MIN(len, max_len); + + cdrom_set_buf_len(dev, BufLen, &len); + + cdrom_data_command_finish(dev, len, len, len, 0); + break; + + case GPCMD_READ_TRACK_INFORMATION: + cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); + + max_len = cdb[7]; + max_len <<= 8; + max_len |= cdb[8]; + + cdrom_buf_alloc(dev, 65536); + + track = ((uint32_t) cdb[2]) << 24; + track |= ((uint32_t) cdb[3]) << 16; + track |= ((uint32_t) cdb[4]) << 8; + track |= (uint32_t) cdb[5]; + + if (((cdb[1] & 0x03) != 1) || (track != 1)) { + cdrom_invalid_field(dev); + cdrom_buf_free(dev); + return; + } + + len = 36; + + memset(cdbufferb, 0, 36); + cdbufferb[0] = 0; + cdbufferb[1] = 34; + cdbufferb[2] = 1; /* track number (LSB) */ + cdbufferb[3] = 1; /* session number (LSB) */ + cdbufferb[5] = (0 << 5) | (0 << 4) | (4 << 0); /* not damaged, primary copy, data track */ + cdbufferb[6] = (0 << 7) | (0 << 6) | (0 << 5) | (0 << 6) | (1 << 0); /* not reserved track, not blank, not packet writing, not fixed packet, data mode 1 */ + cdbufferb[7] = (0 << 1) | (0 << 0); /* last recorded address not valid, next recordable address not valid */ + cdbufferb[24] = (dev->handler->size(dev->id) >> 24) & 0xff; /* track size */ + cdbufferb[25] = (dev->handler->size(dev->id) >> 16) & 0xff; /* track size */ + cdbufferb[26] = (dev->handler->size(dev->id) >> 8) & 0xff; /* track size */ + cdbufferb[27] = dev->handler->size(dev->id) & 0xff; /* track size */ + + if (len > max_len) { + len = max_len; + cdbufferb[0] = ((max_len - 2) >> 8) & 0xff; + cdbufferb[1] = (max_len - 2) & 0xff; + } + + cdrom_set_buf_len(dev, BufLen, &len); + + cdrom_data_command_finish(dev, len, len, max_len, 0); + break; + + case GPCMD_PLAY_AUDIO_10: + case GPCMD_PLAY_AUDIO_12: + case GPCMD_PLAY_AUDIO_MSF: + case GPCMD_PLAY_AUDIO_TRACK_INDEX: + cdrom_set_phase(dev, SCSI_PHASE_STATUS); + + switch(cdb[0]) { + case GPCMD_PLAY_AUDIO_10: + msf = 0; + pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; + len = (cdb[7] << 8) | cdb[8]; + break; + case GPCMD_PLAY_AUDIO_12: + msf = 0; + pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; + len = (cdb[6] << 24) | (cdb[7] << 16) | (cdb[8] << 8) | cdb[9]; + break; + case GPCMD_PLAY_AUDIO_MSF: + /* This is apparently deprecated in the ATAPI spec, and apparently + has been since 1995 (!). Hence I'm having to guess most of it. */ + msf = 1; + pos = (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; + len = (cdb[6] << 16) | (cdb[7] << 8) | cdb[8]; + break; + case GPCMD_PLAY_AUDIO_TRACK_INDEX: + msf = 2; + pos = (cdb[4] << 8) | cdb[5]; + len = (cdb[7] << 8) | cdb[8]; + break; + } + + if ((dev->drv->host_drive < 1) || (dev->cd_status <= CD_STATUS_DATA_ONLY)) { + cdrom_illegal_mode(dev); + break; + } + + if (dev->handler->playaudio) + ret = dev->handler->playaudio(dev->id, pos, len, msf); + else + ret = 0; + + if (ret) + cdrom_command_complete(dev); + else + cdrom_illegal_mode(dev); + break; + + case GPCMD_READ_SUBCHANNEL: + cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); + + max_len = cdb[7]; + max_len <<= 8; + max_len |= cdb[8]; + msf = (cdb[1] >> 1) & 1; + + cdrom_buf_alloc(dev, 32); + + DEBUG("CD-ROM %i: Getting page %i (%s)\n", dev->id, cdb[3], msf ? "MSF" : "LBA"); + + if (cdb[3] > 3) { + /* DEBUG("CD-ROM %i: Read subchannel check condition %02X\n", dev->id, + cdb[3]); */ + cdrom_invalid_field(dev); + cdrom_buf_free(dev); + return; + } + + switch(cdb[3]) { + case 0: + alloc_length = 4; + break; + case 1: + alloc_length = 16; + break; + default: + alloc_length = 24; + break; + } + + memset(cdbufferb, 0, 24); + pos = 0; + cdbufferb[pos++] = 0; + cdbufferb[pos++] = 0; /*Audio status*/ + cdbufferb[pos++] = 0; cdbufferb[pos++] = 0; /*Subchannel length*/ + cdbufferb[pos++] = cdb[3] & 3; /*Format code*/ + if (cdb[3] == 1) { + cdbufferb[1] = dev->handler->getcurrentsubchannel(dev->id, &cdbufferb[5], msf); + switch(dev->cd_status) { + case CD_STATUS_PLAYING: + cdbufferb[1] = 0x11; + break; + case CD_STATUS_PAUSED: + cdbufferb[1] = 0x12; + break; + case CD_STATUS_DATA_ONLY: + cdbufferb[1] = 0x15; + break; + default: + cdbufferb[1] = 0x13; + break; + } + } + + if (!(cdb[2] & 0x40) || (cdb[3] == 0)) + len = 4; + else + len = alloc_length; + + len = MIN(len, max_len); + cdrom_set_buf_len(dev, BufLen, &len); + + DEBUG("CD-ROM %i: Read subchannel:", dev->id); + for (i = 0; i < 32; i += 8) { + DEBUG("[%02X] %02X %02X %02X %02X %02X %02X %02X %02X\n", i, + cdbufferb[i], cdbufferb[i + 1], cdbufferb[i + 2], cdbufferb[i + 3], + cdbufferb[i + 4], cdbufferb[i + 5], cdbufferb[i + 6], cdbufferb[i + 7]); + } + + cdrom_data_command_finish(dev, len, len, len, 0); + break; + + case GPCMD_READ_DVD_STRUCTURE: + cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); + + alloc_length = (((uint32_t) cdb[8]) << 8) | ((uint32_t) cdb[9]); + + cdrom_buf_alloc(dev, alloc_length); + + len = dev->handler->size(dev->id); + + if ((cdb[7] < 0xc0) && (len <= CD_MAX_SECTORS)) { + cdrom_incompatible_format(dev); + cdrom_buf_free(dev); + return; + } + + memset(cdbufferb, 0, alloc_length); + + if ((cdb[7] <= 0x7f) || (cdb[7] == 0xff)) { + if (cdb[1] == 0) { + ret = cdrom_read_dvd_structure(dev, format, cdb, cdbufferb); + if (ret) { + cdrom_set_buf_len(dev, BufLen, &alloc_length); + cdrom_data_command_finish(dev, alloc_length, alloc_length, + len, 0); + } else + cdrom_buf_free(dev); return; } + } else { + cdrom_invalid_field(dev); + cdrom_buf_free(dev); + return; + } + break; - /* polling mode operation */ + case GPCMD_START_STOP_UNIT: + cdrom_set_phase(dev, SCSI_PHASE_STATUS); - /* - * These are the supported events. - * - * We currently only support requests of the 'media' type. - * Notification class requests and supported event classes are bitmasks, - * but they are built from the same values as the "notification class" - * field. - */ - gesn_event_header->supported_events = 1 << GESN_MEDIA; - - /* - * We use |= below to set the class field; other bits in this byte - * are reserved now but this is useful to do if we have to use the - * reserved fields later. - */ - gesn_event_header->notification_class = 0; - - /* - * Responses to requests are to be based on request priority. The - * notification_class_request_type enum above specifies the - * priority: upper elements are higher prio than lower ones. - */ - if (gesn_cdb->class & (1 << GESN_MEDIA)) { - gesn_event_header->notification_class |= GESN_MEDIA; - - cdbufferb[4] = dev->media_status; /* Bits 7-4 = Reserved, Bits 4-1 = Media Status */ - cdbufferb[5] = 1; /* Power Status (1 = Active) */ - cdbufferb[6] = 0; - cdbufferb[7] = 0; - used_len = 8; - } else { - gesn_event_header->notification_class = 0x80; /* No event available */ - used_len = sizeof(*gesn_event_header); - } - gesn_event_header->len = used_len - sizeof(*gesn_event_header); - - memcpy(cdbufferb, gesn_event_header, 4); - - cdrom_set_buf_len(id, BufLen, &used_len); - - cdrom_data_command_finish(id, used_len, used_len, used_len, 0); - break; - - case GPCMD_READ_DISC_INFORMATION: - cdrom_set_phase(id, SCSI_PHASE_DATA_IN); - - max_len = cdb[7]; - max_len <<= 8; - max_len |= cdb[8]; - - cdrom_buf_alloc(id, 65536); - - if (cdrom_drives[id].handler->pass_through) { - ret = cdrom_pass_through(id, &len, dev->current_cdb, cdbufferb); - if (!ret) { - cdrom_buf_free(id); - return; - } - alloc_length = cdbufferb[0]; - alloc_length <<= 8; - alloc_length |= cdbufferb[1]; - alloc_length += 2; - len = alloc_length; - } else { - memset(cdbufferb, 0, 34); - memset(cdbufferb, 1, 9); - cdbufferb[0] = 0; - cdbufferb[1] = 32; - cdbufferb[2] = 0xe; /* last session complete, disc finalized */ - cdbufferb[7] = 0x20; /* unrestricted use */ - cdbufferb[8] = 0x00; /* CD-ROM */ - len=34; - } - - len = MIN(len, max_len); - - cdrom_set_buf_len(id, BufLen, &len); - - cdrom_data_command_finish(id, len, len, len, 0); - break; - - case GPCMD_READ_TRACK_INFORMATION: - cdrom_set_phase(id, SCSI_PHASE_DATA_IN); - - max_len = cdb[7]; - max_len <<= 8; - max_len |= cdb[8]; - - cdrom_buf_alloc(id, 65536); - - track = ((uint32_t) cdb[2]) << 24; - track |= ((uint32_t) cdb[3]) << 16; - track |= ((uint32_t) cdb[4]) << 8; - track |= (uint32_t) cdb[5]; - - if (cdrom_drives[id].handler->pass_through) { - ret = cdrom_pass_through(id, &len, dev->current_cdb, cdbufferb); - if (!ret) { - cdrom_buf_free(id); - return; - } - alloc_length = cdbufferb[0]; - alloc_length <<= 8; - alloc_length |= cdbufferb[1]; - alloc_length += 2; - len = MIN(len, alloc_length); - } else { - if (((cdb[1] & 0x03) != 1) || (track != 1)) { - cdrom_invalid_field(id); - cdrom_buf_free(id); - return; - } - - len = 36; - - memset(cdbufferb, 0, 36); - cdbufferb[0] = 0; - cdbufferb[1] = 34; - cdbufferb[2] = 1; /* track number (LSB) */ - cdbufferb[3] = 1; /* session number (LSB) */ - cdbufferb[5] = (0 << 5) | (0 << 4) | (4 << 0); /* not damaged, primary copy, data track */ - cdbufferb[6] = (0 << 7) | (0 << 6) | (0 << 5) | (0 << 6) | (1 << 0); /* not reserved track, not blank, not packet writing, not fixed packet, data mode 1 */ - cdbufferb[7] = (0 << 1) | (0 << 0); /* last recorded address not valid, next recordable address not valid */ - cdbufferb[24] = (cdrom_drives[id].handler->size(id) >> 24) & 0xff; /* track size */ - cdbufferb[25] = (cdrom_drives[id].handler->size(id) >> 16) & 0xff; /* track size */ - cdbufferb[26] = (cdrom_drives[id].handler->size(id) >> 8) & 0xff; /* track size */ - cdbufferb[27] = cdrom_drives[id].handler->size(id) & 0xff; /* track size */ - - if (len > max_len) { - len = max_len; - cdbufferb[0] = ((max_len - 2) >> 8) & 0xff; - cdbufferb[1] = (max_len - 2) & 0xff; - } - } - - cdrom_set_buf_len(id, BufLen, &len); - - cdrom_data_command_finish(id, len, len, max_len, 0); - break; - - case GPCMD_PLAY_AUDIO_10: - case GPCMD_PLAY_AUDIO_12: - case GPCMD_PLAY_AUDIO_MSF: - case GPCMD_PLAY_AUDIO_TRACK_INDEX: - cdrom_set_phase(id, SCSI_PHASE_STATUS); - - switch(cdb[0]) { - case GPCMD_PLAY_AUDIO_10: - msf = 0; - pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; - len = (cdb[7] << 8) | cdb[8]; - break; - case GPCMD_PLAY_AUDIO_12: - msf = 0; - pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; - len = (cdb[6] << 24) | (cdb[7] << 16) | (cdb[8] << 8) | cdb[9]; - break; - case GPCMD_PLAY_AUDIO_MSF: - /* This is apparently deprecated in the ATAPI spec, and apparently - has been since 1995 (!). Hence I'm having to guess most of it. */ - msf = 1; - pos = (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; - len = (cdb[6] << 16) | (cdb[7] << 8) | cdb[8]; - break; - case GPCMD_PLAY_AUDIO_TRACK_INDEX: - msf = 2; - pos = (cdb[4] << 8) | cdb[5]; - len = (cdb[7] << 8) | cdb[8]; - break; - } - - if (!cdrom_drives[id].handler->is_track_audio) + switch(cdb[4] & 3) { + case 0: /* Stop the disc. */ + if (dev->handler->stop) + dev->handler->stop(dev->id); break; - - if ((cdrom_drives[id].host_drive < 1) || (dev->cd_status <= CD_STATUS_DATA_ONLY) || !cdrom_drives[id].handler->is_track_audio(id, pos, msf)) { - cdrom_illegal_mode(id); + case 1: /* Start the disc and read the TOC. */ + dev->handler->medium_changed(dev->id); /* This causes a TOC reload. */ break; - } - - if (cdrom_drives[id].handler->playaudio) - cdrom_drives[id].handler->playaudio(id, pos, len, msf); - else { - cdrom_illegal_mode(id); + case 2: /* Eject the disc if possible. */ + if (dev->handler->stop) + dev->handler->stop(dev->id); + ui_cdrom_eject(dev->id); break; - } + case 3: /* Load the disc (close tray). */ + ui_cdrom_reload(dev->id); + break; + } - cdrom_command_complete(id); - break; + cdrom_command_complete(dev); + break; - case GPCMD_READ_SUBCHANNEL: - cdrom_set_phase(id, SCSI_PHASE_DATA_IN); - - max_len = cdb[7]; - max_len <<= 8; - max_len |= cdb[8]; - msf = (cdb[1] >> 1) & 1; + case GPCMD_INQUIRY: + cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); - cdrom_buf_alloc(id, 32); + max_len = cdb[3]; + max_len <<= 8; + max_len |= cdb[4]; - cdrom_log("CD-ROM %i: Getting page %i (%s)\n", id, cdb[3], msf ? "MSF" : "LBA"); - if ((cdrom_drives[id].handler->pass_through) && (cdb[3] != 1)) { - ret = cdrom_pass_through(id, &len, dev->current_cdb, cdbufferb); - if (!ret) { - cdrom_buf_free(id); - return; - } - switch(dev->cd_status) { - case CD_STATUS_PLAYING: - cdbufferb[1] = 0x11; - break; - case CD_STATUS_PAUSED: - cdbufferb[1] = 0x12; - break; - case CD_STATUS_DATA_ONLY: - cdbufferb[1] = 0x15; - break; - default: - cdbufferb[1] = 0x13; - break; - } - switch(cdb[3]) { - case 0: - alloc_length = 4; - break; - case 1: - alloc_length = 16; - break; - default: - alloc_length = 24; - break; - } - if (!(cdb[2] & 0x40) || (cdb[3] == 0)) - len = 4; - else - len = alloc_length; - } else { - if (cdb[3] > 3) { - /* cdrom_log("CD-ROM %i: Read subchannel check condition %02X\n", id, cdb[3]); */ - cdrom_invalid_field(id); - cdrom_buf_free(id); - return; - } + cdrom_buf_alloc(dev, 65536); - switch(cdb[3]) { - case 0: - alloc_length = 4; - break; - case 1: - alloc_length = 16; - break; - default: - alloc_length = 24; - break; - } + if (cdb[1] & 1) { + preamble_len = 4; + size_idx = 3; - memset(cdbufferb, 0, 24); - pos = 0; - cdbufferb[pos++] = 0; - cdbufferb[pos++] = 0; /*Audio status*/ - cdbufferb[pos++] = 0; cdbufferb[pos++] = 0; /*Subchannel length*/ - cdbufferb[pos++] = cdb[3] & 3; /*Format code*/ - if (cdb[3] == 1) { - cdbufferb[1] = cdrom_drives[id].handler->getcurrentsubchannel(id, &cdbufferb[5], msf); - switch(dev->cd_status) { - case CD_STATUS_PLAYING: - cdbufferb[1] = 0x11; - break; - case CD_STATUS_PAUSED: - cdbufferb[1] = 0x12; - break; - case CD_STATUS_DATA_ONLY: - cdbufferb[1] = 0x15; - break; - default: - cdbufferb[1] = 0x13; - break; - } - } - if (!(cdb[2] & 0x40) || (cdb[3] == 0)) - len = 4; - else - len = alloc_length; - } + cdbufferb[idx++] = 05; + cdbufferb[idx++] = cdb[2]; + cdbufferb[idx++] = 0; - len = MIN(len, max_len); - cdrom_set_buf_len(id, BufLen, &len); + idx++; - cdrom_log("CD-ROM %i: Read subchannel:", id); - for (i = 0; i < 32; i += 8) { - cdrom_log("[%02X] %02X %02X %02X %02X %02X %02X %02X %02X\n", i, - cdbufferb[i], cdbufferb[i + 1], cdbufferb[i + 2], cdbufferb[i + 3], - cdbufferb[i + 4], cdbufferb[i + 5], cdbufferb[i + 6], cdbufferb[i + 7]); - } - - cdrom_data_command_finish(id, len, len, len, 0); - break; - - case GPCMD_READ_DVD_STRUCTURE: - cdrom_set_phase(id, SCSI_PHASE_DATA_IN); - - alloc_length = (((uint32_t) cdb[8]) << 8) | ((uint32_t) cdb[9]); - - cdrom_buf_alloc(id, alloc_length); - - if (cdrom_drives[id].handler->pass_through) { - ret = cdrom_pass_through(id, &len, dev->current_cdb, cdbufferb); - if (!ret) { - cdrom_buf_free(id); - return; - } else { - if (cdrom_drives[id].bus_type == CDROM_BUS_SCSI) { - if (*BufLen == -1) - *BufLen = len; - else { - *BufLen = MIN((int)len, *BufLen); - len = *BufLen; - } - } - } - } else { - len = cdrom_drives[id].handler->size(id); - - if (cdb[7] < 0xc0) { - if (len <= CD_MAX_SECTORS) { - cdrom_incompatible_format(id); - cdrom_buf_free(id); + switch (cdb[2]) { + case 0x00: + cdbufferb[idx++] = 0x00; + cdbufferb[idx++] = 0x83; + break; + case 0x83: + if (idx + 24 > max_len) { + cdrom_data_phase_error(dev); + cdrom_buf_free(dev); return; } - } - memset(cdbufferb, 0, alloc_length); + cdbufferb[idx++] = 0x02; + cdbufferb[idx++] = 0x00; + cdbufferb[idx++] = 0x00; + cdbufferb[idx++] = 20; + ide_padstr8(cdbufferb + idx, 20, "53R141"); /* Serial */ + idx += 20; - if (((cdb[7] >= 0x00) && (cdb[7] <= 0x7f)) || (cdb[7] == 0xff)) { - if (cdb[1] == 0) { - ret = cdrom_read_dvd_structure(id, format, cdb, cdbufferb); - - if (ret) { - cdrom_set_buf_len(id, BufLen, &alloc_length); - cdrom_data_command_finish(id, alloc_length, alloc_length, len, 0); - } else - cdrom_buf_free(id); - return; - } - } else { - cdrom_invalid_field(id); - cdrom_buf_free(id); + if (idx + 72 > cdb[4]) + goto atapi_out; + cdbufferb[idx++] = 0x02; + cdbufferb[idx++] = 0x01; + cdbufferb[idx++] = 0x00; + cdbufferb[idx++] = 68; + ide_padstr8(cdbufferb + idx, 8, EMU_NAME); /* Vendor */ + idx += 8; + ide_padstr8(cdbufferb + idx, 40, device_identify_ex); /* Product */ + idx += 40; + ide_padstr8(cdbufferb + idx, 20, "53R141"); /* Product */ + idx += 20; + break; + default: + DEBUG("INQUIRY: Invalid page: %02X\n", cdb[2]); + cdrom_invalid_field(dev); + cdrom_buf_free(dev); return; - } } - break; + } else { + preamble_len = 5; + size_idx = 4; - case GPCMD_START_STOP_UNIT: - cdrom_set_phase(id, SCSI_PHASE_STATUS); - - switch(cdb[4] & 3) { - case 0: /* Stop the disc. */ - if (cdrom_drives[id].handler->stop) - cdrom_drives[id].handler->stop(id); - break; - case 1: /* Start the disc and read the TOC. */ - cdrom_drives[id].handler->medium_changed(id); /* This causes a TOC reload. */ - break; - case 2: /* Eject the disc if possible. */ - if (cdrom_drives[id].handler->stop) - cdrom_drives[id].handler->stop(id); - cdrom_eject(id); - break; - case 3: /* Load the disc (close tray). */ - cdrom_reload(id); - break; + memset(cdbufferb, 0, 8); + cdbufferb[0] = 5; /*CD-ROM*/ + cdbufferb[1] = 0x80; /*Removable*/ + cdbufferb[2] = (dev->drv->bus_type == CDROM_BUS_SCSI) ? 0x02 : 0x00; /*SCSI-2 compliant*/ + cdbufferb[3] = (dev->drv->bus_type == CDROM_BUS_SCSI) ? 0x12 : 0x21; + cdbufferb[4] = 31; + if (dev->drv->bus_type == CDROM_BUS_SCSI) { + cdbufferb[6] = 1; /* 16-bit transfers supported */ + cdbufferb[7] = 0x20; /* Wide bus supported */ } - cdrom_command_complete(id); - break; - - case GPCMD_INQUIRY: - cdrom_set_phase(id, SCSI_PHASE_DATA_IN); - - max_len = cdb[3]; - max_len <<= 8; - max_len |= cdb[4]; + ide_padstr8(cdbufferb + 8, 8, EMU_NAME); /* Vendor */ + ide_padstr8(cdbufferb + 16, 16, device_identify); /* Product */ + ide_padstr8(cdbufferb + 32, 4, EMU_VERSION); /* Revision */ + idx = 36; - cdrom_buf_alloc(id, 65536); - - if (cdb[1] & 1) { - preamble_len = 4; - size_idx = 3; - - cdbufferb[idx++] = 05; - cdbufferb[idx++] = cdb[2]; - cdbufferb[idx++] = 0; - - idx++; - - switch (cdb[2]) { - case 0x00: - cdbufferb[idx++] = 0x00; - cdbufferb[idx++] = 0x83; - break; - case 0x83: - if (idx + 24 > max_len) { - cdrom_data_phase_error(id); - cdrom_buf_free(id); - return; - } - - cdbufferb[idx++] = 0x02; - cdbufferb[idx++] = 0x00; - cdbufferb[idx++] = 0x00; - cdbufferb[idx++] = 20; - ide_padstr8(cdbufferb + idx, 20, "53R141"); /* Serial */ - idx += 20; - - if (idx + 72 > cdb[4]) - goto atapi_out; - cdbufferb[idx++] = 0x02; - cdbufferb[idx++] = 0x01; - cdbufferb[idx++] = 0x00; - cdbufferb[idx++] = 68; - ide_padstr8(cdbufferb + idx, 8, EMU_NAME); /* Vendor */ - idx += 8; - ide_padstr8(cdbufferb + idx, 40, device_identify_ex); /* Product */ - idx += 40; - ide_padstr8(cdbufferb + idx, 20, "53R141"); /* Product */ - idx += 20; - break; - default: - cdrom_log("INQUIRY: Invalid page: %02X\n", cdb[2]); - cdrom_invalid_field(id); - cdrom_buf_free(id); - return; - } - } else { - preamble_len = 5; - size_idx = 4; - - memset(cdbufferb, 0, 8); - cdbufferb[0] = 5; /*CD-ROM*/ - cdbufferb[1] = 0x80; /*Removable*/ - cdbufferb[2] = (cdrom_drives[id].bus_type == CDROM_BUS_SCSI) ? 0x02 : 0x00; /*SCSI-2 compliant*/ - cdbufferb[3] = (cdrom_drives[id].bus_type == CDROM_BUS_SCSI) ? 0x12 : 0x21; - cdbufferb[4] = 31; - if (cdrom_drives[id].bus_type == CDROM_BUS_SCSI) { - cdbufferb[6] = 1; /* 16-bit transfers supported */ - cdbufferb[7] = 0x20; /* Wide bus supported */ - } - - ide_padstr8(cdbufferb + 8, 8, EMU_NAME); /* Vendor */ - ide_padstr8(cdbufferb + 16, 16, device_identify); /* Product */ - ide_padstr8(cdbufferb + 32, 4, EMU_VERSION); /* Revision */ - idx = 36; - - if (max_len == 96) { - cdbufferb[4] = 91; - idx = 96; - } + if (max_len == 96) { + cdbufferb[4] = 91; + idx = 96; } + } atapi_out: - cdbufferb[size_idx] = idx - preamble_len; - len=idx; + cdbufferb[size_idx] = idx - preamble_len; + len=idx; - len = MIN(len, max_len); - cdrom_set_buf_len(id, BufLen, &len); + len = MIN(len, max_len); + cdrom_set_buf_len(dev, BufLen, &len); - cdrom_data_command_finish(id, len, len, max_len, 0); - break; + cdrom_data_command_finish(dev, len, len, max_len, 0); + break; - case GPCMD_PREVENT_REMOVAL: - cdrom_set_phase(id, SCSI_PHASE_STATUS); - cdrom_command_complete(id); - break; + case GPCMD_PREVENT_REMOVAL: + cdrom_set_phase(dev, SCSI_PHASE_STATUS); + cdrom_command_complete(dev); + break; - case GPCMD_PAUSE_RESUME_ALT: - case GPCMD_PAUSE_RESUME: - cdrom_set_phase(id, SCSI_PHASE_STATUS); - - if (cdb[8] & 1) { - if (cdrom_drives[id].handler->resume) - cdrom_drives[id].handler->resume(id); - else { - cdrom_illegal_mode(id); - break; - } - } else { - if (cdrom_drives[id].handler->pause) - cdrom_drives[id].handler->pause(id); - else { - cdrom_illegal_mode(id); - break; - } - } - cdrom_command_complete(id); - break; + case GPCMD_PAUSE_RESUME_ALT: + case GPCMD_PAUSE_RESUME: + cdrom_set_phase(dev, SCSI_PHASE_STATUS); - case GPCMD_SEEK_6: - case GPCMD_SEEK_10: - cdrom_set_phase(id, SCSI_PHASE_STATUS); - - switch(cdb[0]) { - case GPCMD_SEEK_6: - pos = (cdb[2] << 8) | cdb[3]; - break; - case GPCMD_SEEK_10: - pos = (cdb[2] << 24) | (cdb[3]<<16) | (cdb[4]<<8) | cdb[5]; - break; - } - dev->seek_diff = ABS((int) (pos - dev->seek_pos)); - cdrom_seek(id, pos); - cdrom_command_complete(id); - break; - - case GPCMD_READ_CDROM_CAPACITY: - cdrom_set_phase(id, SCSI_PHASE_DATA_IN); - - cdrom_buf_alloc(id, 8); - - if (cdrom_read_capacity(id, dev->current_cdb, cdbufferb, &len) == 0) { - cdrom_buf_free(id); - return; - } - - cdrom_set_buf_len(id, BufLen, &len); - - cdrom_data_command_finish(id, len, len, len, 0); - break; - - case GPCMD_STOP_PLAY_SCAN: - cdrom_set_phase(id, SCSI_PHASE_STATUS); - - if (cdrom_drives[id].handler->stop) - cdrom_drives[id].handler->stop(id); + if (cdb[8] & 1) { + if (dev->handler->resume) + dev->handler->resume(dev->id); else { - cdrom_illegal_mode(id); + cdrom_illegal_mode(dev); break; } - cdrom_command_complete(id); + } else { + if (dev->handler->pause) + dev->handler->pause(dev->id); + else { + cdrom_illegal_mode(dev); + break; + } + } + cdrom_command_complete(dev); + break; + + case GPCMD_SEEK_6: + case GPCMD_SEEK_10: + cdrom_set_phase(dev, SCSI_PHASE_STATUS); + + switch(cdb[0]) { + case GPCMD_SEEK_6: + pos = (cdb[2] << 8) | cdb[3]; + break; + case GPCMD_SEEK_10: + pos = (cdb[2] << 24) | (cdb[3]<<16) | (cdb[4]<<8) | cdb[5]; + break; + } + dev->seek_diff = ABS((int) (pos - dev->seek_pos)); + cdrom_seek(dev, pos); + cdrom_command_complete(dev); + break; + + case GPCMD_READ_CDROM_CAPACITY: + cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); + + cdrom_buf_alloc(dev, 8); + + if (cdrom_read_capacity(dev, dev->current_cdb, cdbufferb, (uint32_t *) &len) == 0) { + cdrom_buf_free(dev); + return; + } + + cdrom_set_buf_len(dev, BufLen, &len); + + cdrom_data_command_finish(dev, len, len, len, 0); + break; + + case GPCMD_STOP_PLAY_SCAN: + cdrom_set_phase(dev, SCSI_PHASE_STATUS); + + if (dev->handler->stop) + dev->handler->stop(dev->id); + else { + cdrom_illegal_mode(dev); break; + } + cdrom_command_complete(dev); + break; - default: - cdrom_illegal_opcode(id); - break; - } + default: + cdrom_illegal_opcode(dev); + break; + } - /* cdrom_log("CD-ROM %i: Phase: %02X, request length: %i\n", dev->phase, dev->request_length); */ + /* DEBUG("CD-ROM %i: Phase: %02X, request length: %i\n", dev->phase, dev->request_length); */ - if (cdrom_atapi_phase_to_scsi(id) == SCSI_PHASE_STATUS) - cdrom_buf_free(id); + if (cdrom_atapi_phase_to_scsi(dev) == SCSI_PHASE_STATUS) + cdrom_buf_free(dev); } + /* The command second phase function, needed for Mode Select. */ -uint8_t cdrom_phase_data_out(uint8_t id) +static uint8_t +cdrom_phase_data_out(cdrom_t *dev) { - cdrom_t *dev = cdrom[id]; - uint16_t block_desc_len; - uint16_t pos; + uint16_t block_desc_len, pos; + uint16_t i = 0; - uint8_t error = 0; - uint8_t page, page_len; + uint8_t error = 0; + uint8_t page, page_len, hdr_len, val, old_val, ch; - uint16_t i = 0; + FILE *f; - uint8_t hdr_len, val, old_val, ch; + switch(dev->current_cdb[0]) { + case GPCMD_MODE_SELECT_6: + case GPCMD_MODE_SELECT_10: + f = plat_fopen(nvr_path(L"modeselect.bin"), L"wb"); + fwrite(cdbufferb, 1, dev->total_length, f); + fclose(f); - FILE *f; + if (dev->current_cdb[0] == GPCMD_MODE_SELECT_10) + hdr_len = 8; + else + hdr_len = 4; - switch(dev->current_cdb[0]) { - case GPCMD_MODE_SELECT_6: - case GPCMD_MODE_SELECT_10: - f = plat_fopen(nvr_path(L"modeselect.bin"), L"wb"); - fwrite(cdbufferb, 1, dev->total_length, f); - fclose(f); + if (dev->drv->bus_type == CDROM_BUS_SCSI) { + if (dev->current_cdb[0] == GPCMD_MODE_SELECT_6) { + block_desc_len = cdbufferb[2]; + block_desc_len <<= 8; + block_desc_len |= cdbufferb[3]; + } else { + block_desc_len = cdbufferb[6]; + block_desc_len <<= 8; + block_desc_len |= cdbufferb[7]; + } + } else + block_desc_len = 0; - if (dev->current_cdb[0] == GPCMD_MODE_SELECT_10) - hdr_len = 8; - else - hdr_len = 4; + pos = hdr_len + block_desc_len; - if (cdrom_drives[id].bus_type == CDROM_BUS_SCSI) { - if (dev->current_cdb[0] == GPCMD_MODE_SELECT_6) { - block_desc_len = cdbufferb[2]; - block_desc_len <<= 8; - block_desc_len |= cdbufferb[3]; - } else { - block_desc_len = cdbufferb[6]; - block_desc_len <<= 8; - block_desc_len |= cdbufferb[7]; - } - } else - block_desc_len = 0; + while(1) { + page = cdbufferb[pos] & 0x3F; + page_len = cdbufferb[pos + 1]; - pos = hdr_len + block_desc_len; + pos += 2; - while(1) { - page = cdbufferb[pos] & 0x3F; - page_len = cdbufferb[pos + 1]; - - pos += 2; - - if (!(cdrom_mode_sense_page_flags & (1LL << ((uint64_t) page)))) { - cdrom_log("Unimplemented page %02X\n", page); - error |= 1; - } else { - for (i = 0; i < page_len; i++) { - ch = cdrom_mode_sense_pages_changeable.pages[page][i + 2]; - val = cdbufferb[pos + i]; - old_val = cdrom_mode_sense_pages_saved[id].pages[page][i + 2]; - if (val != old_val) { - if (ch) - cdrom_mode_sense_pages_saved[id].pages[page][i + 2] = val; - else { - cdrom_log("Unchangeable value on position %02X on page %02X\n", i + 2, page); - error |= 1; - } + if (!(cdrom_mode_sense_page_flags & (1LL << ((uint64_t) page)))) { + DEBUG("Unimplemented page %02X\n", page); + error |= 1; + } else { + for (i = 0; i < page_len; i++) { + ch = cdrom_mode_sense_pages_changeable.pages[page][i + 2]; + val = cdbufferb[pos + i]; + old_val = dev->ms_pages_saved.pages[page][i + 2]; + if (val != old_val) { + if (ch) + dev->ms_pages_saved.pages[page][i + 2] = val; + else { + DEBUG("Unchangeable value on position %02X on page %02X\n", i + 2, page); + error |= 1; } } } - - pos += page_len; - - if (cdrom_drives[id].bus_type == CDROM_BUS_SCSI) - val = cdrom_mode_sense_pages_default_scsi.pages[page][0] & 0x80; - else - val = cdrom_mode_sense_pages_default.pages[page][0] & 0x80; - if (dev->do_page_save && val) - cdrom_mode_sense_save(id); - - if (pos >= dev->total_length) - break; } - if (error) { - cdrom_invalid_field_pl(id); - return 0; - } - break; - } + pos += page_len; - return 1; + if (dev->drv->bus_type == CDROM_BUS_SCSI) + val = cdrom_mode_sense_pages_default_scsi.pages[page][0] & 0x80; + else + val = cdrom_mode_sense_pages_default.pages[page][0] & 0x80; + + if (dev->do_page_save && val) + cdrom_mode_sense_save(dev); + + if (pos >= dev->total_length) + break; + } + + if (error) { + cdrom_invalid_field_pl(dev); + return 0; + } + break; + } + + return 1; } + /* This is the general ATAPI PIO request function. */ -void cdrom_pio_request(uint8_t id, uint8_t out) +static void +cdrom_pio_request(cdrom_t *dev, uint8_t out) { - cdrom_t *dev = cdrom[id]; - int old_pos = 0; - int ret = 0; + int ret = 0; + + if (dev->drv->bus_type < CDROM_BUS_SCSI) { + DEBUG("CD-ROM %i: Lowering IDE IRQ\n", dev->id); + ide_irq_lower(ide_drives[dev->drv->ide_channel]); + } + + dev->status = BUSY_STAT; + + if (dev->pos >= dev->packet_len) { + DEBUG("CD-ROM %i: %i bytes %s, command done\n", dev->id, dev->pos, out ? "written" : "read"); + + dev->pos = dev->request_pos = 0; + if (out) { + ret = cdrom_phase_data_out(dev); + /* If ret = 0 (phase 1 error), then we do not do anything else other than + free the buffer, as the phase and callback have already been set by the + error function. */ + if (ret) + cdrom_command_complete(dev); + } else + cdrom_command_complete(dev); + cdrom_buf_free(dev); + } else { + DEBUG("CD-ROM %i: %i bytes %s, %i bytes are still left\n", dev->id, dev->pos, + out ? "written" : "read", dev->packet_len - dev->pos); + + /* If less than (packet length) bytes are remaining, update packet length + accordingly. */ + if ((dev->packet_len - dev->pos) < (dev->max_transfer_len)) + dev->max_transfer_len = dev->packet_len - dev->pos; + DEBUG("CD-ROM %i: Packet length %i, request length %i\n", dev->id, dev->packet_len, + dev->max_transfer_len); + + dev->packet_status = out ? CDROM_PHASE_DATA_OUT : CDROM_PHASE_DATA_IN; - if (cdrom_drives[id].bus_type < CDROM_BUS_SCSI) { - cdrom_log("CD-ROM %i: Lowering IDE IRQ\n", id); - ide_irq_lower(&(ide_drives[cdrom_drives[id].ide_channel])); - } - dev->status = BUSY_STAT; + dev->phase = 1; + cdrom_phase_callback(dev); + dev->callback = 0LL; + cdrom_set_callback(dev); - if (dev->pos >= dev->packet_len) { - cdrom_log("CD-ROM %i: %i bytes %s, command done\n", id, dev->pos, out ? "written" : "read"); - - dev->pos = dev->request_pos = 0; - if (out) { - ret = cdrom_phase_data_out(id); - /* If ret = 0 (phase 1 error), then we do not do anything else other than - free the buffer, as the phase and callback have already been set by the - error function. */ - if (ret) - cdrom_command_complete(id); - } else - cdrom_command_complete(id); - cdrom_buf_free(id); - } else { - cdrom_log("CD-ROM %i: %i bytes %s, %i bytes are still left\n", id, dev->pos, out ? "written" : "read", dev->packet_len - dev->pos); - - /* Make sure to keep pos, and reset request_pos to 0. */ - /* Also make sure to not reset total_read. */ - - /* If less than (packet length) bytes are remaining, update packet length - accordingly. */ - if ((dev->packet_len - dev->pos) < (dev->max_transfer_len)) - dev->max_transfer_len = dev->packet_len - dev->pos; - cdrom_log("CD-ROM %i: Packet length %i, request length %i\n", id, dev->packet_len, dev->max_transfer_len); - - old_pos = dev->pos; - dev->packet_status = out ? CDROM_PHASE_DATA_OUT : CDROM_PHASE_DATA_IN; - cdrom_command_common(id); - dev->pos = old_pos; - dev->request_pos = 0; - } + dev->request_pos = 0; + } } -void cdrom_phase_callback(uint8_t id); -int cdrom_read_from_ide_dma(uint8_t channel) +static int +cdrom_read_from_ide_dma(uint8_t channel) { - uint8_t id = atapi_cdrom_drives[channel]; - cdrom_t *dev; + cdrom_t *dev; - if (id > CDROM_NUM) + uint8_t id = atapi_cdrom_drives[channel]; + int ret; + + if (id > CDROM_NUM) + return 0; + + dev = cdrom[id]; + + if (ide_bus_master_write) { + ret = ide_bus_master_write(channel >> 1, + cdbufferb, dev->packet_len, + ide_bus_master_priv[channel >> 1]); + if (ret == 2) /* DMA not enabled, wait for it to be enabled. */ + return 2; + else if (ret == 1) { /* DMA error. */ + cdrom_bus_master_error(dev); return 0; - - dev = cdrom[id]; - if (ide_bus_master_write) { - if (ide_bus_master_write(channel >> 1, cdbufferb, dev->packet_len)) - return 0; - else - return 1; } else - return 0; - - return 0; -} - -int cdrom_read_from_scsi_dma(uint8_t scsi_id, uint8_t scsi_lun) -{ - uint8_t id = scsi_cdrom_drives[scsi_id][scsi_lun]; - int32_t *BufLen = &SCSIDevices[scsi_id][scsi_lun].BufferLength; - cdrom_t *dev; - - if (id > CDROM_NUM) - return 0; - - dev = cdrom[id]; - cdrom_log("Reading from SCSI DMA: SCSI ID %02X, init length %i\n", scsi_id, *BufLen); - memcpy(cdbufferb, SCSIDevices[scsi_id][scsi_lun].CmdBuffer, *BufLen); - return 1; -} - -void cdrom_irq_raise(uint8_t id) -{ - if (cdrom_drives[id].bus_type < CDROM_BUS_SCSI) - ide_irq_raise(&(ide_drives[cdrom_drives[id].ide_channel])); -} - -int cdrom_read_from_dma(uint8_t id) -{ - cdrom_t *dev = cdrom[id]; - int32_t *BufLen = &SCSIDevices[cdrom_drives[id].scsi_device_id][cdrom_drives[id].scsi_device_lun].BufferLength; - - int ret = 0; - - if (cdrom_drives[id].bus_type == CDROM_BUS_SCSI) - ret = cdrom_read_from_scsi_dma(cdrom_drives[id].scsi_device_id, cdrom_drives[id].scsi_device_lun); - else - ret = cdrom_read_from_ide_dma(cdrom_drives[id].ide_channel); - - if (!ret) - return 0; - - if (cdrom_drives[id].bus_type == CDROM_BUS_SCSI) - cdrom_log("CD-ROM %i: SCSI Input data length: %i\n", id, *BufLen); - else - cdrom_log("CD-ROM %i: ATAPI Input data length: %i\n", id, dev->packet_len); - - ret = cdrom_phase_data_out(id); - - if (ret) return 1; - + } else return 0; + + return 0; } -int cdrom_write_to_ide_dma(uint8_t channel) + +static int +cdrom_read_from_scsi_dma(uint8_t scsi_id, uint8_t scsi_lun) { - uint8_t id = atapi_cdrom_drives[channel]; - cdrom_t *dev; + cdrom_t *dev; - if (id > CDROM_NUM) - return 0; - - dev = cdrom[id]; - if (ide_bus_master_read) { - if (ide_bus_master_read(channel >> 1, cdbufferb, dev->packet_len)) - return 0; - else - return 1; - } + uint8_t id = scsi_cdrom_drives[scsi_id][scsi_lun]; + int32_t *BufLen = &SCSIDevices[scsi_id][scsi_lun].BufferLength; + if (id > CDROM_NUM) return 0; + + dev = cdrom[id]; + + DEBUG("Reading from SCSI DMA: SCSI ID %02X, init length %i\n", scsi_id, *BufLen); + memcpy(cdbufferb, SCSIDevices[scsi_id][scsi_lun].CmdBuffer, *BufLen); + + return 1; } -int cdrom_write_to_scsi_dma(uint8_t scsi_id, uint8_t scsi_lun) + +static void +cdrom_irq_raise(cdrom_t *dev) { - uint8_t id = scsi_cdrom_drives[scsi_id][scsi_lun]; - int32_t *BufLen = &SCSIDevices[scsi_id][scsi_lun].BufferLength; - cdrom_t *dev; + if (dev->drv->bus_type < CDROM_BUS_SCSI) + ide_irq_raise(ide_drives[dev->drv->ide_channel]); +} - if (id > CDROM_NUM) - return 0; - dev = cdrom[id]; - cdrom_log("Writing to SCSI DMA: SCSI ID %02X, init length %i\n", scsi_id, *BufLen); - memcpy(SCSIDevices[scsi_id][scsi_lun].CmdBuffer, cdbufferb, *BufLen); - cdrom_log("CD-ROM %i: Data from CD buffer: %02X %02X %02X %02X %02X %02X %02X %02X\n", id, cdbufferb[0], cdbufferb[1], cdbufferb[2], cdbufferb[3], cdbufferb[4], cdbufferb[5], cdbufferb[6], cdbufferb[7]); - cdrom_log("CD-ROM %i: Data from SCSI DMA : %02X %02X %02X %02X %02X %02X %02X %02X\n", id, SCSIDevices[scsi_id][scsi_lun].CmdBuffer[0], SCSIDevices[scsi_id][scsi_lun].CmdBuffer[1], SCSIDevices[scsi_id][scsi_lun].CmdBuffer[2], SCSIDevices[scsi_id][scsi_lun].CmdBuffer[3], SCSIDevices[scsi_id][scsi_lun].CmdBuffer[4], SCSIDevices[scsi_id][scsi_lun].CmdBuffer[5], SCSIDevices[scsi_id][scsi_lun].CmdBuffer[6], SCSIDevices[scsi_id][scsi_lun].CmdBuffer[7]); +static int +cdrom_read_from_dma(cdrom_t *dev) +{ +#ifdef _LOGGING + int32_t *BufLen = &SCSIDevices[dev->drv->scsi_device_id][dev->drv->scsi_device_lun].BufferLength; +#endif + int ret = 0; + + if (dev->drv->bus_type == CDROM_BUS_SCSI) + ret = cdrom_read_from_scsi_dma(dev->drv->scsi_device_id, dev->drv->scsi_device_lun); + else + ret = cdrom_read_from_ide_dma(dev->drv->ide_channel); + + if (ret != 1) + return ret; + + if (dev->drv->bus_type == CDROM_BUS_SCSI) + DEBUG("CD-ROM %i: SCSI Input data length: %i\n", dev->id, *BufLen); + else + DEBUG("CD-ROM %i: ATAPI Input data length: %i\n", dev->id, dev->packet_len); + + ret = cdrom_phase_data_out(dev); + + if (ret) return 1; + else + return 0; } -int cdrom_write_to_dma(uint8_t id) -{ - cdrom_t *dev = cdrom[id]; - int32_t *BufLen = &SCSIDevices[cdrom_drives[id].scsi_device_id][cdrom_drives[id].scsi_device_lun].BufferLength; - int ret = 0; - if (cdrom_drives[id].bus_type == CDROM_BUS_SCSI) { - cdrom_log("Write to SCSI DMA: (%02X:%02X)\n", cdrom_drives[id].scsi_device_id, cdrom_drives[id].scsi_device_lun); - ret = cdrom_write_to_scsi_dma(cdrom_drives[id].scsi_device_id, cdrom_drives[id].scsi_device_lun); +static int +cdrom_write_to_ide_dma(uint8_t channel) +{ + cdrom_t *dev; + + uint8_t id = atapi_cdrom_drives[channel]; + int ret; + + if (id > CDROM_NUM) + return 0; + + dev = cdrom[id]; + + if (ide_bus_master_read) { + ret = ide_bus_master_read(channel >> 1, + cdbufferb, dev->packet_len, + ide_bus_master_priv[channel >> 1]); + if (ret == 2) /* DMA not enabled, wait for it to be enabled. */ + return 2; + else if (ret == 1) { /* DMA error. */ + cdrom_bus_master_error(dev); + return 0; } else - ret = cdrom_write_to_ide_dma(cdrom_drives[id].ide_channel); - - if (cdrom_drives[id].bus_type == CDROM_BUS_SCSI) - cdrom_log("CD-ROM %i: SCSI Output data length: %i\n", id, *BufLen); - else - cdrom_log("CD-ROM %i: ATAPI Output data length: %i\n", id, dev->packet_len); - - if (ret) return 1; - + } else return 0; } -/* If the result is 1, issue an IRQ, otherwise not. */ -void cdrom_phase_callback(uint8_t id) + +static int +cdrom_write_to_scsi_dma(uint8_t scsi_id, uint8_t scsi_lun) { - cdrom_t *dev = cdrom[id]; - int ret; + cdrom_t *dev; - switch(dev->packet_status) { - case CDROM_PHASE_IDLE: - cdrom_log("CD-ROM %i: CDROM_PHASE_IDLE\n", id); - dev->pos=0; - dev->phase = 1; - dev->status = READY_STAT | DRQ_STAT | (dev->status & ERR_STAT); - return; - case CDROM_PHASE_COMMAND: - cdrom_log("CD-ROM %i: CDROM_PHASE_COMMAND\n", id); - dev->status = BUSY_STAT | (dev->status &ERR_STAT); - memcpy(dev->atapi_cdb, cdbufferb, dev->cdb_len); - cdrom_command(id, dev->atapi_cdb); - return; - case CDROM_PHASE_COMPLETE: - cdrom_log("CD-ROM %i: CDROM_PHASE_COMPLETE\n", id); - dev->status = READY_STAT; - dev->phase = 3; - dev->packet_status = 0xFF; - ui_sb_icon_update(SB_CDROM | id, 0); - cdrom_irq_raise(id); - return; - case CDROM_PHASE_DATA_OUT: - cdrom_log("CD-ROM %i: CDROM_PHASE_DATA_OUT\n", id); - dev->status = READY_STAT | DRQ_STAT | (dev->status & ERR_STAT); - dev->phase = 0; - cdrom_irq_raise(id); - return; - case CDROM_PHASE_DATA_OUT_DMA: - cdrom_log("CD-ROM %i: CDROM_PHASE_DATA_OUT_DMA\n", id); - cdrom_read_from_dma(id); - return; - case CDROM_PHASE_DATA_IN: - cdrom_log("CD-ROM %i: CDROM_PHASE_DATA_IN\n", id); - dev->status = READY_STAT | DRQ_STAT | (dev->status & ERR_STAT); - dev->phase = 2; - cdrom_irq_raise(id); - return; - case CDROM_PHASE_DATA_IN_DMA: - cdrom_log("CD-ROM %i: CDROM_PHASE_DATA_IN_DMA\n", id); - ret = cdrom_write_to_dma(id); + uint8_t id = scsi_cdrom_drives[scsi_id][scsi_lun]; + int32_t *BufLen = &SCSIDevices[scsi_id][scsi_lun].BufferLength; - if (ret || (cdrom_drives[id].bus_type == CDROM_BUS_SCSI)) { - cdrom_log("CD-ROM %i: DMA data in phase done\n"); - cdrom_buf_free(id); - cdrom_command_complete(id); - } else { - cdrom_log("CD-ROM %i: DMA data in phase failure\n"); - cdrom_command_bus(id); - } - return; - case CDROM_PHASE_ERROR: - cdrom_log("CD-ROM %i: CDROM_PHASE_ERROR\n", id); - dev->status = READY_STAT | ERR_STAT; - dev->phase = 3; - cdrom_irq_raise(id); - ui_sb_icon_update(SB_CDROM | id, 0); - return; - } + if (id > CDROM_NUM) + return 0; + + dev = cdrom[id]; + + DEBUG("Writing to SCSI DMA: SCSI ID %02X, init length %i\n", scsi_id, *BufLen); + memcpy(SCSIDevices[scsi_id][scsi_lun].CmdBuffer, cdbufferb, *BufLen); + DEBUG("CD-ROM %i: Data from CD buffer: %02X %02X %02X %02X %02X %02X %02X %02X\n", id, + cdbufferb[0], cdbufferb[1], cdbufferb[2], cdbufferb[3], cdbufferb[4], cdbufferb[5], + cdbufferb[6], cdbufferb[7]); + DEBUG("CD-ROM %i: Data from SCSI DMA : %02X %02X %02X %02X %02X %02X %02X %02X\n", id, + SCSIDevices[scsi_id][scsi_lun].CmdBuffer[0], SCSIDevices[scsi_id][scsi_lun].CmdBuffer[1], + SCSIDevices[scsi_id][scsi_lun].CmdBuffer[2], SCSIDevices[scsi_id][scsi_lun].CmdBuffer[3], + SCSIDevices[scsi_id][scsi_lun].CmdBuffer[4], SCSIDevices[scsi_id][scsi_lun].CmdBuffer[5], + SCSIDevices[scsi_id][scsi_lun].CmdBuffer[6], SCSIDevices[scsi_id][scsi_lun].CmdBuffer[7]); + + return 1; } -/* Reimplement as 8-bit due to reimplementation of IDE data read and write. */ -uint32_t cdrom_read(uint8_t channel, int length) + +static int +cdrom_write_to_dma(cdrom_t *dev) { - uint16_t *cdbufferw; - uint32_t *cdbufferl; - uint32_t temp = 0; - cdrom_t *dev; +#ifdef _LOGGING + int32_t *BufLen = &SCSIDevices[dev->drv->scsi_device_id][dev->drv->scsi_device_lun].BufferLength; +#endif + int ret = 0; - uint8_t id = atapi_cdrom_drives[channel]; + if (dev->drv->bus_type == CDROM_BUS_SCSI) { + DEBUG("Write to SCSI DMA: (%02X:%02X)\n", dev->drv->scsi_device_id, dev->drv->scsi_device_lun); + ret = cdrom_write_to_scsi_dma(dev->drv->scsi_device_id, dev->drv->scsi_device_lun); + } else + ret = cdrom_write_to_ide_dma(dev->drv->ide_channel); - if (id > CDROM_NUM) - return 0; + if (dev->drv->bus_type == CDROM_BUS_SCSI) + DEBUG("CD-ROM %i: SCSI Output data length: %i\n", dev->id, *BufLen); + else + DEBUG("CD-ROM %i: ATAPI Output data length: %i\n", dev->id, dev->packet_len); - dev = cdrom[id]; - cdbufferw = (uint16_t *) cdbufferb; - cdbufferl = (uint32_t *) cdbufferb; - - if (!cdbufferb) - return 0; - - /* Make sure we return a 0 and don't attempt to read from the buffer if we're transferring bytes beyond it, - which can happen when issuing media access commands with an allocated length below minimum request length - (which is 1 sector = 2048 bytes). */ - switch(length) { - case 1: - temp = (dev->pos < dev->packet_len) ? cdbufferb[dev->pos] : 0; - dev->pos++; - dev->request_pos++; - break; - case 2: - temp = (dev->pos < dev->packet_len) ? cdbufferw[dev->pos >> 1] : 0; - dev->pos += 2; - dev->request_pos += 2; - break; - case 4: - temp = (dev->pos < dev->packet_len) ? cdbufferl[dev->pos >> 2] : 0; - dev->pos += 4; - dev->request_pos += 4; - break; - default: - return 0; - } - - if (dev->packet_status == CDROM_PHASE_DATA_IN) { - if ((dev->request_pos >= dev->max_transfer_len) || (dev->pos >= dev->packet_len)) { - /* Time for a DRQ. */ - // cdrom_log("CD-ROM %i: Issuing read callback\n", id); - cdrom_pio_request(id, 0); - } - // cdrom_log("CD-ROM %i: Returning: %02X (buffer position: %i, request position: %i)\n", id, temp, dev->pos, dev->request_pos); - return temp; - } else { - // cdrom_log("CD-ROM %i: Returning zero (buffer position: %i, request position: %i)\n", id, dev->pos, dev->request_pos); - return 0; - } + return ret; } -/* Reimplement as 8-bit due to reimplementation of IDE data read and write. */ -void cdrom_write(uint8_t channel, uint32_t val, int length) + +void +cdrom_phase_callback(cdrom_t *dev) { - uint16_t *cdbufferw; - uint32_t *cdbufferl; - cdrom_t *dev; + int ret; - uint8_t id = atapi_cdrom_drives[channel]; - - if (id > CDROM_NUM) + switch(dev->packet_status) { + case CDROM_PHASE_IDLE: + DEBUG("CD-ROM %i: CDROM_PHASE_IDLE\n", dev->id); + dev->pos = 0; + dev->phase = 1; + dev->status = READY_STAT | DRQ_STAT | (dev->status & ERR_STAT); return; - - dev = cdrom[id]; - if (dev->packet_status == CDROM_PHASE_IDLE) { - if (!cdbufferb) - cdrom_buf_alloc(id, dev->cdb_len); - } - - cdbufferw = (uint16_t *) cdbufferb; - cdbufferl = (uint32_t *) cdbufferb; - - if (!cdbufferb) + case CDROM_PHASE_COMMAND: + DEBUG("CD-ROM %i: CDROM_PHASE_COMMAND\n", dev->id); + dev->status = BUSY_STAT | (dev->status & ERR_STAT); + memcpy(dev->atapi_cdb, cdbufferb, dev->cdb_len); + cdrom_command(dev, dev->atapi_cdb); return; + case CDROM_PHASE_COMPLETE: + DEBUG("CD-ROM %i: CDROM_PHASE_COMPLETE\n", dev->id); + dev->status = READY_STAT; + dev->phase = 3; + dev->packet_status = 0xFF; + ui_sb_icon_update(SB_CDROM | dev->id, 0); + cdrom_irq_raise(dev); + return; + case CDROM_PHASE_DATA_OUT: + DEBUG("CD-ROM %i: CDROM_PHASE_DATA_OUT\n", dev->id); + dev->status = READY_STAT | DRQ_STAT | (dev->status & ERR_STAT); + dev->phase = 0; + cdrom_irq_raise(dev); + return; + case CDROM_PHASE_DATA_OUT_DMA: + DEBUG("CD-ROM %i: CDROM_PHASE_DATA_OUT_DMA\n", dev->id); + ret = cdrom_read_from_dma(dev); - switch(length) { - case 1: - cdbufferb[dev->pos] = val & 0xff; - dev->pos++; - dev->request_pos++; - break; - case 2: - cdbufferw[dev->pos >> 1] = val & 0xffff; - dev->pos += 2; - dev->request_pos += 2; - break; - case 4: - cdbufferl[dev->pos >> 2] = val; - dev->pos += 4; - dev->request_pos += 4; - break; - default: - return; - } - - if (dev->packet_status == CDROM_PHASE_DATA_OUT) { - if ((dev->request_pos >= dev->max_transfer_len) || (dev->pos >= dev->packet_len)) { - /* Time for a DRQ. */ - cdrom_pio_request(id, 1); + if ((ret == 1) || (dev->drv->bus_type == CDROM_BUS_SCSI)) { + DEBUG("CD-ROM %i: DMA data out phase done\n", dev->id); + cdrom_buf_free(dev); + cdrom_command_complete(dev); + } else if (ret == 2) { + DEBUG("CD-ROM %i: DMA out not enabled, wait\n", dev->id); + cdrom_command_bus(dev); + } else { + DEBUG("CD-ROM %i: DMA data out phase failure\n", dev->id); + cdrom_buf_free(dev); } return; - } else if (dev->packet_status == CDROM_PHASE_IDLE) { - if (dev->pos >= (uint32_t)dev->cdb_len) { - dev->pos=0; - dev->status = BUSY_STAT; - dev->packet_status = CDROM_PHASE_COMMAND; - timer_process(); - cdrom_phase_callback(id); - timer_update_outstanding(); + case CDROM_PHASE_DATA_IN: + DEBUG("CD-ROM %i: CDROM_PHASE_DATA_IN\n", dev->id); + dev->status = READY_STAT | DRQ_STAT | (dev->status & ERR_STAT); + dev->phase = 2; + cdrom_irq_raise(dev); + return; + case CDROM_PHASE_DATA_IN_DMA: + DEBUG("CD-ROM %i: CDROM_PHASE_DATA_IN_DMA\n", dev->id); + ret = cdrom_write_to_dma(dev); + + if ((ret == 1) || (dev->drv->bus_type == CDROM_BUS_SCSI)) { + DEBUG("CD-ROM %i: DMA data in phase done\n"); + cdrom_buf_free(dev); + cdrom_command_complete(dev); + } else if (ret == 2) { + DEBUG("CD-ROM %i: DMA in not enabled, wait\n"); + cdrom_command_bus(dev); + } else { + DEBUG("CD-ROM %i: DMA data in phase failure\n"); + cdrom_buf_free(dev); } return; - } + case CDROM_PHASE_ERROR: + DEBUG("CD-ROM %i: CDROM_PHASE_ERROR\n", dev->id); + dev->status = READY_STAT | ERR_STAT; + dev->phase = 3; + cdrom_irq_raise(dev); + ui_sb_icon_update(SB_CDROM | dev->id, 0); + return; + } } + +uint32_t +cdrom_read(uint8_t channel, int length) +{ + cdrom_t *dev; + + uint16_t *cdbufferw; + uint32_t *cdbufferl; + + uint8_t id = atapi_cdrom_drives[channel]; + + uint32_t temp = 0; + + if (id > CDROM_NUM) + return 0; + + dev = cdrom[id]; + + cdbufferw = (uint16_t *) cdbufferb; + cdbufferl = (uint32_t *) cdbufferb; + + if (!cdbufferb) + return 0; + + /* Make sure we return a 0 and don't attempt to read from the buffer if we're transferring bytes beyond it, + which can happen when issuing media access commands with an allocated length below minimum request length + (which is 1 sector = 2048 bytes). */ + switch(length) { + case 1: + temp = (dev->pos < dev->packet_len) ? cdbufferb[dev->pos] : 0; + dev->pos++; + dev->request_pos++; + break; + case 2: + temp = (dev->pos < dev->packet_len) ? cdbufferw[dev->pos >> 1] : 0; + dev->pos += 2; + dev->request_pos += 2; + break; + case 4: + temp = (dev->pos < dev->packet_len) ? cdbufferl[dev->pos >> 2] : 0; + dev->pos += 4; + dev->request_pos += 4; + break; + default: + return 0; + } + + if (dev->packet_status == CDROM_PHASE_DATA_IN) { + DEBUG("CD-ROM %i: Returning: %04X (buffer position: %05i, request position: %05i)\n", + id, temp, (dev->pos - 2) & 0xffff, (dev->request_pos - 2) & 0xffff); + if ((dev->request_pos >= dev->max_transfer_len) || (dev->pos >= dev->packet_len)) { + /* Time for a DRQ. */ + DEBUG("CD-ROM %i: Issuing read callback\n", id); + cdrom_pio_request(dev, 0); + } + return temp; + } else { + DEBUG("CD-ROM %i: Returning: 0000 (buffer position: %05i, request position: %05i)\n", + id, (dev->pos - 2) & 0xffff, (dev->request_pos - 2) & 0xffff); + return 0; + } +} + + +void +cdrom_write(uint8_t channel, uint32_t val, int length) +{ + cdrom_t *dev; + + uint16_t *cdbufferw; + uint32_t *cdbufferl; + + uint8_t id = atapi_cdrom_drives[channel]; + + if (id > CDROM_NUM) + return; + + dev = cdrom[id]; + + if ((dev->packet_status == CDROM_PHASE_IDLE) && !cdbufferb) + cdrom_buf_alloc(dev, dev->cdb_len); + + cdbufferw = (uint16_t *) cdbufferb; + cdbufferl = (uint32_t *) cdbufferb; + + if (!cdbufferb) + return; + + switch(length) { + case 1: + cdbufferb[dev->pos] = val & 0xff; + dev->pos++; + dev->request_pos++; + break; + case 2: + cdbufferw[dev->pos >> 1] = val & 0xffff; + dev->pos += 2; + dev->request_pos += 2; + break; + case 4: + cdbufferl[dev->pos >> 2] = val; + dev->pos += 4; + dev->request_pos += 4; + break; + default: + return; + } + + if (dev->packet_status == CDROM_PHASE_DATA_OUT) { + if ((dev->request_pos >= dev->max_transfer_len) || (dev->pos >= dev->packet_len)) { + /* Time for a DRQ. */ + cdrom_pio_request(dev, 1); + } + return; + } else if (dev->packet_status == CDROM_PHASE_IDLE) { + if (dev->pos >= dev->cdb_len) { + dev->pos = 0; + dev->status = BUSY_STAT; + dev->packet_status = CDROM_PHASE_COMMAND; + timer_process(); + cdrom_phase_callback(dev); + timer_update_outstanding(); + } + return; + } +} + + /* Peform a master init on the entire module. */ void cdrom_global_init(void) { - int c; - /* Clear the global data. */ memset(cdrom, 0x00, sizeof(cdrom)); memset(cdrom_drives, 0x00, sizeof(cdrom_drives)); - - /* Initialize the host devices, if any. */ - cdrom_init_host_drives(); - - /* Set all drives to NULL mode. */ - for (c=0; chandler and logging. */ + dev->id = c; + + cdrom_init(dev); + + if (dev->drv->host_drive == 200) { image_open(c, cdrom_image[c].image_path); image_reset(c); - } else -#ifdef USE_CDROM_IOCTL - if ((cdrom_drives[c].host_drive>='A') && (cdrom_drives[c].host_drive <= 'Z')) { - ioctl_open(c, cdrom_drives[c].host_drive); - ioctl_reset(c); } else -#endif - cdrom_null_open(c, cdrom_drives[c].host_drive); + cdrom_null_open(c); } + } - cdrom_mode_sense_load(c); + build_atapi_cdrom_map(); + + sound_cd_stop(); +} + + +void +cdrom_close_handler(uint8_t id) +{ + cdrom_t *dev = cdrom[id]; + + switch (dev->drv->host_drive) { + case 200: + image_close(id); + break; + default: + null_close(id); + break; } } void -cdrom_close(uint8_t id) +cdrom_close(void) { - switch (cdrom_drives[id].host_drive) { - case 0: - null_close(id); - break; - case 200: - image_close(id); - break; - default: -#ifdef USE_CDROM_IOCTL - ioctl_close(id); -#endif - break; + cdrom_t *dev; + int c; + + for (c = 0; c < CDROM_NUM; c++) { + dev = cdrom[c]; + + if (dev) { + if (dev->drv && dev->handler) + cdrom_close_handler(c); + + free(cdrom[c]); + cdrom[c] = NULL; + } } } + + +int +cdrom_string_to_bus(const char *str) +{ + int ret = CDROM_BUS_DISABLED; + + if (! strcmp(str, "none")) return(ret); + + if (! strcmp(str, "ide") || !strcmp(str, "atapi") +#if 1 + || !strcmp(str, "ide_pio_only") || !strcmp(str, "ide_pio_and_dma") + || !strcmp(str, "atapi_pio_only") || !strcmp(str, "atapi_pio_and_dma") +#endif + ) return(CDROM_BUS_ATAPI); + + if (! strcmp(str, "scsi")) + return(CDROM_BUS_SCSI); + + if (! strcmp(str, "usb")) + ui_msgbox(MBX_ERROR, (wchar_t *)IDS_ERR_NO_USB); + + return(ret); +} + + +const char * +cdrom_bus_to_string(int bus) +{ + const char *ret = "none"; + + switch (bus) { + case CDROM_BUS_DISABLED: + default: + break; + + case CDROM_BUS_ATAPI: + ret = "atapi"; + break; + + case CDROM_BUS_SCSI: + ret = "scsi"; + break; + } + + return(ret); +} diff --git a/src/devices/cdrom/cdrom.h b/src/devices/cdrom/cdrom.h index 6a0c8a7..a8195fe 100644 --- a/src/devices/cdrom/cdrom.h +++ b/src/devices/cdrom/cdrom.h @@ -8,7 +8,7 @@ * * Definitions for the CDROM module.. * - * Version: @(#)cdrom.h 1.0.10 2018/05/08 + * Version: @(#)cdrom.h 1.0.11 2018/09/19 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -39,206 +39,148 @@ #ifndef EMU_CDROM_H #define EMU_CDROM_H + #ifdef __cplusplus extern "C" { #endif -#define CDROM_NUM 4 +#define CDROM_NUM 4 -#define CDROM_SPEED_DEFAULT 8 +#define CDROM_SPEED_DEFAULT 8 -#define CD_STATUS_EMPTY 0 -#define CD_STATUS_DATA_ONLY 1 -#define CD_STATUS_PLAYING 2 -#define CD_STATUS_PAUSED 3 -#define CD_STATUS_STOPPED 4 +#define CD_STATUS_EMPTY 0 +#define CD_STATUS_DATA_ONLY 1 +#define CD_STATUS_PLAYING 2 +#define CD_STATUS_PAUSED 3 +#define CD_STATUS_STOPPED 4 -#define CDROM_PHASE_IDLE 0 -#define CDROM_PHASE_COMMAND 1 -#define CDROM_PHASE_COMPLETE 2 -#define CDROM_PHASE_DATA_IN 3 -#define CDROM_PHASE_DATA_IN_DMA 4 -#define CDROM_PHASE_DATA_OUT 5 -#define CDROM_PHASE_DATA_OUT_DMA 6 -#define CDROM_PHASE_ERROR 0x80 +#define CDROM_PHASE_IDLE 0x00 +#define CDROM_PHASE_COMMAND 0x01 +#define CDROM_PHASE_COMPLETE 0x02 +#define CDROM_PHASE_DATA_IN 0x03 +#define CDROM_PHASE_DATA_IN_DMA 0x04 +#define CDROM_PHASE_DATA_OUT 0x05 +#define CDROM_PHASE_DATA_OUT_DMA 0x06 +#define CDROM_PHASE_ERROR 0x80 -#define BUF_SIZE 32768 +#define BUF_SIZE 32768 -#define CDROM_IMAGE 200 +#define CDROM_IMAGE 200 -#define IDE_TIME (5LL * 100LL * (1LL << TIMER_SHIFT)) -#define CDROM_TIME (5LL * 100LL * (1LL << TIMER_SHIFT)) +#define CDROM_TIME (5LL * 100LL * (1LL << TIMER_SHIFT)) enum { CDROM_BUS_DISABLED = 0, - /* skip ST506 and ESDI */ - CDROM_BUS_ATAPI_PIO_ONLY = 3, - CDROM_BUS_ATAPI_PIO_AND_DMA, + CDROM_BUS_ATAPI, CDROM_BUS_SCSI, - CDROM_BUS_USB = 8 + CDROM_BUS_USB }; +#define CDROM_BUS_MAX (CDROM_BUS_USB) /* USB exclusive */ typedef struct { - int (*ready)(uint8_t id); - int (*medium_changed)(uint8_t id); - int (*media_type_id)(uint8_t id); + int (*ready)(uint8_t id); + int (*medium_changed)(uint8_t id); + int (*media_type_id)(uint8_t id); - void (*audio_callback)(uint8_t id, int16_t *output, int len); - void (*audio_stop)(uint8_t id); - int (*readtoc)(uint8_t id, uint8_t *b, uint8_t starttrack, int msf, int maxlen, int single); - int (*readtoc_session)(uint8_t id, uint8_t *b, int msf, int maxlen); - int (*readtoc_raw)(uint8_t id, uint8_t *b, int maxlen); - uint8_t (*getcurrentsubchannel)(uint8_t id, uint8_t *b, int msf); - int (*pass_through)(uint8_t id, uint8_t *in_cdb, uint8_t *b, uint32_t *len); - int (*readsector_raw)(uint8_t id, uint8_t *buffer, int sector, int ismsf, int cdrom_sector_type, int cdrom_sector_flags, int *len); - void (*playaudio)(uint8_t id, uint32_t pos, uint32_t len, int ismsf); - void (*load)(uint8_t id); - void (*eject)(uint8_t id); - void (*pause)(uint8_t id); - void (*resume)(uint8_t id); - uint32_t (*size)(uint8_t id); - int (*status)(uint8_t id); - int (*is_track_audio)(uint8_t id, uint32_t pos, int ismsf); - void (*stop)(uint8_t id); - void (*exit)(uint8_t id); + int (*audio_callback)(uint8_t id, int16_t *output, int len); + void (*audio_stop)(uint8_t id); + int (*readtoc)(uint8_t id, uint8_t *b, uint8_t starttrack, int msf, int maxlen, int single); + int (*readtoc_session)(uint8_t id, uint8_t *b, int msf, int maxlen); + int (*readtoc_raw)(uint8_t id, uint8_t *b, int maxlen); + uint8_t (*getcurrentsubchannel)(uint8_t id, uint8_t *b, int msf); + int (*readsector_raw)(uint8_t id, uint8_t *buffer, int sector, int ismsf, int cdrom_sector_type, int cdrom_sector_flags, int *len); + uint8_t (*playaudio)(uint8_t id, uint32_t pos, uint32_t len, int ismsf); + void (*pause)(uint8_t id); + void (*resume)(uint8_t id); + uint32_t (*size)(uint8_t id); + int (*status)(uint8_t id); + void (*stop)(uint8_t id); + void (*exit)(uint8_t id); } CDROM; typedef struct { - uint8_t previous_command; + int host_drive, + prev_host_drive; - int toctimes; - int media_status; - - int is_dma; - - int requested_blocks; /* This will be set to something other than 1 when block reads are implemented. */ - - uint64_t current_page_code; - int current_page_len; - - int current_page_pos; - - int mode_select_phase; - - int total_length; - int written_length; - - int do_page_save; - - uint8_t error; - uint8_t features; - uint16_t request_length; - uint16_t max_transfer_len; - uint8_t status; - uint8_t phase; - - uint32_t sector_pos; - uint32_t sector_len; - - uint32_t packet_len; - int packet_status; - - uint8_t atapi_cdb[16]; - uint8_t current_cdb[16]; - - uint32_t pos; - - int64_t callback; - - int data_pos; - uint32_t seek_diff; - - int cdb_len_setting; - int cdb_len; - - int cd_status; - int prev_status; - - int unit_attention; - uint8_t sense[256]; - - int request_pos; - - uint8_t *buffer; - - int times; - - uint32_t seek_pos; - - int total_read; - - int block_total; - int all_blocks_total; - - int old_len; - int block_descriptor_len; - - int init_length; - - int16_t cd_buffer[BUF_SIZE]; - - uint8_t rcbuf[16]; - uint8_t sub_q_data_format[16]; - uint8_t sub_q_channel_data[256]; - int last_subchannel_pos; - - uint32_t cd_end; - uint32_t cdrom_capacity; - - int cd_buflen; - int cd_state; - - int handler_inited; - int disc_changed; - - int cur_speed; -} cdrom_t; - -typedef struct { - CDROM *handler; - - int host_drive; - int prev_host_drive; - - unsigned int bus_type; /* 0 = ATAPI, 1 = SCSI */ - uint8_t bus_mode; /* Bit 0 = PIO suported; + int8_t bus_type, /* 0 = ATAPI, 1 = SCSI */ + bus_mode, /* Bit 0 = PIO suported; Bit 1 = DMA supportd. */ + sound_on, + speed_idx; - uint8_t ide_channel; - - unsigned int scsi_device_id; - unsigned int scsi_device_lun; - - unsigned int sound_on; - unsigned int atapi_dma; - - uint8_t speed_idx; /* index into table */ +#if 0 + union { + int ide_channel; + struct { + int8_t id; + int8_t lun; + } scsi; + } id; +#else + int ide_channel; + int8_t scsi_device_id, + scsi_device_lun; +#endif } cdrom_drive_t; typedef struct { - int image_is_iso; - wchar_t image_path[1024]; - wchar_t *prev_image_path; - FILE* image; + mode_sense_pages_t ms_pages_saved; + + CDROM *handler; + cdrom_drive_t *drv; + + uint8_t previous_command, + error, features, + status, phase, + id, *buffer, + atapi_cdb[16], + current_cdb[16], + sense[256]; + + uint16_t request_length, max_transfer_len; + int16_t cd_buffer[BUF_SIZE]; + + int media_status, is_dma, + packet_status, requested_blocks, + current_page_len, current_page_pos, + mode_select_phase, do_page_save, + total_length, written_length, + data_pos, + cd_status, prev_status, + unit_attention, request_pos, + total_read, cur_speed, + block_total, all_blocks_total, + old_len, block_descriptor_len, + init_length, last_subchannel_pos, + cd_buflen, cd_state, + handler_inited, disc_changed; + + uint32_t sector_pos, sector_len, + seek_pos, seek_diff, + pos, packet_len, + cdb_len, cd_end, + cdrom_capacity; + + uint64_t current_page_code; + + int64_t callback; +} cdrom_t; + +typedef struct { + int image_is_iso; + FILE *image; + + wchar_t image_path[1024], + *prev_image_path; } cdrom_image_t; -#ifdef USE_CDROM_IOCTL typedef struct { - char ioctl_path[8]; - int actual_requested_blocks; - int last_track_pos; - int last_track_nr; - int capacity_read; -} cdrom_ioctl_t; -#endif - -typedef struct { - int8_t speed; - double seek1; - double seek2; + int speed; + double seek1; + double seek2; } cdrom_speed_t; @@ -247,55 +189,52 @@ extern const cdrom_speed_t cdrom_speeds[]; extern cdrom_t *cdrom[CDROM_NUM]; extern cdrom_drive_t cdrom_drives[CDROM_NUM]; extern cdrom_image_t cdrom_image[CDROM_NUM]; -#ifdef USE_CDROM_IOCTL -extern cdrom_ioctl_t cdrom_ioctl[CDROM_NUM]; -#endif extern uint8_t atapi_cdrom_drives[8]; extern uint8_t scsi_cdrom_drives[16][8]; -#define cdrom_sense_error cdrom[id]->sense[0] -#define cdrom_sense_key cdrom[id]->sense[2] -#define cdrom_asc cdrom[id]->sense[12] -#define cdrom_ascq cdrom[id]->sense[13] -#define cdrom_drive cdrom_drives[id].host_drive - -extern int (*ide_bus_master_read)(int channel, uint8_t *data, int transfer_length); -extern int (*ide_bus_master_write)(int channel, uint8_t *data, int transfer_length); -extern void (*ide_bus_master_set_irq)(int channel); -#ifdef USE_CDROM_IOCTL -extern void ioctl_close(uint8_t id); -#endif +#define cdrom_sense_error dev->sense[0] +#define cdrom_sense_key dev->sense[2] +#define cdrom_asc dev->sense[12] +#define cdrom_ascq dev->sense[13] +#define cdrom_drive cdrom_drives[id].host_drive +extern void cdrom_log(int level, const char *fmt, ...); extern int cdrom_speed_idx(int realspeed); -extern uint32_t cdrom_mode_sense_get_channel(uint8_t id, int channel); -extern uint32_t cdrom_mode_sense_get_volume(uint8_t id, int channel); +extern int (*ide_bus_master_read)(int channel, uint8_t *data, int transfer_length, void *priv); +extern int (*ide_bus_master_write)(int channel, uint8_t *data, int transfer_length, void *priv); +extern void (*ide_bus_master_set_irq)(int channel, void *priv); +extern void *ide_bus_master_priv[2]; + +extern uint32_t cdrom_mode_sense_get_channel(cdrom_t *dev, int channel); +extern uint32_t cdrom_mode_sense_get_volume(cdrom_t *dev, int channel); extern void build_atapi_cdrom_map(void); extern void build_scsi_cdrom_map(void); -extern int cdrom_CDROM_PHASE_to_scsi(uint8_t id); -extern int cdrom_atapi_phase_to_scsi(uint8_t id); -extern void cdrom_command(uint8_t id, uint8_t *cdb); -extern void cdrom_phase_callback(uint8_t id); +extern int cdrom_CDROM_PHASE_to_scsi(cdrom_t *dev); +extern int cdrom_atapi_phase_to_scsi(cdrom_t *dev); +extern void cdrom_command(cdrom_t *dev, uint8_t *cdb); +extern void cdrom_phase_callback(cdrom_t *dev); extern uint32_t cdrom_read(uint8_t channel, int length); extern void cdrom_write(uint8_t channel, uint32_t val, int length); extern int cdrom_lba_to_msf_accurate(int lba); -extern void cdrom_destroy_drives(void); -extern void cdrom_close(uint8_t id); -extern void cdrom_reset(uint8_t id); -extern void cdrom_set_signature(int id); -extern void cdrom_request_sense_for_scsi(uint8_t id, uint8_t *buffer, uint8_t alloc_length); +extern void cdrom_close_handler(uint8_t id); +extern void cdrom_close(void); +extern void cdrom_reset(cdrom_t *dev); +extern void cdrom_set_signature(cdrom_t *dev); +extern void cdrom_request_sense_for_scsi(cdrom_t *dev, uint8_t *buffer, uint8_t alloc_length); extern void cdrom_update_cdb(uint8_t *cdb, int lba_pos, int number_of_blocks); -extern void cdrom_insert(uint8_t id); -extern void cdrom_new_image(uint8_t id); +extern void cdrom_insert(cdrom_t *dev); extern int find_cdrom_for_scsi_id(uint8_t scsi_id, uint8_t scsi_lun); -extern int cdrom_read_capacity(uint8_t id, uint8_t *cdb, uint8_t *buffer, uint32_t *len); +extern int cdrom_read_capacity(cdrom_t *dev, uint8_t *cdb, uint8_t *buffer, uint32_t *len); extern void cdrom_global_init(void); extern void cdrom_global_reset(void); extern void cdrom_hard_reset(void); +extern int cdrom_string_to_bus(const char *str); +extern const char *cdrom_bus_to_string(int bus); #ifdef __cplusplus } diff --git a/src/devices/cdrom/cdrom_dosbox.cpp b/src/devices/cdrom/cdrom_dosbox.cpp index 876f032..f1cf21f 100644 --- a/src/devices/cdrom/cdrom_dosbox.cpp +++ b/src/devices/cdrom/cdrom_dosbox.cpp @@ -8,7 +8,7 @@ * * CD-ROM image file handling module. * - * Version: @(#)cdrom_dosbox.cpp 1.0.7 2018/05/06 + * Version: @(#)cdrom_dosbox.cpp 1.0.9 2018/09/25 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -53,6 +53,10 @@ #include #include #include +#ifdef ERROR +# undef ERROR +#endif +#include "../../emu.h" #include "../../plat.h" #include "cdrom_dosbox.h" @@ -70,606 +74,689 @@ using namespace std; #define safe_strncpy(a,b,n) do { strncpy((a),(b),(n)-1); (a)[(n)-1] = 0; } while (0) + + +//FIXME: update to use plat_fopen and wchar! CDROM_Interface_Image::BinaryFile::BinaryFile(const char *filename, bool &error) { - memset(fn, 0, sizeof(fn)); - strcpy(fn, filename); - file = fopen64(fn, "rb"); - if (file == NULL) - error = true; - else - error = false; + memset(fn, 0x00, sizeof(fn)); + strcpy(fn, filename); + file = fopen64(fn, "rb"); + if (file == NULL) + error = true; + else + error = false; } -CDROM_Interface_Image::BinaryFile::~BinaryFile() + +CDROM_Interface_Image::BinaryFile::~BinaryFile(void) { - if (file != NULL) { - fclose(file); - file = NULL; - } - memset(fn, 0, sizeof(fn)); + if (file != NULL) { + fclose(file); + file = NULL; + } + memset(fn, 0x00, sizeof(fn)); } -bool CDROM_Interface_Image::BinaryFile::read(Bit8u *buffer, uint64_t seek, size_t count) + +bool +CDROM_Interface_Image::BinaryFile::read(Bit8u *buffer, uint64_t seek, size_t count) { - if (file == NULL) return 0; - fseeko64(file, seek, SEEK_SET); - fread(buffer, 1, count, file); - return 1; + if (file == NULL) return 0; + + fseeko64(file, seek, SEEK_SET); + fread(buffer, 1, count, file); + + return 1; } -uint64_t CDROM_Interface_Image::BinaryFile::getLength() + +uint64_t +CDROM_Interface_Image::BinaryFile::getLength(void) { - if (file == NULL) return 0; - fseeko64(file, 0, SEEK_END); - return ftello64(file); + if (file == NULL) return 0; + + fseeko64(file, 0, SEEK_END); + + return ftello64(file); } -CDROM_Interface_Image::CDROM_Interface_Image() + +CDROM_Interface_Image::CDROM_Interface_Image(void) { } -CDROM_Interface_Image::~CDROM_Interface_Image() + +CDROM_Interface_Image::~CDROM_Interface_Image(void) { - ClearTracks(); + ClearTracks(); } -void CDROM_Interface_Image::InitNewMedia() + +void +CDROM_Interface_Image::InitNewMedia(void) { } -bool CDROM_Interface_Image::SetDevice(char* path, int forceCD) + +bool +CDROM_Interface_Image::SetDevice(char* path, int forceCD) { - (void)forceCD; - if (LoadCueSheet(path)) return true; - if (LoadIsoFile(path)) return true; + (void)forceCD; + if (LoadCueSheet(path)) return true; + if (LoadIsoFile(path)) return true; - // print error message on dosbox console - //printf("Could not load image file: %s\n", path); + // print error message on dosbox console + //printf("Could not load image file: %s\n", path); + return false; +} + + +bool +CDROM_Interface_Image::GetUPC(unsigned char& attr, char* upc) +{ + attr = 0; + strcpy(upc, this->mcn.c_str()); + + return true; +} + + +bool +CDROM_Interface_Image::GetAudioTracks(int& stTrack, int& end, TMSF& leadOut) +{ + stTrack = 1; + end = (int)(tracks.size() - 1); + FRAMES_TO_MSF(tracks[tracks.size() - 1].start + 150, &leadOut.min, &leadOut.sec, &leadOut.fr); + + return true; +} + + +bool +CDROM_Interface_Image::GetAudioTrackInfo(int track, int& track_number, TMSF& start, unsigned char& attr) +{ + if (track < 1 || track > (int)tracks.size()) return false; + + FRAMES_TO_MSF(tracks[track - 1].start + 150, &start.min, &start.sec, &start.fr); + track_number = tracks[track - 1].track_number; + attr = tracks[track - 1].attr; + + return true; +} + + +bool +CDROM_Interface_Image::GetAudioSub(int sector, unsigned char& attr, unsigned char& track, unsigned char& index, TMSF& relPos, TMSF& absPos) +{ + int cur_track = GetTrack(sector); + + if (cur_track < 1) return false; + + track = (unsigned char)cur_track; + attr = tracks[track - 1].attr; + index = 1; + +#if 1 + FRAMES_TO_MSF(sector + 150, &absPos.min, &absPos.sec, &absPos.fr); +#else + FRAMES_TO_MSF(sector - tracks[track - 1].start + 150, &relPos.min, &relPos.sec, &relPos.fr); +#endif + + /* Yes, the absolute position should be adjusted by 150, but not the relative position. */ + FRAMES_TO_MSF(sector - tracks[track - 1].start, &relPos.min, &relPos.sec, &relPos.fr); + + return true; +} + + +bool +CDROM_Interface_Image::GetMediaTrayStatus(bool& mediaPresent, bool& mediaChanged, bool& trayOpen) +{ + mediaPresent = true; + mediaChanged = false; + trayOpen = false; + + return true; +} + + +bool +CDROM_Interface_Image::ReadSectors(PhysPt buffer, bool raw, unsigned long sector, unsigned long num) +{ + int sectorSize = raw ? RAW_SECTOR_SIZE : COOKED_SECTOR_SIZE; + Bitu buflen = num * sectorSize; + Bit8u* buf = new Bit8u[buflen]; + + bool success = true; //Gobliiins reads 0 sectors + for (unsigned long i = 0; i < num; i++) { + success = ReadSector(&buf[i * sectorSize], raw, sector + i); + if (!success) break; + } + + memcpy((void*)buffer, buf, buflen); + delete[] buf; + + return success; +} + + +bool +CDROM_Interface_Image::LoadUnloadMedia(bool unload) +{ + (void)unload; + + return true; +} + + +int +CDROM_Interface_Image::GetTrack(unsigned int sector) +{ + vector::iterator i = tracks.begin(); + vector::iterator end = tracks.end() - 1; + + while (i != end) { + Track &curr = *i; + Track &next = *(i + 1); + if (curr.start <= sector && sector < next.start) return curr.number; + i++; + } + + return -1; +} + + +bool +CDROM_Interface_Image::ReadSector(Bit8u *buffer, bool raw, unsigned long sector) +{ + size_t length; + + int track = GetTrack(sector) - 1; + if (track < 0) return false; + + uint64_t s = (uint64_t) sector; + uint64_t seek = tracks[track].skip + ((s - tracks[track].start) * tracks[track].sectorSize); + if (tracks[track].mode2) + length = (raw ? RAW_SECTOR_SIZE : 2336); + else + length = (raw ? RAW_SECTOR_SIZE : COOKED_SECTOR_SIZE); + if (tracks[track].sectorSize != RAW_SECTOR_SIZE && raw) return false; + if (tracks[track].sectorSize == RAW_SECTOR_SIZE && !tracks[track].mode2 && !raw) seek += 16; + if (tracks[track].mode2 && !raw) seek += 24; + + return tracks[track].file->read(buffer, seek, length); +} + + +bool +CDROM_Interface_Image::ReadSectorSub(Bit8u *buffer, unsigned long sector) +{ + int track = GetTrack(sector) - 1; + if (track < 0) return false; + + uint64_t s = (uint64_t) sector; + uint64_t seek = tracks[track].skip + ((s - tracks[track].start) * tracks[track].sectorSize); + if (tracks[track].sectorSize != 2448) return false; + + return tracks[track].file->read(buffer, seek, 2448); +} + + +int +CDROM_Interface_Image::GetSectorSize(unsigned long sector) +{ + int track = GetTrack(sector) - 1; + if (track < 0) return 0; + + return tracks[track].sectorSize; +} + + +bool +CDROM_Interface_Image::IsMode2(unsigned long sector) +{ + int track = GetTrack(sector) - 1; + if (track < 0) return false; + + if (tracks[track].mode2) { + return true; + } else { return false; + } } -bool CDROM_Interface_Image::GetUPC(unsigned char& attr, char* upc) + +int +CDROM_Interface_Image::GetMode2Form(unsigned long sector) { - attr = 0; - strcpy(upc, this->mcn.c_str()); - return true; + int track = GetTrack(sector) - 1; + if (track < 0) return false; + + return tracks[track].form; } -bool CDROM_Interface_Image::GetAudioTracks(int& stTrack, int& end, TMSF& leadOut) -{ - stTrack = 1; - end = (int)(tracks.size() - 1); - FRAMES_TO_MSF(tracks[tracks.size() - 1].start + 150, &leadOut.min, &leadOut.sec, &leadOut.fr); - return true; -} -bool CDROM_Interface_Image::GetAudioTrackInfo(int track, int& track_number, TMSF& start, unsigned char& attr) +bool +CDROM_Interface_Image::LoadIsoFile(char* filename) { - if (track < 1 || track > (int)tracks.size()) return false; - FRAMES_TO_MSF(tracks[track - 1].start + 150, &start.min, &start.sec, &start.fr); - track_number = tracks[track - 1].track_number; - attr = tracks[track - 1].attr; - return true; -} - -bool CDROM_Interface_Image::GetAudioSub(int sector, unsigned char& attr, unsigned char& track, unsigned char& index, TMSF& relPos, TMSF& absPos) -{ - int cur_track = GetTrack(sector); - if (cur_track < 1) return false; - track = (unsigned char)cur_track; - attr = tracks[track - 1].attr; - index = 1; - FRAMES_TO_MSF(sector + 150, &absPos.min, &absPos.sec, &absPos.fr); - /* FRAMES_TO_MSF(sector - tracks[track - 1].start + 150, &relPos.min, &relPos.sec, &relPos.fr); */ - /* Note by Kotori: Yes, the absolute position should be adjusted by 150, but not the relative position. */ - FRAMES_TO_MSF(sector - tracks[track - 1].start, &relPos.min, &relPos.sec, &relPos.fr); - return true; -} - -bool CDROM_Interface_Image::GetMediaTrayStatus(bool& mediaPresent, bool& mediaChanged, bool& trayOpen) -{ - mediaPresent = true; - mediaChanged = false; - trayOpen = false; - return true; -} - -bool CDROM_Interface_Image::ReadSectors(PhysPt buffer, bool raw, unsigned long sector, unsigned long num) -{ - int sectorSize = raw ? RAW_SECTOR_SIZE : COOKED_SECTOR_SIZE; - Bitu buflen = num * sectorSize; - Bit8u* buf = new Bit8u[buflen]; + tracks.clear(); - bool success = true; //Gobliiins reads 0 sectors - for(unsigned long i = 0; i < num; i++) { - success = ReadSector(&buf[i * sectorSize], raw, sector + i); - if (!success) break; - } + // data track + Track track = {0, 0, 0, 0, 0, 0, 0, 0, false, NULL}; + bool error; + track.file = new BinaryFile(filename, error); + if (error) { + delete track.file; + return false; + } + track.number = 1; + track.track_number = 1; //IMPORTANT: This is needed. + track.attr = DATA_TRACK; //data + track.form = 0; - memcpy((void*)buffer, buf, buflen); - delete[] buf; - - return success; -} - -bool CDROM_Interface_Image::LoadUnloadMedia(bool unload) -{ - (void)unload; - return true; -} - -int CDROM_Interface_Image::GetTrack(unsigned int sector) -{ - vector::iterator i = tracks.begin(); - vector::iterator end = tracks.end() - 1; - - while(i != end) { - Track &curr = *i; - Track &next = *(i + 1); - if (curr.start <= sector && sector < next.start) return curr.number; - i++; - } - return -1; -} - -bool CDROM_Interface_Image::ReadSector(Bit8u *buffer, bool raw, unsigned long sector) -{ - size_t length; - - int track = GetTrack(sector) - 1; - if (track < 0) return false; - - uint64_t s = (uint64_t) sector; - uint64_t seek = tracks[track].skip + ((s - tracks[track].start) * tracks[track].sectorSize); - if (tracks[track].mode2) - length = (raw ? RAW_SECTOR_SIZE : 2336); - else - length = (raw ? RAW_SECTOR_SIZE : COOKED_SECTOR_SIZE); - if (tracks[track].sectorSize != RAW_SECTOR_SIZE && raw) return false; - if (tracks[track].sectorSize == RAW_SECTOR_SIZE && !tracks[track].mode2 && !raw) seek += 16; - if (tracks[track].mode2 && !raw) seek += 24; - - return tracks[track].file->read(buffer, seek, length); -} - -bool CDROM_Interface_Image::ReadSectorSub(Bit8u *buffer, unsigned long sector) -{ - int track = GetTrack(sector) - 1; - if (track < 0) return false; - - uint64_t s = (uint64_t) sector; - uint64_t seek = tracks[track].skip + ((s - tracks[track].start) * tracks[track].sectorSize); - if (tracks[track].sectorSize != 2448) return false; - - return tracks[track].file->read(buffer, seek, 2448); -} - -int CDROM_Interface_Image::GetSectorSize(unsigned long sector) -{ - int track = GetTrack(sector) - 1; - if (track < 0) return 0; - - return tracks[track].sectorSize; -} - -bool CDROM_Interface_Image::IsMode2(unsigned long sector) -{ - int track = GetTrack(sector) - 1; - if (track < 0) return false; - - if (tracks[track].mode2) - { - return true; - } - else - { - return false; - } -} - -int CDROM_Interface_Image::GetMode2Form(unsigned long sector) -{ - int track = GetTrack(sector) - 1; - if (track < 0) return false; - - return tracks[track].form; -} - -bool CDROM_Interface_Image::LoadIsoFile(char* filename) -{ - tracks.clear(); - - // data track - Track track = {0, 0, 0, 0, 0, 0, 0, 0, false, NULL}; - bool error; - track.file = new BinaryFile(filename, error); - if (error) { - delete track.file; - return false; - } - track.number = 1; - track.track_number = 1;//IMPORTANT: This is needed. - track.attr = DATA_TRACK;//data - track.form = 0; - - // try to detect iso type - if (CanReadPVD(track.file, COOKED_SECTOR_SIZE, false)) { + // try to detect iso type + if (CanReadPVD(track.file, COOKED_SECTOR_SIZE, false)) { + track.sectorSize = COOKED_SECTOR_SIZE; + track.mode2 = false; + } else if (CanReadPVD(track.file, RAW_SECTOR_SIZE, false)) { + track.sectorSize = RAW_SECTOR_SIZE; + track.mode2 = false; + } else if (CanReadPVD(track.file, 2336, true)) { + track.sectorSize = 2336; + track.mode2 = true; + } else if (CanReadPVD(track.file, 2324, true)) { + track.sectorSize = 2324; + track.form = 2; + track.mode2 = true; + } else if (CanReadPVD(track.file, RAW_SECTOR_SIZE, true)) { + track.sectorSize = RAW_SECTOR_SIZE; + track.mode2 = true; + } else { + /* Unknown mode: Assume regular 2048-byte sectors, this is needed so Apple Rhapsody ISO's can be mounted. */ track.sectorSize = COOKED_SECTOR_SIZE; track.mode2 = false; - } else if (CanReadPVD(track.file, RAW_SECTOR_SIZE, false)) { - track.sectorSize = RAW_SECTOR_SIZE; - track.mode2 = false; - } else if (CanReadPVD(track.file, 2336, true)) { - track.sectorSize = 2336; - track.mode2 = true; - } else if (CanReadPVD(track.file, 2324, true)) { - track.sectorSize = 2324; - track.form = 2; - track.mode2 = true; - } else if (CanReadPVD(track.file, RAW_SECTOR_SIZE, true)) { - track.sectorSize = RAW_SECTOR_SIZE; - track.mode2 = true; - } else { - /* Unknown mode: Assume regular 2048-byte sectors, this is needed so Apple Rhapsody ISO's can be mounted. */ - track.sectorSize = COOKED_SECTOR_SIZE; - track.mode2 = false; - } - - track.length = track.file->getLength() / track.sectorSize; - tracks.push_back(track); - - // leadout track - track.number = 2; - track.track_number = 0xAA; - track.attr = 0x16; /* Was 0x00 but I believe 0x16 is appropriate. */ - track.start = track.length; - track.length = 0; - track.file = NULL; - tracks.push_back(track); + } - return true; + track.length = track.file->getLength() / track.sectorSize; + tracks.push_back(track); + + // leadout track + track.number = 2; + track.track_number = 0xAA; + track.attr = 0x16; /* Was 0x00 but I believe 0x16 is appropriate. */ + track.start = track.length; + track.length = 0; + track.file = NULL; + tracks.push_back(track); + + return true; } -bool CDROM_Interface_Image::CanReadPVD(TrackFile *file, uint64_t sectorSize, bool mode2) + +bool +CDROM_Interface_Image::CanReadPVD(TrackFile *file, uint64_t sectorSize, bool mode2) { - Bit8u pvd[COOKED_SECTOR_SIZE]; - uint64_t seek = 16 * sectorSize; // first vd is located at sector 16 - if (sectorSize == RAW_SECTOR_SIZE && !mode2) seek += 16; - if (mode2) seek += 24; - file->read(pvd, seek, COOKED_SECTOR_SIZE); - // pvd[0] = descriptor type, pvd[1..5] = standard identifier, pvd[6] = iso version (+8 for High Sierra) - return ((pvd[0] == 1 && !strncmp((char*)(&pvd[1]), "CD001", 5) && pvd[6] == 1) || - (pvd[8] == 1 && !strncmp((char*)(&pvd[9]), "CDROM", 5) && pvd[14] == 1)); + Bit8u pvd[COOKED_SECTOR_SIZE]; + uint64_t seek = 16 * sectorSize; // first vd is located at sector 16 + + if (sectorSize == RAW_SECTOR_SIZE && !mode2) seek += 16; + if (mode2) seek += 24; + + file->read(pvd, seek, COOKED_SECTOR_SIZE); + +#if 0 + pvd[0] = descriptor type, pvd[1..5] = standard identifier, pvd[6] = iso version (+8 for High Sierra) +#endif + + return ((pvd[0] == 1 && !strncmp((char*)(&pvd[1]), "CD001", 5) && pvd[6] == 1) || + (pvd[8] == 1 && !strncmp((char*)(&pvd[9]), "CDROM", 5) && pvd[14] == 1)); } + #ifdef _WIN32 -static string dirname(char * file) { - char * sep = strrchr(file, '\\'); - if (sep == NULL) - sep = strrchr(file, '/'); - if (sep == NULL) - return ""; - else { - int len = (int)(sep - file); - char tmp[MAX_FILENAME_LENGTH]; - safe_strncpy(tmp, file, len+1); - return tmp; - } +static string +dirname(char * file) +{ + char *sep = strrchr(file, '\\'); + + if (sep == NULL) + sep = strrchr(file, '/'); + if (sep == NULL) + return ""; + else { + int len = (int)(sep - file); + char tmp[MAX_FILENAME_LENGTH]; + safe_strncpy(tmp, file, len+1); + return tmp; + } } #endif -bool CDROM_Interface_Image::LoadCueSheet(char *cuefile) + +bool +CDROM_Interface_Image::LoadCueSheet(char *cuefile) { - Track track = {0, 0, 0, 0, 0, 0, 0, 0, false, NULL}; - tracks.clear(); - uint64_t shift = 0; - uint64_t currPregap = 0; - uint64_t totalPregap = 0; - uint64_t prestart = 0; - bool success; - bool canAddTrack = false; - char tmp[MAX_FILENAME_LENGTH]; // dirname can change its argument - safe_strncpy(tmp, cuefile, MAX_FILENAME_LENGTH); - string pathname(dirname(tmp)); - ifstream in; - in.open(cuefile, ios::in); - if (in.fail()) return false; -// int last_attr = 0x00; + Track track = {0, 0, 0, 0, 0, 0, 0, 0, false, NULL}; + tracks.clear(); - while(!in.eof()) { - // get next line - char buf[MAX_LINE_LENGTH]; - in.getline(buf, MAX_LINE_LENGTH); - if (in.fail() && !in.eof()) return false; // probably a binary file - istringstream line(buf); + uint64_t shift = 0; + uint64_t currPregap = 0; + uint64_t totalPregap = 0; + uint64_t prestart = 0; + bool success; + bool canAddTrack = false; + char tmp[MAX_FILENAME_LENGTH]; // dirname can change its argument - string command; - GetCueKeyword(command, line); + safe_strncpy(tmp, cuefile, MAX_FILENAME_LENGTH); + string pathname(dirname(tmp)); + ifstream in; + in.open(cuefile, ios::in); + if (in.fail()) return false; - if (command == "TRACK") { - if (canAddTrack) success = AddTrack(track, shift, prestart, totalPregap, currPregap); - else success = true; + while (!in.eof()) { + // get next line + char buf[MAX_LINE_LENGTH]; + in.getline(buf, MAX_LINE_LENGTH); + if (in.fail() && !in.eof()) return false; // probably a binary file + istringstream line(buf); - track.start = 0; - track.skip = 0; - currPregap = 0; - prestart = 0; + string command; + GetCueKeyword(command, line); - line >> track.number; - track.track_number = track.number; - string type; - GetCueKeyword(type, line); + if (command == "TRACK") { + if (canAddTrack) success = AddTrack(track, shift, prestart, totalPregap, currPregap); + else success = true; - track.form = 0; + track.start = 0; + track.skip = 0; + currPregap = 0; + prestart = 0; - if (type == "AUDIO") { - track.sectorSize = RAW_SECTOR_SIZE; - track.attr = AUDIO_TRACK; - track.mode2 = false; - } else if (type == "MODE1/2048") { - track.sectorSize = COOKED_SECTOR_SIZE; - track.attr = DATA_TRACK; - track.mode2 = false; - } else if (type == "MODE1/2352") { - track.sectorSize = RAW_SECTOR_SIZE; - track.attr = DATA_TRACK; - track.mode2 = false; - } else if (type == "MODE2/2048") { - track.form = 1; - track.sectorSize = 2048; - track.attr = DATA_TRACK; - track.mode2 = true; - } else if (type == "MODE2/2324") { - track.form = 2; - track.sectorSize = 2324; - track.attr = DATA_TRACK; - track.mode2 = true; - } else if (type == "MODE2/2336") { - track.sectorSize = 2336; - track.attr = DATA_TRACK; - track.mode2 = true; - } else if (type == "MODE2/2352") { - track.form = 1; /* Assume this is XA Mode 2 Form 1. */ - track.sectorSize = RAW_SECTOR_SIZE; - track.attr = DATA_TRACK; - track.mode2 = true; - } else if (type == "CDG/2448") { - track.sectorSize = 2448; - track.attr = DATA_TRACK; - track.mode2 = true; - } else if (type == "CDI/2336") { - track.sectorSize = 2336; - track.attr = DATA_TRACK; - track.mode2 = true; - } else if (type == "CDI/2352") { - track.sectorSize = RAW_SECTOR_SIZE; - track.attr = DATA_TRACK; - track.mode2 = true; - } else success = false; -// last_attr = track.attr; + line >> track.number; + track.track_number = track.number; + string type; + GetCueKeyword(type, line); - canAddTrack = true; + track.form = 0; + + if (type == "AUDIO") { + track.sectorSize = RAW_SECTOR_SIZE; + track.attr = AUDIO_TRACK; + track.mode2 = false; + } else if (type == "MODE1/2048") { + track.sectorSize = COOKED_SECTOR_SIZE; + track.attr = DATA_TRACK; + track.mode2 = false; + } else if (type == "MODE1/2352") { + track.sectorSize = RAW_SECTOR_SIZE; + track.attr = DATA_TRACK; + track.mode2 = false; + } else if (type == "MODE2/2048") { + track.form = 1; + track.sectorSize = 2048; + track.attr = DATA_TRACK; + track.mode2 = true; + } else if (type == "MODE2/2324") { + track.form = 2; + track.sectorSize = 2324; + track.attr = DATA_TRACK; + track.mode2 = true; + } else if (type == "MODE2/2336") { + track.sectorSize = 2336; + track.attr = DATA_TRACK; + track.mode2 = true; + } else if (type == "MODE2/2352") { + track.form = 1; /* Assume this is XA Mode 2 Form 1. */ + track.sectorSize = RAW_SECTOR_SIZE; + track.attr = DATA_TRACK; + track.mode2 = true; + } else if (type == "CDG/2448") { + track.sectorSize = 2448; + track.attr = DATA_TRACK; + track.mode2 = true; + } else if (type == "CDI/2336") { + track.sectorSize = 2336; + track.attr = DATA_TRACK; + track.mode2 = true; + } else if (type == "CDI/2352") { + track.sectorSize = RAW_SECTOR_SIZE; + track.attr = DATA_TRACK; + track.mode2 = true; + } else success = false; + + canAddTrack = true; + } else if (command == "INDEX") { + uint64_t index; + line >> index; + uint64_t frame; + success = GetCueFrame(frame, line); + + if (index == 1) track.start = frame; + else if (index == 0) prestart = frame; + // ignore other indices + } else if (command == "FILE") { + if (canAddTrack) success = AddTrack(track, shift, prestart, totalPregap, currPregap); + else success = true; + canAddTrack = false; + + string filename; + GetCueString(filename, line); + GetRealFileName(filename, pathname); + string type; + GetCueKeyword(type, line); + + track.file = NULL; + bool error = true; + if (type == "BINARY") { + track.file = new BinaryFile(filename.c_str(), error); } - else if (command == "INDEX") { - uint64_t index; - line >> index; - uint64_t frame; - success = GetCueFrame(frame, line); - - if (index == 1) track.start = frame; - else if (index == 0) prestart = frame; - // ignore other indices + if (error) { + delete track.file; + success = false; } - else if (command == "FILE") { - if (canAddTrack) success = AddTrack(track, shift, prestart, totalPregap, currPregap); - else success = true; - canAddTrack = false; + } else if (command == "PREGAP") success = GetCueFrame(currPregap, line); + else if (command == "CATALOG") success = GetCueString(mcn, line); + // ignored commands + else if (command == "CDTEXTFILE" || command == "FLAGS" || command == "ISRC" + || command == "PERFORMER" || command == "POSTGAP" || command == "REM" + || command == "SONGWRITER" || command == "TITLE" || command == "") success = true; + // failure + else success = false; - string filename; - GetCueString(filename, line); - GetRealFileName(filename, pathname); - string type; - GetCueKeyword(type, line); + if (!success) return false; + } - track.file = NULL; - bool error = true; - if (type == "BINARY") { - track.file = new BinaryFile(filename.c_str(), error); - } - if (error) { - delete track.file; - success = false; - } - } - else if (command == "PREGAP") success = GetCueFrame(currPregap, line); - else if (command == "CATALOG") success = GetCueString(mcn, line); - // ignored commands - else if (command == "CDTEXTFILE" || command == "FLAGS" || command == "ISRC" - || command == "PERFORMER" || command == "POSTGAP" || command == "REM" - || command == "SONGWRITER" || command == "TITLE" || command == "") success = true; - // failure - else success = false; + // add last track + if (!AddTrack(track, shift, prestart, totalPregap, currPregap)) return false; - if (!success) return false; - } - // add last track - if (!AddTrack(track, shift, prestart, totalPregap, currPregap)) return false; + // add leadout track + track.number++; + track.track_number = 0xAA; + // track.attr = 0;//sync with load iso + track.attr = 0x16; /* Was 0x00 but I believe 0x16 is appropriate. */ + track.start = 0; + track.length = 0; + track.file = NULL; + if(!AddTrack(track, shift, 0, totalPregap, 0)) return false; - // add leadout track - track.number++; - track.track_number = 0xAA; - // track.attr = 0;//sync with load iso - track.attr = 0x16; /* Was 0x00 but I believe 0x16 is appropriate. */ - // track.attr = last_attr | 0x02; - track.start = 0; - track.length = 0; - track.file = NULL; - if(!AddTrack(track, shift, 0, totalPregap, 0)) return false; - - return true; + return true; } -bool CDROM_Interface_Image::AddTrack(Track &curr, uint64_t &shift, uint64_t prestart, uint64_t &totalPregap, uint64_t currPregap) + +bool +CDROM_Interface_Image::AddTrack(Track &curr, uint64_t &shift, uint64_t prestart, uint64_t &totalPregap, uint64_t currPregap) { - // frames between index 0(prestart) and 1(curr.start) must be skipped - uint64_t skip; - if (prestart > 0) { - if (prestart > curr.start) return false; - skip = curr.start - prestart; - } else skip = 0; + // frames between index 0(prestart) and 1(curr.start) must be skipped + uint64_t skip; - // first track (track number must be 1) - if (tracks.empty()) { - if (curr.number != 1) return false; - curr.skip = skip * curr.sectorSize; - curr.start += currPregap; - totalPregap = currPregap; - tracks.push_back(curr); - return true; - } - - Track &prev = *(tracks.end() - 1); - - // current track consumes data from the same file as the previous - if (prev.file == curr.file) { - curr.start += shift; - prev.length = curr.start + totalPregap - prev.start - skip; - curr.skip += prev.skip + (prev.length * prev.sectorSize) + (skip * curr.sectorSize); - totalPregap += currPregap; - curr.start += totalPregap; - // current track uses a different file as the previous track - } else { - uint64_t tmp = prev.file->getLength() - ((uint64_t) prev.skip); - prev.length = tmp / ((uint64_t) prev.sectorSize); - if (tmp % prev.sectorSize != 0) prev.length++; // padding - - curr.start += prev.start + prev.length + currPregap; - curr.skip = skip * curr.sectorSize; - shift += prev.start + prev.length; - totalPregap = currPregap; - } - - // error checks - if (curr.number <= 1) return false; - if (prev.number + 1 != curr.number) return false; - if (curr.start < prev.start + prev.length) return false; -#if 0 - /* curr.length is unsigned, so... --FvK */ - if (curr.length < 0) return false; -#endif + if (prestart > 0) { + if (prestart > curr.start) return false; + skip = curr.start - prestart; + } else skip = 0; + // first track (track number must be 1) + if (tracks.empty()) { + if (curr.number != 1) return false; + curr.skip = skip * curr.sectorSize; + curr.start += currPregap; + totalPregap = currPregap; tracks.push_back(curr); return true; -} + } -bool CDROM_Interface_Image::HasDataTrack(void) -{ - //Data track has attribute 0x14 - for(track_it it = tracks.begin(); it != tracks.end(); it++) { - if ((*it).attr == DATA_TRACK) return true; - } - return false; -} + Track &prev = *(tracks.end() - 1); -bool CDROM_Interface_Image::HasAudioTracks(void) -{ - for(track_it it = tracks.begin(); it != tracks.end(); it++) { - if ((*it).attr == AUDIO_TRACK) return true; - } - return false; + // current track consumes data from the same file as the previous + if (prev.file == curr.file) { + curr.start += shift; + prev.length = curr.start + totalPregap - prev.start - skip; + curr.skip += prev.skip + (prev.length * prev.sectorSize) + (skip * curr.sectorSize); + totalPregap += currPregap; + curr.start += totalPregap; + // current track uses a different file as the previous track + } else { + uint64_t tmp = prev.file->getLength() - ((uint64_t) prev.skip); + prev.length = tmp / ((uint64_t) prev.sectorSize); + if (tmp % prev.sectorSize != 0) prev.length++; // padding + + curr.start += prev.start + prev.length + currPregap; + curr.skip = skip * curr.sectorSize; + shift += prev.start + prev.length; + totalPregap = currPregap; + } + + // error checks + if (curr.number <= 1) return false; + if (prev.number + 1 != curr.number) return false; + if (curr.start < prev.start + prev.length) return false; + + tracks.push_back(curr); + + return true; } -bool CDROM_Interface_Image::GetRealFileName(string &filename, string &pathname) +bool +CDROM_Interface_Image::HasDataTrack(void) { - // check if file exists - struct stat test; - if (stat(filename.c_str(), &test) == 0) return true; + //Data track has attribute 0x14 + for (track_it it = tracks.begin(); it != tracks.end(); it++) { + if ((*it).attr == DATA_TRACK) return true; + } + return false; +} + + +bool +CDROM_Interface_Image::HasAudioTracks(void) +{ + for (track_it it = tracks.begin(); it != tracks.end(); it++) { + if ((*it).attr == AUDIO_TRACK) return true; + } + return false; +} + + +bool +CDROM_Interface_Image::GetRealFileName(string &filename, string &pathname) +{ + // check if file exists + struct stat test; + if (stat(filename.c_str(), &test) == 0) return true; + + // check if file with path relative to cue file exists + string tmpstr(pathname + "/" + filename); + if (stat(tmpstr.c_str(), &test) == 0) { + filename = tmpstr; + return true; + } - // check if file with path relative to cue file exists - string tmpstr(pathname + "/" + filename); - if (stat(tmpstr.c_str(), &test) == 0) { - filename = tmpstr; - return true; - } #if defined (_WIN32) || defined(OS2) - //Nothing + //Nothing #else - //Consider the possibility that the filename has a windows directory seperator (inside the CUE file) - //which is common for some commercial rereleases of DOS games using DOSBox + //Consider the possibility that the filename has a windows directory seperator (inside the CUE file) + //which is common for some commercial rereleases of DOS games using DOSBox - string copy = filename; - size_t l = copy.size(); - for (size_t i = 0; i < l;i++) { - if(copy[i] == '\\') copy[i] = '/'; - } + string copy = filename; + size_t l = copy.size(); + for (size_t i = 0; i < l;i++) { + if(copy[i] == '\\') copy[i] = '/'; + } - if (stat(copy.c_str(), &test) == 0) { - filename = copy; + if (stat(copy.c_str(), &test) == 0) { + filename = copy; + return true; + } + + tmpstr = pathname + "/" + copy; + if (stat(tmpstr.c_str(), &test) == 0) { + filename = tmpstr; return true; - } - - tmpstr = pathname + "/" + copy; - if (stat(tmpstr.c_str(), &test) == 0) { - filename = tmpstr; - return true; - } - + } #endif - return false; + return false; } -bool CDROM_Interface_Image::GetCueKeyword(string &keyword, istream &in) -{ - in >> keyword; - for(Bitu i = 0; i < keyword.size(); i++) keyword[i] = toupper(keyword[i]); - return true; +bool +CDROM_Interface_Image::GetCueKeyword(string &keyword, istream &in) +{ + in >> keyword; + for (Bitu i = 0; i < keyword.size(); i++) keyword[i] = toupper(keyword[i]); + + return true; } -bool CDROM_Interface_Image::GetCueFrame(uint64_t &frames, istream &in) -{ - string msf; - in >> msf; - int min, sec, fr; - bool success = sscanf(msf.c_str(), "%d:%d:%d", &min, &sec, &fr) == 3; - frames = MSF_TO_FRAMES(min, sec, fr); - return success; +bool +CDROM_Interface_Image::GetCueFrame(uint64_t &frames, istream &in) +{ + string msf; + in >> msf; + int min, sec, fr; + bool success = sscanf(msf.c_str(), "%d:%d:%d", &min, &sec, &fr) == 3; + frames = MSF_TO_FRAMES(min, sec, fr); + + return success; } -bool CDROM_Interface_Image::GetCueString(string &str, istream &in) + +bool +CDROM_Interface_Image::GetCueString(string &str, istream &in) { - int pos = (int)in.tellg(); - in >> str; - if (str[0] == '\"') { - if (str[str.size() - 1] == '\"') { - str.assign(str, 1, str.size() - 2); - } else { - in.seekg(pos, ios::beg); - char buffer[MAX_FILENAME_LENGTH]; - in.getline(buffer, MAX_FILENAME_LENGTH, '\"'); // skip - in.getline(buffer, MAX_FILENAME_LENGTH, '\"'); - str = buffer; - } + int pos = (int)in.tellg(); + in >> str; + if (str[0] == '\"') { + if (str[str.size() - 1] == '\"') { + str.assign(str, 1, str.size() - 2); + } else { + in.seekg(pos, ios::beg); + char buffer[MAX_FILENAME_LENGTH]; + in.getline(buffer, MAX_FILENAME_LENGTH, '\"'); // skip + in.getline(buffer, MAX_FILENAME_LENGTH, '\"'); + str = buffer; } - return true; + } + + return true; } -void CDROM_Interface_Image::ClearTracks() + +void +CDROM_Interface_Image::ClearTracks(void) { - vector::iterator i = tracks.begin(); - vector::iterator end = tracks.end(); + vector::iterator i = tracks.begin(); + vector::iterator end = tracks.end(); - TrackFile* last = NULL; - while(i != end) { - Track &curr = *i; - if (curr.file != last) { - delete curr.file; - last = curr.file; - } - i++; + TrackFile* last = NULL; + while(i != end) { + Track &curr = *i; + if (curr.file != last) { + delete curr.file; + last = curr.file; } - tracks.clear(); + i++; + } + tracks.clear(); } diff --git a/src/devices/cdrom/cdrom_image.cpp b/src/devices/cdrom/cdrom_image.cpp index 60b4cb4..fb2d818 100644 --- a/src/devices/cdrom/cdrom_image.cpp +++ b/src/devices/cdrom/cdrom_image.cpp @@ -8,7 +8,7 @@ * * CD-ROM image support. * - * Version: @(#)cdrom_image.cpp 1.0.9 2018/05/06 + * Version: @(#)cdrom_image.cpp 1.0.10 2018/10/05 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -38,1126 +38,1089 @@ #define __USE_LARGEFILE64 #define _LARGEFILE_SOURCE #define _LARGEFILE64_SOURCE -#include #include #include #include #include +#include #include +#define HAVE_STDARG_H +#define dbglog cdrom_image_log #include "../../emu.h" #include "../../plat.h" -#include "cdrom_dosbox.h" +#include "../scsi/scsi_device.h" #include "cdrom.h" #include "cdrom_image.h" +#include "cdrom_dosbox.h" #include "cdrom_null.h" + +#ifdef ENABLE_CDROM_IMAGE_LOG +int cdrom_image_do_log = ENABLE_CDROM_IMAGE_LOG; +#endif + + +void +cdrom_image_log(int level, const char *format, ...) +{ +#ifdef ENABLE_CDROM_IMAGE_LOG + va_list ap; + + if (cdrom_image_do_log >= level) { + va_start(ap, format); + pclog_ex(format, ap); + va_end(ap); + } +#endif +} + + #define CD_STATUS_EMPTY 0 #define CD_STATUS_DATA_ONLY 1 #define CD_STATUS_PLAYING 2 #define CD_STATUS_PAUSED 3 #define CD_STATUS_STOPPED 4 + /* The addresses sent from the guest are absolute, ie. a LBA of 0 corresponds to a MSF of 00:00:00. Otherwise, the counter displayed by the guest is wrong: there is a seeming 2 seconds in which audio plays but counter does not move, while a data track before audio jumps to 2 seconds before the actual start of the audio while audio still plays. With an absolute conversion, the counter is fine. */ -#define MSFtoLBA(m,s,f) ((((m*60)+s)*75)+f) +#define MSFtoLBA(m,s,f) ((((m*60)+s)*75)+f) -extern CDROM image_cdrom; +extern CDROM image_cdrom; -enum -{ - CD_STOPPED = 0, - CD_PLAYING, - CD_PAUSED -}; - -#ifdef ENABLE_CDROM_IMAGE_LOG -int cdrom_image_do_log = ENABLE_CDROM_IMAGE_LOG; -#endif - -CDROM_Interface_Image* cdimg[CDROM_NUM] = { NULL, NULL, NULL, NULL }; - - -void cdrom_image_log(const char *format, ...) -{ -#ifdef ENABLE_CDROM_IMAGE_LOG - if (cdrom_image_do_log) - { - va_list ap; - va_start(ap, format); - vprintf(format, ap); - va_end(ap); - fflush(stdout); - } -#else - (void)format; -#endif -} - -void image_close(uint8_t id); - -static void image_audio_callback(uint8_t id, int16_t *output, int len) -{ - cdrom_t *dev = cdrom[id]; - - if (!cdrom_drives[id].sound_on || (dev->cd_state != CD_PLAYING) || cdrom_image[id].image_is_iso) - { - cdrom_image_log("image_audio_callback(i): Not playing\n", id); - if (dev->cd_state == CD_PLAYING) - { - dev->seek_pos += (len >> 11); - } - memset(output, 0, len * 2); - return; - } - while (dev->cd_buflen < len) - { - if (dev->seek_pos < dev->cd_end) - { - if (!cdimg[id]->ReadSector((unsigned char*)&dev->cd_buffer[dev->cd_buflen], true, dev->seek_pos)) - { - memset(&dev->cd_buffer[dev->cd_buflen], 0, (BUF_SIZE - dev->cd_buflen) * 2); - dev->cd_state = CD_STOPPED; - dev->cd_buflen = len; - } - else - { - dev->seek_pos++; - dev->cd_buflen += (RAW_SECTOR_SIZE / 2); - } - } - else - { - memset(&dev->cd_buffer[dev->cd_buflen], 0, (BUF_SIZE - dev->cd_buflen) * 2); - dev->cd_state = CD_STOPPED; - dev->cd_buflen = len; - } - } - memcpy(output, dev->cd_buffer, len * 2); - memmove(dev->cd_buffer, &dev->cd_buffer[len], (BUF_SIZE - len) * 2); - dev->cd_buflen -= len; -} - -static void image_audio_stop(uint8_t id) -{ - cdrom_t *dev = cdrom[id]; - - dev->cd_state = CD_STOPPED; -} - -static void image_playaudio(uint8_t id, uint32_t pos, uint32_t len, int ismsf) -{ - cdrom_t *dev = cdrom[id]; - - if (!cdimg[id]) return; - int number; - unsigned char attr; - TMSF tmsf; - int m = 0, s = 0, f = 0; - cdimg[id]->GetAudioTrackInfo(cdimg[id]->GetTrack(pos), number, tmsf, attr); - if (attr == DATA_TRACK) - { - cdrom_image_log("Can't play data track\n"); - dev->seek_pos = 0; - dev->cd_state = CD_STOPPED; - return; - } - cdrom_image_log("Play audio - %08X %08X %i\n", pos, len, ismsf); - if (ismsf == 2) - { - cdimg[id]->GetAudioTrackInfo(pos, number, tmsf, attr); - pos = MSFtoLBA(tmsf.min, tmsf.sec, tmsf.fr) - 150; - cdimg[id]->GetAudioTrackInfo(len, number, tmsf, attr); - len = MSFtoLBA(tmsf.min, tmsf.sec, tmsf.fr) - 150; - } - else if (ismsf == 1) - { - m = (pos >> 16) & 0xff; - s = (pos >> 8) & 0xff; - f = pos & 0xff; - - if (pos == 0xffffff) - { - cdrom_image_log("Playing from current position (MSF)\n"); - pos = dev->seek_pos; - } - else - { - pos = MSFtoLBA(m, s, f) - 150; - } - - m = (len >> 16) & 0xff; - s = (len >> 8) & 0xff; - f = len & 0xff; - len = MSFtoLBA(m, s, f) - 150; - - cdrom_image_log("MSF - pos = %08X len = %08X\n", pos, len); - } - else if (ismsf == 0) - { - if (pos == 0xffffffff) - { - cdrom_image_log("Playing from current position\n"); - pos = dev->seek_pos; - } - len += pos; - } - dev->seek_pos = pos; - dev->cd_end = len; - dev->cd_state = CD_PLAYING; - dev->cd_buflen = 0; -} - -static void image_pause(uint8_t id) -{ - cdrom_t *dev = cdrom[id]; - - if (!cdimg[id] || cdrom_image[id].image_is_iso) return; - if (dev->cd_state == CD_PLAYING) - dev->cd_state = CD_PAUSED; -} - -static void image_resume(uint8_t id) -{ - cdrom_t *dev = cdrom[id]; - - if (!cdimg[id] || cdrom_image[id].image_is_iso) return; - if (dev->cd_state == CD_PAUSED) - dev->cd_state = CD_PLAYING; -} - -static void image_stop(uint8_t id) -{ - cdrom_t *dev = cdrom[id]; - - if (!cdimg[id] || cdrom_image[id].image_is_iso) return; - dev->cd_state = CD_STOPPED; -} - -static int image_ready(uint8_t id) -{ - if (!cdimg[id]) - return 0; - - if (wcslen(cdrom_image[id].image_path) == 0) - return 0; - - if (cdrom_drives[id].prev_host_drive != cdrom_drives[id].host_drive) - { - return 1; - } - - return 1; -} - -static int image_get_last_block(uint8_t id, UNUSED(uint8_t starttrack), UNUSED(int msf), UNUSED(int maxlen), UNUSED(int single)) -{ - int c; - uint32_t lb=0; - - if (!cdimg[id]) return 0; - - int first_track; - int last_track; - int number; - unsigned char attr; - TMSF tmsf; - cdimg[id]->GetAudioTracks(first_track, last_track, tmsf); - - for (c = 0; c <= last_track; c++) - { - uint32_t address; - cdimg[id]->GetAudioTrackInfo(c+1, number, tmsf, attr); - address = MSFtoLBA(tmsf.min, tmsf.sec, tmsf.fr) - 150; /* Do the - 150 here as well. */ - if (address > lb) - lb = address; - } - return lb; -} - -static int image_medium_changed(uint8_t id) -{ - if (!cdimg[id]) - return 0; - - if (wcslen(cdrom_image[id].image_path) == 0) - { - return 0; - } - - if (cdrom_drives[id].prev_host_drive != cdrom_drives[id].host_drive) - { - cdrom_drives[id].prev_host_drive = cdrom_drives[id].host_drive; - return 1; - } - - return 0; -} - -static uint8_t image_getcurrentsubchannel(uint8_t id, uint8_t *b, int msf) -{ - cdrom_t *dev = cdrom[id]; - uint8_t ret; - int pos=0; - - if (!cdimg[id]) return 0; - - uint32_t cdpos = dev->seek_pos; - TMSF relPos, absPos; - unsigned char attr, track, index; - cdimg[id]->GetAudioSub(cdpos, attr, track, index, relPos, absPos); - - if (cdrom_image[id].image_is_iso) - { - ret = 0x15; - } - else - { - if (dev->cd_state == CD_PLAYING) - ret = 0x11; - else if (dev->cd_state == CD_PAUSED) - ret = 0x12; - else - ret = 0x13; - } - - b[pos++] = attr; - b[pos++] = track; - b[pos++] = index; - - if (msf) - { - b[pos + 3] = (uint8_t) absPos.fr; - b[pos + 2] = (uint8_t) absPos.sec; - b[pos + 1] = (uint8_t) absPos.min; - b[pos] = 0; - pos += 4; - b[pos + 3] = (uint8_t) relPos.fr; - b[pos + 2] = (uint8_t) relPos.sec; - b[pos + 1] = (uint8_t) relPos.min; - b[pos] = 0; - pos += 4; - } - else - { - uint32_t dat = MSFtoLBA(absPos.min, absPos.sec, absPos.fr) - 150; - b[pos++] = (dat >> 24) & 0xff; - b[pos++] = (dat >> 16) & 0xff; - b[pos++] = (dat >> 8) & 0xff; - b[pos++] = dat & 0xff; - dat = MSFtoLBA(relPos.min, relPos.sec, relPos.fr); - b[pos++] = (dat >> 24) & 0xff; - b[pos++] = (dat >> 16) & 0xff; - b[pos++] = (dat >> 8) & 0xff; - b[pos++] = dat & 0xff; - } - - return ret; -} - -static void image_eject(UNUSED(uint8_t id)) -{ - return; -} - -static void image_load(UNUSED(uint8_t id)) -{ - return; -} - -static int image_is_track_audio(uint8_t id, uint32_t pos, int ismsf) -{ - int m, s, f; - unsigned char attr; - TMSF tmsf; - int number; - - if (!cdimg[id] || cdrom_image[id].image_is_iso) return 0; - - if (ismsf) - { - m = (pos >> 16) & 0xff; - s = (pos >> 8) & 0xff; - f = pos & 0xff; - pos = MSFtoLBA(m, s, f) - 150; - } - - /* GetTrack requires LBA. */ - cdimg[id]->GetAudioTrackInfo(cdimg[id]->GetTrack(pos), number, tmsf, attr); - - return attr == AUDIO_TRACK; -} - - -#pragma pack(push, 1) -typedef struct -{ - uint8_t user_data[2048]; - uint8_t ecc[288]; +#pragma pack(push,1) +typedef struct { + uint8_t user_data[2048], + ecc[288]; } m1_data_t; -typedef struct -{ - uint8_t sub_header[8]; - uint8_t user_data[2328]; +typedef struct { + uint8_t sub_header[8], + user_data[2328]; } m2_data_t; -typedef union -{ - m1_data_t m1_data; - m2_data_t m2_data; - uint8_t raw_data[2336]; +typedef union { + m1_data_t m1_data; + m2_data_t m2_data; + uint8_t raw_data[2336]; } sector_data_t; -typedef struct -{ - uint8_t sync[12]; - uint8_t header[4]; - sector_data_t data; +typedef struct { + uint8_t sync[12]; + uint8_t header[4]; + sector_data_t data; } sector_raw_data_t; -typedef union -{ - sector_raw_data_t sector_data; - uint8_t raw_data[2352]; +typedef union { + sector_raw_data_t sector_data; + uint8_t raw_data[2352]; } sector_t; -typedef struct -{ - sector_t sector; - uint8_t c2[296]; - uint8_t subchannel_raw[96]; - uint8_t subchannel_q[16]; - uint8_t subchannel_rw[96]; +typedef struct { + sector_t sector; + uint8_t c2[296]; + uint8_t subchannel_raw[96]; + uint8_t subchannel_q[16]; + uint8_t subchannel_rw[96]; } cdrom_sector_t; -typedef union -{ - cdrom_sector_t cdrom_sector; - uint8_t buffer[2856]; +typedef union { + cdrom_sector_t cdrom_sector; + uint8_t buffer[2856]; } sector_buffer_t; #pragma pack(pop) + sector_buffer_t cdrom_sector_buffer; int cdrom_sector_size; uint8_t raw_buffer[2448]; uint8_t extra_buffer[296]; -static int is_legal(int id, int cdrom_sector_type, int cdrom_sector_flags, int audio, int mode2, int form) +enum { + CD_STOPPED = 0, + CD_PLAYING, + CD_PAUSED +}; + + +static CDROM_Interface_Image* cdimg[CDROM_NUM] = { NULL, NULL, NULL, NULL }; +static char afn[1024]; + +void image_close(uint8_t id); + + +int +image_audio_callback(uint8_t id, int16_t *output, int len) { - if (!(cdrom_sector_flags & 0x70)) { /* 0x00/0x08/0x80/0x88 are illegal modes */ - cdrom_image_log("CD-ROM %i: [Any Mode] 0x00/0x08/0x80/0x88 are illegal modes\n", id); - return 0; - } + cdrom_t *dev = cdrom[id]; + int ret = 1; - if ((cdrom_sector_type != 1) && !audio) - { - if (!(cdrom_sector_flags & 0x70)) { /* 0x00/0x08/0x80/0x88 are illegal modes */ - cdrom_image_log("CD-ROM %i: [Any Data Mode] 0x00/0x08/0x80/0x88 are illegal modes\n", id); - return 0; - } - - if ((cdrom_sector_flags & 0x06) == 0x06) { - cdrom_image_log("CD-ROM %i: [Any Data Mode] Invalid error flags\n", id); - return 0; - } - - if (((cdrom_sector_flags & 0x700) == 0x300) || ((cdrom_sector_flags & 0x700) > 0x400)) { - cdrom_image_log("CD-ROM %i: [Any Data Mode] Invalid subchannel data flags (%02X)\n", id, cdrom_sector_flags & 0x700); - return 0; - } - - if ((cdrom_sector_flags & 0x18) == 0x08) { /* EDC/ECC without user data is an illegal mode */ - cdrom_image_log("CD-ROM %i: [Any Data Mode] EDC/ECC without user data is an illegal mode\n", id); - return 0; - } - - if (((cdrom_sector_flags & 0xf0) == 0x90) || ((cdrom_sector_flags & 0xf0) == 0xc0)) { /* 0x90/0x98/0xC0/0xC8 are illegal modes */ - cdrom_image_log("CD-ROM %i: [Any Data Mode] 0x90/0x98/0xC0/0xC8 are illegal modes\n", id); - return 0; - } - - if (((cdrom_sector_type > 3) && (cdrom_sector_type != 8)) || (mode2 && form)) - { - if ((cdrom_sector_flags & 0xf0) == 0x30) { /* 0x30/0x38 are illegal modes */ - cdrom_image_log("CD-ROM %i: [Any XA Mode 2] 0x30/0x38 are illegal modes\n", id); - return 0; - } - if (((cdrom_sector_flags & 0xf0) == 0xb0) || ((cdrom_sector_flags & 0xf0) == 0xd0)) { /* 0xBx and 0xDx are illegal modes */ - cdrom_image_log("CD-ROM %i: [Any XA Mode 2] 0xBx and 0xDx are illegal modes\n", id); - return 0; - } - } - } - - return 1; -} - -static void read_sector_to_buffer(uint8_t id, uint8_t *raw_buffer, uint32_t msf, uint32_t lba, int mode2, int form, int len) -{ - cdimg[id]->ReadSector(raw_buffer + 16, false, lba); - - uint8_t *bb = raw_buffer; - - /* sync bytes */ - bb[0] = 0; - memset(bb + 1, 0xff, 10); - bb[11] = 0; - bb += 12; - - bb[0] = (msf >> 16) & 0xff; - bb[1] = (msf >> 8) & 0xff; - bb[2] = msf & 0xff; - - bb[3] = 1; /* mode 1 data */ - bb += mode2 ? 12 : 4; - bb += len; - if (mode2 && (form == 1)) - memset(bb, 0, 280); - else if (!mode2) - memset(bb, 0, 288); -} - -static int image_readsector_raw(uint8_t id, uint8_t *buffer, int sector, int ismsf, int cdrom_sector_type, int cdrom_sector_flags, int *len) -{ - uint8_t *b; - uint8_t *temp_b; - uint32_t msf; - uint32_t lba; - int audio; - int mode2; - int m, s, f; - int form; - - if (!cdimg[id]) - return 0; - - if (!cdrom_drives[id].host_drive) - return 0; - - b = temp_b = buffer; - - *len = 0; - - if (ismsf) { - m = (sector >> 16) & 0xff; - s = (sector >> 8) & 0xff; - f = sector & 0xff; - lba = MSFtoLBA(m, s, f) - 150; - msf = sector; - } else { - lba = sector; - msf = cdrom_lba_to_msf_accurate(sector); - } - - if (cdrom_image[id].image_is_iso) { - audio = 0; - mode2 = cdimg[id]->IsMode2(lba) ? 1 : 0; - } else { - audio = image_is_track_audio(id, sector, ismsf); - mode2 = cdimg[id]->IsMode2(lba) ? 1 : 0; - } - - form = cdimg[id]->GetMode2Form(lba); - - memset(raw_buffer, 0, 2448); - memset(extra_buffer, 0, 296); - - if (!(cdrom_sector_flags & 0xf0)) { /* 0x00 and 0x08 are illegal modes */ - cdrom_image_log("CD-ROM %i: [Mode 1] 0x00 and 0x08 are illegal modes\n", id); - return 0; - } - - if ((cdrom_sector_type == 3) || ((cdrom_sector_type > 4) && (cdrom_sector_type != 8))) { - if (cdrom_sector_type == 3) - cdrom_image_log("CD-ROM %i: Attempting to read a Yellowbook Mode 2 data sector from an image\n", id); - if (cdrom_sector_type > 4) - cdrom_image_log("CD-ROM %i: Attempting to read a XA Mode 2 Form 2 data sector from an image\n", id); - return 0; - } - else if (cdrom_sector_type == 1) { - if (!audio || cdrom_image[id].image_is_iso) { - cdrom_image_log("CD-ROM %i: [Audio] Attempting to read an audio sector from a data image\n", id); - return 0; - } - -read_audio: - if (!is_legal(id, cdrom_sector_type, cdrom_sector_flags, audio, mode2, form)) - return 0; - - if (cdimg[id]->GetSectorSize(lba) == 2352) - cdimg[id]->ReadSector(raw_buffer, true, lba); - else - cdimg[id]->ReadSectorSub(raw_buffer, lba); - - memcpy(temp_b, raw_buffer, 2352); - cdrom_sector_size = 2352; - } else if (cdrom_sector_type == 2) { - if (audio || mode2) { - cdrom_image_log("CD-ROM %i: [Mode 1] Attempting to read a sector of another type\n", id); - return 0; - } - -read_mode1: - if (!is_legal(id, cdrom_sector_type, cdrom_sector_flags, audio, mode2, form)) - return 0; - - if ((cdrom_image[id].image_is_iso) || (cdimg[id]->GetSectorSize(lba) == 2048)) - read_sector_to_buffer(id, raw_buffer, msf, lba, mode2, form, 2048); - else if (cdimg[id]->GetSectorSize(lba) == 2352) - cdimg[id]->ReadSector(raw_buffer, true, lba); - else - cdimg[id]->ReadSectorSub(raw_buffer, lba); - - cdrom_sector_size = 0; - - if (cdrom_sector_flags & 0x80) { /* Sync */ - cdrom_image_log("CD-ROM %i: [Mode 1] Sync\n", id); - memcpy(temp_b, raw_buffer, 12); - cdrom_sector_size += 12; - temp_b += 12; - } - - if (cdrom_sector_flags & 0x20) { /* Header */ - cdrom_image_log("CD-ROM %i: [Mode 1] Header\n", id); - memcpy(temp_b, raw_buffer + 12, 4); - cdrom_sector_size += 4; - temp_b += 4; - } - - if (cdrom_sector_flags & 0x40) { /* Sub-header */ - if (!(cdrom_sector_flags & 0x10)) { /* No user data */ - cdrom_image_log("CD-ROM %i: [Mode 1] Sub-header\n", id); - memcpy(temp_b, raw_buffer + 16, 8); - cdrom_sector_size += 8; - temp_b += 8; - } - } - - if (cdrom_sector_flags & 0x10) { /* User data */ - cdrom_image_log("CD-ROM %i: [Mode 1] User data\n", id); - memcpy(temp_b, raw_buffer + 16, 2048); - cdrom_sector_size += 2048; - temp_b += 2048; - } - - if (cdrom_sector_flags & 0x08) { /* EDC/ECC */ - cdrom_image_log("CD-ROM %i: [Mode 1] EDC/ECC\n", id); - memcpy(temp_b, raw_buffer + 2064, 288); - cdrom_sector_size += 288; - temp_b += 288; - } - } else if (cdrom_sector_type == 3) { - if (audio || !mode2 || form) { - cdrom_image_log("CD-ROM %i: [Mode 2 Formless] Attempting to read a sector of another type\n", id); - return 0; - } - -read_mode2_non_xa: - if (!is_legal(id, cdrom_sector_type, cdrom_sector_flags, audio, mode2, form)) - return 0; - - if ((cdrom_image[id].image_is_iso) || (cdimg[id]->GetSectorSize(lba) == 2336)) - read_sector_to_buffer(id, raw_buffer, msf, lba, mode2, form, 2336); - else if (cdimg[id]->GetSectorSize(lba) == 2352) - cdimg[id]->ReadSector(raw_buffer, true, lba); - else - cdimg[id]->ReadSectorSub(raw_buffer, lba); - - cdrom_sector_size = 0; - - if (cdrom_sector_flags & 0x80) { /* Sync */ - cdrom_image_log("CD-ROM %i: [Mode 2 Formless] Sync\n", id); - memcpy(temp_b, raw_buffer, 12); - cdrom_sector_size += 12; - temp_b += 12; - } - - - if (cdrom_sector_flags & 0x20) { /* Header */ - cdrom_image_log("CD-ROM %i: [Mode 2 Formless] Header\n", id); - memcpy(temp_b, raw_buffer + 12, 4); - cdrom_sector_size += 4; - temp_b += 4; - } - - /* Mode 1 sector, expected type is 1 type. */ - if (cdrom_sector_flags & 0x40) { /* Sub-header */ - cdrom_image_log("CD-ROM %i: [Mode 2 Formless] Sub-header\n", id); - memcpy(temp_b, raw_buffer + 16, 8); - cdrom_sector_size += 8; - temp_b += 8; - } - - if (cdrom_sector_flags & 0x10) { /* User data */ - cdrom_image_log("CD-ROM %i: [Mode 2 Formless] User data\n", id); - memcpy(temp_b, raw_buffer + 24, 2336); - cdrom_sector_size += 2336; - temp_b += 2336; - } - } else if (cdrom_sector_type == 4) { - if (audio || !mode2 || (form != 1)) { - cdrom_image_log("CD-ROM %i: [XA Mode 2 Form 1] Attempting to read a sector of another type\n", id); - return 0; - } - -read_mode2_xa_form1: - if (!is_legal(id, cdrom_sector_type, cdrom_sector_flags, audio, mode2, form)) - return 0; - - if ((cdrom_image[id].image_is_iso) || (cdimg[id]->GetSectorSize(lba) == 2048)) - read_sector_to_buffer(id, raw_buffer, msf, lba, mode2, form, 2048); - else if (cdimg[id]->GetSectorSize(lba) == 2352) - cdimg[id]->ReadSector(raw_buffer, true, lba); - else - cdimg[id]->ReadSectorSub(raw_buffer, lba); - - cdrom_sector_size = 0; - - if (cdrom_sector_flags & 0x80) { /* Sync */ - cdrom_image_log("CD-ROM %i: [XA Mode 2 Form 1] Sync\n", id); - memcpy(temp_b, raw_buffer, 12); - cdrom_sector_size += 12; - temp_b += 12; - } - - if (cdrom_sector_flags & 0x20) { /* Header */ - cdrom_image_log("CD-ROM %i: [XA Mode 2 Form 1] Header\n", id); - memcpy(temp_b, raw_buffer + 12, 4); - cdrom_sector_size += 4; - temp_b += 4; - } - - if (cdrom_sector_flags & 0x40) { /* Sub-header */ - cdrom_image_log("CD-ROM %i: [XA Mode 2 Form 1] Sub-header\n", id); - memcpy(temp_b, raw_buffer + 16, 8); - cdrom_sector_size += 8; - temp_b += 8; - } - - if (cdrom_sector_flags & 0x10) { /* User data */ - cdrom_image_log("CD-ROM %i: [XA Mode 2 Form 1] User data\n", id); - memcpy(temp_b, raw_buffer + 24, 2048); - cdrom_sector_size += 2048; - temp_b += 2048; - } - - if (cdrom_sector_flags & 0x08) { /* EDC/ECC */ - cdrom_image_log("CD-ROM %i: [XA Mode 2 Form 1] EDC/ECC\n", id); - memcpy(temp_b, raw_buffer + 2072, 280); - cdrom_sector_size += 280; - temp_b += 280; - } - } else if (cdrom_sector_type == 5) { - if (audio || !mode2 || (form != 2)) { - cdrom_image_log("CD-ROM %i: [XA Mode 2 Form 2] Attempting to read a sector of another type\n", id); - return 0; - } - -read_mode2_xa_form2: - if (!is_legal(id, cdrom_sector_type, cdrom_sector_flags, audio, mode2, form)) - return 0; - - if ((cdrom_image[id].image_is_iso) || (cdimg[id]->GetSectorSize(lba) == 2324)) - read_sector_to_buffer(id, raw_buffer, msf, lba, mode2, form, 2324); - else if (cdimg[id]->GetSectorSize(lba) == 2352) - cdimg[id]->ReadSector(raw_buffer, true, lba); - else - cdimg[id]->ReadSectorSub(raw_buffer, lba); - - cdrom_sector_size = 0; - - if (cdrom_sector_flags & 0x80) { /* Sync */ - cdrom_image_log("CD-ROM %i: [XA Mode 2 Form 2] Sync\n", id); - memcpy(temp_b, raw_buffer, 12); - cdrom_sector_size += 12; - temp_b += 12; - } - - if (cdrom_sector_flags & 0x20) { /* Header */ - cdrom_image_log("CD-ROM %i: [XA Mode 2 Form 2] Header\n", id); - memcpy(temp_b, raw_buffer + 12, 4); - cdrom_sector_size += 4; - temp_b += 4; - } - - if (cdrom_sector_flags & 0x40) { /* Sub-header */ - cdrom_image_log("CD-ROM %i: [XA Mode 2 Form 2] Sub-header\n", id); - memcpy(temp_b, raw_buffer + 16, 8); - cdrom_sector_size += 8; - temp_b += 8; - } - - if (cdrom_sector_flags & 0x10) { /* User data */ - cdrom_image_log("CD-ROM %i: [XA Mode 2 Form 2] User data\n", id); - memcpy(temp_b, raw_buffer + 24, 2328); - cdrom_sector_size += 2328; - temp_b += 2328; - } - } else if (cdrom_sector_type == 8) { - if (audio) { - cdrom_image_log("CD-ROM %i: [Any Data] Attempting to read a data sector from an audio track\n", id); - return 0; - } - - if (mode2 && (form == 1)) - goto read_mode2_xa_form1; - else if (!mode2) - goto read_mode1; - else { - cdrom_image_log("CD-ROM %i: [Any Data] Attempting to read a data sector whose cooked size is not 2048 bytes\n", id); - return 0; + if (!cdrom_drives[id].sound_on || (dev->cd_state != CD_PLAYING) || cdrom_image[id].image_is_iso) { + DEBUG("image_audio_callback(i): Not playing\n", id); + if (dev->cd_state == CD_PLAYING) + dev->seek_pos += (len >> 11); + memset(output, 0, len * 2); + return 0; + } + while (dev->cd_buflen < len) { + if (dev->seek_pos < dev->cd_end) { + if (!cdimg[id]->ReadSector((unsigned char*)&dev->cd_buffer[dev->cd_buflen], true, + dev->seek_pos)) { + memset(&dev->cd_buffer[dev->cd_buflen], 0, (BUF_SIZE - dev->cd_buflen) * 2); + dev->cd_state = CD_STOPPED; + dev->cd_buflen = len; + ret = 0; + } else { + dev->seek_pos++; + dev->cd_buflen += (RAW_SECTOR_SIZE / 2); + ret = 1; } } else { - if (mode2) - if (form == 1) - goto read_mode2_xa_form1; - else if (form == 2) - goto read_mode2_xa_form2; - else - goto read_mode2_non_xa; - else { - if (audio) - goto read_audio; - else - goto read_mode1; - } + memset(&dev->cd_buffer[dev->cd_buflen], 0, (BUF_SIZE - dev->cd_buflen) * 2); + dev->cd_state = CD_STOPPED; + dev->cd_buflen = len; + ret = 0; } + } - if ((cdrom_sector_flags & 0x06) == 0x02) { - /* Add error flags. */ - cdrom_image_log("CD-ROM %i: Error flags\n", id); - memcpy(b + cdrom_sector_size, extra_buffer, 294); - cdrom_sector_size += 294; - } - else if ((cdrom_sector_flags & 0x06) == 0x04) { - /* Add error flags. */ - cdrom_image_log("CD-ROM %i: Full error flags\n", id); - memcpy(b + cdrom_sector_size, extra_buffer, 296); - cdrom_sector_size += 296; - } - - if ((cdrom_sector_flags & 0x700) == 0x100) { - cdrom_image_log("CD-ROM %i: Raw subchannel data\n", id); - memcpy(b + cdrom_sector_size, raw_buffer + 2352, 96); - cdrom_sector_size += 96; - } - else if ((cdrom_sector_flags & 0x700) == 0x200) { - cdrom_image_log("CD-ROM %i: Q subchannel data\n", id); - memcpy(b + cdrom_sector_size, raw_buffer + 2352, 16); - cdrom_sector_size += 16; - } - else if ((cdrom_sector_flags & 0x700) == 0x400) { - cdrom_image_log("CD-ROM %i: R/W subchannel data\n", id); - memcpy(b + cdrom_sector_size, raw_buffer + 2352, 96); - cdrom_sector_size += 96; - } - - *len = cdrom_sector_size; - - return 1; + memcpy(output, dev->cd_buffer, len * 2); + memmove(dev->cd_buffer, &dev->cd_buffer[len], (BUF_SIZE - len) * 2); + dev->cd_buflen -= len; + return ret; } -static uint32_t image_size(uint8_t id) +void +image_audio_stop(uint8_t id) { - cdrom_t *dev = cdrom[id]; + cdrom_t *dev = cdrom[id]; - return dev->cdrom_capacity; + dev->cd_state = CD_STOPPED; } -static int image_readtoc(uint8_t id, unsigned char *b, unsigned char starttrack, int msf, int maxlen, int single) + +static uint8_t +image_playaudio(uint8_t id, uint32_t pos, uint32_t len, int ismsf) { - if (!cdimg[id]) return 0; - int len=4; - int c,d; - uint32_t temp; - - int first_track; - int last_track; - int number; - unsigned char attr; - TMSF tmsf; - - cdimg[id]->GetAudioTracks(first_track, last_track, tmsf); - - b[2] = first_track; - b[3] = last_track; - - d = 0; - for (c = 0; c <= last_track; c++) - { - cdimg[id]->GetAudioTrackInfo(c+1, number, tmsf, attr); - if (number >= starttrack) - { - d=c; - break; - } - } - - if (starttrack != 0xAA) - { - cdimg[id]->GetAudioTrackInfo(c+1, number, tmsf, attr); - b[2] = number; - } - - for (c = d; c <= last_track; c++) - { - if ((len + 8) > maxlen) - break; - cdimg[id]->GetAudioTrackInfo(c+1, number, tmsf, attr); - - b[len++] = 0; /* reserved */ - b[len++] = attr; - b[len++] = number; /* track number */ - b[len++] = 0; /* reserved */ - - if (msf) - { - b[len++] = 0; - b[len++] = tmsf.min; - b[len++] = tmsf.sec; - b[len++] = tmsf.fr; - } - else - { - temp = MSFtoLBA(tmsf.min, tmsf.sec, tmsf.fr) - 150; - b[len++] = temp >> 24; - b[len++] = temp >> 16; - b[len++] = temp >> 8; - b[len++] = temp; - } - if (single) - break; - } - b[0] = (uint8_t)(((len-2) >> 8) & 0xff); - b[1] = (uint8_t)((len-2) & 0xff); - return len; -} - -static int image_readtoc_session(uint8_t id, unsigned char *b, int msf, int maxlen) -{ - int len = 4; - - int number; - TMSF tmsf; - unsigned char attr; - - if (!cdimg[id]) return 0; - - cdimg[id]->GetAudioTrackInfo(1, number, tmsf, attr); - - if (number == 0) - { - number = 1; - } - - b[2] = 1; - b[3] = 1; - b[len++] = 0; /* reserved */ - b[len++] = attr; - b[len++] = number; /* track number */ - b[len++] = 0; /* reserved */ - if (msf) - { - b[len++] = 0; - b[len++] = tmsf.min; - b[len++] = tmsf.sec; - b[len++] = tmsf.fr; - } - else - { - uint32_t temp = MSFtoLBA(tmsf.min, tmsf.sec, tmsf.fr) - 150; /* Do the - 150. */ - b[len++] = temp >> 24; - b[len++] = temp >> 16; - b[len++] = temp >> 8; - b[len++] = temp; - } - - if (maxlen < len) - { - return maxlen; - } - - return len; -} - -static int image_readtoc_raw(uint8_t id, unsigned char *b, int maxlen) -{ - int track; - int len = 4; - - int first_track; - int last_track; - int number; - unsigned char attr; - TMSF tmsf; - - if (!cdimg[id]) return 0; - - cdimg[id]->GetAudioTracks(first_track, last_track, tmsf); - - b[2] = first_track; - b[3] = last_track; - - for (track = first_track; track <= last_track; track++) - { - if ((len + 11) > maxlen) - { - cdrom_image_log("image_readtocraw: This iteration would fill the buffer beyond the bounds, aborting...\n"); - return len; - } - - cdimg[id]->GetAudioTrackInfo(track, number, tmsf, attr); - - b[len++] = track; - if (len == maxlen) return len; - b[len++]= attr; - if (len == maxlen) return len; - b[len++]=0; - if (len == maxlen) return len; - b[len++]=0; - if (len == maxlen) return len; - b[len++]=0; - if (len == maxlen) return len; - b[len++]=0; - if (len == maxlen) return len; - b[len++]=0; - if (len == maxlen) return len; - b[len++]=0; - if (len == maxlen) return len; - b[len++] = tmsf.min; - if (len == maxlen) return len; - b[len++] = tmsf.sec; - if (len == maxlen) return len; - b[len++] = tmsf.fr; - if (len == maxlen) return len; - } - return len; -} - -static int image_status(uint8_t id) -{ - cdrom_t *dev = cdrom[id]; - - if (!cdimg[id]) return CD_STATUS_EMPTY; - if (cdrom_image[id].image_is_iso) return CD_STATUS_DATA_ONLY; - if (cdimg[id]->HasAudioTracks()) - { - switch(dev->cd_state) - { - case CD_PLAYING: - return CD_STATUS_PLAYING; - case CD_PAUSED: - return CD_STATUS_PAUSED; - case CD_STOPPED: - default: - return CD_STATUS_STOPPED; - } - } - return CD_STATUS_DATA_ONLY; -} - -void image_reset(UNUSED(uint8_t id)) -{ - return; -} - -void image_close(uint8_t id) -{ - cdrom_t *dev = cdrom[id]; - - dev->cd_state = CD_STOPPED; - if (cdimg[id]) - { - delete cdimg[id]; - cdimg[id] = NULL; - } - memset(cdrom_image[id].image_path, 0, 2048); -} - -static char afn[1024]; - -int image_open(uint8_t id, wchar_t *fn) -{ - cdrom_t *dev = cdrom[id]; - - wcscpy(cdrom_image[id].image_path, fn); - - if (! wcscasecmp(plat_get_extension(fn), L"ISO")) - { - cdrom_image[id].image_is_iso = 1; - } - else - { - cdrom_image[id].image_is_iso = 0; - } - - cdimg[id] = new CDROM_Interface_Image(); - memset(afn, 0, sizeof(afn)); - wcstombs(afn, fn, sizeof(afn)); - if (!cdimg[id]->SetDevice(afn, false)) - { - image_close(id); - cdrom_set_null_handler(id); - return 1; - } - dev->cd_state = CD_STOPPED; + cdrom_t *dev = cdrom[id]; + if (!cdimg[id]) + return 0; + int number; + unsigned char attr; + TMSF tmsf; + int m = 0, s = 0, f = 0; + cdimg[id]->GetAudioTrackInfo(cdimg[id]->GetTrack(pos), number, tmsf, attr); + if (attr == DATA_TRACK) { + DEBUG("Can't play data track\n"); dev->seek_pos = 0; - dev->cd_buflen = 0; - dev->cdrom_capacity = image_get_last_block(id, 0, 0, 4096, 0) + 1; - cdrom_drives[id].handler = &image_cdrom; + dev->cd_state = CD_STOPPED; + return 0; + } - return 0; + DEBUG("Play audio - %08X %08X %i\n", pos, len, ismsf); + if (ismsf == 2) { + cdimg[id]->GetAudioTrackInfo(pos, number, tmsf, attr); + pos = MSFtoLBA(tmsf.min, tmsf.sec, tmsf.fr) - 150; + cdimg[id]->GetAudioTrackInfo(len, number, tmsf, attr); + len = MSFtoLBA(tmsf.min, tmsf.sec, tmsf.fr) - 150; + } else if (ismsf == 1) { + m = (pos >> 16) & 0xff; + s = (pos >> 8) & 0xff; + f = pos & 0xff; + + if (pos == 0xffffff) { + DEBUG("Playing from current position (MSF)\n"); + pos = dev->seek_pos; + } else + pos = MSFtoLBA(m, s, f) - 150; + + m = (len >> 16) & 0xff; + s = (len >> 8) & 0xff; + f = len & 0xff; + len = MSFtoLBA(m, s, f) - 150; + + DEBUG("MSF - pos = %08X len = %08X\n", pos, len); + } else if (ismsf == 0) { + if (pos == 0xffffffff) { + DEBUG("Playing from current position\n"); + pos = dev->seek_pos; + } + len += pos; + } + + dev->seek_pos = pos; + dev->cd_end = len; + dev->cd_state = CD_PLAYING; + dev->cd_buflen = 0; + + return 1; } -static void image_exit(uint8_t id) + +static void +image_pause(uint8_t id) { - cdrom_t *dev = cdrom[id]; + cdrom_t *dev = cdrom[id]; - dev->handler_inited = 0; + if (!cdimg[id] || cdrom_image[id].image_is_iso) return; + if (dev->cd_state == CD_PLAYING) + dev->cd_state = CD_PAUSED; } + +static void +image_resume(uint8_t id) +{ + cdrom_t *dev = cdrom[id]; + + if (!cdimg[id] || cdrom_image[id].image_is_iso) + return; + if (dev->cd_state == CD_PAUSED) + dev->cd_state = CD_PLAYING; +} + + +static void +image_stop(uint8_t id) +{ + cdrom_t *dev = cdrom[id]; + + if (!cdimg[id] || cdrom_image[id].image_is_iso) + return; + dev->cd_state = CD_STOPPED; +} + + +static int +image_ready(uint8_t id) +{ + if (!cdimg[id] || (wcslen(cdrom_image[id].image_path) == 0)) + return 0; + + return 1; +} + + +static int +image_get_last_block(uint8_t id) +{ + int first_track, last_track; + int number, c; + unsigned char attr; + TMSF tmsf; + uint32_t lb=0; + + if (!cdimg[id]) + return 0; + + cdimg[id]->GetAudioTracks(first_track, last_track, tmsf); + + for (c = 0; c <= last_track; c++) { + uint32_t address; + cdimg[id]->GetAudioTrackInfo(c+1, number, tmsf, attr); + address = MSFtoLBA(tmsf.min, tmsf.sec, tmsf.fr) - 150; /* Do the - 150 here as well. */ + if (address > lb) + lb = address; + } + return lb; +} + + +static int +image_medium_changed(UNUSED(uint8_t id)) +{ + /* There is no way to change the medium within an already mounted image. */ + return 0; +} + + +static uint8_t +image_getcurrentsubchannel(uint8_t id, uint8_t *b, int msf) +{ + cdrom_t *dev = cdrom[id]; + uint8_t ret; + int pos = 0; + uint32_t cdpos; + TMSF relPos, absPos; + unsigned char attr, track, index; + + cdpos = dev->seek_pos; + + if (!cdimg[id]) + return 0; + + cdimg[id]->GetAudioSub(cdpos, attr, track, index, relPos, absPos); + + if (cdrom_image[id].image_is_iso) + ret = 0x15; + else { + if (dev->cd_state == CD_PLAYING) + ret = 0x11; + else if (dev->cd_state == CD_PAUSED) + ret = 0x12; + else + ret = 0x13; + } + + b[pos++] = attr; + b[pos++] = track; + b[pos++] = index; + + if (msf) { + b[pos + 3] = (uint8_t) absPos.fr; + b[pos + 2] = (uint8_t) absPos.sec; + b[pos + 1] = (uint8_t) absPos.min; + b[pos] = 0; + pos += 4; + b[pos + 3] = (uint8_t) relPos.fr; + b[pos + 2] = (uint8_t) relPos.sec; + b[pos + 1] = (uint8_t) relPos.min; + b[pos] = 0; + pos += 4; + } else { + uint32_t dat = MSFtoLBA(absPos.min, absPos.sec, absPos.fr) - 150; + b[pos++] = (dat >> 24) & 0xff; + b[pos++] = (dat >> 16) & 0xff; + b[pos++] = (dat >> 8) & 0xff; + b[pos++] = dat & 0xff; + dat = MSFtoLBA(relPos.min, relPos.sec, relPos.fr); + b[pos++] = (dat >> 24) & 0xff; + b[pos++] = (dat >> 16) & 0xff; + b[pos++] = (dat >> 8) & 0xff; + b[pos++] = dat & 0xff; + } + + return ret; +} + + +static int +image_is_track_audio(uint8_t id, uint32_t pos, int ismsf) +{ + int m, s, f; + unsigned char attr; + TMSF tmsf; + int number; + + if (!cdimg[id] || cdrom_image[id].image_is_iso) + return 0; + + if (ismsf) { + m = (pos >> 16) & 0xff; + s = (pos >> 8) & 0xff; + f = pos & 0xff; + pos = MSFtoLBA(m, s, f) - 150; + } + + /* GetTrack requires LBA. */ + cdimg[id]->GetAudioTrackInfo(cdimg[id]->GetTrack(pos), number, tmsf, attr); + + return attr == AUDIO_TRACK; +} + + +static int +is_legal(UNUSED(int id), int type, int flags, int audio, int mode2) +{ + if (!(flags & 0x70)) { /* 0x00/0x08/0x80/0x88 are illegal modes */ + DEBUG("CD-ROM %i: [Any Mode] 0x00/0x08/0x80/0x88 are illegal modes\n", id); + return 0; + } + + if ((type != 1) && !audio) { + if (!(flags & 0x70)) { /* 0x00/0x08/0x80/0x88 are illegal modes */ + DEBUG("CD-ROM %i: [Any Data Mode] 0x00/0x08/0x80/0x88 are illegal modes\n", id); + return 0; + } + + if ((flags & 0x06) == 0x06) { + DEBUG("CD-ROM %i: [Any Data Mode] Invalid error flags\n", id); + return 0; + } + + if (((flags & 0x700) == 0x300) || ((flags & 0x700) > 0x400)) { + DEBUG("CD-ROM %i: [Any Data Mode] Invalid subchannel data flags (%02X)\n", id, flags & 0x700); + return 0; + } + + if ((flags & 0x18) == 0x08) { /* EDC/ECC without user data is an illegal mode */ + DEBUG("CD-ROM %i: [Any Data Mode] EDC/ECC without user data is an illegal mode\n", id); + return 0; + } + + if (((flags & 0xf0) == 0x90) || ((flags & 0xf0) == 0xc0)) { /* 0x90/0x98/0xC0/0xC8 are illegal modes */ + DEBUG("CD-ROM %i: [Any Data Mode] 0x90/0x98/0xC0/0xC8 are illegal modes\n", id); + return 0; + } + + if (((type > 3) && (type != 8)) || (mode2 && (mode2 & 0x03))) { + if ((flags & 0xf0) == 0x30) { /* 0x30/0x38 are illegal modes */ + DEBUG("CD-ROM %i: [Any XA Mode 2] 0x30/0x38 are illegal modes\n", id); + return 0; + } + if (((flags & 0xf0) == 0xb0) || ((flags & 0xf0) == 0xd0)) { /* 0xBx and 0xDx are illegal modes */ + DEBUG("CD-ROM %i: [Any XA Mode 2] 0xBx and 0xDx are illegal modes\n", id); + return 0; + } + } + } + + return 1; +} + + +static void +read_sector_to_buffer(uint8_t id, uint8_t *raw_buffer, uint32_t msf, uint32_t lba, int mode2, int len) +{ + uint8_t *bb = raw_buffer; + + cdimg[id]->ReadSector(raw_buffer + 16, false, lba); + + /* Sync bytes */ + bb[0] = 0; + memset(bb + 1, 0xff, 10); + bb[11] = 0; + bb += 12; + + /* Sector header */ + bb[0] = (msf >> 16) & 0xff; + bb[1] = (msf >> 8) & 0xff; + bb[2] = msf & 0xff; + + bb[3] = 1; /* mode 1 data */ + bb += mode2 ? 12 : 4; + bb += len; + if (mode2 && ((mode2 & 0x03) == 1)) + memset(bb, 0, 280); + else if (!mode2) + memset(bb, 0, 288); +} + + +static void +read_audio(int id, uint32_t lba, uint8_t *b) +{ + if (cdimg[id]->GetSectorSize(lba) == 2352) + cdimg[id]->ReadSector(raw_buffer, true, lba); + else + cdimg[id]->ReadSectorSub(raw_buffer, lba); + + memcpy(b, raw_buffer, 2352); + cdrom_sector_size = 2352; +} + + +static void +read_mode1(int id, int cdrom_sector_flags, uint32_t lba, uint32_t msf, int mode2, uint8_t *b) +{ + if ((cdrom_image[id].image_is_iso) || (cdimg[id]->GetSectorSize(lba) == 2048)) + read_sector_to_buffer(id, raw_buffer, msf, lba, mode2, 2048); + else if (cdimg[id]->GetSectorSize(lba) == 2352) + cdimg[id]->ReadSector(raw_buffer, true, lba); + else + cdimg[id]->ReadSectorSub(raw_buffer, lba); + + cdrom_sector_size = 0; + + if (cdrom_sector_flags & 0x80) { /* Sync */ + DEBUG("CD-ROM %i: [Mode 1] Sync\n", id); + memcpy(b, raw_buffer, 12); + cdrom_sector_size += 12; + b += 12; + } + + if (cdrom_sector_flags & 0x20) { /* Header */ + DEBUG("CD-ROM %i: [Mode 1] Header\n", id); + memcpy(b, raw_buffer + 12, 4); + cdrom_sector_size += 4; + b += 4; + } + + if (cdrom_sector_flags & 0x40) { /* Sub-header */ + if (!(cdrom_sector_flags & 0x10)) { /* No user data */ + DEBUG("CD-ROM %i: [Mode 1] Sub-header\n", id); + memcpy(b, raw_buffer + 16, 8); + cdrom_sector_size += 8; + b += 8; + } + } + + if (cdrom_sector_flags & 0x10) { /* User data */ + DEBUG("CD-ROM %i: [Mode 1] User data\n", id); + memcpy(b, raw_buffer + 16, 2048); + cdrom_sector_size += 2048; + b += 2048; + } + + if (cdrom_sector_flags & 0x08) { /* EDC/ECC */ + DEBUG("CD-ROM %i: [Mode 1] EDC/ECC\n", id); + memcpy(b, raw_buffer + 2064, 288); + cdrom_sector_size += 288; + b += 288; + } +} + + +static void +read_mode2_non_xa(int id, int cdrom_sector_flags, uint32_t lba, uint32_t msf, int mode2, uint8_t *b) +{ + if ((cdrom_image[id].image_is_iso) || (cdimg[id]->GetSectorSize(lba) == 2336)) + read_sector_to_buffer(id, raw_buffer, msf, lba, mode2, 2336); + else if (cdimg[id]->GetSectorSize(lba) == 2352) + cdimg[id]->ReadSector(raw_buffer, true, lba); + else + cdimg[id]->ReadSectorSub(raw_buffer, lba); + + cdrom_sector_size = 0; + + if (cdrom_sector_flags & 0x80) { /* Sync */ + DEBUG("CD-ROM %i: [Mode 2 Formless] Sync\n", id); + memcpy(b, raw_buffer, 12); + cdrom_sector_size += 12; + b += 12; + } + + if (cdrom_sector_flags & 0x20) { /* Header */ + DEBUG("CD-ROM %i: [Mode 2 Formless] Header\n", id); + memcpy(b, raw_buffer + 12, 4); + cdrom_sector_size += 4; + b += 4; + } + + /* Mode 1 sector, expected type is 1 type. */ + if (cdrom_sector_flags & 0x40) { /* Sub-header */ + DEBUG("CD-ROM %i: [Mode 2 Formless] Sub-header\n", id); + memcpy(b, raw_buffer + 16, 8); + cdrom_sector_size += 8; + b += 8; + } + + if (cdrom_sector_flags & 0x10) { /* User data */ + DEBUG("CD-ROM %i: [Mode 2 Formless] User data\n", id); + memcpy(b, raw_buffer + 24, 2336); + cdrom_sector_size += 2336; + b += 2336; + } +} + + +static void +read_mode2_xa_form1(int id, int cdrom_sector_flags, uint32_t lba, uint32_t msf, int mode2, uint8_t *b) +{ + if ((cdrom_image[id].image_is_iso) || (cdimg[id]->GetSectorSize(lba) == 2048)) + read_sector_to_buffer(id, raw_buffer, msf, lba, mode2, 2048); + else if (cdimg[id]->GetSectorSize(lba) == 2352) + cdimg[id]->ReadSector(raw_buffer, true, lba); + else + cdimg[id]->ReadSectorSub(raw_buffer, lba); + + cdrom_sector_size = 0; + + if (cdrom_sector_flags & 0x80) { /* Sync */ + DEBUG("CD-ROM %i: [XA Mode 2 Form 1] Sync\n", id); + memcpy(b, raw_buffer, 12); + cdrom_sector_size += 12; + b += 12; + } + + if (cdrom_sector_flags & 0x20) { /* Header */ + DEBUG("CD-ROM %i: [XA Mode 2 Form 1] Header\n", id); + memcpy(b, raw_buffer + 12, 4); + cdrom_sector_size += 4; + b += 4; + } + + if (cdrom_sector_flags & 0x40) { /* Sub-header */ + DEBUG("CD-ROM %i: [XA Mode 2 Form 1] Sub-header\n", id); + memcpy(b, raw_buffer + 16, 8); + cdrom_sector_size += 8; + b += 8; + } + + if (cdrom_sector_flags & 0x10) { /* User data */ + DEBUG("CD-ROM %i: [XA Mode 2 Form 1] User data\n", id); + memcpy(b, raw_buffer + 24, 2048); + cdrom_sector_size += 2048; + b += 2048; + } + + if (cdrom_sector_flags & 0x08) { /* EDC/ECC */ + DEBUG("CD-ROM %i: [XA Mode 2 Form 1] EDC/ECC\n", id); + memcpy(b, raw_buffer + 2072, 280); + cdrom_sector_size += 280; + b += 280; + } +} + + +static void +read_mode2_xa_form2(int id, int cdrom_sector_flags, uint32_t lba, uint32_t msf, int mode2, uint8_t *b) +{ + if ((cdrom_image[id].image_is_iso) || (cdimg[id]->GetSectorSize(lba) == 2324)) + read_sector_to_buffer(id, raw_buffer, msf, lba, mode2, 2324); + else if (cdimg[id]->GetSectorSize(lba) == 2352) + cdimg[id]->ReadSector(raw_buffer, true, lba); + else + cdimg[id]->ReadSectorSub(raw_buffer, lba); + + cdrom_sector_size = 0; + + if (cdrom_sector_flags & 0x80) { /* Sync */ + DEBUG("CD-ROM %i: [XA Mode 2 Form 2] Sync\n", id); + memcpy(b, raw_buffer, 12); + cdrom_sector_size += 12; + b += 12; + } + + if (cdrom_sector_flags & 0x20) { /* Header */ + DEBUG("CD-ROM %i: [XA Mode 2 Form 2] Header\n", id); + memcpy(b, raw_buffer + 12, 4); + cdrom_sector_size += 4; + b += 4; + } + + if (cdrom_sector_flags & 0x40) { /* Sub-header */ + DEBUG("CD-ROM %i: [XA Mode 2 Form 2] Sub-header\n", id); + memcpy(b, raw_buffer + 16, 8); + cdrom_sector_size += 8; + b += 8; + } + + if (cdrom_sector_flags & 0x10) { /* User data */ + DEBUG("CD-ROM %i: [XA Mode 2 Form 2] User data\n", id); + memcpy(b, raw_buffer + 24, 2328); + cdrom_sector_size += 2328; + b += 2328; + } +} + + +static int +image_readsector_raw(uint8_t id, uint8_t *buffer, int sector, int ismsf, int cdrom_sector_type, + int cdrom_sector_flags, int *len) +{ + uint8_t *b, *temp_b; + uint32_t msf, lba; + int audio, mode2; + int m, s, f; + + if (!cdimg[id]) + return 0; + + if (!cdrom_drives[id].host_drive) + return 0; + + b = temp_b = buffer; + + *len = 0; + + if (ismsf) { + m = (sector >> 16) & 0xff; + s = (sector >> 8) & 0xff; + f = sector & 0xff; + lba = MSFtoLBA(m, s, f) - 150; + msf = sector; + } else { + lba = sector; + msf = cdrom_lba_to_msf_accurate(sector); + } + + if (cdrom_image[id].image_is_iso) { + audio = 0; + mode2 = cdimg[id]->IsMode2(lba) ? 1 : 0; + } else { + audio = image_is_track_audio(id, sector, ismsf); + mode2 = cdimg[id]->IsMode2(lba) ? 1 : 0; + } + mode2 <<= 2; + mode2 |= cdimg[id]->GetMode2Form(lba); + + memset(raw_buffer, 0, 2448); + memset(extra_buffer, 0, 296); + + if (!(cdrom_sector_flags & 0xf0)) { /* 0x00 and 0x08 are illegal modes */ + DEBUG("CD-ROM %i: [Mode 1] 0x00 and 0x08 are illegal modes\n", id); + return 0; + } + + if (!is_legal(id, cdrom_sector_type, cdrom_sector_flags, audio, mode2)) + return 0; + + if ((cdrom_sector_type == 3) || ((cdrom_sector_type > 4) && (cdrom_sector_type != 8))) { + if (cdrom_sector_type == 3) { + DEBUG("CD-ROM %i: Attempting to read a Yellowbook Mode 2 data sector from an image\n", id); + } + if (cdrom_sector_type > 4) { + DEBUG("CD-ROM %i: Attempting to read a XA Mode 2 Form 2 data sector from an image\n", id); + } + return 0; + } else if (cdrom_sector_type == 1) { + if (!audio || cdrom_image[id].image_is_iso) { + DEBUG("CD-ROM %i: [Audio] Attempting to read an audio sector from a data image\n", id); + return 0; + } + + read_audio(id, lba, temp_b); + } else if (cdrom_sector_type == 2) { + if (audio || mode2) { + DEBUG("CD-ROM %i: [Mode 1] Attempting to read a sector of another type\n", id); + return 0; + } + + read_mode1(id, cdrom_sector_flags, lba, msf, mode2, temp_b); + } else if (cdrom_sector_type == 3) { + if (audio || !mode2 || (mode2 & 0x03)) { + DEBUG("CD-ROM %i: [Mode 2 Formless] Attempting to read a sector of another type\n", id); + return 0; + } + + read_mode2_non_xa(id, cdrom_sector_flags, lba, msf, mode2, temp_b); + } else if (cdrom_sector_type == 4) { + if (audio || !mode2 || ((mode2 & 0x03) != 1)) { + DEBUG("CD-ROM %i: [XA Mode 2 Form 1] Attempting to read a sector of another type\n", id); + return 0; + } + + read_mode2_xa_form1(id, cdrom_sector_flags, lba, msf, mode2, temp_b); + } else if (cdrom_sector_type == 5) { + if (audio || !mode2 || ((mode2 & 0x03) != 2)) { + DEBUG("CD-ROM %i: [XA Mode 2 Form 2] Attempting to read a sector of another type\n", id); + return 0; + } + + read_mode2_xa_form2(id, cdrom_sector_flags, lba, msf, mode2, temp_b); + } else if (cdrom_sector_type == 8) { + if (audio) { + DEBUG("CD-ROM %i: [Any Data] Attempting to read a data sector from an audio track\n", id); + return 0; + } + + if (mode2 && ((mode2 & 0x03) == 1)) + read_mode2_xa_form1(id, cdrom_sector_flags, lba, msf, mode2, temp_b); + else if (!mode2) + read_mode1(id, cdrom_sector_flags, lba, msf, mode2, temp_b); + else { + DEBUG("CD-ROM %i: [Any Data] Attempting to read a data sector whose cooked size is not 2048 bytes\n", id); + return 0; + } + } else { + if (mode2) { + if ((mode2 & 0x03) == 0x01) + read_mode2_xa_form1(id, cdrom_sector_flags, lba, msf, mode2, temp_b); + else if ((mode2 & 0x03) == 0x02) + read_mode2_xa_form2(id, cdrom_sector_flags, lba, msf, mode2, temp_b); + else + read_mode2_non_xa(id, cdrom_sector_flags, lba, msf, mode2, temp_b); + } else { + if (audio) + read_audio(id, lba, temp_b); + else + read_mode1(id, cdrom_sector_flags, lba, msf, mode2, temp_b); + } + } + + if ((cdrom_sector_flags & 0x06) == 0x02) { + /* Add error flags. */ + DEBUG("CD-ROM %i: Error flags\n", id); + memcpy(b + cdrom_sector_size, extra_buffer, 294); + cdrom_sector_size += 294; + } else if ((cdrom_sector_flags & 0x06) == 0x04) { + /* Add error flags. */ + DEBUG("CD-ROM %i: Full error flags\n", id); + memcpy(b + cdrom_sector_size, extra_buffer, 296); + cdrom_sector_size += 296; + } + + if ((cdrom_sector_flags & 0x700) == 0x100) { + DEBUG("CD-ROM %i: Raw subchannel data\n", id); + memcpy(b + cdrom_sector_size, raw_buffer + 2352, 96); + cdrom_sector_size += 96; + } else if ((cdrom_sector_flags & 0x700) == 0x200) { + DEBUG("CD-ROM %i: Q subchannel data\n", id); + memcpy(b + cdrom_sector_size, raw_buffer + 2352, 16); + cdrom_sector_size += 16; + } else if ((cdrom_sector_flags & 0x700) == 0x400) { + DEBUG("CD-ROM %i: R/W subchannel data\n", id); + memcpy(b + cdrom_sector_size, raw_buffer + 2352, 96); + cdrom_sector_size += 96; + } + + *len = cdrom_sector_size; + + return 1; +} + + +static uint32_t +image_size(uint8_t id) +{ + cdrom_t *dev = cdrom[id]; + + return dev->cdrom_capacity; +} + + +static int +image_readtoc(uint8_t id, unsigned char *b, unsigned char starttrack, int msf, UNUSED(int maxlen), int single) +{ + int number, len = 4; + int c, d, first_track, last_track; + uint32_t temp; + unsigned char attr; + TMSF tmsf; + + if (!cdimg[id]) + return 0; + + cdimg[id]->GetAudioTracks(first_track, last_track, tmsf); + + b[2] = first_track; + b[3] = last_track; + + d = 0; + for (c = 0; c <= last_track; c++) { + cdimg[id]->GetAudioTrackInfo(c+1, number, tmsf, attr); + if (number >= starttrack) { + d=c; + break; + } + } + + if (starttrack != 0xAA) { + cdimg[id]->GetAudioTrackInfo(c+1, number, tmsf, attr); + b[2] = number; + } + + for (c = d; c <= last_track; c++) { + cdimg[id]->GetAudioTrackInfo(c+1, number, tmsf, attr); + + b[len++] = 0; /* reserved */ + b[len++] = attr; + b[len++] = number; /* track number */ + b[len++] = 0; /* reserved */ + + if (msf) { + b[len++] = 0; + b[len++] = tmsf.min; + b[len++] = tmsf.sec; + b[len++] = tmsf.fr; + } else { + temp = MSFtoLBA(tmsf.min, tmsf.sec, tmsf.fr) - 150; + b[len++] = temp >> 24; + b[len++] = temp >> 16; + b[len++] = temp >> 8; + b[len++] = temp; + } + + if (single) + break; + } + + b[0] = (uint8_t)(((len-2) >> 8) & 0xff); + b[1] = (uint8_t)((len-2) & 0xff); + + return len; +} + + +static int +image_readtoc_session(uint8_t id, unsigned char *b, int msf, int maxlen) +{ + int number, len = 4; + TMSF tmsf; + unsigned char attr; + uint32_t temp; + + if (!cdimg[id]) + return 0; + + cdimg[id]->GetAudioTrackInfo(1, number, tmsf, attr); + + if (number == 0) + number = 1; + + b[2] = b[3] = 1; + b[len++] = 0; /* reserved */ + b[len++] = attr; + b[len++] = number; /* track number */ + b[len++] = 0; /* reserved */ + if (msf) { + b[len++] = 0; + b[len++] = tmsf.min; + b[len++] = tmsf.sec; + b[len++] = tmsf.fr; + } else { + temp = MSFtoLBA(tmsf.min, tmsf.sec, tmsf.fr) - 150; /* Do the - 150. */ + b[len++] = temp >> 24; + b[len++] = temp >> 16; + b[len++] = temp >> 8; + b[len++] = temp; + } + + if (maxlen < len) + return maxlen; + + return len; +} + + +static int +image_readtoc_raw(uint8_t id, unsigned char *b, UNUSED(int maxlen)) +{ + int track, len = 4; + int first_track, last_track; + int number; + unsigned char attr; + TMSF tmsf; + + if (!cdimg[id]) + return 0; + + cdimg[id]->GetAudioTracks(first_track, last_track, tmsf); + + b[2] = first_track; + b[3] = last_track; + + for (track = first_track; track <= last_track; track++) { + cdimg[id]->GetAudioTrackInfo(track, number, tmsf, attr); + + b[len++] = track; + b[len++]= attr; + b[len++]=0; + b[len++]=0; + b[len++]=0; + b[len++]=0; + b[len++]=0; + b[len++]=0; + b[len++] = tmsf.min; + b[len++] = tmsf.sec; + b[len++] = tmsf.fr; + } + + return len; +} + + +static int +image_status(uint8_t id) +{ + cdrom_t *dev = cdrom[id]; + + if (!cdimg[id]) + return CD_STATUS_EMPTY; + + if (cdrom_image[id].image_is_iso) + return CD_STATUS_DATA_ONLY; + + if (cdimg[id]->HasAudioTracks()) { + switch(dev->cd_state) { + case CD_PLAYING: + return CD_STATUS_PLAYING; + case CD_PAUSED: + return CD_STATUS_PAUSED; + case CD_STOPPED: + default: + return CD_STATUS_STOPPED; + } + } + + return CD_STATUS_DATA_ONLY; +} + + +void +image_reset(UNUSED(uint8_t id)) +{ + return; +} + + +void +image_close(uint8_t id) +{ + cdrom_t *dev = cdrom[id]; + + dev->cd_state = CD_STOPPED; + if (cdimg[id]) { + delete cdimg[id]; + cdimg[id] = NULL; + } +} + + +int +image_open(uint8_t id, wchar_t *fn) +{ + cdrom_t *dev = cdrom[id]; + + wcscpy(cdrom_image[id].image_path, fn); + + if (! wcscasecmp(plat_get_extension(fn), L"ISO")) + cdrom_image[id].image_is_iso = 1; + else + cdrom_image[id].image_is_iso = 0; + + cdimg[id] = new CDROM_Interface_Image(); + memset(afn, 0, sizeof(afn)); + wcstombs(afn, fn, sizeof(afn)); + if (!cdimg[id]->SetDevice(afn, false)) { + image_close(id); + cdrom_set_null_handler(id); + DEBUG("[f] image_open(): cdrom[%i]->handler = %08X\n", id, cdrom[id]->handler); + return 1; + } + dev->cd_state = CD_STOPPED; + dev->seek_pos = 0; + dev->cd_buflen = 0; + dev->cdrom_capacity = image_get_last_block(id) + 1; + cdrom[id]->handler = &image_cdrom; + + return 0; +} + + +static void +image_exit(uint8_t id) +{ + cdrom_t *dev = cdrom[id]; + + dev->handler_inited = 0; +} + + /* TODO: Check for what data type a mixed CD is. */ static int image_media_type_id(uint8_t id) { - if (!cdrom_image[id].image_is_iso) - { - return 3; /* Mixed mode CD. */ - } - - if (image_size(id) <= 405000) - { + if (image_size(id) > 405000) + return 65; /* DVD. */ + else { + if (cdrom_image[id].image_is_iso) return 1; /* Data CD. */ - } else - { - return 65; /* DVD. */ - } + return 3; /* Mixed mode CD. */ + } } + CDROM image_cdrom = { - image_ready, - image_medium_changed, - image_media_type_id, - image_audio_callback, - image_audio_stop, - image_readtoc, - image_readtoc_session, - image_readtoc_raw, - image_getcurrentsubchannel, - NULL, - image_readsector_raw, - image_playaudio, - image_load, - image_eject, - image_pause, - image_resume, - image_size, - image_status, - image_is_track_audio, - image_stop, - image_exit + image_ready, + image_medium_changed, + image_media_type_id, + image_audio_callback, + image_audio_stop, + image_readtoc, + image_readtoc_session, + image_readtoc_raw, + image_getcurrentsubchannel, + image_readsector_raw, + image_playaudio, + image_pause, + image_resume, + image_size, + image_status, + image_stop, + image_exit }; diff --git a/src/devices/cdrom/cdrom_image.h b/src/devices/cdrom/cdrom_image.h index 597b0a2..e6a9b1e 100644 --- a/src/devices/cdrom/cdrom_image.h +++ b/src/devices/cdrom/cdrom_image.h @@ -11,7 +11,7 @@ * This header file lists the functions provided by * various platform specific cdrom-ioctl files. * - * Version: @(#)cdrom_image.h 1.0.3 2018/04/10 + * Version: @(#)cdrom_image.h 1.0.5 2018/09/14 * * Authors: Miran Grca, * RichardG, @@ -48,13 +48,17 @@ extern "C" { extern int cdrom_image_do_log; -extern int image_open(uint8_t id, wchar_t *fn); -extern void image_reset(uint8_t id); - -extern void image_close(uint8_t id); +extern void cdrom_image_log(int level, const char *fmt, ...); extern void cdrom_set_null_handler(uint8_t id); +extern int image_open(uint8_t id, wchar_t *fn); +extern void image_close(uint8_t id); +extern void image_reset(uint8_t id); + +extern int image_audio_callback(uint8_t id, int16_t *output, int len); +extern void image_audio_stop(uint8_t id); + #ifdef __cplusplus } #endif diff --git a/src/devices/cdrom/cdrom_null.c b/src/devices/cdrom/cdrom_null.c index 829fbf8..aa9166a 100644 --- a/src/devices/cdrom/cdrom_null.c +++ b/src/devices/cdrom/cdrom_null.c @@ -9,7 +9,7 @@ * Implementation of the CD-ROM null interface for unmounted * guest CD-ROM drives. * - * Version: @(#)cdrom_null.c 1.0.3 2018/05/06 + * Version: @(#)cdrom_null.c 1.0.4 2018/10/05 * * Author: Miran Grca, * Sarah Walker, @@ -40,10 +40,9 @@ #include #include #include "../../emu.h" +#include "../scsi/scsi_device.h" #include "cdrom.h" - - -static CDROM null_cdrom; +#include "cdrom_null.h" static int @@ -68,17 +67,6 @@ null_getcurrentsubchannel(uint8_t id, uint8_t *b, int msf) } -static void -null_eject(uint8_t id) -{ -} - - -static void -null_load(uint8_t id) -{ -} - static int null_readsector_raw(uint8_t id, uint8_t *buffer, int sector, int ismsf, int cdrom_sector_type, int cdrom_sector_flags, int *len) { @@ -132,7 +120,7 @@ cdrom_null_reset(uint8_t id) void cdrom_set_null_handler(uint8_t id); int -cdrom_null_open(uint8_t id, char d) +cdrom_null_open(uint8_t id) { cdrom_set_null_handler(id); @@ -152,20 +140,6 @@ void null_exit(uint8_t id) } -static int -null_is_track_audio(uint8_t id, uint32_t pos, int ismsf) -{ - return(0); -} - - -static int -null_pass_through(uint8_t id, uint8_t *in_cdb, uint8_t *b, uint32_t *len) -{ - return(0); -} - - static int null_media_type_id(uint8_t id) { @@ -173,15 +147,6 @@ null_media_type_id(uint8_t id) } -void -cdrom_set_null_handler(uint8_t id) -{ - cdrom_drives[id].handler = &null_cdrom; - cdrom_drives[id].host_drive = 0; - memset(cdrom_image[id].image_path, 0, sizeof(cdrom_image[id].image_path)); -} - - static CDROM null_cdrom = { null_ready, null_medium_changed, @@ -192,16 +157,21 @@ static CDROM null_cdrom = { null_readtoc_session, null_readtoc_raw, null_getcurrentsubchannel, - null_pass_through, null_readsector_raw, NULL, - null_load, - null_eject, NULL, NULL, null_size, null_status, - null_is_track_audio, NULL, null_exit }; + + +void +cdrom_set_null_handler(uint8_t id) +{ + cdrom[id]->handler = &null_cdrom; + cdrom_drives[id].host_drive = 0; + memset(cdrom_image[id].image_path, 0, sizeof(cdrom_image[id].image_path)); +} diff --git a/src/devices/cdrom/cdrom_null.h b/src/devices/cdrom/cdrom_null.h index 2354fdc..d352de2 100644 --- a/src/devices/cdrom/cdrom_null.h +++ b/src/devices/cdrom/cdrom_null.h @@ -8,7 +8,7 @@ * * Definitions for the NULL CD-ROM handler. * - * Version: @(#)cdrom_null.h 1.0.1 2018/02/14 + * Version: @(#)cdrom_null.h 1.0.2 2018/09/04 * * Authors: Miran Grca, * Sarah Walker, @@ -37,11 +37,12 @@ #ifndef EMU_CDROM_NULL_H # define EMU_CDROM_NULL_H + #ifdef __cplusplus extern "C" { #endif -extern int cdrom_null_open(uint8_t id, char d); +extern int cdrom_null_open(uint8_t id); extern void cdrom_null_reset(uint8_t id); extern void null_close(uint8_t id); @@ -49,4 +50,5 @@ extern void null_close(uint8_t id); } #endif + #endif /*EMU_CDROM_NULL_H*/ diff --git a/src/devices/cdrom/cdrom_speed.c b/src/devices/cdrom/cdrom_speed.c new file mode 100644 index 0000000..e5672ee --- /dev/null +++ b/src/devices/cdrom/cdrom_speed.c @@ -0,0 +1,115 @@ +/* + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. + * + * This file is part of the VARCem Project. + * + * Define the various speeds supported by optical devices. + * + * List of usable CD-ROM speeds (from Wikipedia): + * + * Speed KiB/s Mbit/s RPM + * 1x 150 1.2288 200-500 + * 2x 300 2.4576 400-1,000 + * 4x 600 4.9152 800-2,000 + * 6x ? ? ? + * 8x 1,200 9.8304 1,600-4,000 + * 10x 1,500 12.288 2,000-5,000 + * 12x 1,800 14.7456 2,400-6,000 + * 16x ? ? ? + * 20x 1,200-3,000 up to 24.576 4,000 (CAV) + * 24x ? ? ? + * 32x 1,920-4,800 up to 39.3216 6,400 (CAV) + * 36x 2,160-5,400 up to 44.2368 7,200 (CAV) + * 40x 2,400-6,000 up to 49.152 8,000 (CAV) + * 44x ? ? ? + * 48x 2,880-7,200 up to 58.9824 9,600 (CAV) + * 52x 3,120-7,800 up to 63.8976 10,400 (CAV) + * 56x 3,360-8,400 up to 68.8128 11,200 (CAV) + * 72x 6,750-10,800 up to 88.4736 2,000 (multi-beam) + * + * We discard the latter two ones. + * + * Version: @(#)cdrom_speed.c 1.0.2 2018/10/05 + * + * Author: Fred N. van Kempen, + * + * Copyright 2017,2018 Fred N. van Kempen. + * + * Redistribution and use in source and binary forms, with + * or without modification, are permitted provided that the + * following conditions are met: + * + * 1. Redistributions of source code must retain the entire + * above notice, this list of conditions and the following + * disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the + * following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names + * of its contributors may be used to endorse or promote + * products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include +#include +#include +#include +#include "../../emu.h" +#include "../../version.h" +#include "../../ui/ui.h" +#include "../../plat.h" +#include "../scsi/scsi_device.h" +#include "cdrom.h" + + +const cdrom_speed_t cdrom_speeds[] = { + { 1, 140.0, 1446.0 }, + { 2, 160.0, 1000.0 }, + { 4, 112.0, 675.0 }, + { 6, 112.0, 675.0 }, + { 8, 112.0, 675.0 }, + { 10, 112.0, 675.0 }, + { 12, 75.0, 400.0 }, + { 16, 58.0, 350.0 }, + { 20, 50.0, 300.0 }, + { 24, 45.0, 270.0 }, + { 32, 45.0, 270.0 }, + { 36, 50.0, 300.0 }, + { 40, 50.0, 300.0 }, + { 44, 50.0, 300.0 }, + { 48, 50.0, 300.0 }, + { 52, 45.0, 270.0 }, + { -1, 0.0, 0.0 }, +}; + + +/* Return a speed index for a given real speed. */ +int +cdrom_speed_idx(int realspeed) +{ + int idx; + + for (idx = 0; cdrom_speeds[idx].speed > 0; idx++) + if (cdrom_speeds[idx].speed == realspeed) + return(idx); + + return(-1); +} diff --git a/src/devices/disk/hdc.c b/src/devices/disk/hdc.c index 032576b..14af373 100644 --- a/src/devices/disk/hdc.c +++ b/src/devices/disk/hdc.c @@ -8,7 +8,7 @@ * * Common code to handle all sorts of disk controllers. * - * Version: @(#)hdc.c 1.0.13 2018/05/06 + * Version: @(#)hdc.c 1.0.14 2018/09/16 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -40,10 +40,12 @@ #include #include #define HAVE_STDARG_H +#define dbglog hdc_log #include "../../emu.h" #include "../../machines/machine.h" #include "../../device.h" #include "hdc.h" +#include "hdd.h" #include "hdc_ide.h" @@ -52,119 +54,49 @@ int hdc_do_log = ENABLE_HDC_LOG; #endif -static void * -null_init(const device_t *info) -{ - return(NULL); -} - - -static void -null_close(void *priv) -{ -} - - -static const device_t null_device = { - "Null HDC", 0, 0, - null_init, null_close, NULL, - NULL, NULL, NULL, NULL, - NULL -}; - - -static void * -inthdc_init(const device_t *info) -{ - return(NULL); -} - - -static void -inthdc_close(void *priv) -{ -} - - -static const device_t inthdc_device = { - "Internal Controller", 0, 0, - inthdc_init, inthdc_close, NULL, - NULL, NULL, NULL, NULL, - NULL -}; - - static const struct { - const char *name; const char *internal_name; const device_t *device; - int is_st506; } controllers[] = { - { "Disabled", "none", - &null_device, 0 }, + { "none", NULL }, + { "internal", NULL }, - { "Internal Controller", "internal", - &inthdc_device, 0 }, + { "st506_xt", &st506_xt_xebec_device }, + { "st506_dtc5150x", &st506_xt_dtc5150x_device }, - { "[ISA] [ST506] IBM PC Fixed Disk Adapter", "st506_xt", - &st506_xt_xebec_device, 1 }, + { "xta_wdxt150", &xta_wdxt150_device }, - { "[ISA] [ST506] DTC-5150X Fixed Disk Adapter", "st506_dtc5150x", - &st506_xt_dtc5150x_device, 1 }, + { "xtide", &xtide_device }, + { "xtide_acculogic", &xtide_acculogic_device }, - { "[ISA] [IDE] WDXT-150 IDE (XTA) Adapter", "xta_wdxt150", - &xta_wdxt150_device, 0, }, + { "st506_at", &st506_at_wd1003_device }, + { "esdi_at", &esdi_at_wd1007vse1_device }, - { "[ISA] [IDE] PC/XT XTIDE (ATA)", "xtide", - &xtide_device, 0 }, + { "ide_isa", &ide_isa_device }, + { "ide_isa_2ch", &ide_isa_2ch_device }, - { "[ISA] [IDE] PC/XT Acculogic XT IDE", "xtide_acculogic", - &xtide_acculogic_device, 0 }, + { "xtide_at", &xtide_at_device }, + { "xtide_at_ps2", &xtide_at_ps2_device }, - { "[ISA] [ST506] IBM PC/AT Fixed Disk Adapter", "st506_at", - &st506_at_wd1003_device, 1 }, + { "esdi_mca", &esdi_ps2_device }, - { "[ISA] [ESDI] PC/AT ESDI Fixed Disk Adapter", "esdi_at", - &esdi_at_wd1007vse1_device, 0 }, + { "ide_pci", &ide_pci_device }, + { "ide_pci_2ch", &ide_pci_2ch_device }, - { "[ISA] [IDE] PC/AT IDE (ATA) Adapter", "ide_isa", - &ide_isa_device, 0 }, + { "vlb_isa", &ide_vlb_device }, + { "vlb_isa_2ch", &ide_vlb_2ch_device }, - { "[ISA] [IDE] PC/AT IDE Adapter (Dual-Channel)", "ide_isa_2ch", - &ide_isa_2ch_device, 0 }, - - { "[ISA] [IDE] PC/AT XTIDE", "xtide_at", - &xtide_at_device, 0 }, - - { "[ISA] [IDE] PS/2 AT XTIDE (1.1.5)", "xtide_at_ps2", - &xtide_at_ps2_device, 0 }, - - { "[MCA] [ESDI] IBM PS/2 ESDI Fixed Disk Adapter","esdi_mca", - &esdi_ps2_device, 1 }, - - { "[PCI] [IDE] PCI IDE Adapter", "ide_pci", - &ide_pci_device, 0 }, - - { "[PCI] [IDE] PCI IDE Adapter (Dual-Channel)", "ide_pci_2ch", - &ide_pci_2ch_device, 0 }, - - { "[VLB] [IDE] PC/AT IDE Adapter", "vlb_isa", - &ide_vlb_device, 0 }, - - { "[VLB] [IDE] PC/AT IDE Adapter (Dual-Channel)", "vlb_isa_2ch", - &ide_vlb_2ch_device, 0 }, - - { NULL, NULL, NULL, 0 } + { NULL, NULL } }; void -hdc_log(const char *fmt, ...) +hdc_log(int level, const char *fmt, ...) { #ifdef ENABLE_HDC_LOG va_list ap; - if (hdc_do_log) { + if (hdc_do_log >= level) { va_start(ap, fmt); pclog_ex(fmt, ap); va_end(ap); @@ -173,34 +105,41 @@ hdc_log(const char *fmt, ...) } +/* Initialize the HDC module. */ +void +hdc_init(void) +{ + /* Zero all the hard disk image arrays. */ + hdd_image_init(); +} + + /* Reset the HDC, whichever one that is. */ void hdc_reset(void) { -#ifdef ENABLE_HDC_LOG - hdc_log("HDC: reset(current=%d, internal=%d)\n", - hdc_type, (machines[machine].flags & MACHINE_HDC)?1:0); -#endif + INFO("HDC: reset(current=%d, internal=%d)\n", + hdc_type, !!(machines[machine].flags & MACHINE_HDC)); /* If we have a valid controller, add its device. */ - if (hdc_type > 1) + if (controllers[hdc_type].device != NULL) device_add(controllers[hdc_type].device); - /* Reconfire and reset the IDE layer. */ - ide_ter_disable(); - ide_qua_disable(); - if (ide_enable[2]) - ide_ter_init(); - if (ide_enable[3]) - ide_qua_init(); - ide_reset_hard(); + /* Now, add the tertiary and/or quaternary IDE controllers. */ + if (ide_ter_enabled) + device_add(&ide_ter_device); + if (ide_qua_enabled) + device_add(&ide_qua_device); } const char * hdc_get_name(int hdc) { - return(controllers[hdc].name); + if (controllers[hdc].device != NULL) + return(controllers[hdc].device->name); + + return(NULL); } @@ -211,6 +150,21 @@ hdc_get_internal_name(int hdc) } +int +hdc_get_from_internal_name(const char *s) +{ + int c = 0; + + while (controllers[c].internal_name != NULL) { + if (! strcmp(controllers[c].internal_name, s)) + return(c); + c++; + } + + /* Not found. */ + return(0); +} + const device_t * hdc_get_device(int hdc) @@ -235,7 +189,10 @@ hdc_has_config(int hdc) int hdc_get_flags(int hdc) { - return(controllers[hdc].device->flags); + if (controllers[hdc].device != NULL) + return(controllers[hdc].device->flags); + + return(0); } @@ -244,19 +201,3 @@ hdc_available(int hdc) { return(device_available(controllers[hdc].device)); } - - -int -hdc_get_from_internal_name(const char *s) -{ - int c = 0; - - while (controllers[c].internal_name != NULL) { - if (! strcmp(controllers[c].internal_name, s)) - return(c); - c++; - } - - /* Not found. */ - return(0); -} diff --git a/src/devices/disk/hdc.h b/src/devices/disk/hdc.h index 39c1874..c7944c1 100644 --- a/src/devices/disk/hdc.h +++ b/src/devices/disk/hdc.h @@ -8,7 +8,7 @@ * * Definitions for the common disk controller handler. * - * Version: @(#)hdc.h 1.0.13 2018/04/25 + * Version: @(#)hdc.h 1.0.14 2018/09/28 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -40,7 +40,8 @@ #define ST506_NUM 2 /* 2 drives per controller supported */ #define ESDI_NUM 2 /* 2 drives per controller supported */ -#define IDE_NUM 8 +#define IDE_NUM 8 /* 4 controllers, 2 drives per controller */ +#define XTIDE_NUM 2 /* 2 drives, part of IDE structures */ #define SCSI_NUM 16 /* theoretically the controller can have at * least 7 devices, with each device being * able to support 8 units, but hey... */ @@ -64,6 +65,7 @@ extern const device_t esdi_ps2_device; /* esdi_mca */ extern const device_t xta_wdxt150_device; /* xta_wdxt150 */ extern const device_t xta_hd20_device; /* EuroPC internal */ +extern const device_t xta_t1200_device; /* T1200 internal */ extern const device_t xtide_device; /* xtide_xt */ extern const device_t xtide_acculogic_device; /* xtide_ps2 */ @@ -76,13 +78,16 @@ extern const device_t ide_vlb_2ch_device; /* vlb_ide_2ch */ extern const device_t ide_pci_device; /* pci_ide */ extern const device_t ide_pci_2ch_device; /* pci_ide_2ch */ +extern const device_t ide_ter_device; +extern const device_t ide_qua_device; + extern const device_t xtide_at_device; /* xtide_at */ extern const device_t xtide_at_ps2_device; /* xtide_at_ps2 */ #endif -extern void hdc_log(const char *fmt, ...); -extern void hdc_init(char *name); +extern void hdc_log(int level, const char *fmt, ...); +extern void hdc_init(void); extern void hdc_reset(void); extern const char *hdc_get_name(int hdc); diff --git a/src/devices/disk/hdc_esdi_at.c b/src/devices/disk/hdc_esdi_at.c index 7bfe213..28e3069 100644 --- a/src/devices/disk/hdc_esdi_at.c +++ b/src/devices/disk/hdc_esdi_at.c @@ -8,7 +8,7 @@ * * Driver for the ESDI controller (WD1007-vse1) for PC/AT. * - * Version: @(#)hdc_esdi_at.c 1.0.11 2018/06/08 + * Version: @(#)hdc_esdi_at.c 1.0.12 2018/09/22 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -44,6 +44,7 @@ #include #include #include +#define dbglog hdc_log #include "../../emu.h" #include "../../cpu/cpu.h" #include "../../machines/machine.h" @@ -127,32 +128,23 @@ typedef struct { static __inline void irq_raise(hdc_t *dev) { - /* If not already pending.. */ - if (! dev->irqstat) { - /* If enabled in the control register.. */ - if (! (dev->fdisk & 0x02)) { - /* .. raise IRQ14. */ - picint(1<<14); - } - - /* Remember this. */ - dev->irqstat = 1; + /* If enabled in the control register.. */ + if (! (dev->fdisk & 0x02)) { + /* .. raise IRQ14. */ + picint(1 << 14); } + + dev->irqstat = 1; } static __inline void irq_lower(hdc_t *dev) { - /* If raised.. */ if (dev->irqstat) { - /* If enabled in the control register.. */ - if (! (dev->fdisk & 0x02)) { - /* .. drop IRQ14. */ - picintc(1<<14); - } + if (! (dev->fdisk & 0x02)) + picintc(1 << 14); - /* Remember this. */ dev->irqstat = 0; } } @@ -168,16 +160,12 @@ get_sector(hdc_t *dev, off64_t *addr) int c, h, s; if (dev->head > heads) { -#ifdef ENABLE_HDC_LOG - hdc_log("dev_get_sector: past end of configured heads\n"); -#endif + DEBUG("dev_get_sector: past end of configured heads\n"); return(1); } if (dev->sector >= sectors+1) { -#ifdef ENABLE_HDC_LOG - hdc_log("dev_get_sector: past end of configured sectors\n"); -#endif + DEBUG("dev_get_sector: past end of configured sectors\n"); return(1); } @@ -249,9 +237,7 @@ hdc_write(uint16_t port, uint8_t val, void *priv) { hdc_t *dev = (hdc_t *)priv; -#ifdef ENABLE_HDC_LOG - hdc_log("WD1007 write(%04x, %02x)\n", port, val); -#endif + DBGLOG(2, "WD1007 write(%04x, %02x)\n", port, val); switch (port) { case 0x1f0: /* data */ @@ -293,9 +279,7 @@ hdc_write(uint16_t port, uint8_t val, void *priv) dev->command = val; dev->error = 0; -#ifdef ENABLE_HDC_LOG - hdc_log("WD1007: command %02x\n", val & 0xf0); -#endif + DEBUG("WD1007: command %02x\n", val & 0xf0); switch (val & 0xf0) { case CMD_RESTORE: dev->command &= ~0x0f; /*mask off step rate*/ @@ -385,9 +369,7 @@ hdc_write(uint16_t port, uint8_t val, void *priv) break; default: -#ifdef ENABLE_HDC_LOG - hdc_log("WD1007: bad command %02X\n", val); -#endif + DEBUG("WD1007: bad command %02X\n", val); case 0xe8: /*???*/ dev->status = STAT_BUSY; timer_clock(); @@ -417,7 +399,7 @@ hdc_write(uint16_t port, uint8_t val, void *priv) dev->fdisk = val; /* Lower IRQ on IRQ disable. */ - if ((val & 2) && !(dev->fdisk & 0x02)) + if ((val & 0x02) && !(dev->fdisk & 0x02)) picintc(1 << 14); break; } @@ -447,8 +429,6 @@ hdc_readw(uint16_t port, void *priv) dev->callback = (3125LL * TIMER_USEC) / 8LL; timer_update_outstanding(); - } else { - ui_sb_icon_update(SB_HDD|HDD_BUS_ESDI, 0); } } } @@ -498,9 +478,7 @@ hdc_read(uint16_t port, void *priv) break; } -#ifdef ENABLE_HDC_LOG - hdc_log("WD1007 read(%04x) = %02x\n", port, temp); -#endif + DBGLOG(2, "WD1007 read(%04x) = %02x\n", port, temp); return(temp); } @@ -523,14 +501,12 @@ hdc_callback(void *priv) dev->cylinder = 0; dev->reset = 0; - ui_sb_icon_update(SB_HDD|HDD_BUS_ESDI, 0); + hdd_active(drive->hdd_num, 0); return; } -#ifdef ENABLE_HDC_LOG - hdc_log("WD1007: command %02x\n", dev->command); -#endif + DEBUG("WD1007: command %02x\n", dev->command); switch (dev->command) { case CMD_RESTORE: @@ -569,13 +545,14 @@ hdc_callback(void *priv) break; } + hdd_active(drive->hdd_num, 1); + hdd_image_read(drive->hdd_num, addr, 1, (uint8_t *)dev->buffer); dev->pos = 0; dev->status = STAT_DRQ|STAT_READY|STAT_DSC; irq_raise(dev); - ui_sb_icon_update(SB_HDD|HDD_BUS_ESDI, 1); break; case CMD_WRITE: @@ -593,6 +570,8 @@ hdc_callback(void *priv) break; } + hdd_active(drive->hdd_num, 1); + hdd_image_write(drive->hdd_num, addr, 1, (uint8_t *)dev->buffer); @@ -605,7 +584,6 @@ hdc_callback(void *priv) } else { dev->status = STAT_READY|STAT_DSC; } - ui_sb_icon_update(SB_HDD|HDD_BUS_ESDI, 1); break; case CMD_VERIFY: @@ -623,10 +601,11 @@ hdc_callback(void *priv) break; } + hdd_active(drive->hdd_num, 1); + hdd_image_read(drive->hdd_num, addr, 1, (uint8_t *)dev->buffer); - ui_sb_icon_update(SB_HDD|HDD_BUS_ESDI, 1); next_sector(dev); dev->secount = (dev->secount - 1) & 0xff; if (dev->secount) @@ -653,11 +632,12 @@ hdc_callback(void *priv) break; } + hdd_active(drive->hdd_num, 1); + hdd_image_zero(drive->hdd_num, addr, dev->secount); dev->status = STAT_READY|STAT_DSC; irq_raise(dev); - ui_sb_icon_update(SB_HDD|HDD_BUS_ESDI, 1); break; case CMD_DIAGNOSE: @@ -676,9 +656,7 @@ hdc_callback(void *priv) drive->cfg_spt = dev->secount; drive->cfg_hpc = dev->head+1; -#ifdef ENABLE_HDC_LOG - hdc_log("WD1007: parameters: spt=%i hpc=%i\n", drive->cfg_spt,drive->cfg_hpc); -#endif + DEBUG("WD1007: parameters: spt=%i hpc=%i\n", drive->cfg_spt,drive->cfg_hpc); if (! dev->secount) fatal("WD1007: secount=0\n"); dev->status = STAT_READY|STAT_DSC; @@ -717,10 +695,8 @@ hdc_callback(void *priv) break; default: -#ifdef ENABLE_HDC_LOG - hdc_log("WD1007: bad read config %02x\n", + DEBUG("WD1007: bad read config %02x\n", dev->cylinder >> 8); -#endif break; } dev->status = STAT_READY|STAT_DSC; @@ -777,9 +753,7 @@ hdc_callback(void *priv) break; default: -#ifdef ENABLE_HDC_LOG - hdc_log("WD1007: callback on unknown command %02x\n", dev->command); -#endif + DEBUG("WD1007: callback on unknown command %02x\n", dev->command); /*FALLTHROUGH*/ case 0xe8: @@ -789,7 +763,7 @@ hdc_callback(void *priv) break; } - ui_sb_icon_update(SB_HDD|HDD_BUS_ESDI, 0); + hdd_active(drive->hdd_num, 0); } @@ -799,9 +773,7 @@ loadhd(hdc_t *dev, int hdd_num, int d, const wchar_t *fn) drive_t *drive = &dev->drives[hdd_num]; if (! hdd_image_load(d)) { -#ifdef ENABLE_HDC_LOG - hdc_log("WD1007: drive %d not present!\n", d); -#endif + DEBUG("WD1007: drive %d not present!\n", d); drive->present = 0; return; } @@ -817,16 +789,19 @@ loadhd(hdc_t *dev, int hdd_num, int d, const wchar_t *fn) static void * wd1007vse1_init(const device_t *info) { + hdc_t *dev; int c, d; - hdc_t *dev = malloc(sizeof(hdc_t)); + dev = (hdc_t *)mem_alloc(sizeof(hdc_t)); memset(dev, 0x00, sizeof(hdc_t)); c = 0; - for (d=0; d= ESDI_NUM) break; } } @@ -848,8 +823,6 @@ wd1007vse1_init(const device_t *info) timer_add(hdc_callback, &dev->callback, &dev->callback, dev); - ui_sb_icon_update(SB_HDD | HDD_BUS_ESDI, 0); - return(dev); } @@ -869,7 +842,7 @@ wd1007vse1_close(void *priv) free(dev); - ui_sb_icon_update(SB_HDD | HDD_BUS_ESDI, 0); + ui_sb_icon_update(SB_DISK | HDD_BUS_ESDI, 0); } @@ -881,9 +854,9 @@ wd1007vse1_available(void) const device_t esdi_at_wd1007vse1_device = { - "Western Digital WD1007V-SE1 (ESDI)", + "PC/AT ESDI Fixed Disk Adapter", DEVICE_ISA | DEVICE_AT, - 0, + (HDD_BUS_ESDI << 8) | 0, wd1007vse1_init, wd1007vse1_close, NULL, wd1007vse1_available, NULL, NULL, NULL, diff --git a/src/devices/disk/hdc_esdi_mca.c b/src/devices/disk/hdc_esdi_mca.c index f8a7c40..c10c394 100644 --- a/src/devices/disk/hdc_esdi_mca.c +++ b/src/devices/disk/hdc_esdi_mca.c @@ -52,7 +52,7 @@ * however, are auto-configured by the system software as * shown above. * - * Version: @(#)hdc_esdi_mca.c 1.0.11 2018/05/06 + * Version: @(#)hdc_esdi_mca.c 1.0.12 2018/09/22 * * Authors: Fred N. van Kempen, * Sarah Walker, @@ -83,6 +83,7 @@ #include #include #include +#define dbglog hdc_log #include "../../emu.h" #include "../../io.h" #include "../../mem.h" @@ -120,8 +121,6 @@ typedef struct { } drive_t; typedef struct { - uint16_t base; - int8_t irq; int8_t dma; uint32_t bios; @@ -209,6 +208,7 @@ typedef struct { #define CMD_GET_POS_INFO 0x0a #define STATUS_LEN(x) ((x) << 8) +#define STATUS_DEVICE(x) ((x) << 5) #define STATUS_DEVICE_HOST_ADAPTER (7 << 5) @@ -216,14 +216,14 @@ static __inline void set_irq(hdc_t *dev) { if (dev->basic_ctrl & CTRL_IRQ_ENA) - picint(1 << dev->irq); + picint(1 << ESDI_IRQCHAN); } static __inline void clear_irq(hdc_t *dev) { - picintc(1 << dev->irq); + picintc(1 << ESDI_IRQCHAN); } @@ -292,6 +292,24 @@ rba_out_of_range(hdc_t *dev) set_irq(dev); } + +static void +complete_command_status(hdc_t *dev) +{ + dev->status_len = 7; + if (dev->cmd_dev == ATTN_DEVICE_0) + dev->status_data[0] = CMD_READ | STATUS_LEN(7) | STATUS_DEVICE(0); + else + dev->status_data[0] = CMD_READ | STATUS_LEN(7) | STATUS_DEVICE(1); + dev->status_data[1] = 0x0000; /*Error bits*/ + dev->status_data[2] = 0x1900; /*Device status*/ + dev->status_data[3] = 0; /*Number of blocks left to do*/ + dev->status_data[4] = (dev->rba-1) & 0xffff; /*Last RBA processed*/ + dev->status_data[5] = (dev->rba-1) >> 8; + dev->status_data[6] = 0; /*Number of blocks requiring error recovery*/ +} + + #define ESDI_ADAPTER_ONLY() do \ { \ if (dev->cmd_dev != ATTN_HOST_ADAPTER) \ @@ -374,8 +392,9 @@ hdc_callback(void *priv) if (! dev->data_pos) { if (dev->rba >= drive->sectors) fatal("Read past end of drive\n"); + hdd_active(drive->hdd_num, 1); + hdd_image_read(drive->hdd_num, dev->rba, 1, (uint8_t *)dev->data); - ui_sb_icon_update(SB_HDD | HDD_BUS_ESDI, 1); } while (dev->data_pos < 256) { @@ -400,7 +419,8 @@ hdc_callback(void *priv) break; case 2: - dev->status = STATUS_IRQ; + complete_command_status(dev); + dev->status = STATUS_IRQ | STATUS_STATUS_OUT_FULL; dev->irq_status = dev->cmd_dev | IRQ_CMD_COMPLETE_SUCCESS; dev->irq_in_progress = 1; set_irq(dev); @@ -458,14 +478,16 @@ hdc_callback(void *priv) if (dev->rba >= drive->sectors) fatal("Write past end of drive\n"); + + hdd_active(drive->hdd_num, + dev->cmd_dev == ATTN_DEVICE_0 ? 0 : 1); + hdd_image_write(drive->hdd_num, dev->rba, 1, (uint8_t *)dev->data); dev->rba++; dev->sector_pos++; - ui_sb_icon_update(SB_HDD | HDD_BUS_ESDI, 1); dev->data_pos = 0; } - ui_sb_icon_update(SB_HDD | HDD_BUS_ESDI, 0); dev->status = STATUS_CMD_IN_PROGRESS; dev->cmd_state = 2; @@ -473,7 +495,8 @@ hdc_callback(void *priv) break; case 2: - dev->status = STATUS_IRQ; + complete_command_status(dev); + dev->status = STATUS_IRQ | STATUS_STATUS_OUT_FULL; dev->irq_status = dev->cmd_dev | IRQ_CMD_COMPLETE_SUCCESS; dev->irq_in_progress = 1; set_irq(dev); @@ -494,7 +517,9 @@ hdc_callback(void *priv) return; } - dev->status = STATUS_IRQ; + dev->rba += dev->sector_count; + complete_command_status(dev); + dev->status = STATUS_IRQ | STATUS_STATUS_OUT_FULL; dev->irq_status = dev->cmd_dev | IRQ_CMD_COMPLETE_SUCCESS; dev->irq_in_progress = 1; set_irq(dev); @@ -508,7 +533,8 @@ hdc_callback(void *priv) return; } - dev->status = STATUS_IRQ; + complete_command_status(dev); + dev->status = STATUS_IRQ | STATUS_STATUS_OUT_FULL; dev->irq_status = dev->cmd_dev | IRQ_CMD_COMPLETE_SUCCESS; dev->irq_in_progress = 1; set_irq(dev); @@ -522,8 +548,6 @@ hdc_callback(void *priv) return; } - if (dev->status_pos) - fatal("Status send in progress\n"); if ((dev->status & STATUS_IRQ) || dev->irq_in_progress) fatal("IRQ in progress %02x %i\n", dev->status, dev->irq_in_progress); @@ -552,8 +576,6 @@ hdc_callback(void *priv) return; } - if (dev->status_pos) - fatal("Status send in progress\n"); if ((dev->status & STATUS_IRQ) || dev->irq_in_progress) fatal("IRQ in progress %02x %i\n", dev->status, dev->irq_in_progress); @@ -565,13 +587,11 @@ hdc_callback(void *priv) dev->status_data[4] = drive->tracks; dev->status_data[5] = drive->hpc | (drive->spt << 16); -#if 0 - hdc_log("CMD_GET_DEV_CONFIG %i %04x %04x %04x %04x %04x %04x\n", - drive->sectors, - dev->status_data[0], dev->status_data[1], - dev->status_data[2], dev->status_data[3], - dev->status_data[4], dev->status_data[5]); -#endif + DEBUG("CMD_GET_DEV_CONFIG %i %04x %04x %04x %04x %04x %04x\n", + drive->sectors, + dev->status_data[0], dev->status_data[1], + dev->status_data[2], dev->status_data[3], + dev->status_data[4], dev->status_data[5]); dev->status = STATUS_IRQ | STATUS_STATUS_OUT_FULL; dev->irq_status = dev->cmd_dev | IRQ_CMD_COMPLETE_SUCCESS; dev->irq_in_progress = 1; @@ -580,8 +600,7 @@ hdc_callback(void *priv) case CMD_GET_POS_INFO: ESDI_ADAPTER_ONLY(); - if (dev->status_pos) - fatal("Status send in progress\n"); + if ((dev->status & STATUS_IRQ) || dev->irq_in_progress) fatal("IRQ in progress %02x %i\n", dev->status, dev->irq_in_progress); @@ -590,8 +609,8 @@ hdc_callback(void *priv) dev->status_data[1] = 0xffdd; /*MCA ID*/ dev->status_data[2] = dev->pos_regs[3] | (dev->pos_regs[2] << 8); - dev->status_data[3] = 0xffff; - dev->status_data[4] = 0xffff; + dev->status_data[3] = 0xff; + dev->status_data[4] = 0xff; dev->status = STATUS_IRQ | STATUS_STATUS_OUT_FULL; dev->irq_status = IRQ_HOST_ADAPTER | IRQ_CMD_COMPLETE_SUCCESS; @@ -711,8 +730,6 @@ hdc_callback(void *priv) case 0x12: ESDI_ADAPTER_ONLY(); - if (dev->status_pos) - fatal("Status send in progress\n"); if ((dev->status & STATUS_IRQ) || dev->irq_in_progress) fatal("IRQ in progress %02x %i\n", dev->status, dev->irq_in_progress); @@ -727,7 +744,7 @@ hdc_callback(void *priv) break; default: - hdc_log("BAD COMMAND %02x %i\n", dev->command, dev->cmd_dev); + DEBUG("BAD COMMAND %02x %i\n", dev->command, dev->cmd_dev); } } @@ -738,7 +755,7 @@ hdc_read(uint16_t port, void *priv) hdc_t *dev = (hdc_t *)priv; uint8_t ret = 0xff; - switch (port-dev->base) { + switch (port & 7) { case 2: /*Basic status register*/ ret = dev->status; break; @@ -749,9 +766,11 @@ hdc_read(uint16_t port, void *priv) break; default: - hdc_log("esdi_read port=%04x\n", port); + DEBUG("esdi_read port=%04x\n", port); } + DBGLOG(2, "ESDI: rd(%04x) = %02x\n", port & 7, ret); + return(ret); } @@ -761,11 +780,10 @@ hdc_write(uint16_t port, uint8_t val, void *priv) { hdc_t *dev = (hdc_t *)priv; -#ifdef ENABLE_HDC_LOG - hdc_log("ESDI: wr(%04x, %02x)\n", port-dev->base, val); -#endif - switch (port-dev->base) { - case 2: /*Basic control register*/ + DBGLOG(2, "ESDI: wr(%04x, %02x)\n", port & 7, val); + + switch (port & 7) { + case 2: /*Basic control register*/ if ((dev->basic_ctrl & CTRL_RESET) && !(val & CTRL_RESET)) { dev->in_reset = 1; dev->callback = ESDI_TIME * 50LL; @@ -774,10 +792,10 @@ hdc_write(uint16_t port, uint8_t val, void *priv) dev->basic_ctrl = val; if (! (dev->basic_ctrl & CTRL_IRQ_ENA)) - picintc(1 << dev->irq); + picintc(1 << 14); break; - case 3: /*Attention register*/ + case 3: /*Attention register*/ switch (val & ATTN_DEVICE_SEL) { case ATTN_HOST_ADAPTER: switch (val & ATTN_REQ_MASK) { @@ -788,6 +806,7 @@ hdc_write(uint16_t port, uint8_t val, void *priv) dev->cmd_dev = ATTN_HOST_ADAPTER; dev->status |= STATUS_BUSY; dev->cmd_pos = 0; + dev->status_pos = 0; break; case ATTN_EOI: @@ -803,7 +822,7 @@ hdc_write(uint16_t port, uint8_t val, void *priv) break; default: - hdc_log("Bad attention request %02x\n", val); + DEBUG("Bad attention request %02x\n", val); } break; @@ -816,6 +835,7 @@ hdc_write(uint16_t port, uint8_t val, void *priv) dev->cmd_dev = ATTN_DEVICE_0; dev->status |= STATUS_BUSY; dev->cmd_pos = 0; + dev->status_pos = 0; break; case ATTN_EOI: @@ -825,7 +845,7 @@ hdc_write(uint16_t port, uint8_t val, void *priv) break; default: - hdc_log("Bad attention request %02x\n", val); + DEBUG("Bad attention request %02x\n", val); } break; @@ -847,17 +867,17 @@ hdc_write(uint16_t port, uint8_t val, void *priv) break; default: - hdc_log("Bad attention request %02x\n", val); + DEBUG("Bad attention request %02x\n", val); } break; default: - hdc_log("Attention to unknown device %02x\n", val); + DEBUG("Attention to unknown device %02x\n", val); } break; default: - hdc_log("esdi_write port=%04x val=%02x\n", port, val); + DEBUG("esdi_write port=%04x val=%02x\n", port, val); } } @@ -868,8 +888,8 @@ hdc_readw(uint16_t port, void *priv) hdc_t *dev = (hdc_t *)priv; uint16_t ret = 0xffff; - switch (port-dev->base) { - case 0: /*Status Interface Register*/ + switch (port & 7) { + case 0: /*Status Interface Register*/ if (dev->status_pos >= dev->status_len) return(0); ret = dev->status_data[dev->status_pos++]; @@ -880,7 +900,7 @@ hdc_readw(uint16_t port, void *priv) break; default: - hdc_log("esdi_readw port=%04x\n", port); + DEBUG("esdi_readw port=%04x\n", port); } return(ret); @@ -892,11 +912,10 @@ hdc_writew(uint16_t port, uint16_t val, void *priv) { hdc_t *dev = (hdc_t *)priv; -#ifdef ENABLE_HDC_LOG - hdc_log("ESDI: wrw(%04x, %04x)\n", port-dev->base, val); -#endif - switch (port-dev->base) { - case 0: /*Command Interface Register*/ + DBGLOG(2, "ESDI: wrw(%04x, %04x)\n", port & 7, val); + + switch (port & 7) { + case 0: /*Command Interface Register*/ if (dev->cmd_pos >= 4) fatal("CIR pos 4\n"); dev->cmd_data[dev->cmd_pos++] = val; @@ -916,7 +935,7 @@ hdc_writew(uint16_t port, uint16_t val, void *priv) break; default: - hdc_log("esdi_writew port=%04x val=%04x\n", port, val); + DEBUG("esdi_writew port=%04x val=%04x\n", port, val); } } @@ -925,11 +944,11 @@ static uint8_t hdc_mca_read(int port, void *priv) { hdc_t *dev = (hdc_t *)priv; + uint8_t ret = dev->pos_regs[port & 7]; -#ifdef ENABLE_HDC_LOG - hdc_log("ESDI: mcard(%04x)\n", port); -#endif - return(dev->pos_regs[port & 7]); + DBGLOG(1, "ESDI: mcard(%04x) = %02x\n", port, ret); + + return(ret); } @@ -938,43 +957,18 @@ hdc_mca_write(int port, uint8_t val, void *priv) { hdc_t *dev = (hdc_t *)priv; -#ifdef ENABLE_HDC_LOG - hdc_log("ESDI: mcawr(%04x, %02x) pos[2]=%02x pos[3]=%02x\n", + DBGLOG(1, "ESDI: mcawr(%04x, %02x) pos[2]=%02x pos[3]=%02x\n", port, val, dev->pos_regs[2], dev->pos_regs[3]); -#endif - if (port < 0x102) return; - /* - * The PS/2 Model 80 BIOS always enables a card if it finds one, - * even if no resources were assigned yet (because we only added - * the card, but have not run AutoConfig yet...) - * - * So, remove current address, if any. - * - * Note by Kotori: Moved this to the beginning of esdi_mca_write, - * so the *old* base is removed rather than the - * new base. - */ - io_removehandler(dev->base, 8, - hdc_read, hdc_readw, NULL, - hdc_write, hdc_writew, NULL, dev); - mem_mapping_disable(&dev->bios_rom.mapping); + if (port < 0x102) return; /* Save the new value. */ dev->pos_regs[port & 7] = val; - /* Extract the new I/O base. */ - switch(dev->pos_regs[2] & 0x02) { - case 0x00: /* PRIMARY [0]=XXxx xx0X 0x3510 */ - dev->base = ESDI_IOADDR_PRI; - break; + io_removehandler(ESDI_IOADDR_PRI, 8, + hdc_read,hdc_readw,NULL, hdc_write,hdc_writew,NULL, dev); + mem_map_disable(&dev->bios_rom.mapping); - case 0x02: /* SECONDARY [0]=XXxx xx1X 0x3518 */ - dev->base = ESDI_IOADDR_SEC; - break; - } - - /* Extract the new DMA channel. */ switch(dev->pos_regs[2] & 0x3c) { case 0x14: /* DMA 5 [0]=XX01 01XX */ dev->dma = 5; @@ -992,11 +986,11 @@ hdc_mca_write(int port, uint8_t val, void *priv) dev->dma = 0; break; - case 0x01: /* DMA 1 [0]=XX00 01XX */ + case 0x04: /* DMA 1 [0]=XX00 01XX */ dev->dma = 1; break; - case 0x04: /* DMA 3 [0]=XX00 11XX */ + case 0x0c: /* DMA 3 [0]=XX00 11XX */ dev->dma = 3; break; @@ -1005,60 +999,22 @@ hdc_mca_write(int port, uint8_t val, void *priv) break; } - /* Extract the new BIOS address. */ - if (! (dev->pos_regs[3] & 0x08)) switch(dev->pos_regs[3] & 0x0f) { - case 0: /* ROM C000 [1]=XXXX 0000 */ - dev->bios = 0xC0000; - break; - - case 1: /* ROM C400 [1]=XXXX 0001 */ - dev->bios = 0xC4000; - break; - - case 2: /* ROM C800 [1]=XXXX 0010 */ - dev->bios = 0xC8000; - break; - - case 3: /* ROM CC00 [1]=XXXX 0011 */ - dev->bios = 0xCC000; - break; - - case 4: /* ROM D000 [1]=XXXX 0100 */ - dev->bios = 0xD0000; - break; - - case 5: /* ROM D400 [1]=XXXX 0101 */ - dev->bios = 0xD4000; - break; - - case 6: /* ROM D800 [1]=XXXX 0110 */ - dev->bios = 0xD8000; - break; - - case 7: /* ROM DC00 [1]=XXXX 0111 */ - dev->bios = 0xDC000; - break; - } else { - /* BIOS ROM disabled. */ - dev->bios = 0x000000; - } - if (dev->pos_regs[2] & 0x01) { /* Card enabled; register (new) I/O handler. */ - io_sethandler(dev->base, 8, + io_sethandler(ESDI_IOADDR_PRI, 8, hdc_read, hdc_readw, NULL, hdc_write, hdc_writew, NULL, dev); /* Enable or disable the BIOS ROM. */ - if (dev->bios != 0x000000) { - mem_mapping_enable(&dev->bios_rom.mapping); - mem_mapping_set_addr(&dev->bios_rom.mapping, - dev->bios, 0x4000); + if (!(dev->pos_regs[3] & 0x08)) { + dev->bios = ((dev->pos_regs[3] & 7) * 0x4000) + 0xc0000; + mem_map_enable(&dev->bios_rom.mapping); + mem_map_set_addr(&dev->bios_rom.mapping, dev->bios, 0x4000); } /* Say hello. */ - hdc_log("ESDI: I/O=%04x, IRQ=%d, DMA=%d, BIOS @%05X\n", - dev->base, dev->irq, dev->dma, dev->bios); + INFO("ESDI: I/O=%04x, IRQ=%d, DMA=%d, BIOS @%05X\n", + ESDI_IOADDR_PRI, 14, dev->dma, dev->bios); } } @@ -1070,28 +1026,27 @@ esdi_init(const device_t *info) hdc_t *dev; int c, i; - dev = malloc(sizeof(hdc_t)); - if (dev == NULL) return(NULL); + dev = (hdc_t *)mem_alloc(sizeof(hdc_t)); memset(dev, 0x00, sizeof(hdc_t)); /* Mark as unconfigured. */ dev->irq_status = 0xff; - /* This is hardwired. */ - dev->irq = ESDI_IRQCHAN; - rom_init_interleaved(&dev->bios_rom, BIOS_FILE_H, BIOS_FILE_L, 0xc8000, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL); - mem_mapping_disable(&dev->bios_rom.mapping); + mem_map_disable(&dev->bios_rom.mapping); dev->drives[0].present = dev->drives[1].present = 0; - for (c=0,i=0; idrives[hdd[i].id.esdi_channel]; + hdd_active(drive->hdd_num, 0); + /* Try to load an image for the drive. */ if (! hdd_image_load(i)) { /* Nope. */ @@ -1103,7 +1058,7 @@ esdi_init(const device_t *info) drive->spt = (uint8_t)hdd[i].spt; drive->hpc = (uint8_t)hdd[i].hpc; drive->tracks = (uint16_t)hdd[i].tracks; - drive->sectors = (uint32_t)(hdd[i].spt*hdd[i].hpc*hdd[i].tracks); + drive->sectors = hdd_image_get_last_sector(i) + 1; drive->hdd_num = i; /* Mark drive as present. */ @@ -1159,8 +1114,9 @@ esdi_available(void) const device_t esdi_ps2_device = { - "IBM ESDI Fixed Disk Adapter (MCA)", - DEVICE_MCA, 0, + "IBM PS/2 ESDI Fixed Disk Adapter", + DEVICE_MCA, + (HDD_BUS_ESDI << 8) | 0, esdi_init, esdi_close, NULL, esdi_available, NULL, NULL, NULL, diff --git a/src/devices/disk/hdc_ide.h b/src/devices/disk/hdc_ide.h index ba62cc4..f0f2574 100644 --- a/src/devices/disk/hdc_ide.h +++ b/src/devices/disk/hdc_ide.h @@ -8,7 +8,7 @@ * * Definitions for the IDE module. * - * Version: @(#)hdc_ide.h 1.0.8 2018/04/23 + * Version: @(#)hdc_ide.h 1.0.10 2018/09/28 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -41,66 +41,52 @@ typedef struct { - int8_t type; - int8_t board; - uint8_t atastat; - uint8_t error; - int secount, - sector, - cylinder, - head, - drive, - cylprecomp; - uint8_t command; - uint8_t fdisk; - int pos; - int packlen; - uint8_t spt, - hpc; - int t_spt, - t_hpc; - int tracks; - int packetstatus; - uint8_t asc; - int reset; + uint8_t atastat, error, + command, fdisk; + + int type, board, + irqstat, service, + blocksize, blockcount, + hdd_num, channel, + pos, sector_pos, + skip512, reset, + mdma_mode, do_initial_read; + + uint32_t secount, sector, + cylinder, head, + drive, cylprecomp, + tracks, spt, hpc, + cfg_spt, cfg_hpc, + lba, lba_addr; + uint16_t *buffer; - int irqstat; - int service; - int lba; - int channel; - uint32_t lba_addr; - int skip512; - int blocksize, - blockcount; - uint16_t dma_identify_data[3]; - int hdi, - base; - int hdd_num; - uint8_t specify_success; - int mdma_mode; uint8_t *sector_buffer; - int do_initial_read; - int sector_pos; -} IDE; +} ide_t; extern int ideboard; -extern int ide_enable[5]; -extern int ide_irq[5]; -extern IDE ide_drives[IDE_NUM]; +extern int ide_ter_enabled, ide_qua_enabled; +extern ide_t *ide_drives[IDE_NUM+XTIDE_NUM]; extern int64_t idecallback[5]; -extern void ide_irq_raise(IDE *ide); -extern void ide_irq_lower(IDE *ide); +extern void ide_irq_raise(ide_t *); +extern void ide_irq_lower(ide_t *); -extern void writeide(int ide_board, uint16_t addr, uint8_t val); -extern void writeidew(int ide_board, uint16_t val); -extern uint8_t readide(int ide_board, uint16_t addr); -extern uint16_t readidew(int ide_board); -extern void callbackide(int ide_board); +extern void *ide_xtide_init(void); +extern void ide_xtide_close(void); + +extern void ide_writew(uint16_t addr, uint16_t val, void *priv); +extern void ide_write_devctl(uint16_t addr, uint8_t val, void *priv); +extern void ide_writeb(uint16_t addr, uint8_t val, void *priv); +extern uint8_t ide_readb(uint16_t addr, void *priv); +extern uint8_t ide_read_alt_status(uint16_t addr, void *priv); +extern uint16_t ide_readw(uint16_t addr, void *priv); +extern void ide_set_bus_master(int (*read)(int channel, uint8_t *data, int transfer_length, void *priv), + int (*write)(int channel, uint8_t *data, int transfer_length, void *priv), + void (*set_irq)(int channel, void *priv), + void *priv0, void *priv1); -extern void ide_set_bus_master(int (*read)(int channel, uint8_t *data, int transfer_length), int (*write)(int channel, uint8_t *data, int transfer_length), void (*set_irq)(int channel)); extern void win_cdrom_eject(uint8_t id); extern void win_cdrom_reload(uint8_t id); @@ -108,36 +94,22 @@ extern void win_cdrom_reload(uint8_t id); extern void ide_set_base(int controller, uint16_t port); extern void ide_set_side(int controller, uint16_t port); -extern void ide_init_first(void); - -extern void ide_reset(void); -extern void ide_reset_hard(void); - -extern void ide_set_all_signatures(void); - -extern void ide_xtide_init(void); - extern void ide_pri_enable(void); -extern void ide_pri_enable_ex(void); extern void ide_pri_disable(void); extern void ide_sec_enable(void); extern void ide_sec_disable(void); -extern void ide_ter_enable(void); -extern void ide_ter_disable(void); -extern void ide_ter_init(void); -extern void ide_qua_enable(void); -extern void ide_qua_disable(void); -extern void ide_qua_init(void); extern void ide_set_callback(uint8_t channel, int64_t callback); extern void secondary_ide_check(void); extern void ide_padstr8(uint8_t *buf, int buf_size, const char *src); -extern void ide_destroy_buffers(void); -extern int (*ide_bus_master_read)(int channel, uint8_t *data, int transfer_length); -extern int (*ide_bus_master_write)(int channel, uint8_t *data, int transfer_length); -extern void (*ide_bus_master_set_irq)(int channel); +extern int (*ide_bus_master_read)(int channel, uint8_t *data, int transfer_length, void *priv); +extern int (*ide_bus_master_write)(int channel, uint8_t *data, int transfer_length, void *priv); +extern void (*ide_bus_master_set_irq)(int channel, void *priv); +extern void *ide_bus_master_priv[2]; + +extern void ide_enable_pio_override(void); #endif /*EMU_IDE_H*/ diff --git a/src/devices/disk/hdc_ide_ata.c b/src/devices/disk/hdc_ide_ata.c index fd9b35e..e9ab20d 100644 --- a/src/devices/disk/hdc_ide_ata.c +++ b/src/devices/disk/hdc_ide_ata.c @@ -14,7 +14,7 @@ * Devices currently implemented are hard disk, CD-ROM and * ZIP IDE/ATAPI devices. * - * Version: @(#)hdc_ide_ata.c 1.0.22 2018/05/06 + * Version: @(#)hdc_ide_ata.c 1.0.23 2018/10/05 * * Authors: Miran Grca, * Sarah Walker, @@ -50,48 +50,84 @@ #include #include #include +#define dbglog hdc_log #include "../../emu.h" #include "../../version.h" #include "../../cpu/cpu.h" #include "../../machines/machine.h" #include "../../io.h" +#include "../../mem.h" +#include "../../rom.h" #include "../../timer.h" #include "../../device.h" #include "../../ui/ui.h" #include "../../plat.h" #include "../system/pic.h" #include "../system/pci.h" +#include "../scsi/scsi_device.h" #include "../cdrom/cdrom.h" -#include "../scsi/scsi.h" #include "hdc.h" #include "hdc_ide.h" #include "hdd.h" #include "zip.h" +enum { + IDE_NONE = 0, +#if 0 +/* In the future, there's going to be just the IDE_ATAPI type, + leaving it to the common ATAPI/SCSI device handler to know + what type the device is. */ + IDE_DISK, + IDE_ATAPI +#else + IDE_HDD, + IDE_CDROM, + IDE_ZIP +#endif +}; + + +#define IDE_PCI (PCI && pio_override) +#define IDE_TIME (20LL * TIMER_USEC) / 3LL + + /* Bits of 'atastat' */ -#define ERR_STAT 0x01 +#define ERR_STAT 0x01 /* Error */ +#define IDX_STAT 0x02 /* Index */ +#define CORR_STAT 0x04 /* Corrected data */ #define DRQ_STAT 0x08 /* Data request */ -#define DSC_STAT 0x10 -#define SERVICE_STAT 0x10 -#define READY_STAT 0x40 -#define BUSY_STAT 0x80 +#define DSC_STAT 0x10 /* Drive seek complete */ +#define SERVICE_STAT 0x10 /* ATAPI service */ +#define DWF_STAT 0x20 /* Drive write fault */ +#define DRDY_STAT 0x40 /* Ready */ +#define BSY_STAT 0x80 /* Busy */ /* Bits of 'error' */ +#define AMNF_ERR 0x01 /* Address mark not found */ +#define TK0NF_ERR 0x02 /* Track 0 not found */ #define ABRT_ERR 0x04 /* Command aborted */ #define MCR_ERR 0x08 /* Media change request */ +#define IDNF_ERR 0x10 /* Sector ID not found */ +#define MC_ERR 0x20 /* Media change */ +#define UNC_ERR 0x40 /* Uncorrectable data error */ +#define BBK_ERR 0x80 /* Bad block mark detected */ + /* ATA Commands */ #define WIN_NOP 0x00 #define WIN_SRST 0x08 /* ATAPI Device Reset */ #define WIN_RECAL 0x10 -#define WIN_RESTORE WIN_RECAL #define WIN_READ 0x20 /* 28-Bit Read */ -#define WIN_READ_NORETRY 0x21 /* 28-Bit Read - no retry*/ +#define WIN_READ_NORETRY 0x21 /* 28-Bit Read - no retry */ #define WIN_WRITE 0x30 /* 28-Bit Write */ -#define WIN_WRITE_NORETRY 0x31 /* 28-Bit Write */ +#define WIN_WRITE_NORETRY 0x31 /* 28-Bit Write - no retry */ #define WIN_VERIFY 0x40 /* 28-Bit Verify */ -#define WIN_VERIFY_ONCE 0x41 /* Added by OBattler - deprected older ATA command, according to the specification I found, it is identical to 0x40 */ +#define WIN_VERIFY_ONCE 0x41 /* Added by OBattler - deprected + * older ATA command, according + * to the specification I found, + * it is identical to 0x40 + */ #define WIN_FORMAT 0x50 #define WIN_SEEK 0x70 #define WIN_DRIVE_DIAGNOSTICS 0x90 /* Execute Drive Diagnostics */ @@ -123,147 +159,224 @@ #define FEATURE_DISABLE_IRQ_SERVICE 0xde -enum +typedef struct { + int bit32, + cur_dev, + irq; + + int64_t callback; +} ide_board_t; + + +static ide_board_t *ide_boards[4]; +static int pio_override = 0; +static uint16_t ide_base_main[4] = { 0x1f0, 0x170, 0x168, 0x1e8 }; +static uint16_t ide_side_main[4] = { 0x3f6, 0x376, 0x36e, 0x3ee }; + + +ide_t *ide_drives[IDE_NUM+XTIDE_NUM]; +int (*ide_bus_master_read)(int channel, uint8_t *data, int transfer_length, void *priv); +int (*ide_bus_master_write)(int channel, uint8_t *data, int transfer_length, void *priv); +void (*ide_bus_master_set_irq)(int channel, void *priv); +void *ide_bus_master_priv[2]; +int ide_inited = 0; +int ide_ter_enabled = 0, ide_qua_enabled = 0; + + +static void ide_callback(void *priv); + + +uint8_t +getstat(ide_t *ide) { - IDE_NONE = 0, - IDE_HDD, - IDE_CDROM, - IDE_ZIP -}; - - -IDE ide_drives[IDE_NUM]; -IDE *ext_ide; -int (*ide_bus_master_read)(int channel, uint8_t *data, int transfer_length); -int (*ide_bus_master_write)(int channel, uint8_t *data, int transfer_length); -void (*ide_bus_master_set_irq)(int channel); -int64_t idecallback[5] = {0LL, 0LL, 0LL, 0LL, 0LL}; -int cur_ide[5]; -int ide_init_ch[2] = {0, 0}; - - -uint8_t getstat(IDE *ide) { return ide->atastat; } - - -int ide_drive_is_cdrom(IDE *ide) -{ - if (ide->channel >= 8) - { - return 0; - } - - if (atapi_cdrom_drives[ide->channel] >= CDROM_NUM) - { - return 0; - } - else - { - if ((cdrom_drives[atapi_cdrom_drives[ide->channel]].bus_type == CDROM_BUS_ATAPI_PIO_ONLY) || (cdrom_drives[atapi_cdrom_drives[ide->channel]].bus_type == CDROM_BUS_ATAPI_PIO_AND_DMA)) - { - return 1; - } - else - { - return 0; - } - } + return ide->atastat; } -int ide_drive_is_zip(IDE *ide) -{ - if (ide->channel >= 8) - { - return 0; - } - if (atapi_zip_drives[ide->channel] >= ZIP_NUM) - { - return 0; - } - else - { - if ((zip_drives[atapi_zip_drives[ide->channel]].bus_type == ZIP_BUS_ATAPI_PIO_ONLY) || (zip_drives[atapi_zip_drives[ide->channel]].bus_type == ZIP_BUS_ATAPI_PIO_AND_DMA)) - { - return 1; +int64_t +ide_get_period(ide_t *ide, int size) +{ + double period = 10.0 / 3.0; + + switch(ide->mdma_mode & 0x300) { + case 0x000: /* PIO */ + switch(ide->mdma_mode & 0xff) { + case 0: + period = 10.0 / 3.0; + break; + case 1: + period = (period * 600.0) / 383.0; + break; + case 2: + period = 25.0 / 3.0; + break; + case 3: + period = 100.0 / 9.0; + break; + case 4: + period = 50.0 / 3.0; + break; } - else - { - return 0; + break; + + case 0x100: /* Single Word DMA */ + switch(ide->mdma_mode & 0xff) { + case 0: + period = 25.0 / 12.0; + break; + case 1: + period = 25.0 / 6.0; + break; + case 2: + period = 25.0 / 3.0; + break; } - } + break; + + case 0x200: /* Multiword DMA */ + switch(ide->mdma_mode & 0xff) { + case 0: + period = 25.0 / 6.0; + break; + case 1: + period = 40.0 / 3.0; + break; + case 2: + period = 50.0 / 3.0; + break; + } + break; + + case 0x300: /* Ultra DMA */ + switch(ide->mdma_mode & 0xff) { + case 0: + period = 50.0 / 3.0; + break; + case 1: + period = 25.0; + break; + case 2: + period = 100.0 / 3.0; + break; + case 3: + period = 400.0 / 9.0; + break; + case 4: + period = 200.0 / 3.0; + break; + case 5: + period = 100.0; + break; + } + break; + } + period *= 1048576.0; /* period * MB */ + period = 1000000.0 / period; + period *= (double) TIMER_USEC; + period *= (double) size; + return (int64_t) period; } -int ide_enable[5] = { 1, 1, 0, 0, 1 }; -int ide_irq[5] = { 14, 15, 10, 11, 0 }; -void ide_irq_raise(IDE *ide) +#if 0 +int64_t +ide_get_seek_time(ide_t *ide, uint32_t new_pos) { - /* hdc_log("Attempting to raise IRQ %i (board %i)\n", ide_irq[ide->board], ide->board); */ - - if ((ide->board > 3) || ide->irqstat) - { - ide->irqstat=1; - ide->service=1; - - return; - } - -#ifdef ENABLE_HDC_LOG - hdc_log("Raising IRQ %i (board %i)\n", ide_irq[ide->board], ide->board); -#endif - - if (!(ide->fdisk&2)) - { - if (pci_use_mirq(0) && (ide->board == 1)) - { - pci_set_mirq(0); - } - else - { - picint(1 << ide_irq[ide->board]); - } - - if (ide->board < 2) - { - if (ide_bus_master_set_irq) - { - ide_bus_master_set_irq(ide->board | 0x40); - } - } - } - - ide->irqstat=1; - ide->service=1; + double dusec, time; + uint32_t pos = hdd_image_get_pos(ide->hdd_num); + uint32_t t, nt; + t = pos / ide->spt; + nt = new_pos / ide->spt; + dusec = (double) TIMER_USEC; + time = (1000000.0 / 2800.0) * dusec; /* Revolution (1/2800 s). */ + if ((t % ide->hpc) != (pos % ide->hpc)) /* Head change. */ + time += (dusec / 250.0); /* 4ns */ + t /= ide->hpc; + nt /= ide->hpc; + if (t != nt) { + t = ABS(t - nt); + time += ((40000.0 * dusec) / ((double) ide->tracks)) * ((double) t); + } + return (int64_t) time; } - -void ide_irq_lower(IDE *ide) -{ - if ((ide->board > 3) || !(ide->irqstat)) - { - ide->irqstat=0; - return; - } - -#ifdef ENABLE_HDC_LOG - hdc_log("Lowering IRQ %i (board %i)\n", ide_irq[ide->board], ide->board); #endif - if (pci_use_mirq(0) && (ide->board == 1)) - { - pci_clear_mirq(0); - } - else - { - picintc(1 << ide_irq[ide->board]); - } - if (ide_bus_master_set_irq) - { - ide_bus_master_set_irq(ide->board); - } - ide->irqstat=0; +int +ide_drive_is_cdrom(ide_t *ide) +{ + int ch = ide->channel; + + if (ch >= 8) + return 0; + + if (atapi_cdrom_drives[ch] >= CDROM_NUM) + return 0; + + if (cdrom_drives[atapi_cdrom_drives[ch]].bus_type == CDROM_BUS_ATAPI) + return 1; + + return 0; } + +int +ide_drive_is_zip(ide_t *ide) +{ + int ch = ide->channel; + + if (ch >= 8) + return 0; + + if (atapi_zip_drives[ch] >= ZIP_NUM) + return 0; + + if (zip_drives[atapi_zip_drives[ch]].bus_type == ZIP_BUS_ATAPI) + return 1; + + return 0; +} + + +void +ide_irq_raise(ide_t *ide) +{ + if (!ide_boards[ide->board]) + return; + + DBGLOG(1, "Raising IRQ %i (board %i)\n", ide_boards[ide->board]->irq, ide->board); + + if (!(ide->fdisk & 0x02) && (ide_boards[ide->board]->irq != -1)) { + if ((ide->board < 2) && ide_bus_master_set_irq) + ide_bus_master_set_irq(ide->board | 0x40, ide_bus_master_priv[ide->board]); + else + picint(1 << ide_boards[ide->board]->irq); + } + + ide->irqstat=1; + ide->service=1; +} + + +void +ide_irq_lower(ide_t *ide) +{ + if (!ide_boards[ide->board]) + return; + + DBGLOG(1, "Lowering IRQ %i (board %i)\n", ide_boards[ide->board]->irq, ide->board); + + if ((ide_boards[ide->board]->irq != -1) && ide->irqstat) { + if ((ide->board < 2) && ide_bus_master_set_irq) + ide_bus_master_set_irq(ide->board, ide_bus_master_priv[ide->board]); + else + picintc(1 << ide_boards[ide->board]->irq); + } + + ide->irqstat=0; +} + + /** * Copy a string into a buffer, padding with spaces, and placing characters as * if they were packed into 16-bit values, stored little-endian. @@ -276,22 +389,19 @@ void ide_irq_lower(IDE *ide) static void ide_padstr(char *str, const char *src, int len) { - int i, v; + char v; + int i; - for (i = 0; i < len; i++) - { - if (*src != '\0') - { - v = *src++; - } - else - { - v = ' '; - } - str[i ^ 1] = v; - } + for (i = 0; i < len; i++) { + if (*src != '\0') + v = *src++; + else + v = ' '; + str[i ^ 1] = v; + } } + /** * Copy a string into a buffer, padding with spaces. Does not add string * terminator. @@ -301,1056 +411,1094 @@ ide_padstr(char *str, const char *src, int len) * this length will be padded with spaces. * @param src Source string */ -void ide_padstr8(uint8_t *buf, int buf_size, const char *src) +void +ide_padstr8(uint8_t *buf, int buf_size, const char *src) { - int i; + int i; - for (i = 0; i < buf_size; i++) - { - if (*src != '\0') - { - buf[i] = *src++; - } - else - { - buf[i] = ' '; - } - } + for (i = 0; i < buf_size; i++) { + if (*src != '\0') + buf[i] = (uint8_t)*src++; + else + buf[i] = (uint8_t)' '; + } } + +enum { + TYPE_PIO = 0, + TYPE_SDMA, + TYPE_MDMA, + TYPE_UDMA +}; + + +/* + * Type: + * 0 = PIO, + * 1 = SDMA, + * 2 = MDMA, + * 3 = UDMA + * + * Return: + * -1 = Not supported, + * Anything else = maximum mode + * + * This will eventually be hookable. + */ +static int +ide_get_max(ide_t *ide, int type) +{ + switch(type) { + case TYPE_PIO: /* PIO */ + if (!IDE_PCI || (ide->board >= 2)) + return 0; /* Maximum PIO 0 for legacy PIO-only drive. */ + if (ide_drive_is_zip(ide)) + return 3; + return 4; + + case TYPE_SDMA: /* SDMA */ + if (!IDE_PCI || (ide->board >= 2) || ide_drive_is_zip(ide)) + return -1; + return 2; + + case TYPE_MDMA: /* MDMA */ + if (!IDE_PCI || (ide->board >= 2)) + return -1; + if (ide_drive_is_zip(ide)) + return 1; + return 2; + + case TYPE_UDMA: /* UDMA */ + if (!IDE_PCI || (ide->board >= 2)) + return -1; + return 2; + + default: + fatal("Unknown transfer type: %i\n", type); + return -1; + } +} + + +enum { + TIMINGS_DMA = 0, + TIMINGS_PIO, + TIMINGS_PIO_FC +}; + + +/* + * Return: + * 0 = Not supported, + * Anything else = timings + * + * This will eventually be hookable. + */ +static int +ide_get_timings(ide_t *ide, int type) +{ + switch(type) { + case TIMINGS_DMA: + if (!IDE_PCI || (ide->board >= 2)) + return 0; + if (ide_drive_is_zip(ide)) + return 0x96; + return 120; + + case TIMINGS_PIO: + if (!IDE_PCI || (ide->board >= 2)) + return 0; + if (ide_drive_is_zip(ide)) + return 0xb4; + return 120; + + case TIMINGS_PIO_FC: + if (!IDE_PCI || (ide->board >= 2)) + return 0; + if (ide_drive_is_zip(ide)) + return 0xb4; + return 0; + + default: + fatal("Unknown transfer type: %i\n", type); + return 0; + } +} + + /** * Fill in ide->buffer with the output of the "IDENTIFY DEVICE" command */ -static void ide_identify(IDE *ide) +static void +ide_hd_identify(ide_t *ide) { - uint32_t d; - char device_identify[9] = { 'E', 'M', 'U', '_', 'H', 'D', '0', '0', 0 }; + char device_identify[9] = { 'E', 'M', 'U', '_', 'H', 'D', '0', '0', 0 }; + uint32_t d_hpc, d_spt, d_tracks; + uint64_t full_size = (hdd[ide->hdd_num].tracks * hdd[ide->hdd_num].hpc * hdd[ide->hdd_num].spt); - uint64_t d_hpc, d_spt, d_tracks; - uint64_t full_size = (hdd[ide->hdd_num].tracks * hdd[ide->hdd_num].hpc * hdd[ide->hdd_num].spt); + device_identify[6] = (ide->hdd_num / 10) + 0x30; + device_identify[7] = (ide->hdd_num % 10) + 0x30; + DEBUG("IDE Identify: %s\n", device_identify); - device_identify[6] = (ide->hdd_num / 10) + 0x30; - device_identify[7] = (ide->hdd_num % 10) + 0x30; -#ifdef ENABLE_HDC_LOG - hdc_log("IDE Identify: %s\n", device_identify); -#endif + d_spt = ide->spt; + if (ide->hpc <= 16) { + /* HPC <= 16, report as needed. */ + d_tracks = ide->tracks; + d_hpc = ide->hpc; + } else { + /* HPC > 16, convert to 16 HPC. */ + d_hpc = 16; + d_tracks = (ide->tracks * ide->hpc) / 16; + } - memset(ide->buffer, 0, 512); - d_spt = ide->spt; - if (ide->hpc <= 16) { - /* HPC <= 16, report as needed. */ - d_tracks = ide->tracks; - d_hpc = ide->hpc; + /* Specify default CHS translation */ + if (full_size <= 16514064) { + ide->buffer[1] = d_tracks; + ide->buffer[3] = d_hpc; + ide->buffer[6] = d_spt; + } else { + ide->buffer[1] = 16383; + ide->buffer[3] = 16; + ide->buffer[6] = 63; + } + DEBUG("Default CHS translation: %i, %i, %i\n", ide->buffer[1], ide->buffer[3], ide->buffer[6]); + + /* Serial Number, Firmware and Model. */ + ide_padstr((char *) (ide->buffer + 10), "", 20); + ide_padstr((char *) (ide->buffer + 23), EMU_VERSION, 8); + ide_padstr((char *) (ide->buffer + 27), device_identify, 40); + + /* Buffer type and size. */ + ide->buffer[20] = 3; + ide->buffer[21] = 512; + + /* Capabilities. */ + ide->buffer[50] = 0x4000; + ide->buffer[59] = ide->blocksize ? (ide->blocksize | 0x100) : 0; + if ((ide->tracks >= 1024) || (ide->hpc > 16) || (ide->spt > 63)) { + ide->buffer[49] = (1 << 9); + DEBUG("LBA supported\n"); + + /* Total addressable sectors (LBA) */ + ide->buffer[60] = full_size & 0xFFFF; + ide->buffer[61] = (full_size >> 16) & 0x0FFF; + DEBUG("Full size: %" PRIu64 "\n", full_size); + + /* + * Bit 0 = The fields reported in words 54-58 are valid; + * Bit 1 = The fields reported in words 64-70 are valid; + * Bit 2 = The fields reported in word 88 are valid. + */ + ide->buffer[53] = 1; + if (ide->cfg_spt != 0) { + ide->buffer[54] = (uint16_t) ((full_size / ide->cfg_hpc) / ide->cfg_spt); + ide->buffer[55] = ide->cfg_hpc; + ide->buffer[56] = ide->cfg_spt; } else { - /* HPC > 16, convert to 16 HPC. */ - d_hpc = 16; - d_tracks = (ide->tracks * ide->hpc) / 16; - } - - /* Specify default CHS translation */ - if (full_size <= 16514064) { - ide->buffer[1] = (uint16_t)d_tracks; /* Tracks in default CHS translation. */ - ide->buffer[3] = (uint16_t)d_hpc; /* Heads in default CHS translation. */ - ide->buffer[6] = (uint16_t)d_spt; /* Heads in default CHS translation. */ - } else { - ide->buffer[1] = 16383; /* Tracks in default CHS translation. */ - ide->buffer[3] = 16; /* Heads in default CHS translation. */ - ide->buffer[6] = 63; /* Heads in default CHS translation. */ - } -#ifdef ENABLE_HDC_LOG - hdc_log("Default CHS translation: %i, %i, %i\n", ide->buffer[1], ide->buffer[3], ide->buffer[6]); -#endif - - ide_padstr((char *) (ide->buffer + 10), "", 20); /* Serial Number */ - ide_padstr((char *) (ide->buffer + 23), EMU_VERSION, 8); /* Firmware */ - ide_padstr((char *) (ide->buffer + 27), device_identify, 40); /* Model */ - ide->buffer[20] = 3; /*Buffer type*/ - ide->buffer[21] = 512; /*Buffer size*/ - ide->buffer[48] = 1; /*Dword transfers supported*/ - if (PCI && (ide->board < 2) && (hdd[ide->hdd_num].bus == HDD_BUS_IDE_PIO_AND_DMA)) { - ide->buffer[47] = 32 | 0x8000; /*Max sectors on multiple transfer command*/ - ide->buffer[49] = (1 << 8); /* LBA and DMA supported */ - } else { - ide->buffer[47] = 16 | 0x8000; /*Max sectors on multiple transfer command*/ - ide->buffer[49] = 0; - } - if ((ide->tracks >= 1024) || (ide->hpc > 16) || (ide->spt > 63)) - { - ide->buffer[49] |= (1 << 9); -#ifdef ENABLE_HDC_LOG - hdc_log("LBA supported\n"); -#endif - } - ide->buffer[50] = 0x4000; /* Capabilities */ - ide->buffer[51] = 2 << 8; /*PIO timing mode*/ - - if (ide->buffer[49] & (1 << 9)) - { - ide->buffer[60] = full_size & 0xFFFF; /* Total addressable sectors (LBA) */ - ide->buffer[61] = (full_size >> 16) & 0x0FFF; -#ifdef ENABLE_HDC_LOG - hdc_log("Full size: %" PRIu64 "\n", full_size); -#endif - - ide->buffer[53] |= 1; - - if (ide->specify_success) { - ide->buffer[54] = (uint16_t)((full_size / ide->t_hpc) / ide->t_spt); - ide->buffer[55] = (uint16_t)ide->t_hpc; - ide->buffer[56] = (uint16_t)ide->t_spt; - } else { - if (full_size <= 16514064) { - ide->buffer[54] = (uint16_t)d_tracks; - ide->buffer[55] = (uint16_t)d_hpc; - ide->buffer[56] = (uint16_t)d_spt; - } else { - ide->buffer[54] = 16383; - ide->buffer[55] = 16; - ide->buffer[56] = 63; - } + if (full_size <= 16514064) { + ide->buffer[54] = d_tracks; + ide->buffer[55] = d_hpc; + ide->buffer[56] = d_spt; + ide->buffer[54] = 16383; + ide->buffer[55] = 16; + ide->buffer[56] = 63; } - - full_size = ((uint64_t) ide->buffer[54]) * ((uint64_t) ide->buffer[55]) * ((uint64_t) ide->buffer[56]); - - ide->buffer[57] = full_size & 0xFFFF; /* Total addressable sectors (LBA) */ - ide->buffer[58] = (full_size >> 16) & 0x0FFF; - -#ifdef ENABLE_HDC_LOG - hdc_log("Current CHS translation: %i, %i, %i\n", ide->buffer[54], ide->buffer[55], ide->buffer[56]); -#endif } - ide->buffer[59] = ide->blocksize ? (ide->blocksize | 0x100) : 0; + full_size = ((uint64_t) ide->buffer[54]) * ((uint64_t) ide->buffer[55]) * ((uint64_t) ide->buffer[56]); - if (ide->buffer[49] & (1 << 8)) - { - ide->buffer[51] = 120; - ide->buffer[52] = 120; /*DMA timing mode*/ - ide->buffer[53] |= 6; + /* Total addressable sectors (LBA) */ + ide->buffer[57] = full_size & 0xFFFF; + ide->buffer[58] = (full_size >> 16) & 0x0FFF; - ide->buffer[62] = 7; - ide->buffer[63] = 7; - ide->buffer[64] = 3; /*PIO Modes 3 & 4*/ - ide->buffer[88] = 7; - if (ide->mdma_mode != -1) - { - d = (ide->mdma_mode & 0xff); - d <<= 8; - if ((ide->mdma_mode & 0x300) == 0x200) - ide->buffer[88] |= d; - else if ((ide->mdma_mode & 0x300) == 0x100) - ide->buffer[63] |= d; - else if ((ide->mdma_mode & 0x300) == 0x400) { - if ((ide->mdma_mode & 0xff) >= 3) - ide->buffer[64] |= d; - } else - ide->buffer[62] |= d; -#ifdef ENABLE_HDC_LOG - hdc_log(" IDENTIFY DMA Mode: %04X, %04X\n", ide->buffer[62], ide->buffer[63]); -#endif - } - ide->buffer[65] = 120; - ide->buffer[66] = 120; - ide->buffer[80] = 0x1e; /*ATA-1 to ATA-4 supported*/ - ide->buffer[81] = 0x18; /*ATA-4 revision 18 supported*/ - } else { - ide->buffer[80] = 0x0e; /*ATA-1 to ATA-3 supported*/ - } + DEBUG("Current CHS translation: %i, %i, %i\n", ide->buffer[54], ide->buffer[55], ide->buffer[56]); + } + + if (IDE_PCI && (ide->board < 2)) { + /* Max sectors on multiple transfer command. */ + ide->buffer[47] = 32 | 0x8000; + + ide->buffer[80] = 0x1e; /* ATA-1 to ATA-4 supported */ + ide->buffer[81] = 0x18; /* ATA-4 revision 18 supported */ + } else { + /* Max sectors on multiple transfer command. */ + ide->buffer[47] = 16 | 0x8000; + + ide->buffer[80] = 0x0e; /* ATA-1 to ATA-3 supported */ + } } + /** * Fill in ide->buffer with the output of the "IDENTIFY PACKET DEVICE" command */ -static void ide_atapi_identify(IDE *ide) +static void +ide_atapi_cdrom_identify(ide_t *ide) { - char device_identify[9] = { 'E', 'M', 'U', '_', 'C', 'D', '0', '0', 0 }; + char device_identify[9] = { 'E', 'M', 'U', '_', 'C', 'D', '0', '0', 0 }; + uint8_t cdrom_id; + cdrom_id = atapi_cdrom_drives[ide->channel]; - uint8_t cdrom_id; - int32_t d; + device_identify[7] = cdrom_id + 0x30; - memset(ide->buffer, 0, 512); - cdrom_id = atapi_cdrom_drives[ide->channel]; + DEBUG("ATAPI Identify: %s\n", device_identify); - device_identify[7] = cdrom_id + 0x30; -#ifdef ENABLE_HDC_LOG - hdc_log("ATAPI Identify: %s\n", device_identify); + /* ATAPI device, CD-ROM drive, removable media, accelerated DRQ */ + ide->buffer[0] = 0x8000 | (5<<8) | 0x80 | (2<<5); + + /* Serial Number, Firmware and Model. */ + ide_padstr((char *) (ide->buffer + 10), "", 20); +#if 1 + ide_padstr((char *) (ide->buffer + 23), EMU_VERSION, 8); + ide_padstr((char *) (ide->buffer + 27), device_identify, 40); +#else + ide_padstr((char *) (ide->buffer + 23), "4.20 ", 8); + ide_padstr((char *) (ide->buffer + 27), + "NEC CD-ROM DRIVE:273 ", 40); #endif - ide->buffer[0] = 0x8000 | (5<<8) | 0x80 | (2<<5); /* ATAPI device, CD-ROM drive, removable media, accelerated DRQ */ - ide_padstr((char *) (ide->buffer + 10), "", 20); /* Serial Number */ - ide_padstr((char *) (ide->buffer + 23), EMU_VERSION, 8); /* Firmware */ - ide_padstr((char *) (ide->buffer + 27), device_identify, 40); /* Model */ - ide->buffer[48] = 1; /*Dword transfers supported*/ - ide->buffer[49] = 0x200; /* LBA supported */ - ide->buffer[51] = 2 << 8; /*PIO timing mode*/ - ide->buffer[126] = 0xfffe; /* Interpret zero byte count limit as maximum length */ + /* LBA supported */ + ide->buffer[49] = 0x200; - if (PCI && (ide->board < 2) && (cdrom_drives[cdrom_id].bus_type == CDROM_BUS_ATAPI_PIO_AND_DMA)) - { - ide->buffer[49] |= 0x100; /* DMA supported */ - ide->buffer[51] = 120; - ide->buffer[52] = 120; /*DMA timing mode*/ - ide->buffer[53] = 7; - ide->buffer[62] = 7; - ide->buffer[63] = 7; - ide->buffer[64] = 3; /*PIO Modes 3 & 4*/ - ide->buffer[88] = 7; - if (ide->mdma_mode != -1) - { - d = (ide->mdma_mode & 0xff); - d <<= 8; - if ((ide->mdma_mode & 0x300) == 0x200) - ide->buffer[88] |= d; - else if ((ide->mdma_mode & 0x300) == 0x100) - ide->buffer[63] |= d; - else if ((ide->mdma_mode & 0x300) == 0x400) { - if ((ide->mdma_mode & 0xff) >= 3) - ide->buffer[64] |= d; - } else - ide->buffer[62] |= d; -#ifdef ENABLE_HDC_LOG - hdc_log("PIDENTIFY DMA Mode: %04X, %04X\n", ide->buffer[62], ide->buffer[63]); -#endif - } - ide->buffer[65] = 120; - ide->buffer[66] = 120; - ide->buffer[67] = 120; - ide->buffer[71] = 30; - ide->buffer[72] = 30; - ide->buffer[80] = 0x1e; /*ATA-1 to ATA-4 supported*/ - ide->buffer[81] = 0x18; /*ATA-4 revision 18 supported*/ - } + /* Interpret zero byte count limit as maximum length. */ + ide->buffer[126] = 0xfffe; + + if (IDE_PCI && (ide->board < 2)) { + ide->buffer[71] = 30; + ide->buffer[72] = 30; + } } -static void ide_atapi_zip_identify(IDE *ide) + +static void +ide_atapi_zip_100_identify(ide_t *ide) { - uint8_t zip_id; - int32_t d; - - memset(ide->buffer, 0, 512); - zip_id = atapi_zip_drives[ide->channel]; - - /* Using (2<<5) below makes the ASUS P/I-P54TP4XE misdentify the ZIP drive - as a LS-120. */ - ide->buffer[0] = 0x8000 | (0<<8) | 0x80 | (1<<5); /* ATAPI device, direct-access device, removable media, interrupt DRQ */ - ide_padstr((char *) (ide->buffer + 10), "", 20); /* Serial Number */ - if (zip_drives[zip_id].is_250) { - ide_padstr((char *) (ide->buffer + 23), "42.S", 8); /* Firmware */ - ide_padstr((char *) (ide->buffer + 27), "IOMEGA ZIP 250 ATAPI", 40); /* Model */ - } else { - ide_padstr((char *) (ide->buffer + 23), "E.08", 8); /* Firmware */ - ide_padstr((char *) (ide->buffer + 27), "IOMEGA ZIP 100 ATAPI", 40); /* Model */ - } - - ide->buffer[48] = 1; /*Dword transfers supported*/ - ide->buffer[49] = 0x200; /* LBA supported */ - - /* Note by Kotori: Look at this if this is supported by ZIP at all. */ - ide->buffer[51] = 2 << 8; /*PIO timing mode*/ - - ide->buffer[126] = 0xfffe; /* Interpret zero byte count limit as maximum length */ - - if (PCI && (ide->board < 2) && (zip_drives[zip_id].bus_type == ZIP_BUS_ATAPI_PIO_AND_DMA)) - { - ide->buffer[49] |= 0x100; /* DMA supported */ - if (zip_drives[zip_id].is_250) { - ide->buffer[52] = 0 << 8; /*DMA timing mode*/ - ide->buffer[53] = 6; - ide->buffer[63] = 3; - ide->buffer[88] = 7; - ide->buffer[64] = 0x0001; /*PIO Mode 3*/ - ide->buffer[65] = 0x96; - ide->buffer[66] = 0x96; - ide->buffer[67] = 0xb4; - ide->buffer[68] = 0xb4; - ide->buffer[80] = 0x30; /*Supported ATA versions : ATA/ATAPI-4 ATA/ATAPI-5*/ - ide->buffer[81] = 0x15; /*Maximum ATA revision supported : ATA/ATAPI-5 T13 1321D revision 1*/ - } else { - ide->buffer[51] = 120; - ide->buffer[52] = 120; - ide->buffer[53] = 2; /*Words 64-70 are valid*/ - ide->buffer[63] = 0x0003; /*Multi-word DMA 0 & 1*/ - ide->buffer[88] = 7; - ide->buffer[64] = 0x0001; /*PIO Mode 3*/ - ide->buffer[65] = 120; - ide->buffer[66] = 120; - ide->buffer[67] = 120; - } - - if (ide->mdma_mode != -1) - { - d = (ide->mdma_mode & 0xff); - d <<= 8; - if ((ide->mdma_mode & 0x300) == 0x200) - ide->buffer[88] |= d; - else if ((ide->mdma_mode & 0x300) == 0x100) - ide->buffer[63] |= d; - else if ((ide->mdma_mode & 0x300) == 0x400) { - if ((ide->mdma_mode & 0xff) >= 3) - ide->buffer[64] |= d; - } -#ifdef ENABLE_HDC_LOG - hdc_log("PIDENTIFY DMA Mode: %04X, %04X\n", ide->buffer[62], ide->buffer[63]); -#endif - } - } + /* Firmware and Model. */ + ide_padstr((char *) (ide->buffer + 23), "E.08", 8); + ide_padstr((char *) (ide->buffer + 27), "IOMEGA ZIP 100 ATAPI", 40); } + +static void +ide_atapi_zip_250_identify(ide_t *ide) +{ + /* Firmware and Model. */ + ide_padstr((char *) (ide->buffer + 23), "42.S", 8); + ide_padstr((char *) (ide->buffer + 27), "IOMEGA ZIP 250 ATAPI", 40); + + if (IDE_PCI && (ide->board < 2)) { + /*Supported ATA versions : ATA/ATAPI-4 ATA/ATAPI-5*/ + ide->buffer[80] = 0x30; + + /*Maximum ATA revision supported : ATA/ATAPI-5 T13 1321D revision 1*/ + ide->buffer[81] = 0x15; + } +} + + +static void +ide_atapi_zip_identify(ide_t *ide) +{ + uint8_t zip_id; + + zip_id = atapi_zip_drives[ide->channel]; + + /* + * ATAPI device, direct-access device, removable media, interrupt DRQ. + * + * Using (2<<5) here makes the ASUS P/I-P54TP4XE misidentify the ZIP + * drive as an LS-120. + */ + ide->buffer[0] = 0x8000 | (0<<8) | 0x80 | (1<<5); + + /* Serial Number. */ + ide_padstr((char *) (ide->buffer + 10), "", 20); + + /* LBA supported. */ + ide->buffer[49] = 0x200; + + /* Interpret zero byte count limit as maximum length. */ + ide->buffer[126] = 0xfffe; + + if (zip_drives[zip_id].is_250) + ide_atapi_zip_250_identify(ide); + else + ide_atapi_zip_100_identify(ide); +} + + +static void +ide_identify(ide_t *ide) +{ + int d, i, max_pio, max_sdma, max_mdma, max_udma; + + DEBUG("IDE IDENTIFY (PACKET DEVICE) on board %i (channel %i)\n", + ide->board, ide->channel); + memset(ide->buffer, 0, 512); + + if (ide_drive_is_cdrom(ide)) + ide_atapi_cdrom_identify(ide); + else if (ide_drive_is_zip(ide)) + ide_atapi_zip_identify(ide); + else if (ide->type != IDE_NONE) + ide_hd_identify(ide); + else { + fatal("IDE IDENTIFY (PACKET DEVICE) on non-attached IDE device\n"); + } + + max_pio = ide_get_max(ide, TYPE_PIO); + max_sdma = ide_get_max(ide, TYPE_SDMA); + max_mdma = ide_get_max(ide, TYPE_MDMA); + max_udma = ide_get_max(ide, TYPE_UDMA); + + if (ide_boards[ide->board]->bit32) + ide->buffer[48] |= 1; /*Dword transfers supported*/ + ide->buffer[51] = ide_get_timings(ide, TIMINGS_PIO); + ide->buffer[53] &= 0x0006; + ide->buffer[52] = ide->buffer[62] = ide->buffer[63] = ide->buffer[64] = 0x0000; + ide->buffer[65] = ide->buffer[66] = ide->buffer[67] = ide->buffer[68] = 0x0000; + ide->buffer[88] = 0x0000; + + if (max_pio >= 3) { + ide->buffer[53] |= 0x0002; + ide->buffer[67] = ide_get_timings(ide, TIMINGS_PIO); + ide->buffer[68] = ide_get_timings(ide, TIMINGS_PIO_FC); + for (i = 3; i <= max_pio; i++) + ide->buffer[64] |= (1 << (i - 3)); + } + if (max_sdma != -1) { + for (i = 0; i <= max_sdma; i++) + ide->buffer[62] |= (1 << i); + } + if (max_mdma != -1) { + for (i = 0; i <= max_mdma; i++) + ide->buffer[63] |= (1 << i); + } + if (max_udma != -1) { + ide->buffer[53] |= 0x0004; + for (i = 0; i <= max_udma; i++) + ide->buffer[88] |= (1 << i); + } + if ((max_sdma != -1) || (max_mdma != -1) || (max_udma != -1)) { + ide->buffer[49] |= 0x100; /* DMA supported */ + ide->buffer[52] = ide_get_timings(ide, TIMINGS_DMA); + } + if ((max_mdma != -1) || (max_udma != -1)) { + ide->buffer[65] = ide_get_timings(ide, TIMINGS_DMA); + ide->buffer[66] = ide_get_timings(ide, TIMINGS_DMA); + } + if (ide->mdma_mode != -1) { + d = (ide->mdma_mode & 0xff); + d <<= 8; + if ((ide->mdma_mode & 0x300) == 0x000) { + if ((ide->mdma_mode & 0xff) >= 3) + ide->buffer[64] |= d; + } else if ((ide->mdma_mode & 0x300) == 0x100) + ide->buffer[62] |= d; + else if ((ide->mdma_mode & 0x300) == 0x200) + ide->buffer[63] |= d; + else if ((ide->mdma_mode & 0x300) == 0x300) + ide->buffer[88] |= d; + + DEBUG("PIDENTIFY DMA Mode: %04X, %04X\n", ide->buffer[62], ide->buffer[63]); + } +} + + /* * Return the sector offset for the current register values */ -static off64_t ide_get_sector(IDE *ide) +static off64_t +ide_get_sector(ide_t *ide) { - if (ide->lba) - { - return (off64_t)ide->lba_addr + ide->skip512; - } - else - { - uint32_t heads = (uint32_t)ide->t_hpc; - uint32_t sectors = (uint32_t)ide->t_spt; + uint32_t heads, sectors; - return ((((off64_t) ide->cylinder * heads) + ide->head) * - sectors) + (ide->sector - 1) + ide->skip512; - } + if (ide->lba) + return (off64_t)ide->lba_addr + ide->skip512; + + heads = ide->cfg_hpc; + sectors = ide->cfg_spt; + + return ((((off64_t) ide->cylinder * heads) + ide->head) * + sectors) + (ide->sector - 1) + ide->skip512; } + /** * Move to the next sector using CHS addressing */ -static void ide_next_sector(IDE *ide) +static void +ide_next_sector(ide_t *ide) { - if (ide->lba) - { - ide->lba_addr++; - } - else - { - ide->sector++; - if (ide->sector == (ide->t_spt + 1)) - { - ide->sector = 1; - ide->head++; - if (ide->head == ide->t_hpc) - { - ide->head = 0; - ide->cylinder++; - } - } - } -} - -static void loadhd(IDE *ide, int d, const wchar_t *fn) -{ - if (! hdd_image_load(d)) { - ide->type = IDE_NONE; - return; - } - - ide->spt = (uint8_t)hdd[d].spt; - ide->hpc = (uint8_t)hdd[d].hpc; - ide->tracks = (int)hdd[d].tracks; - ide->type = IDE_HDD; - ide->hdd_num = d; - ide->hdi = hdd_image_get_type(d); -} - -void ide_set_signature(IDE *ide) -{ - uint8_t cdrom_id = atapi_cdrom_drives[ide->channel]; - uint8_t zip_id = atapi_zip_drives[ide->channel]; - ide->sector=1; - ide->head=0; - if (ide_drive_is_zip(ide)) - { - zip_set_signature(zip_id); - ide->secount = zip[zip_id].phase; - ide->cylinder = zip[zip_id].request_length; - } - else if (ide_drive_is_cdrom(ide)) - { - cdrom_set_signature(cdrom_id); - ide->secount = cdrom[cdrom_id]->phase; - ide->cylinder = cdrom[cdrom_id]->request_length; - } - else - { - ide->secount=1; - ide->cylinder=((ide->type == IDE_HDD) ? 0 : 0xFFFF); - if (ide->type == IDE_HDD) - { - ide->drive = 0; + if (ide->lba) + ide->lba_addr++; + else { + if (++ide->sector == (ide->cfg_spt + 1)) { + ide->sector = 1; + if (++ide->head == ide->cfg_hpc) { + ide->head = 0; + ide->cylinder++; } } + } } -static int ide_set_features(IDE *ide) + +static void +loadhd(ide_t *ide, int d, const wchar_t *fn) { - uint8_t features, features_data; - uint8_t mode, submode; + if (! hdd_image_load(d)) { + ide->type = IDE_NONE; + return; + } - int bus, dma; - int max_pio = 2, max_mdma = 2; + ide->spt = hdd[d].spt; + ide->hpc = hdd[d].hpc; + ide->tracks = hdd[d].tracks; + ide->type = IDE_HDD; + ide->hdd_num = d; +} - features = ide->cylprecomp; - features_data = ide->secount; - if (ide_drive_is_zip(ide)) { - bus = zip_drives[atapi_zip_drives[ide->channel]].bus_type; - dma = (bus == ZIP_BUS_ATAPI_PIO_AND_DMA); - if (!PCI || !dma || (ide->board >= 2)) - max_pio = 0; - else - max_pio = 3; - max_mdma = 1; - } else if (ide_drive_is_cdrom(ide)) { - bus = cdrom_drives[atapi_cdrom_drives[ide->channel]].bus_type; - dma = (bus == CDROM_BUS_ATAPI_PIO_AND_DMA); - if (!PCI || !dma || (ide->board >= 2)) - max_pio = 0; - else - max_pio = 4; - } else { - bus = hdd[ide->hdd_num].bus; - dma = (bus == HDD_BUS_IDE_PIO_AND_DMA); - if (!PCI || !dma || (ide->board >= 2)) - max_pio = 0; - else - max_pio = 4; - } +void +ide_set_signature(ide_t *ide) +{ + uint8_t cdrom_id = atapi_cdrom_drives[ide->channel]; + uint8_t zip_id = atapi_zip_drives[ide->channel]; -#ifdef ENABLE_HDC_LOG - hdc_log("Features code %02X\n", features); + ide->sector = 1; + ide->head = 0; - hdc_log("IDE %02X: Set features: %02X, %02X\n", ide->channel, features, features_data); -#endif + if (ide_drive_is_zip(ide)) { + zip_set_signature(zip[zip_id]); + ide->secount = zip[zip_id]->phase; + ide->cylinder = zip[zip_id]->request_length; + } else if (ide_drive_is_cdrom(ide)) { + cdrom_set_signature(cdrom[cdrom_id]); + ide->secount = cdrom[cdrom_id]->phase; + ide->cylinder = cdrom[cdrom_id]->request_length; + } else { + ide->secount=1; + ide->cylinder=((ide->type == IDE_HDD) ? 0 : 0xFFFF); + if (ide->type == IDE_HDD) + ide->drive = 0; + } +} - switch(features) - { - case FEATURE_SET_TRANSFER_MODE: /* Set transfer mode. */ -#ifdef ENABLE_HDC_LOG - hdc_log("Transfer mode %02X\n", features_data >> 3); -#endif - mode = (features_data >> 3); - submode = features_data & 7; +static int +ide_set_features(ide_t *ide) +{ + uint8_t features, features_data; + int mode, submode, max; - switch(mode) - { - case 0x00: /* PIO default */ - if (submode != 0) - { - return 0; - } - ide->mdma_mode = -1; -#ifdef ENABLE_HDC_LOG - hdc_log("IDE %02X: Setting DPIO mode: %02X, %08X\n", ide->channel, submode, ide->mdma_mode); -#endif - break; + features = ide->cylprecomp; + features_data = ide->secount; - case 0x01: /* PIO mode */ - if (submode > max_pio) - { - return 0; - } - ide->mdma_mode = (1 << submode) | 0x400; -#ifdef ENABLE_HDC_LOG - hdc_log("IDE %02X: Setting PIO mode: %02X, %08X\n", ide->channel, submode, ide->mdma_mode); -#endif - break; + DEBUG("IDE %02X: Set features: %02X, %02X\n", + ide->channel, features, features_data); - case 0x02: /* Singleword DMA mode */ - if (!PCI || !dma || ide_drive_is_zip(ide) || (ide->board >= 2) || (submode > 2)) - { - return 0; - } - ide->mdma_mode = (1 << submode); -#ifdef ENABLE_HDC_LOG - hdc_log("IDE %02X: Setting SDMA mode: %02X, %08X\n", ide->channel, submode, ide->mdma_mode); -#endif - break; - - case 0x04: /* Multiword DMA mode */ - if (!PCI || !dma || (ide->board >= 2) || (submode > max_mdma)) - { - return 0; - } - ide->mdma_mode = (1 << submode) | 0x100; -#ifdef ENABLE_HDC_LOG - hdc_log("IDE %02X: Setting MDMA mode: %02X, %08X\n", ide->channel, submode, ide->mdma_mode); -#endif - break; - - case 0x08: /* Ultra DMA mode */ - if (!PCI || !dma || (ide->board >= 2) || (submode > 2)) - { - return 0; - } - ide->mdma_mode = (1 << submode) | 0x200; -#ifdef ENABLE_HDC_LOG - hdc_log("IDE %02X: Setting UDMA mode: %02X, %08X\n", ide->channel, submode, ide->mdma_mode); -#endif - break; - - default: + switch(features) { + case FEATURE_SET_TRANSFER_MODE: /* Set transfer mode. */ + DEBUG("Transfer mode %02X\n", features_data >> 3); + mode = (features_data >> 3); + submode = features_data & 7; + switch(mode) { + case 0x00: /* PIO default */ + if (submode != 0) return 0; - } + max = ide_get_max(ide, TYPE_PIO); + ide->mdma_mode = (1 << max); + DEBUG("IDE %02X: Setting DPIO mode: %02X, %08X\n", ide->channel, submode, ide->mdma_mode); + break; - case FEATURE_ENABLE_IRQ_OVERLAPPED: - case FEATURE_ENABLE_IRQ_SERVICE: - case FEATURE_DISABLE_IRQ_OVERLAPPED: - case FEATURE_DISABLE_IRQ_SERVICE: - if (!PCI || !dma || (ide->board >= 2)) + case 0x01: /* PIO mode */ + max = ide_get_max(ide, TYPE_PIO); + if (submode > max) + return 0; + ide->mdma_mode = (1 << submode); + DEBUG("IDE %02X: Setting PIO mode: %02X, %08X\n", ide->channel, submode, ide->mdma_mode); + break; + + case 0x02: /* Singleword DMA mode */ + max = ide_get_max(ide, TYPE_SDMA); + if (submode > max) + return 0; + ide->mdma_mode = (1 << submode) | 0x100; + DEBUG("IDE %02X: Setting SDMA mode: %02X, %08X\n", ide->channel, submode, ide->mdma_mode); + break; + + case 0x04: /* Multiword DMA mode */ + max = ide_get_max(ide, TYPE_MDMA); + if (submode > max) + return 0; + ide->mdma_mode = (1 << submode) | 0x200; + DEBUG("IDE %02X: Setting MDMA mode: %02X, %08X\n", ide->channel, submode, ide->mdma_mode); + break; + + case 0x08: /* Ultra DMA mode */ + max = ide_get_max(ide, TYPE_UDMA); + if (submode > max) + return 0; + ide->mdma_mode = (1 << submode) | 0x300; + DEBUG("IDE %02X: Setting UDMA mode: %02X, %08X\n", ide->channel, submode, ide->mdma_mode); + break; + + default: return 0; - else - return 1; + } - case FEATURE_DISABLE_REVERT: /* Disable reverting to power on defaults. */ - case FEATURE_ENABLE_REVERT: /* Enable reverting to power on defaults. */ + case FEATURE_ENABLE_IRQ_OVERLAPPED: + case FEATURE_ENABLE_IRQ_SERVICE: + case FEATURE_DISABLE_IRQ_OVERLAPPED: + case FEATURE_DISABLE_IRQ_SERVICE: + max = ide_get_max(ide, TYPE_MDMA); + if (max == -1) + return 0; + else return 1; - default: - return 0; - } + case FEATURE_DISABLE_REVERT: /* Disable reverting to power on defaults. */ + case FEATURE_ENABLE_REVERT: /* Enable reverting to power on defaults. */ + return 1; - return 1; -} + default: + return 0; + } -void ide_set_sector(IDE *ide, int64_t sector_num) -{ - uint32_t cyl, r; - if (ide->lba) - { - ide->head = (int)(sector_num >> 24); - ide->cylinder = (int)(sector_num >> 8); - ide->sector = (int)(sector_num); - } - else - { - cyl = (uint32_t) (sector_num / (hdd[ide->hdd_num].hpc * hdd[ide->hdd_num].spt)); - r = (uint32_t) (sector_num % (hdd[ide->hdd_num].hpc * hdd[ide->hdd_num].spt)); - ide->cylinder = (int)cyl; - ide->head = ((r / hdd[ide->hdd_num].spt) & 0x0f); - ide->sector = (int)(r % hdd[ide->hdd_num].spt) + 1; - } -} - -void ide_ter_disable_cond(); -void ide_qua_disable_cond(); - - -void ide_destroy_buffers(void) -{ - int d; - - for (d = 0; d < (IDE_NUM); d++) - { - if (ide_drives[d].buffer) { - free(ide_drives[d].buffer); - ide_drives[d].buffer = NULL; - } - - if (ide_drives[d].sector_buffer) { - free(ide_drives[d].sector_buffer); - ide_drives[d].sector_buffer = NULL; - } - } + return 1; } -void ide_reset(void) +void +ide_set_sector(ide_t *ide, int64_t sector_num) { - int c, d; + uint32_t cyl, r; - build_atapi_cdrom_map(); - build_atapi_zip_map(); - - /* Close hard disk image files (if previously open) */ - for (d = 0; d < (IDE_NUM); d++) - { - ide_drives[d].channel = d; - ide_drives[d].type = IDE_NONE; - if (ide_drives[d].hdd_num != -1) - hdd_image_close(ide_drives[d].hdd_num); - if ((d < 8) && ide_drive_is_zip(&ide_drives[d])) - { - zip[atapi_zip_drives[d]].status = READY_STAT | DSC_STAT; - } - else if ((d < 8) && ide_drive_is_cdrom(&ide_drives[d])) - { - cdrom[atapi_cdrom_drives[d]]->status = READY_STAT | DSC_STAT; - } - ide_drives[d].atastat = READY_STAT | DSC_STAT; - ide_drives[d].service = 0; - ide_drives[d].board = d >> 1; - - if (ide_drives[d].buffer) { - free(ide_drives[d].buffer); - ide_drives[d].buffer = NULL; - } - - if (ide_drives[d].sector_buffer) { - free(ide_drives[d].sector_buffer); - ide_drives[d].sector_buffer = NULL; - } - } - - idecallback[0]=idecallback[1]=0LL; - idecallback[2]=idecallback[3]=0LL; - idecallback[4]=0LL; - -#ifdef ENABLE_HDC_LOG - hdc_log("IDE: loading disks...\n"); -#endif - c = 0; - for (d = 0; d < HDD_NUM; d++) - { - if (((hdd[d].bus == HDD_BUS_IDE_PIO_ONLY) || (hdd[d].bus == HDD_BUS_IDE_PIO_AND_DMA)) && (hdd[d].id.ide_channel < IDE_NUM)) - { -#ifdef ENABLE_HDC_LOG - hdc_log("Found IDE hard disk on channel %i\n", hdd[d].id.ide_channel); -#endif - loadhd(&ide_drives[hdd[d].id.ide_channel], d, hdd[d].fn); - ide_drives[hdd[d].id.ide_channel].sector_buffer = (uint8_t *) malloc(256*512); - memset(ide_drives[hdd[d].id.ide_channel].sector_buffer, 0, 256*512); - if (++c >= IDE_NUM) break; - } - } -#ifdef ENABLE_HDC_LOG - hdc_log("IDE: done, loaded %d disks.\n", c); -#endif - - for (d = 0; d < IDE_NUM; d++) - { - if (ide_drive_is_zip(&ide_drives[d]) && (ide_drives[d].type == IDE_NONE)) - ide_drives[d].type = IDE_ZIP; - else if (ide_drive_is_cdrom(&ide_drives[d]) && (ide_drives[d].type == IDE_NONE)) - ide_drives[d].type = IDE_CDROM; - - if (ide_drives[d].type != IDE_NONE) { - ide_drives[d].buffer = (uint16_t *) malloc(65536 * sizeof(uint16_t)); - memset(ide_drives[d].buffer, 0, 65536 * sizeof(uint16_t)); - } - - ide_set_signature(&ide_drives[d]); - - ide_drives[d].mdma_mode = -1; - ide_drives[d].error = 1; - } - - for (d = 0; d < 5; d++) - { - cur_ide[d] = d << 1; - } - - ide_ter_disable_cond(); - ide_qua_disable_cond(); + if (ide->lba) { + ide->head = (uint32_t) (sector_num >> 24); + ide->cylinder = (uint32_t) (sector_num >> 8); + ide->sector = (uint32_t) sector_num; + } else { + cyl = (uint32_t) (sector_num / (hdd[ide->hdd_num].hpc * hdd[ide->hdd_num].spt)); + r = (uint32_t) (sector_num % (hdd[ide->hdd_num].hpc * hdd[ide->hdd_num].spt)); + ide->cylinder = cyl; + ide->head = ((r / hdd[ide->hdd_num].spt) & 0x0f); + ide->sector = (r % hdd[ide->hdd_num].spt) + 1; + } } -void ide_set_all_signatures(void) +static void +ide_zero(int d) { - int d; + ide_t *dev; - for (d = 0; d < IDE_NUM; d++) - { - ide_set_signature(&ide_drives[d]); - - if (ide_drives[d].sector_buffer) - memset(ide_drives[d].sector_buffer, 0, 256*512); - - if (ide_drives[d].buffer) - memset(ide_drives[d].buffer, 0, 65536 * sizeof(uint16_t)); - } + ide_drives[d] = (ide_t *) mem_alloc(sizeof(ide_t)); + memset(ide_drives[d], 0, sizeof(ide_t)); + dev = ide_drives[d]; + dev->channel = d; + dev->type = IDE_NONE; + dev->hdd_num = -1; + dev->atastat = DRDY_STAT | DSC_STAT; + dev->service = 0; + dev->board = d >> 1; } -void ide_reset_hard(void) +static void +ide_board_close(int board) { - int d; + cdrom_t *cddev; + zip_t *zipdev; + ide_t *dev; + int c, d; - for (d = 0; d < (IDE_NUM); d++) - { - ide_drives[d].t_spt = ide_drives[d].spt; - ide_drives[d].t_hpc = ide_drives[d].hpc; - ide_drives[d].specify_success = 0; - } + /* Close hard disk image files (if previously open) */ + for (d = 0; d < 2; d++) { + c = (board << 1) + d; + dev = ide_drives[c]; - ide_reset(); -} + if ((dev->type == IDE_HDD) && (dev->hdd_num != -1)) + hdd_image_close(dev->hdd_num); - -int idetimes = 0; - -void ide_set_callback(uint8_t channel, int64_t callback) -{ - IDE *ide = &ide_drives[channel]; - if (callback) - idecallback[ide->board] += callback; - else - idecallback[ide->board] = 0LL; -} - -void ide_write_data(int ide_board, uint32_t val, int length) -{ - IDE *ide = &ide_drives[cur_ide[ide_board]]; - - uint8_t *idebufferb = (uint8_t *) ide->buffer; - uint16_t *idebufferw = ide->buffer; - uint32_t *idebufferl = (uint32_t *) ide->buffer; - - if (ide->command == WIN_PACKETCMD) - { - ide->pos = 0; - - if (!ide_drive_is_zip(ide) && !ide_drive_is_cdrom(ide)) - { - return; + if (board < 4) { + if (ide_drive_is_zip(dev)) { + zipdev = zip[atapi_zip_drives[c]]; + if (zipdev != NULL) + zipdev->status = DRDY_STAT | DSC_STAT; + } else if (ide_drive_is_cdrom(dev)) { + cddev = cdrom[atapi_cdrom_drives[c]]; + if (cddev != NULL) + cddev->status = DRDY_STAT | DSC_STAT; } + } - if (ide_drive_is_zip(ide)) - zip_write(cur_ide[ide_board], val, length); - else - cdrom_write(cur_ide[ide_board], val, length); + if (dev->buffer) + free(dev->buffer); + + if (dev->sector_buffer) + free(dev->sector_buffer); + + free(dev); + } +} + + +static void +ide_board_init(int board) +{ + ide_t *dev; + int c, d; + int max, ch; + int is_ide, valid_ch; + int min_ch, max_ch; + + min_ch = (board << 1); + max_ch = min_ch + 1; + DEBUG("IDE: board %i: loading disks...\n", board); + + for (d = 0; d < 2; d++) { + c = (board << 1) + d; + ide_zero(c); + } + + c = 0; + for (d = 0; d < HDD_NUM; d++) { + is_ide = (hdd[d].bus == HDD_BUS_IDE); + ch = hdd[d].id.ide_channel; + + if (board == 4) { + valid_ch = ((ch >= 0) && (ch <= 1)); + ch |= 8; + } else + valid_ch = ((ch >= min_ch) && (ch <= max_ch)); + + if (is_ide && valid_ch) { + DEBUG("Found IDE hard disk on channel %i\n", ch); + loadhd(ide_drives[ch], d, hdd[d].fn); + ide_drives[ch]->sector_buffer = (uint8_t *) mem_alloc(256*512); + memset(ide_drives[ch]->sector_buffer, 0, 256*512); + if (++c >= 2) break; + } + } + DEBUG("IDE: board %i: done, loaded %d disks.\n", board, c); + + for (d = 0; d < 2; d++) { + c = (board << 1) + d; + dev = ide_drives[c]; + + if (board < 4) { + if (ide_drive_is_zip(dev) && (dev->type == IDE_NONE)) + dev->type = IDE_ZIP; + else if (ide_drive_is_cdrom(dev) && (dev->type == IDE_NONE)) + dev->type = IDE_CDROM; + } + + if (dev->type != IDE_NONE) { + dev->buffer = (uint16_t *) mem_alloc(65536 * sizeof(uint16_t)); + memset(dev->buffer, 0, 65536 * sizeof(uint16_t)); + } + + ide_set_signature(dev); + + max = ide_get_max(dev, TYPE_PIO); + dev->mdma_mode = (1 << max); + dev->error = 1; + dev->cfg_spt = dev->cfg_hpc = 0; + } +} + + +void +ide_set_callback(uint8_t board, int64_t callback) +{ + ide_board_t *dev = ide_boards[board]; + + DEBUG("ide_set_callback(%i)\n", board); + if (dev == NULL) { + DEBUG("Set callback failed\n"); + return; + } + + dev->callback = callback; +} + + +void +ide_write_data(ide_t *ide, uint32_t val, int length) +{ + int ch = ide->channel; + uint8_t *idebufferb = (uint8_t *) ide->buffer; + uint16_t *idebufferw = ide->buffer; + uint32_t *idebufferl = (uint32_t *) ide->buffer; + + if (ide->command == WIN_PACKETCMD) { + ide->pos = 0; + + if (!ide_drive_is_zip(ide) && !ide_drive_is_cdrom(ide)) return; - } + + if (ide_drive_is_zip(ide)) + zip_write(ch, val, length); + else + cdrom_write(ch, val, length); + + return; + } + + switch(length) { + case 1: + idebufferb[ide->pos] = val & 0xff; + ide->pos++; + break; + + case 2: + idebufferw[ide->pos >> 1] = val & 0xffff; + ide->pos += 2; + break; + + case 4: + idebufferl[ide->pos >> 2] = val; + ide->pos += 4; + break; + + default: + return; + } + + if (ide->pos>=512) { + ide->pos=0; + ide->atastat = BSY_STAT; + timer_process(); + if (ide->command == WIN_WRITE_MULTIPLE) + ide_callback(ide_boards[ide->board]); else - { - switch(length) - { - case 1: - idebufferb[ide->pos] = val & 0xff; - ide->pos++; - break; - case 2: - idebufferw[ide->pos >> 1] = val & 0xffff; - ide->pos += 2; - break; - case 4: - idebufferl[ide->pos >> 2] = val; - ide->pos += 4; - break; - default: - return; + ide_set_callback(ide->board, ide_get_period(ide, 512)); + timer_update_outstanding(); + } +} + + + +void +ide_writew(uint16_t addr, uint16_t val, void *priv) +{ + ide_board_t *dev = (ide_board_t *) priv; + ide_t *ide; + int ch; + + ch = dev->cur_dev; + ide = ide_drives[ch]; + DBGLOG(1, "ide_writew %04X %04X from %04X(%08X):%08X\n", addr, val, CS, cs, cpu_state.pc); + + addr &= 0x7; + + if ((ide->type == IDE_NONE) && ((addr == 0x0) || (addr == 0x7))) + return; + + switch (addr) { + case 0x0: /* Data */ + ide_write_data(ide, val, 2); + break; + } +} + + +static void +ide_writel(uint16_t addr, uint32_t val, void *priv) +{ + ide_board_t *dev = (ide_board_t *) priv; + ide_t *ide; + int ch; + + ch = dev->cur_dev; + ide = ide_drives[ch]; + DBGLOG(1, "ide_writel %04X %08X from %04X(%08X):%08X\n", addr, val, CS, cs, cpu_state.pc); + + addr &= 0x7; + + if ((ide->type == IDE_NONE) && ((addr == 0x0) || (addr == 0x7))) + return; + + switch (addr) { + case 0x0: /* Data */ + ide_write_data(ide, val & 0xffff, 2); + ide_write_data(ide, val >> 16, 2); + break; + } +} + + +void +ide_write_devctl(uint16_t addr, uint8_t val, void *priv) +{ + ide_board_t *dev = (ide_board_t *) priv; + ide_t *ide, *ide_other; + int ch; + + ch = dev->cur_dev; + ide = ide_drives[ch]; + ide_other = ide_drives[ch ^ 1]; + + DEBUG("ide_write_devctl %04X %02X from %04X(%08X):%08X\n", addr, val, CS, cs, cpu_state.pc); + + if ((ide->fdisk & 4) && !(val&4) && (ide->type != IDE_NONE || ide_other->type != IDE_NONE)) { + timer_process(); + if (ide_drive_is_zip(ide)) + zip[atapi_zip_drives[ide->channel]]->callback = 0LL; + else if (ide_drive_is_cdrom(ide)) + cdrom[atapi_cdrom_drives[ide->channel]]->callback = 0LL; + ide_set_callback(ide->board, 500LL * IDE_TIME); + timer_update_outstanding(); + + if (ide->type != IDE_NONE) + ide->reset = 1; + if (ide_other->type != IDE_NONE) + ide->reset = 1; + if (ide_drive_is_zip(ide)) + zip[atapi_zip_drives[ide->channel]]->status = BSY_STAT; + else if (ide_drive_is_cdrom(ide)) + cdrom[atapi_cdrom_drives[ide->channel]]->status = BSY_STAT; + ide->atastat = ide_other->atastat = BSY_STAT; + } + + if (val & 4) { + /*Drive held in reset*/ + timer_process(); + ide_set_callback(ide->board, 0LL); + timer_update_outstanding(); + ide->atastat = ide_other->atastat = BSY_STAT; + } + + ide->fdisk = ide_other->fdisk = val; +} + + +void +ide_writeb(uint16_t addr, uint8_t val, void *priv) +{ + ide_board_t *dev = (ide_board_t *) priv; + ide_t *ide, *ide_other; + int ch; + + ch = dev->cur_dev; + ide = ide_drives[ch]; + ide_other = ide_drives[ch ^ 1]; + + DEBUG("ide_write %04X %02X from %04X(%08X):%08X\n", addr, val, CS, cs, cpu_state.pc); + + addr &= 0x7; + + if ((ide->type == IDE_NONE) && ((addr == 0x0) || (addr == 0x7))) + return; + + switch (addr) { + case 0x0: /* Data */ + ide_write_data(ide, val | (val << 8), 2); + return; + + /* Note: for ATAPI, bit 0 of this is DMA if set, PIO if clear. */ + case 0x1: /* Features */ + if (ide_drive_is_zip(ide)) { + DEBUG("ATAPI transfer mode: %s\n", (val & 1) ? "DMA" : "PIO"); + zip[atapi_zip_drives[ch]]->features = val; + } else if (ide_drive_is_cdrom(ide)) { + DEBUG("ATAPI transfer mode: %s\n", (val & 1) ? "DMA" : "PIO"); + cdrom[atapi_cdrom_drives[ch]]->features = val; } + ide->cylprecomp = val; - if (ide->pos>=512) - { - ide->pos=0; - ide->atastat = BUSY_STAT; - timer_process(); - if (ide->command == WIN_WRITE_MULTIPLE) - { - callbackide(ide_board); - } - else - { - idecallback[ide_board]=6LL*IDE_TIME; - } - timer_update_outstanding(); + if (ide_drive_is_zip(ide_other)) + zip[atapi_zip_drives[ch ^ 1]]->features = val; + else if (ide_drive_is_cdrom(ide_other)) + cdrom[atapi_cdrom_drives[ch ^ 1]]->features = val; + ide_other->cylprecomp = val; + return; + + case 0x2: /* Sector count */ + if (ide_drive_is_zip(ide)) { + DEBUG("Sector count write: %i\n", val); + zip[atapi_zip_drives[ch]]->phase = val; + } else if (ide_drive_is_cdrom(ide)) { + DEBUG("Sector count write: %i\n", val); + cdrom[atapi_cdrom_drives[ch]]->phase = val; } - } -} + ide->secount = val; -void writeidew(int ide_board, uint16_t val) -{ - ide_write_data(ide_board, val, 2); -} + if (ide_drive_is_zip(ide_other)) { + DEBUG("Other sector count write: %i\n", val); + zip[atapi_zip_drives[ch ^ 1]]->phase = val; + } else if (ide_drive_is_cdrom(ide_other)) { + DEBUG("Other sector count write: %i\n", val); + cdrom[atapi_cdrom_drives[ch ^ 1]]->phase = val; + } + ide_other->secount = val; + return; -void writeidel(int ide_board, uint32_t val) -{ - writeidew(ide_board, val); - writeidew(ide_board, val >> 16); -} + case 0x3: /* Sector */ + ide->sector = val; + ide->lba_addr = (ide->lba_addr & 0xFFFFF00) | val; + ide_other->sector = val; + ide_other->lba_addr = (ide_other->lba_addr & 0xFFFFF00) | val; + return; -void writeide(int ide_board, uint16_t addr, uint8_t val) -{ - IDE *ide = &ide_drives[cur_ide[ide_board]]; - IDE *ide_other = &ide_drives[cur_ide[ide_board] ^ 1]; + case 0x4: /* Cylinder low */ + if (ide_drive_is_zip(ide)) { + zip[atapi_zip_drives[ch]]->request_length &= 0xFF00; + zip[atapi_zip_drives[ch]]->request_length |= val; + } else if (ide_drive_is_cdrom(ide)) { + cdrom[atapi_cdrom_drives[ch]]->request_length &= 0xFF00; + cdrom[atapi_cdrom_drives[ch]]->request_length |= val; + } + ide->cylinder = (ide->cylinder & 0xFF00) | val; + ide->lba_addr = (ide->lba_addr & 0xFFF00FF) | (val << 8); -#ifdef ENABLE_HDC_LOG - hdc_log("WriteIDE %04X %02X from %04X(%08X):%08X\n", addr, val, CS, cs, cpu_state.pc); -#endif - addr|=0x90; - addr&=0xFFF7; + if (ide_drive_is_zip(ide_other)) { + zip[atapi_zip_drives[ch ^ 1]]->request_length &= 0xFF00; + zip[atapi_zip_drives[ch ^ 1]]->request_length |= val; + } else if (ide_drive_is_cdrom(ide_other)) { + cdrom[atapi_cdrom_drives[ch ^ 1]]->request_length &= 0xFF00; + cdrom[atapi_cdrom_drives[ch ^ 1]]->request_length |= val; + } + ide_other->cylinder = (ide_other->cylinder & 0xFF00) | val; + ide_other->lba_addr = (ide_other->lba_addr & 0xFFF00FF) | (val << 8); + return; - if (ide->type == IDE_NONE && (addr == 0x1f0 || addr == 0x1f7)) return; - - switch (addr) - { - case 0x1F0: /* Data */ - writeidew(ide_board, val | (val << 8)); - return; + case 0x5: /* Cylinder high */ + if (ide_drive_is_zip(ide)) { + zip[atapi_zip_drives[ch]]->request_length &= 0xFF; + zip[atapi_zip_drives[ch]]->request_length |= (val << 8); + } else if (ide_drive_is_cdrom(ide)) { + cdrom[atapi_cdrom_drives[ch]]->request_length &= 0xFF; + cdrom[atapi_cdrom_drives[ch]]->request_length |= (val << 8); + } + ide->cylinder = (ide->cylinder & 0xFF) | (val << 8); + ide->lba_addr = (ide->lba_addr & 0xF00FFFF) | (val << 16); - /* Note to self: for ATAPI, bit 0 of this is DMA if set, PIO if clear. */ - case 0x1F1: /* Features */ - if (ide_drive_is_zip(ide)) - { -#ifdef ENABLE_HDC_LOG - hdc_log("ATAPI transfer mode: %s\n", (val & 1) ? "DMA" : "PIO"); -#endif - zip[atapi_zip_drives[cur_ide[ide_board]]].features = val; - } - else if (ide_drive_is_cdrom(ide)) - { -#ifdef ENABLE_HDC_LOG - hdc_log("ATAPI transfer mode: %s\n", (val & 1) ? "DMA" : "PIO"); -#endif - cdrom[atapi_cdrom_drives[cur_ide[ide_board]]]->features = val; - } - ide->cylprecomp = val; + if (ide_drive_is_zip(ide_other)) { + zip[atapi_zip_drives[ch ^ 1]]->request_length &= 0xFF; + zip[atapi_zip_drives[ch ^ 1]]->request_length |= (val << 8); + } else if (ide_drive_is_cdrom(ide_other)) { + cdrom[atapi_cdrom_drives[ch ^ 1]]->request_length &= 0xFF; + cdrom[atapi_cdrom_drives[ch ^ 1]]->request_length |= (val << 8); + } + ide_other->cylinder = (ide_other->cylinder & 0xFF) | (val << 8); + ide_other->lba_addr = (ide_other->lba_addr & 0xF00FFFF) | (val << 16); + return; - if (ide_drive_is_zip(ide_other)) - { - zip[atapi_zip_drives[cur_ide[ide_board] ^ 1]].features = val; - } - else if (ide_drive_is_cdrom(ide_other)) - { - cdrom[atapi_cdrom_drives[cur_ide[ide_board] ^ 1]]->features = val; - } - ide_other->cylprecomp = val; - return; + case 0x6: /* Drive/Head */ + if (ch != ((val >> 4) & 1) + (ide->board << 1)) { + ide_boards[ide->board]->cur_dev = ((val >> 4) & 1) + (ide->board << 1); + ch = ide_boards[ide->board]->cur_dev; - case 0x1F2: /* Sector count */ - if (ide_drive_is_zip(ide)) - { -#ifdef ENABLE_HDC_LOG - hdc_log("Sector count write: %i\n", val); -#endif - zip[atapi_zip_drives[cur_ide[ide_board]]].phase = val; - } - else if (ide_drive_is_cdrom(ide)) - { -#ifdef ENABLE_HDC_LOG - hdc_log("Sector count write: %i\n", val); -#endif - cdrom[atapi_cdrom_drives[cur_ide[ide_board]]]->phase = val; - } - ide->secount = val; + if (ide->reset || ide_other->reset) { + ide->atastat = ide_other->atastat = DRDY_STAT | DSC_STAT; + ide->error = ide_other->error = 1; + ide->secount = ide_other->secount = 1; + ide->sector = ide_other->sector = 1; + ide->head = ide_other->head = 0; + ide->cylinder = ide_other->cylinder = 0; + ide->reset = ide_other->reset = 0; - if (ide_drive_is_zip(ide_other)) - { -#ifdef ENABLE_HDC_LOG - hdc_log("Other sector count write: %i\n", val); -#endif - zip[atapi_zip_drives[cur_ide[ide_board] ^ 1]].phase = val; - } - else if (ide_drive_is_cdrom(ide_other)) - { -#ifdef ENABLE_HDC_LOG - hdc_log("Other sector count write: %i\n", val); -#endif - cdrom[atapi_cdrom_drives[cur_ide[ide_board] ^ 1]]->phase = val; - } - ide_other->secount = val; - return; - - case 0x1F3: /* Sector */ - ide->sector = val; - ide->lba_addr = (ide->lba_addr & 0xFFFFF00) | val; - ide_other->sector = val; - ide_other->lba_addr = (ide_other->lba_addr & 0xFFFFF00) | val; - return; - - case 0x1F4: /* Cylinder low */ - if (ide_drive_is_zip(ide)) - { - zip[atapi_zip_drives[cur_ide[ide_board]]].request_length &= 0xFF00; - zip[atapi_zip_drives[cur_ide[ide_board]]].request_length |= val; - } - else if (ide_drive_is_cdrom(ide)) - { - cdrom[atapi_cdrom_drives[cur_ide[ide_board]]]->request_length &= 0xFF00; - cdrom[atapi_cdrom_drives[cur_ide[ide_board]]]->request_length |= val; - } - ide->cylinder = (ide->cylinder & 0xFF00) | val; - ide->lba_addr = (ide->lba_addr & 0xFFF00FF) | (val << 8); - - if (ide_drive_is_zip(ide_other)) - { - zip[atapi_zip_drives[cur_ide[ide_board] ^ 1]].request_length &= 0xFF00; - zip[atapi_zip_drives[cur_ide[ide_board] ^ 1]].request_length |= val; - } - else if (ide_drive_is_cdrom(ide_other)) - { - cdrom[atapi_cdrom_drives[cur_ide[ide_board] ^ 1]]->request_length &= 0xFF00; - cdrom[atapi_cdrom_drives[cur_ide[ide_board] ^ 1]]->request_length |= val; - } - ide_other->cylinder = (ide_other->cylinder&0xFF00) | val; - ide_other->lba_addr = (ide_other->lba_addr&0xFFF00FF) | (val << 8); - return; - - case 0x1F5: /* Cylinder high */ - if (ide_drive_is_zip(ide)) - { - zip[atapi_zip_drives[cur_ide[ide_board]]].request_length &= 0xFF; - zip[atapi_zip_drives[cur_ide[ide_board]]].request_length |= (val << 8); - } - else if (ide_drive_is_cdrom(ide)) - { - cdrom[atapi_cdrom_drives[cur_ide[ide_board]]]->request_length &= 0xFF; - cdrom[atapi_cdrom_drives[cur_ide[ide_board]]]->request_length |= (val << 8); - } - ide->cylinder = (ide->cylinder & 0xFF) | (val << 8); - ide->lba_addr = (ide->lba_addr & 0xF00FFFF) | (val << 16); - - if (ide_drive_is_zip(ide_other)) - { - zip[atapi_zip_drives[cur_ide[ide_board] ^ 1]].request_length &= 0xFF; - zip[atapi_zip_drives[cur_ide[ide_board] ^ 1]].request_length |= (val << 8); - } - else if (ide_drive_is_cdrom(ide_other)) - { - cdrom[atapi_cdrom_drives[cur_ide[ide_board] ^ 1]]->request_length &= 0xFF; - cdrom[atapi_cdrom_drives[cur_ide[ide_board] ^ 1]]->request_length |= (val << 8); - } - ide_other->cylinder = (ide_other->cylinder & 0xFF) | (val << 8); - ide_other->lba_addr = (ide_other->lba_addr & 0xF00FFFF) | (val << 16); - return; - - case 0x1F6: /* Drive/Head */ - if (cur_ide[ide_board] != ((val>>4)&1)+(ide_board<<1)) - { - cur_ide[ide_board]=((val>>4)&1)+(ide_board<<1); - - if (ide->reset || ide_other->reset) - { - ide->atastat = ide_other->atastat = READY_STAT | DSC_STAT; - ide->error = ide_other->error = 1; - ide->secount = ide_other->secount = 1; - ide->sector = ide_other->sector = 1; - ide->head = ide_other->head = 0; - ide->cylinder = ide_other->cylinder = 0; - ide->reset = ide_other->reset = 0; - - if (ide_drive_is_zip(ide)) - { - zip[atapi_zip_drives[ide->channel]].status = READY_STAT | DSC_STAT; - zip[atapi_zip_drives[ide->channel]].error = 1; - zip[atapi_zip_drives[ide->channel]].phase = 1; - zip[atapi_zip_drives[ide->channel]].request_length = 0xEB14; - zip[atapi_zip_drives[ide->channel]].callback = 0LL; - ide->cylinder = 0xEB14; - } - else if (ide_drive_is_cdrom(ide)) - { - cdrom[atapi_cdrom_drives[ide->channel]]->status = READY_STAT | DSC_STAT; - cdrom[atapi_cdrom_drives[ide->channel]]->error = 1; - cdrom[atapi_cdrom_drives[ide->channel]]->phase = 1; - cdrom[atapi_cdrom_drives[ide->channel]]->request_length = 0xEB14; - cdrom[atapi_cdrom_drives[ide->channel]]->callback = 0LL; - ide->cylinder = 0xEB14; - } - - if (ide_drive_is_zip(ide_other)) - { - zip[atapi_zip_drives[ide_other->channel]].status = READY_STAT | DSC_STAT; - zip[atapi_zip_drives[ide_other->channel]].error = 1; - zip[atapi_zip_drives[ide_other->channel]].phase = 1; - zip[atapi_zip_drives[ide_other->channel]].request_length = 0xEB14; - zip[atapi_zip_drives[ide_other->channel]].callback = 0LL; - ide->cylinder = 0xEB14; - } - else if (ide_drive_is_cdrom(ide_other)) - { - cdrom[atapi_cdrom_drives[ide_other->channel]]->status = READY_STAT | DSC_STAT; - cdrom[atapi_cdrom_drives[ide_other->channel]]->error = 1; - cdrom[atapi_cdrom_drives[ide_other->channel]]->phase = 1; - cdrom[atapi_cdrom_drives[ide_other->channel]]->request_length = 0xEB14; - cdrom[atapi_cdrom_drives[ide_other->channel]]->callback = 0LL; - ide->cylinder = 0xEB14; - } - - idecallback[ide_board] = 0LL; - timer_update_outstanding(); - return; + if (ide_drive_is_zip(ide)) { + zip[atapi_zip_drives[ide->channel]]->status = DRDY_STAT | DSC_STAT; + zip[atapi_zip_drives[ide->channel]]->error = 1; + zip[atapi_zip_drives[ide->channel]]->phase = 1; + zip[atapi_zip_drives[ide->channel]]->request_length = 0xEB14; + zip[atapi_zip_drives[ide->channel]]->callback = 0LL; + ide->cylinder = 0xEB14; + } else if (ide_drive_is_cdrom(ide)) { + cdrom[atapi_cdrom_drives[ide->channel]]->status = DRDY_STAT | DSC_STAT; + cdrom[atapi_cdrom_drives[ide->channel]]->error = 1; + cdrom[atapi_cdrom_drives[ide->channel]]->phase = 1; + cdrom[atapi_cdrom_drives[ide->channel]]->request_length = 0xEB14; + cdrom[atapi_cdrom_drives[ide->channel]]->callback = 0LL; + ide->cylinder = 0xEB14; } - ide = &ide_drives[cur_ide[ide_board]]; - } - - ide->head = val & 0xF; - ide->lba = val & 0x40; - ide_other->head = val & 0xF; - ide_other->lba = val & 0x40; - - ide->lba_addr = (ide->lba_addr & 0x0FFFFFF) | ((val & 0xF) << 24); - ide_other->lba_addr = (ide_other->lba_addr & 0x0FFFFFF)|((val & 0xF) << 24); + if (ide_drive_is_zip(ide_other)) { + zip[atapi_zip_drives[ide_other->channel]]->status = DRDY_STAT | DSC_STAT; + zip[atapi_zip_drives[ide_other->channel]]->error = 1; + zip[atapi_zip_drives[ide_other->channel]]->phase = 1; + zip[atapi_zip_drives[ide_other->channel]]->request_length = 0xEB14; + zip[atapi_zip_drives[ide_other->channel]]->callback = 0LL; + ide->cylinder = 0xEB14; + } else if (ide_drive_is_cdrom(ide_other)) { + cdrom[atapi_cdrom_drives[ide_other->channel]]->status = DRDY_STAT | DSC_STAT; + cdrom[atapi_cdrom_drives[ide_other->channel]]->error = 1; + cdrom[atapi_cdrom_drives[ide_other->channel]]->phase = 1; + cdrom[atapi_cdrom_drives[ide_other->channel]]->request_length = 0xEB14; + cdrom[atapi_cdrom_drives[ide_other->channel]]->callback = 0LL; + ide->cylinder = 0xEB14; + } - return; - - case 0x1F7: /* Command register */ - if (ide->type == IDE_NONE) - { + ide_set_callback(ide->board, 0LL); + timer_update_outstanding(); return; } + ide = ide_drives[ch]; + } + + ide->head = val & 0xF; + ide->lba = val & 0x40; + ide_other->head = val & 0xF; + ide_other->lba = val & 0x40; + + ide->lba_addr = (ide->lba_addr & 0x0FFFFFF) | ((val & 0xF) << 24); + ide_other->lba_addr = (ide_other->lba_addr & 0x0FFFFFF)|((val & 0xF) << 24); + return; + + case 0x7: /* Command register */ + if (ide->type == IDE_NONE) + return; + ide_irq_lower(ide); ide->command=val; ide->error=0; if (ide_drive_is_zip(ide)) - { - zip[atapi_zip_drives[ide->channel]].error = 0; - } + zip[atapi_zip_drives[ide->channel]]->error = 0; else if (ide_drive_is_cdrom(ide)) - { cdrom[atapi_cdrom_drives[ide->channel]]->error = 0; - } - if (((val >= WIN_RESTORE) && (val <= 0x1F)) || ((val >= WIN_SEEK) && (val <= 0x7F))) - { + + if (((val >= WIN_RECAL) && (val <= 0x1F)) || ((val >= WIN_SEEK) && (val <= 0x7F))) { if (ide_drive_is_zip(ide)) - { - zip[atapi_zip_drives[ide->channel]].status = READY_STAT; - } + zip[atapi_zip_drives[ide->channel]]->status = DRDY_STAT; else if (ide_drive_is_cdrom(ide)) - { - cdrom[atapi_cdrom_drives[ide->channel]]->status = READY_STAT; - } + cdrom[atapi_cdrom_drives[ide->channel]]->status = DRDY_STAT; else - { - ide->atastat = BUSY_STAT; - } + ide->atastat = BSY_STAT; timer_process(); + if (ide_drive_is_zip(ide)) - { - zip[atapi_zip_drives[ide->channel]].callback = 100LL*IDE_TIME; - } - if (ide_drive_is_cdrom(ide)) - { + zip[atapi_zip_drives[ide->channel]]->callback = 100LL*IDE_TIME; + else if (ide_drive_is_cdrom(ide)) cdrom[atapi_cdrom_drives[ide->channel]]->callback = 100LL*IDE_TIME; - } - idecallback[ide_board]=40000LL * TIMER_USEC /*100LL*IDE_TIME*/; + ide_set_callback(ide->board, 100LL * IDE_TIME); timer_update_outstanding(); return; } - switch (val) - { + + switch (val) { case WIN_SRST: /* ATAPI Device Reset */ if (ide_drive_is_zip(ide)) - { - zip[atapi_zip_drives[ide->channel]].status = BUSY_STAT; - } + zip[atapi_zip_drives[ide->channel]]->status = BSY_STAT; else if (ide_drive_is_cdrom(ide)) - { - cdrom[atapi_cdrom_drives[ide->channel]]->status = BUSY_STAT; - } + cdrom[atapi_cdrom_drives[ide->channel]]->status = BSY_STAT; else - { - ide->atastat = READY_STAT; - } + ide->atastat = DRDY_STAT; timer_process(); + if (ide_drive_is_zip(ide)) - { - zip[atapi_zip_drives[ide->channel]].callback = 100LL*IDE_TIME; - } + zip[atapi_zip_drives[ide->channel]]->callback = 100LL*IDE_TIME; else if (ide_drive_is_cdrom(ide)) - { cdrom[atapi_cdrom_drives[ide->channel]]->callback = 100LL*IDE_TIME; - } - idecallback[ide_board]=100LL*IDE_TIME; - timer_update_outstanding(); - return; + ide_set_callback(ide->board, 100LL * IDE_TIME); + timer_update_outstanding(); + return; case WIN_READ_MULTIPLE: /* Fatal removed in accordance with the official ATAPI reference: @@ -1359,124 +1507,99 @@ void writeide(int ide_board, uint16_t addr, uint8_t val) disabled, the Read Multiple operation is rejected with an Aborted Com- mand error. */ ide->blockcount = 0; + /* Turn on the activity indicator *here* so that it gets turned on + less times. */ + /* hdd_active(ide->hdd_num, 1); */ case WIN_READ: case WIN_READ_NORETRY: case WIN_READ_DMA: case WIN_READ_DMA_ALT: if (ide_drive_is_zip(ide)) - { - zip[atapi_zip_drives[ide->channel]].status = BUSY_STAT; - } + zip[atapi_zip_drives[ide->channel]]->status = BSY_STAT; else if (ide_drive_is_cdrom(ide)) - { - cdrom[atapi_cdrom_drives[ide->channel]]->status = BUSY_STAT; - } + cdrom[atapi_cdrom_drives[ide->channel]]->status = BSY_STAT; else - { - ide->atastat = BUSY_STAT; - } + ide->atastat = BSY_STAT; timer_process(); + if (ide_drive_is_zip(ide)) - { - zip[atapi_zip_drives[ide->channel]].callback = 200LL*IDE_TIME; - } + zip[atapi_zip_drives[ide->channel]]->callback = 200LL*IDE_TIME; else if (ide_drive_is_cdrom(ide)) - { cdrom[atapi_cdrom_drives[ide->channel]]->callback = 200LL*IDE_TIME; - } - idecallback[ide_board]=200LL*IDE_TIME; + if (ide->type == IDE_HDD) { + if ((val == WIN_READ_DMA) || (val == WIN_READ_DMA_ALT)) { + if (ide->secount) + ide_set_callback(ide->board, ide_get_period(ide, (int) ide->secount << 9)); + else + ide_set_callback(ide->board, ide_get_period(ide, 131072)); + } else + ide_set_callback(ide->board, ide_get_period(ide, 512)); + } else + ide_set_callback(ide->board, 200LL * IDE_TIME); timer_update_outstanding(); ide->do_initial_read = 1; return; case WIN_WRITE_MULTIPLE: if (!ide->blocksize && !ide_drive_is_zip(ide) && !ide_drive_is_cdrom(ide)) - { fatal("Write_MULTIPLE - blocksize = 0\n"); - } ide->blockcount = 0; + /* Turn on the activity indicator *here* so that it gets turned on + less times. */ + /* hdd_active(ide->hdd_num, 1); */ case WIN_WRITE: case WIN_WRITE_NORETRY: - if (ide_drive_is_zip(ide)) - { - zip[atapi_zip_drives[ide->channel]].status = DRQ_STAT | DSC_STAT | READY_STAT; - zip[atapi_zip_drives[ide->channel]].pos = 0; - } - else if (ide_drive_is_cdrom(ide)) - { - cdrom[atapi_cdrom_drives[ide->channel]]->status = DRQ_STAT | DSC_STAT | READY_STAT; + if (ide_drive_is_zip(ide)) { + zip[atapi_zip_drives[ide->channel]]->status = DRQ_STAT | DSC_STAT | DRDY_STAT; + zip[atapi_zip_drives[ide->channel]]->pos = 0; + } else if (ide_drive_is_cdrom(ide)) { + cdrom[atapi_cdrom_drives[ide->channel]]->status = DRQ_STAT | DSC_STAT | DRDY_STAT; cdrom[atapi_cdrom_drives[ide->channel]]->pos = 0; - } - else - { - ide->atastat = DRQ_STAT | DSC_STAT | READY_STAT; + } else { + ide->atastat = DRQ_STAT | DSC_STAT | DRDY_STAT; ide->pos=0; } return; case WIN_WRITE_DMA: case WIN_WRITE_DMA_ALT: - if (ide_drive_is_zip(ide)) - { - zip[atapi_zip_drives[ide->channel]].status = BUSY_STAT; - } - else if (ide_drive_is_cdrom(ide)) - { - cdrom[atapi_cdrom_drives[ide->channel]]->status = BUSY_STAT; - } - else - { - ide->atastat = BUSY_STAT; - } - timer_process(); - if (ide_drive_is_zip(ide)) - { - zip[atapi_zip_drives[ide->channel]].callback = 200LL*IDE_TIME; - } - else if (ide_drive_is_cdrom(ide)) - { - cdrom[atapi_cdrom_drives[ide->channel]]->callback = 200LL*IDE_TIME; - } - idecallback[ide_board]=200LL*IDE_TIME; - timer_update_outstanding(); - return; - case WIN_VERIFY: case WIN_VERIFY_ONCE: + case WIN_IDENTIFY: /* Identify Device */ + case WIN_SET_FEATURES: /* Set Features */ + case WIN_READ_NATIVE_MAX: if (ide_drive_is_zip(ide)) - { - zip[atapi_zip_drives[ide->channel]].status = BUSY_STAT; - } + zip[atapi_zip_drives[ide->channel]]->status = BSY_STAT; else if (ide_drive_is_cdrom(ide)) - { - cdrom[atapi_cdrom_drives[ide->channel]]->status = BUSY_STAT; - } + cdrom[atapi_cdrom_drives[ide->channel]]->status = BSY_STAT; else - { - ide->atastat = BUSY_STAT; - } + ide->atastat = BSY_STAT; timer_process(); + if (ide_drive_is_zip(ide)) - { - zip[atapi_zip_drives[ide->channel]].callback = 200LL*IDE_TIME; - } + zip[atapi_zip_drives[ide->channel]]->callback = 200LL*IDE_TIME; else if (ide_drive_is_cdrom(ide)) - { cdrom[atapi_cdrom_drives[ide->channel]]->callback = 200LL*IDE_TIME; - } - idecallback[ide_board]=200LL*IDE_TIME; + if ((ide->type == IDE_HDD) && + ((val == WIN_WRITE_DMA) || (val == WIN_WRITE_DMA_ALT))) { + if (ide->secount) + ide_set_callback(ide->board, ide_get_period(ide, (int) ide->secount << 9)); + else + ide_set_callback(ide->board, ide_get_period(ide, 131072)); + } else if ((ide->type == IDE_HDD) && + ((val == WIN_VERIFY) || (val == WIN_VERIFY_ONCE))) + ide_set_callback(ide->board, ide_get_period(ide, 512)); + else + ide_set_callback(ide->board, 200LL * IDE_TIME); timer_update_outstanding(); return; case WIN_FORMAT: if (ide_drive_is_zip(ide) || ide_drive_is_cdrom(ide)) - { goto ide_bad_command; - } - else - { + else { ide->atastat = DRQ_STAT; ide->pos=0; } @@ -1484,51 +1607,42 @@ void writeide(int ide_board, uint16_t addr, uint8_t val) case WIN_SPECIFY: /* Initialize Drive Parameters */ if (ide_drive_is_zip(ide)) - { - zip[atapi_zip_drives[ide->channel]].status = BUSY_STAT; - } + zip[atapi_zip_drives[ide->channel]]->status = BSY_STAT; else if (ide_drive_is_cdrom(ide)) - { - cdrom[atapi_cdrom_drives[ide->channel]]->status = BUSY_STAT; - } + cdrom[atapi_cdrom_drives[ide->channel]]->status = BSY_STAT; else - { - ide->atastat = BUSY_STAT; - } + ide->atastat = BSY_STAT; timer_process(); + if (ide_drive_is_zip(ide)) - { - zip[atapi_zip_drives[ide->channel]].callback = 30LL*IDE_TIME; - } + zip[atapi_zip_drives[ide->channel]]->callback = 30LL*IDE_TIME; else if (ide_drive_is_cdrom(ide)) - { cdrom[atapi_cdrom_drives[ide->channel]]->callback = 30LL*IDE_TIME; - } - idecallback[ide_board]=30LL*IDE_TIME; + ide_set_callback(ide->board, 30LL * IDE_TIME); timer_update_outstanding(); return; case WIN_DRIVE_DIAGNOSTICS: /* Execute Drive Diagnostics */ if (ide_drive_is_zip(ide)) - zip[atapi_zip_drives[ide->channel]].status = BUSY_STAT; + zip[atapi_zip_drives[ide->channel]]->status = BSY_STAT; else if (ide_drive_is_cdrom(ide)) - cdrom[atapi_cdrom_drives[ide->channel]]->status = BUSY_STAT; + cdrom[atapi_cdrom_drives[ide->channel]]->status = BSY_STAT; else - ide->atastat = BUSY_STAT; + ide->atastat = BSY_STAT; if (ide_drive_is_zip(ide_other)) - zip[atapi_zip_drives[ide_other->channel]].status = BUSY_STAT; + zip[atapi_zip_drives[ide_other->channel]]->status = BSY_STAT; else if (ide_drive_is_cdrom(ide_other)) - cdrom[atapi_cdrom_drives[ide_other->channel]]->status = BUSY_STAT; + cdrom[atapi_cdrom_drives[ide_other->channel]]->status = BSY_STAT; else - ide_other->atastat = BUSY_STAT; + ide_other->atastat = BSY_STAT; timer_process(); if (ide_drive_is_zip(ide)) - zip[atapi_zip_drives[ide->channel]].callback = 200LL * IDE_TIME; + zip[atapi_zip_drives[ide->channel]]->callback = 200LL * IDE_TIME; else if (ide_drive_is_cdrom(ide)) cdrom[atapi_cdrom_drives[ide->channel]]->callback = 200LL * IDE_TIME; - idecallback[ide_board] = 200LL * IDE_TIME; + ide_set_callback(ide->board, 200LL * IDE_TIME); timer_update_outstanding(); return; @@ -1541,66 +1655,33 @@ void writeide(int ide_board, uint16_t addr, uint8_t val) case WIN_CHECKPOWERMODE1: case WIN_SLEEP1: if (ide_drive_is_zip(ide)) - zip[atapi_zip_drives[ide->channel]].status = BUSY_STAT; + zip[atapi_zip_drives[ide->channel]]->status = BSY_STAT; else if (ide_drive_is_cdrom(ide)) - cdrom[atapi_cdrom_drives[ide->channel]]->status = BUSY_STAT; + cdrom[atapi_cdrom_drives[ide->channel]]->status = BSY_STAT; else - ide->atastat = BUSY_STAT; + ide->atastat = BSY_STAT; timer_process(); - callbackide(ide_board); - timer_update_outstanding(); - return; - - case WIN_IDENTIFY: /* Identify Device */ - case WIN_SET_FEATURES: /* Set Features */ - case WIN_READ_NATIVE_MAX: - if (ide_drive_is_zip(ide)) - { - zip[atapi_zip_drives[ide->channel]].status = BUSY_STAT; - } - else if (ide_drive_is_cdrom(ide)) - { - cdrom[atapi_cdrom_drives[ide->channel]]->status = BUSY_STAT; - } - else - { - ide->atastat = BUSY_STAT; - } - timer_process(); - if (ide_drive_is_zip(ide)) - { - zip[atapi_zip_drives[ide->channel]].callback = 200LL*IDE_TIME; - } - else if (ide_drive_is_cdrom(ide)) - { - cdrom[atapi_cdrom_drives[ide->channel]]->callback = 200LL*IDE_TIME; - } - idecallback[ide_board]=200LL*IDE_TIME; + ide_callback(dev); timer_update_outstanding(); return; case WIN_PACKETCMD: /* ATAPI Packet */ /* Skip the command callback wait, and process immediately. */ - if (ide_drive_is_zip(ide)) - { - zip[atapi_zip_drives[ide->channel]].packet_status = ZIP_PHASE_IDLE; - zip[atapi_zip_drives[ide->channel]].pos=0; - zip[atapi_zip_drives[ide->channel]].phase = 1; - zip[atapi_zip_drives[ide->channel]].status = READY_STAT | DRQ_STAT; - ide_irq_raise(ide); /* Interrupt IRQ, requires IRQ on any DRQ. */ - } - else if (ide_drive_is_cdrom(ide)) - { + if (ide_drive_is_zip(ide)) { + zip[atapi_zip_drives[ide->channel]]->packet_status = ZIP_PHASE_IDLE; + zip[atapi_zip_drives[ide->channel]]->pos=0; + zip[atapi_zip_drives[ide->channel]]->phase = 1; + zip[atapi_zip_drives[ide->channel]]->status = DRDY_STAT | DRQ_STAT; + ide_irq_raise(ide); /* Interrupt DRQ, requires IRQ on any DRQ. */ + } else if (ide_drive_is_cdrom(ide)) { cdrom[atapi_cdrom_drives[ide->channel]]->packet_status = CDROM_PHASE_IDLE; cdrom[atapi_cdrom_drives[ide->channel]]->pos=0; cdrom[atapi_cdrom_drives[ide->channel]]->phase = 1; - cdrom[atapi_cdrom_drives[ide->channel]]->status = READY_STAT | DRQ_STAT; - } - else - { - ide->atastat = BUSY_STAT; + cdrom[atapi_cdrom_drives[ide->channel]]->status = DRDY_STAT | DRQ_STAT; + } else { + ide->atastat = BSY_STAT; timer_process(); - idecallback[ide_board]=200LL*IDE_TIME; + ide_set_callback(ide->board, 200LL * IDE_TIME); timer_update_outstanding(); ide->pos=0; } @@ -1609,1372 +1690,1088 @@ void writeide(int ide_board, uint16_t addr, uint8_t val) case 0xF0: default: ide_bad_command: - if (ide_drive_is_zip(ide)) - { - zip[atapi_zip_drives[ide->channel]].status = READY_STAT | ERR_STAT | DSC_STAT; - zip[atapi_zip_drives[ide->channel]].error = ABRT_ERR; - } - else if (ide_drive_is_cdrom(ide)) - { - cdrom[atapi_cdrom_drives[ide->channel]]->status = READY_STAT | ERR_STAT | DSC_STAT; + if (ide_drive_is_zip(ide)) { + zip[atapi_zip_drives[ide->channel]]->status = DRDY_STAT | ERR_STAT | DSC_STAT; + zip[atapi_zip_drives[ide->channel]]->error = ABRT_ERR; + } else if (ide_drive_is_cdrom(ide)) { + cdrom[atapi_cdrom_drives[ide->channel]]->status = DRDY_STAT | ERR_STAT | DSC_STAT; cdrom[atapi_cdrom_drives[ide->channel]]->error = ABRT_ERR; - } - else - { - ide->atastat = READY_STAT | ERR_STAT | DSC_STAT; + } else { + ide->atastat = DRDY_STAT | ERR_STAT | DSC_STAT; ide->error = ABRT_ERR; } ide_irq_raise(ide); return; } return; - - case 0x3F6: /* Device control */ - if ((ide->fdisk & 4) && !(val&4) && (ide->type != IDE_NONE || ide_other->type != IDE_NONE)) - { - timer_process(); - if (ide_drive_is_zip(ide)) - { - zip[atapi_zip_drives[ide->channel]].callback = 0LL; - } - else if (ide_drive_is_cdrom(ide)) - { - cdrom[atapi_cdrom_drives[ide->channel]]->callback = 0LL; - } - idecallback[ide_board]=500LL*IDE_TIME; - timer_update_outstanding(); - - if (ide->type != IDE_NONE) - { - ide->reset = 1; - } - if (ide_other->type != IDE_NONE) - { - ide->reset = 1; - } - if (ide_drive_is_zip(ide)) - { - zip[atapi_zip_drives[ide->channel]].status = BUSY_STAT; - } - else if (ide_drive_is_cdrom(ide)) - { - cdrom[atapi_cdrom_drives[ide->channel]]->status = BUSY_STAT; - } - ide->atastat = ide_other->atastat = BUSY_STAT; - } - if (val & 4) - { - /*Drive held in reset*/ - timer_process(); - idecallback[ide_board] = 0LL; - timer_update_outstanding(); - ide->atastat = ide_other->atastat = BUSY_STAT; - } - ide->fdisk = ide_other->fdisk = val; - return; - } + } } -uint32_t ide_read_data(int ide_board, int length) + +static uint32_t +ide_read_data(ide_t *ide, int length) { - IDE *ide = &ide_drives[cur_ide[ide_board]]; - uint32_t temp; + int ch = ide->channel; + uint32_t temp; - if (!ide->buffer) { - switch (length) - { - case 1: - return 0xff; - case 2: - return 0xffff; - case 4: - return 0xffffffff; - default: - return 0; - } - } + if (!ide->buffer) { + switch (length) { + case 1: + return 0xff; - uint8_t *idebufferb = (uint8_t *) ide->buffer; - uint16_t *idebufferw = ide->buffer; - uint32_t *idebufferl = (uint32_t *) ide->buffer; - - if (ide->command == WIN_PACKETCMD) - { - ide->pos = 0; - if (!ide_drive_is_zip(ide) && !ide_drive_is_cdrom(ide)) - { -#ifdef ENABLE_HDC_LOG - hdc_log("Drive not ZIP or CD-ROM (position: %i)\n", ide->pos); -#endif + case 2: + return 0xffff; + + case 4: + return 0xffffffff; + + default: return 0; - } - if (ide_drive_is_zip(ide)) - temp = zip_read(cur_ide[ide_board], length); - else - temp = cdrom_read(cur_ide[ide_board], length); } + } + + uint8_t *idebufferb = (uint8_t *) ide->buffer; + uint16_t *idebufferw = ide->buffer; + uint32_t *idebufferl = (uint32_t *) ide->buffer; + + if (ide->command == WIN_PACKETCMD) { + ide->pos = 0; + if (!ide_drive_is_zip(ide) && !ide_drive_is_cdrom(ide)) { + DEBUG("Drive not ZIP or CD-ROM (position: %i)\n", ide->pos); + return 0; + } + if (ide_drive_is_zip(ide)) + temp = zip_read(ch, length); else - { - switch (length) - { - case 1: - temp = idebufferb[ide->pos]; - ide->pos++; - break; - case 2: - temp = idebufferw[ide->pos >> 1]; - ide->pos += 2; - break; - case 4: - temp = idebufferl[ide->pos >> 2]; - ide->pos += 4; - break; - default: - return 0; - } - } - if (ide->pos>=512 && ide->command != WIN_PACKETCMD) - { - ide->pos=0; - ide->atastat = READY_STAT | DSC_STAT; - if (ide_drive_is_zip(ide)) - { - zip[atapi_zip_drives[cur_ide[ide_board]]].status = READY_STAT | DSC_STAT; - zip[atapi_zip_drives[cur_ide[ide_board]]].packet_status = ZIP_PHASE_IDLE; - } - else if (ide_drive_is_cdrom(ide)) - { - cdrom[atapi_cdrom_drives[cur_ide[ide_board]]]->status = READY_STAT | DSC_STAT; - cdrom[atapi_cdrom_drives[cur_ide[ide_board]]]->packet_status = CDROM_PHASE_IDLE; - } - if (ide->command == WIN_READ || ide->command == WIN_READ_NORETRY || ide->command == WIN_READ_MULTIPLE) - { - ide->secount = (ide->secount - 1) & 0xff; - if (ide->secount) - { - ide_next_sector(ide); - ide->atastat = BUSY_STAT; - timer_process(); - if (ide->command == WIN_READ_MULTIPLE) - { - callbackide(ide_board); - } - else - { - idecallback[ide_board]=6LL*IDE_TIME; - } - timer_update_outstanding(); - } - else - { - ui_sb_icon_update(SB_HDD | hdd[ide->hdd_num].bus, 0); - } - } - } - - return temp; -} - -uint8_t readide(int ide_board, uint16_t addr) -{ - IDE *ide = &ide_drives[cur_ide[ide_board]]; - uint8_t temp; - uint16_t tempw; - - addr |= 0x90; - addr &= 0xFFF7; - - switch (addr) - { - case 0x1F0: /* Data */ - tempw = readidew(ide_board); - temp = tempw & 0xff; + temp = cdrom_read(ch, length); + } else { + switch (length) { + case 1: + temp = idebufferb[ide->pos]; + ide->pos++; break; - /* For ATAPI: Bits 7-4 = sense key, bit 3 = MCR (media change requested), - Bit 2 = ABRT (aborted command), Bit 1 = EOM (end of media), - and Bit 0 = ILI (illegal length indication). */ - case 0x1F1: /* Error */ - if (ide->type == IDE_NONE) - { - temp = 0; - } - else - { - if (ide_drive_is_zip(ide)) - { - temp = zip[atapi_zip_drives[cur_ide[ide_board]]].error; - } - else if (ide_drive_is_cdrom(ide)) - { - temp = cdrom[atapi_cdrom_drives[cur_ide[ide_board]]]->error; - } - else - { - temp = ide->error; - } - } + case 2: + temp = idebufferw[ide->pos >> 1]; + ide->pos += 2; break; - /* For ATAPI: - Bit 0: Command or Data: - Data if clear, Command if set; - Bit 1: I/OB - Direction: - To device if set; - From device if clear. - IO DRQ CoD - 0 1 1 Ready to accept command packet - 1 1 1 Message - ready to send message to host - 1 1 0 Data to host - 0 1 0 Data from host - 1 0 1 Status. */ - case 0x1F2: /* Sector count */ - if (ide_drive_is_zip(ide)) - { - temp = zip[atapi_zip_drives[cur_ide[ide_board]]].phase; - } - else if (ide_drive_is_cdrom(ide)) - { - temp = cdrom[atapi_cdrom_drives[cur_ide[ide_board]]]->phase; - } - else - { - temp = ide->secount; - } - break; - - case 0x1F3: /* Sector */ - temp = (uint8_t)ide->sector; - break; - - case 0x1F4: /* Cylinder low */ - if (ide->type == IDE_NONE) - { - temp = 0xFF; - } - else - { - if (ide_drive_is_zip(ide)) - { - temp = zip[atapi_zip_drives[cur_ide[ide_board]]].request_length & 0xff; - } - else if (ide_drive_is_cdrom(ide)) - { - temp = cdrom[atapi_cdrom_drives[cur_ide[ide_board]]]->request_length & 0xff; - } - else - { - temp = ide->cylinder & 0xff; - } - } - break; - - case 0x1F5: /* Cylinder high */ - if (ide->type == IDE_NONE) - { - temp = 0xFF; - } - else - { - if (ide_drive_is_zip(ide)) - { - temp = zip[atapi_zip_drives[cur_ide[ide_board]]].request_length >> 8; - } - else if (ide_drive_is_cdrom(ide)) - { - temp = cdrom[atapi_cdrom_drives[cur_ide[ide_board]]]->request_length >> 8; - } - else - { - temp = ide->cylinder >> 8; - } - } - break; - - case 0x1F6: /* Drive/Head */ - temp = (uint8_t)(ide->head | ((cur_ide[ide_board] & 1) ? 0x10 : 0) | (ide->lba ? 0x40 : 0) | 0xa0); - break; - - /* For ATAPI: Bit 5 is DMA ready, but without overlapped or interlaved DMA, it is - DF (drive fault). */ - case 0x1F7: /* Status */ - ide_irq_lower(ide); - if (ide->type == IDE_NONE) - { - temp = 0; - } - else - { - if (ide_drive_is_zip(ide)) - { - temp = (zip[atapi_zip_drives[cur_ide[ide_board]]].status & ~DSC_STAT) | (ide->service ? SERVICE_STAT : 0); - } - else if (ide_drive_is_cdrom(ide)) - { - temp = (cdrom[atapi_cdrom_drives[cur_ide[ide_board]]]->status & ~DSC_STAT) | (ide->service ? SERVICE_STAT : 0); - } - else - { - temp = ide->atastat; - } - } - break; - - case 0x3F6: /* Alternate Status */ - if (ide->type == IDE_NONE) - { - temp = 0; - } - else - { - if (ide_drive_is_zip(ide)) - { - temp = (zip[atapi_zip_drives[cur_ide[ide_board]]].status & ~DSC_STAT) | (ide->service ? SERVICE_STAT : 0); - } - else if (ide_drive_is_cdrom(ide)) - { - temp = (cdrom[atapi_cdrom_drives[cur_ide[ide_board]]]->status & ~DSC_STAT) | (ide->service ? SERVICE_STAT : 0); - } - else - { - temp = ide->atastat; - } - } + case 4: + temp = idebufferl[ide->pos >> 2]; + ide->pos += 4; break; default: - temp = 0xff; - break; + return 0; } -#ifdef ENABLE_HDC_LOG - /* if (ide_board) */ hdc_log("Read IDEb %04X %02X %02X %02X %i %04X:%04X %i\n", addr, temp, ide->atastat,(ide->atastat & ~DSC_STAT) | (ide->service ? SERVICE_STAT : 0),cur_ide[ide_board],CS,cpu_state.pc,ide_board); -#endif - return temp; + } + + if (ide->pos>=512 && ide->command != WIN_PACKETCMD) { + ide->pos=0; + ide->atastat = DRDY_STAT | DSC_STAT; + + if (ide_drive_is_zip(ide)) { + zip[atapi_zip_drives[ch]]->status = DRDY_STAT | DSC_STAT; + zip[atapi_zip_drives[ch]]->packet_status = ZIP_PHASE_IDLE; + } else if (ide_drive_is_cdrom(ide)) { + cdrom[atapi_cdrom_drives[ch]]->status = DRDY_STAT | DSC_STAT; + cdrom[atapi_cdrom_drives[ch]]->packet_status = CDROM_PHASE_IDLE; + } + + if (ide->command == WIN_READ || ide->command == WIN_READ_NORETRY || ide->command == WIN_READ_MULTIPLE) { + ide->secount = (ide->secount - 1) & 0xff; + if (ide->secount) { + ide_next_sector(ide); + ide->atastat = BSY_STAT; + timer_process(); + if (ide->command == WIN_READ_MULTIPLE) + ide_callback(ide_boards[ide->board]); + else + ide_set_callback(ide->board, ide_get_period(ide, 512)); + timer_update_outstanding(); + } else { + if (ide->command != WIN_READ_MULTIPLE) + hdd_active(ide->hdd_num, 0); + } + } + } + + return temp; } -uint8_t cdb[16]; -int old_len = 0; - -int total_read = 0; - -int block_total = 0; -int all_blocks_total = 0; - -uint16_t readidew(int ide_board) +static uint8_t +ide_status(ide_t *ide, int ch) { - return ide_read_data(ide_board, 2); -} - -uint32_t readidel(int ide_board) -{ - uint16_t temp; - temp = readidew(ide_board); - return temp | (readidew(ide_board) << 16); -} - -int times30=0; -void callbackide(int ide_board) -{ - IDE *ide, *ide_other; - int64_t snum; - int cdrom_id; - int cdrom_id_other; - int zip_id; - int zip_id_other; - uint64_t full_size = 0; - - ide = &ide_drives[cur_ide[ide_board]]; - ide_other = &ide_drives[cur_ide[ide_board] ^ 1]; - if (ide->type == IDE_HDD) - { - full_size = (hdd[ide->hdd_num].tracks * hdd[ide->hdd_num].hpc * hdd[ide->hdd_num].spt); - } - ext_ide = ide; - - if (ide->command==0x30) times30++; -#ifdef ENABLE_HDC_LOG - /*if (ide_board) */hdc_log("CALLBACK %02X %i %i %i\n",ide->command,times30,ide->reset,cur_ide[ide_board]); -#endif - - if (ide->reset) - { - ide->atastat = ide_other->atastat = READY_STAT | DSC_STAT; - ide->error = ide_other->error = 1; - ide->secount = ide_other->secount = 1; - ide->sector = ide_other->sector = 1; - ide->head = ide_other->head = 0; - ide->cylinder = ide_other->cylinder = 0; - ide->reset = ide_other->reset = 0; - - if (ide_drive_is_zip(ide)) - { - zip_id = atapi_zip_drives[cur_ide[ide_board]]; - zip[zip_id].status = READY_STAT | DSC_STAT; - zip[zip_id].error = 1; - zip[zip_id].phase = 1; - zip[zip_id].request_length=0xEB14; - ide->cylinder = 0xEB14; - } - else if (ide_drive_is_cdrom(ide)) - { - cdrom_id = atapi_cdrom_drives[cur_ide[ide_board]]; - cdrom[cdrom_id]->status = READY_STAT | DSC_STAT; - cdrom[cdrom_id]->error = 1; - cdrom[cdrom_id]->phase = 1; - cdrom[cdrom_id]->request_length=0xEB14; - ide->cylinder = 0xEB14; - if (cdrom_drives[cdrom_id].handler->stop) - { - cdrom_drives[cdrom_id].handler->stop(cdrom_id); - } - } - if (ide->type == IDE_NONE) - { - ide->cylinder=0xFFFF; - } - if (ide_drive_is_zip(ide_other)) - { - zip_id_other = atapi_zip_drives[cur_ide[ide_board] ^ 1]; - zip[zip_id_other].status = READY_STAT | DSC_STAT; - zip[zip_id_other].error = 1; - zip[zip_id_other].phase = 1; - zip[zip_id_other].request_length=0xEB14; - ide->cylinder = 0xEB14; - } - else if (ide_drive_is_cdrom(ide_other)) - { - cdrom_id_other = atapi_cdrom_drives[cur_ide[ide_board] ^ 1]; - cdrom[cdrom_id_other]->status = READY_STAT | DSC_STAT; - cdrom[cdrom_id_other]->error = 1; - cdrom[cdrom_id_other]->phase = 1; - cdrom[cdrom_id_other]->request_length=0xEB14; - ide_other->cylinder = 0xEB14; - if (cdrom_drives[cdrom_id_other].handler->stop) - { - cdrom_drives[cdrom_id_other].handler->stop(cdrom_id_other); - } - } - if (ide_other->type == IDE_NONE) - { - ide_other->cylinder=0xFFFF; - } - return; - } - - cdrom_id = atapi_cdrom_drives[cur_ide[ide_board]]; - cdrom_id_other = atapi_cdrom_drives[cur_ide[ide_board] ^ 1]; - - zip_id = atapi_zip_drives[cur_ide[ide_board]]; - zip_id_other = atapi_zip_drives[cur_ide[ide_board] ^ 1]; - - if (((ide->command >= WIN_RESTORE) && (ide->command <= 0x1F)) || ((ide->command >= WIN_SEEK) && (ide->command <= 0x7F))) - { - if (ide_drive_is_zip(ide) || ide_drive_is_cdrom(ide)) - { - goto abort_cmd; - } - if ((ide->command >= WIN_SEEK) && (ide->command <= 0x7F)) - { - full_size /= ide->t_hpc; - full_size /= ide->t_spt; - - if ((ide->cylinder >= full_size) || (ide->head >= ide->t_hpc) || !ide->sector || (ide->sector > ide->t_spt)) - goto id_not_found; - } - ide->atastat = READY_STAT | DSC_STAT; - ide_irq_raise(ide); - return; - } - switch (ide->command) - { - /* Initialize the Task File Registers as follows: Status = 00h, Error = 01h, Sector Count = 01h, Sector Number = 01h, - Cylinder Low = 14h, Cylinder High =EBh and Drive/Head = 00h. */ - case WIN_SRST: /*ATAPI Device Reset */ - ide->atastat = READY_STAT | DSC_STAT; - ide->error=1; /*Device passed*/ - ide->secount = ide->sector = 1; - ide_set_signature(ide); - - if (ide_drive_is_zip(ide)) - { - zip[zip_id].status = READY_STAT | DSC_STAT; - zip[zip_id].error = 1; - zip[zip_id].phase = 1; - zip_reset(zip_id); - } - else if (ide_drive_is_cdrom(ide)) - { - cdrom[cdrom_id]->status = READY_STAT | DSC_STAT; - cdrom[cdrom_id]->error = 1; - cdrom[cdrom_id]->phase = 1; - cdrom_reset(cdrom_id); - } - ide_irq_raise(ide); - if (ide_drive_is_zip(ide) || ide_drive_is_cdrom(ide)) - { - ide->service = 0; - } - return; - - case WIN_NOP: - case WIN_STANDBYNOW1: - case WIN_IDLENOW1: - case WIN_SETIDLE1: - if (ide_drive_is_zip(ide)) - { - zip[zip_id].status = READY_STAT | DSC_STAT; - } - else if (ide_drive_is_cdrom(ide)) - { - cdrom[cdrom_id]->status = READY_STAT | DSC_STAT; - } - else - { - ide->atastat = READY_STAT | DSC_STAT; - } - ide_irq_raise(ide); - return; - - case WIN_CHECKPOWERMODE1: - case WIN_SLEEP1: - if (ide_drive_is_zip(ide)) - { - zip[zip_id].phase = 0xFF; - zip[zip_id].status = READY_STAT | DSC_STAT; - } - else if (ide_drive_is_cdrom(ide)) - { - cdrom[cdrom_id]->phase = 0xFF; - cdrom[cdrom_id]->status = READY_STAT | DSC_STAT; - } - ide->secount = 0xFF; - ide->atastat = READY_STAT | DSC_STAT; - ide_irq_raise(ide); - return; - - case WIN_READ: - case WIN_READ_NORETRY: - if (ide_drive_is_zip(ide) || ide_drive_is_cdrom(ide)) - { - ide_set_signature(ide); - goto abort_cmd; - } - if (!ide->specify_success) - { - goto id_not_found; - } - - if (ide->do_initial_read) - { - ide->do_initial_read = 0; - ide->sector_pos = 0; - if (ide->secount) - { - hdd_image_read(ide->hdd_num, ide_get_sector(ide), ide->secount, ide->sector_buffer); - } - else - { - hdd_image_read(ide->hdd_num, ide_get_sector(ide), 256, ide->sector_buffer); - } - } - - memcpy(ide->buffer, &ide->sector_buffer[ide->sector_pos*512], 512); - - ide->sector_pos++; - ide->pos=0; - - ide->atastat = DRQ_STAT | READY_STAT | DSC_STAT; - - ide_irq_raise(ide); - - ui_sb_icon_update(SB_HDD | hdd[ide->hdd_num].bus, 1); - return; - - case WIN_READ_DMA: - case WIN_READ_DMA_ALT: - if (ide_drive_is_zip(ide) || ide_drive_is_cdrom(ide) || (ide->board >= 2)) - { -#ifdef ENABLE_HDC_LOG - hdc_log("IDE %i: DMA read aborted (bad device or board)\n", ide->channel); -#endif - goto abort_cmd; - } - if (!ide->specify_success) - { -#ifdef ENABLE_HDC_LOG - hdc_log("IDE %i: DMA read aborted (SPECIFY failed)\n", ide->channel); -#endif - goto id_not_found; - } - - ide->sector_pos = 0; - if (ide->secount) - { - ide->sector_pos = ide->secount; - } - else - { - ide->sector_pos = 256; - } - hdd_image_read(ide->hdd_num, ide_get_sector(ide), ide->sector_pos, ide->sector_buffer); - - ide->pos=0; - - if (ide_bus_master_read) - { - if (ide_bus_master_read(ide_board, ide->sector_buffer, ide->sector_pos * 512)) - { -#ifdef ENABLE_HDC_LOG - hdc_log("IDE %i: DMA read aborted (failed)\n", ide->channel); -#endif - goto abort_cmd; - } - else - { - /*DMA successful*/ -#ifdef ENABLE_HDC_LOG - hdc_log("IDE %i: DMA read successful\n", ide->channel); -#endif - - ide->atastat = READY_STAT | DSC_STAT; - - ide_irq_raise(ide); - ui_sb_icon_update(SB_HDD | hdd[ide->hdd_num].bus, 0); - } - } else { -#ifdef ENABLE_HDC_LOG - hdc_log("IDE %i: DMA read aborted (no bus master)\n", ide->channel); -#endif - goto abort_cmd; - } - - return; - - case WIN_READ_MULTIPLE: - /* According to the official ATA reference: - - If the Read Multiple command is attempted before the Set Multiple Mode - command has been executed or when Read Multiple commands are - disabled, the Read Multiple operation is rejected with an Aborted Com- - mand error. */ - if (ide_drive_is_zip(ide) || ide_drive_is_cdrom(ide) || !ide->blocksize) - { - goto abort_cmd; - } - if (!ide->specify_success) - { - goto id_not_found; - } - - if (ide->do_initial_read) - { - ide->do_initial_read = 0; - ide->sector_pos = 0; - if (ide->secount) - { - hdd_image_read(ide->hdd_num, ide_get_sector(ide), ide->secount, ide->sector_buffer); - } - else - { - hdd_image_read(ide->hdd_num, ide_get_sector(ide), 256, ide->sector_buffer); - } - } - - memcpy(ide->buffer, &ide->sector_buffer[ide->sector_pos*512], 512); - - ide->sector_pos++; - ide->pos=0; - - ide->atastat = DRQ_STAT | READY_STAT | DSC_STAT; - if (!ide->blockcount) - { - ide_irq_raise(ide); - } - ide->blockcount++; - if (ide->blockcount >= ide->blocksize) - { - ide->blockcount = 0; - } - - ui_sb_icon_update(SB_HDD | hdd[ide->hdd_num].bus, 1); - return; - - case WIN_WRITE: - case WIN_WRITE_NORETRY: - if (ide_drive_is_zip(ide) || ide_drive_is_cdrom(ide)) - { - goto abort_cmd; - } - if (!ide->specify_success) - { - goto id_not_found; - } - hdd_image_write(ide->hdd_num, ide_get_sector(ide), 1, (uint8_t *) ide->buffer); - ide_irq_raise(ide); - ide->secount = (ide->secount - 1) & 0xff; - if (ide->secount) - { - ide->atastat = DRQ_STAT | READY_STAT | DSC_STAT; - ide->pos=0; - ide_next_sector(ide); - ui_sb_icon_update(SB_HDD | hdd[ide->hdd_num].bus, 1); - } - else - { - ide->atastat = READY_STAT | DSC_STAT; - ui_sb_icon_update(SB_HDD | hdd[ide->hdd_num].bus, 0); - } - - return; - - case WIN_WRITE_DMA: - case WIN_WRITE_DMA_ALT: - if (ide_drive_is_zip(ide) || ide_drive_is_cdrom(ide) || (ide_board >= 2)) - { -#ifdef ENABLE_HDC_LOG - hdc_log("IDE %i: DMA write aborted (bad device type or board)\n", ide->channel); -#endif - goto abort_cmd; - } - if (!ide->specify_success) - { -#ifdef ENABLE_HDC_LOG - hdc_log("IDE %i: DMA write aborted (SPECIFY failed)\n", ide->channel); -#endif - goto id_not_found; - } - - if (ide_bus_master_read) - { - if (ide->secount) - ide->sector_pos = ide->secount; - else - ide->sector_pos = 256; - - if (ide_bus_master_write(ide_board, ide->sector_buffer, ide->sector_pos * 512)) - { -#ifdef ENABLE_HDC_LOG - hdc_log("IDE %i: DMA write aborted (failed)\n", ide->channel); -#endif - goto abort_cmd; - } - else - { - /*DMA successful*/ -#ifdef ENABLE_HDC_LOG - hdc_log("IDE %i: DMA write successful\n", ide->channel); -#endif - - hdd_image_write(ide->hdd_num, ide_get_sector(ide), ide->sector_pos, ide->sector_buffer); - - ide->atastat = READY_STAT | DSC_STAT; - - ide_irq_raise(ide); - ui_sb_icon_update(SB_HDD | hdd[ide->hdd_num].bus, 0); - } - } else { -#ifdef ENABLE_HDC_LOG - hdc_log("IDE %i: DMA write aborted (no bus master)\n", ide->channel); -#endif - goto abort_cmd; - } - - return; - - case WIN_WRITE_MULTIPLE: - if (ide_drive_is_zip(ide) || ide_drive_is_cdrom(ide)) - { - goto abort_cmd; - } - if (!ide->specify_success) - { - goto id_not_found; - } - hdd_image_write(ide->hdd_num, ide_get_sector(ide), 1, (uint8_t *) ide->buffer); - ide->blockcount++; - if (ide->blockcount >= ide->blocksize || ide->secount == 1) - { - ide->blockcount = 0; - ide_irq_raise(ide); - } - ide->secount = (ide->secount - 1) & 0xff; - if (ide->secount) - { - ide->atastat = DRQ_STAT | READY_STAT | DSC_STAT; - ide->pos=0; - ide_next_sector(ide); - ui_sb_icon_update(SB_HDD | hdd[ide->hdd_num].bus, 1); - } - else - { - ide->atastat = READY_STAT | DSC_STAT; - ui_sb_icon_update(SB_HDD | hdd[ide->hdd_num].bus, 0); - } - return; - - case WIN_VERIFY: - case WIN_VERIFY_ONCE: - if (ide_drive_is_zip(ide) || ide_drive_is_cdrom(ide)) - { - goto abort_cmd; - } - if (!ide->specify_success) - { - goto id_not_found; - } - ide->pos=0; - ide->atastat = READY_STAT | DSC_STAT; - ide_irq_raise(ide); - ui_sb_icon_update(SB_HDD | hdd[ide->hdd_num].bus, 1); - return; - - case WIN_FORMAT: - if (ide_drive_is_zip(ide) || ide_drive_is_cdrom(ide)) - { - goto abort_cmd; - } - if (!ide->specify_success) - { - goto id_not_found; - } - hdd_image_zero(ide->hdd_num, ide_get_sector(ide), ide->secount); - - ide->atastat = READY_STAT | DSC_STAT; - ide_irq_raise(ide); - - /* ui_sb_icon_update(SB_HDD | hdd[ide->hdd_num].bus, 1); */ - return; - - case WIN_DRIVE_DIAGNOSTICS: - ide_set_signature(ide); - ide->error=1; /*No error detected*/ - - if (ide_drive_is_zip(ide)) - { - zip[zip_id].status = 0; - zip[zip_id].error = 1; - ide_irq_raise(ide); - } - else if (ide_drive_is_cdrom(ide)) - { - cdrom[cdrom_id]->status = 0; - cdrom[cdrom_id]->error = 1; - ide_irq_raise(ide); - } - else - { - ide->atastat = READY_STAT | DSC_STAT; - ide->error = 1; - ide_irq_raise(ide); - } - - ide_set_signature(ide_other); - ide_other->error=1; /*No error detected*/ - - if (ide_drive_is_zip(ide_other)) - { - zip[zip_id_other].status = 0; - zip[zip_id_other].error = 1; - } - else if (ide_drive_is_cdrom(ide_other)) - { - cdrom[cdrom_id_other]->status = 0; - cdrom[cdrom_id_other]->error = 1; - } - else - { - ide_other->atastat = READY_STAT | DSC_STAT; - ide_other->error = 1; - } - - cur_ide[ide_board] &= ~1; - return; - - case WIN_SPECIFY: /* Initialize Drive Parameters */ - if (ide_drive_is_zip(ide) || ide_drive_is_cdrom(ide)) - { - goto abort_cmd; - } - full_size /= (ide->head+1); - full_size /= ide->secount; - ide->specify_success = 1; - hdd_image_specify(ide->hdd_num, ide->head + 1, ide->secount); - ide->t_spt=ide->secount; - ide->t_hpc=ide->head; - ide->t_hpc++; - ide->atastat = READY_STAT | DSC_STAT; - ide_irq_raise(ide); - return; - - case WIN_PIDENTIFY: /* Identify Packet Device */ - if (ide_drive_is_zip(ide)) - { - ide_atapi_zip_identify(ide); - ide->pos = 0; - zip[zip_id].phase = 2; - zip[zip_id].pos = 0; - zip[zip_id].error = 0; - zip[zip_id].status = DRQ_STAT | READY_STAT | DSC_STAT; - ide_irq_raise(ide); - return; - } - else if (ide_drive_is_cdrom(ide)) - { - ide_atapi_identify(ide); - ide->pos = 0; - cdrom[cdrom_id]->phase = 2; - cdrom[cdrom_id]->pos = 0; - cdrom[cdrom_id]->error = 0; - cdrom[cdrom_id]->status = DRQ_STAT | READY_STAT | DSC_STAT; - ide_irq_raise(ide); - return; - } - goto abort_cmd; - - case WIN_SET_MULTIPLE_MODE: - if (ide_drive_is_zip(ide) || ide_drive_is_cdrom(ide)) - { - goto abort_cmd; - } - ide->blocksize = ide->secount; - ide->atastat = READY_STAT | DSC_STAT; - ide_irq_raise(ide); - return; - - case WIN_SET_FEATURES: - if (ide->type == IDE_NONE) - { - goto abort_cmd; - } - - if (!ide_set_features(ide)) - { - goto abort_cmd; - } - else - { - if (ide_drive_is_zip(ide)) { - zip[zip_id].status = READY_STAT | DSC_STAT; - zip[zip_id].pos = 0; - } - else if (ide_drive_is_cdrom(ide)) { - cdrom[cdrom_id]->status = READY_STAT | DSC_STAT; - cdrom[cdrom_id]->pos = 0; - } - ide->atastat = READY_STAT | DSC_STAT; - ide_irq_raise(ide); - } - return; - - case WIN_READ_NATIVE_MAX: - if (ide->type != IDE_HDD) - { - goto abort_cmd; - } - snum = hdd[ide->hdd_num].spt; - snum *= hdd[ide->hdd_num].hpc; - snum *= hdd[ide->hdd_num].tracks; - ide_set_sector(ide, (int)(snum - 1)); - ide->atastat = READY_STAT | DSC_STAT; - ide_irq_raise(ide); - return; - - case WIN_IDENTIFY: /* Identify Device */ - if (ide->type != IDE_HDD) - { - ide_set_signature(ide); - goto abort_cmd; - } - else - { - ide_identify(ide); - ide->pos=0; - ide->atastat = DRQ_STAT | READY_STAT | DSC_STAT; - ide_irq_raise(ide); - } - return; - - case WIN_PACKETCMD: /* ATAPI Packet */ - if (!ide_drive_is_zip(ide) && !ide_drive_is_cdrom(ide)) - { - goto abort_cmd; - } - - if (ide_drive_is_zip(ide)) - zip_phase_callback(atapi_zip_drives[cur_ide[ide_board]]); - else - cdrom_phase_callback(atapi_cdrom_drives[cur_ide[ide_board]]); -#ifdef ENABLE_HDC_LOG - hdc_log("IDE callback now: %i\n", idecallback[ide_board]); -#endif - return; - - case 0xFF: - goto abort_cmd; - } - -abort_cmd: - ide->command = 0; + if (ide->type == IDE_NONE) + return 0; + else { if (ide_drive_is_zip(ide)) - { - zip[zip_id].status = READY_STAT | ERR_STAT | DSC_STAT; - zip[zip_id].error = ABRT_ERR; - zip[zip_id].pos = 0; - } + return (zip[atapi_zip_drives[ch]]->status & ~DSC_STAT) | (ide->service ? SERVICE_STAT : 0); else if (ide_drive_is_cdrom(ide)) - { - cdrom[cdrom_id]->status = READY_STAT | ERR_STAT | DSC_STAT; - cdrom[cdrom_id]->error = ABRT_ERR; - cdrom[cdrom_id]->pos = 0; - } + return (cdrom[atapi_cdrom_drives[ch]]->status & ~DSC_STAT) | (ide->service ? SERVICE_STAT : 0); else - { - ide->atastat = READY_STAT | ERR_STAT | DSC_STAT; - ide->error = ABRT_ERR; - ide->pos = 0; + return ide->atastat; + } +} + + +uint8_t +ide_readb(uint16_t addr, void *priv) +{ + ide_board_t *dev = (ide_board_t *) priv; + uint8_t temp = 0xff; + uint16_t tempw; + ide_t *ide; + int ch; + + ch = dev->cur_dev; + ide = ide_drives[ch]; + + addr |= 0x90; + addr &= 0xFFF7; + + switch (addr & 0x7) { + case 0: /* Data */ + tempw = ide_read_data(ide, 2); + temp = tempw & 0xff; + break; + + /* For ATAPI: Bits 7-4 = sense key, bit 3 = MCR (media change requested), + Bit 2 = ABRT (aborted command), Bit 1 = EOM (end of media), + and Bit 0 = ILI (illegal length indication). */ + case 1: /* Error */ + if (ide->type == IDE_NONE) + temp = 0; + else { + if (ide_drive_is_zip(ide)) + temp = zip[atapi_zip_drives[ch]]->error; + else if (ide_drive_is_cdrom(ide)) + temp = cdrom[atapi_cdrom_drives[ch]]->error; + else + temp = ide->error; + } + break; + + /* For ATAPI: + Bit 0: Command or Data: + Data if clear, Command if set; + Bit 1: I/OB + Direction: + To device if set; + From device if clear. + IO DRQ CoD + 0 1 1 Ready to accept command packet + 1 1 1 Message - ready to send message to host + 1 1 0 Data to host + 0 1 0 Data from host + 1 0 1 Status. */ + case 2: /* Sector count */ + if (ide_drive_is_zip(ide)) + temp = zip[atapi_zip_drives[ch]]->phase; + else if (ide_drive_is_cdrom(ide)) + temp = cdrom[atapi_cdrom_drives[ch]]->phase; + else + temp = ide->secount; + break; + + case 3: /* Sector */ + temp = (uint8_t)ide->sector; + break; + + case 4: /* Cylinder low */ + if (ide->type == IDE_NONE) + temp = 0xFF; + else { + if (ide_drive_is_zip(ide)) + temp = zip[atapi_zip_drives[ch]]->request_length & 0xff; + else if (ide_drive_is_cdrom(ide)) + temp = cdrom[atapi_cdrom_drives[ch]]->request_length & 0xff; + else + temp = ide->cylinder & 0xff; + } + break; + + case 5: /* Cylinder high */ + if (ide->type == IDE_NONE) + temp = 0xFF; + else { + if (ide_drive_is_zip(ide)) + temp = zip[atapi_zip_drives[ch]]->request_length >> 8; + else if (ide_drive_is_cdrom(ide)) + temp = cdrom[atapi_cdrom_drives[ch]]->request_length >> 8; + else + temp = ide->cylinder >> 8; + } + break; + + case 6: /* Drive/Head */ + temp = (uint8_t)(ide->head | ((ch & 1) ? 0x10 : 0) | (ide->lba ? 0x40 : 0) | 0xa0); + break; + + /* For ATAPI: Bit 5 is DMA ready, but without overlapped or interlaved DMA, it is + DF (drive fault). */ + case 7: /* Status */ + ide_irq_lower(ide); + temp = ide_status(ide, ch); + break; + } + + DBGLOG(2, "ide_readb(%04X, %08X) = %02X\n", addr, priv, temp); + + return temp; +} + + +uint8_t +ide_read_alt_status(uint16_t addr, void *priv) +{ + ide_board_t *dev = (ide_board_t *) priv; + uint8_t temp = 0xff; + ide_t *ide; + int ch; + + ch = dev->cur_dev; + ide = ide_drives[ch]; + + /* Per the Seagate ATA-3 specification: + Reading the alternate status does *NOT* clear the IRQ. */ + temp = ide_status(ide, ch); + + DBGLOG(2, "ide_read_alt_status(%04X, %08X) = %02X\n", addr, priv, temp); + + return temp; +} + + +uint16_t +ide_readw(uint16_t addr, void *priv) +{ + ide_board_t *dev = (ide_board_t *) priv; + uint16_t temp = 0xffff; + ide_t *ide; + int ch; + + ch = dev->cur_dev; + ide = ide_drives[ch]; + + switch (addr & 0x7) { + case 0x0: /* Data */ + temp = ide_read_data(ide, 2); + break; + + default: + break; + } + + DBGLOG(3, "ide_readw(%04X, %08X) = %04X\n", addr, priv, temp); + + return temp; +} + + +static uint32_t +ide_readl(uint16_t addr, void *priv) +{ + ide_board_t *dev = (ide_board_t *) priv; + uint32_t temp = 0xffffffff; + uint16_t temp2; + ide_t *ide; + int ch; + + ch = dev->cur_dev; + ide = ide_drives[ch]; + + switch (addr & 0x7) { + case 0x0: /* Data */ + temp2 = ide_read_data(ide, 2); + temp = temp2 | (ide_read_data(ide, 2) << 16); + break; + } + + DBGLOG(3, "ide_readl(%04X, %08X) = %04X\n", addr, priv, temp); + + return temp; +} + + +static void +ide_callback(void *priv) +{ + ide_board_t *dev = (ide_board_t *) priv; + ide_t *ide, *ide_other; + int snum, ret, ch; + int cdrom_id, cdrom_id_other; + int zip_id, zip_id_other; + + ch = dev->cur_dev; + ide = ide_drives[ch]; + ide_other = ide_drives[ch ^ 1]; + + ide_set_callback(ide->board, 0LL); + + if (ide->reset) { + DEBUG("CALLBACK RESET %i %i\n", ide->reset,ch); + + ide->atastat = ide_other->atastat = DRDY_STAT | DSC_STAT; + ide->error = ide_other->error = 1; + ide->secount = ide_other->secount = 1; + ide->sector = ide_other->sector = 1; + ide->head = ide_other->head = 0; + ide->cylinder = ide_other->cylinder = 0; + + // ide->cfg_spt = ide->cfg_hpc = 0; /* need new parameters (drive 0) */ + // ide_other->cfg_spt = ide_other->cfg_hpc = 0; /* need new parameters (drive 1) */ + + ide->reset = ide_other->reset = 0; + + ide_set_signature(ide); + if (ide_drive_is_zip(ide)) { + zip_id = atapi_zip_drives[ch]; + zip[zip_id]->status = DRDY_STAT | DSC_STAT; + zip[zip_id]->error = 1; + } else if (ide_drive_is_cdrom(ide)) { + cdrom_id = atapi_cdrom_drives[ch]; + cdrom[cdrom_id]->status = DRDY_STAT | DSC_STAT; + cdrom[cdrom_id]->error = 1; + if (cdrom[cdrom_id]->handler->stop) + cdrom[cdrom_id]->handler->stop(cdrom_id); } + + ide_set_signature(ide_other); + if (ide_drive_is_zip(ide_other)) { + zip_id_other = atapi_zip_drives[ch ^ 1]; + zip[zip_id_other]->status = DRDY_STAT | DSC_STAT; + zip[zip_id_other]->error = 1; + } else if (ide_drive_is_cdrom(ide_other)) { + cdrom_id_other = atapi_cdrom_drives[ch ^ 1]; + cdrom[cdrom_id_other]->status = DRDY_STAT | DSC_STAT; + cdrom[cdrom_id_other]->error = 1; + if (cdrom[cdrom_id_other]->handler->stop) + cdrom[cdrom_id_other]->handler->stop(cdrom_id_other); + } + + return; + } + + DEBUG("CALLBACK %02X %i %i\n", ide->command, ide->reset,ch); + + cdrom_id = atapi_cdrom_drives[ch]; + cdrom_id_other = atapi_cdrom_drives[ch ^ 1]; + + zip_id = atapi_zip_drives[ch]; + zip_id_other = atapi_zip_drives[ch ^ 1]; + + if (((ide->command >= WIN_RECAL) && (ide->command <= 0x1F)) || + ((ide->command >= WIN_SEEK) && (ide->command <= 0x7F))) { + if (ide->type != IDE_HDD) + goto abort_cmd; + if ((ide->command >= WIN_SEEK) && (ide->command <= 0x7F)) { + if ((ide->cylinder >= ide->tracks) || (ide->head >= ide->hpc) || + !ide->sector || (ide->sector > ide->spt)) + goto id_not_found; + } + ide->atastat = DRDY_STAT | DSC_STAT; ide_irq_raise(ide); return; + } + + switch (ide->command) { + /* Initialize the Task File Registers as follows: Status = 00h, Error = 01h, Sector Count = 01h, Sector Number = 01h, + Cylinder Low = 14h, Cylinder High =EBh and Drive/Head = 00h. */ + case WIN_SRST: /*ATAPI Device Reset */ + ide->atastat = DRDY_STAT | DSC_STAT; + ide->error = 1; /*Device passed*/ + ide->secount = 1; + ide->sector = 1; + + ide_set_signature(ide); + + if (ide_drive_is_zip(ide)) { + zip[zip_id]->status = DRDY_STAT | DSC_STAT; + zip[zip_id]->error = 1; + zip_reset(zip[zip_id]); + } else if (ide_drive_is_cdrom(ide)) { + cdrom[cdrom_id]->status = DRDY_STAT | DSC_STAT; + cdrom[cdrom_id]->error = 1; + cdrom_reset(cdrom[cdrom_id]); + } + ide_irq_raise(ide); + if (ide_drive_is_zip(ide) || ide_drive_is_cdrom(ide)) + ide->service = 0; + return; + + case WIN_NOP: + case WIN_STANDBYNOW1: + case WIN_IDLENOW1: + case WIN_SETIDLE1: + if (ide_drive_is_zip(ide)) + zip[zip_id]->status = DRDY_STAT | DSC_STAT; + else if (ide_drive_is_cdrom(ide)) + cdrom[cdrom_id]->status = DRDY_STAT | DSC_STAT; + else + ide->atastat = DRDY_STAT | DSC_STAT; + ide_irq_raise(ide); + return; + + case WIN_CHECKPOWERMODE1: + case WIN_SLEEP1: + if (ide_drive_is_zip(ide)) { + zip[zip_id]->phase = 0xFF; + zip[zip_id]->status = DRDY_STAT | DSC_STAT; + } else if (ide_drive_is_cdrom(ide)) { + cdrom[cdrom_id]->phase = 0xFF; + cdrom[cdrom_id]->status = DRDY_STAT | DSC_STAT; + } + ide->secount = 0xFF; + ide->atastat = DRDY_STAT | DSC_STAT; + ide_irq_raise(ide); + return; + + case WIN_READ: + case WIN_READ_NORETRY: + if (ide_drive_is_zip(ide) || ide_drive_is_cdrom(ide)) { + ide_set_signature(ide); + goto abort_cmd; + } + if (ide->cfg_spt == 0) + goto id_not_found; + + if (ide->do_initial_read) { + ide->do_initial_read = 0; + ide->sector_pos = 0; + if (ide->secount) + hdd_image_read(ide->hdd_num, ide_get_sector(ide), ide->secount, ide->sector_buffer); + else + hdd_image_read(ide->hdd_num, ide_get_sector(ide), 256, ide->sector_buffer); + } + + memcpy(ide->buffer, &ide->sector_buffer[ide->sector_pos*512], 512); + + ide->sector_pos++; + ide->pos = 0; + + ide->atastat = DRQ_STAT | DRDY_STAT | DSC_STAT; + + ide_irq_raise(ide); + + hdd_active(ide->hdd_num, 1); + return; + + case WIN_READ_DMA: + case WIN_READ_DMA_ALT: + if (ide_drive_is_zip(ide) || ide_drive_is_cdrom(ide) || (ide->board >= 2)) { + DEBUG("IDE %i: DMA read aborted (bad device or board)\n", ide->channel); + goto abort_cmd; + } + if (ide->cfg_spt == 0) { + DEBUG("IDE %i: DMA read aborted (SPECIFY failed)\n", ide->channel); + goto id_not_found; + } + + ide->sector_pos = 0; + if (ide->secount) + ide->sector_pos = ide->secount; + else + ide->sector_pos = 256; + hdd_image_read(ide->hdd_num, ide_get_sector(ide), ide->sector_pos, ide->sector_buffer); + + ide->pos=0; + + if (ide_bus_master_read) { + /* We should not abort - we should simply wait for the host to start DMA. */ + ret = ide_bus_master_read(ide->board, + ide->sector_buffer, ide->sector_pos * 512, + ide_bus_master_priv[ide->board]); + if (ret == 2) { + /* Bus master DMA disabled, simply wait for the host to enable DMA. */ + ide->atastat = DRQ_STAT | DRDY_STAT | DSC_STAT; + ide_set_callback(ide->board, 6LL * IDE_TIME); + return; + } else if (ret == 1) { + /* Bus master DMAS error, abort the command. */ + DEBUG("IDE %i: DMA read aborted (failed)\n", ide->channel); + goto abort_cmd; + } else { + /*DMA successful*/ + DEBUG("IDE %i: DMA read successful\n", ide->channel); + + ide->atastat = DRDY_STAT | DSC_STAT; + + ide_irq_raise(ide); + hdd_active(ide->hdd_num, 0); + } + } else { + DEBUG("IDE %i: DMA read aborted (no bus master)\n", ide->channel); + goto abort_cmd; + } + return; + + case WIN_READ_MULTIPLE: + /* According to the official ATA reference: + + If the Read Multiple command is attempted before the Set Multiple Mode + command has been executed or when Read Multiple commands are + disabled, the Read Multiple operation is rejected with an Aborted Com- + mand error. */ + if (ide_drive_is_zip(ide) || ide_drive_is_cdrom(ide) || !ide->blocksize) + goto abort_cmd; + if (ide->cfg_spt == 0) + goto id_not_found; + + if (ide->do_initial_read) { + ide->do_initial_read = 0; + ide->sector_pos = 0; + if (ide->secount) + hdd_image_read(ide->hdd_num, ide_get_sector(ide), ide->secount, ide->sector_buffer); + else + hdd_image_read(ide->hdd_num, ide_get_sector(ide), 256, ide->sector_buffer); + } + + memcpy(ide->buffer, &ide->sector_buffer[ide->sector_pos*512], 512); + + ide->sector_pos++; + ide->pos=0; + + ide->atastat = DRQ_STAT | DRDY_STAT | DSC_STAT; + if (!ide->blockcount) + ide_irq_raise(ide); + ide->blockcount++; + if (ide->blockcount >= ide->blocksize) + ide->blockcount = 0; + return; + + case WIN_WRITE: + case WIN_WRITE_NORETRY: + if (ide_drive_is_zip(ide) || ide_drive_is_cdrom(ide)) + goto abort_cmd; + if (ide->cfg_spt == 0) + goto id_not_found; + hdd_image_write(ide->hdd_num, ide_get_sector(ide), 1, (uint8_t *) ide->buffer); + ide_irq_raise(ide); + ide->secount = (ide->secount - 1) & 0xff; + if (ide->secount) { + ide->atastat = DRQ_STAT | DRDY_STAT | DSC_STAT; + ide->pos=0; + ide_next_sector(ide); + hdd_active(ide->hdd_num, 1); + } else { + ide->atastat = DRDY_STAT | DSC_STAT; + hdd_active(ide->hdd_num, 0); + } + return; + + case WIN_WRITE_DMA: + case WIN_WRITE_DMA_ALT: + if (ide_drive_is_zip(ide) || ide_drive_is_cdrom(ide) || (ide->board >= 2)) { + DEBUG("IDE %i: DMA write aborted (bad device type or board)\n", ide->channel); + goto abort_cmd; + } + if (ide->cfg_spt == 0) { + DEBUG("IDE %i: DMA write aborted (SPECIFY failed)\n", ide->channel); + goto id_not_found; + } + + if (ide_bus_master_read) { + if (ide->secount) + ide->sector_pos = ide->secount; + else + ide->sector_pos = 256; + + ret = ide_bus_master_write(ide->board, + ide->sector_buffer, ide->sector_pos * 512, + ide_bus_master_priv[ide->board]); + + if (ret == 2) { + /* Bus master DMA disabled, simply wait for the host to enable DMA. */ + ide->atastat = DRQ_STAT | DRDY_STAT | DSC_STAT; + ide_set_callback(ide->board, 6LL * IDE_TIME); + return; + } else if (ret == 1) { + /* Bus master DMA error, abort the command. */ + DEBUG("IDE %i: DMA read aborted (failed)\n", ide->channel); + goto abort_cmd; + } else { + /*DMA successful*/ + DEBUG("IDE %i: DMA write successful\n", ide->channel); + + hdd_image_write(ide->hdd_num, ide_get_sector(ide), ide->sector_pos, ide->sector_buffer); + + ide->atastat = DRDY_STAT | DSC_STAT; + + ide_irq_raise(ide); + hdd_active(ide->hdd_num, 1); + } + } else { + DEBUG("IDE %i: DMA write aborted (no bus master)\n", ide->channel); + goto abort_cmd; + } + + return; + + case WIN_WRITE_MULTIPLE: + if (ide_drive_is_zip(ide) || ide_drive_is_cdrom(ide)) + goto abort_cmd; + if (ide->cfg_spt == 0) + goto id_not_found; + hdd_image_write(ide->hdd_num, ide_get_sector(ide), 1, (uint8_t *) ide->buffer); + ide->blockcount++; + if (ide->blockcount >= ide->blocksize || ide->secount == 1) { + ide->blockcount = 0; + ide_irq_raise(ide); + } + ide->secount = (ide->secount - 1) & 0xff; + if (ide->secount) { + ide->atastat = DRQ_STAT | DRDY_STAT | DSC_STAT; + ide->pos=0; + ide_next_sector(ide); + } else { + ide->atastat = DRDY_STAT | DSC_STAT; + hdd_active(ide->hdd_num, 0); + } + return; + + case WIN_VERIFY: + case WIN_VERIFY_ONCE: + if (ide_drive_is_zip(ide) || ide_drive_is_cdrom(ide)) + goto abort_cmd; + if (ide->cfg_spt == 0) + goto id_not_found; + ide->pos=0; + ide->atastat = DRDY_STAT | DSC_STAT; + ide_irq_raise(ide); + hdd_active(ide->hdd_num, 1); + return; + + case WIN_FORMAT: + if (ide_drive_is_zip(ide) || ide_drive_is_cdrom(ide)) + goto abort_cmd; + if (ide->cfg_spt == 0) + goto id_not_found; + hdd_image_zero(ide->hdd_num, ide_get_sector(ide), ide->secount); + + ide->atastat = DRDY_STAT | DSC_STAT; + ide_irq_raise(ide); + + /* hdd_active(ide->hdd_num, 1); */ + return; + + case WIN_DRIVE_DIAGNOSTICS: + ide_set_signature(ide); + ide->error=1; /*No error detected*/ + + if (ide_drive_is_zip(ide)) { + zip[zip_id]->status = 0; + zip[zip_id]->error = 1; + ide_irq_raise(ide); + } else if (ide_drive_is_cdrom(ide)) { + cdrom[cdrom_id]->status = 0; + cdrom[cdrom_id]->error = 1; + ide_irq_raise(ide); + } else { + ide->atastat = DRDY_STAT | DSC_STAT; + ide->error = 1; + ide_irq_raise(ide); + } + + ide_set_signature(ide_other); + ide_other->error=1; /*No error detected*/ + + if (ide_drive_is_zip(ide_other)) { + zip[zip_id_other]->status = 0; + zip[zip_id_other]->error = 1; + } else if (ide_drive_is_cdrom(ide_other)) { + cdrom[cdrom_id_other]->status = 0; + cdrom[cdrom_id_other]->error = 1; + } else { + ide_other->atastat = DRDY_STAT | DSC_STAT; + ide_other->error = 1; + } + + ide_boards[ide->board]->cur_dev &= ~1; + ch = ide_boards[ide->board]->cur_dev; + return; + + case WIN_SPECIFY: /* Initialize Drive Parameters */ + if (ide_drive_is_zip(ide) || ide_drive_is_cdrom(ide)) + goto abort_cmd; + if (ide->cfg_spt == 0) { + /* Only accept after RESET or DIAG. */ + ide->cfg_spt = ide->secount; + ide->cfg_hpc = ide->head + 1; + } + ide->command = 0x00; + ide->atastat = DRDY_STAT | DSC_STAT; + ide->error = 1; + ide_irq_raise(ide); + return; + + case WIN_PIDENTIFY: /* Identify Packet Device */ + if (ide_drive_is_zip(ide)) { + ide_identify(ide); + ide->pos = 0; + zip[zip_id]->phase = 2; + zip[zip_id]->pos = 0; + zip[zip_id]->error = 0; + zip[zip_id]->status = DRQ_STAT | DRDY_STAT | DSC_STAT; + ide_irq_raise(ide); + return; + } else if (ide_drive_is_cdrom(ide)) { + ide_identify(ide); + ide->pos = 0; + cdrom[cdrom_id]->phase = 2; + cdrom[cdrom_id]->pos = 0; + cdrom[cdrom_id]->error = 0; + cdrom[cdrom_id]->status = DRQ_STAT | DRDY_STAT | DSC_STAT; + ide_irq_raise(ide); + return; + } + goto abort_cmd; + + case WIN_SET_MULTIPLE_MODE: + if (ide_drive_is_zip(ide) || ide_drive_is_cdrom(ide)) + goto abort_cmd; + ide->blocksize = ide->secount; + ide->atastat = DRDY_STAT | DSC_STAT; + ide_irq_raise(ide); + return; + + case WIN_SET_FEATURES: + if (ide->type == IDE_NONE) + goto abort_cmd; + + if (!ide_set_features(ide)) + goto abort_cmd; + else { + if (ide_drive_is_zip(ide)) { + zip[zip_id]->status = DRDY_STAT | DSC_STAT; + zip[zip_id]->pos = 0; + } else if (ide_drive_is_cdrom(ide)) { + cdrom[cdrom_id]->status = DRDY_STAT | DSC_STAT; + cdrom[cdrom_id]->pos = 0; + } + ide->atastat = DRDY_STAT | DSC_STAT; + ide_irq_raise(ide); + } + return; + + case WIN_READ_NATIVE_MAX: + if (ide->type != IDE_HDD) + goto abort_cmd; + snum = hdd[ide->hdd_num].spt; + snum *= hdd[ide->hdd_num].hpc; + snum *= hdd[ide->hdd_num].tracks; + ide_set_sector(ide, snum - 1); + ide->atastat = DRDY_STAT | DSC_STAT; + ide_irq_raise(ide); + return; + + case WIN_IDENTIFY: /* Identify Device */ + if (ide->type != IDE_HDD) { + ide_set_signature(ide); + goto abort_cmd; + } else { + ide_identify(ide); + ide->pos=0; + ide->atastat = DRQ_STAT | DRDY_STAT | DSC_STAT; + ide_irq_raise(ide); + } + return; + + case WIN_PACKETCMD: /* ATAPI Packet */ + if (!ide_drive_is_zip(ide) && !ide_drive_is_cdrom(ide)) + goto abort_cmd; + + if (ide_drive_is_zip(ide)) + zip_phase_callback(zip[atapi_zip_drives[ch]]); + else + cdrom_phase_callback(cdrom[atapi_cdrom_drives[ch]]); + return; + + case 0xFF: + goto abort_cmd; + } + +abort_cmd: + ide->command = 0; + if (ide_drive_is_zip(ide)) { + zip[zip_id]->status = DRDY_STAT | ERR_STAT | DSC_STAT; + zip[zip_id]->error = ABRT_ERR; + zip[zip_id]->pos = 0; + } else if (ide_drive_is_cdrom(ide)) { + cdrom[cdrom_id]->status = DRDY_STAT | ERR_STAT | DSC_STAT; + cdrom[cdrom_id]->error = ABRT_ERR; + cdrom[cdrom_id]->pos = 0; + } else { + ide->atastat = DRDY_STAT | ERR_STAT | DSC_STAT; + ide->error = ABRT_ERR; + ide->pos = 0; + } + ide_irq_raise(ide); + return; id_not_found: - ide->atastat = READY_STAT | ERR_STAT | DSC_STAT; - ide->error = ABRT_ERR | 0x10; - ide->pos = 0; - ide_irq_raise(ide); + ide->atastat = DRDY_STAT | ERR_STAT | DSC_STAT; + ide->error = IDNF_ERR; + ide->pos = 0; + ide_irq_raise(ide); } -void ide_callback(void *priv) -{ - int drivenum = (int)priv; - idecallback[drivenum] = 0LL; - callbackide(drivenum); -} -void ide_callback_pri(void *priv) +static void +ide_set_handlers(uint8_t board) { - idecallback[0] = 0LL; - callbackide(0); -} - -void ide_callback_sec(void *priv) -{ - idecallback[1] = 0LL; - callbackide(1); -} - -void ide_callback_ter(void *priv) -{ - idecallback[2] = 0LL; - callbackide(2); -} - -void ide_callback_qua(void *priv) -{ - idecallback[3] = 0LL; - callbackide(3); -} - -void ide_callback_xtide(void *priv) -{ - idecallback[4] = 0LL; - callbackide(4); -} - -void ide_write_pri(uint16_t addr, uint8_t val, void *priv) -{ - writeide(0, addr, val); -} -void ide_write_pri_w(uint16_t addr, uint16_t val, void *priv) -{ - writeidew(0, val); -} -void ide_write_pri_l(uint16_t addr, uint32_t val, void *priv) -{ - writeidel(0, val); -} -uint8_t ide_read_pri(uint16_t addr, void *priv) -{ - return readide(0, addr); -} -uint16_t ide_read_pri_w(uint16_t addr, void *priv) -{ - return readidew(0); -} -uint32_t ide_read_pri_l(uint16_t addr, void *priv) -{ - return readidel(0); -} - -void ide_write_sec(uint16_t addr, uint8_t val, void *priv) -{ - writeide(1, addr, val); -} -void ide_write_sec_w(uint16_t addr, uint16_t val, void *priv) -{ - writeidew(1, val); -} -void ide_write_sec_l(uint16_t addr, uint32_t val, void *priv) -{ - writeidel(1, val); -} -uint8_t ide_read_sec(uint16_t addr, void *priv) -{ - return readide(1, addr); -} -uint16_t ide_read_sec_w(uint16_t addr, void *priv) -{ - return readidew(1); -} -uint32_t ide_read_sec_l(uint16_t addr, void *priv) -{ - return readidel(1); -} - -void ide_write_ter(uint16_t addr, uint8_t val, void *priv) -{ - writeide(2, addr, val); -} -void ide_write_ter_w(uint16_t addr, uint16_t val, void *priv) -{ - writeidew(2, val); -} -void ide_write_ter_l(uint16_t addr, uint32_t val, void *priv) -{ - writeidel(2, val); -} -uint8_t ide_read_ter(uint16_t addr, void *priv) -{ - return readide(2, addr); -} -uint16_t ide_read_ter_w(uint16_t addr, void *priv) -{ - return readidew(2); -} -uint32_t ide_read_ter_l(uint16_t addr, void *priv) -{ - return readidel(2); -} - -void ide_write_qua(uint16_t addr, uint8_t val, void *priv) -{ - writeide(3, addr, val); -} -void ide_write_qua_w(uint16_t addr, uint16_t val, void *priv) -{ - writeidew(3, val); -} -void ide_write_qua_l(uint16_t addr, uint32_t val, void *priv) -{ - writeidel(3, val); -} -uint8_t ide_read_qua(uint16_t addr, void *priv) -{ - return readide(3, addr); -} -uint16_t ide_read_qua_w(uint16_t addr, void *priv) -{ - return readidew(3); -} -uint32_t ide_read_qua_l(uint16_t addr, void *priv) -{ - return readidel(3); -} - -static uint16_t ide_base_main[2] = { 0x1f0, 0x170 }; -static uint16_t ide_side_main[2] = { 0x3f6, 0x376 }; - - -void ide_pri_enable(void) -{ - io_sethandler(0x01f0, 0x0008, ide_read_pri, ide_read_pri_w, ide_read_pri_l, ide_write_pri, ide_write_pri_w, ide_write_pri_l, NULL); - io_sethandler(0x03f6, 0x0001, ide_read_pri, NULL, NULL, ide_write_pri, NULL, NULL , NULL); - ide_base_main[0] = 0x1f0; - ide_side_main[0] = 0x3f6; -} - -void ide_pri_enable_ex(void) -{ - if (ide_base_main[0] & 0x300) - { -#ifdef ENABLE_HDC_LOG - hdc_log("Enabling primary base (%04X)...\n", ide_base_main[0]); -#endif - io_sethandler(ide_base_main[0], 0x0008, ide_read_pri, ide_read_pri_w, ide_read_pri_l, ide_write_pri, ide_write_pri_w, ide_write_pri_l, NULL); - } - if (ide_side_main[0] & 0x300) - { -#ifdef ENABLE_HDC_LOG - hdc_log("Enabling primary side (%04X)...\n", ide_side_main[0]); -#endif - io_sethandler(ide_side_main[0], 0x0001, ide_read_pri, NULL, NULL, ide_write_pri, NULL, NULL , NULL); + if (ide_base_main[board] & 0x300) { + if (ide_boards[board]->bit32) { + io_sethandler(ide_base_main[board], 1, + ide_readb, ide_readw, ide_readl, + ide_writeb, ide_writew, ide_writel, + ide_boards[board]); + } else { + io_sethandler(ide_base_main[board], 1, + ide_readb, ide_readw, NULL, + ide_writeb, ide_writew, NULL, + ide_boards[board]); } + io_sethandler(ide_base_main[board] + 1, 7, + ide_readb, NULL, NULL, + ide_writeb, NULL, NULL, + ide_boards[board]); + } + + if (ide_side_main[board] & 0x300) { + io_sethandler(ide_side_main[board], 1, + ide_read_alt_status, NULL, NULL, + ide_write_devctl, NULL, NULL, + ide_boards[board]); + } } -void ide_pri_disable(void) + +static void +ide_remove_handlers(uint8_t board) { - io_removehandler(ide_base_main[0], 0x0008, ide_read_pri, ide_read_pri_w, ide_read_pri_l, ide_write_pri, ide_write_pri_w, ide_write_pri_l, NULL); - io_removehandler(ide_side_main[0], 0x0001, ide_read_pri, NULL, NULL, ide_write_pri, NULL, NULL , NULL); + if (ide_boards[board]->bit32) { + io_removehandler(ide_base_main[board], 1, + ide_readb, ide_readw, ide_readl, + ide_writeb, ide_writew, ide_writel, + ide_boards[board]); + } else { + io_removehandler(ide_base_main[board], 1, + ide_readb, ide_readw, NULL, + ide_writeb, ide_writew, NULL, + ide_boards[board]); + } + io_removehandler(ide_base_main[board] + 1, 7, + ide_readb, NULL, NULL, + ide_writeb, NULL, NULL, + ide_boards[board]); + + io_removehandler(ide_side_main[board], 1, + ide_read_alt_status, NULL, NULL, + ide_write_devctl, NULL, NULL, + ide_boards[board]); } -void ide_sec_enable(void) + +void +ide_pri_enable(void) { - io_sethandler(0x0170, 0x0008, ide_read_sec, ide_read_sec_w, ide_read_sec_l, ide_write_sec, ide_write_sec_w, ide_write_sec_l, NULL); - io_sethandler(0x0376, 0x0001, ide_read_sec, NULL, NULL, ide_write_sec, NULL, NULL , NULL); - ide_base_main[1] = 0x170; - ide_side_main[1] = 0x376; + ide_set_handlers(0); } -void ide_sec_enable_ex(void) + +void +ide_pri_disable(void) { - if (ide_base_main[1] & 0x300) - { - io_sethandler(ide_base_main[1], 0x0008, ide_read_sec, ide_read_sec_w, ide_read_sec_l, ide_write_sec, ide_write_sec_w, ide_write_sec_l, NULL); - } - if (ide_side_main[1] & 0x300) - { - io_sethandler(ide_side_main[1], 0x0001, ide_read_sec, NULL, NULL, ide_write_sec, NULL, NULL , NULL); - } + ide_remove_handlers(0); } -void ide_sec_disable(void) + +void +ide_sec_enable(void) { - io_removehandler(ide_base_main[1], 0x0008, ide_read_sec, ide_read_sec_w, ide_read_sec_l, ide_write_sec, ide_write_sec_w, ide_write_sec_l, NULL); - io_removehandler(ide_side_main[1], 0x0001, ide_read_sec, NULL, NULL, ide_write_sec, NULL, NULL , NULL); + ide_set_handlers(1); } -void ide_set_base(int controller, uint16_t port) +void +ide_sec_disable(void) { - ide_base_main[controller] = port; + ide_remove_handlers(1); } -void ide_set_side(int controller, uint16_t port) + +void +ide_set_base(int controller, uint16_t port) { - ide_side_main[controller] = port; + ide_base_main[controller] = port; } -void ide_ter_enable(void) + +void +ide_set_side(int controller, uint16_t port) { - io_sethandler(0x0168, 0x0008, ide_read_ter, ide_read_ter_w, ide_read_ter_l, ide_write_ter, ide_write_ter_w, ide_write_ter_l, NULL); - io_sethandler(0x036e, 0x0001, ide_read_ter, NULL, NULL, ide_write_ter, NULL, NULL , NULL); -} - -void ide_ter_disable(void) -{ - io_removehandler(0x0168, 0x0008, ide_read_ter, ide_read_ter_w, ide_read_ter_l, ide_write_ter, ide_write_ter_w, ide_write_ter_l, NULL); - io_removehandler(0x036e, 0x0001, ide_read_ter, NULL, NULL, ide_write_ter, NULL, NULL , NULL); -} - -void ide_ter_disable_cond(void) -{ - if ((ide_drives[4].type == IDE_NONE) && (ide_drives[5].type == IDE_NONE)) - { - ide_ter_disable(); - } -} - -void ide_ter_init(void) -{ - ide_ter_enable(); - - timer_add(ide_callback_ter, &idecallback[2], &idecallback[2], NULL); -} - -void ide_qua_enable(void) -{ - io_sethandler(0x01e8, 0x0008, ide_read_qua, ide_read_qua_w, ide_read_qua_l, ide_write_qua, ide_write_qua_w, ide_write_qua_l, NULL); - io_sethandler(0x03ee, 0x0001, ide_read_qua, NULL, NULL, ide_write_qua, NULL, NULL , NULL); -} - -void ide_qua_disable_cond(void) -{ - if ((ide_drives[6].type == IDE_NONE) && (ide_drives[7].type == IDE_NONE)) - { - ide_qua_disable(); - } -} - -void ide_qua_disable(void) -{ - io_removehandler(0x01e8, 0x0008, ide_read_qua, ide_read_qua_w, ide_read_qua_l, ide_write_qua, ide_write_qua_w, ide_write_qua_l, NULL); - io_removehandler(0x03ee, 0x0001, ide_read_qua, NULL, NULL, ide_write_qua, NULL, NULL , NULL); -} - -void ide_qua_init(void) -{ - ide_qua_enable(); - - timer_add(ide_callback_qua, &idecallback[3], &idecallback[3], NULL); + ide_side_main[controller] = port; } -/*FIXME: this will go away after Kotori's rewrite. --FvK */ -void ide_init_first(void) -{ - int d; - - memset(ide_drives, 0x00, sizeof(ide_drives)); - for (d = 0; d < (IDE_NUM); d++) - { - ide_drives[d].channel = d; - ide_drives[d].type = IDE_NONE; - ide_drives[d].hdd_num = -1; - ide_drives[d].atastat = READY_STAT | DSC_STAT; - ide_drives[d].service = 0; - ide_drives[d].board = d >> 1; - } -} - - -void ide_xtide_init(void) -{ - ide_bus_master_read = ide_bus_master_write = NULL; - - timer_add(ide_callback_xtide, &idecallback[4], &idecallback[4], NULL); -} - -void ide_set_bus_master(int (*read)(int channel, uint8_t *data, int transfer_length), int (*write)(int channel, uint8_t *data, int transfer_length), void (*set_irq)(int channel)) -{ - ide_bus_master_read = read; - ide_bus_master_write = write; - ide_bus_master_set_irq = set_irq; -} - -void secondary_ide_check(void) -{ - int i = 0; - int secondary_cdroms = 0; - int secondary_zips = 0; - - for (i=0; i= 2) && (zip_drives[i].ide_channel <= 3) && ((zip_drives[i].bus_type == ZIP_BUS_ATAPI_PIO_ONLY) || (zip_drives[i].bus_type == ZIP_BUS_ATAPI_PIO_AND_DMA))) - secondary_zips++; - } - for (i=0; i= 2) && (cdrom_drives[i].ide_channel <= 3) && ((cdrom_drives[i].bus_type == CDROM_BUS_ATAPI_PIO_ONLY) || (cdrom_drives[i].bus_type == CDROM_BUS_ATAPI_PIO_AND_DMA))) - secondary_cdroms++; - } - if (!secondary_zips && !secondary_cdroms) { - ide_sec_disable(); - ide_init_ch[1] = 0; - } -} - - -/* - * Initialization of standalone IDE controller instance. - * - * Eventually, we should clean up the whole mess by only - * using device_t units, with configuration parameters to - * indicate primary/secondary and all that, rather than - * keeping a zillion of duplicate functions around. - */ static void * -ide_sainit(const device_t *info) +ide_ter_init(const device_t *info) { - switch(info->local) { + ide_board_t *dev; + + dev = (ide_board_t *)mem_alloc(sizeof(ide_board_t)); + memset(dev, 0x00, sizeof(ide_board_t)); + dev->irq = device_get_config_int("irq"); + dev->cur_dev = 4; + ide_boards[2] = dev; + + ide_set_handlers(2); + + timer_add(ide_callback, &dev->callback, &dev->callback, dev); + + ide_board_init(2); + + return(dev); +} + + +/* Close a standalone IDE unit. */ +static void +ide_ter_close(void *priv) +{ + if (ide_boards[2]) { + free(ide_boards[2]); + ide_boards[2] = NULL; + + ide_board_close(2); + } +} + + +static void * +ide_qua_init(const device_t *info) +{ + ide_board_t *dev; + + dev = (ide_board_t *)mem_alloc(sizeof(ide_board_t)); + memset(dev, 0x00, sizeof(ide_board_t)); + dev->irq = device_get_config_int("irq"); + dev->cur_dev = 6; + + ide_boards[3] = dev; + + ide_set_handlers(3); + + timer_add(ide_callback, &dev->callback, &dev->callback, dev); + + ide_board_init(3); + + return(dev); +} + + +/* Close a standalone IDE unit. */ +static void +ide_qua_close(void *priv) +{ + if (ide_boards[3]) { + free(ide_boards[3]); + ide_boards[3] = NULL; + + ide_board_close(3); + } +} + + +static void +ide_clear_bus_master(void) +{ + ide_bus_master_read = ide_bus_master_write = NULL; + ide_bus_master_set_irq = NULL; + ide_bus_master_priv[0] = ide_bus_master_priv[1] = NULL; +} + + +void * +ide_xtide_init(void) +{ + ide_clear_bus_master(); + + if (!ide_boards[0]) { + ide_boards[0] = (ide_board_t *) mem_alloc(sizeof(ide_board_t)); + memset(ide_boards[0], 0, sizeof(ide_board_t)); + ide_boards[0]->cur_dev = 0; + + timer_add(ide_callback, &ide_boards[0]->callback, &ide_boards[0]->callback, + ide_boards[0]); + + ide_board_init(0); + } + ide_boards[0]->irq = -1; + + return ide_boards[0]; +} + + +void +ide_xtide_close(void) +{ + if (ide_boards[0]) { + free(ide_boards[0]); + ide_boards[0] = NULL; + + ide_board_close(0); + } +} + + +void +ide_set_bus_master(int (*read)(int channel, uint8_t *data, int transfer_length, void *priv), + int (*write)(int channel, uint8_t *data, int transfer_length, void *priv), + void (*set_irq)(int channel, void *priv), + void *priv0, void *priv1) +{ + ide_bus_master_read = read; + ide_bus_master_write = write; + ide_bus_master_set_irq = set_irq; + ide_bus_master_priv[0] = priv0; + ide_bus_master_priv[1] = priv1; +} + + +void +secondary_ide_check(void) +{ + int i = 0; + int secondary_cdroms = 0; + int secondary_zips = 0; + + for (i = 0; i < ZIP_NUM; i++) { + if ((zip_drives[i].ide_channel >= 2) && (zip_drives[i].ide_channel <= 3) && + (zip_drives[i].bus_type == ZIP_BUS_ATAPI)) + secondary_zips++; + } + for (i = 0; i < CDROM_NUM; i++) { + if ((cdrom_drives[i].ide_channel >= 2) && (cdrom_drives[i].ide_channel <= 3) && + (cdrom_drives[i].bus_type == CDROM_BUS_ATAPI)) + secondary_cdroms++; + } + if (!secondary_zips && !secondary_cdroms) + ide_remove_handlers(1); +} + + +/* Initialization of standalone IDE controller instance. */ +static void * +ide_init(const device_t *info) +{ + int type = info->local & 255; + + DEBUG("Initializing IDE (type %i) ...\n", type); + + switch(type) { case 0: /* ISA, single-channel */ case 2: /* ISA, dual-channel */ case 3: /* ISA, dual-channel, optional 2nd channel */ @@ -2982,23 +2779,55 @@ ide_sainit(const device_t *info) case 6: /* VLB, dual-channel */ case 8: /* PCI, single-channel */ case 10: /* PCI, dual-channel */ - if (!ide_init_ch[0]) { - ide_pri_enable(); - timer_add(ide_callback_pri, &idecallback[0], &idecallback[0], NULL); - ide_init_ch[0] = 1; + if (! ide_inited) { + pio_override = 0; + + if (! (type & 8)) + ide_clear_bus_master(); } - if ((info->local & 2) && !ide_init_ch[1]) { - ide_sec_enable(); - timer_add(ide_callback_sec, &idecallback[1], &idecallback[1], NULL); - ide_init_ch[1] = 1; + if (!(ide_inited & 1)) { + ide_boards[0] = (ide_board_t *)mem_alloc(sizeof(ide_board_t)); + memset(ide_boards[0], 0, sizeof(ide_board_t)); + ide_boards[0]->irq = 14; + ide_boards[0]->cur_dev = 0; + if (type & 8) + ide_boards[0]->bit32 = 1; + ide_base_main[0] = 0x1f0; + ide_side_main[0] = 0x3f6; + ide_set_handlers(0); - if (info->local & 1) + timer_add(ide_callback, &ide_boards[0]->callback, + &ide_boards[0]->callback, ide_boards[0]); + DEBUG("Callback 0 pointer: %08X\n", &ide_boards[0]->callback); + + ide_board_init(0); + + ide_inited |= 1; + } + + if ((type & 3) && !(ide_inited & 2)) { + ide_boards[1] = (ide_board_t *)mem_alloc(sizeof(ide_board_t)); + memset(ide_boards[1], 0, sizeof(ide_board_t)); + ide_boards[1]->irq = 15; + ide_boards[1]->cur_dev = 2; + if (type & 8) + ide_boards[1]->bit32 = 1; + ide_base_main[1] = 0x170; + ide_side_main[1] = 0x376; + ide_set_handlers(1); + + timer_add(ide_callback, &ide_boards[1]->callback, + &ide_boards[1]->callback, ide_boards[1]); + DEBUG("Callback 1 pointer: %08X\n", &ide_boards[1]->callback); + + ide_board_init(1); + + if (type & 1) secondary_ide_check(); - } - if (!(info->local & 8)) - ide_bus_master_read = ide_bus_master_write = NULL; + ide_inited |= 2; + } break; } @@ -3006,73 +2835,241 @@ ide_sainit(const device_t *info) } +void +ide_enable_pio_override(void) +{ + pio_override = 1; +} + + +static void +ide_drive_reset(int d) +{ + ide_drives[d]->channel = d; + ide_drives[d]->atastat = DRDY_STAT | DSC_STAT; + ide_drives[d]->service = 0; + ide_drives[d]->board = d >> 1; + + if (ide_boards[d >> 1]) { + ide_boards[d >> 1]->cur_dev = d & ~1; + ide_boards[d >> 1]->callback = 0LL; + } + + ide_set_signature(ide_drives[d]); + + if (ide_drives[d]->sector_buffer) + memset(ide_drives[d]->sector_buffer, 0, 256*512); + + if (ide_drives[d]->buffer) + memset(ide_drives[d]->buffer, 0, 65536 * sizeof(uint16_t)); +} + + +/* Reset a standalone IDE unit. */ +static void +ide_reset(void *p) +{ + int d; + + DEBUG("Resetting IDE...\n"); + + if (ide_inited & 1) { + for (d = 0; d < 2; d++) + ide_drive_reset(d); + } + + if (ide_inited & 2) { + for (d = 2; d < 4; d++) + ide_drive_reset(d); + } +} + + /* Close a standalone IDE unit. */ static void -ide_saclose(void *priv) +ide_close(void *priv) { - ide_init_ch[0] = ide_init_ch[1] = 0; + DEBUG("Closing IDE...\n"); + + if ((ide_inited & 1) && (ide_boards[0])) { + free(ide_boards[0]); + ide_boards[0] = NULL; + + ide_board_close(0); + } + + if ((ide_inited & 2) && (ide_boards[1])) { + free(ide_boards[1]); + ide_boards[1] = NULL; + + ide_board_close(1); + } + + ide_inited = 0; } const device_t ide_isa_device = { - "ISA PC/AT IDE Controller", + "PC/AT IDE Controller", DEVICE_ISA | DEVICE_AT, - 0, - ide_sainit, ide_saclose, NULL, + (HDD_BUS_IDE << 8) | 0, + ide_init, ide_close, ide_reset, NULL, NULL, NULL, NULL, NULL }; const device_t ide_isa_2ch_device = { - "ISA PC/AT IDE Controller (Dual-Channel)", + "PC/AT IDE Controller (Dual-Channel)", DEVICE_ISA | DEVICE_AT, - 2, - ide_sainit, ide_saclose, NULL, + (HDD_BUS_IDE << 8) | 2, + ide_init, ide_close, ide_reset, NULL, NULL, NULL, NULL, NULL }; const device_t ide_isa_2ch_opt_device = { - "ISA PC/AT IDE Controller (Single/Dual)", + "PC/AT IDE Controller (Single/Dual)", DEVICE_ISA | DEVICE_AT, - 3, - ide_sainit, ide_saclose, NULL, + (HDD_BUS_IDE << 8) | 3, + ide_init, ide_close, ide_reset, NULL, NULL, NULL, NULL, NULL }; const device_t ide_vlb_device = { - "VLB IDE Controller", + "IDE Controller", DEVICE_VLB | DEVICE_AT, - 4, - ide_sainit, ide_saclose, NULL, + (HDD_BUS_IDE << 8) | 4, + ide_init, ide_close, ide_reset, NULL, NULL, NULL, NULL, NULL }; const device_t ide_vlb_2ch_device = { - "VLB IDE Controller (Dual-Channel)", + "IDE Controller (Dual-Channel)", DEVICE_VLB | DEVICE_AT, - 6, - ide_sainit, ide_saclose, NULL, + (HDD_BUS_IDE << 8) | 6, + ide_init, ide_close, ide_reset, NULL, NULL, NULL, NULL, NULL }; const device_t ide_pci_device = { - "PCI IDE Controller", + "IDE Controller", DEVICE_PCI | DEVICE_AT, - 8, - ide_sainit, ide_saclose, NULL, + (HDD_BUS_IDE << 8) | 8, + ide_init, ide_close, ide_reset, NULL, NULL, NULL, NULL, NULL }; const device_t ide_pci_2ch_device = { - "PCI IDE Controller (Dual-Channel)", + "IDE Controller (Dual-Channel)", DEVICE_PCI | DEVICE_AT, - 10, - ide_sainit, ide_saclose, NULL, + (HDD_BUS_IDE << 8) | 10, + ide_init, ide_close, ide_reset, NULL, NULL, NULL, NULL, NULL }; + + +static const device_config_t ide_ter_config[] = { + { + "irq", "IRQ", CONFIG_SELECTION, "", 10, + { + { + "IRQ 2", 2 + }, + { + "IRQ 3", 3 + }, + { + "IRQ 4", 4 + }, + { + "IRQ 5", 5 + }, + { + "IRQ 7", 7 + }, + { + "IRQ 9", 9 + }, + { + "IRQ 10", 10 + }, + { + "IRQ 11", 11 + }, + { + "IRQ 12", 12 + }, + { + "" + } + } + }, + { + "", "", -1 + } +}; + +const device_t ide_ter_device = { + "Tertiary IDE Controller", + DEVICE_AT, + (HDD_BUS_IDE << 8) | 0, + ide_ter_init, ide_ter_close, NULL, + NULL, NULL, NULL, NULL, + ide_ter_config +}; + + +static const device_config_t ide_qua_config[] = { + { + "irq", "IRQ", CONFIG_SELECTION, "", 11, + { + { + "IRQ 2", 2 + }, + { + "IRQ 3", 3 + }, + { + "IRQ 4", 4 + }, + { + "IRQ 5", 5 + }, + { + "IRQ 7", 7 + }, + { + "IRQ 9", 9 + }, + { + "IRQ 10", 10 + }, + { + "IRQ 11", 11 + }, + { + "IRQ 12", 12 + }, + { + "" + } + } + }, + { + "", "", -1 + } +}; + +const device_t ide_qua_device = { + "Quaternary IDE Controller", + DEVICE_AT, + (HDD_BUS_IDE << 8) | 0, + ide_qua_init, ide_qua_close, NULL, + NULL, NULL, NULL, NULL, + ide_qua_config +}; diff --git a/src/devices/disk/hdc_ide_xta.c b/src/devices/disk/hdc_ide_xta.c index 872e0db..4a719c6 100644 --- a/src/devices/disk/hdc_ide_xta.c +++ b/src/devices/disk/hdc_ide_xta.c @@ -46,7 +46,7 @@ * * NOTE: The XTA interface is 0-based for sector numbers !! * - * Version: @(#)hdc_ide_xta.c 1.0.8 2018/05/11 + * Version: @(#)hdc_ide_xta.c 1.0.9 2018/10/05 * * Author: Fred N. van Kempen, * @@ -92,6 +92,7 @@ #include #include #include +#define dbglog hdc_log #include "../../emu.h" #include "../../io.h" #include "../../mem.h" @@ -247,6 +248,7 @@ typedef struct { int8_t irq; /* controller IRQ channel */ int8_t dma; /* controller DMA channel */ int8_t type; /* controller type ID */ + int8_t spt; /* sectors per track */ uint32_t rom_addr; /* address where ROM is */ rom_t bios_rom; /* descriptor for the BIOS */ @@ -296,20 +298,20 @@ static int get_sector(hdc_t *dev, drive_t *drive, off64_t *addr) { if (drive->cur_cyl != dev->track) { - hdc_log("%s: get_sector: wrong cylinder %d/%d\n", - dev->name, drive->cur_cyl, dev->track); + DEBUG("%s: get_sector: wrong cylinder %d/%d\n", + dev->name, drive->cur_cyl, dev->track); dev->sense = ERR_ILLADDR; return(1); } if (dev->head >= drive->hpc) { - hdc_log("%s: get_sector: past end of heads\n", dev->name); + DEBUG("%s: get_sector: past end of heads\n", dev->name); dev->sense = ERR_ILLADDR; return(1); } if (dev->sector >= drive->spt) { - hdc_log("%s: get_sector: past end of sectors\n", dev->name); + DEBUG("%s: get_sector: past end of sectors\n", dev->name); dev->sense = ERR_ILLADDR; return(1); } @@ -382,13 +384,12 @@ do_format(hdc_t *dev, drive_t *drive, dcb_t *dcb) dev->head = dcb->head; dev->sector = 0; -#ifdef ENABLE_HDC_LOG - hdc_log("%s: format_%s(%d) %d,%d\n", dev->name, - (dcb->cmd==CMD_FORMAT_DRIVE)?"drive":"track", - drive->id, dev->track, dev->head); -#endif + DEBUG("%s: format_%s(%d) %d,%d\n", dev->name, + (dcb->cmd==CMD_FORMAT_DRIVE)?"drive":"track", + drive->id, dev->track, dev->head); + /* Activate the status icon. */ - ui_sb_icon_update(SB_HDD|HDD_BUS_IDE, 1); + hdd_active(drive->hdd_num, 1); do_fmt: /* @@ -423,7 +424,7 @@ do_fmt: } /* De-activate the status icon. */ - ui_sb_icon_update(SB_HDD|HDD_BUS_IDE, 0); + hdd_active(drive->hdd_num, 0); } @@ -449,10 +450,9 @@ hdc_callback(void *priv) switch (dcb->cmd) { case CMD_TEST_READY: -#ifdef ENABLE_HDC_LOG - hdc_log("%s: test_ready(%d) ready=%d\n", - dev->name, dcb->drvsel, drive->present); -#endif + DEBUG("%s: test_ready(%d) ready=%d\n", + dev->name, dcb->drvsel, drive->present); + if (! drive->present) { dev->comp |= COMP_ERR; dev->sense = ERR_NOTRDY; @@ -461,10 +461,9 @@ hdc_callback(void *priv) break; case CMD_RECALIBRATE: -#ifdef ENABLE_HDC_LOG - hdc_log("%s: recalibrate(%d) ready=%d\n", - dev->name, dcb->drvsel, drive->present); -#endif + DEBUG("%s: recalibrate(%d) ready=%d\n", + dev->name, dcb->drvsel, drive->present); + if (! drive->present) { dev->comp |= COMP_ERR; dev->sense = ERR_NOTRDY; @@ -477,10 +476,9 @@ hdc_callback(void *priv) case CMD_READ_SENSE: switch(dev->state) { case STATE_IDLE: -#ifdef ENABLE_HDC_LOG - hdc_log("%s: sense(%d)\n", - dev->name, dcb->drvsel); -#endif + DEBUG("%s: sense(%d)\n", + dev->name, dcb->drvsel); + dev->buf_idx = 0; dev->buf_len = 4; dev->buf_ptr = dev->data; @@ -530,18 +528,17 @@ hdc_callback(void *priv) case STATE_SEND: /* Activate the status icon. */ - ui_sb_icon_update(SB_HDD|HDD_BUS_IDE, 1); -#ifdef ENABLE_HDC_LOG - hdc_log("%s: read_%s(%d: %d,%d,%d) cnt=%d\n", - dev->name, (no_data)?"verify":"sector", - drive->id, dev->track, dev->head, - dev->sector, dev->count); -#endif + hdd_active(drive->hdd_num, 1); + + DEBUG("%s: read_%s(%d: %d,%d,%d) cnt=%d\n", + dev->name, (no_data)?"verify":"sector", + drive->id, dev->track, dev->head, + dev->sector, dev->count); do_send: /* Get address of sector to load. */ if (get_sector(dev, drive, &addr)) { /* De-activate the status icon. */ - ui_sb_icon_update(SB_HDD|HDD_BUS_IDE, 0); + hdd_active(drive->hdd_num, 0); dev->comp |= COMP_ERR; set_intr(dev); return; @@ -581,7 +578,8 @@ do_send: val = dma_channel_write(dev->dma, *dev->buf_ptr); if (val == DMA_NODATA) { - hdc_log("%s: CMD_READ_SECTORS out of data (idx=%d, len=%d)!\n", dev->name, dev->buf_idx, dev->buf_len); + ERRLOG("%s: CMD_READ_SECTORS out of data (idx=%d, len=%d)!\n", + dev->name, dev->buf_idx, dev->buf_len); dev->status |= (STAT_CD | STAT_IO| STAT_REQ); dev->callback = HDC_TIME; @@ -598,14 +596,13 @@ do_send: case STATE_SDONE: dev->buf_idx = 0; if (--dev->count == 0) { -#ifdef ENABLE_HDC_LOG - hdc_log("%s: read_%s(%d) DONE\n", - dev->name, - (no_data)?"verify":"sector", - drive->id); -#endif + DEBUG("%s: read_%s(%d) DONE\n", + dev->name, + (no_data)?"verify":"sector", + drive->id); + /* De-activate the status icon. */ - ui_sb_icon_update(SB_HDD|HDD_BUS_IDE, 0); + hdd_active(drive->hdd_num, 0); set_intr(dev); return; @@ -653,13 +650,12 @@ do_send: case STATE_RECV: /* Activate the status icon. */ - ui_sb_icon_update(SB_HDD|HDD_BUS_IDE, 1); -#ifdef ENABLE_HDC_LOG - hdc_log("%s: write_%s(%d: %d,%d,%d) cnt=%d\n", - dev->name, (no_data)?"verify":"sector", - dcb->drvsel, dev->track, - dev->head, dev->sector, dev->count); -#endif + hdd_active(drive->hdd_num, 1); + + DEBUG("%s: write_%s(%d: %d,%d,%d) cnt=%d\n", + dev->name, (no_data)?"verify":"sector", + dcb->drvsel, dev->track, + dev->head, dev->sector, dev->count); do_recv: /* Ready to transfer the data in. */ dev->state = STATE_RDATA; @@ -687,9 +683,11 @@ do_recv: while (dev->buf_idx < dev->buf_len) { val = dma_channel_read(dev->dma); if (val == DMA_NODATA) { - hdc_log("%s: CMD_WRITE_SECTORS out of data (idx=%d, len=%d)!\n", dev->name, dev->buf_idx, dev->buf_len); + ERRLOG("%s: CMD_WRITE_SECTORS out of data (idx=%d, len=%d)!\n", + dev->name, dev->buf_idx, dev->buf_len); - hdc_log("%s: CMD_WRITE_SECTORS out of data!\n", dev->name); + ERRLOG("%s: CMD_WRITE_SECTORS out of data!\n", + dev->name); dev->status |= (STAT_CD | STAT_IO | STAT_REQ); dev->callback = HDC_TIME; return; @@ -712,7 +710,7 @@ do_recv: /* Get address of sector to write. */ if (get_sector(dev, drive, &addr)) { /* De-activate the status icon. */ - ui_sb_icon_update(SB_HDD|HDD_BUS_IDE, 0); + hdd_active(drive->hdd_num, 0); dev->comp |= COMP_ERR; set_intr(dev); @@ -725,13 +723,13 @@ do_recv: dev->buf_idx = 0; if (--dev->count == 0) { -#ifdef ENABLE_HDC_LOG - hdc_log("HDC: write_%s(%d) DONE\n", - (no_data)?"verify":"sector", - drive->id); -#endif + DEBUG("%s: write_%s(%d) DONE\n", + dev->name, + (no_data)?"verify":"sector", + drive->id); + /* De-activate the status icon. */ - ui_sb_icon_update(SB_HDD|HDD_BUS_IDE, 0); + hdd_active(drive->hdd_num, 0); set_intr(dev); return; @@ -760,10 +758,10 @@ do_recv: case CMD_SEEK: /* Seek to cylinder. */ val = (dcb->cyl_low | (dcb->cyl_high << 8)); -#ifdef ENABLE_HDC_LOG - hdc_log("%s: seek(%d) %d/%d ready=%d\n", dev->name, - dcb->drvsel, val, drive->cur_cyl, drive->present); -#endif + + DEBUG("%s: seek(%d) %d/%d ready=%d\n", dev->name, + dcb->drvsel, val, drive->cur_cyl, drive->present); + if (drive->present) { do_seek(dev, drive, val); if (val != drive->cur_cyl) { @@ -792,12 +790,12 @@ do_recv: drive->tracks = (params->cyl_high << 8) | params->cyl_low; drive->hpc = params->heads; - drive->spt = 17 /*hardcoded*/; -#ifdef ENABLE_HDC_LOG - hdc_log("%s: set_params(%d) cyl=%d,hd=%d,spt=%d\n", - dev->name, dcb->drvsel, drive->tracks, - drive->hpc, drive->spt); -#endif + drive->spt = dev->spt; /*hardcoded*/ + + INFO("%s: set_params(%d) cyl=%d,hd=%d,spt=%d\n", + dev->name, dcb->drvsel, drive->tracks, + drive->hpc, drive->spt); + dev->status &= ~STAT_REQ; set_intr(dev); break; @@ -807,10 +805,7 @@ do_recv: case CMD_WRITE_SECTOR_BUFFER: switch (dev->state) { case STATE_IDLE: -#ifdef ENABLE_HDC_LOG - hdc_log("%s: write_sector_buffer()\n", - dev->name); -#endif + DEBUG("%s: write_sector_buffer()\n", dev->name); dev->buf_idx = 0; dev->buf_len = 512; dev->state = STATE_RDATA; @@ -829,7 +824,8 @@ do_recv: while (dev->buf_idx < dev->buf_len) { val = dma_channel_read(dev->dma); if (val == DMA_NODATA) { - hdc_log("%s: CMD_WRITE_BUFFER out of data!\n", dev->name); + ERRLOG("%s: CMD_WRITE_BUFFER out of data!\n", + dev->name); dev->status |= (STAT_CD | STAT_IO | STAT_REQ); dev->callback = HDC_TIME; return; @@ -855,9 +851,7 @@ do_recv: case CMD_RAM_DIAGS: switch(dev->state) { case STATE_IDLE: -#ifdef ENABLE_HDC_LOG - hdc_log("%s: ram_diags\n", dev->name); -#endif + DEBUG("%s: ram_diags\n", dev->name); dev->state = STATE_RDONE; dev->callback = 5*HDC_TIME; break; @@ -871,10 +865,9 @@ do_recv: case CMD_DRIVE_DIAGS: switch(dev->state) { case STATE_IDLE: -#ifdef ENABLE_HDC_LOG - hdc_log("%s: drive_diags(%d) ready=%d\n", - dev->name, dcb->drvsel, drive->present); -#endif + DEBUG("%s: drive_diags(%d) ready=%d\n", + dev->name, dcb->drvsel, drive->present); + if (drive->present) { dev->state = STATE_RDONE; dev->callback = 5*HDC_TIME; @@ -894,9 +887,7 @@ do_recv: case CMD_CTRL_DIAGS: switch(dev->state) { case STATE_IDLE: -#ifdef ENABLE_HDC_LOG - hdc_log("%s: ctrl_diags\n", dev->name); -#endif + DEBUG("%s: ctrl_diags\n", dev->name); dev->state = STATE_RDONE; dev->callback = 10*HDC_TIME; break; @@ -908,7 +899,7 @@ do_recv: break; default: - hdc_log("%s: unknown command - %02x\n", dev->name, dcb->cmd); + DEBUG("%s: unknown command - %02x\n", dev->name, dcb->cmd); dev->comp |= COMP_ERR; dev->sense = ERR_ILLCMD; set_intr(dev); @@ -929,8 +920,8 @@ hdc_read(uint16_t port, void *priv) if (dev->state == STATE_SDATA) { if (dev->buf_idx > dev->buf_len) { - hdc_log("%s: read with empty buffer!\n", - dev->name); + DEBUG("%s: read with empty buffer!\n", + dev->name); dev->comp |= COMP_ERR; dev->sense = ERR_ILLCMD; break; @@ -973,14 +964,16 @@ hdc_write(uint16_t port, uint8_t val, void *priv) case 0: /* DATA register */ if (dev->state == STATE_RDATA) { if (! (dev->status & STAT_REQ)) { - hdc_log("%s: not ready for command/data!\n", dev->name); + DEBUG("%s: not ready for command/data!\n", + dev->name); dev->comp |= COMP_ERR; dev->sense = ERR_ILLCMD; break; } if (dev->buf_idx >= dev->buf_len) { - hdc_log("%s: write with full buffer!\n", dev->name); + DEBUG("%s: write with full buffer!\n", + dev->name); dev->comp |= COMP_ERR; dev->sense = ERR_ILLCMD; break; @@ -1029,11 +1022,13 @@ xta_init(const device_t *info) wchar_t *fn = NULL; hdc_t *dev; int c, i; + int bus; /* Allocate and initialize device block. */ - dev = malloc(sizeof(hdc_t)); + dev = (hdc_t *)mem_alloc(sizeof(hdc_t)); memset(dev, 0x00, sizeof(hdc_t)); - dev->type = info->local; + dev->type = info->local & 255; + bus = (info->local >> 8) & 255; /* Do per-controller-type setup. */ switch(dev->type) { @@ -1043,6 +1038,7 @@ xta_init(const device_t *info) dev->irq = device_get_config_int("irq"); dev->rom_addr = device_get_config_hex20("bios_addr"); dev->dma = 3; + dev->spt = 17; /* MFM */ fn = WD_BIOS_FILE; break; @@ -1051,19 +1047,30 @@ xta_init(const device_t *info) dev->base = 0x0320; dev->irq = 5; dev->dma = 3; + dev->spt = 17; /* MFM */ + break; + + case 2: /* Toshiba T1200 */ + dev->name = "T1200-HD"; + dev->base = 0x0320; + dev->irq = 5; + dev->dma = 3; + dev->rom_addr = 0xc8000; + dev->spt = 17; + fn = WD_BIOS_FILE; break; } - pclog("%s: initializing (I/O=%04X, IRQ=%d, DMA=%d", + INFO("%s: initializing (I/O=%04X, IRQ=%d, DMA=%d", dev->name, dev->base, dev->irq, dev->dma); if (dev->rom_addr != 0x000000) - pclog(", BIOS=%06X", dev->rom_addr); - pclog(")\n"); + INFO(", BIOS=%06X", dev->rom_addr); + INFO(")\n"); /* Load any disks for this device class. */ c = 0; for (i = 0; i < HDD_NUM; i++) { - if ((hdd[i].bus == HDD_BUS_IDE) && (hdd[i].id.ide_channel < XTA_NUM)) { + if ((hdd[i].bus == bus) && (hdd[i].id.ide_channel < XTA_NUM)) { drive = &dev->drives[hdd[i].id.ide_channel]; if (! hdd_image_load(i)) { @@ -1084,9 +1091,9 @@ xta_init(const device_t *info) drive->hpc = drive->cfg_hpc; drive->tracks = drive->cfg_tracks; - pclog("%s: drive%d (cyl=%d,hd=%d,spt=%d), disk %d\n", - dev->name, hdd[i].id.ide_channel, drive->tracks, - drive->hpc, drive->spt, i); + INFO("%s: drive%d (cyl=%d,hd=%d,spt=%d), disk %d\n", + dev->name, hdd[i].id.ide_channel, drive->tracks, + drive->hpc, drive->spt, i); if (++c > XTA_NUM) break; } @@ -1132,68 +1139,77 @@ xta_close(void *priv) static const device_config_t wdxt150_config[] = { + { + "base", "Address", CONFIG_HEX16, "", 0x0320, /*W2*/ { - "base", "Address", CONFIG_HEX16, "", 0x0320, /*W2*/ { - { - "320H", 0x0320 - }, - { - "324H", 0x0324 - }, - { - "" - } + "320H", 0x0320 }, - }, + { + "324H", 0x0324 + }, + { + "" + } + } + }, + { + "irq", "IRQ", CONFIG_SELECTION, "", 5, /*W3*/ { - "irq", "IRQ", CONFIG_SELECTION, "", 5, /*W3*/ { - { - "IRQ 5", 5 - }, - { - "IRQ 4", 4 - }, - { - "" - } + "IRQ 5", 5 }, - }, + { + "IRQ 4", 4 + }, + { + "" + } + } + }, + { + "bios_addr", "BIOS Address", CONFIG_HEX20, "", 0xc8000, /*W1*/ { - "bios_addr", "BIOS Address", CONFIG_HEX20, "", 0xc8000, /*W1*/ { - { - "C800H", 0xc8000 - }, - { - "CA00H", 0xca000 - }, - { - "" - } + "C800H", 0xc8000 }, - }, - { - "", "", -1 - } + { + "CA00H", 0xca000 + }, + { + "" + } + } + }, + { + "", "", -1 + } }; const device_t xta_wdxt150_device = { - "WDXT-150 Fixed Disk Controller", + "WDXT-150 XTA Fixed Disk Controller", DEVICE_ISA, - 0, + (HDD_BUS_IDE << 8) | 0, xta_init, xta_close, NULL, NULL, NULL, NULL, NULL, wdxt150_config }; - const device_t xta_hd20_device = { "EuroPC HD20 Fixed Disk Controller", DEVICE_ISA, - 1, + (HDD_BUS_IDE << 8) | 1, + xta_init, xta_close, NULL, + NULL, NULL, NULL, NULL, + NULL +}; + + +const device_t xta_t1200_device = { + "Toshiba T1200 Fixed Disk Controller", + DEVICE_ISA, + (HDD_BUS_IDE << 8) | 2, xta_init, xta_close, NULL, NULL, NULL, NULL, NULL, NULL diff --git a/src/devices/disk/hdc_st506_at.c b/src/devices/disk/hdc_st506_at.c index e9bed03..cac46f6 100644 --- a/src/devices/disk/hdc_st506_at.c +++ b/src/devices/disk/hdc_st506_at.c @@ -12,7 +12,7 @@ * based design. Most cards were WD1003-WA2 or -WAH, where the * -WA2 cards had a floppy controller as well (to save space.) * - * Version: @(#)hdc_st506_at.c 1.0.9 2018/06/08 + * Version: @(#)hdc_st506_at.c 1.0.11 2018/09/22 * * Authors: Fred N. van Kempen, * Sarah Walker, @@ -46,6 +46,7 @@ #include #include #include +#define dbglog hdc_log #include "../../emu.h" #include "../../cpu/cpu.h" #include "../../machines/machine.h" @@ -102,7 +103,6 @@ typedef struct { int16_t curcyl; /* current track number */ } drive_t; - typedef struct { uint8_t precomp, /* 1: precomp/error register */ error, @@ -131,36 +131,19 @@ typedef struct { static __inline void irq_raise(hdc_t *dev) { -#if 0 - /* If not already pending.. */ - if (! dev->irqstat) { -#endif - /* If enabled in the control register.. */ - if (! (dev->fdisk & 0x02)) { - /* .. raise IRQ14. */ - picint(1<<14); - } + if (! (dev->fdisk & 0x02)) + picint(1 << 14); - /* Remember this. */ - dev->irqstat = 1; -#if 0 - } -#endif + dev->irqstat = 1; } static __inline void irq_lower(hdc_t *dev) { - /* If raised.. */ if (dev->irqstat) { - /* If enabled in the control register.. */ - if (! (dev->fdisk & 0x02)) { - /* .. drop IRQ14. */ + if (! (dev->fdisk & 0x02)) picintc(1<<14); - } - - /* Remember this. */ dev->irqstat = 0; } } @@ -184,41 +167,31 @@ get_sector(hdc_t *dev, off64_t *addr) drive_t *drive = &dev->drives[dev->drvsel]; if (drive->curcyl != dev->cylinder) { -#ifdef ENABLE_HDC_LOG - hdc_log("WD1003(%d) sector: wrong cylinder\n"); -#endif + DEBUG("WD1003(%d) sector: wrong cylinder\n"); return(1); } if (dev->head > drive->cfg_hpc) { -#ifdef ENABLE_HDC_LOG - hdc_log("WD1003(%d) get_sector: past end of configured heads\n", + DEBUG("WD1003(%d) get_sector: past end of configured heads\n", dev->drvsel); -#endif return(1); } if (dev->sector >= drive->cfg_spt+1) { -#ifdef ENABLE_HDC_LOG - hdc_log("WD1003(%d) get_sector: past end of configured sectors\n", + DEBUG("WD1003(%d) get_sector: past end of configured sectors\n", dev->drvsel); -#endif return(1); } #if 1 /* We should check this in the SET_DRIVE_PARAMETERS command! --FvK */ if (dev->head > drive->hpc) { -#ifdef ENABLE_HDC_LOG - hdc_log("WD1003(%d) get_sector: past end of heads\n", dev->drvsel); -#endif + DEBUG("WD1003(%d) get_sector: past end of heads\n", dev->drvsel); return(1); } if (dev->sector >= drive->spt+1) { -#ifdef ENABLE_HDC_LOG - hdc_log("WD1003(%d) get_sector: past end of sectors\n", dev->drvsel); -#endif + DEBUG("WD1003(%d) get_sector: past end of sectors\n", dev->drvsel); return(1); } #endif @@ -255,10 +228,8 @@ hdc_cmd(hdc_t *dev, uint8_t val) if (! drive->present) { /* This happens if sofware polls all drives. */ -#ifdef ENABLE_HDC_LOG - hdc_log("WD1003(%d) command %02x on non-present drive\n", + DEBUG("WD1003(%d) command %02x on non-present drive\n", dev->drvsel, val); -#endif dev->command = 0xff; dev->status = STAT_BUSY; timer_clock(); @@ -269,24 +240,23 @@ hdc_cmd(hdc_t *dev, uint8_t val) } irq_lower(dev); + dev->command = val; dev->error = 0; switch (val & 0xf0) { case CMD_RESTORE: drive->steprate = (val & 0x0f); -#ifdef ENABLE_HDC_LOG - hdc_log("WD1003(%d) restore, step=%d\n", + DEBUG("WD1003(%d) restore, step=%d\n", dev->drvsel, drive->steprate); -#endif drive->curcyl = 0; dev->status = STAT_READY|STAT_DSC; - dev->command = 0x00; + dev->command &= 0xf0; irq_raise(dev); break; case CMD_SEEK: drive->steprate = (val & 0x0f); - dev->command = (val & 0xf0); + dev->command &= 0xf0; dev->status = STAT_BUSY; timer_clock(); dev->callback = 200LL*ST506_TIME; @@ -299,11 +269,9 @@ hdc_cmd(hdc_t *dev, uint8_t val) case CMD_READ+1: case CMD_READ+2: case CMD_READ+3: -#ifdef ENABLE_HDC_LOG - hdc_log("WD1003(%d) read, opt=%d\n", + DEBUG("WD1003(%d) read, opt=%d\n", dev->drvsel, val&0x03); -#endif - dev->command = (val & 0xf0); + dev->command &= 0xfc; if (val & 2) fatal("WD1003: READ with ECC\n"); dev->status = STAT_BUSY; @@ -316,11 +284,9 @@ hdc_cmd(hdc_t *dev, uint8_t val) case CMD_WRITE+1: case CMD_WRITE+2: case CMD_WRITE+3: -#ifdef ENABLE_HDC_LOG - hdc_log("WD1003(%d) write, opt=%d\n", + DEBUG("WD1003(%d) write, opt=%d\n", dev->drvsel, val & 0x03); -#endif - dev->command = (val & 0xf0); + dev->command &= 0xfc; if (val & 2) fatal("WD1003: WRITE with ECC\n"); dev->status = STAT_DRQ|STAT_DSC; @@ -329,7 +295,7 @@ hdc_cmd(hdc_t *dev, uint8_t val) case CMD_VERIFY: case CMD_VERIFY+1: - dev->command = (val & 0xfe); + dev->command &= 0xfe; dev->status = STAT_BUSY; timer_clock(); dev->callback = 200LL*ST506_TIME; @@ -337,13 +303,11 @@ hdc_cmd(hdc_t *dev, uint8_t val) break; case CMD_FORMAT: - dev->command = val; dev->status = STAT_DRQ|STAT_BUSY; dev->pos = 0; break; case CMD_DIAGNOSE: - dev->command = val; dev->status = STAT_BUSY; timer_clock(); dev->callback = 200LL*ST506_TIME; @@ -354,10 +318,10 @@ hdc_cmd(hdc_t *dev, uint8_t val) /* * NOTE: * - * We currently just set these parameters, and - * never bother to check if they "fit within" - * the actual parameters, as determined by the - * image loader. + * We currently just set these parameters, + * and never bother to check if they "fit + * within" the actual parameters, as + * determined by the image loader. * * The difference in parameters is OK, and * occurs when the BIOS or operating system @@ -371,17 +335,13 @@ hdc_cmd(hdc_t *dev, uint8_t val) /* Only accept after RESET or DIAG. */ drive->cfg_spt = dev->secount; drive->cfg_hpc = dev->head+1; -#ifdef ENABLE_HDC_LOG - hdc_log("WD1003(%d) parameters: tracks=%d, spt=%i, hpc=%i\n", - dev->drvsel, drive->tracks, - drive->cfg_spt, drive->cfg_hpc); -#endif + DEBUG("WD1003(%d) parameters: tracks=%d, spt=%i, hpc=%i\n", + dev->drvsel, drive->tracks, + drive->cfg_spt, drive->cfg_hpc); } else { -#ifdef ENABLE_HDC_LOG - hdc_log("WD1003(%d) parameters: tracks=%d,spt=%i,hpc=%i (IGNORED)\n", - dev->drvsel, drive->tracks, - drive->cfg_spt, drive->cfg_hpc); -#endif + DEBUG("WD1003(%d) parameters: tracks=%d,spt=%i,hpc=%i (IGNORED)\n", + dev->drvsel, drive->tracks, + drive->cfg_spt, drive->cfg_hpc); } dev->command = 0x00; dev->status = STAT_READY|STAT_DSC; @@ -390,9 +350,7 @@ hdc_cmd(hdc_t *dev, uint8_t val) break; default: -#ifdef ENABLE_HDC_LOG - hdc_log("WD1003: bad command %02X\n", val); -#endif + DEBUG("WD1003: bad command %02X\n", val); dev->status = STAT_BUSY; timer_clock(); dev->callback = 200LL*ST506_TIME; @@ -429,9 +387,8 @@ hdc_write(uint16_t port, uint8_t val, void *priv) { hdc_t *dev = (hdc_t *)priv; -#ifdef ENABLE_HDC_LOG - hdc_log("WD1003 write(%04x, %02x)\n", port, val); -#endif + DBGLOG(2, "WD1003 write(%04x, %02x)\n", port, val); + switch (port) { case 0x01f0: /* data */ hdc_writew(port, val | (val << 8), priv); @@ -473,24 +430,24 @@ hdc_write(uint16_t port, uint8_t val, void *priv) case 0x03f6: /* device control */ val &= 0x0f; if ((dev->fdisk & 0x04) && !(val & 0x04)) { - dev->status = STAT_BUSY; - dev->reset = 1; timer_clock(); dev->callback = 500LL*ST506_TIME; timer_update_outstanding(); + dev->reset = 1; + dev->status = STAT_BUSY; } if (val & 0x04) { /* Drive held in reset. */ - dev->status = STAT_BUSY; - dev->callback = 0LL; timer_clock(); + dev->callback = 0LL; timer_update_outstanding(); + dev->status = STAT_BUSY; } dev->fdisk = val; /* Lower IRQ on IRQ disable. */ - if ((val & 2) && !(dev->fdisk & 0x02)) + if ((val & 0x02) && !(dev->fdisk & 0x02)) picintc(1 << 14); break; } @@ -519,8 +476,6 @@ hdc_readw(uint16_t port, void *priv) dev->callback = ((3125LL * TIMER_USEC) / 4LL); timer_update_outstanding(); - } else { - ui_sb_icon_update(SB_HDD|HDD_BUS_ST506, 0); } } } @@ -572,9 +527,8 @@ hdc_read(uint16_t port, void *priv) default: break; } -#ifdef ENABLE_HDC_LOG - hdc_log("WD1003 read(%04x) = %02x\n", port, ret); -#endif + + DBGLOG(2, "WD1003 read(%04x) = %02x\n", port, ret); return(ret); } @@ -585,10 +539,9 @@ do_seek(hdc_t *dev) { drive_t *drive = &dev->drives[dev->drvsel]; -#ifdef ENABLE_HDC_LOG - hdc_log("WD1003(%d) seek(%d) max=%d\n", - dev->drvsel,dev->cylinder,drive->tracks); -#endif + DEBUG("WD1003(%d) seek(%d) max=%d\n", + dev->drvsel,dev->cylinder,drive->tracks); + if (dev->cylinder < drive->tracks) drive->curcyl = dev->cylinder; else @@ -605,9 +558,8 @@ do_callback(void *priv) dev->callback = 0LL; if (dev->reset) { -#ifdef ENABLE_HDC_LOG - hdc_log("WD1003(%d) reset\n", dev->drvsel); -#endif + DEBUG("WD1003(%d) reset\n", dev->drvsel); + dev->status = STAT_READY|STAT_DSC; dev->error = 1; dev->secount = 1; @@ -620,27 +572,23 @@ do_callback(void *priv) dev->reset = 0; - ui_sb_icon_update(SB_HDD|HDD_BUS_ST506, 0); + hdd_active(drive->hdd_num, 0); return; } switch (dev->command) { case CMD_SEEK: -#ifdef ENABLE_HDC_LOG - hdc_log("WD1003(%d) seek, step=%d\n", - dev->drvsel, drive->steprate); -#endif + DEBUG("WD1003(%d) seek, step=%d\n", + dev->drvsel, drive->steprate); do_seek(dev); dev->status = STAT_READY|STAT_DSC; irq_raise(dev); break; case CMD_READ: -#ifdef ENABLE_HDC_LOG - hdc_log("WD1003(%d) read(%d,%d,%d)\n", - dev->drvsel, dev->cylinder, dev->head, dev->sector); -#endif + DEBUG("WD1003(%d) read(%d,%d,%d)\n", + dev->drvsel, dev->cylinder, dev->head, dev->sector); do_seek(dev); if (get_sector(dev, &addr)) { dev->error = ERR_ID_NOT_FOUND; @@ -654,14 +602,12 @@ do_callback(void *priv) dev->pos = 0; dev->status = STAT_DRQ|STAT_READY|STAT_DSC; irq_raise(dev); - ui_sb_icon_update(SB_HDD|HDD_BUS_ST506, 1); + hdd_active(drive->hdd_num, 1); break; case CMD_WRITE: -#ifdef ENABLE_HDC_LOG - hdc_log("WD1003(%d) write(%d,%d,%d)\n", - dev->drvsel, dev->cylinder, dev->head, dev->sector); -#endif + DEBUG("WD1003(%d) write(%d,%d,%d)\n", + dev->drvsel, dev->cylinder, dev->head, dev->sector); do_seek(dev); if (get_sector(dev, &addr)) { dev->error = ERR_ID_NOT_FOUND; @@ -671,38 +617,33 @@ do_callback(void *priv) } hdd_image_write(drive->hdd_num, addr, 1,(uint8_t *)dev->buffer); + irq_raise(dev); + dev->secount = (dev->secount - 1) & 0xff; dev->status = STAT_READY|STAT_DSC; - dev->secount = (dev->secount - 1) & 0xff; if (dev->secount) { /* More sectors to do.. */ dev->status |= STAT_DRQ; dev->pos = 0; next_sector(dev); - ui_sb_icon_update(SB_HDD|HDD_BUS_ST506, 1); - } else { - ui_sb_icon_update(SB_HDD|HDD_BUS_ST506, 0); - } - irq_raise(dev); + hdd_active(drive->hdd_num, 1); + } else + hdd_active(drive->hdd_num, 0); break; case CMD_VERIFY: -#ifdef ENABLE_HDC_LOG - hdc_log("WD1003(%d) verify(%d,%d,%d)\n", - dev->drvsel, dev->cylinder, dev->head, dev->sector); -#endif + DEBUG("WD1003(%d) verify(%d,%d,%d)\n", + dev->drvsel, dev->cylinder, dev->head, dev->sector); do_seek(dev); dev->pos = 0; dev->status = STAT_READY|STAT_DSC; irq_raise(dev); - ui_sb_icon_update(SB_HDD|HDD_BUS_ST506, 1); + hdd_active(drive->hdd_num, 1); break; case CMD_FORMAT: -#ifdef ENABLE_HDC_LOG - hdc_log("WD1003(%d) format(%d,%d)\n", - dev->drvsel, dev->cylinder, dev->head); -#endif + DEBUG("WD1003(%d) format(%d,%d)\n", + dev->drvsel, dev->cylinder, dev->head); do_seek(dev); if (get_sector(dev, &addr)) { dev->error = ERR_ID_NOT_FOUND; @@ -715,13 +656,11 @@ do_callback(void *priv) dev->status = STAT_READY|STAT_DSC; irq_raise(dev); - ui_sb_icon_update(SB_HDD|HDD_BUS_ST506, 1); + hdd_active(drive->hdd_num, 1); break; case CMD_DIAGNOSE: -#ifdef ENABLE_HDC_LOG - hdc_log("WD1003(%d) diag\n", dev->drvsel); -#endif + DEBUG("WD1003(%d) diag\n", dev->drvsel); drive->steprate = 0x0f; dev->error = 1; dev->status = STAT_READY|STAT_DSC; @@ -729,10 +668,8 @@ do_callback(void *priv) break; default: -#ifdef ENABLE_HDC_LOG - hdc_log("WD1003(%d) callback on unknown command %02x\n", + DEBUG("WD1003(%d) callback on unknown command %02x\n", dev->drvsel, dev->command); -#endif dev->status = STAT_READY|STAT_ERR|STAT_DSC; dev->error = ERR_ABRT; irq_raise(dev); @@ -766,21 +703,20 @@ st506_init(const device_t *info) hdc_t *dev; int c, d; -#ifdef ENABLE_HDC_LOG - hdc_log("WD1003: ISA ST506/RLL Fixed Disk Adapter initializing ...\n"); -#endif - dev = malloc(sizeof(hdc_t)); + dev = (hdc_t *)mem_alloc(sizeof(hdc_t)); memset(dev, 0x00, sizeof(hdc_t)); + INFO("HDC: WD1003: ISA ST506/RLL Fixed Disk Adapter initializing ...\n"); + c = 0; - for (d=0; d= ST506_NUM) break; } @@ -798,8 +734,6 @@ st506_init(const device_t *info) timer_add(do_callback, &dev->callback, &dev->callback, dev); - ui_sb_icon_update(SB_HDD|HDD_BUS_ST506, 0); - return(dev); } @@ -810,7 +744,7 @@ st506_close(void *priv) hdc_t *dev = (hdc_t *)priv; int d; - for (d=0; d<2; d++) { + for (d = 0; d < 2; d++) { drive_t *drive = &dev->drives[d]; hdd_image_close(drive->hdd_num); @@ -818,14 +752,14 @@ st506_close(void *priv) free(dev); - ui_sb_icon_update(SB_HDD|HDD_BUS_ST506, 0); + ui_sb_icon_update(SB_DISK|HDD_BUS_ST506, 0); } const device_t st506_at_wd1003_device = { - "WD1003 AT MFM/RLL Controller", + "IBM PC/AT Fixed Disk Adapter", DEVICE_ISA | DEVICE_AT, - 0, + (HDD_BUS_ST506 << 8) | 0, st506_init, st506_close, NULL, NULL, NULL, NULL, NULL, NULL diff --git a/src/devices/disk/hdc_st506_xt.c b/src/devices/disk/hdc_st506_xt.c index ddf2507..aea54d1 100644 --- a/src/devices/disk/hdc_st506_xt.c +++ b/src/devices/disk/hdc_st506_xt.c @@ -41,7 +41,7 @@ * Since all controllers (including the ones made by DTC) use * (mostly) the same API, we keep them all in this module. * - * Version: @(#)hdc_st506_xt.c 1.0.12 2018/08/27 + * Version: @(#)hdc_st506_xt.c 1.0.13 2018/10/05 * * Authors: Fred N. van Kempen, * Sarah Walker, @@ -75,6 +75,7 @@ #include #include #include +#define dbglog hdc_log #include "../../emu.h" #include "../../io.h" #include "../../mem.h" @@ -89,12 +90,45 @@ #include "hdd.h" -#define ST506_TIME (2000LL*TIMER_USEC) - #define XEBEC_BIOS_FILE L"disk/st506/ibm_xebec_62x0822_1985.bin" #define DTC_BIOS_FILE L"disk/st506/dtc_cxd21a.bin" +#define ST506_TIME (50LL*TIMER_USEC) + +#define STAT_IRQ 0x20 +#define STAT_DRQ 0x10 +#define STAT_BSY 0x08 +#define STAT_CD 0x04 +#define STAT_IO 0x02 +#define STAT_REQ 0x01 + +#define IRQ_ENA 0x02 +#define DMA_ENA 0x01 + +#define CMD_TEST_DRIVE_READY 0x00 +#define CMD_RECALIBRATE 0x01 +#define CMD_READ_STATUS 0x03 +#define CMD_VERIFY_SECTORS 0x05 +#define CMD_FORMAT_TRACK 0x06 +#define CMD_READ_SECTORS 0x08 +#define CMD_WRITE_SECTORS 0x0a +#define CMD_SEEK 0x0b +#define CMD_INIT_DRIVE_PARAMS 0x0c +#define CMD_WRITE_SECTOR_BUFFER 0x0f +#define CMD_BUFFER_DIAGNOSTIC 0xe0 +#define CMD_CONTROLLER_DIAGNOSTIC 0xe4 + +#define CMD_DTC_GET_DRIVE_PARAMS 0xfb +#define CMD_DTC_SET_STEP_RATE 0xfc +#define CMD_DTC_SET_GEOMETRY 0xfe +#define CMD_DTC_GET_GEOMETRY 0xff + +#define ERR_NOT_READY 0x04 +#define ERR_SEEK_ERROR 0x15 +#define ERR_ILLEGAL_SECTOR_ADDRESS 0x21 + + enum { STATE_IDLE, STATE_RECEIVE_COMMAND, @@ -135,7 +169,7 @@ typedef struct { uint8_t completion_byte; uint8_t error; int drive_sel; - drive_t drives[2]; + drive_t drives[ST506_NUM]; int sector, head, cylinder; @@ -143,37 +177,17 @@ typedef struct { uint8_t switches; } hdc_t; -#define STAT_IRQ 0x20 -#define STAT_DRQ 0x10 -#define STAT_BSY 0x08 -#define STAT_CD 0x04 -#define STAT_IO 0x02 -#define STAT_REQ 0x01 -#define IRQ_ENA 0x02 -#define DMA_ENA 0x01 - -#define CMD_TEST_DRIVE_READY 0x00 -#define CMD_RECALIBRATE 0x01 -#define CMD_READ_STATUS 0x03 -#define CMD_VERIFY_SECTORS 0x05 -#define CMD_FORMAT_TRACK 0x06 -#define CMD_READ_SECTORS 0x08 -#define CMD_WRITE_SECTORS 0x0a -#define CMD_SEEK 0x0b -#define CMD_INIT_DRIVE_PARAMS 0x0c -#define CMD_WRITE_SECTOR_BUFFER 0x0f -#define CMD_BUFFER_DIAGNOSTIC 0xe0 -#define CMD_CONTROLLER_DIAGNOSTIC 0xe4 - -#define CMD_DTC_GET_DRIVE_PARAMS 0xfb -#define CMD_DTC_SET_STEP_RATE 0xfc -#define CMD_DTC_SET_GEOMETRY 0xfe -#define CMD_DTC_GET_GEOMETRY 0xff - -#define ERR_NOT_READY 0x04 -#define ERR_SEEK_ERROR 0x15 -#define ERR_ILLEGAL_SECTOR_ADDRESS 0x21 +static const struct { + uint16_t tracks; + uint8_t hpc; + uint8_t spt; +} hd_types[4] = { + { 306, 4, 17 }, /* Type 0 */ + { 612, 4, 17 }, /* Type 16 */ + { 615, 4, 17 }, /* Type 2 */ + { 306, 8, 17 } /* Type 13 */ +}; static uint8_t @@ -263,7 +277,7 @@ st506_write(uint16_t port, uint8_t val, void *priv) break; default: - hdc_log("Write data unknown state - %i %02x\n", dev->state, dev->status); + DEBUG("Write data unknown state - %i %02x\n", dev->state, dev->status); } break; @@ -303,9 +317,7 @@ st506_error(hdc_t *dev, uint8_t error) dev->completion_byte |= 0x02; dev->error = error; -#ifdef ENABLE_HDC_LOG - hdc_log("st506_error - %02x\n", dev->error); -#endif + DEBUG("st506_error - %02x\n", dev->error); } @@ -316,30 +328,22 @@ get_sector(hdc_t *dev, off64_t *addr) int heads = drive->cfg_hpc; if (drive->current_cylinder != dev->cylinder) { -#ifdef ENABLE_HDC_LOG - hdc_log("st506_get_sector: wrong cylinder\n"); -#endif + DEBUG("st506_get_sector: wrong cylinder\n"); dev->error = ERR_ILLEGAL_SECTOR_ADDRESS; return(1); } if (dev->head > heads) { -#ifdef ENABLE_HDC_LOG - hdc_log("st506_get_sector: past end of configured heads\n"); -#endif + DEBUG("st506_get_sector: past end of configured heads\n"); dev->error = ERR_ILLEGAL_SECTOR_ADDRESS; return(1); } if (dev->head > drive->hpc) { -#ifdef ENABLE_HDC_LOG - hdc_log("st506_get_sector: past end of heads\n"); -#endif + DEBUG("st506_get_sector: past end of heads\n"); dev->error = ERR_ILLEGAL_SECTOR_ADDRESS; return(1); } if (dev->sector >= 17) { -#ifdef ENABLE_HDC_LOG - hdc_log("st506_get_sector: past end of sectors\n"); -#endif + DEBUG("st506_get_sector: past end of sectors\n"); dev->error = ERR_ILLEGAL_SECTOR_ADDRESS; return(1); } @@ -430,9 +434,7 @@ st506_callback(void *priv) dev->sector_count = dev->command[4]; do { if (get_sector(dev, &addr)) { -#ifdef ENABLE_HDC_LOG - hdc_log("get_sector failed\n"); -#endif + DEBUG("get_sector failed\n"); st506_error(dev, dev->error); st506_complete(dev); return; @@ -445,7 +447,7 @@ st506_callback(void *priv) st506_complete(dev); - ui_sb_icon_update(SB_HDD | HDD_BUS_ST506, 1); + hdd_active(drive->hdd_num, 1); break; default: @@ -459,9 +461,7 @@ st506_callback(void *priv) dev->head = dev->command[1] & 0x1f; if (get_sector(dev, &addr)) { -#ifdef ENABLE_HDC_LOG - hdc_log("get_sector failed\n"); -#endif + DEBUG("get_sector failed\n"); st506_error(dev, dev->error); st506_complete(dev); return; @@ -490,9 +490,10 @@ st506_callback(void *priv) return; } + hdd_active(drive->hdd_num, 1); + hdd_image_read(drive->hdd_num, addr, 1, (uint8_t *) dev->sector_buf); - ui_sb_icon_update(SB_HDD|HDD_BUS_ST506, 1); if (dev->irq_dma_mask & DMA_ENA) dev->callback = ST506_TIME; @@ -509,9 +510,7 @@ st506_callback(void *priv) int val = dma_channel_write(3, dev->sector_buf[dev->data_pos]); if (val == DMA_NODATA) { -#ifdef ENABLE_HDC_LOG - hdc_log("CMD_READ_SECTORS out of data!\n"); -#endif + ERRLOG("HDC: CMD_READ_SECTORS out of data!\n"); dev->status = STAT_BSY | STAT_CD | STAT_IO | STAT_REQ; dev->callback = ST506_TIME; return; @@ -519,8 +518,7 @@ st506_callback(void *priv) } dev->state = STATE_SENT_DATA; dev->callback = ST506_TIME; - } else - fatal("Read sectors no DMA! - shouldn't get here\n"); + } break; case STATE_SENT_DATA: @@ -537,9 +535,10 @@ st506_callback(void *priv) return; } + hdd_active(drive->hdd_num, 1); + hdd_image_read(drive->hdd_num, addr, 1, (uint8_t *) dev->sector_buf); - ui_sb_icon_update(SB_HDD|HDD_BUS_ST506, 1); dev->state = STATE_SEND_DATA; @@ -551,7 +550,7 @@ st506_callback(void *priv) } } else { st506_complete(dev); - ui_sb_icon_update(SB_HDD | HDD_BUS_ST506, 0); + hdd_active(drive->hdd_num, 0); } break; @@ -584,9 +583,7 @@ st506_callback(void *priv) int val = dma_channel_read(3); if (val == DMA_NODATA) { -#ifdef ENABLE_HDC_LOG - hdc_log("CMD_WRITE_SECTORS out of data!\n"); -#endif + ERRLOG("CMD_WRITE_SECTORS out of data!\n"); dev->status = STAT_BSY | STAT_CD | STAT_IO | STAT_REQ; dev->callback = ST506_TIME; return; @@ -597,8 +594,7 @@ st506_callback(void *priv) dev->state = STATE_RECEIVED_DATA; dev->callback = ST506_TIME; - } else - fatal("Write sectors no DMA! - should never get here\n"); + } break; case STATE_RECEIVED_DATA: @@ -611,9 +607,10 @@ st506_callback(void *priv) return; } + hdd_active(drive->hdd_num, 1); + hdd_image_write(drive->hdd_num, addr, 1, (uint8_t *) dev->sector_buf); - ui_sb_icon_update(SB_HDD|HDD_BUS_ST506, 1); next_sector(dev); dev->data_pos = 0; @@ -660,9 +657,7 @@ st506_callback(void *priv) case STATE_RECEIVED_DATA: drive->cfg_cyl = dev->data[1] | (dev->data[0] << 8); drive->cfg_hpc = dev->data[2]; -#ifdef ENABLE_HDC_LOG - hdc_log("Drive %i: cylinders=%i, heads=%i\n", dev->drive_sel, drive->cfg_cyl, drive->cfg_hpc); -#endif + DEBUG("Drive %i: cylinders=%i, heads=%i\n", dev->drive_sel, drive->cfg_cyl, drive->cfg_hpc); st506_complete(dev); break; @@ -691,7 +686,7 @@ st506_callback(void *priv) int val = dma_channel_read(3); if (val == DMA_NODATA) { - hdc_log("CMD_WRITE_SECTOR_BUFFER out of data!\n"); + ERRLOG("CMD_WRITE_SECTOR_BUFFER out of data!\n"); dev->status = STAT_BSY | STAT_CD | STAT_IO | STAT_REQ; dev->callback = ST506_TIME; return; @@ -702,8 +697,7 @@ st506_callback(void *priv) dev->state = STATE_RECEIVED_DATA; dev->callback = ST506_TIME; - } else - fatal("CMD_WRITE_SECTOR_BUFFER - should never get here!\n"); + } break; case STATE_RECEIVED_DATA: @@ -740,9 +734,7 @@ st506_callback(void *priv) dev->data[0] = drive->tracks & 0xff; dev->data[1] = 17 | ((drive->tracks >> 2) & 0xc0); dev->data[2] = drive->hpc-1; -#ifdef ENABLE_HDC_LOG - hdc_log("Get drive params %02x %02x %02x %i\n", dev->data[0], dev->data[1], dev->data[2], drive->tracks); -#endif + DEBUG("Get drive params %02x %02x %02x %i\n", dev->data[0], dev->data[1], dev->data[2], drive->tracks); break; case STATE_SENT_DATA: @@ -816,20 +808,8 @@ loadhd(hdc_t *dev, int c, int d, const wchar_t *fn) } -static const struct { - uint16_t tracks; - uint8_t hpc; - uint8_t spt; -} hd_types[4] = { - { 306, 4, 17 }, /* Type 0 */ - { 612, 4, 17 }, /* Type 16 */ - { 615, 4, 17 }, /* Type 2 */ - { 306, 8, 17 } /* Type 13 */ -}; - - static void -st506_set_switches(hdc_t *dev) +set_switches(hdc_t *dev) { drive_t *drive; int c, d; @@ -850,12 +830,12 @@ st506_set_switches(hdc_t *dev) } } - pclog("ST506: "); + INFO("ST506: "); if (c == 4) - pclog("*WARNING* drive%d unsupported", d); + INFO("*WARNING* drive%d unsupported", d); else - pclog("drive%d is type %d", d, c); - pclog(" (%d/%d/%d)\n", drive->tracks, drive->hpc, drive->spt); + INFO("drive%d is type %d", d, c); + INFO(" (%d/%d/%d)\n", drive->tracks, drive->hpc, drive->spt); } } @@ -867,31 +847,26 @@ st506_init(const device_t *info) hdc_t *dev; int i, c; - dev = malloc(sizeof(hdc_t)); + dev = (hdc_t *)mem_alloc(sizeof(hdc_t)); memset(dev, 0x00, sizeof(hdc_t)); -#ifdef ENABLE_HDC_LOG - hdc_log("ST506: looking for disks..\n"); -#endif + DEBUG("ST506: looking for disks..\n"); + c = 0; for (i = 0; i < HDD_NUM; i++) { if ((hdd[i].bus == HDD_BUS_ST506) && (hdd[i].id.st506_channel < ST506_NUM)) { -#ifdef ENABLE_HDC_LOG - hdc_log("Found ST506 hard disk on channel %i\n", hdd[i].id.st506_channel); -#endif + DEBUG("Found ST506 hard disk on channel %i\n", hdd[i].id.st506_channel); loadhd(dev, hdd[i].id.st506_channel, i, hdd[i].fn); if (++c > ST506_NUM) break; } } -#ifdef ENABLE_HDC_LOG - hdc_log("ST506: %d disks loaded.\n", c); -#endif + DEBUG("ST506: %d disks loaded.\n", c); - switch(info->local) { + switch(info->local & 255) { case 0: /* Xebec */ fn = XEBEC_BIOS_FILE; - st506_set_switches(dev); + set_switches(dev); break; case 1: /* DTC5150 */ @@ -922,7 +897,7 @@ st506_close(void *priv) hdc_t *dev = (hdc_t *)priv; int d; - for (d = 0; d < 2; d++) { + for (d = 0; d < ST506_NUM; d++) { drive_t *drive = &dev->drives[d]; hdd_image_close(drive->hdd_num); @@ -949,17 +924,19 @@ dtc5150x_available(void) const device_t st506_xt_xebec_device = { "IBM PC Fixed Disk Adapter", DEVICE_ISA, - 0, + (HDD_BUS_ST506 << 8) | 0, st506_init, st506_close, NULL, - xebec_available, NULL, NULL, NULL, + xebec_available, + NULL, NULL, NULL, NULL }; const device_t st506_xt_dtc5150x_device = { - "DTC 5150X", + "DTC 5150X Fixed Disk Adapter", DEVICE_ISA, - 1, + (HDD_BUS_ST506 << 8) | 1, st506_init, st506_close, NULL, - dtc5150x_available, NULL, NULL, NULL, + dtc5150x_available, + NULL, NULL, NULL, NULL }; diff --git a/src/devices/disk/hdc_xtide.c b/src/devices/disk/hdc_xtide.c index 011bb23..d6a394d 100644 --- a/src/devices/disk/hdc_xtide.c +++ b/src/devices/disk/hdc_xtide.c @@ -21,7 +21,10 @@ * already on their way out, the newer IDE standard based on the * PC/AT controller and 16b design became the IDE we now know. * - * Version: @(#)hdc_xtide.c 1.0.8 2018/05/06 + * FIXME: Make sure this works with the new IDE stuff, the AT and PS/2 + * controllers do not have dev->ide set to anything... + * + * Version: @(#)hdc_xtide.c 1.0.9 2018/09/22 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -52,6 +55,7 @@ #include #include #include +#define dbglog hdc_log #include "../../emu.h" #include "../../io.h" #include "../../mem.h" @@ -59,6 +63,7 @@ #include "../../device.h" #include "hdc.h" #include "hdc_ide.h" +#include "hdd.h" #define ROM_PATH_XT L"disk/xtide/ide_xt.bin" @@ -68,6 +73,8 @@ typedef struct { + void *ide_board; + uint8_t data_high; rom_t bios_rom; } hdc_t; @@ -80,7 +87,7 @@ hdc_write(uint16_t port, uint8_t val, void *priv) switch (port & 0x0f) { case 0: - writeidew(4, val | (dev->data_high << 8)); + ide_writew(0, val | (dev->data_high << 8), dev->ide_board); return; case 1: @@ -90,7 +97,7 @@ hdc_write(uint16_t port, uint8_t val, void *priv) case 5: case 6: case 7: - writeide(4, 0x01f0 | (port & 0x0f), val); + ide_writeb((port & 0x0f), val, dev->ide_board); return; case 8: @@ -98,7 +105,7 @@ hdc_write(uint16_t port, uint8_t val, void *priv) return; case 14: - writeide(4, 0x03f6, val); + ide_write_devctl(0, val, dev->ide_board); return; } } @@ -112,7 +119,7 @@ hdc_read(uint16_t port, void *priv) switch (port & 0x0f) { case 0: - tempw = readidew(4); + tempw = ide_readw(0, dev->ide_board); dev->data_high = tempw >> 8; break; @@ -123,7 +130,7 @@ hdc_read(uint16_t port, void *priv) case 5: case 6: case 7: - tempw = readide(4, 0x01f0 | (port & 0x0f)); + tempw = ide_readb((port & 0x0f), dev->ide_board); break; case 8: @@ -131,7 +138,7 @@ hdc_read(uint16_t port, void *priv) break; case 14: - tempw = readide(4, 0x03f6); + tempw = ide_read_alt_status(0, dev->ide_board); break; default: @@ -150,7 +157,7 @@ xtide_init(const device_t *info) int io = 0; hdc_t *dev; - dev = malloc(sizeof(hdc_t)); + dev = (hdc_t *)mem_alloc(sizeof(hdc_t)); memset(dev, 0x00, sizeof(hdc_t)); switch(info->local) { @@ -158,15 +165,13 @@ xtide_init(const device_t *info) fn = ROM_PATH_XT; rom_sz = 0x4000; io = 0x300; - - ide_xtide_init(); + dev->ide_board = ide_xtide_init(); break; case 1: fn = ROM_PATH_AT; rom_sz = 0x4000; io = 0x300; - device_add(&ide_isa_2ch_device); break; @@ -174,14 +179,12 @@ xtide_init(const device_t *info) fn = ROM_PATH_PS2; rom_sz = 0x8000; //FIXME: file is 8KB ? io = 0x360; - - ide_xtide_init(); + dev->ide_board = ide_xtide_init(); break; case 3: fn = ROM_PATH_PS2_AT; rom_sz = 0x4000; //FIXME: no I/O address? - device_add(&ide_isa_2ch_device); break; } @@ -203,6 +206,8 @@ xtide_close(void *priv) hdc_t *dev = (hdc_t *)priv; free(dev); + + ide_xtide_close(); } @@ -232,37 +237,41 @@ xtide_at_ps2_available(void) const device_t xtide_device = { - "XTIDE", + "PC/XT XTIDE", DEVICE_ISA, - 0, + (HDD_BUS_IDE << 8) | 0, xtide_init, xtide_close, NULL, - xtide_available, NULL, NULL, NULL, + xtide_available, + NULL, NULL, NULL, NULL }; const device_t xtide_at_device = { - "XTIDE (AT)", + "PC/AT XTIDE", DEVICE_ISA | DEVICE_AT, - 1, + (HDD_BUS_IDE << 8) | 1, xtide_init, xtide_close, NULL, - xtide_at_available, NULL, NULL, NULL, + xtide_at_available, + NULL, NULL, NULL, NULL }; const device_t xtide_acculogic_device = { - "XTIDE (Acculogic)", + "PC/XT XTIDE (Acculogic)", DEVICE_ISA, - 2, + (HDD_BUS_IDE << 8) | 2, xtide_init, xtide_close, NULL, - xtide_acculogic_available, NULL, NULL, NULL, + xtide_acculogic_available, + NULL, NULL, NULL, NULL }; const device_t xtide_at_ps2_device = { - "XTIDE (AT) (1.1.5)", + "PS/2 AT XTIDE (1.1.5)", DEVICE_ISA | DEVICE_PS2, - 3, + (HDD_BUS_IDE << 8) | 3, xtide_init, xtide_close, NULL, - xtide_at_ps2_available, NULL, NULL, NULL, + xtide_at_ps2_available, + NULL, NULL, NULL, NULL }; diff --git a/src/devices/disk/hdd.c b/src/devices/disk/hdd.c index 06fc783..b501acd 100644 --- a/src/devices/disk/hdd.c +++ b/src/devices/disk/hdd.c @@ -8,7 +8,7 @@ * * Common code to handle all sorts of hard disk images. * - * Version: @(#)hdd.c 1.0.8 2018/06/06 + * Version: @(#)hdd.c 1.0.9 2018/09/16 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -40,6 +40,7 @@ #include #include #define HAVE_STDARG_H +#define dbglog hdd_log #include "../../emu.h" #include "../../ui/ui.h" #include "../../plat.h" @@ -53,12 +54,12 @@ int hdd_do_log = ENABLE_HDD_LOG; void -hdd_log(const char *fmt, ...) +hdd_log(int level, const char *fmt, ...) { #ifdef ENABLE_HDD_LOG va_list ap; - if (hdd_do_log) { + if (hdd_do_log >= level) { va_start(ap, fmt); pclog_ex(fmt, ap); va_end(ap); @@ -93,77 +94,39 @@ hdd_count(int bus) int -hdd_string_to_bus(const char *str, int cdrom) +hdd_string_to_bus(const char *str) { - if (! strcmp(str, "none")) - return(HDD_BUS_DISABLED); + int ret = HDD_BUS_DISABLED; - if (!strcmp(str, "st506") || !strcmp(str, "mfm")) { - if (cdrom) { -no_cdrom: - ui_msgbox(MBX_ERROR, (wchar_t *)IDS_ERR_NOCDROM); - return(0); - } + if (! strcmp(str, "none")) return(ret); + if (!strcmp(str, "st506") || !strcmp(str, "mfm") || !strcmp(str, "rll")) return(HDD_BUS_ST506); - } - - if (! strcmp(str, "esdi")) { - if (cdrom) goto no_cdrom; + if (! strcmp(str, "esdi")) return(HDD_BUS_ESDI); - } - if (! strcmp(str, "ide")) - return(HDD_BUS_IDE_PIO_ONLY); - - if (! strcmp(str, "ide_pio_only")) - return(HDD_BUS_IDE_PIO_ONLY); - - if (! strcmp(str, "ide_pio_and_dma")) - return(HDD_BUS_IDE_PIO_AND_DMA); - - if (! strcmp(str, "atapi")) - return(HDD_BUS_IDE_PIO_ONLY); - - if (! strcmp(str, "atapi_pio_only")) - return(HDD_BUS_IDE_PIO_ONLY); - - if (! strcmp(str, "atapi_pio_and_dma")) - return(HDD_BUS_IDE_PIO_AND_DMA); + if (! strcmp(str, "ide") || !strcmp(str, "atapi") +#if 1 + || !strcmp(str, "ide_pio_only") || !strcmp(str, "ide_pio_and_dma") + || !strcmp(str, "atapi_pio_only") || !strcmp(str, "atapi_pio_and_dma") +#endif + ) return(HDD_BUS_IDE); if (! strcmp(str, "scsi")) return(HDD_BUS_SCSI); - if (! strcmp(str, "removable")) { - if (cdrom) goto no_cdrom; - - return(HDD_BUS_SCSI_REMOVABLE); - } - - if (! strcmp(str, "scsi_removable")) { - if (cdrom) goto no_cdrom; - - return(HDD_BUS_SCSI_REMOVABLE); - } - - if (! strcmp(str, "removable_scsi")) { - if (cdrom) goto no_cdrom; - - return(HDD_BUS_SCSI_REMOVABLE); - } - if (! strcmp(str, "usb")) ui_msgbox(MBX_ERROR, (wchar_t *)IDS_ERR_NO_USB); - return(0); + return(ret); } const char * -hdd_bus_to_string(int bus, int cdrom) +hdd_bus_to_string(int bus) { - const char *s = "none"; + const char *ret = "none"; switch (bus) { case HDD_BUS_DISABLED: @@ -171,31 +134,23 @@ hdd_bus_to_string(int bus, int cdrom) break; case HDD_BUS_ST506: - s = "st506"; + ret = "st506"; break; case HDD_BUS_ESDI: - s = "esdi"; + ret = "esdi"; break; - case HDD_BUS_IDE_PIO_ONLY: - s = cdrom ? "atapi_pio_only" : "ide_pio_only"; - break; - - case HDD_BUS_IDE_PIO_AND_DMA: - s = cdrom ? "atapi_pio_and_dma" : "ide_pio_and_dma"; + case HDD_BUS_IDE: + ret = "ide"; break; case HDD_BUS_SCSI: - s = "scsi"; - break; - - case HDD_BUS_SCSI_REMOVABLE: - s = "scsi_removable"; + ret = "scsi"; break; } - return(s); + return(ret); } @@ -204,10 +159,28 @@ hdd_is_valid(int c) { if (hdd[c].bus == HDD_BUS_DISABLED) return(0); - if ((wcslen(hdd[c].fn) == 0) && - (hdd[c].bus != HDD_BUS_SCSI_REMOVABLE)) return(0); + if (wcslen(hdd[c].fn) == 0) return(0); if ((hdd[c].tracks==0) || (hdd[c].hpc==0) || (hdd[c].spt==0)) return(0); return(1); } + + +const wchar_t * +hdd_bus_to_ids(int bus) +{ + if (bus == 0) + bus = IDS_DISABLED; + else + bus = IDS_3515 + bus - 1; + + return(get_string(bus)); +} + + +void +hdd_active(int drive, int active) +{ + ui_sb_icon_update(SB_DISK | drive, active); +} diff --git a/src/devices/disk/hdd.h b/src/devices/disk/hdd.h index dce6cd4..a02235e 100644 --- a/src/devices/disk/hdd.h +++ b/src/devices/disk/hdd.h @@ -8,7 +8,7 @@ * * Definitions for the hard disk image handler. * - * Version: @(#)hdd.h 1.0.9 2018/06/06 + * Version: @(#)hdd.h 1.0.10 2018/09/16 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -50,16 +50,37 @@ enum { HDD_BUS_DISABLED = 0, HDD_BUS_ST506, HDD_BUS_ESDI, - HDD_BUS_IDE_PIO_ONLY, - HDD_BUS_IDE_PIO_AND_DMA, + HDD_BUS_IDE, HDD_BUS_SCSI, - HDD_BUS_SCSI_REMOVABLE, HDD_BUS_USB }; -#define HDD_BUS_IDE HDD_BUS_IDE_PIO_ONLY -#define HDD_BUS_EIDE HDD_BUS_IDE_PIO_AND_DMA +#define HDD_BUS_MAX (HDD_BUS_USB) /* USB exclusive */ +typedef struct vhd_footer_t +{ + uint8_t cookie[8]; + uint32_t features; + uint32_t version; + uint64_t offset; + uint32_t timestamp; + uint8_t creator[4]; + uint32_t creator_vers; + uint8_t creator_host_os[4]; + uint64_t orig_size; + uint64_t curr_size; + struct { + uint16_t cyl; + uint8_t heads; + uint8_t spt; + } geom; + uint32_t type; + uint32_t checksum; + uint8_t uuid[16]; + uint8_t saved_state; + uint8_t reserved[427]; +} vhd_footer_t; + /* Define a hard disk table entry. */ typedef struct { uint16_t cyls; @@ -71,28 +92,27 @@ typedef struct { typedef struct { int8_t is_hdi; /* image type (should rename) */ int8_t wp; /* disk has been mounted READ-ONLY */ - + int8_t removable; /* disk is removable type */ uint8_t bus; + int num; /* global disk number */ union { uint8_t st506_channel; /* bus channel ID's */ uint8_t esdi_channel; - uint8_t xtide_channel; uint8_t ide_channel; - uint8_t scsi_id; union { - uint8_t id; - uint8_t lun; + int8_t id; + int8_t lun; } scsi; } id; uint32_t base; - uint8_t spt, /* physical geometry parameters */ + uint32_t spt, /* physical geometry parameters */ hpc; - uint16_t tracks; + uint32_t tracks; - uint8_t at_spt, /* [Translation] parameters */ + uint32_t at_spt, /* [Translation] parameters */ at_hpc; FILE *f; /* current file handle to image */ @@ -107,13 +127,17 @@ extern hard_disk_t hdd[HDD_NUM]; extern int hdd_do_log; -extern void hdd_log(const char *fmt, ...); +extern void hdd_log(int level, const char *fmt, ...); extern int hdd_init(void); extern int hdd_count(int bus); -extern int hdd_string_to_bus(const char *str, int cdrom); -extern const char *hdd_bus_to_string(int bus, int cdrom); +extern int hdd_string_to_bus(const char *str); +extern const char *hdd_bus_to_string(int bus); +extern const wchar_t *hdd_bus_to_ids(int bus); extern int hdd_is_valid(int c); +extern void hdd_active(int c, int active); +extern void hdd_image_log(int level, const char *fmt, ...); +extern void hdd_image_init(void); extern int hdd_image_load(int id); extern void hdd_image_seek(uint8_t id, uint32_t sector); extern void hdd_image_read(uint8_t id, uint32_t sector, uint32_t count, uint8_t *buffer); @@ -123,13 +147,20 @@ extern int hdd_image_write_ex(uint8_t id, uint32_t sector, uint32_t count, uint8 extern void hdd_image_zero(uint8_t id, uint32_t sector, uint32_t count); extern int hdd_image_zero_ex(uint8_t id, uint32_t sector, uint32_t count); extern uint32_t hdd_image_get_last_sector(uint8_t id); +extern uint32_t hdd_image_get_pos(uint8_t id); extern uint8_t hdd_image_get_type(uint8_t id); extern void hdd_image_specify(uint8_t id, int hpc, int spt); extern void hdd_image_unload(uint8_t id, int fn_preserve); extern void hdd_image_close(uint8_t id); +extern void hdd_image_calc_chs(uint32_t *c, uint32_t *h, uint32_t *s, uint32_t size); +extern void vhd_footer_from_bytes(vhd_footer_t *vhd, uint8_t *bytes); +extern void vhd_footer_to_bytes(uint8_t *bytes, vhd_footer_t *vhd); +extern void new_vhd_footer(vhd_footer_t **vhd); +extern void generate_vhd_checksum(vhd_footer_t *vhd); extern int image_is_hdi(const wchar_t *s); extern int image_is_hdx(const wchar_t *s, int check_signature); +extern int image_is_vhd(const wchar_t *s, int check_signature); #ifdef __cplusplus } diff --git a/src/devices/disk/hdd_image.c b/src/devices/disk/hdd_image.c index 5e43070..5be88a5 100644 --- a/src/devices/disk/hdd_image.c +++ b/src/devices/disk/hdd_image.c @@ -8,7 +8,13 @@ * * Handling of hard disk image files. * - * Version: @(#)hdd_image.c 1.0.5 2018/05/06 + * FIXME: The hdd_image_t structure should be merged with the main + * hard_disk_t structure, with an extra field for private + * data for an image handler. This entire module should be + * merged with hdd.c, since that is the scope of hdd.c. The + * actual format handlers can then be in hdd_format.c etc. + * + * Version: @(#)hdd_image.c 1.0.7 2018/10/01 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -39,61 +45,104 @@ #define _GNU_SOURCE #include #include -#include #include +#include +#include #include #include +#include +#define HAVE_STDARG_H +#define dbglog hdd_image_log #include "../../emu.h" #include "../../plat.h" +#include "../../random.h" #include "hdd.h" +#define VHD_OFFSET_COOKIE 0 +#define VHD_OFFSET_FEATURES 8 +#define VHD_OFFSET_VERSION 12 +#define VHD_OFFSET_DATA_OFFSET 16 +#define VHD_OFFSET_TIMESTAMP 24 +#define VHD_OFFSET_CREATOR 28 +#define VHD_OFFSET_CREATOR_VERS 32 +#define VHD_OFFSET_CREATOR_HOST 36 +#define VHD_OFFSET_ORIG_SIZE 40 +#define VHD_OFFSET_CURR_SIZE 48 +#define VHD_OFFSET_GEOM_CYL 56 +#define VHD_OFFSET_GEOM_HEAD 58 +#define VHD_OFFSET_GEOM_SPT 59 +#define VHD_OFFSET_TYPE 60 +#define VHD_OFFSET_CHECKSUM 64 +#define VHD_OFFSET_UUID 68 +#define VHD_OFFSET_SAVED_STATE 84 +#define VHD_OFFSET_RESERVED 85 + + typedef struct { - FILE *file; - uint32_t base; - uint32_t last_sector; - uint8_t type; - uint8_t loaded; + FILE *file; + uint32_t base; + uint32_t last_sector, + pos; + uint8_t type; + uint8_t loaded; } hdd_image_t; +#ifdef ENABLE_HDD_LOG +int hdd_image_do_log = ENABLE_HDD_LOG; +#endif hdd_image_t hdd_images[HDD_NUM]; -static char empty_sector[512]; -static char *empty_sector_1mb; +static char empty_sector[512]; +static char *empty_sector_1mb; + + +void +hdd_image_log(int level, const char *fmt, ...) +{ +#ifdef ENABLE_HDD_LOG + va_list ap; + + if (hdd_image_do_log >= level) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +#endif +} int image_is_hdi(const wchar_t *s) { - wchar_t ext[5] = { 0, 0, 0, 0, 0 }; - char *ws = (char *)s; int len; - + wchar_t ext[5] = { 0, 0, 0, 0, 0 }; + char *ws = (char *) s; len = wcslen(s); - if ((len < 4) || (s[0] == L'.')) return 0; - + if ((len < 4) || (s[0] == L'.')) + return 0; memcpy(ext, ws + ((len - 4) << 1), 8); - if (! wcscasecmp(ext, L".HDI")) return 1; - - return 0; + if (! wcscasecmp(ext, L".HDI")) + return 1; + else + return 0; } int image_is_hdx(const wchar_t *s, int check_signature) { - wchar_t ext[5] = { 0, 0, 0, 0, 0 }; - char *ws = (char *)s; - uint64_t signature; - uint64_t filelen; - FILE *f; int len; - + FILE *f; + uint64_t filelen; + uint64_t signature; + char *ws = (char *) s; + wchar_t ext[5] = { 0, 0, 0, 0, 0 }; len = wcslen(s); - if ((len < 4) || (s[0] == L'.')) return 0; - + if ((len < 4) || (s[0] == L'.')) + return 0; memcpy(ext, ws + ((len - 4) << 1), 8); if (wcscasecmp(ext, L".HDX") == 0) { if (check_signature) { @@ -109,32 +158,390 @@ image_is_hdx(const wchar_t *s, int check_signature) fclose(f); if (signature == 0xD778A82044445459ll) return 1; + else + return 0; + } else + return 1; + } else + return 0; +} - return 0; - } - return 1; +int +image_is_vhd(const wchar_t *s, int check_signature) +{ + int len; + FILE *f; + uint64_t filelen; + uint64_t signature; + char *ws = (char *) s; + wchar_t ext[5] = { 0, 0, 0, 0, 0 }; + + len = wcslen(s); + if ((len < 4) || (s[0] == L'.')) + return 0; + + memcpy(ext, ws + ((len - 4) << 1), 8); + if (wcscasecmp(ext, L".VHD") == 0) { + if (check_signature) { + f = plat_fopen((wchar_t *)s, L"rb"); + if (!f) + return 0; + fseeko64(f, 0, SEEK_END); + filelen = ftello64(f); + fseeko64(f, -512, SEEK_END); + if (filelen < 512) + return 0; + fread(&signature, 1, 8, f); + fclose(f); + if (signature == 0x78697463656E6F63ll) + return 1; + else + return 0; + } else + return 1; + } else + return 0; +} + + +static uint64_t +be_to_u64(uint8_t *bytes, int start) +{ + uint64_t n = ((uint64_t)bytes[start+7] << 0) | + ((uint64_t)bytes[start+6] << 8) | + ((uint64_t)bytes[start+5] << 16) | + ((uint64_t)bytes[start+4] << 24) | + ((uint64_t)bytes[start+3] << 32) | + ((uint64_t)bytes[start+2] << 40) | + ((uint64_t)bytes[start+1] << 48) | + ((uint64_t)bytes[start] << 56); + return n; +} + + +static uint32_t +be_to_u32(uint8_t *bytes, int start) +{ + uint32_t n = ((uint32_t)bytes[start+3] << 0) | + ((uint32_t)bytes[start+2] << 8) | + ((uint32_t)bytes[start+1] << 16) | + ((uint32_t)bytes[start] << 24); + return n; +} + + +static uint16_t +be_to_u16(uint8_t *bytes, int start) +{ + uint16_t n = ((uint16_t)bytes[start+1] << 0) | + ((uint16_t)bytes[start] <<8); + return n; +} + + +static uint64_t +u64_to_be(uint64_t value, int is_be) +{ + uint64_t res = 0; + + if (is_be) + res = value; + else { + uint64_t mask = 0xff00000000000000; + + res = ((value & (mask >> 0)) >> 56) | + ((value & (mask >> 8)) >> 40) | + ((value & (mask >> 16)) >> 24) | + ((value & (mask >> 24)) >> 8) | + ((value & (mask >> 32)) << 8) | + ((value & (mask >> 40)) << 24) | + ((value & (mask >> 48)) << 40) | + ((value & (mask >> 56)) << 56); } - return 0; + return res; +} + + +static uint32_t +u32_to_be(uint32_t value, int is_be) +{ + uint32_t res = 0; + + if (is_be) + res = value; + else { + uint32_t mask = 0xff000000; + + res = ((value & (mask >> 0)) >> 24) | + ((value & (mask >> 8)) >> 8) | + ((value & (mask >> 16)) << 8) | + ((value & (mask >> 24)) << 24); + } + + return res; +} + + +static uint16_t +u16_to_be(uint16_t value, int is_be) +{ + uint16_t res = 0; + + if (is_be) + res = value; + else + res = (value >> 8) | (value << 8); + + return res; +} + + +static void +mk_guid(uint8_t *guid) +{ + int n; + + for (n = 0; n < 16; n++) + guid[n] = random_generate(); + + guid[6] &= 0x0F; + guid[6] |= 0x40; /* Type 4 */ + guid[8] &= 0x3F; + guid[8] |= 0x80; /* Variant 1 */ +} + + +static uint32_t +calc_vhd_timestamp(void) +{ + time_t start_time; + time_t curr_time; + double vhd_time; + + start_time = 946684800; /* 1 Jan 2000 00:00 */ + curr_time = time(NULL); + vhd_time = difftime(curr_time, start_time); + + return (uint32_t)vhd_time; +} + + +void +vhd_footer_from_bytes(vhd_footer_t *vhd, uint8_t *bytes) +{ + memcpy(vhd->cookie, bytes + VHD_OFFSET_COOKIE, sizeof(vhd->cookie)); + vhd->features = be_to_u32(bytes, VHD_OFFSET_FEATURES); + vhd->version = be_to_u32(bytes, VHD_OFFSET_VERSION); + vhd->offset = be_to_u64(bytes, VHD_OFFSET_DATA_OFFSET); + vhd->timestamp = be_to_u32(bytes, VHD_OFFSET_TIMESTAMP); + memcpy(vhd->creator, bytes + VHD_OFFSET_CREATOR, sizeof(vhd->creator)); + vhd->creator_vers = be_to_u32(bytes, VHD_OFFSET_CREATOR_VERS); + memcpy(vhd->creator_host_os, bytes + VHD_OFFSET_CREATOR_HOST, sizeof(vhd->creator_host_os)); + vhd->orig_size = be_to_u64(bytes, VHD_OFFSET_ORIG_SIZE); + vhd->curr_size = be_to_u64(bytes, VHD_OFFSET_CURR_SIZE); + vhd->geom.cyl = be_to_u16(bytes, VHD_OFFSET_GEOM_CYL); + vhd->geom.heads = bytes[VHD_OFFSET_GEOM_HEAD]; + vhd->geom.spt = bytes[VHD_OFFSET_GEOM_SPT]; + vhd->type = be_to_u32(bytes, VHD_OFFSET_TYPE); + vhd->checksum = be_to_u32(bytes, VHD_OFFSET_CHECKSUM); + memcpy(vhd->uuid, bytes + VHD_OFFSET_UUID, sizeof(vhd->uuid)); /* TODO: handle UUID's properly */ + vhd->saved_state = bytes[VHD_OFFSET_SAVED_STATE]; + memcpy(vhd->reserved, bytes + VHD_OFFSET_RESERVED, sizeof(vhd->reserved)); +} + + +void +vhd_footer_to_bytes(uint8_t *bytes, vhd_footer_t *vhd) +{ + /* Quick endian check */ + int is_be = 0; + uint8_t e = 1; + uint8_t *ep = &e; + uint16_t u16; + uint32_t u32; + uint64_t u64; + + if (ep[0] == 0) + is_be = 1; + + memcpy(bytes + VHD_OFFSET_COOKIE, vhd->cookie, sizeof(vhd->cookie)); + u32 = u32_to_be(vhd->features, is_be); + memcpy(bytes + VHD_OFFSET_FEATURES, &u32, sizeof(vhd->features)); + u32 = u32_to_be(vhd->version, is_be); + memcpy(bytes + VHD_OFFSET_VERSION, &u32, sizeof(vhd->version)); + u64 = u64_to_be(vhd->offset, is_be); + memcpy(bytes + VHD_OFFSET_DATA_OFFSET, &u64, sizeof(vhd->offset)); + u32 = u32_to_be(vhd->timestamp, is_be); + memcpy(bytes + VHD_OFFSET_TIMESTAMP, &u32, sizeof(vhd->timestamp)); + memcpy(bytes + VHD_OFFSET_CREATOR, vhd->creator, sizeof(vhd->creator)); + u32 = u32_to_be(vhd->creator_vers, is_be); + memcpy(bytes + VHD_OFFSET_CREATOR_VERS, &u32, sizeof(vhd->creator_vers)); + memcpy(bytes + VHD_OFFSET_CREATOR_HOST, vhd->creator_host_os, sizeof(vhd->creator_host_os)); + u64 = u64_to_be(vhd->orig_size, is_be); + memcpy(bytes + VHD_OFFSET_ORIG_SIZE, &u64, sizeof(vhd->orig_size)); + u64 = u64_to_be(vhd->curr_size, is_be); + memcpy(bytes + VHD_OFFSET_CURR_SIZE, &u64, sizeof(vhd->curr_size)); + u16 = u16_to_be(vhd->geom.cyl, is_be); + memcpy(bytes + VHD_OFFSET_GEOM_CYL, &u16, sizeof(vhd->geom.cyl)); + memcpy(bytes + VHD_OFFSET_GEOM_HEAD, &(vhd->geom.heads), sizeof(vhd->geom.heads)); + memcpy(bytes + VHD_OFFSET_GEOM_SPT, &(vhd->geom.spt), sizeof(vhd->geom.spt)); + u32 = u32_to_be(vhd->type, is_be); + memcpy(bytes + VHD_OFFSET_TYPE, &u32, sizeof(vhd->type)); + u32 = u32_to_be(vhd->checksum, is_be); + memcpy(bytes + VHD_OFFSET_CHECKSUM, &u32, sizeof(vhd->checksum)); + memcpy(bytes + VHD_OFFSET_UUID, vhd->uuid, sizeof(vhd->uuid)); + memcpy(bytes + VHD_OFFSET_SAVED_STATE, &(vhd->saved_state), sizeof(vhd->saved_state)); + memcpy(bytes + VHD_OFFSET_RESERVED, vhd->reserved, sizeof(vhd->reserved)); +} + + +void +new_vhd_footer(vhd_footer_t **vhd) +{ + uint8_t cookie[8] = {'c', 'o', 'n', 'e', 'c', 't', 'i', 'x'}; + uint8_t creator[4] = {'V', 'A', 'R', 'C'}; + uint8_t cr_host_os[4] = {'W', 'i', '2', 'k'}; + + if (*vhd == NULL) + *vhd = (vhd_footer_t *)mem_alloc(sizeof(vhd_footer_t)); + + memcpy((*vhd)->cookie, cookie, 8); + (*vhd)->features = 0x00000002; + (*vhd)->version = 0x00010000; + (*vhd)->offset = 0xffffffffffffffff; /* fixed disk */ + (*vhd)->timestamp = calc_vhd_timestamp(); + memcpy((*vhd)->creator, creator, 4); + (*vhd)->creator_vers = 0x00010000; + memcpy((*vhd)->creator_host_os, cr_host_os, 4); + (*vhd)->type = 2; /* fixed disk */ + mk_guid((*vhd)->uuid); + (*vhd)->saved_state = 0; + memset((*vhd)->reserved, 0, 427); +} + + +void +generate_vhd_checksum(vhd_footer_t *vhd) +{ + uint32_t chk = 0; + int i; + + for (i = 0; i < sizeof(vhd_footer_t); i++) { + /* We don't include the checksum field in the checksum */ + if ((i < VHD_OFFSET_CHECKSUM) || (i >= VHD_OFFSET_UUID)) + chk += ((uint8_t*)vhd)[i]; + } + + vhd->checksum = ~chk; +} + + +/* + * Calculate the geometry from size (in MB), using the algorithm + * provided in "Virtual Hard Disk Image Format Specification, + * Appendix: CHS Calculation"i + */ +void +hdd_image_calc_chs(uint32_t *c, uint32_t *h, uint32_t *s, uint32_t size) +{ + uint64_t ts = ((uint64_t) size) << 11LL; + uint32_t spt, heads, cyl, cth; + + if (ts > 65535 * 16 * 255) + ts = 65535 * 16 * 255; + if (ts >= 65535 * 16 * 63) { + spt = 255; + heads = 16; + cth = (uint32_t) (ts / spt); + } else { + spt = 17; + cth = (uint32_t) (ts / spt); + heads = (cth +1023) / 1024; + if (heads < 4) + heads = 4; + if ((cth >= (heads * 1024)) || (heads > 16)) { + spt = 31; + heads = 16; + cth = (uint32_t) (ts / spt); + } + if (cth >= (heads * 1024)) { + spt = 63; + heads = 16; + cth = (uint32_t) (ts / spt); + } + } + cyl = cth / heads; + *c = cyl; + *h = heads; + *s = spt; +} + + +static int +prepare_new_hard_disk(uint8_t id, uint64_t full_size) +{ + uint64_t target_size = (full_size + hdd_images[id].base) - ftello64(hdd_images[id].file); + + uint32_t size; + uint32_t t, i; + + t = (uint32_t) (target_size >> 20); /* Amount of 1 MB blocks. */ + size = (uint32_t) (target_size & 0xfffff); /* 1 MB mask. */ + + empty_sector_1mb = (char *)mem_alloc(1048576); + memset(empty_sector_1mb, 0, 1048576); + + /* First, write all the 1 MB blocks. */ + if (t > 0) { + for (i = 0; i < t; i++) + fwrite(empty_sector_1mb, 1, 1045876, hdd_images[id].file); + } + + /* Then, write the remainder. */ + fwrite(empty_sector_1mb, 1, size, hdd_images[id].file); + + free(empty_sector_1mb); + + hdd_images[id].last_sector = (uint32_t) (full_size >> 9) - 1; + + hdd_images[id].loaded = 1; + + return 1; +} + + +void +hdd_image_init(void) +{ + int i; + + for (i = 0; i < HDD_NUM; i++) + memset(&hdd_images[i], 0, sizeof(hdd_image_t)); } int hdd_image_load(int id) { - uint64_t signature = 0xD778A82044445459ll; - uint64_t s = 0, t, full_size = 0; - int spt = 0, hpc = 0, tracks = 0; uint32_t sector_size = 512; + uint32_t zero = 0; + uint64_t signature = 0xD778A82044445459ll; + uint64_t full_size = 0; + int spt = 0, hpc = 0, tracks = 0; + int c, ret; + uint64_t s = 0; wchar_t *fn = hdd[id].fn; int is_hdx[2] = { 0, 0 }; - uint32_t zero = 0; - int c, i; + int is_vhd[2] = { 0, 0 }; + vhd_footer_t *vft = NULL; memset(empty_sector, 0, sizeof(empty_sector)); hdd_images[id].base = 0; + is_vhd[0] = image_is_vhd(fn, 0); + is_vhd[1] = image_is_vhd(fn, 1); if (hdd_images[id].loaded) { if (hdd_images[id].file) { @@ -147,15 +554,9 @@ hdd_image_load(int id) is_hdx[0] = image_is_hdx(fn, 0); is_hdx[1] = image_is_hdx(fn, 1); - /* Try to open existing hard disk image */ - if (fn[0] == '.') { -#ifdef ENABLE_HDD_LOG - hdd_log("File name starts with .\n"); -#endif - memset(hdd[id].fn, 0, sizeof(hdd[id].fn)); - return 0; - } + hdd_images[id].pos = 0; + /* Try to open existing hard disk image */ hdd_images[id].file = plat_fopen(fn, L"rb+"); if (hdd_images[id].file == NULL) { /* Failed to open existing hard disk image */ @@ -163,23 +564,21 @@ hdd_image_load(int id) /* Failed because it does not exist, so try to create new file */ if (hdd[id].wp) { -#ifdef ENABLE_HDD_LOG - hdd_log("A write-protected image must exist\n"); -#endif + DEBUG("A write-protected image must exist\n"); memset(hdd[id].fn, 0, sizeof(hdd[id].fn)); return 0; } hdd_images[id].file = plat_fopen(fn, L"wb+"); if (hdd_images[id].file == NULL) { -#ifdef ENABLE_HDD_LOG - hdd_log("Unable to open image\n"); -#endif + DEBUG("Unable to open image\n"); memset(hdd[id].fn, 0, sizeof(hdd[id].fn)); return 0; } else { if (image_is_hdi(fn)) { - full_size = hdd[id].spt * hdd[id].hpc * hdd[id].tracks * 512; + full_size = ((uint64_t) hdd[id].spt) * + ((uint64_t) hdd[id].hpc) * + ((uint64_t) hdd[id].tracks) << 9LL; hdd_images[id].base = 0x1000; fwrite(&zero, 1, 4, hdd_images[id].file); fwrite(&zero, 1, 4, hdd_images[id].file); @@ -193,7 +592,9 @@ hdd_image_load(int id) fwrite(&zero, 1, 4, hdd_images[id].file); hdd_images[id].type = 1; } else if (is_hdx[0]) { - full_size = hdd[id].spt * hdd[id].hpc * hdd[id].tracks * 512; + full_size = ((uint64_t) hdd[id].spt) * + ((uint64_t) hdd[id].hpc) * + ((uint64_t) hdd[id].tracks) << 9LL; hdd_images[id].base = 0x28; fwrite(&signature, 1, 8, hdd_images[id].file); fwrite(&full_size, 1, 8, hdd_images[id].file); @@ -204,20 +605,75 @@ hdd_image_load(int id) fwrite(&zero, 1, 4, hdd_images[id].file); fwrite(&zero, 1, 4, hdd_images[id].file); hdd_images[id].type = 2; - } else { - hdd_images[id].type = 0; + } else if (is_vhd[1]) { + empty_sector_1mb = (char *)mem_alloc(512); + memset(empty_sector_1mb, 0, 512); + fseeko64(hdd_images[id].file, -512, SEEK_END); + fread(empty_sector_1mb, 1, 512, hdd_images[id].file); + new_vhd_footer(&vft); + vhd_footer_from_bytes(vft, (uint8_t *) empty_sector_1mb); + if (vft->type != 2) { + /* VHD is not fixed size */ + DEBUG("VHD: Image is not fixed size\n"); + free(vft); + vft = NULL; + free(empty_sector_1mb); + empty_sector_1mb = NULL; + fclose(hdd_images[id].file); + hdd_images[id].file = NULL; + memset(hdd[id].fn, 0, sizeof(hdd[id].fn)); + return 0; + } + full_size = vft->orig_size; + hdd[id].tracks = vft->geom.cyl; + hdd[id].hpc = vft->geom.heads; + hdd[id].spt = vft->geom.spt; + free(vft); + vft = NULL; + free(empty_sector_1mb); + empty_sector_1mb = NULL; + hdd_images[id].type = 3; + + /* If we're here, this means there is a valid VHD footer in the + image, which means that by definition, all valid sectors + are there. */ + hdd_images[id].last_sector = (uint32_t) (full_size >> 9) - 1; + hdd_images[id].loaded = 1; + return 1; } + else + hdd_images[id].type = 0; hdd_images[id].last_sector = 0; } - s = full_size = hdd[id].spt * hdd[id].hpc * hdd[id].tracks * 512; + s = full_size = ((uint64_t) hdd[id].spt) * + ((uint64_t) hdd[id].hpc) * + ((uint64_t) hdd[id].tracks) << 9LL; - goto prepare_new_hard_disk; + ret = prepare_new_hard_disk(id, full_size); + if (is_vhd[0]) { + /* VHD image. */ + /* Generate new footer. */ + empty_sector_1mb = (char *)mem_alloc(512); + new_vhd_footer(&vft); + vft->orig_size = vft->curr_size = full_size; + vft->geom.cyl = tracks; + vft->geom.heads = hpc; + vft->geom.spt = spt; + generate_vhd_checksum(vft); + memset(empty_sector_1mb, 0, 512); + vhd_footer_to_bytes((uint8_t *) empty_sector_1mb, vft); + fwrite(empty_sector_1mb, 1, 512, hdd_images[id].file); + free(vft); + vft = NULL; + free(empty_sector_1mb); + empty_sector_1mb = NULL; + hdd_images[id].type = 3; + } + return ret; } else { /* Failed for another reason */ -#ifdef ENABLE_HDD_LOG - hdd_log("Failed for another reason\n"); -#endif + DEBUG("Failed for another reason\n"); memset(hdd[id].fn, 0, sizeof(hdd[id].fn)); return 0; } @@ -226,15 +682,13 @@ hdd_image_load(int id) fseeko64(hdd_images[id].file, 0x8, SEEK_SET); fread(&(hdd_images[id].base), 1, 4, hdd_images[id].file); fseeko64(hdd_images[id].file, 0xC, SEEK_SET); - full_size = 0; + full_size = 0LL; fread(&full_size, 1, 4, hdd_images[id].file); fseeko64(hdd_images[id].file, 0x10, SEEK_SET); fread(§or_size, 1, 4, hdd_images[id].file); if (sector_size != 512) { /* Sector size is not 512 */ -#ifdef ENABLE_HDD_LOG - hdd_log("HDI: Sector size is not 512\n"); -#endif + DEBUG("HDI: Sector size is not 512\n"); fclose(hdd_images[id].file); hdd_images[id].file = NULL; memset(hdd[id].fn, 0, sizeof(hdd[id].fn)); @@ -243,22 +697,11 @@ hdd_image_load(int id) fread(&spt, 1, 4, hdd_images[id].file); fread(&hpc, 1, 4, hdd_images[id].file); fread(&tracks, 1, 4, hdd_images[id].file); - if (hdd[id].bus == HDD_BUS_SCSI_REMOVABLE) { - if ((spt != hdd[id].spt) || (hpc != hdd[id].hpc) || (tracks != hdd[id].tracks)) { -#ifdef ENABLE_HDD_LOG - hdd_log("HDI: Geometry mismatch\n"); -#endif - fclose(hdd_images[id].file); - hdd_images[id].file = NULL; - memset(hdd[id].fn, 0, sizeof(hdd[id].fn)); - return 0; - } - } - hdd[id].spt = (uint8_t)spt; - hdd[id].hpc = (uint8_t)hpc; - hdd[id].tracks = (uint16_t)tracks; - hdd_images[id].type = 1; - } else if (is_hdx[1]) { + hdd[id].spt = spt; + hdd[id].hpc = hpc; + hdd[id].tracks = tracks; + hdd_images[id].type = 1; + } else if (is_hdx[1]) { hdd_images[id].base = 0x28; fseeko64(hdd_images[id].file, 8, SEEK_SET); fread(&full_size, 1, 8, hdd_images[id].file); @@ -266,9 +709,7 @@ hdd_image_load(int id) fread(§or_size, 1, 4, hdd_images[id].file); if (sector_size != 512) { /* Sector size is not 512 */ -#ifdef ENABLE_HDD_LOG - hdd_log("HDX: Sector size is not 512\n"); -#endif + DEBUG("HDX: Sector size is not 512\n"); fclose(hdd_images[id].file); hdd_images[id].file = NULL; memset(hdd[id].fn, 0, sizeof(hdd[id].fn)); @@ -277,61 +718,29 @@ hdd_image_load(int id) fread(&spt, 1, 4, hdd_images[id].file); fread(&hpc, 1, 4, hdd_images[id].file); fread(&tracks, 1, 4, hdd_images[id].file); - if (hdd[id].bus == HDD_BUS_SCSI_REMOVABLE) { - if ((spt != hdd[id].spt) || (hpc != hdd[id].hpc) || (tracks != hdd[id].tracks)) { -#ifdef ENABLE_HDD_LOG - hdd_log("HDX: Geometry mismatch\n"); -#endif - fclose(hdd_images[id].file); - hdd_images[id].file = NULL; - memset(hdd[id].fn, 0, sizeof(hdd[id].fn)); - return 0; - } - } - hdd[id].spt = (uint8_t)spt; - hdd[id].hpc = (uint8_t)hpc; - hdd[id].tracks = (uint16_t)tracks; + hdd[id].spt = spt; + hdd[id].hpc = hpc; + hdd[id].tracks = tracks; fread(&(hdd[id].at_spt), 1, 4, hdd_images[id].file); fread(&(hdd[id].at_hpc), 1, 4, hdd_images[id].file); hdd_images[id].type = 2; } else { - full_size = hdd[id].spt * hdd[id].hpc * hdd[id].tracks * 512; + full_size = ((uint64_t) hdd[id].spt) * + ((uint64_t) hdd[id].hpc) * + ((uint64_t) hdd[id].tracks) << 9LL; hdd_images[id].type = 0; } } fseeko64(hdd_images[id].file, 0, SEEK_END); - if (ftello64(hdd_images[id].file) < (int64_t)(full_size + hdd_images[id].base)) { - s = (full_size + hdd_images[id].base) - ftello64(hdd_images[id].file); -prepare_new_hard_disk: - s >>= 9; - t = (s >> 11) << 11; - s -= t; - t >>= 11; - - empty_sector_1mb = (char *) malloc(1048576); - memset(empty_sector_1mb, 0, 1048576); - - if (s > 0) { - for (i = 0; i < s; i++) { - fwrite(empty_sector, 1, 512, hdd_images[id].file); - } - } - - if (t > 0) { - for (i = 0; i < t; i++) { - fwrite(empty_sector_1mb, 1, 1045876, hdd_images[id].file); - } - } - - free(empty_sector_1mb); + s = ftello64(hdd_images[id].file); + if (s < (full_size + hdd_images[id].base)) + return prepare_new_hard_disk(id, full_size); + else { + hdd_images[id].last_sector = (uint32_t) (full_size >> 9) - 1; + hdd_images[id].loaded = 1; + return 1; } - - hdd_images[id].last_sector = (uint32_t) (full_size >> 9) - 1; - - hdd_images[id].loaded = 1; - - return 1; } @@ -339,7 +748,9 @@ void hdd_image_seek(uint8_t id, uint32_t sector) { off64_t addr = sector; - addr = (uint64_t)sector * 512; + addr = (uint64_t)sector << 9LL; + + hdd_images[id].pos = sector; fseeko64(hdd_images[id].file, addr + hdd_images[id].base, SEEK_SET); } @@ -348,8 +759,10 @@ hdd_image_seek(uint8_t id, uint32_t sector) void hdd_image_read(uint8_t id, uint32_t sector, uint32_t count, uint8_t *buffer) { - fseeko64(hdd_images[id].file, ((uint64_t)sector * 512) + hdd_images[id].base, SEEK_SET); - fread(buffer, 1, count * 512, hdd_images[id].file); + hdd_images[id].pos = sector; + + fseeko64(hdd_images[id].file, ((uint64_t)sector << 9LL) + hdd_images[id].base, SEEK_SET); + fread(buffer, 1, count << 9, hdd_images[id].file); } @@ -357,8 +770,7 @@ uint32_t hdd_sectors(uint8_t id) { fseeko64(hdd_images[id].file, 0, SEEK_END); - - return (uint32_t) (ftello64(hdd_images[id].file) >> 9); + return (uint32_t) ((ftello64(hdd_images[id].file) - hdd_images[id].base) >> 9); } @@ -371,8 +783,10 @@ hdd_image_read_ex(uint8_t id, uint32_t sector, uint32_t count, uint8_t *buffer) if ((sectors - sector) < transfer_sectors) transfer_sectors = sectors - sector; - fseeko64(hdd_images[id].file, ((uint64_t)sector * 512) + hdd_images[id].base, SEEK_SET); - fread(buffer, 1, transfer_sectors * 512, hdd_images[id].file); + hdd_images[id].pos = sector; + + fseeko64(hdd_images[id].file, ((uint64_t)sector << 9LL) + hdd_images[id].base, SEEK_SET); + fread(buffer, 1, transfer_sectors << 9, hdd_images[id].file); if (count != transfer_sectors) return 1; @@ -384,8 +798,10 @@ hdd_image_read_ex(uint8_t id, uint32_t sector, uint32_t count, uint8_t *buffer) void hdd_image_write(uint8_t id, uint32_t sector, uint32_t count, uint8_t *buffer) { - fseeko64(hdd_images[id].file, ((uint64_t)sector * 512) + hdd_images[id].base, SEEK_SET); - fwrite(buffer, count * 512, 1, hdd_images[id].file); + hdd_images[id].pos = sector; + + fseeko64(hdd_images[id].file, ((uint64_t)sector << 9LL) + hdd_images[id].base, SEEK_SET); + fwrite(buffer, count << 9, 1, hdd_images[id].file); } @@ -398,12 +814,13 @@ hdd_image_write_ex(uint8_t id, uint32_t sector, uint32_t count, uint8_t *buffer) if ((sectors - sector) < transfer_sectors) transfer_sectors = sectors - sector; - fseeko64(hdd_images[id].file, ((uint64_t)sector * 512) + hdd_images[id].base, SEEK_SET); - fwrite(buffer, transfer_sectors * 512, 1, hdd_images[id].file); + hdd_images[id].pos = sector; + + fseeko64(hdd_images[id].file, ((uint64_t)sector << 9LL) + hdd_images[id].base, SEEK_SET); + fwrite(buffer, transfer_sectors << 9, 1, hdd_images[id].file); if (count != transfer_sectors) return 1; - return 0; } @@ -411,9 +828,11 @@ hdd_image_write_ex(uint8_t id, uint32_t sector, uint32_t count, uint8_t *buffer) void hdd_image_zero(uint8_t id, uint32_t sector, uint32_t count) { - uint32_t i; + uint32_t i = 0; - fseeko64(hdd_images[id].file, ((uint64_t)sector * 512) + hdd_images[id].base, SEEK_SET); + hdd_images[id].pos = sector; + + fseeko64(hdd_images[id].file, ((uint64_t)sector << 9LL) + hdd_images[id].base, SEEK_SET); for (i = 0; i < count; i++) fwrite(empty_sector, 512, 1, hdd_images[id].file); } @@ -422,14 +841,17 @@ hdd_image_zero(uint8_t id, uint32_t sector, uint32_t count) int hdd_image_zero_ex(uint8_t id, uint32_t sector, uint32_t count) { + uint32_t i = 0; + uint32_t transfer_sectors = count; uint32_t sectors = hdd_sectors(id); - uint32_t i; if ((sectors - sector) < transfer_sectors) transfer_sectors = sectors - sector; - fseeko64(hdd_images[id].file, ((uint64_t)sector * 512) + hdd_images[id].base, SEEK_SET); + hdd_images[id].pos = sector; + + fseeko64(hdd_images[id].file, ((uint64_t)sector << 9LL) + hdd_images[id].base, SEEK_SET); for (i = 0; i < transfer_sectors; i++) fwrite(empty_sector, 1, 512, hdd_images[id].file); @@ -447,6 +869,13 @@ hdd_image_get_last_sector(uint8_t id) } +uint32_t +hdd_image_get_pos(uint8_t id) +{ + return hdd_images[id].pos; +} + + uint8_t hdd_image_get_type(uint8_t id) { @@ -458,8 +887,8 @@ void hdd_image_specify(uint8_t id, int hpc, int spt) { if (hdd_images[id].type == 2) { - hdd[id].at_hpc = (uint8_t)hpc; - hdd[id].at_spt = (uint8_t)spt; + hdd[id].at_hpc = hpc; + hdd[id].at_spt = spt; fseeko64(hdd_images[id].file, 0x20, SEEK_SET); fwrite(&(hdd[id].at_spt), 1, 4, hdd_images[id].file); fwrite(&(hdd[id].at_hpc), 1, 4, hdd_images[id].file); @@ -470,7 +899,8 @@ hdd_image_specify(uint8_t id, int hpc, int spt) void hdd_image_unload(uint8_t id, int fn_preserve) { - if (wcslen(hdd[id].fn) == 0) return; + if (wcslen(hdd[id].fn) == 0) + return; if (hdd_images[id].loaded) { if (hdd_images[id].file != NULL) { @@ -492,10 +922,15 @@ hdd_image_unload(uint8_t id, int fn_preserve) void hdd_image_close(uint8_t id) { + DEBUG("hdd_image_close(%i)\n", id); + + if (!hdd_images[id].loaded) + return; + if (hdd_images[id].file != NULL) { fclose(hdd_images[id].file); hdd_images[id].file = NULL; } - + memset(&hdd_images[id], 0, sizeof(hdd_image_t)); hdd_images[id].loaded = 0; } diff --git a/src/devices/disk/zip.c b/src/devices/disk/zip.c index cd9d1e9..0c45da3 100644 --- a/src/devices/disk/zip.c +++ b/src/devices/disk/zip.c @@ -9,7 +9,7 @@ * Implementation of the Iomega ZIP drive with SCSI(-like) * commands, for both ATAPI and SCSI usage. * - * Version: @(#)zip.c 1.0.14 2018/05/06 + * Version: @(#)zip.c 1.0.15 2018/10/05 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -49,7 +49,7 @@ #include "../../ui/ui.h" #include "../../plat.h" #include "../system/intel_piix.h" -#include "../scsi/scsi.h" +#include "../scsi/scsi_device.h" #include "../disk/hdc.h" #include "../disk/hdc_ide.h" #include "zip.h" @@ -67,30 +67,39 @@ #define ABRT_ERR 0x04 /* Command aborted */ #define MCR_ERR 0x08 /* Media change request */ -zip_t zip[ZIP_NUM]; +#define zipbufferb dev->buffer + + +#ifdef ENABLE_ZIP_LOG +int zip_do_log = ENABLE_ZIP_LOG; +#endif +zip_t *zip[ZIP_NUM]; zip_drive_t zip_drives[ZIP_NUM]; -uint8_t atapi_zip_drives[8] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; -uint8_t scsi_zip_drives[16][8] = { { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } }; +uint8_t atapi_zip_drives[8] = { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF +}; +uint8_t scsi_zip_drives[16][8] = { + { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, + { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, + { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, + { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, + { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, + { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, + { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, + { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, + { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, + { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, + { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, + { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, + { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, + { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, + { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, + { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } +}; /* Table of all SCSI commands and their flags, needed for the new disc change / not ready handler. */ -static const uint8_t zip_command_flags[0x100] = -{ +const uint8_t zip_command_flags[0x100] = { IMPLEMENTED | CHECK_READY | NONDATA, /* 0x00 */ IMPLEMENTED | ALLOW_UA | NONDATA | SCSI_ONLY, /* 0x01 */ 0, @@ -102,7 +111,7 @@ static const uint8_t zip_command_flags[0x100] = IMPLEMENTED | CHECK_READY, /* 0x08 */ 0, IMPLEMENTED | CHECK_READY, /* 0x0A */ - 0, + IMPLEMENTED | CHECK_READY | NONDATA, /* 0x0B */ IMPLEMENTED, /* 0x0C */ IMPLEMENTED | ATAPI_ONLY, /* 0x0D */ 0, 0, 0, 0, @@ -113,7 +122,7 @@ static const uint8_t zip_command_flags[0x100] = IMPLEMENTED | SCSI_ONLY, /* 0x16 */ IMPLEMENTED | SCSI_ONLY, /* 0x17 */ 0, 0, - IMPLEMENTED, + IMPLEMENTED, /* 0x1A */ IMPLEMENTED | CHECK_READY, /* 0x1B */ 0, IMPLEMENTED, /* 0x1D */ @@ -126,7 +135,8 @@ static const uint8_t zip_command_flags[0x100] = IMPLEMENTED | CHECK_READY, /* 0x28 */ 0, IMPLEMENTED | CHECK_READY, /* 0x2A */ - 0, 0, 0, + IMPLEMENTED | CHECK_READY | NONDATA, /* 0x2B */ + 0, 0, IMPLEMENTED | CHECK_READY, /* 0x2E */ IMPLEMENTED | CHECK_READY | NONDATA | SCSI_ONLY, /* 0x2F */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -158,2555 +168,2633 @@ static const uint8_t zip_command_flags[0x100] = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; -uint64_t zip_mode_sense_page_flags = (1LL << GPMODE_R_W_ERROR_PAGE) | (1LL << 0x02LL) | (1LL << 0x2FLL) | (1LL << GPMODE_ALL_PAGES); -uint64_t zip_250_mode_sense_page_flags = (1LL << GPMODE_R_W_ERROR_PAGE) | (1LL << 0x05LL) | (1LL << 0x08LL) | (1LL << 0x2FLL) | (1LL << GPMODE_ALL_PAGES); +static uint64_t zip_mode_sense_page_flags = (GPMODEP_R_W_ERROR_PAGE | + GPMODEP_UNK_PAGE_02 | + GPMODEP_UNK_PAGE_2F | + GPMODEP_ALL_PAGES); +static uint64_t zip_250_mode_sense_page_flags = (GPMODEP_R_W_ERROR_PAGE | + GPMODEP_UNK_PAGE_05 | + GPMODEP_UNK_PAGE_08 | + GPMODEP_UNK_PAGE_2F | + GPMODEP_ALL_PAGES); -static const mode_sense_pages_t zip_mode_sense_pages_default = -{ { - { 0, 0 }, - { GPMODE_R_W_ERROR_PAGE, 0x0a, 0xc8, 22, 0, 0, 0, 0, 90, 0, 0x50, 0x20 }, - { 0x02, 0x0e, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0x2f, 0x04, 0x5c, 0x0f, 0xff, 0x0f } -} }; +static const mode_sense_pages_t zip_mode_sense_pages_default = { + { + { 0, 0 }, + { GPMODE_R_W_ERROR_PAGE, 0x0a, 0xc8, 22, 0, 0, 0, 0, 90, 0, 0x50, 0x20 }, + { 0x02, 0x0e, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0x2f, 0x04, 0x5c, 0x0f, 0xff, 0x0f } +} }; static const mode_sense_pages_t zip_250_mode_sense_pages_default = -{ { - { 0, 0 }, - { GPMODE_R_W_ERROR_PAGE, 0x06, 0xc8, 0x64, 0, 0, 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0x05, 0x1e, 0x80, 0, 0x40, 0x20, 2, 0, 0, 0xef, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x0b, 0x7d, 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0x08, 0x0a, 4, 0, 0xff, 0xff, 0, 0, 0xff, 0xff, 0xff, 0xff }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0x2f, 0x04, 0x5c, 0x0f, 0x3c, 0x0f } -} }; +{ { + { 0, 0 }, + { GPMODE_R_W_ERROR_PAGE, 0x06, 0xc8, 0x64, 0, 0, 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0x05, 0x1e, 0x80, 0, 0x40, 0x20, 2, 0, 0, 0xef, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x0b, 0x7d, 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0x08, 0x0a, 4, 0, 0xff, 0xff, 0, 0, 0xff, 0xff, 0xff, 0xff }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0x2f, 0x04, 0x5c, 0x0f, 0x3c, 0x0f } +} }; static const mode_sense_pages_t zip_mode_sense_pages_default_scsi = -{ { - { 0, 0 }, - { GPMODE_R_W_ERROR_PAGE, 0x0a, 0xc8, 22, 0, 0, 0, 0, 90, 0, 0x50, 0x20 }, - { 0x02, 0x0e, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0x2f, 0x04, 0x5c, 0x0f, 0xff, 0x0f } -} }; +{ { + { 0, 0 }, + { GPMODE_R_W_ERROR_PAGE, 0x0a, 0xc8, 22, 0, 0, 0, 0, 90, 0, 0x50, 0x20 }, + { 0x02, 0x0e, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0x2f, 0x04, 0x5c, 0x0f, 0xff, 0x0f } +} }; static const mode_sense_pages_t zip_250_mode_sense_pages_default_scsi = -{ { - { 0, 0 }, - { GPMODE_R_W_ERROR_PAGE, 0x06, 0xc8, 0x64, 0, 0, 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0x05, 0x1e, 0x80, 0, 0x40, 0x20, 2, 0, 0, 0xef, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x0b, 0x7d, 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0x08, 0x0a, 4, 0, 0xff, 0xff, 0, 0, 0xff, 0xff, 0xff, 0xff }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0x2f, 0x04, 0x5c, 0x0f, 0x3c, 0x0f } -} }; +{ { + { 0, 0 }, + { GPMODE_R_W_ERROR_PAGE, 0x06, 0xc8, 0x64, 0, 0, 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0x05, 0x1e, 0x80, 0, 0x40, 0x20, 2, 0, 0, 0xef, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x0b, 0x7d, 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0x08, 0x0a, 4, 0, 0xff, 0xff, 0, 0, 0xff, 0xff, 0xff, 0xff }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0x2f, 0x04, 0x5c, 0x0f, 0x3c, 0x0f } +} }; static const mode_sense_pages_t zip_mode_sense_pages_changeable = -{ { - { 0, 0 }, - { GPMODE_R_W_ERROR_PAGE, 0x0a, 0xc8, 22, 0, 0, 0, 0, 90, 0, 0x50, 0x20 }, - { 0x02, 0x0e, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0x2f, 0x04, 0x5c, 0x0f, 0xff, 0x0f } -} }; +{ { + { 0, 0 }, + { GPMODE_R_W_ERROR_PAGE, 0x0a, 0xc8, 22, 0, 0, 0, 0, 90, 0, 0x50, 0x20 }, + { 0x02, 0x0e, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0x2f, 0x04, 0x5c, 0x0f, 0xff, 0x0f } +} }; static const mode_sense_pages_t zip_250_mode_sense_pages_changeable = -{ { - { 0, 0 }, - { GPMODE_R_W_ERROR_PAGE, 0x06, 0xc8, 0x64, 0, 0, 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0x05, 0x1e, 0x80, 0, 0x40, 0x20, 2, 0, 0, 0xef, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x0b, 0x7d, 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0x08, 0x0a, 4, 0, 0xff, 0xff, 0, 0, 0xff, 0xff, 0xff, 0xff }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0x2f, 0x04, 0x5c, 0x0f, 0x3c, 0x0f } -} }; - -static mode_sense_pages_t zip_mode_sense_pages_saved[ZIP_NUM]; +{ { + { 0, 0 }, + { GPMODE_R_W_ERROR_PAGE, 0x06, 0xc8, 0x64, 0, 0, 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0x05, 0x1e, 0x80, 0, 0x40, 0x20, 2, 0, 0, 0xef, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x0b, 0x7d, 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0x08, 0x0a, 4, 0, 0xff, 0xff, 0, 0, 0xff, 0xff, 0xff, 0xff }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0x2f, 0x04, 0x5c, 0x0f, 0x3c, 0x0f } +} }; -#ifdef ENABLE_ZIP_LOG -int zip_do_log = ENABLE_ZIP_LOG; -#endif - - -#ifdef ENABLE_ZIP_LOG static void zip_log(const char *format, ...) { #ifdef ENABLE_ZIP_LOG - va_list ap; + va_list ap; - if (zip_do_log) - { - va_start(ap, format); - pclog_ex(format, ap); - va_end(ap); - } + if (zip_do_log) { + va_start(ap, format); + pclog_ex(format, ap); + va_end(ap); + } #endif } -#endif -int find_zip_for_channel(uint8_t channel) +int +find_zip_for_channel(uint8_t channel) { - uint8_t i = 0; + uint8_t i = 0; - for (i = 0; i < ZIP_NUM; i++) { - if (((zip_drives[i].bus_type == ZIP_BUS_ATAPI_PIO_ONLY) || (zip_drives[i].bus_type == ZIP_BUS_ATAPI_PIO_AND_DMA)) && (zip_drives[i].ide_channel == channel)) - return i; - } - return 0xff; + for (i = 0; i < ZIP_NUM; i++) { + if ((zip_drives[i].bus_type == ZIP_BUS_ATAPI) && (zip_drives[i].ide_channel == channel)) + return i; + } + return 0xff; } -void zip_init(int id, int cdb_len_setting); -int zip_load(uint8_t id, const wchar_t *fn) +int +zip_load(zip_t *dev, const wchar_t *fn) { - int read_only = zip_drives[id].ui_writeprot; - int size = 0; + int read_only = dev->drv->ui_writeprot; + int size = 0; - zip_drives[id].f = plat_fopen(fn, zip_drives[id].ui_writeprot ? L"rb" : L"rb+"); - if (!zip_drives[id].ui_writeprot && !zip_drives[id].f) { - zip_drives[id].f = plat_fopen(fn, L"rb"); - read_only = 1; - } - if (zip_drives[id].f) { - fseek(zip_drives[id].f, 0, SEEK_END); - size = ftell(zip_drives[id].f); + dev->drv->f = plat_fopen(fn, dev->drv->ui_writeprot ? L"rb" : L"rb+"); + if (!dev->drv->ui_writeprot && !dev->drv->f) { + dev->drv->f = plat_fopen(fn, L"rb"); + read_only = 1; + } + if (dev->drv->f) { + fseek(dev->drv->f, 0, SEEK_END); + size = ftell(dev->drv->f); - if ((size == ((ZIP_250_SECTORS << 9) + 0x1000)) || (size == ((ZIP_SECTORS << 9) + 0x1000))) { - /* This is a ZDI image. */ - size -= 0x1000; - zip_drives[id].base = 0x1000; - } else - zip_drives[id].base = 0; + if ((size == ((ZIP_250_SECTORS << 9) + 0x1000)) || (size == ((ZIP_SECTORS << 9) + 0x1000))) { + /* This is a ZDI image. */ + size -= 0x1000; + dev->drv->base = 0x1000; + } else + dev->drv->base = 0; - if (zip_drives[id].is_250) { - if ((size != (ZIP_250_SECTORS << 9)) && (size != (ZIP_SECTORS << 9))) { -#ifdef ENABLE_ZIP_LOG - zip_log("File is incorrect size for a ZIP image\nMust be exactly %i or %i bytes\n", ZIP_250_SECTORS << 9, ZIP_SECTORS << 9); -#endif - fclose(zip_drives[id].f); - zip_drives[id].f = NULL; - zip_drives[id].medium_size = 0; - zip_eject(id); /* Make sure the host OS knows we've rejected (and ejected) the image. */ - return 0; - } - } else { - if (size != (ZIP_SECTORS << 9)) { -#ifdef ENABLE_ZIP_LOG - zip_log("File is incorrect size for a ZIP image\nMust be exactly %i bytes\n", ZIP_SECTORS << 9); -#endif - fclose(zip_drives[id].f); - zip_drives[id].f = NULL; - zip_drives[id].medium_size = 0; - zip_eject(id); /* Make sure the host OS knows we've rejected (and ejected) the image. */ - return 0; - } - } - - zip_drives[id].medium_size = size >> 9; - - fseek(zip_drives[id].f, zip_drives[id].base, SEEK_SET); - - memcpy(zip_drives[id].image_path, fn, sizeof(zip_drives[id].image_path)); - - zip_drives[id].read_only = read_only; - - return 1; - } - - return 0; -} - -void zip_disk_reload(uint8_t id) -{ - int ret = 0; - - if (wcslen(zip_drives[id].prev_image_path) == 0) - return; - else - ret = zip_load(id, zip_drives[id].prev_image_path); - - if (ret) - zip[id].unit_attention = 1; -} - -void zip_close(uint8_t id) -{ - if (zip_drives[id].f) { - fclose(zip_drives[id].f); - zip_drives[id].f = NULL; - - memcpy(zip_drives[id].prev_image_path, zip_drives[id].image_path, sizeof(zip_drives[id].prev_image_path)); - memset(zip_drives[id].image_path, 0, sizeof(zip_drives[id].image_path)); - - zip_drives[id].medium_size = 0; - } -} - -void build_atapi_zip_map(void) -{ - uint8_t i = 0; - - memset(atapi_zip_drives, 0xff, 8); - - for (i = 0; i < 8; i++) { - atapi_zip_drives[i] = find_zip_for_channel(i); - if (atapi_zip_drives[i] != 0xff) - zip_init(atapi_zip_drives[i], 12); - } -} - -int find_zip_for_scsi_id(uint8_t scsi_id, uint8_t scsi_lun) -{ - uint8_t i = 0; - - for (i = 0; i < ZIP_NUM; i++) { - if ((zip_drives[i].bus_type == ZIP_BUS_SCSI) && (zip_drives[i].scsi_device_id == scsi_id) && (zip_drives[i].scsi_device_lun == scsi_lun)) - return i; - } - return 0xff; -} - -void build_scsi_zip_map(void) -{ - uint8_t i = 0; - uint8_t j = 0; - - for (i = 0; i < 16; i++) - memset(scsi_zip_drives[i], 0xff, 8); - - for (i = 0; i < 16; i++) { - for (j = 0; j < 8; j++) { - scsi_zip_drives[i][j] = find_zip_for_scsi_id(i, j); - if (scsi_zip_drives[i][j] != 0xff) - zip_init(scsi_zip_drives[i][j], 12); - } - } -} - -void zip_set_callback(uint8_t id) -{ - if (zip_drives[id].bus_type != ZIP_BUS_SCSI) - ide_set_callback(zip_drives[id].ide_channel, zip[id].callback); -} - -void zip_set_cdb_len(int id, int cdb_len) -{ - zip[id].cdb_len = cdb_len; -} - -void zip_reset_cdb_len(int id) -{ - zip[id].cdb_len = zip[id].cdb_len_setting ? 16 : 12; -} - -void zip_set_signature(int id) -{ - if (id >= ZIP_NUM) - return; - zip[id].phase = 1; - zip[id].request_length = 0xEB14; -} - -void zip_init(int id, int cdb_len_setting) -{ - if (id >= ZIP_NUM) - return; - memset(&(zip[id]), 0, sizeof(zip_t)); - zip[id].requested_blocks = 1; - if (cdb_len_setting <= 1) - zip[id].cdb_len_setting = cdb_len_setting; - zip_reset_cdb_len(id); - zip[id].sense[0] = 0xf0; - zip[id].sense[7] = 10; - zip_drives[id].bus_mode = 0; - if (zip_drives[id].bus_type >= ZIP_BUS_ATAPI_PIO_AND_DMA) - zip_drives[id].bus_mode |= 2; - if (zip_drives[id].bus_type < ZIP_BUS_SCSI) - zip_drives[id].bus_mode |= 1; -#ifdef ENABLE_ZIP_LOG - zip_log("ZIP %i: Bus type %i, bus mode %i\n", id, zip_drives[id].bus_type, zip_drives[id].bus_mode); -#endif - if (zip_drives[id].bus_type < ZIP_BUS_SCSI) - zip_set_signature(id); - zip[id].status = READY_STAT | DSC_STAT; - zip[id].pos = 0; - zip[id].packet_status = 0xff; - zip_sense_key = zip_asc = zip_ascq = zip[id].unit_attention = 0; - zip[id].cdb_len_setting = 0; - zip[id].cdb_len = 12; -} - -int zip_supports_pio(int id) -{ - return (zip_drives[id].bus_mode & 1); -} - -int zip_supports_dma(int id) -{ - return (zip_drives[id].bus_mode & 2); -} - -/* Returns: 0 for none, 1 for PIO, 2 for DMA. */ -int zip_current_mode(int id) -{ - if (!zip_supports_pio(id) && !zip_supports_dma(id)) - return 0; - if (zip_supports_pio(id) && !zip_supports_dma(id)) { -#ifdef ENABLE_ZIP_LOG - zip_log("ZIP %i: Drive does not support DMA, setting to PIO\n", id); -#endif - return 1; - } - if (!zip_supports_pio(id) && zip_supports_dma(id)) - return 2; - if (zip_supports_pio(id) && zip_supports_dma(id)) { -#ifdef ENABLE_ZIP_LOG - zip_log("ZIP %i: Drive supports both, setting to %s\n", id, (zip[id].features & 1) ? "DMA" : "PIO", id); -#endif - return (zip[id].features & 1) ? 2 : 1; - } - - return 0; -} - -/* Translates ATAPI status (ERR_STAT flag) to SCSI status. */ -int zip_ZIP_PHASE_to_scsi(uint8_t id) -{ - if (zip[id].status & ERR_STAT) - return SCSI_STATUS_CHECK_CONDITION; - else - return SCSI_STATUS_OK; -} - -/* Translates ATAPI phase (DRQ, I/O, C/D) to SCSI phase (MSG, C/D, I/O). */ -int zip_atapi_phase_to_scsi(uint8_t id) -{ - if (zip[id].status & 8) { - switch (zip[id].phase & 3) { - case 0: - return 0; - case 1: - return 2; - case 2: - return 1; - case 3: - return 7; + if (dev->drv->is_250) { + if ((size != (ZIP_250_SECTORS << 9)) && (size != (ZIP_SECTORS << 9))) { + zip_log("File is incorrect size for a ZIP image\nMust be exactly %i or %i bytes\n", + ZIP_250_SECTORS << 9, ZIP_SECTORS << 9); + fclose(dev->drv->f); + dev->drv->f = NULL; + dev->drv->medium_size = 0; + ui_zip_eject(dev->id); /* Make sure the host OS knows we've rejected (and ejected) the image. */ + return 0; } } else { - if ((zip[id].phase & 3) == 3) - return 3; - else - return 4; - } - - return 0; -} - -int zip_lba_to_msf_accurate(int lba) -{ - int temp_pos; - int m, s, f; - - temp_pos = lba + 150; - f = temp_pos % 75; - temp_pos -= f; - temp_pos /= 75; - s = temp_pos % 60; - temp_pos -= s; - temp_pos /= 60; - m = temp_pos; - - return ((m << 16) | (s << 8) | f); -} - -void zip_mode_sense_load(uint8_t id) -{ - FILE *f; - wchar_t file_name[512]; - int i; - memset(&zip_mode_sense_pages_saved[id], 0, sizeof(mode_sense_pages_t)); - for (i = 0; i < 0x3f; i++) { - if (zip_drives[id].is_250) { - if (zip_250_mode_sense_pages_default.pages[i][1] != 0) { - if (zip_drives[id].bus_type == ZIP_BUS_SCSI) - memcpy(zip_mode_sense_pages_saved[id].pages[i], zip_250_mode_sense_pages_default_scsi.pages[i], zip_250_mode_sense_pages_default_scsi.pages[i][1] + 2); - else - memcpy(zip_mode_sense_pages_saved[id].pages[i], zip_250_mode_sense_pages_default.pages[i], zip_250_mode_sense_pages_default.pages[i][1] + 2); - } - } else { - if (zip_mode_sense_pages_default.pages[i][1] != 0) { - if (zip_drives[id].bus_type == ZIP_BUS_SCSI) - memcpy(zip_mode_sense_pages_saved[id].pages[i], zip_mode_sense_pages_default_scsi.pages[i], zip_mode_sense_pages_default_scsi.pages[i][1] + 2); - else - memcpy(zip_mode_sense_pages_saved[id].pages[i], zip_mode_sense_pages_default.pages[i], zip_mode_sense_pages_default.pages[i][1] + 2); - } + if (size != (ZIP_SECTORS << 9)) { + zip_log("File is incorrect size for a ZIP image\nMust be exactly %i bytes\n", + ZIP_SECTORS << 9); + fclose(dev->drv->f); + dev->drv->f = NULL; + dev->drv->medium_size = 0; + ui_zip_eject(dev->id); /* Make sure the host OS knows we've rejected (and ejected) the image. */ + return 0; } } - memset(file_name, 0, 512 * sizeof(wchar_t)); - if (zip_drives[id].bus_type == ZIP_BUS_SCSI) - swprintf(file_name, 512, L"scsi_zip_%02i_mode_sense_bin", id); - else - swprintf(file_name, 512, L"zip_%02i_mode_sense_bin", id); - f = plat_fopen(nvr_path(file_name), L"rb"); - if (f) - fclose(f); -} -void zip_mode_sense_save(uint8_t id) -{ - FILE *f; - wchar_t file_name[512]; - memset(file_name, 0, 512 * sizeof(wchar_t)); - if (zip_drives[id].bus_type == ZIP_BUS_SCSI) - swprintf(file_name, 512, L"scsi_zip_%02i_mode_sense_bin", id); - else - swprintf(file_name, 512, L"zip_%02i_mode_sense_bin", id); - f = plat_fopen(nvr_path(file_name), L"wb"); - if (f) - fclose(f); -} + dev->drv->medium_size = size >> 9; -static void zip_command_complete(uint8_t id); + fseek(dev->drv->f, dev->drv->base, SEEK_SET); -uint8_t zip_read_capacity_cdb[12] = {0x25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + memcpy(dev->drv->image_path, fn, sizeof(dev->drv->image_path)); -int zip_read_capacity(uint8_t id, uint8_t *cdb, uint8_t *buffer, uint32_t *len) -{ - int size = 0; - - if (zip_drives[id].is_250) - size = zip_drives[id].medium_size - 1; /* IMPORTANT: What's returned is the last LBA block. */ - else - size = ZIP_SECTORS - 1; /* IMPORTANT: What's returned is the last LBA block. */ - memset(buffer, 0, 8); - buffer[0] = (size >> 24) & 0xff; - buffer[1] = (size >> 16) & 0xff; - buffer[2] = (size >> 8) & 0xff; - buffer[3] = size & 0xff; - buffer[6] = 2; /* 512 = 0x0200 */ - *len = 8; + dev->drv->read_only = read_only; return 1; + } + + return 0; } + +void +zip_disk_reload(zip_t *dev) +{ + int ret = 0; + + if (wcslen(dev->drv->prev_image_path) == 0) + return; + else + ret = zip_load(dev, dev->drv->prev_image_path); + + if (ret) + dev->unit_attention = 1; +} + + +void +zip_disk_close(zip_t *dev) +{ + if (dev->drv->f) { + fclose(dev->drv->f); + dev->drv->f = NULL; + + memcpy(dev->drv->prev_image_path, dev->drv->image_path, sizeof(dev->drv->prev_image_path)); + memset(dev->drv->image_path, 0, sizeof(dev->drv->image_path)); + + dev->drv->medium_size = 0; + } +} + + +void +zip_build_atapi_map(void) +{ + uint8_t i; + + memset(atapi_zip_drives, 0xff, 8); + + for (i = 0; i < 8; i++) + atapi_zip_drives[i] = find_zip_for_channel(i); +} + + +int +find_zip_for_scsi_id(uint8_t scsi_id, uint8_t scsi_lun) +{ + uint8_t i; + + for (i = 0; i < ZIP_NUM; i++) { + if ((zip_drives[i].bus_type == ZIP_BUS_SCSI) && + (zip_drives[i].scsi_device_id == scsi_id) && + (zip_drives[i].scsi_device_lun == scsi_lun)) + return i; + } + + return 0xff; +} + + +void +zip_build_scsi_map(void) +{ + uint8_t i, j; + + for (i = 0; i < 16; i++) { + memset(scsi_zip_drives[i], 0xff, 8); + + for (j = 0; j < 8; j++) + scsi_zip_drives[i][j] = find_zip_for_scsi_id(i, j); + } +} + + +static void +zip_set_callback(zip_t *dev) +{ + if (dev->drv->bus_type != ZIP_BUS_SCSI) + ide_set_callback(dev->drv->ide_channel >> 1, dev->callback); +} + + +#if 0 /*UNUSED*/ +static void +zip_reset_cdb_len(zip_t *dev) +{ + if (dev->drv->bus_type != ZIP_BUS_SCSI) + dev->cdb_len = dev->cdb_len_setting ? 16 : 12; +} +#endif + + +void +zip_set_signature(zip_t *dev) +{ + if (dev->id >= ZIP_NUM) + return; + dev->phase = 1; + dev->request_length = 0xEB14; +} + + +void +zip_init(zip_t *dev) +{ + if (dev->id >= ZIP_NUM) + return; + + dev->requested_blocks = 1; + dev->sense[0] = 0xf0; + dev->sense[7] = 10; + dev->drv->bus_mode = 0; + if (dev->drv->bus_type >= ZIP_BUS_ATAPI) + dev->drv->bus_mode |= 2; + if (dev->drv->bus_type < ZIP_BUS_SCSI) + dev->drv->bus_mode |= 1; + zip_log("ZIP %i: Bus type %i, bus mode %i\n", dev->id, dev->drv->bus_type, dev->drv->bus_mode); + if (dev->drv->bus_type < ZIP_BUS_SCSI) + zip_set_signature(dev); + dev->status = READY_STAT | DSC_STAT; + dev->pos = 0; + dev->packet_status = 0xff; + zip_sense_key = zip_asc = zip_ascq = dev->unit_attention = 0; +} + + +static int +zip_supports_pio(zip_t *dev) +{ + return (dev->drv->bus_mode & 1); +} + + +static int +zip_supports_dma(zip_t *dev) +{ + return (dev->drv->bus_mode & 2); +} + + +/* Returns: 0 for none, 1 for PIO, 2 for DMA. */ +static int +zip_current_mode(zip_t *dev) +{ + if (!zip_supports_pio(dev) && !zip_supports_dma(dev)) + return 0; + if (zip_supports_pio(dev) && !zip_supports_dma(dev)) { + zip_log("ZIP %i: Drive does not support DMA, setting to PIO\n", dev->id); + return 1; + } + if (!zip_supports_pio(dev) && zip_supports_dma(dev)) + return 2; + if (zip_supports_pio(dev) && zip_supports_dma(dev)) { + zip_log("ZIP %i: Drive supports both, setting to %s\n", dev->id, (dev->features & 1) ? "DMA" : "PIO"); + return (dev->features & 1) ? 2 : 1; + } + + return 0; +} + + +/* Translates ATAPI status (ERR_STAT flag) to SCSI status. */ +int +zip_ZIP_PHASE_to_scsi(zip_t *dev) +{ + if (dev->status & ERR_STAT) + return SCSI_STATUS_CHECK_CONDITION; + else + return SCSI_STATUS_OK; +} + + +/* Translates ATAPI phase (DRQ, I/O, C/D) to SCSI phase (MSG, C/D, I/O). */ +int +zip_atapi_phase_to_scsi(zip_t *dev) +{ + if (dev->status & 8) { + switch (dev->phase & 3) { + case 0: + return 0; + case 1: + return 2; + case 2: + return 1; + case 3: + return 7; + } + } else { + if ((dev->phase & 3) == 3) + return 3; + else + return 4; + } + + return 0; +} + + +static void +zip_mode_sense_load(zip_t *dev) +{ + wchar_t file_name[512]; +#if 0 + FILE *f; +#endif + int i; + + memset(&dev->ms_pages_saved, 0, sizeof(mode_sense_pages_t)); + for (i = 0; i < 0x3f; i++) { + if (dev->drv->is_250) { + if (zip_250_mode_sense_pages_default.pages[i][1] != 0) { + if (zip_drives[dev->id].bus_type == ZIP_BUS_SCSI) { + memcpy(dev->ms_pages_saved.pages[i], + zip_250_mode_sense_pages_default_scsi.pages[i], + zip_250_mode_sense_pages_default_scsi.pages[i][1] + 2); + } else { + memcpy(dev->ms_pages_saved.pages[i], + zip_250_mode_sense_pages_default.pages[i], + zip_250_mode_sense_pages_default.pages[i][1] + 2); + } + } + } else { + if (zip_mode_sense_pages_default.pages[i][1] != 0) { + if (dev->drv->bus_type == ZIP_BUS_SCSI) { + memcpy(dev->ms_pages_saved.pages[i], + zip_mode_sense_pages_default_scsi.pages[i], + zip_mode_sense_pages_default_scsi.pages[i][1] + 2); + } else { + memcpy(dev->ms_pages_saved.pages[i], + zip_mode_sense_pages_default.pages[i], + zip_mode_sense_pages_default.pages[i][1] + 2); + } + } + } + } + memset(file_name, 0, 512 * sizeof(wchar_t)); + if (dev->drv->bus_type == ZIP_BUS_SCSI) + swprintf(file_name, 512, L"scsi_zip_%02i_mode_sense_bin", dev->id); + else + swprintf(file_name, 512, L"zip_%02i_mode_sense_bin", dev->id); + +#if 0 + /* FIXME: Doesnt do anything. Maybe "rb+" was meant? --FvK */ + f = plat_fopen(nvr_path(file_name), L"rb"); + if (f) + fclose(f); +#endif +} + + +static void +zip_mode_sense_save(zip_t *dev) +{ + wchar_t file_name[512]; + FILE *f; + + memset(file_name, 0, 512 * sizeof(wchar_t)); + if (dev->drv->bus_type == ZIP_BUS_SCSI) + swprintf(file_name, 512, L"scsi_zip_%02i_mode_sense_bin", dev->id); + else + swprintf(file_name, 512, L"zip_%02i_mode_sense_bin", dev->id); + f = plat_fopen(nvr_path(file_name), L"wb"); + if (f) + fclose(f); +} + + +int +zip_read_capacity(zip_t *dev, uint8_t *cdb, uint8_t *buffer, uint32_t *len) +{ + int size = 0; + + if (dev->drv->is_250) + size = dev->drv->medium_size - 1; /* IMPORTANT: What's returned is the last LBA block. */ + else + size = ZIP_SECTORS - 1; /* IMPORTANT: What's returned is the last LBA block. */ + memset(buffer, 0, 8); + buffer[0] = (size >> 24) & 0xff; + buffer[1] = (size >> 16) & 0xff; + buffer[2] = (size >> 8) & 0xff; + buffer[3] = size & 0xff; + buffer[6] = 2; /* 512 = 0x0200 */ + *len = 8; + + return 1; +} + + /*SCSI Mode Sense 6/10*/ -uint8_t zip_mode_sense_read(uint8_t id, uint8_t page_control, uint8_t page, uint8_t pos) +static uint8_t +zip_mode_sense_read(zip_t *dev, uint8_t page_control, uint8_t page, uint8_t pos) { - switch (page_control) { - case 0: - case 3: - if (zip_drives[id].is_250 && (page == 5) && (pos == 9) && (zip_drives[id].medium_size == ZIP_SECTORS)) + switch (page_control) { + case 0: + case 3: + if (dev->drv->is_250 && (page == 5) && (pos == 9) && (dev->drv->medium_size == ZIP_SECTORS)) + return 0x60; + return dev->ms_pages_saved.pages[page][pos]; + break; + case 1: + if (dev->drv->is_250) + return zip_250_mode_sense_pages_changeable.pages[page][pos]; + else + return zip_mode_sense_pages_changeable.pages[page][pos]; + break; + case 2: + if (dev->drv->is_250) { + if ((page == 5) && (pos == 9) && (dev->drv->medium_size == ZIP_SECTORS)) return 0x60; - return zip_mode_sense_pages_saved[id].pages[page][pos]; - break; - case 1: - if (zip_drives[id].is_250) - return zip_250_mode_sense_pages_changeable.pages[page][pos]; + if (dev->drv->bus_type == ZIP_BUS_SCSI) + return zip_250_mode_sense_pages_default_scsi.pages[page][pos]; else - return zip_mode_sense_pages_changeable.pages[page][pos]; - break; - case 2: - if (zip_drives[id].is_250) { - if ((page == 5) && (pos == 9) && (zip_drives[id].medium_size == ZIP_SECTORS)) - return 0x60; - if (zip_drives[id].bus_type == ZIP_BUS_SCSI) - return zip_250_mode_sense_pages_default_scsi.pages[page][pos]; - else - return zip_250_mode_sense_pages_default.pages[page][pos]; - } else { - if (zip_drives[id].bus_type == ZIP_BUS_SCSI) - return zip_mode_sense_pages_default_scsi.pages[page][pos]; - else - return zip_mode_sense_pages_default.pages[page][pos]; - } - break; - } - - return 0; -} - -uint32_t zip_mode_sense(uint8_t id, uint8_t *buf, uint32_t pos, uint8_t type, uint8_t block_descriptor_len) -{ - uint64_t pg_flags; - uint8_t pg_control = (type >> 6) & 3; - - if (zip_drives[id].is_250) - pg_flags = zip_250_mode_sense_page_flags; - else - pg_flags = zip_mode_sense_page_flags; - - int i = 0; - int j = 0; - - uint8_t msplen; - - type &= 0x3f; - - if (block_descriptor_len) { - if (zip_drives[id].is_250) { - buf[pos++] = ((zip_drives[id].medium_size >> 24) & 0xff); - buf[pos++] = ((zip_drives[id].medium_size >> 16) & 0xff); - buf[pos++] = ((zip_drives[id].medium_size >> 8) & 0xff); - buf[pos++] = ( zip_drives[id].medium_size & 0xff); + return zip_250_mode_sense_pages_default.pages[page][pos]; } else { - buf[pos++] = ((ZIP_SECTORS >> 24) & 0xff); - buf[pos++] = ((ZIP_SECTORS >> 16) & 0xff); - buf[pos++] = ((ZIP_SECTORS >> 8) & 0xff); - buf[pos++] = ( ZIP_SECTORS & 0xff); + if (dev->drv->bus_type == ZIP_BUS_SCSI) + return zip_mode_sense_pages_default_scsi.pages[page][pos]; + else + return zip_mode_sense_pages_default.pages[page][pos]; } - buf[pos++] = 0; /* Reserved. */ - buf[pos++] = 0; /* Block length (0x200 = 512 bytes). */ - buf[pos++] = 2; - buf[pos++] = 0; - } + break; + } - for (i = 0; i < 0x40; i++) { - if ((type == GPMODE_ALL_PAGES) || (type == i)) { - if (pg_flags & (1LL << zip[id].current_page_code)) { - buf[pos++] = zip_mode_sense_read(id, pg_control, i, 0); - msplen = zip_mode_sense_read(id, pg_control, i, 1); - buf[pos++] = msplen; -#ifdef ENABLE_ZIP_LOG - zip_log("ZIP %i: MODE SENSE: Page [%02X] length %i\n", id, i, msplen); -#endif - for (j = 0; j < msplen; j++) - buf[pos++] = zip_mode_sense_read(id, pg_control, i, 2 + j); + return 0; +} + + +static uint32_t +zip_mode_sense(zip_t *dev, uint8_t *buf, uint32_t pos, uint8_t type, uint8_t block_descriptor_len) +{ + uint8_t page_control = (type >> 6) & 3; + uint8_t msplen; + uint64_t pf; + int i, j; + + if (dev->drv->is_250) + pf = zip_250_mode_sense_page_flags; + else + pf = zip_mode_sense_page_flags; + + type &= 0x3f; + + if (block_descriptor_len) { + if (dev->drv->is_250) { + buf[pos++] = ((dev->drv->medium_size >> 24) & 0xff); + buf[pos++] = ((dev->drv->medium_size >> 16) & 0xff); + buf[pos++] = ((dev->drv->medium_size >> 8) & 0xff); + buf[pos++] = ( dev->drv->medium_size & 0xff); + } else { + buf[pos++] = ((ZIP_SECTORS >> 24) & 0xff); + buf[pos++] = ((ZIP_SECTORS >> 16) & 0xff); + buf[pos++] = ((ZIP_SECTORS >> 8) & 0xff); + buf[pos++] = ( ZIP_SECTORS & 0xff); + } + buf[pos++] = 0; /* Reserved. */ + buf[pos++] = 0; /* Block length (0x200 = 512 bytes). */ + buf[pos++] = 2; + buf[pos++] = 0; + } + + for (i = 0; i < 0x40; i++) { + if ((type == GPMODE_ALL_PAGES) || (type == i)) { + if (pf & (1LL << dev->current_page_code)) { + buf[pos++] = zip_mode_sense_read(dev, page_control, i, 0); + msplen = zip_mode_sense_read(dev, page_control, i, 1); + buf[pos++] = msplen; + zip_log("ZIP %i: MODE SENSE: Page [%02X] length %i\n", dev->id, i, msplen); + for (j = 0; j < msplen; j++) + buf[pos++] = zip_mode_sense_read(dev, page_control, i, 2 + j); + } + } + } + + return pos; +} + + +static void +zip_update_request_length(zip_t *dev, int len, int block_len) +{ + int bt, min_len = 0; + + dev->max_transfer_len = dev->request_length; + + /* For media access commands, make sure the requested DRQ length matches the block length. */ + switch (dev->current_cdb[0]) { + case 0x08: + case 0x28: + case 0xa8: + /* Make sure total length is not bigger than sum of the lengths of + all the requested blocks. */ + bt = (dev->requested_blocks * block_len); + if (len > bt) + len = bt; + + min_len = block_len; + + if (len <= block_len) { + /* Total length is less or equal to block length. */ + if (dev->max_transfer_len < block_len) { + /* Transfer a minimum of (block size) bytes. */ + dev->max_transfer_len = block_len; + dev->packet_len = block_len; + break; } } - } + default: + dev->packet_len = len; + break; + } + /* If the DRQ length is odd, and the total remaining length is bigger, make sure it's even. */ + if ((dev->max_transfer_len & 1) && (dev->max_transfer_len < len)) + dev->max_transfer_len &= 0xfffe; + /* If the DRQ length is smaller or equal in size to the total remaining length, set it to that. */ + if (!dev->max_transfer_len) + dev->max_transfer_len = 65534; - return pos; + if ((len <= dev->max_transfer_len) && (len >= min_len)) + dev->request_length = dev->max_transfer_len = len; + else if (len > dev->max_transfer_len) + dev->request_length = dev->max_transfer_len; + + return; } -void zip_update_request_length(uint8_t id, int len, int block_len) + +static void +zip_command_bus(zip_t *dev) { - int bt; + dev->status = BUSY_STAT; + dev->phase = 1; + dev->pos = 0; + dev->callback = 1LL * ZIP_TIME; - if (!zip[id].request_length) - zip[id].max_transfer_len = 65534; - else - zip[id].max_transfer_len = zip[id].request_length; - - /* For media access commands, make sure the requested DRQ length matches the block length. */ - switch (zip[id].current_cdb[0]) { - case 0x08: - case 0x28: - case 0xa8: - if (zip[id].max_transfer_len < block_len) - zip[id].max_transfer_len = block_len; - bt = (zip[id].requested_blocks * block_len); - if (len > bt) - len = bt; - default: - zip[id].packet_len = len; - break; - } - /* If the DRQ length is odd, and the total remaining length is bigger, make sure it's even. */ - if ((zip[id].max_transfer_len & 1) && (zip[id].max_transfer_len < len)) - zip[id].max_transfer_len &= 0xfffe; - /* If the DRQ length is smaller or equal in size to the total remaining length, set it to that. */ - if (len <= zip[id].max_transfer_len) - zip[id].max_transfer_len = len; - return; + zip_set_callback(dev); } -static void zip_command_common(uint8_t id) -{ - double bytes_per_second, period; - double dusec; - bytes_per_second = 0.0; - zip[id].status = BUSY_STAT; - zip[id].phase = 1; - zip[id].pos = 0; - if (zip[id].packet_status == ZIP_PHASE_COMPLETE) { - zip_phase_callback(id); - zip[id].callback = 0LL; +static void +zip_command_common(zip_t *dev) +{ + double bytes_per_second, period; + double dusec; + + dev->status = BUSY_STAT; + dev->phase = 1; + dev->pos = 0; + + if (dev->packet_status == ZIP_PHASE_COMPLETE) { + zip_phase_callback(dev); + dev->callback = 0LL; + } else { + if (dev->drv->bus_type == ZIP_BUS_SCSI) { + dev->callback = -1LL; /* Speed depends on SCSI controller */ + return; } else { - if (zip_drives[id].bus_type == ZIP_BUS_SCSI) { - zip[id].callback = -1LL; /* Speed depends on SCSI controller */ - return; - } else if (zip_drives[id].bus_type == ZIP_BUS_ATAPI_PIO_AND_DMA) { - if (zip_current_mode(id) == 2) - bytes_per_second = 66666666.666666666666666; /* 66 MB/s MDMA-2 speed */ - else - bytes_per_second = 8333333.333333333333333; /* 8.3 MB/s PIO-2 speed */ - } else - bytes_per_second = 3333333.333333333333333; /* 3.3 MB/s PIO-0 speed */ - - period = 1000000.0 / bytes_per_second; - dusec = (double) TIMER_USEC; - dusec = dusec * period * (double) (zip[id].packet_len); - zip[id].callback = ((int32_t) dusec); + if (zip_current_mode(dev) == 2) + bytes_per_second = 66666666.666666666666666; /* 66 MB/s MDMA-2 speed */ + else + bytes_per_second = 8333333.333333333333333; /* 8.3 MB/s PIO-2 speed */ } - zip_set_callback(id); + period = 1000000.0 / bytes_per_second; + dusec = (double) TIMER_USEC; + dusec = dusec * period * (double) (dev->packet_len); + dev->callback = (int64_t)dusec; + } + + zip_set_callback(dev); } -static void zip_command_complete(uint8_t id) + +static void +zip_command_complete(zip_t *dev) { - zip[id].packet_status = ZIP_PHASE_COMPLETE; - zip_command_common(id); + dev->packet_status = ZIP_PHASE_COMPLETE; + + zip_command_common(dev); } -static void zip_command_read(uint8_t id) + +static void +zip_command_read(zip_t *dev) { - zip[id].packet_status = ZIP_PHASE_DATA_IN; - zip_command_common(id); - zip[id].total_read = 0; + dev->packet_status = ZIP_PHASE_DATA_IN; + zip_command_common(dev); + dev->total_read = 0; } -static void zip_command_read_dma(uint8_t id) + +static void +zip_command_read_dma(zip_t *dev) { - zip[id].packet_status = ZIP_PHASE_DATA_IN_DMA; - zip_command_common(id); - zip[id].total_read = 0; + dev->packet_status = ZIP_PHASE_DATA_IN_DMA; + zip_command_common(dev); + dev->total_read = 0; } -static void zip_command_write(uint8_t id) + +static void +zip_command_write(zip_t *dev) { - zip[id].packet_status = ZIP_PHASE_DATA_OUT; - zip_command_common(id); + dev->packet_status = ZIP_PHASE_DATA_OUT; + + zip_command_common(dev); } -static void zip_command_write_dma(uint8_t id) + +static void +zip_command_write_dma(zip_t *dev) { - zip[id].packet_status = ZIP_PHASE_DATA_OUT_DMA; - zip_command_common(id); + dev->packet_status = ZIP_PHASE_DATA_OUT_DMA; + + zip_command_common(dev); } -/* id = Current ZIP device ID; + +/* dev = Current ZIP device; len = Total transfer length; block_len = Length of a single block (why does it matter?!); alloc_len = Allocated transfer length; direction = Transfer direction (0 = read from host, 1 = write to host). */ -static void zip_data_command_finish(uint8_t id, int len, int block_len, int alloc_len, int direction) +static void +zip_data_command_finish(zip_t *dev, int len, int block_len, int alloc_len, int direction) { -#ifdef ENABLE_ZIP_LOG - zip_log("ZIP %i: Finishing command (%02X): %i, %i, %i, %i, %i\n", id, zip[id].current_cdb[0], len, block_len, alloc_len, direction, zip[id].request_length); -#endif - zip[id].pos=0; - if (alloc_len >= 0) { - if (alloc_len < len) { - len = alloc_len; - } + zip_log("ZIP %i: Finishing command (%02X): %i, %i, %i, %i, %i\n", + dev->id, dev->current_cdb[0], len, block_len, + alloc_len, direction, dev->request_length); + dev->pos = 0; + if (alloc_len >= 0) { + if (alloc_len < len) + len = alloc_len; + } + if ((len == 0) || (zip_current_mode(dev) == 0)) { + if (dev->drv->bus_type != ZIP_BUS_SCSI) + dev->packet_len = 0; + + zip_command_complete(dev); + } else { + if (zip_current_mode(dev) == 2) { + if (dev->drv->bus_type != ZIP_BUS_SCSI) + dev->packet_len = alloc_len; + + if (direction == 0) + zip_command_read_dma(dev); + else + zip_command_write_dma(dev); + } else { + zip_update_request_length(dev, len, block_len); + if (direction == 0) + zip_command_read(dev); + else + zip_command_write(dev); } + } - if ((len == 0) || (zip_current_mode(id) == 0)) { - if (zip_drives[id].bus_type != ZIP_BUS_SCSI) { - zip[id].packet_len = 0; - } - zip_command_complete(id); - } - else { - if (zip_current_mode(id) == 2) { - if (zip_drives[id].bus_type != ZIP_BUS_SCSI) { - zip[id].packet_len = alloc_len; - } - - if (direction == 0) - zip_command_read_dma(id); - else - zip_command_write_dma(id); - } - else { - zip_update_request_length(id, len, block_len); - if (direction == 0) - zip_command_read(id); - else - zip_command_write(id); - } - } - -#ifdef ENABLE_ZIP_LOG - zip_log("ZIP %i: Status: %i, cylinder %i, packet length: %i, position: %i, phase: %i\n", id, zip[id].packet_status, zip[id].request_length, zip[id].packet_len, zip[id].pos, zip[id].phase); -#endif + zip_log("ZIP %i: Status: %i, cylinder %i, packet length: %i, position: %i, phase: %i\n", + dev->id, dev->packet_status, dev->request_length, + dev->packet_len, dev->pos, dev->phase); } -static void zip_sense_clear(int id, int command) + +static void +zip_sense_clear(zip_t *dev, int command) { - zip[id].previous_command = command; - zip_sense_key = zip_asc = zip_ascq = 0; + dev->previous_command = command; + zip_sense_key = zip_asc = zip_ascq = 0; } -static void zip_set_phase(uint8_t id, uint8_t phase) + +static void +zip_set_phase(zip_t *dev, uint8_t phase) { - uint8_t scsi_id = zip_drives[id].scsi_device_id; - uint8_t scsi_lun = zip_drives[id].scsi_device_lun; + uint8_t scsi_id = dev->drv->scsi_device_id; + uint8_t scsi_lun = dev->drv->scsi_device_lun; - if (zip_drives[id].bus_type != ZIP_BUS_SCSI) - return; + if (dev->drv->bus_type != ZIP_BUS_SCSI) + return; - SCSIDevices[scsi_id][scsi_lun].Phase = phase; + SCSIDevices[scsi_id][scsi_lun].Phase = phase; } -static void zip_cmd_error(uint8_t id) + +static void +zip_cmd_error(zip_t *dev) { - zip_set_phase(id, SCSI_PHASE_STATUS); - zip[id].error = ((zip_sense_key & 0xf) << 4) | ABRT_ERR; - if (zip[id].unit_attention) - zip[id].error |= MCR_ERR; - zip[id].status = READY_STAT | ERR_STAT; - zip[id].phase = 3; - zip[id].pos = 0; - zip[id].packet_status = 0x80; - zip[id].callback = 50LL * ZIP_TIME; - zip_set_callback(id); -#ifdef ENABLE_ZIP_LOG - zip_log("ZIP %i: [%02X] ERROR: %02X/%02X/%02X\n", id, zip[id].current_cdb[0], zip_sense_key, zip_asc, zip_ascq); -#endif + zip_set_phase(dev, SCSI_PHASE_STATUS); + + dev->error = ((zip_sense_key & 0xf) << 4) | ABRT_ERR; + if (dev->unit_attention) + dev->error |= MCR_ERR; + dev->status = READY_STAT | ERR_STAT; + dev->phase = 3; + dev->pos = 0; + dev->packet_status = 0x80; + dev->callback = 50LL * ZIP_TIME; + + zip_set_callback(dev); + + zip_log("ZIP %i: [%02X] ERROR: %02X/%02X/%02X\n", + dev->id, dev->current_cdb[0], zip_sense_key, zip_asc, zip_ascq); } -static void zip_unit_attention(uint8_t id) + +static void +zip_unit_attention(zip_t *dev) { - zip_set_phase(id, SCSI_PHASE_STATUS); - zip[id].error = (SENSE_UNIT_ATTENTION << 4) | ABRT_ERR; - if (zip[id].unit_attention) - zip[id].error |= MCR_ERR; - zip[id].status = READY_STAT | ERR_STAT; - zip[id].phase = 3; - zip[id].pos = 0; - zip[id].packet_status = 0x80; - zip[id].callback = 50LL * ZIP_TIME; - zip_set_callback(id); -#ifdef ENABLE_ZIP_LOG - zip_log("ZIP %i: UNIT ATTENTION\n", id); -#endif + zip_set_phase(dev, SCSI_PHASE_STATUS); + + dev->error = (SENSE_UNIT_ATTENTION << 4) | ABRT_ERR; + if (dev->unit_attention) + dev->error |= MCR_ERR; + dev->status = READY_STAT | ERR_STAT; + dev->phase = 3; + dev->pos = 0; + dev->packet_status = 0x80; + dev->callback = 50LL * ZIP_TIME; + + zip_set_callback(dev); + + zip_log("ZIP %i: UNIT ATTENTION\n", dev->id); } -static void zip_not_ready(uint8_t id) + +static void +zip_bus_master_error(zip_t *dev) { - zip_sense_key = SENSE_NOT_READY; - zip_asc = ASC_MEDIUM_NOT_PRESENT; - zip_ascq = 0; - zip_cmd_error(id); + zip_sense_key = zip_asc = zip_ascq = 0; + + zip_cmd_error(dev); } -static void zip_write_protected(uint8_t id) + +static void +zip_not_ready(zip_t *dev) { - zip_sense_key = SENSE_UNIT_ATTENTION; - zip_asc = ASC_WRITE_PROTECTED; - zip_ascq = 0; - zip_cmd_error(id); + zip_sense_key = SENSE_NOT_READY; + zip_asc = ASC_MEDIUM_NOT_PRESENT; + zip_ascq = 0; + + zip_cmd_error(dev); } -static void zip_invalid_lun(uint8_t id) + +static void +zip_write_protected(zip_t *dev) { - zip_sense_key = SENSE_ILLEGAL_REQUEST; - zip_asc = ASC_INV_LUN; - zip_ascq = 0; - zip_cmd_error(id); + zip_sense_key = SENSE_UNIT_ATTENTION; + zip_asc = ASC_WRITE_PROTECTED; + zip_ascq = 0; + + zip_cmd_error(dev); } -static void zip_illegal_opcode(uint8_t id) + +static void +zip_invalid_lun(zip_t *dev) { - zip_sense_key = SENSE_ILLEGAL_REQUEST; - zip_asc = ASC_ILLEGAL_OPCODE; - zip_ascq = 0; - zip_cmd_error(id); + zip_sense_key = SENSE_ILLEGAL_REQUEST; + zip_asc = ASC_INV_LUN; + zip_ascq = 0; + + zip_cmd_error(dev); } -static void zip_lba_out_of_range(uint8_t id) + +static void +zip_illegal_opcode(zip_t *dev) { - zip_sense_key = SENSE_ILLEGAL_REQUEST; - zip_asc = ASC_LBA_OUT_OF_RANGE; - zip_ascq = 0; - zip_cmd_error(id); + zip_sense_key = SENSE_ILLEGAL_REQUEST; + zip_asc = ASC_ILLEGAL_OPCODE; + zip_ascq = 0; + + zip_cmd_error(dev); } -static void zip_invalid_field(uint8_t id) + +static void +zip_lba_out_of_range(zip_t *dev) { - zip_sense_key = SENSE_ILLEGAL_REQUEST; - zip_asc = ASC_INV_FIELD_IN_CMD_PACKET; - zip_ascq = 0; - zip_cmd_error(id); - zip[id].status = 0x53; + zip_sense_key = SENSE_ILLEGAL_REQUEST; + zip_asc = ASC_LBA_OUT_OF_RANGE; + zip_ascq = 0; + + zip_cmd_error(dev); } -static void zip_invalid_field_pl(uint8_t id) + +static void +zip_invalid_field(zip_t *dev) { - zip_sense_key = SENSE_ILLEGAL_REQUEST; - zip_asc = ASC_INV_FIELD_IN_PARAMETER_LIST; - zip_ascq = 0; - zip_cmd_error(id); - zip[id].status = 0x53; + zip_sense_key = SENSE_ILLEGAL_REQUEST; + zip_asc = ASC_INV_FIELD_IN_CMD_PACKET; + zip_ascq = 0; + + zip_cmd_error(dev); + + dev->status = 0x53; } -static void zip_data_phase_error(uint8_t id) + +static void +zip_invalid_field_pl(zip_t *dev) { - zip_sense_key = SENSE_ILLEGAL_REQUEST; - zip_asc = ASC_DATA_PHASE_ERROR; - zip_ascq = 0; - zip_cmd_error(id); + zip_sense_key = SENSE_ILLEGAL_REQUEST; + zip_asc = ASC_INV_FIELD_IN_PARAMETER_LIST; + zip_ascq = 0; + + zip_cmd_error(dev); + + dev->status = 0x53; } -#define zipbufferb zip[id].buffer -int zip_blocks(uint8_t id, uint32_t *len, int first_batch, int out) +static void +zip_data_phase_error(zip_t *dev) { - zip[id].data_pos = 0; + zip_sense_key = SENSE_ILLEGAL_REQUEST; + zip_asc = ASC_DATA_PHASE_ERROR; + zip_ascq = 0; - *len = 0; - - if (!zip[id].sector_len) { - zip_command_complete(id); - return -1; - } - - *len = zip[id].requested_blocks << 9; - - if (zip[id].sector_pos >= zip_drives[id].medium_size) { -#ifdef ENABLE_ZIP_LOG - zip_log("ZIP %i: Trying to %s beyond the end of disk\n", id, out ? "write" : "read"); -#endif - zip_lba_out_of_range(id); - return 0; - } - -#ifdef ENABLE_ZIP_LOG - zip_log("%s %i bytes of blocks...\n", out ? "Written" : "Read", *len); fseek(zip_drives[id].f, zip_drives[id].base + (zip[id].sector_pos << 9), SEEK_SET); -#endif - if (out) - fwrite(zipbufferb, 1, *len, zip_drives[id].f); - else - fread(zipbufferb, 1, *len, zip_drives[id].f); - -#ifdef ENABLE_ZIP_LOG - zip_log("%s %i bytes of blocks...\n", out ? "Written" : "Read", *len); -#endif - - zip[id].sector_pos += zip[id].requested_blocks; - zip[id].sector_len -= zip[id].requested_blocks; - - return 1; + zip_cmd_error(dev); } -void zip_insert(uint8_t id) + +static int +zip_blocks(zip_t *dev, int32_t *len, int first_batch, int out) { - zip[id].unit_attention = 1; + dev->data_pos = 0; + + *len = 0; + + if (! dev->sector_len) { + zip_command_complete(dev); + return -1; + } + + zip_log("%sing %i blocks starting from %i...\n", + out ? "Writ" : "Read", dev->requested_blocks, dev->sector_pos); + + if (dev->sector_pos >= dev->drv->medium_size) { + zip_log("ZIP %i: Trying to %s beyond the end of disk\n", + dev->id, out ? "write" : "read"); + zip_lba_out_of_range(dev); + return 0; + } + + *len = dev->requested_blocks << 9; + + fseek(dev->drv->f, dev->drv->base + (dev->sector_pos << 9), SEEK_SET); + if (out) + fwrite(zipbufferb, 1, *len, dev->drv->f); + else + fread(zipbufferb, 1, *len, dev->drv->f); + + zip_log("%s %i bytes of blocks...\n", out ? "Written" : "Read", *len); + + dev->sector_pos += dev->requested_blocks; + dev->sector_len -= dev->requested_blocks; + + return 1; } + +void +zip_insert(zip_t *dev) +{ + dev->unit_attention = 1; +} + + /*SCSI Sense Initialization*/ -void zip_sense_code_ok(uint8_t id) +void +zip_sense_code_ok(zip_t *dev) { - zip_sense_key = SENSE_NONE; - zip_asc = 0; - zip_ascq = 0; + zip_sense_key = SENSE_NONE; + zip_asc = 0; + zip_ascq = 0; } -int zip_pre_execution_check(uint8_t id, uint8_t *cdb) + +static int +zip_pre_execution_check(zip_t *dev, uint8_t *cdb) { - int ready = 0; + int ready = 0; - if (zip_drives[id].bus_type == ZIP_BUS_SCSI) { - if (((zip[id].request_length >> 5) & 7) != zip_drives[id].scsi_device_lun) { -#ifdef ENABLE_ZIP_LOG - zip_log("ZIP %i: Attempting to execute a unknown command targeted at SCSI LUN %i\n", id, ((zip[id].request_length >> 5) & 7)); + if (dev->drv->bus_type == ZIP_BUS_SCSI) { +#if 0 + if (((dev->request_length >> 5) & 7) != dev->drv->scsi_device_lun) { +#else + if ((cdb[0] != GPCMD_REQUEST_SENSE) && (cdb[1] & 0xe0)) { #endif - zip_invalid_lun(id); - return 0; - } - } - - if (!(zip_command_flags[cdb[0]] & IMPLEMENTED)) { -#ifdef ENABLE_ZIP_LOG - zip_log("ZIP %i: Attempting to execute unknown command %02X over %s\n", id, cdb[0], (zip_drives[id].bus_type == ZIP_BUS_SCSI) ? "SCSI" : ((zip_drives[id].bus_type == ZIP_BUS_ATAPI_PIO_AND_DMA) ? "ATAPI PIO/DMA" : "ATAPI PIO")); -#endif - - zip_illegal_opcode(id); + zip_log("ZIP %i: Attempting to execute a unknown command targeted at SCSI LUN %i\n", + dev->id, ((dev->request_length >> 5) & 7)); + zip_invalid_lun(dev); return 0; } + } - if ((zip_drives[id].bus_type < ZIP_BUS_SCSI) && (zip_command_flags[cdb[0]] & SCSI_ONLY)) { -#ifdef ENABLE_ZIP_LOG - zip_log("ZIP %i: Attempting to execute SCSI-only command %02X over ATAPI\n", id, cdb[0]); -#endif - zip_illegal_opcode(id); + if (!(zip_command_flags[cdb[0]] & IMPLEMENTED)) { + zip_log("ZIP %i: Attempting to execute unknown command %02X over %s\n", + dev->id, cdb[0], +//FIXME: use function zip_bus_name(bus_type) .. --FvK + (dev->drv->bus_type == ZIP_BUS_SCSI) ? "SCSI" : "ATAPI"); + + zip_illegal_opcode(dev); + return 0; + } + + if ((dev->drv->bus_type != ZIP_BUS_SCSI) && + (zip_command_flags[cdb[0]] & SCSI_ONLY)) { + zip_log("ZIP %i: Attempting to execute SCSI-only command %02X over ATAPI\n", + dev->id, cdb[0]); + zip_illegal_opcode(dev); + return 0; + } + + if ((dev->drv->bus_type != ZIP_BUS_ATAPI) && + (zip_command_flags[cdb[0]] & ATAPI_ONLY)) { + zip_log("ZIP %i: Attempting to execute ATAPI-only command %02X over SCSI\n", + dev->id, cdb[0]); + zip_illegal_opcode(dev); + return 0; + } + + ready = (dev->drv->f != NULL); + + /* If the drive is not ready, there is no reason to keep the + UNIT ATTENTION condition present, as we only use it to mark + disc changes. */ + if (!ready && dev->unit_attention) + dev->unit_attention = 0; + + /* If the UNIT ATTENTION condition is set and the command does not allow + execution under it, error out and report the condition. */ + if (dev->unit_attention == 1) { + /* Only increment the unit attention phase if the command can not pass through it. */ + if (!(zip_command_flags[cdb[0]] & ALLOW_UA)) { + /* zip_log("ZIP %i: Unit attention now 2\n", dev->id); */ + dev->unit_attention = 2; + zip_log("ZIP %i: UNIT ATTENTION: Command %02X not allowed to pass through\n", dev->id, cdb[0]); + zip_unit_attention(dev); return 0; } - - if ((zip_drives[id].bus_type == ZIP_BUS_SCSI) && (zip_command_flags[cdb[0]] & ATAPI_ONLY)) { -#ifdef ENABLE_ZIP_LOG - zip_log("ZIP %i: Attempting to execute ATAPI-only command %02X over SCSI\n", id, cdb[0]); -#endif - zip_illegal_opcode(id); - return 0; + } else if (dev->unit_attention == 2) { + if (cdb[0] != GPCMD_REQUEST_SENSE) { + /* zip_log("ZIP %i: Unit attention now 0\n", dev->id); */ + dev->unit_attention = 0; } + } - ready = (zip_drives[id].f != NULL); + /* Unless the command is REQUEST SENSE, clear the sense. This will *NOT* + the UNIT ATTENTION condition if it's set. */ + if (cdb[0] != GPCMD_REQUEST_SENSE) + zip_sense_clear(dev, cdb[0]); + /* Next it's time for NOT READY. */ + if (! ready) + dev->media_status = MEC_MEDIA_REMOVAL; + else + dev->media_status = (dev->unit_attention) ? MEC_NEW_MEDIA : MEC_NO_CHANGE; + + if ((zip_command_flags[cdb[0]] & CHECK_READY) && !ready) { + zip_log("ZIP %i: Not ready (%02X)\n", dev->id, cdb[0]); + zip_not_ready(dev); + return 0; + } + + zip_log("ZIP %i: Continuing with command %02X\n", dev->id, cdb[0]); + + return 1; +} + + +static void +zip_seek(zip_t *dev, uint32_t pos) +{ + /* zip_log("ZIP %i: Seek %08X\n", dev->id, pos); */ + dev->sector_pos = pos; +} + + +static void +zip_rezero(zip_t *dev) +{ + dev->sector_pos = dev->sector_len = 0; + + zip_seek(dev, 0); +} + + +void +zip_reset(zip_t *dev) +{ + zip_rezero(dev); + + dev->status = 0; + dev->callback = 0LL; + + zip_set_callback(dev); + + dev->packet_status = 0xff; + dev->unit_attention = 0; +} + + +static void +zip_request_sense(zip_t *dev, uint8_t *buffer, uint8_t alloc_length, int desc) +{ + /*Will return 18 bytes of 0*/ + if (alloc_length != 0) { + memset(buffer, 0, alloc_length); + if (! desc) + memcpy(buffer, dev->sense, alloc_length); + else { + buffer[1] = zip_sense_key; + buffer[2] = zip_asc; + buffer[3] = zip_ascq; + } + } + + buffer[0] = desc ? 0x72 : 0x70; + + if (dev->unit_attention && (zip_sense_key == 0)) { + buffer[desc ? 1 : 2] = SENSE_UNIT_ATTENTION; + buffer[desc ? 2 : 12] = ASC_MEDIUM_MAY_HAVE_CHANGED; + buffer[desc ? 3 : 13] = 0; + } + + zip_log("ZIP %i: Reporting sense: %02X %02X %02X\n", + dev->id, buffer[2], buffer[12], buffer[13]); + + if (buffer[desc ? 1 : 2] == SENSE_UNIT_ATTENTION) { + /* If the last remaining sense is unit attention, clear + that condition. */ + dev->unit_attention = 0; + } + + /* Clear the sense stuff as per the spec. */ + zip_sense_clear(dev, GPCMD_REQUEST_SENSE); +} + + +void +zip_request_sense_for_scsi(zip_t *dev, uint8_t *buffer, uint8_t alloc_length) +{ + int ready; + + ready = (dev->drv->f != NULL); + + if (!ready && dev->unit_attention) { /* If the drive is not ready, there is no reason to keep the UNIT ATTENTION condition present, as we only use it to mark disc changes. */ - if (!ready && zip[id].unit_attention) - zip[id].unit_attention = 0; + dev->unit_attention = 0; + } - /* If the UNIT ATTENTION condition is set and the command does not allow - execution under it, error out and report the condition. */ - if (zip[id].unit_attention == 1) { - /* Only increment the unit attention phase if the command can not pass through it. */ - if (!(zip_command_flags[cdb[0]] & ALLOW_UA)) { -#ifdef ENABLE_ZIP_LOG - /* zip_log("ZIP %i: Unit attention now 2\n", id); */ -#endif - zip[id].unit_attention = 2; -#ifdef ENABLE_ZIP_LOG - zip_log("ZIP %i: UNIT ATTENTION: Command %02X not allowed to pass through\n", id, cdb[0]); -#endif - zip_unit_attention(id); - return 0; + /* Do *NOT* advance the unit attention phase. */ + + zip_request_sense(dev, buffer, alloc_length, 0); +} + + +static void +zip_set_buf_len(zip_t *dev, int32_t *BufLen, int32_t *src_len) +{ + if (dev->drv->bus_type == ZIP_BUS_SCSI) { + if (*BufLen == -1) + *BufLen = *src_len; + else { + *BufLen = MIN(*src_len, *BufLen); + *src_len = *BufLen; + } + zip_log("ZIP %i: Actual transfer length: %i\n", dev->id, *BufLen); + } +} + + +static void +zip_buf_alloc(zip_t *dev, uint32_t len) +{ + zip_log("ZIP %i: Allocated buffer length: %i\n", dev->id, len); + + zipbufferb = (uint8_t *)mem_alloc(len); +} + + +static void +zip_buf_free(zip_t *dev) +{ + if (zipbufferb) { + zip_log("ZIP %i: Freeing buffer...\n", dev->id); + free(zipbufferb); + zipbufferb = NULL; + } +} + + +void +zip_command(zip_t *dev, uint8_t *cdb) +{ + int pos = 0, block_desc = 0; + int32_t len, max_len; + int32_t alloc_length; + int size_idx, idx = 0; + unsigned preamble_len; + uint32_t i = 0; + int32_t blen = 0; + int32_t *BufLen; + uint32_t ulen; + int ret; + + if (dev->drv->bus_type == ZIP_BUS_SCSI) { + BufLen = &SCSIDevices[dev->drv->scsi_device_id][dev->drv->scsi_device_lun].BufferLength; + dev->status &= ~ERR_STAT; + } else { + BufLen = &blen; + dev->error = 0; + } + + dev->packet_len = 0; + dev->request_pos = 0; + dev->data_pos = 0; + + memcpy(dev->current_cdb, cdb, 12); + + if (cdb[0] != 0) { + zip_log("ZIP %i: Command 0x%02X, Sense Key %02X, Asc %02X, Ascq %02X, Unit attention: %i\n", dev->id, cdb[0], zip_sense_key, zip_asc, zip_ascq, dev->unit_attention); + zip_log("ZIP %i: Request length: %04X\n", dev->id, dev->request_length); + + zip_log("ZIP %i: CDB: %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n", dev->id, + cdb[0], cdb[1], cdb[2], cdb[3], cdb[4], cdb[5], cdb[6], cdb[7], + cdb[8], cdb[9], cdb[10], cdb[11]); + } + + dev->sector_len = 0; + + zip_set_phase(dev, SCSI_PHASE_STATUS); + + /* This handles the Not Ready/Unit Attention check if it has to be handled at this point. */ + if (zip_pre_execution_check(dev, cdb) == 0) + return; + + switch (cdb[0]) { + case GPCMD_SEND_DIAGNOSTIC: + if (!(cdb[1] & (1 << 2))) { + zip_invalid_field(dev); + return; } - } - else if (zip[id].unit_attention == 2) { - if (cdb[0] != GPCMD_REQUEST_SENSE) { -#ifdef ENABLE_ZIP_LOG - /* zip_log("ZIP %i: Unit attention now 0\n", id); */ -#endif - zip[id].unit_attention = 0; + case GPCMD_SCSI_RESERVE: + case GPCMD_SCSI_RELEASE: + case GPCMD_TEST_UNIT_READY: + zip_set_phase(dev, SCSI_PHASE_STATUS); + zip_command_complete(dev); + break; + + case GPCMD_FORMAT_UNIT: + if ((dev->drv->bus_type == ZIP_BUS_SCSI) && dev->drv->read_only) + { + zip_write_protected(dev); + return; } - } - /* Unless the command is REQUEST SENSE, clear the sense. This will *NOT* - the UNIT ATTENTION condition if it's set. */ - if (cdb[0] != GPCMD_REQUEST_SENSE) - zip_sense_clear(id, cdb[0]); + zip_set_phase(dev, SCSI_PHASE_STATUS); + zip_command_complete(dev); + break; - /* Next it's time for NOT READY. */ - if (!ready) - zip[id].media_status = MEC_MEDIA_REMOVAL; - else - zip[id].media_status = (zip[id].unit_attention) ? MEC_NEW_MEDIA : MEC_NO_CHANGE; - - if ((zip_command_flags[cdb[0]] & CHECK_READY) && !ready) { -#ifdef ENABLE_ZIP_LOG - zip_log("ZIP %i: Not ready (%02X)\n", id, cdb[0]); -#endif - zip_not_ready(id); - return 0; - } - -#ifdef ENABLE_ZIP_LOG - zip_log("ZIP %i: Continuing with command %02X\n", id, cdb[0]); -#endif - - return 1; -} - -void zip_clear_callback(uint8_t channel) -{ - uint8_t id = atapi_zip_drives[channel]; - - if (id < ZIP_NUM) - { - zip[id].callback = 0LL; - zip_set_callback(id); - } -} - -static void zip_seek(uint8_t id, uint32_t pos) -{ -#ifdef ENABLE_ZIP_LOG - /* zip_log("ZIP %i: Seek %08X\n", id, pos); */ -#endif - zip[id].sector_pos = pos; -} - -static void zip_rezero(uint8_t id) -{ - zip[id].sector_pos = zip[id].sector_len = 0; - zip_seek(id, 0); -} - -void zip_reset(uint8_t id) -{ - zip_rezero(id); - zip[id].status = 0; - zip[id].callback = 0LL; - zip_set_callback(id); - zip[id].packet_status = 0xff; - zip[id].unit_attention = 0; -} - -void zip_request_sense(uint8_t id, uint8_t *buffer, uint8_t alloc_length, int desc) -{ - /*Will return 18 bytes of 0*/ - if (alloc_length != 0) { - memset(buffer, 0, alloc_length); - if (!desc) - memcpy(buffer, zip[id].sense, alloc_length); - else { - buffer[1] = zip_sense_key; - buffer[2] = zip_asc; - buffer[3] = zip_ascq; + case GPCMD_IOMEGA_SENSE: + zip_set_phase(dev, SCSI_PHASE_DATA_IN); + max_len = cdb[4]; + zip_buf_alloc(dev, 256); + zip_set_buf_len(dev, BufLen, &max_len); + memset(zipbufferb, 0, 256); + if (cdb[2] == 1) { + /* This page is related to disk health status - setting + this page to 0 makes disk health read as "marginal". */ + zipbufferb[0] = 0x58; + zipbufferb[1] = 0x00; + for (i = 0x00; i < 0x58; i++) + zipbufferb[i + 0x02] = 0xff; + } else if (cdb[2] == 2) { + zipbufferb[0] = 0x3d; + zipbufferb[1] = 0x00; + for (i = 0x00; i < 0x13; i++) + zipbufferb[i + 0x02] = 0x00; + zipbufferb[0x15] = 0x00; + if (dev->drv->read_only) + zipbufferb[0x15] |= 0x02; + for (i = 0x00; i < 0x27; i++) + zipbufferb[i + 0x16] = 0x00; + } else { + zip_invalid_field(dev); + zip_buf_free(dev); + return; } - } + zip_data_command_finish(dev, 18, 18, cdb[4], 0); + break; - buffer[0] = desc ? 0x72 : 0x70; + case GPCMD_REZERO_UNIT: + dev->sector_pos = dev->sector_len = 0; + zip_seek(dev, 0); + zip_set_phase(dev, SCSI_PHASE_STATUS); + break; - if (zip[id].unit_attention && (zip_sense_key == 0)) { - buffer[desc ? 1 : 2]=SENSE_UNIT_ATTENTION; - buffer[desc ? 2 : 12]=ASC_MEDIUM_MAY_HAVE_CHANGED; - buffer[desc ? 3 : 13]=0; - } + case GPCMD_REQUEST_SENSE: + /* If there's a unit attention condition and there's a buffered not ready, a standalone REQUEST SENSE + should forget about the not ready, and report unit attention straight away. */ + zip_set_phase(dev, SCSI_PHASE_DATA_IN); + max_len = cdb[4]; + zip_buf_alloc(dev, 256); + zip_set_buf_len(dev, BufLen, &max_len); + len = (cdb[1] & 1) ? 8 : 18; + zip_request_sense(dev, zipbufferb, max_len, cdb[1] & 1); + zip_data_command_finish(dev, len, len, cdb[4], 0); + break; -#ifdef ENABLE_ZIP_LOG - zip_log("ZIP %i: Reporting sense: %02X %02X %02X\n", id, buffer[2], buffer[12], buffer[13]); -#endif + case GPCMD_MECHANISM_STATUS: + zip_set_phase(dev, SCSI_PHASE_DATA_IN); + len = (cdb[7] << 16) | (cdb[8] << 8) | cdb[9]; - if (buffer[desc ? 1 : 2] == SENSE_UNIT_ATTENTION) { - /* If the last remaining sense is unit attention, clear - that condition. */ - zip[id].unit_attention = 0; - } + zip_buf_alloc(dev, 8); - /* Clear the sense stuff as per the spec. */ - zip_sense_clear(id, GPCMD_REQUEST_SENSE); -} + zip_set_buf_len(dev, BufLen, &len); -void zip_request_sense_for_scsi(uint8_t id, uint8_t *buffer, uint8_t alloc_length) -{ - int ready = 0; + memset(zipbufferb, 0, 8); + zipbufferb[5] = 1; - ready = (zip_drives[id].f != NULL); + zip_data_command_finish(dev, 8, 8, len, 0); + break; - if (!ready && zip[id].unit_attention) { - /* If the drive is not ready, there is no reason to keep the - UNIT ATTENTION condition present, as we only use it to mark - disc changes. */ - zip[id].unit_attention = 0; - } + case GPCMD_READ_6: + case GPCMD_READ_10: + case GPCMD_READ_12: + zip_set_phase(dev, SCSI_PHASE_DATA_IN); + alloc_length = 512; - /* Do *NOT* advance the unit attention phase. */ - - zip_request_sense(id, buffer, alloc_length, 0); -} - -void zip_set_buf_len(uint8_t id, int32_t *BufLen, uint32_t *src_len) -{ - if (zip_drives[id].bus_type == ZIP_BUS_SCSI) { - if (*BufLen == -1) - *BufLen = *src_len; - else { - *BufLen = MIN(*src_len, (uint32_t)*BufLen); - *src_len = *BufLen; + switch(cdb[0]) { + case GPCMD_READ_6: + dev->sector_len = cdb[4]; + dev->sector_pos = ((((uint32_t) cdb[1]) & 0x1f) << 16) | (((uint32_t) cdb[2]) << 8) | ((uint32_t) cdb[3]); + zip_log("ZIP %i: Length: %i, LBA: %i\n", dev->id, dev->sector_len, dev->sector_pos); + break; + case GPCMD_READ_10: + dev->sector_len = (cdb[7] << 8) | cdb[8]; + dev->sector_pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; + zip_log("ZIP %i: Length: %i, LBA: %i\n", dev->id, dev->sector_len, dev->sector_pos); + break; + case GPCMD_READ_12: + dev->sector_len = (((uint32_t) cdb[6]) << 24) | (((uint32_t) cdb[7]) << 16) | (((uint32_t) cdb[8]) << 8) | ((uint32_t) cdb[9]); + dev->sector_pos = (((uint32_t) cdb[2]) << 24) | (((uint32_t) cdb[3]) << 16) | (((uint32_t) cdb[4]) << 8) | ((uint32_t) cdb[5]); + break; } -#ifdef ENABLE_ZIP_LOG - zip_log("ZIP %i: Actual transfer length: %i\n", id, *BufLen); -#endif - } -} -void zip_buf_alloc(uint8_t id, uint32_t len) -{ -#ifdef ENABLE_ZIP_LOG - zip_log("ZIP %i: Allocated buffer length: %i\n", id, len); -#endif - zipbufferb = (uint8_t *) malloc(len); -} + if (!dev->sector_len) { + zip_set_phase(dev, SCSI_PHASE_STATUS); + /* zip_log("ZIP %i: All done - callback set\n", dev->id); */ + dev->packet_status = ZIP_PHASE_COMPLETE; + dev->callback = 20LL * ZIP_TIME; + zip_set_callback(dev); + break; + } -void zip_buf_free(uint8_t id) -{ - if (zipbufferb) { -#ifdef ENABLE_ZIP_LOG - zip_log("ZIP %i: Freeing buffer...\n", id); -#endif - free(zipbufferb); - zipbufferb = NULL; - } -} + max_len = dev->sector_len; + dev->requested_blocks = max_len; /* If we're reading all blocks in one go for DMA, why not also for PIO, it should NOT + matter anyway, this step should be identical and only the way the read dat is + transferred to the host should be different. */ -void zip_command(uint8_t id, uint8_t *cdb) -{ - uint32_t len; - int pos=0; - uint32_t max_len; - unsigned idx = 0; - unsigned size_idx; - unsigned preamble_len; - uint32_t alloc_length; - int block_desc = 0; - int ret; - int32_t blen = 0; - int32_t *BufLen; - uint32_t i = 0; + dev->packet_len = max_len * alloc_length; + zip_buf_alloc(dev, dev->packet_len); - if (zip_drives[id].bus_type == ZIP_BUS_SCSI) { - BufLen = &SCSIDevices[zip_drives[id].scsi_device_id][zip_drives[id].scsi_device_lun].BufferLength; - zip[id].status &= ~ERR_STAT; - } else { - BufLen = &blen; - zip[id].error = 0; - } + ret = zip_blocks(dev, &alloc_length, 1, 0); + if (ret <= 0) { + zip_buf_free(dev); + return; + } - zip[id].packet_len = 0; - zip[id].request_pos = 0; + dev->requested_blocks = max_len; + dev->packet_len = alloc_length; - zip[id].data_pos = 0; + zip_set_buf_len(dev, BufLen, (int32_t *)&dev->packet_len); - memcpy(zip[id].current_cdb, cdb, zip[id].cdb_len); + zip_data_command_finish(dev, alloc_length, 512, alloc_length, 0); -#ifdef ENABLE_ZIP_LOG - if (cdb[0] != 0) { - zip_log("ZIP %i: Command 0x%02X, Sense Key %02X, Asc %02X, Ascq %02X, Unit attention: %i\n", id, cdb[0], zip_sense_key, zip_asc, zip_ascq, zip[id].unit_attention); - zip_log("ZIP %i: Request length: %04X\n", id, zip[id].request_length); - - zip_log("ZIP %i: CDB: %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n", id, - cdb[0], cdb[1], cdb[2], cdb[3], cdb[4], cdb[5], cdb[6], cdb[7], - cdb[8], cdb[9], cdb[10], cdb[11]); - } -#endif - - zip[id].sector_len = 0; - - zip_set_phase(id, SCSI_PHASE_STATUS); - - /* This handles the Not Ready/Unit Attention check if it has to be handled at this point. */ - if (zip_pre_execution_check(id, cdb) == 0) + dev->all_blocks_total = dev->block_total; + if (dev->packet_status != ZIP_PHASE_COMPLETE) + ui_sb_icon_update(SB_ZIP | dev->id, 1); + else + ui_sb_icon_update(SB_ZIP | dev->id, 0); return; - switch (cdb[0]) { - case GPCMD_SEND_DIAGNOSTIC: - if (!(cdb[1] & (1 << 2))) { - zip_invalid_field(id); - return; - } - case GPCMD_SCSI_RESERVE: - case GPCMD_SCSI_RELEASE: - case GPCMD_TEST_UNIT_READY: - zip_set_phase(id, SCSI_PHASE_STATUS); - zip_command_complete(id); + case GPCMD_VERIFY_6: + case GPCMD_VERIFY_10: + case GPCMD_VERIFY_12: + if (!(cdb[1] & 2)) { + zip_set_phase(dev, SCSI_PHASE_STATUS); + zip_command_complete(dev); break; + } + case GPCMD_WRITE_6: + case GPCMD_WRITE_10: + case GPCMD_WRITE_AND_VERIFY_10: + case GPCMD_WRITE_12: + case GPCMD_WRITE_AND_VERIFY_12: + zip_set_phase(dev, SCSI_PHASE_DATA_OUT); + alloc_length = 512; - case GPCMD_FORMAT_UNIT: - if ((zip_drives[id].bus_type == ZIP_BUS_SCSI) && zip_drives[id].read_only) - { - zip_write_protected(id); - return; - } + if ((dev->drv->bus_type == ZIP_BUS_SCSI) && dev->drv->read_only) { + zip_write_protected(dev); + return; + } - zip_set_phase(id, SCSI_PHASE_STATUS); - zip_command_complete(id); - break; - - case GPCMD_IOMEGA_SENSE: - zip_set_phase(id, SCSI_PHASE_DATA_IN); - max_len = cdb[4]; - zip_buf_alloc(id, 256); - zip_set_buf_len(id, BufLen, &max_len); - memset(zipbufferb, 0, 256); - if (cdb[2] == 1) { - /* This page is related to disk health status - setting - this page to 0 makes disk health read as "marginal". */ - zipbufferb[0] = 0x58; - zipbufferb[1] = 0x00; - for (i = 0x00; i < 0x58; i++) - zipbufferb[i + 0x02] = 0xff; - } else if (cdb[2] == 2) { - zipbufferb[0] = 0x3d; - zipbufferb[1] = 0x00; - for (i = 0x00; i < 0x13; i++) - zipbufferb[i + 0x02] = 0x00; - zipbufferb[0x15] = 0x00; - if (zip_drives[id].read_only) - zipbufferb[0x15] |= 0x02; - for (i = 0x00; i < 0x27; i++) - zipbufferb[i + 0x16] = 0x00; - } else { - zip_invalid_field(id); - zip_buf_free(id); - return; - } - zip_data_command_finish(id, 18, 18, cdb[4], 0); - break; - - case GPCMD_REZERO_UNIT: - zip[id].sector_pos = zip[id].sector_len = 0; - zip_seek(id, 0); - zip_set_phase(id, SCSI_PHASE_STATUS); - break; - - case GPCMD_REQUEST_SENSE: - /* If there's a unit attention condition and there's a buffered not ready, a standalone REQUEST SENSE - should forget about the not ready, and report unit attention straight away. */ - zip_set_phase(id, SCSI_PHASE_DATA_IN); - max_len = cdb[4]; - zip_buf_alloc(id, 256); - zip_set_buf_len(id, BufLen, &max_len); - len = (cdb[1] & 1) ? 8 : 18; - zip_request_sense(id, zipbufferb, max_len, cdb[1] & 1); - zip_data_command_finish(id, len, len, cdb[4], 0); - break; - - case GPCMD_SET_SPEED: - case GPCMD_SET_SPEED_ALT: - zip_set_phase(id, SCSI_PHASE_STATUS); - zip_command_complete(id); - break; - - case GPCMD_MECHANISM_STATUS: - zip_set_phase(id, SCSI_PHASE_DATA_IN); - len = (cdb[7] << 16) | (cdb[8] << 8) | cdb[9]; - - zip_buf_alloc(id, 8); - - zip_set_buf_len(id, BufLen, &len); - - memset(zipbufferb, 0, 8); - zipbufferb[5] = 1; - - zip_data_command_finish(id, 8, 8, len, 0); - break; - - case GPCMD_READ_6: - case GPCMD_READ_10: - case GPCMD_READ_12: - zip_set_phase(id, SCSI_PHASE_DATA_IN); - alloc_length = 512; - - switch(cdb[0]) { - case GPCMD_READ_6: - zip[id].sector_len = cdb[4]; - zip[id].sector_pos = ((((uint32_t) cdb[1]) & 0x1f) << 16) | (((uint32_t) cdb[2]) << 8) | ((uint32_t) cdb[3]); -#ifdef ENABLE_ZIP_LOG - zip_log("ZIP %i: Length: %i, LBA: %i\n", id, zip[id].sector_len, zip[id].sector_pos); -#endif - break; - case GPCMD_READ_10: - zip[id].sector_len = (cdb[7] << 8) | cdb[8]; - zip[id].sector_pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; -#ifdef ENABLE_ZIP_LOG - zip_log("ZIP %i: Length: %i, LBA: %i\n", id, zip[id].sector_len, zip[id].sector_pos); -#endif - break; - case GPCMD_READ_12: - zip[id].sector_len = (((uint32_t) cdb[6]) << 24) | (((uint32_t) cdb[7]) << 16) | (((uint32_t) cdb[8]) << 8) | ((uint32_t) cdb[9]); - zip[id].sector_pos = (((uint32_t) cdb[2]) << 24) | (((uint32_t) cdb[3]) << 16) | (((uint32_t) cdb[4]) << 8) | ((uint32_t) cdb[5]); - break; - } - - if (!zip[id].sector_len) { - zip_set_phase(id, SCSI_PHASE_STATUS); -#ifdef ENABLE_ZIP_LOG - /* zip_log("ZIP %i: All done - callback set\n", id); */ -#endif - zip[id].packet_status = ZIP_PHASE_COMPLETE; - zip[id].callback = 20LL * ZIP_TIME; - zip_set_callback(id); + switch(cdb[0]) { + case GPCMD_VERIFY_6: + case GPCMD_WRITE_6: + dev->sector_len = cdb[4]; + dev->sector_pos = ((((uint32_t) cdb[1]) & 0x1f) << 16) | (((uint32_t) cdb[2]) << 8) | ((uint32_t) cdb[3]); break; - } - - max_len = zip[id].sector_len; - zip[id].requested_blocks = max_len; /* If we're reading all blocks in one go for DMA, why not also for PIO, it should NOT - matter anyway, this step should be identical and only the way the read dat is - transferred to the host should be different. */ - - zip[id].packet_len = max_len * alloc_length; - zip_buf_alloc(id, zip[id].packet_len); - - ret = zip_blocks(id, &alloc_length, 1, 0); - if (ret <= 0) { - zip_buf_free(id); - return; - } - - zip[id].requested_blocks = max_len; - zip[id].packet_len = alloc_length; - - zip_set_buf_len(id, BufLen, &zip[id].packet_len); - - zip_data_command_finish(id, alloc_length, 512, alloc_length, 0); - - zip[id].all_blocks_total = zip[id].block_total; - if (zip[id].packet_status != ZIP_PHASE_COMPLETE) - ui_sb_icon_update(SB_ZIP | id, 1); - else - ui_sb_icon_update(SB_ZIP | id, 0); - return; - - case GPCMD_VERIFY_6: - case GPCMD_VERIFY_10: - case GPCMD_VERIFY_12: - if (!(cdb[1] & 2)) { - zip_set_phase(id, SCSI_PHASE_STATUS); - zip_command_complete(id); + case GPCMD_VERIFY_10: + case GPCMD_WRITE_10: + case GPCMD_WRITE_AND_VERIFY_10: + dev->sector_len = (cdb[7] << 8) | cdb[8]; + dev->sector_pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; + zip_log("ZIP %i: Length: %i, LBA: %i\n", dev->id, dev->sector_len, dev->sector_pos); break; - } - case GPCMD_WRITE_6: - case GPCMD_WRITE_10: - case GPCMD_WRITE_AND_VERIFY_10: - case GPCMD_WRITE_12: - case GPCMD_WRITE_AND_VERIFY_12: - zip_set_phase(id, SCSI_PHASE_DATA_OUT); - alloc_length = 512; - - if ((zip_drives[id].bus_type == ZIP_BUS_SCSI) && zip_drives[id].read_only) - { - zip_write_protected(id); - return; - } - - switch(cdb[0]) { - case GPCMD_VERIFY_6: - case GPCMD_WRITE_6: - zip[id].sector_len = cdb[4]; - zip[id].sector_pos = ((((uint32_t) cdb[1]) & 0x1f) << 16) | (((uint32_t) cdb[2]) << 8) | ((uint32_t) cdb[3]); - break; - case GPCMD_VERIFY_10: - case GPCMD_WRITE_10: - case GPCMD_WRITE_AND_VERIFY_10: - zip[id].sector_len = (cdb[7] << 8) | cdb[8]; - zip[id].sector_pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; -#ifdef ENABLE_ZIP_LOG - zip_log("ZIP %i: Length: %i, LBA: %i\n", id, zip[id].sector_len, zip[id].sector_pos); -#endif - break; - case GPCMD_VERIFY_12: - case GPCMD_WRITE_12: - case GPCMD_WRITE_AND_VERIFY_12: - zip[id].sector_len = (((uint32_t) cdb[6]) << 24) | (((uint32_t) cdb[7]) << 16) | (((uint32_t) cdb[8]) << 8) | ((uint32_t) cdb[9]); - zip[id].sector_pos = (((uint32_t) cdb[2]) << 24) | (((uint32_t) cdb[3]) << 16) | (((uint32_t) cdb[4]) << 8) | ((uint32_t) cdb[5]); - break; - } - - if (zip_drives[id].is_250) { - if ((zip[id].sector_pos >= zip_drives[id].medium_size) || ((zip[id].sector_pos + zip[id].sector_len - 1) >= zip_drives[id].medium_size)) - { - zip_lba_out_of_range(id); - return; - } - } else { - if ((zip[id].sector_pos >= ZIP_SECTORS) || ((zip[id].sector_pos + zip[id].sector_len - 1) >= ZIP_SECTORS)) - { - zip_lba_out_of_range(id); - return; - } - } - - if (!zip[id].sector_len) { - zip_set_phase(id, SCSI_PHASE_STATUS); -#ifdef ENABLE_ZIP_LOG - /* zip_log("ZIP %i: All done - callback set\n", id); */ -#endif - zip[id].packet_status = ZIP_PHASE_COMPLETE; - zip[id].callback = 20LL * ZIP_TIME; - zip_set_callback(id); + case GPCMD_VERIFY_12: + case GPCMD_WRITE_12: + case GPCMD_WRITE_AND_VERIFY_12: + dev->sector_len = (((uint32_t) cdb[6]) << 24) | (((uint32_t) cdb[7]) << 16) | (((uint32_t) cdb[8]) << 8) | ((uint32_t) cdb[9]); + dev->sector_pos = (((uint32_t) cdb[2]) << 24) | (((uint32_t) cdb[3]) << 16) | (((uint32_t) cdb[4]) << 8) | ((uint32_t) cdb[5]); break; - } + } - max_len = zip[id].sector_len; - zip[id].requested_blocks = max_len; /* If we're writing all blocks in one go for DMA, why not also for PIO, it should NOT - matter anyway, this step should be identical and only the way the read dat is - transferred to the host should be different. */ - - zip[id].packet_len = max_len * alloc_length; - zip_buf_alloc(id, zip[id].packet_len); - - zip[id].requested_blocks = max_len; - zip[id].packet_len = max_len << 9; - - zip_set_buf_len(id, BufLen, &zip[id].packet_len); - - zip_data_command_finish(id, zip[id].packet_len, 512, zip[id].packet_len, 1); - - zip[id].all_blocks_total = zip[id].block_total; - if (zip[id].packet_status != ZIP_PHASE_COMPLETE) - ui_sb_icon_update(SB_ZIP | id, 1); - else - ui_sb_icon_update(SB_ZIP | id, 0); - return; - - case GPCMD_WRITE_SAME_10: - zip_set_phase(id, SCSI_PHASE_DATA_OUT); - alloc_length = 512; - - if ((cdb[1] & 6) == 6) - { - zip_invalid_field(id); + if (dev->drv->is_250) { + if ((dev->sector_pos >= dev->drv->medium_size) || + ((dev->sector_pos + dev->sector_len - 1) >= dev->drv->medium_size)) { + zip_lba_out_of_range(dev); return; } - - if ((zip_drives[id].bus_type == ZIP_BUS_SCSI) && zip_drives[id].read_only) - { - zip_write_protected(id); + } else { + if ((dev->sector_pos >= ZIP_SECTORS) || + ((dev->sector_pos + dev->sector_len - 1) >= ZIP_SECTORS)) { + zip_lba_out_of_range(dev); return; } + } - zip[id].sector_len = (cdb[7] << 8) | cdb[8]; - zip[id].sector_pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; - - if (zip_drives[id].is_250) { - if ((zip[id].sector_pos >= zip_drives[id].medium_size) || ((zip[id].sector_pos + zip[id].sector_len - 1) >= zip_drives[id].medium_size)) - { - zip_lba_out_of_range(id); - return; - } - } else { - if ((zip[id].sector_pos >= ZIP_SECTORS) || ((zip[id].sector_pos + zip[id].sector_len - 1) >= ZIP_SECTORS)) - { - zip_lba_out_of_range(id); - return; - } - } - - if (!zip[id].sector_len) { - zip_set_phase(id, SCSI_PHASE_STATUS); -#ifdef ENABLE_ZIP_LOG - /* zip_log("ZIP %i: All done - callback set\n", id); */ -#endif - zip[id].packet_status = ZIP_PHASE_COMPLETE; - zip[id].callback = 20LL * ZIP_TIME; - zip_set_callback(id); - break; - } - - max_len = zip[id].sector_len; - zip[id].requested_blocks = max_len; /* If we're writing all blocks in one go for DMA, why not also for PIO, it should NOT - matter anyway, this step should be identical and only the way the read dat is - transferred to the host should be different. */ - - zip[id].packet_len = max_len * alloc_length; - zip_buf_alloc(id, zip[id].packet_len); - - zip[id].requested_blocks = max_len; - zip[id].packet_len = alloc_length; - - zip_set_buf_len(id, BufLen, &zip[id].packet_len); - - zip_data_command_finish(id, zip[id].packet_len, 512, zip[id].packet_len, 1); - - zip[id].all_blocks_total = zip[id].block_total; - if (zip[id].packet_status != ZIP_PHASE_COMPLETE) - ui_sb_icon_update(SB_ZIP | id, 1); - else - ui_sb_icon_update(SB_ZIP | id, 0); - return; - - case GPCMD_MODE_SENSE_6: - case GPCMD_MODE_SENSE_10: - zip_set_phase(id, SCSI_PHASE_DATA_IN); - - if (zip_drives[id].bus_type == ZIP_BUS_SCSI) - block_desc = ((cdb[1] >> 3) & 1) ? 0 : 1; - else - block_desc = 0; - - if (cdb[0] == GPCMD_MODE_SENSE_6) { - len = cdb[4]; - zip_buf_alloc(id, 256); - } else { - len = (cdb[8] | (cdb[7] << 8)); - zip_buf_alloc(id, 65536); - } - - zip[id].current_page_code = cdb[2] & 0x3F; -#ifdef ENABLE_ZIP_LOG - zip_log("Mode sense page: %02X\n", zip[id].current_page_code); -#endif - - if (!(zip_mode_sense_page_flags & (1LL << zip[id].current_page_code))) { - zip_invalid_field(id); - zip_buf_free(id); - return; - } - - memset(zipbufferb, 0, len); - alloc_length = len; - - if (cdb[0] == GPCMD_MODE_SENSE_6) { - len = zip_mode_sense(id, zipbufferb, 4, cdb[2], block_desc); - len = MIN(len, alloc_length); - zipbufferb[0] = len - 1; - zipbufferb[1] = 0; - if (block_desc) - zipbufferb[3] = 8; - } else { - len = zip_mode_sense(id, zipbufferb, 8, cdb[2], block_desc); - len = MIN(len, alloc_length); - zipbufferb[0]=(len - 2) >> 8; - zipbufferb[1]=(len - 2) & 255; - zipbufferb[2] = 0; - if (block_desc) { - zipbufferb[6] = 0; - zipbufferb[7] = 8; - } - } - - zip_set_buf_len(id, BufLen, &len); - -#ifdef ENABLE_ZIP_LOG - zip_log("ZIP %i: Reading mode page: %02X...\n", id, cdb[2]); -#endif - - zip_data_command_finish(id, len, len, alloc_length, 0); - return; - - case GPCMD_MODE_SELECT_6: - case GPCMD_MODE_SELECT_10: - zip_set_phase(id, SCSI_PHASE_DATA_OUT); - - if (cdb[0] == GPCMD_MODE_SELECT_6) { - len = cdb[4]; - zip_buf_alloc(id, 256); - } else { - len = (cdb[7] << 8) | cdb[8]; - zip_buf_alloc(id, 65536); - } - - zip_set_buf_len(id, BufLen, &len); - - zip[id].total_length = len; - zip[id].do_page_save = cdb[1] & 1; - - zip[id].current_page_pos = 0; - - zip_data_command_finish(id, len, len, len, 1); - return; - - case GPCMD_START_STOP_UNIT: - zip_set_phase(id, SCSI_PHASE_STATUS); - - switch(cdb[4] & 3) { - case 0: /* Stop the disc. */ - zip_eject(id); /* The Iomega Windows 9x drivers require this. */ - break; - case 1: /* Start the disc and read the TOC. */ - break; - case 2: /* Eject the disc if possible. */ - /* zip_eject(id); */ - break; - case 3: /* Load the disc (close tray). */ - zip_reload(id); - break; - } - - zip_command_complete(id); + if (!dev->sector_len) { + zip_set_phase(dev, SCSI_PHASE_STATUS); + /* zip_log("ZIP %i: All done - callback set\n", dev->id); */ + dev->packet_status = ZIP_PHASE_COMPLETE; + dev->callback = 20LL * ZIP_TIME; + zip_set_callback(dev); break; - - case GPCMD_INQUIRY: - zip_set_phase(id, SCSI_PHASE_DATA_IN); - - max_len = cdb[3]; - max_len <<= 8; - max_len |= cdb[4]; + } - zip_buf_alloc(id, 65536); + max_len = dev->sector_len; + dev->requested_blocks = max_len; /* If we're writing all blocks in one go for DMA, why not also for PIO, it should NOT + matter anyway, this step should be identical and only the way the read dat is + transferred to the host should be different. */ - if (cdb[1] & 1) { - preamble_len = 4; - size_idx = 3; - - zipbufferb[idx++] = 05; - zipbufferb[idx++] = cdb[2]; - zipbufferb[idx++] = 0; + dev->packet_len = max_len * alloc_length; + zip_buf_alloc(dev, dev->packet_len); - idx++; + dev->requested_blocks = max_len; + dev->packet_len = max_len << 9; - switch (cdb[2]) { - case 0x00: - zipbufferb[idx++] = 0x00; - zipbufferb[idx++] = 0x83; - break; - case 0x83: - if (idx + 24 > max_len) { - zip_data_phase_error(id); - zip_buf_free(id); - return; - } + zip_set_buf_len(dev, BufLen, (int32_t *)&dev->packet_len); - zipbufferb[idx++] = 0x02; - zipbufferb[idx++] = 0x00; - zipbufferb[idx++] = 0x00; - zipbufferb[idx++] = 20; - ide_padstr8(zipbufferb + idx, 20, "53R141"); /* Serial */ - idx += 20; + zip_data_command_finish(dev, dev->packet_len, 512, dev->packet_len, 1); - if (idx + 72 > cdb[4]) - goto atapi_out; - zipbufferb[idx++] = 0x02; - zipbufferb[idx++] = 0x01; - zipbufferb[idx++] = 0x00; - zipbufferb[idx++] = 68; - ide_padstr8(zipbufferb + idx, 8, "IOMEGA "); /* Vendor */ - idx += 8; - if (zip_drives[id].is_250) - ide_padstr8(zipbufferb + idx, 40, "ZIP 250 "); /* Product */ - else - ide_padstr8(zipbufferb + idx, 40, "ZIP 100 "); /* Product */ - idx += 40; - ide_padstr8(zipbufferb + idx, 20, "53R141"); /* Product */ - idx += 20; - break; - default: -#ifdef ENABLE_ZIP_LOG - zip_log("INQUIRY: Invalid page: %02X\n", cdb[2]); -#endif - zip_invalid_field(id); - zip_buf_free(id); + dev->all_blocks_total = dev->block_total; + if (dev->packet_status != ZIP_PHASE_COMPLETE) + ui_sb_icon_update(SB_ZIP | dev->id, 1); + else + ui_sb_icon_update(SB_ZIP | dev->id, 0); + return; + + case GPCMD_WRITE_SAME_10: + zip_set_phase(dev, SCSI_PHASE_DATA_OUT); + alloc_length = 512; + + if ((cdb[1] & 6) == 6) { + zip_invalid_field(dev); + return; + } + + if ((dev->drv->bus_type == ZIP_BUS_SCSI) && dev->drv->read_only) { + zip_write_protected(dev); + return; + } + + dev->sector_len = (cdb[7] << 8) | cdb[8]; + dev->sector_pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; + + if (dev->drv->is_250) { + if ((dev->sector_pos >= dev->drv->medium_size) || + ((dev->sector_pos + dev->sector_len - 1) >= dev->drv->medium_size)) { + zip_lba_out_of_range(dev); + return; + } + } else { + if ((dev->sector_pos >= ZIP_SECTORS) || + ((dev->sector_pos + dev->sector_len - 1) >= ZIP_SECTORS)) { + zip_lba_out_of_range(dev); + return; + } + } + + if (!dev->sector_len) { + zip_set_phase(dev, SCSI_PHASE_STATUS); + /* zip_log("ZIP %i: All done - callback set\n", dev->id); */ + dev->packet_status = ZIP_PHASE_COMPLETE; + dev->callback = 20LL * ZIP_TIME; + zip_set_callback(dev); + break; + } + + max_len = dev->sector_len; + dev->requested_blocks = max_len; /* If we're writing all blocks in one go for DMA, why not also for PIO, it should NOT + matter anyway, this step should be identical and only the way the read dat is + transferred to the host should be different. */ + + dev->packet_len = max_len * alloc_length; + zip_buf_alloc(dev, dev->packet_len); + + dev->requested_blocks = max_len; + dev->packet_len = alloc_length; + + zip_set_buf_len(dev, BufLen, (int32_t *)&dev->packet_len); + + zip_data_command_finish(dev, dev->packet_len, 512, dev->packet_len, 1); + + dev->all_blocks_total = dev->block_total; + if (dev->packet_status != ZIP_PHASE_COMPLETE) + ui_sb_icon_update(SB_ZIP | dev->id, 1); + else + ui_sb_icon_update(SB_ZIP | dev->id, 0); + return; + + case GPCMD_MODE_SENSE_6: + case GPCMD_MODE_SENSE_10: + zip_set_phase(dev, SCSI_PHASE_DATA_IN); + + if (dev->drv->bus_type == ZIP_BUS_SCSI) + block_desc = ((cdb[1] >> 3) & 1) ? 0 : 1; + else + block_desc = 0; + + if (cdb[0] == GPCMD_MODE_SENSE_6) { + len = cdb[4]; + zip_buf_alloc(dev, 256); + } else { + len = (cdb[8] | (cdb[7] << 8)); + zip_buf_alloc(dev, 65536); + } + + dev->current_page_code = cdb[2] & 0x3F; + zip_log("Mode sense page: %02X\n", dev->current_page_code); + + if (!(zip_mode_sense_page_flags & (1LL << dev->current_page_code))) { + zip_invalid_field(dev); + zip_buf_free(dev); + return; + } + + memset(zipbufferb, 0, len); + alloc_length = len; + + if (cdb[0] == GPCMD_MODE_SENSE_6) { + len = zip_mode_sense(dev, zipbufferb, 4, cdb[2], block_desc); + len = MIN(len, alloc_length); + zipbufferb[0] = len - 1; + zipbufferb[1] = 0; + if (block_desc) + zipbufferb[3] = 8; + } else { + len = zip_mode_sense(dev, zipbufferb, 8, cdb[2], block_desc); + len = MIN(len, alloc_length); + zipbufferb[0]=(len - 2) >> 8; + zipbufferb[1]=(len - 2) & 255; + zipbufferb[2] = 0; + if (block_desc) { + zipbufferb[6] = 0; + zipbufferb[7] = 8; + } + } + + zip_set_buf_len(dev, BufLen, &len); + + zip_log("ZIP %i: Reading mode page: %02X...\n", dev->id, cdb[2]); + + zip_data_command_finish(dev, len, len, alloc_length, 0); + return; + + case GPCMD_MODE_SELECT_6: + case GPCMD_MODE_SELECT_10: + zip_set_phase(dev, SCSI_PHASE_DATA_OUT); + + if (cdb[0] == GPCMD_MODE_SELECT_6) { + len = cdb[4]; + zip_buf_alloc(dev, 256); + } else { + len = (cdb[7] << 8) | cdb[8]; + zip_buf_alloc(dev, 65536); + } + + zip_set_buf_len(dev, BufLen, &len); + + dev->total_length = len; + dev->do_page_save = cdb[1] & 1; + + dev->current_page_pos = 0; + + zip_data_command_finish(dev, len, len, len, 1); + return; + + case GPCMD_START_STOP_UNIT: + zip_set_phase(dev, SCSI_PHASE_STATUS); + + switch(cdb[4] & 3) { + case 0: /* Stop the disc. */ + ui_zip_eject(dev->id); /* The Iomega Windows 9x drivers require this. */ + break; + case 1: /* Start the disc and read the TOC. */ + break; + case 2: /* Eject the disc if possible. */ + /* ui_zip_eject(dev->id); */ + break; + case 3: /* Load the disc (close tray). */ + ui_zip_reload(dev->id); + break; + } + + zip_command_complete(dev); + break; + + case GPCMD_INQUIRY: + zip_set_phase(dev, SCSI_PHASE_DATA_IN); + + max_len = cdb[3]; + max_len <<= 8; + max_len |= cdb[4]; + + zip_buf_alloc(dev, 65536); + + if (cdb[1] & 1) { + preamble_len = 4; + size_idx = 3; + + zipbufferb[idx++] = 05; + zipbufferb[idx++] = cdb[2]; + zipbufferb[idx++] = 0; + + idx++; + + switch (cdb[2]) { + case 0x00: + zipbufferb[idx++] = 0x00; + zipbufferb[idx++] = 0x83; + break; + case 0x83: + if (idx + 24 > max_len) { + zip_data_phase_error(dev); + zip_buf_free(dev); return; - } - } else { - preamble_len = 5; - size_idx = 4; + } - memset(zipbufferb, 0, 8); - if (cdb[1] & 0xe0) - zipbufferb[0] = 0x60; /*No physical device on this LUN*/ - else - zipbufferb[0] = 0x00; /*Hard disk*/ - zipbufferb[1] = 0x80; /*Removable*/ - if (zip_drives[id].is_250) { - zipbufferb[2] = (zip_drives[id].bus_type == ZIP_BUS_SCSI) ? 0x02 : 0x00; /*SCSI-2 compliant*/ - zipbufferb[3] = (zip_drives[id].bus_type == ZIP_BUS_SCSI) ? 0x02 : 0x21; - } else { - zipbufferb[2] = (zip_drives[id].bus_type == ZIP_BUS_SCSI) ? 0x02 : 0x00; /*SCSI-2 compliant*/ - zipbufferb[3] = (zip_drives[id].bus_type == ZIP_BUS_SCSI) ? 0x02 : 0x21; - } - zipbufferb[4] = 31; - if (zip_drives[id].bus_type == ZIP_BUS_SCSI) { - zipbufferb[6] = 1; /* 16-bit transfers supported */ - zipbufferb[7] = 0x20; /* Wide bus supported */ - } + zipbufferb[idx++] = 0x02; + zipbufferb[idx++] = 0x00; + zipbufferb[idx++] = 0x00; + zipbufferb[idx++] = 20; + ide_padstr8(zipbufferb + idx, 20, "53R141"); /* Serial */ + idx += 20; - ide_padstr8(zipbufferb + 8, 8, "IOMEGA "); /* Vendor */ - if (zip_drives[id].is_250) { - ide_padstr8(zipbufferb + 16, 16, "ZIP 250 "); /* Product */ - ide_padstr8(zipbufferb + 32, 4, "42.S"); /* Revision */ - if (max_len >= 44) - ide_padstr8(zipbufferb + 36, 8, "08/08/01"); /* Date? */ - if (max_len >= 122) - ide_padstr8(zipbufferb + 96, 26, "(c) Copyright IOMEGA 2000 "); /* Copyright string */ - - } else { - ide_padstr8(zipbufferb + 16, 16, "ZIP 100 "); /* Product */ - ide_padstr8(zipbufferb + 32, 4, "E.08"); /* Revision */ - } - idx = 36; - - if (max_len == 96) { - zipbufferb[4] = 91; - idx = 96; - } else if (max_len == 128) { - zipbufferb[4] = 0x75; - idx = 128; - } + if (idx + 72 > cdb[4]) + goto atapi_out; + zipbufferb[idx++] = 0x02; + zipbufferb[idx++] = 0x01; + zipbufferb[idx++] = 0x00; + zipbufferb[idx++] = 68; + ide_padstr8(zipbufferb + idx, 8, "IOMEGA "); /* Vendor */ + idx += 8; + if (dev->drv->is_250) + ide_padstr8(zipbufferb + idx, 40, "ZIP 250 "); /* Product */ + else + ide_padstr8(zipbufferb + idx, 40, "ZIP 100 "); /* Product */ + idx += 40; + ide_padstr8(zipbufferb + idx, 20, "53R141"); /* Product */ + idx += 20; + break; + default: + zip_log("INQUIRY: Invalid page: %02X\n", cdb[2]); + zip_invalid_field(dev); + zip_buf_free(dev); + return; } + } else { + preamble_len = 5; + size_idx = 4; + + memset(zipbufferb, 0, 8); + if (cdb[1] & 0xe0) + zipbufferb[0] = 0x60; /*No physical device on this LUN*/ + else + zipbufferb[0] = 0x00; /*Hard disk*/ + zipbufferb[1] = 0x80; /*Removable*/ + if (dev->drv->is_250) { + zipbufferb[2] = (dev->drv->bus_type == ZIP_BUS_SCSI) ? 0x02 : 0x00; /*SCSI-2 compliant*/ + zipbufferb[3] = (dev->drv->bus_type == ZIP_BUS_SCSI) ? 0x02 : 0x21; + } else { + zipbufferb[2] = (dev->drv->bus_type == ZIP_BUS_SCSI) ? 0x02 : 0x00; /*SCSI-2 compliant*/ + zipbufferb[3] = (dev->drv->bus_type == ZIP_BUS_SCSI) ? 0x02 : 0x21; + } + zipbufferb[4] = 31; + if (dev->drv->bus_type == ZIP_BUS_SCSI) { + zipbufferb[6] = 1; /* 16-bit transfers supported */ + zipbufferb[7] = 0x20; /* Wide bus supported */ + } + + ide_padstr8(zipbufferb + 8, 8, "IOMEGA "); /* Vendor */ + if (dev->drv->is_250) { + ide_padstr8(zipbufferb + 16, 16, "ZIP 250 "); /* Product */ + ide_padstr8(zipbufferb + 32, 4, "42.S"); /* Revision */ + if (max_len >= 44) + ide_padstr8(zipbufferb + 36, 8, "08/08/01"); /* Date? */ + if (max_len >= 122) + ide_padstr8(zipbufferb + 96, 26, "(c) Copyright IOMEGA 2000 "); /* Copyright string */ + } else { + ide_padstr8(zipbufferb + 16, 16, "ZIP 100 "); /* Product */ + ide_padstr8(zipbufferb + 32, 4, "E.08"); /* Revision */ + } + idx = 36; + + if (max_len == 96) { + zipbufferb[4] = 91; + idx = 96; + } else if (max_len == 128) { + zipbufferb[4] = 0x75; + idx = 128; + } + } atapi_out: - zipbufferb[size_idx] = idx - preamble_len; - len=idx; + zipbufferb[size_idx] = idx - preamble_len; + len = idx; - len = MIN(len, max_len); - zip_set_buf_len(id, BufLen, &len); + len = MIN(len, max_len); + zip_set_buf_len(dev, BufLen, &len); - zip_data_command_finish(id, len, len, max_len, 0); - break; + zip_data_command_finish(dev, len, len, max_len, 0); + break; - case GPCMD_PREVENT_REMOVAL: - zip_set_phase(id, SCSI_PHASE_STATUS); - zip_command_complete(id); - break; + case GPCMD_PREVENT_REMOVAL: + zip_set_phase(dev, SCSI_PHASE_STATUS); + zip_command_complete(dev); + break; - case GPCMD_SEEK_6: - case GPCMD_SEEK_10: - zip_set_phase(id, SCSI_PHASE_STATUS); - - switch(cdb[0]) { - case GPCMD_SEEK_6: - pos = (cdb[2] << 8) | cdb[3]; - break; - case GPCMD_SEEK_10: - pos = (cdb[2] << 24) | (cdb[3]<<16) | (cdb[4]<<8) | cdb[5]; - break; - } - zip_seek(id, pos); - zip_command_complete(id); - break; + case GPCMD_SEEK_6: + case GPCMD_SEEK_10: + zip_set_phase(dev, SCSI_PHASE_STATUS); - case GPCMD_READ_CDROM_CAPACITY: - zip_set_phase(id, SCSI_PHASE_DATA_IN); + switch(cdb[0]) { + case GPCMD_SEEK_6: + pos = (cdb[2] << 8) | cdb[3]; + break; + case GPCMD_SEEK_10: + pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; + break; + } + zip_seek(dev, pos); + zip_command_complete(dev); + break; - zip_buf_alloc(id, 8); + case GPCMD_READ_CDROM_CAPACITY: + zip_set_phase(dev, SCSI_PHASE_DATA_IN); - if (zip_read_capacity(id, zip[id].current_cdb, zipbufferb, &len) == 0) { - zip_buf_free(id); - return; - } + zip_buf_alloc(dev, 8); - zip_set_buf_len(id, BufLen, &len); + if (zip_read_capacity(dev, dev->current_cdb, zipbufferb, &ulen) == 0) { + zip_buf_free(dev); + return; + } + len = (int32_t)ulen; - zip_data_command_finish(id, len, len, len, 0); - break; + zip_set_buf_len(dev, BufLen, &len); - case GPCMD_IOMEGA_EJECT: - zip_set_phase(id, SCSI_PHASE_STATUS); - zip_eject(id); - zip_command_complete(id); - break; + zip_data_command_finish(dev, len, len, len, 0); + break; - case GPCMD_READ_FORMAT_CAPACITIES: - len = (cdb[7] << 8) | cdb[8]; + case GPCMD_IOMEGA_EJECT: + zip_set_phase(dev, SCSI_PHASE_STATUS); + ui_zip_eject(dev->id); + zip_command_complete(dev); + break; - zip_buf_alloc(id, len); - memset(zipbufferb, 0, len); + case GPCMD_READ_FORMAT_CAPACITIES: + len = (cdb[7] << 8) | cdb[8]; - pos = 0; + zip_buf_alloc(dev, len); + memset(zipbufferb, 0, len); - /* List header */ - zipbufferb[pos++] = 0; - zipbufferb[pos++] = 0; - zipbufferb[pos++] = 0; - if (zip_drives[id].f != NULL) - zipbufferb[pos++] = 16; - else - zipbufferb[pos++] = 8; + pos = 0; - /* Current/Maximum capacity header */ - if (zip_drives[id].is_250) { - if (zip_drives[id].f != NULL) { - zipbufferb[pos++] = (zip_drives[id].medium_size >> 24) & 0xff; - zipbufferb[pos++] = (zip_drives[id].medium_size >> 16) & 0xff; - zipbufferb[pos++] = (zip_drives[id].medium_size >> 8) & 0xff; - zipbufferb[pos++] = zip_drives[id].medium_size & 0xff; - zipbufferb[pos++] = 2; /* Current medium capacity */ - } else { - zipbufferb[pos++] = (ZIP_250_SECTORS >> 24) & 0xff; - zipbufferb[pos++] = (ZIP_250_SECTORS >> 16) & 0xff; - zipbufferb[pos++] = (ZIP_250_SECTORS >> 8) & 0xff; - zipbufferb[pos++] = ZIP_250_SECTORS & 0xff; - zipbufferb[pos++] = 3; /* Maximum medium capacity */ - } + /* List header */ + zipbufferb[pos++] = 0; + zipbufferb[pos++] = 0; + zipbufferb[pos++] = 0; + if (dev->drv->f != NULL) + zipbufferb[pos++] = 16; + else + zipbufferb[pos++] = 8; + + /* Current/Maximum capacity header */ + if (dev->drv->is_250) { + if (dev->drv->f != NULL) { + zipbufferb[pos++] = (dev->drv->medium_size >> 24) & 0xff; + zipbufferb[pos++] = (dev->drv->medium_size >> 16) & 0xff; + zipbufferb[pos++] = (dev->drv->medium_size >> 8) & 0xff; + zipbufferb[pos++] = dev->drv->medium_size & 0xff; + zipbufferb[pos++] = 2; /* Current medium capacity */ } else { - zipbufferb[pos++] = (ZIP_SECTORS >> 24) & 0xff; - zipbufferb[pos++] = (ZIP_SECTORS >> 16) & 0xff; - zipbufferb[pos++] = (ZIP_SECTORS >> 8) & 0xff; - zipbufferb[pos++] = ZIP_SECTORS & 0xff; - if (zip_drives[id].f != NULL) - zipbufferb[pos++] = 2; - else - zipbufferb[pos++] = 3; + zipbufferb[pos++] = (ZIP_250_SECTORS >> 24) & 0xff; + zipbufferb[pos++] = (ZIP_250_SECTORS >> 16) & 0xff; + zipbufferb[pos++] = (ZIP_250_SECTORS >> 8) & 0xff; + zipbufferb[pos++] = ZIP_250_SECTORS & 0xff; + zipbufferb[pos++] = 3; /* Maximum medium capacity */ } + } else { + zipbufferb[pos++] = (ZIP_SECTORS >> 24) & 0xff; + zipbufferb[pos++] = (ZIP_SECTORS >> 16) & 0xff; + zipbufferb[pos++] = (ZIP_SECTORS >> 8) & 0xff; + zipbufferb[pos++] = ZIP_SECTORS & 0xff; + if (dev->drv->f != NULL) + zipbufferb[pos++] = 2; + else + zipbufferb[pos++] = 3; + } + zipbufferb[pos++] = 512 >> 16; + zipbufferb[pos++] = 512 >> 8; + zipbufferb[pos++] = 512 & 0xff; + + if (dev->drv->f != NULL) { + /* Formattable capacity descriptor */ + zipbufferb[pos++] = (dev->drv->medium_size >> 24) & 0xff; + zipbufferb[pos++] = (dev->drv->medium_size >> 16) & 0xff; + zipbufferb[pos++] = (dev->drv->medium_size >> 8) & 0xff; + zipbufferb[pos++] = dev->drv->medium_size & 0xff; + zipbufferb[pos++] = 0; zipbufferb[pos++] = 512 >> 16; zipbufferb[pos++] = 512 >> 8; zipbufferb[pos++] = 512 & 0xff; + } - if (zip_drives[id].f != NULL) { - /* Formattable capacity descriptor */ - zipbufferb[pos++] = (zip_drives[id].medium_size >> 24) & 0xff; - zipbufferb[pos++] = (zip_drives[id].medium_size >> 16) & 0xff; - zipbufferb[pos++] = (zip_drives[id].medium_size >> 8) & 0xff; - zipbufferb[pos++] = zip_drives[id].medium_size & 0xff; - zipbufferb[pos++] = 0; - zipbufferb[pos++] = 512 >> 16; - zipbufferb[pos++] = 512 >> 8; - zipbufferb[pos++] = 512 & 0xff; - } + zip_set_buf_len(dev, BufLen, &len); - zip_set_buf_len(id, BufLen, &len); + zip_data_command_finish(dev, len, len, len, 0); + break; - zip_data_command_finish(id, len, len, len, 0); - break; + default: + zip_illegal_opcode(dev); + break; + } - default: - zip_illegal_opcode(id); - break; - } + /* zip_log("ZIP %i: Phase: %02X, request length: %i\n", dev->phase, dev->request_length); */ -#ifdef ENABLE_ZIP_LOG - /* zip_log("ZIP %i: Phase: %02X, request length: %i\n", zip[id].phase, zip[id].request_length); */ -#endif - - if (zip_atapi_phase_to_scsi(id) == SCSI_PHASE_STATUS) - zip_buf_free(id); + if (zip_atapi_phase_to_scsi(dev) == SCSI_PHASE_STATUS) + zip_buf_free(dev); } + /* The command second phase function, needed for Mode Select. */ -uint8_t zip_phase_data_out(uint8_t id) +static uint8_t +zip_phase_data_out(zip_t *dev) { - uint16_t block_desc_len; - uint16_t pos; + uint16_t block_desc_len; + uint16_t pos; + uint8_t error = 0; + uint8_t page, page_len; + uint32_t i = 0; + uint8_t hdr_len, val, old_val, ch; + uint32_t last_to_write = 0; + uint32_t c, h, s; + int len = 0; - uint8_t error = 0; - uint8_t page, page_len; - - uint32_t i = 0; - - uint8_t hdr_len, val, old_val, ch; - - uint32_t last_to_write = 0, len = 0; - uint32_t c, h, s; - - switch(zip[id].current_cdb[0]) { - case GPCMD_VERIFY_6: - case GPCMD_VERIFY_10: - case GPCMD_VERIFY_12: - break; - case GPCMD_WRITE_6: - case GPCMD_WRITE_10: - case GPCMD_WRITE_AND_VERIFY_10: - case GPCMD_WRITE_12: - case GPCMD_WRITE_AND_VERIFY_12: - if (zip[id].requested_blocks > 0) - zip_blocks(id, &len, 1, 1); - break; - case GPCMD_WRITE_SAME_10: - if (!zip[id].current_cdb[7] && !zip[id].current_cdb[8]) { - if (zip_drives[id].is_250) - last_to_write = (zip_drives[id].medium_size - 1); - else - last_to_write = (ZIP_SECTORS - 1); - } else - last_to_write = zip[id].sector_pos + zip[id].sector_len - 1; - - for (i = zip[id].sector_pos; i <= last_to_write; i++) { - if (zip[id].current_cdb[1] & 2) { - zipbufferb[0] = (i >> 24) & 0xff; - zipbufferb[1] = (i >> 16) & 0xff; - zipbufferb[2] = (i >> 8) & 0xff; - zipbufferb[3] = i & 0xff; - } else if (zip[id].current_cdb[1] & 4) { - /* CHS are 96,1,2048 (ZIP 100) and 239,1,2048 (ZIP 250) */ - s = (i % 2048); - h = ((i - s) / 2048) % 1; - c = ((i - s) / 2048) / 1; - zipbufferb[0] = (c >> 16) & 0xff; - zipbufferb[1] = (c >> 8) & 0xff; - zipbufferb[2] = c & 0xff; - zipbufferb[3] = h & 0xff; - zipbufferb[4] = (s >> 24) & 0xff; - zipbufferb[5] = (s >> 16) & 0xff; - zipbufferb[6] = (s >> 8) & 0xff; - zipbufferb[7] = s & 0xff; - } - fseek(zip_drives[id].f, zip_drives[id].base + (i << 9), SEEK_SET); - fwrite(zipbufferb, 1, 512, zip_drives[id].f); - } - break; - case GPCMD_MODE_SELECT_6: - case GPCMD_MODE_SELECT_10: - if (zip[id].current_cdb[0] == GPCMD_MODE_SELECT_10) - hdr_len = 8; + switch(dev->current_cdb[0]) { + case GPCMD_VERIFY_6: + case GPCMD_VERIFY_10: + case GPCMD_VERIFY_12: + break; + case GPCMD_WRITE_6: + case GPCMD_WRITE_10: + case GPCMD_WRITE_AND_VERIFY_10: + case GPCMD_WRITE_12: + case GPCMD_WRITE_AND_VERIFY_12: + if (dev->requested_blocks > 0) + zip_blocks(dev, &len, 1, 1); + break; + case GPCMD_WRITE_SAME_10: + if (!dev->current_cdb[7] && !dev->current_cdb[8]) { + if (dev->drv->is_250) + last_to_write = (dev->drv->medium_size - 1); else - hdr_len = 4; + last_to_write = (ZIP_SECTORS - 1); + } else + last_to_write = dev->sector_pos + dev->sector_len - 1; - if (zip_drives[id].bus_type == ZIP_BUS_SCSI) { - if (zip[id].current_cdb[0] == GPCMD_MODE_SELECT_6) { - block_desc_len = zipbufferb[2]; - block_desc_len <<= 8; - block_desc_len |= zipbufferb[3]; - } else { - block_desc_len = zipbufferb[6]; - block_desc_len <<= 8; - block_desc_len |= zipbufferb[7]; - } - } else - block_desc_len = 0; + for (i = dev->sector_pos; i <= last_to_write; i++) { + if (dev->current_cdb[1] & 2) { + zipbufferb[0] = (i >> 24) & 0xff; + zipbufferb[1] = (i >> 16) & 0xff; + zipbufferb[2] = (i >> 8) & 0xff; + zipbufferb[3] = i & 0xff; + } else if (dev->current_cdb[1] & 4) { + /* CHS are 96,1,2048 (ZIP 100) and 239,1,2048 (ZIP 250) */ + s = (i % 2048); + h = ((i - s) / 2048) % 1; + c = ((i - s) / 2048) / 1; + zipbufferb[0] = (c >> 16) & 0xff; + zipbufferb[1] = (c >> 8) & 0xff; + zipbufferb[2] = c & 0xff; + zipbufferb[3] = h & 0xff; + zipbufferb[4] = (s >> 24) & 0xff; + zipbufferb[5] = (s >> 16) & 0xff; + zipbufferb[6] = (s >> 8) & 0xff; + zipbufferb[7] = s & 0xff; + } + fseek(dev->drv->f, dev->drv->base + (i << 9), SEEK_SET); + fwrite(zipbufferb, 1, 512, dev->drv->f); + } + break; + case GPCMD_MODE_SELECT_6: + case GPCMD_MODE_SELECT_10: + if (dev->current_cdb[0] == GPCMD_MODE_SELECT_10) + hdr_len = 8; + else + hdr_len = 4; - pos = hdr_len + block_desc_len; + if (dev->drv->bus_type == ZIP_BUS_SCSI) { + if (dev->current_cdb[0] == GPCMD_MODE_SELECT_6) { + block_desc_len = zipbufferb[2]; + block_desc_len <<= 8; + block_desc_len |= zipbufferb[3]; + } else { + block_desc_len = zipbufferb[6]; + block_desc_len <<= 8; + block_desc_len |= zipbufferb[7]; + } + } else + block_desc_len = 0; - while(1) { - page = zipbufferb[pos] & 0x3F; - page_len = zipbufferb[pos + 1]; + pos = hdr_len + block_desc_len; - pos += 2; + while(1) { + page = zipbufferb[pos] & 0x3F; + page_len = zipbufferb[pos + 1]; - if (!(zip_mode_sense_page_flags & (1LL << ((uint64_t) page)))) - error |= 1; - else { - for (i = 0; i < page_len; i++) { - ch = zip_mode_sense_pages_changeable.pages[page][i + 2]; - val = zipbufferb[pos + i]; - old_val = zip_mode_sense_pages_saved[id].pages[page][i + 2]; - if (val != old_val) { - if (ch) - zip_mode_sense_pages_saved[id].pages[page][i + 2] = val; - else - error |= 1; - } + pos += 2; + + if (!(zip_mode_sense_page_flags & (1LL << ((uint64_t) page)))) + error |= 1; + else { + for (i = 0; i < page_len; i++) { + ch = zip_mode_sense_pages_changeable.pages[page][i + 2]; + val = zipbufferb[pos + i]; + old_val = dev->ms_pages_saved.pages[page][i + 2]; + if (val != old_val) { + if (ch) + dev->ms_pages_saved.pages[page][i + 2] = val; + else + error |= 1; } } - - pos += page_len; - - if (zip_drives[id].bus_type == ZIP_BUS_SCSI) - val = zip_mode_sense_pages_default_scsi.pages[page][0] & 0x80; - else - val = zip_mode_sense_pages_default.pages[page][0] & 0x80; - if (zip[id].do_page_save && val) - zip_mode_sense_save(id); - - if (pos >= zip[id].total_length) - break; } - if (error) { - zip_invalid_field_pl(id); - return 0; - } - break; - } + pos += page_len; - return 1; + if (dev->drv->bus_type == ZIP_BUS_SCSI) + val = zip_mode_sense_pages_default_scsi.pages[page][0] & 0x80; + else + val = zip_mode_sense_pages_default.pages[page][0] & 0x80; + if (dev->do_page_save && val) + zip_mode_sense_save(dev); + + if (pos >= dev->total_length) + break; + } + + if (error) { + zip_invalid_field_pl(dev); + return 0; + } + break; + } + + return 1; } + /* This is the general ATAPI PIO request function. */ -void zip_pio_request(uint8_t id, uint8_t out) +static void +zip_pio_request(zip_t *dev, uint8_t out) { - int old_pos = 0; - int ret = 0; + int ret = 0; - if (zip_drives[id].bus_type < ZIP_BUS_SCSI) { -#ifdef ENABLE_ZIP_LOG - zip_log("ZIP %i: Lowering IDE IRQ\n", id); -#endif - ide_irq_lower(&(ide_drives[zip_drives[id].ide_channel])); - } - - zip[id].status = BUSY_STAT; + if (dev->drv->bus_type == ZIP_BUS_ATAPI) { + zip_log("ZIP %i: Lowering IDE IRQ\n", dev->id); +//FIXME: should be ide_lower_irq(dev->drv->ide_channel) .. --FvK + ide_irq_lower(ide_drives[dev->drv->ide_channel]); + } - if (zip[id].pos >= zip[id].packet_len) { -#ifdef ENABLE_ZIP_LOG - zip_log("ZIP %i: %i bytes %s, command done\n", id, zip[id].pos, out ? "written" : "read"); -#endif + dev->status = BUSY_STAT; - zip[id].pos = zip[id].request_pos = 0; - if (out) { - ret = zip_phase_data_out(id); - /* If ret = 0 (phase 1 error), then we do not do anything else other than - free the buffer, as the phase and callback have already been set by the - error function. */ - if (ret) - zip_command_complete(id); - } else - zip_command_complete(id); - ui_sb_icon_update(SB_ZIP | id, 0); - zip_buf_free(id); - } else { -#ifdef ENABLE_ZIP_LOG - zip_log("ZIP %i: %i bytes %s, %i bytes are still left\n", id, zip[id].pos, out ? "written" : "read", zip[id].packet_len - zip[id].pos); -#endif + if (dev->pos >= dev->packet_len) { + zip_log("ZIP %i: %i bytes %s, command done\n", + dev->id, dev->pos, out ? "written" : "read"); - /* Make sure to keep pos, and reset request_pos to 0. */ - /* Also make sure to not reset total_read. */ - - /* If less than (packet length) bytes are remaining, update packet length - accordingly. */ - if ((zip[id].packet_len - zip[id].pos) < (zip[id].max_transfer_len)) - zip[id].max_transfer_len = zip[id].packet_len - zip[id].pos; - - old_pos = zip[id].pos; - zip[id].packet_status = out ? ZIP_PHASE_DATA_OUT : ZIP_PHASE_DATA_IN; - zip_command_common(id); - zip[id].pos = old_pos; - zip[id].request_pos = 0; - } -} - -void zip_phase_callback(uint8_t id); - -int zip_read_from_ide_dma(uint8_t channel) -{ - uint8_t id = atapi_zip_drives[channel]; - - if (id > ZIP_NUM) - return 0; - - if (ide_bus_master_write) { - if (ide_bus_master_write(channel >> 1, zipbufferb, zip[id].packet_len)) - return 0; - else - return 1; - } - - return 0; -} - -int zip_read_from_scsi_dma(uint8_t scsi_id, uint8_t scsi_lun) -{ - uint8_t id = scsi_zip_drives[scsi_id][scsi_lun]; - int32_t *BufLen = &SCSIDevices[scsi_id][scsi_lun].BufferLength; - - if (id > ZIP_NUM) - return 0; - -#ifdef ENABLE_ZIP_LOG - zip_log("Reading from SCSI DMA: SCSI ID %02X, init length %i\n", scsi_id, *BufLen); -#endif - memcpy(zipbufferb, SCSIDevices[scsi_id][scsi_lun].CmdBuffer, *BufLen); - return 1; -} - -void zip_irq_raise(uint8_t id) -{ - if (zip_drives[id].bus_type < ZIP_BUS_SCSI) - ide_irq_raise(&(ide_drives[zip_drives[id].ide_channel])); -} - -int zip_read_from_dma(uint8_t id) -{ -#ifdef ENABLE_ZIP_LOG - int32_t *BufLen = &SCSIDevices[zip_drives[id].scsi_device_id][zip_drives[id].scsi_device_lun].BufferLength; -#endif - - int ret = 0; - -#ifdef ENABLE_ZIP_LOG - int in_data_length = 0; -#endif - - if (zip_drives[id].bus_type == ZIP_BUS_SCSI) - ret = zip_read_from_scsi_dma(zip_drives[id].scsi_device_id, zip_drives[id].scsi_device_lun); - else - ret = zip_read_from_ide_dma(zip_drives[id].ide_channel); - - if (!ret) - return 0; - - if (zip_drives[id].bus_type == ZIP_BUS_SCSI) { -#ifdef ENABLE_ZIP_LOG - in_data_length = *BufLen; - zip_log("ZIP %i: SCSI Input data length: %i\n", id, in_data_length); -#endif - } else { -#ifdef ENABLE_ZIP_LOG - in_data_length = zip[id].max_transfer_len; - zip_log("ZIP %i: ATAPI Input data length: %i\n", id, in_data_length); -#endif - } - - ret = zip_phase_data_out(id); - - if (ret || (zip_drives[id].bus_type == ZIP_BUS_SCSI)) { - zip_buf_free(id); - zip[id].packet_status = ZIP_PHASE_COMPLETE; - zip[id].status = READY_STAT; - zip[id].phase = 3; - ui_sb_icon_update(SB_ZIP | id, 0); - zip_irq_raise(id); + dev->pos = dev->request_pos = 0; + if (out) { + ret = zip_phase_data_out(dev); + /* If ret = 0 (phase 1 error), then we do not do anything else other than + free the buffer, as the phase and callback have already been set by the + error function. */ if (ret) - return 1; - else - return 0; - } - - return 0; -} - -int zip_write_to_ide_dma(uint8_t channel) -{ - uint8_t id = atapi_zip_drives[channel]; - - if (id > ZIP_NUM) { -#ifdef ENABLE_ZIP_LOG - zip_log("ZIP %i: Drive not found\n", id); -#endif - return 0; - } - - if (ide_bus_master_read) { - if (ide_bus_master_read(channel >> 1, zipbufferb, zip[id].packet_len)) - return 0; - else - return 1; - } - - return 0; -} - -int zip_write_to_scsi_dma(uint8_t scsi_id, uint8_t scsi_lun) -{ - uint8_t id = scsi_zip_drives[scsi_id][scsi_lun]; - int32_t *BufLen = &SCSIDevices[scsi_id][scsi_lun].BufferLength; - - if (id > ZIP_NUM) - return 0; - -#ifdef ENABLE_ZIP_LOG - zip_log("Writing to SCSI DMA: SCSI ID %02X, init length %i\n", scsi_id, *BufLen); -#endif - memcpy(SCSIDevices[scsi_id][scsi_lun].CmdBuffer, zipbufferb, *BufLen); -#ifdef ENABLE_ZIP_LOG - zip_log("ZIP %i: Data from CD buffer: %02X %02X %02X %02X %02X %02X %02X %02X\n", id, zipbufferb[0], zipbufferb[1], zipbufferb[2], zipbufferb[3], zipbufferb[4], zipbufferb[5], zipbufferb[6], zipbufferb[7]); - zip_log("ZIP %i: Data from SCSI DMA : %02X %02X %02X %02X %02X %02X %02X %02X\n", id, SCSIDevices[scsi_id][scsi_lun].CmdBuffer[0], SCSIDevices[scsi_id][scsi_lun].CmdBuffer[1], SCSIDevices[scsi_id][scsi_lun].CmdBuffer[2], SCSIDevices[scsi_id][scsi_lun].CmdBuffer[3], SCSIDevices[scsi_id][scsi_lun].CmdBuffer[4], SCSIDevices[scsi_id][scsi_lun].CmdBuffer[5], SCSIDevices[scsi_id][scsi_lun].CmdBuffer[6], SCSIDevices[scsi_id][scsi_lun].CmdBuffer[7]); -#endif - return 1; -} - -int zip_write_to_dma(uint8_t id) -{ - int ret = 0; - - if (zip_drives[id].bus_type == ZIP_BUS_SCSI) { -#ifdef ENABLE_ZIP_LOG - zip_log("Write to SCSI DMA: (%02X:%02X)\n", zip_drives[id].scsi_device_id, zip_drives[id].scsi_device_lun); -#endif - ret = zip_write_to_scsi_dma(zip_drives[id].scsi_device_id, zip_drives[id].scsi_device_lun); + zip_command_complete(dev); } else - ret = zip_write_to_ide_dma(zip_drives[id].ide_channel); + zip_command_complete(dev); + zip_buf_free(dev); + } else { + zip_log("ZIP %i: %i bytes %s, %i bytes are still left\n", + dev->id, dev->pos, out ? "written" : "read", dev->packet_len - dev->pos); - if (ret || (zip_drives[id].bus_type == ZIP_BUS_SCSI)) { - zip_buf_free(id); - zip[id].packet_status = ZIP_PHASE_COMPLETE; - zip[id].status = READY_STAT; - zip[id].phase = 3; - ui_sb_icon_update(SB_ZIP | id, 0); - zip_irq_raise(id); - if (ret) - return 1; - else - return 0; - } + /* If less than (packet length) bytes are remaining, update packet length + accordingly. */ + if ((dev->packet_len - dev->pos) < (dev->max_transfer_len)) + dev->max_transfer_len = dev->packet_len - dev->pos; + zip_log("ZIP %i: Packet length %i, request length %i\n", + dev->id, dev->packet_len, dev->max_transfer_len); + dev->packet_status = out ? ZIP_PHASE_DATA_OUT : ZIP_PHASE_DATA_IN; + dev->status = BUSY_STAT; + dev->phase = 1; + zip_phase_callback(dev); + dev->callback = 0LL; + zip_set_callback(dev); + + dev->request_pos = 0; + } +} + + +static int +zip_read_from_ide_dma(uint8_t channel) +{ + zip_t *dev; + uint8_t id; + int ret; + + id = atapi_zip_drives[channel]; + if (id > ZIP_NUM) + return 0; + + dev = zip[id]; + + if (ide_bus_master_write) { + ret = ide_bus_master_write(channel >> 1, + zipbufferb, dev->packet_len, + ide_bus_master_priv[channel >> 1]); + if (ret == 2) /* DMA not enabled, wait for it to be enabled. */ + return 2; + else if (ret == 1) { /* DMA error. */ + zip_bus_master_error(dev); + return 0; + } else + return 1; + } + + return 0; +} + + +static int +zip_read_from_scsi_dma(uint8_t scsi_id, uint8_t scsi_lun) +{ + int32_t *BufLen = &SCSIDevices[scsi_id][scsi_lun].BufferLength; + zip_t *dev; + uint8_t id; + + id = scsi_zip_drives[scsi_id][scsi_lun]; + if (id > ZIP_NUM) + return 0; + + dev = zip[id]; + + zip_log("Reading from SCSI DMA: SCSI ID %02X, init length %i\n", scsi_id, *BufLen); + memcpy(zipbufferb, SCSIDevices[scsi_id][scsi_lun].CmdBuffer, *BufLen); + + return 1; +} + + +static void +zip_irq_raise(zip_t *dev) +{ + if (dev->drv->bus_type < ZIP_BUS_SCSI) +//FIXME: should be ide_lower_irq(dev->drv->ide_channel) .. --FvK + ide_irq_raise(ide_drives[dev->drv->ide_channel]); +} + + +static int +zip_read_from_dma(zip_t *dev) +{ + int32_t *BufLen = &SCSIDevices[dev->drv->scsi_device_id][dev->drv->scsi_device_lun].BufferLength; + int ret = 0; + + if (dev->drv->bus_type == ZIP_BUS_SCSI) + ret = zip_read_from_scsi_dma(dev->drv->scsi_device_id, dev->drv->scsi_device_lun); + else + ret = zip_read_from_ide_dma(dev->drv->ide_channel); + + if (ret != 1) + return ret; + + if (dev->drv->bus_type == ZIP_BUS_SCSI) + zip_log("ZIP %i: SCSI Input data length: %i\n", dev->id, *BufLen); + else + zip_log("ZIP %i: ATAPI Input data length: %i\n", dev->id, dev->packet_len); + + ret = zip_phase_data_out(dev); + + if (ret) + return 1; + else return 0; } + +static int +zip_write_to_ide_dma(uint8_t channel) +{ + uint8_t id = atapi_zip_drives[channel]; + zip_t *dev; + int ret; + + if (id > ZIP_NUM) { + zip_log("ZIP %i: Drive not found\n", id); + return 0; + } + + dev = zip[id]; + + if (ide_bus_master_read) { + ret = ide_bus_master_read(channel >> 1, + zipbufferb, dev->packet_len, + ide_bus_master_priv[channel >> 1]); + if (ret == 2) /* DMA not enabled, wait for it to be enabled. */ + return 2; + else if (ret == 1) { /* DMA error. */ + zip_bus_master_error(dev); + return 0; + } else + return 1; + } + + return 0; +} + + +static int +zip_write_to_scsi_dma(uint8_t scsi_id, uint8_t scsi_lun) +{ + int32_t *BufLen = &SCSIDevices[scsi_id][scsi_lun].BufferLength; + zip_t *dev; + + uint8_t id = scsi_zip_drives[scsi_id][scsi_lun]; + if (id > ZIP_NUM) + return 0; + + dev = zip[id]; + + memcpy(SCSIDevices[scsi_id][scsi_lun].CmdBuffer, zipbufferb, *BufLen); + zip_log("ZIP %i: Data from CD buffer: %02X %02X %02X %02X %02X %02X %02X %02X\n", id, + zipbufferb[0], zipbufferb[1], zipbufferb[2], zipbufferb[3], zipbufferb[4], zipbufferb[5], + zipbufferb[6], zipbufferb[7]); + zip_log("ZIP %i: Data from SCSI DMA : %02X %02X %02X %02X %02X %02X %02X %02X\n", id, + SCSIDevices[scsi_id][scsi_lun].CmdBuffer[0], SCSIDevices[scsi_id][scsi_lun].CmdBuffer[1], + SCSIDevices[scsi_id][scsi_lun].CmdBuffer[2], SCSIDevices[scsi_id][scsi_lun].CmdBuffer[3], + SCSIDevices[scsi_id][scsi_lun].CmdBuffer[4], SCSIDevices[scsi_id][scsi_lun].CmdBuffer[5], + SCSIDevices[scsi_id][scsi_lun].CmdBuffer[6], SCSIDevices[scsi_id][scsi_lun].CmdBuffer[7]); + + return 1; +} + + +static int +zip_write_to_dma(zip_t *dev) +{ + int32_t *BufLen = &SCSIDevices[dev->drv->scsi_device_id][dev->drv->scsi_device_lun].BufferLength; + int ret = 0; + + if (dev->drv->bus_type == ZIP_BUS_SCSI) { + zip_log("Write to SCSI DMA: (%02X:%02X)\n", dev->drv->scsi_device_id, dev->drv->scsi_device_lun); + ret = zip_write_to_scsi_dma(dev->drv->scsi_device_id, dev->drv->scsi_device_lun); + } else + ret = zip_write_to_ide_dma(dev->drv->ide_channel); + + if (dev->drv->bus_type == ZIP_BUS_SCSI) + zip_log("ZIP %i: SCSI Output data length: %i\n", dev->id, *BufLen); + else + zip_log("ZIP %i: ATAPI Output data length: %i\n", dev->id, dev->packet_len); + + return ret; +} + + /* If the result is 1, issue an IRQ, otherwise not. */ -void zip_phase_callback(uint8_t id) +void +zip_phase_callback(zip_t *dev) { - switch(zip[id].packet_status) { - case ZIP_PHASE_IDLE: -#ifdef ENABLE_ZIP_LOG - zip_log("ZIP %i: ZIP_PHASE_IDLE\n", id); -#endif - zip[id].pos=0; - zip[id].phase = 1; - zip[id].status = READY_STAT | DRQ_STAT | (zip[id].status & ERR_STAT); - return; - case ZIP_PHASE_COMMAND: -#ifdef ENABLE_ZIP_LOG - zip_log("ZIP %i: ZIP_PHASE_COMMAND\n", id); -#endif - zip[id].status = BUSY_STAT | (zip[id].status &ERR_STAT); - memcpy(zip[id].atapi_cdb, zipbufferb, zip[id].cdb_len); - zip_command(id, zip[id].atapi_cdb); - return; - case ZIP_PHASE_COMPLETE: -#ifdef ENABLE_ZIP_LOG - zip_log("ZIP %i: ZIP_PHASE_COMPLETE\n", id); -#endif - zip[id].status = READY_STAT; - zip[id].phase = 3; - zip[id].packet_status = 0xFF; - ui_sb_icon_update(SB_ZIP | id, 0); - zip_irq_raise(id); - return; - case ZIP_PHASE_DATA_OUT: -#ifdef ENABLE_ZIP_LOG - zip_log("ZIP %i: ZIP_PHASE_DATA_OUT\n", id); -#endif - zip[id].status = READY_STAT | DRQ_STAT | (zip[id].status & ERR_STAT); - zip[id].phase = 0; - zip_irq_raise(id); - return; - case ZIP_PHASE_DATA_OUT_DMA: -#ifdef ENABLE_ZIP_LOG - zip_log("ZIP %i: ZIP_PHASE_DATA_OUT_DMA\n", id); -#endif - zip_read_from_dma(id); - return; - case ZIP_PHASE_DATA_IN: -#ifdef ENABLE_ZIP_LOG - zip_log("ZIP %i: ZIP_PHASE_DATA_IN\n", id); -#endif - zip[id].status = READY_STAT | DRQ_STAT | (zip[id].status & ERR_STAT); - zip[id].phase = 2; - zip_irq_raise(id); - return; - case ZIP_PHASE_DATA_IN_DMA: -#ifdef ENABLE_ZIP_LOG - zip_log("ZIP %i: ZIP_PHASE_DATA_IN_DMA\n", id); -#endif - zip_write_to_dma(id); - return; - case ZIP_PHASE_ERROR: -#ifdef ENABLE_ZIP_LOG - zip_log("ZIP %i: ZIP_PHASE_ERROR\n", id); -#endif - zip[id].status = READY_STAT | ERR_STAT; - zip[id].phase = 3; - zip[id].packet_status = 0xFF; - zip_irq_raise(id); - ui_sb_icon_update(SB_ZIP | id, 0); - return; - } + int ret; + + switch(dev->packet_status) { + case ZIP_PHASE_IDLE: + zip_log("ZIP %i: ZIP_PHASE_IDLE\n", dev->id); + dev->pos = 0; + dev->phase = 1; + dev->status = READY_STAT | DRQ_STAT | (dev->status & ERR_STAT); + return; + case ZIP_PHASE_COMMAND: + zip_log("ZIP %i: ZIP_PHASE_COMMAND\n", dev->id); + dev->status = BUSY_STAT | (dev->status & ERR_STAT); + memcpy(dev->atapi_cdb, zipbufferb, 12); + zip_command(dev, dev->atapi_cdb); + return; + case ZIP_PHASE_COMPLETE: + zip_log("ZIP %i: ZIP_PHASE_COMPLETE\n", dev->id); + dev->status = READY_STAT; + dev->phase = 3; + dev->packet_status = 0xFF; + ui_sb_icon_update(SB_ZIP | dev->id, 0); + zip_irq_raise(dev); + return; + case ZIP_PHASE_DATA_OUT: + zip_log("ZIP %i: ZIP_PHASE_DATA_OUT\n", dev->id); + dev->status = READY_STAT | DRQ_STAT | (dev->status & ERR_STAT); + dev->phase = 0; + zip_irq_raise(dev); + return; + case ZIP_PHASE_DATA_OUT_DMA: + zip_log("ZIP %i: ZIP_PHASE_DATA_OUT_DMA\n", dev->id); + ret = zip_read_from_dma(dev); + + if ((ret == 1) || (dev->drv->bus_type == ZIP_BUS_SCSI)) { + zip_log("ZIP %i: DMA data out phase done\n", dev->id); + zip_buf_free(dev); + zip_command_complete(dev); + } else if (ret == 2) { + zip_log("ZIP %i: DMA out not enabled, wait\n", dev->id); + zip_command_bus(dev); + } else { + zip_log("ZIP %i: DMA data out phase failure\n", dev->id); + zip_buf_free(dev); + } + return; + case ZIP_PHASE_DATA_IN: + zip_log("ZIP %i: ZIP_PHASE_DATA_IN\n", dev->id); + dev->status = READY_STAT | DRQ_STAT | (dev->status & ERR_STAT); + dev->phase = 2; + zip_irq_raise(dev); + return; + case ZIP_PHASE_DATA_IN_DMA: + zip_log("ZIP %i: ZIP_PHASE_DATA_IN_DMA\n", dev->id); + ret = zip_write_to_dma(dev); + + if ((ret == 1) || (dev->drv->bus_type == ZIP_BUS_SCSI)) { + zip_log("ZIP %i: DMA data in phase done\n", dev->id); + zip_buf_free(dev); + zip_command_complete(dev); + } else if (ret == 2) { + zip_log("ZIP %i: DMA in not enabled, wait\n", dev->id); + zip_command_bus(dev); + } else { + zip_log("ZIP %i: DMA data in phase failure\n", dev->id); + zip_buf_free(dev); + } + return; + case ZIP_PHASE_ERROR: + zip_log("ZIP %i: ZIP_PHASE_ERROR\n", dev->id); + dev->status = READY_STAT | ERR_STAT; + dev->phase = 3; + dev->packet_status = 0xFF; + zip_irq_raise(dev); + ui_sb_icon_update(SB_ZIP | dev->id, 0); + return; + } } -/* Reimplement as 8-bit due to reimplementation of IDE data read and write. */ -uint32_t zip_read(uint8_t channel, int length) + +uint32_t +zip_read(uint8_t channel, int length) { - uint16_t *zipbufferw; - uint32_t *zipbufferl; + uint8_t id = atapi_zip_drives[channel]; + uint16_t *zipbufferw; + uint32_t *zipbufferl; + uint32_t temp = 0; + zip_t *dev; - uint8_t id = atapi_zip_drives[channel]; + if (id > ZIP_NUM) + return 0; - uint32_t temp = 0; + dev = zip[id]; - if (id > ZIP_NUM) + zipbufferw = (uint16_t *) zipbufferb; + zipbufferl = (uint32_t *) zipbufferb; + + if (!zipbufferb) + return 0; + + /* Make sure we return a 0 and don't attempt to read from the buffer if we're transferring bytes beyond it, + which can happen when issuing media access commands with an allocated length below minimum request length + (which is 1 sector = 512 bytes). */ + switch(length) { + case 1: + temp = (dev->pos < dev->packet_len) ? zipbufferb[dev->pos] : 0; + dev->pos++; + dev->request_pos++; + break; + case 2: + temp = (dev->pos < dev->packet_len) ? zipbufferw[dev->pos >> 1] : 0; + dev->pos += 2; + dev->request_pos += 2; + break; + case 4: + temp = (dev->pos < dev->packet_len) ? zipbufferl[dev->pos >> 2] : 0; + dev->pos += 4; + dev->request_pos += 4; + break; + default: return 0; + } - zipbufferw = (uint16_t *) zipbufferb; - zipbufferl = (uint32_t *) zipbufferb; - - if (!zipbufferb) - return 0; - - /* Make sure we return a 0 and don't attempt to read from the buffer if we're transferring bytes beyond it, - which can happen when issuing media access commands with an allocated length below minimum request length - (which is 1 sector = 512 bytes). */ - switch(length) { - case 1: - temp = (zip[id].pos < zip[id].packet_len) ? zipbufferb[zip[id].pos] : 0; - zip[id].pos++; - zip[id].request_pos++; - break; - case 2: - temp = (zip[id].pos < zip[id].packet_len) ? zipbufferw[zip[id].pos >> 1] : 0; - zip[id].pos += 2; - zip[id].request_pos += 2; - break; - case 4: - temp = (zip[id].pos < zip[id].packet_len) ? zipbufferl[zip[id].pos >> 2] : 0; - zip[id].pos += 4; - zip[id].request_pos += 4; - break; - default: - return 0; - } - - if (zip[id].packet_status == ZIP_PHASE_DATA_IN) { - if ((zip[id].request_pos >= zip[id].max_transfer_len) || (zip[id].pos >= zip[id].packet_len)) { - /* Time for a DRQ. */ -#ifdef ENABLE_ZIP_LOG - // zip_log("ZIP %i: Issuing read callback\n", id); -#endif - zip_pio_request(id, 0); - } -#ifdef ENABLE_ZIP_LOG - // zip_log("ZIP %i: Returning: %02X (buffer position: %i, request position: %i)\n", id, temp, zip[id].pos, zip[id].request_pos); -#endif - return temp; - } else { -#ifdef ENABLE_ZIP_LOG - // zip_log("ZIP %i: Returning zero (buffer position: %i, request position: %i)\n", id, zip[id].pos, zip[id].request_pos); -#endif - return 0; + if (dev->packet_status == ZIP_PHASE_DATA_IN) { + zip_log("ZIP %i: Returning: %04X (buffer position: %05i, request position: %05i)\n", + id, temp, (dev->pos - 2) & 0xffff, (dev->request_pos - 2) & 0xffff); + if ((dev->request_pos >= dev->max_transfer_len) || (dev->pos >= dev->packet_len)) { + /* Time for a DRQ. */ + zip_log("ZIP %i: Issuing read callback\n", id); + zip_pio_request(dev, 0); } + return temp; + } else { + zip_log("ZIP %i: Returning: 0000 (buffer position: %05i, request position: %05i)\n", + id, (dev->pos - 2) & 0xffff, (dev->request_pos - 2) & 0xffff); + return 0; + } } -/* Reimplement as 8-bit due to reimplementation of IDE data read and write. */ -void zip_write(uint8_t channel, uint32_t val, int length) + +void +zip_write(uint8_t channel, uint32_t val, int length) { - uint16_t *zipbufferw; - uint32_t *zipbufferl; + uint8_t id = atapi_zip_drives[channel]; + uint16_t *zipbufferw; + uint32_t *zipbufferl; + zip_t *dev; - uint8_t id = atapi_zip_drives[channel]; + if (id > ZIP_NUM) + return; - if (id > ZIP_NUM) - return; - - if (zip[id].packet_status == ZIP_PHASE_IDLE) { - if (!zipbufferb) - zip_buf_alloc(id, zip[id].cdb_len); - } - - zipbufferw = (uint16_t *) zipbufferb; - zipbufferl = (uint32_t *) zipbufferb; + dev = zip[id]; + if (dev->packet_status == ZIP_PHASE_IDLE) { if (!zipbufferb) - return; + zip_buf_alloc(dev, 12); + } - switch(length) { - case 1: - zipbufferb[zip[id].pos] = val & 0xff; - zip[id].pos++; - zip[id].request_pos++; - break; - case 2: - zipbufferw[zip[id].pos >> 1] = val & 0xffff; - zip[id].pos += 2; - zip[id].request_pos += 2; - break; - case 4: - zipbufferl[zip[id].pos >> 2] = val; - zip[id].pos += 4; - zip[id].request_pos += 4; - break; - default: - return; - } + zipbufferw = (uint16_t *) zipbufferb; + zipbufferl = (uint32_t *) zipbufferb; - if (zip[id].packet_status == ZIP_PHASE_DATA_OUT) { - if ((zip[id].request_pos >= zip[id].max_transfer_len) || (zip[id].pos >= zip[id].packet_len)) { - /* Time for a DRQ. */ - zip_pio_request(id, 1); - } - return; - } else if (zip[id].packet_status == ZIP_PHASE_IDLE) { - if (zip[id].pos >= (uint32_t)zip[id].cdb_len) { - zip[id].pos=0; - zip[id].status = BUSY_STAT; - zip[id].packet_status = ZIP_PHASE_COMMAND; - timer_process(); - zip_phase_callback(id); - timer_update_outstanding(); - } + if (!zipbufferb) + return; + + switch(length) { + case 1: + zipbufferb[dev->pos] = val & 0xff; + dev->pos++; + dev->request_pos++; + break; + case 2: + zipbufferw[dev->pos >> 1] = val & 0xffff; + dev->pos += 2; + dev->request_pos += 2; + break; + case 4: + zipbufferl[dev->pos >> 2] = val; + dev->pos += 4; + dev->request_pos += 4; + break; + default: return; + } + + if (dev->packet_status == ZIP_PHASE_DATA_OUT) { + if ((dev->request_pos >= dev->max_transfer_len) || (dev->pos >= dev->packet_len)) { + /* Time for a DRQ. */ + zip_pio_request(dev, 1); } + return; + } else if (dev->packet_status == ZIP_PHASE_IDLE) { + if (dev->pos >= 12) { + dev->pos = 0; + dev->status = BUSY_STAT; + dev->packet_status = ZIP_PHASE_COMMAND; + timer_process(); + zip_phase_callback(dev); + timer_update_outstanding(); + } + return; + } } @@ -2725,16 +2813,89 @@ zip_hard_reset(void) { int c; - for (c=0; cid = c; + zip[c]->drv = &zip_drives[c]; + zip_init(zip[c]); + + if (wcslen(zip_drives[c].image_path)) + zip_load(zip[c], zip_drives[c].image_path); + + zip_mode_sense_load(zip[c]); + } + } + + zip_build_atapi_map(); +} + + +void +zip_close(void) +{ + zip_t *dev; + int c; + + for (c = 0; c < ZIP_NUM; c++) { + dev = zip[c]; + if (dev) { + zip_disk_close(dev); + free(zip[c]); + zip[c] = NULL; + } } } + + +int +zip_string_to_bus(const char *str) +{ + int ret = ZIP_BUS_DISABLED; + + if (! strcmp(str, "none")) return(ret); + + if (! strcmp(str, "ide") || !strcmp(str, "atapi") +#if 1 + || !strcmp(str, "ide_pio_only") || !strcmp(str, "ide_pio_and_dma") + || !strcmp(str, "atapi_pio_only") || !strcmp(str, "atapi_pio_and_dma") +#endif + ) return(ZIP_BUS_ATAPI); + + if (! strcmp(str, "scsi")) + return(ZIP_BUS_SCSI); + + if (! strcmp(str, "usb")) + ui_msgbox(MBX_ERROR, (wchar_t *)IDS_ERR_NO_USB); + + return(ret); +} + + +const char * +zip_bus_to_string(int bus) +{ + const char *ret = "none"; + + switch (bus) { + case ZIP_BUS_DISABLED: + default: + break; + + case ZIP_BUS_ATAPI: + ret = "atapi"; + break; + + case ZIP_BUS_SCSI: + ret = "scsi"; + break; + } + + return(ret); +} diff --git a/src/devices/disk/zip.h b/src/devices/disk/zip.h index 0cf7a92..9475182 100644 --- a/src/devices/disk/zip.h +++ b/src/devices/disk/zip.h @@ -9,7 +9,7 @@ * Implementation of the Iomega ZIP drive with SCSI(-like) * commands, for both ATAPI and SCSI usage. * - * Version: @(#)zip.h 1.0.6 2018/05/16 + * Version: @(#)zip.h 1.0.7 2018/09/09 * * Author: Miran Grca, * @@ -37,189 +37,136 @@ #define EMU_ZIP_H -#define ZIP_NUM 4 +#define ZIP_NUM 4 -#define ZIP_PHASE_IDLE 0 -#define ZIP_PHASE_COMMAND 1 -#define ZIP_PHASE_COMPLETE 2 -#define ZIP_PHASE_DATA_IN 3 -#define ZIP_PHASE_DATA_IN_DMA 4 -#define ZIP_PHASE_DATA_OUT 5 -#define ZIP_PHASE_DATA_OUT_DMA 6 -#define ZIP_PHASE_ERROR 0x80 +#define ZIP_PHASE_IDLE 0x00 +#define ZIP_PHASE_COMMAND 0x01 +#define ZIP_PHASE_COMPLETE 0x02 +#define ZIP_PHASE_DATA_IN 0x03 +#define ZIP_PHASE_DATA_IN_DMA 0x04 +#define ZIP_PHASE_DATA_OUT 0x05 +#define ZIP_PHASE_DATA_OUT_DMA 0x06 +#define ZIP_PHASE_ERROR 0x80 -#define BUF_SIZE 32768 +#define BUF_SIZE 32768 -#define IDE_TIME (5LL * 100LL * (1LL << TIMER_SHIFT)) -#define ZIP_TIME (5LL * 100LL * (1LL << TIMER_SHIFT)) +#define ZIP_TIME (5LL * 100LL * (1LL << TIMER_SHIFT)) -#define ZIP_SECTORS (96*2048) - -#define ZIP_250_SECTORS (489532) +#define ZIP_SECTORS (96*2048) +#define ZIP_250_SECTORS (489532) enum { ZIP_BUS_DISABLED = 0, - /* skip ST506 and ESDI */ - ZIP_BUS_ATAPI_PIO_ONLY = 3, - ZIP_BUS_ATAPI_PIO_AND_DMA, + ZIP_BUS_ATAPI, ZIP_BUS_SCSI, - ZIP_BUS_USB = 8 + ZIP_BUS_USB }; +#define ZIP_BUS_MAX (ZIP_BUS_USB) /* USB exclusive */ typedef struct { - uint8_t previous_command; - - int toctimes; - int media_status; - - int is_dma; - - int requested_blocks; /* This will be set to something other than 1 when block reads are implemented. */ - - uint64_t current_page_code; - int current_page_len; - - int current_page_pos; - - int mode_select_phase; - - int total_length; - int written_length; - - int do_page_save; - - uint8_t error; - uint8_t features; - uint16_t request_length; - uint16_t max_transfer_len; - uint8_t status; - uint8_t phase; - - uint32_t sector_pos; - uint32_t sector_len; - - uint32_t packet_len; - int packet_status; - - uint8_t atapi_cdb[16]; - uint8_t current_cdb[16]; - - uint32_t pos; - - int callback; - - int data_pos; - - int cdb_len_setting; - int cdb_len; - - int cd_status; - int prev_status; - - int unit_attention; - uint8_t sense[256]; - - int request_pos; - - uint8_t *buffer; - - int times; - - uint32_t seek_pos; - - int total_read; - - int block_total; - int all_blocks_total; - - int old_len; - int block_descriptor_len; - - int init_length; -} zip_t; - -typedef struct { - int host_drive; - int prev_host_drive; - - unsigned int bus_type; /* 0 = ATAPI, 1 = SCSI */ - uint8_t bus_mode; /* Bit 0 = PIO suported; + int8_t bus_type, /* 0 = ATAPI, 1 = SCSI */ + bus_mode, /* Bit 0 = PIO suported; Bit 1 = DMA supportd. */ + is_250, + read_only, + ui_writeprot; - uint8_t ide_channel; + uint8_t ide_channel; + uint8_t scsi_device_id, + scsi_device_lun; - unsigned int scsi_device_id; - unsigned int scsi_device_lun; - - unsigned int is_250; - unsigned int atapi_dma; + wchar_t image_path[1024], + prev_image_path[1024]; - wchar_t image_path[1024]; - wchar_t prev_image_path[1024]; - - uint32_t medium_size; - - int read_only; - int ui_writeprot; - - uint32_t base; - - FILE *f; + uint32_t medium_size, + base; + FILE *f; } zip_drive_t; +typedef struct { + mode_sense_pages_t ms_pages_saved; -extern zip_t zip[ZIP_NUM]; + zip_drive_t *drv; + + uint8_t id, + previous_command, + error, features, + status, phase, + *buffer, + atapi_cdb[16], + current_cdb[16], + sense[256]; + + uint16_t request_length, + max_transfer_len; + + int toctimes, media_status, + is_dma, requested_blocks, + current_page_len, current_page_pos, + total_length, written_length, + mode_select_phase, do_page_save, + data_pos, + packet_status, unit_attention, + cdb_len_setting, cdb_len, + request_pos, total_read, + block_total, all_blocks_total, + old_len, block_descriptor_len, + init_length; + + uint32_t sector_pos, sector_len, + packet_len, pos, + seek_pos; + + uint64_t current_page_code; + int64_t callback; +} zip_t; + + +extern zip_t *zip[ZIP_NUM]; extern zip_drive_t zip_drives[ZIP_NUM]; extern uint8_t atapi_zip_drives[8]; extern uint8_t scsi_zip_drives[16][8]; -#define zip_sense_error zip[id].sense[0] -#define zip_sense_key zip[id].sense[2] -#define zip_asc zip[id].sense[12] -#define zip_ascq zip[id].sense[13] -#define zip_drive zip_drives[id].host_drive +/*FIXME: These should be removed, it makes the code unclear. --FvK */ +#define zip_sense_error dev->sense[0] +#define zip_sense_key dev->sense[2] +#define zip_asc dev->sense[12] +#define zip_ascq dev->sense[13] #ifdef __cplusplus extern "C" { #endif -extern int (*ide_bus_master_read)(int channel, uint8_t *data, int transfer_length); -extern int (*ide_bus_master_write)(int channel, uint8_t *data, int transfer_length); -extern void (*ide_bus_master_set_irq)(int channel); -extern void ioctl_close(uint8_t id); +extern int zip_ZIP_PHASE_to_scsi(zip_t *dev); +extern int zip_atapi_phase_to_scsi(zip_t *dev); +extern void zip_command(zip_t *dev, uint8_t *cdb); +extern void zip_phase_callback(zip_t *dev); +extern void zip_disk_close(zip_t *dev); +extern void zip_disk_reload(zip_t *dev); +extern void zip_reset(zip_t *dev); +extern void zip_set_signature(zip_t *dev); +extern void zip_request_sense_for_scsi(zip_t *dev, uint8_t *buffer, uint8_t alloc_length); +extern void zip_update_cdb(uint8_t *cdb, int lba_pos, int number_of_blocks); +extern void zip_insert(zip_t *dev); +extern int find_zip_for_scsi_id(uint8_t scsi_id, uint8_t scsi_lun); +extern int zip_read_capacity(zip_t *dev, uint8_t *cdb, uint8_t *buffer, uint32_t *len); -extern uint32_t zip_mode_sense_get_channel(uint8_t id, int channel); -extern uint32_t zip_mode_sense_get_volume(uint8_t id, int channel); -extern void build_atapi_zip_map(void); -extern void build_scsi_zip_map(void); -extern int zip_ZIP_PHASE_to_scsi(uint8_t id); -extern int zip_atapi_phase_to_scsi(uint8_t id); -extern void zip_command(uint8_t id, uint8_t *cdb); -extern void zip_phase_callback(uint8_t id); extern uint32_t zip_read(uint8_t channel, int length); extern void zip_write(uint8_t channel, uint32_t val, int length); -extern int zip_lba_to_msf_accurate(int lba); - -extern void zip_close(uint8_t id); -extern void zip_disk_reload(uint8_t id); -extern void zip_reset(uint8_t id); -extern void zip_set_signature(int id); -extern void zip_request_sense_for_scsi(uint8_t id, uint8_t *buffer, uint8_t alloc_length); -extern void zip_update_cdb(uint8_t *cdb, int lba_pos, int number_of_blocks); -extern void zip_insert(uint8_t id); - -extern int find_zip_for_scsi_id(uint8_t scsi_id, uint8_t scsi_lun); -extern int zip_read_capacity(uint8_t id, uint8_t *cdb, uint8_t *buffer, uint32_t *len); - extern void zip_global_init(void); extern void zip_hard_reset(void); +extern void zip_build_atapi_map(void); +extern void zip_build_scsi_map(void); +extern int zip_string_to_bus(const char *str); +extern const char *zip_bus_to_string(int bus); -extern int zip_load(uint8_t id, const wchar_t *fn); -extern void zip_close(uint8_t id); +extern void zip_close(void); +extern int zip_load(zip_t *dev, const wchar_t *fn); +extern void zip_disk_close(zip_t *dev); #ifdef __cplusplus } diff --git a/src/devices/floppy/fdc.c b/src/devices/floppy/fdc.c index b3d131a..927ab64 100644 --- a/src/devices/floppy/fdc.c +++ b/src/devices/floppy/fdc.c @@ -9,7 +9,7 @@ * Implementation of the NEC uPD-765 and compatible floppy disk * controller. * - * Version: @(#)fdc.c 1.0.16 2018/09/22 + * Version: @(#)fdc.c 1.0.15 2018/09/22 * * Authors: Miran Grca, * Sarah Walker, @@ -42,6 +42,7 @@ #include #include #define HAVE_STDARG_H +#define dbglog fdc_log #include "../../emu.h" #include "../../cpu/cpu.h" #include "../../machines/machine.h" @@ -100,26 +101,26 @@ static const int command_has_drivesel[256] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + +#ifdef ENABLE_FDC_LOG +int fdc_do_log = ENABLE_FDC_LOG; +#endif uint8_t current_drive = 0; int lastbyte = 0; int floppymodified[FDD_NUM]; int floppyrate[FDD_NUM]; -#ifdef ENABLE_FDC_LOG -int fdc_do_log = ENABLE_FDC_LOG; -#endif static void fdc_callback(void *priv); -static void -fdc_log(const char *fmt, ...) +void +fdc_log(int level, const char *fmt, ...) { #ifdef ENABLE_FDC_LOG va_list ap; - if (fdc_do_log) - { + if (fdc_do_log >= level) { va_start(ap, fmt); pclog_ex(fmt, ap); va_end(ap); @@ -131,10 +132,21 @@ fdc_log(const char *fmt, ...) uint8_t fdc_ps1_525(void) { - if ((romset == ROM_IBMPS1_2011) && fdd_is_525(current_drive)) - return(0x40); +#if 1 + return fdd_is_525(current_drive) ? 0x40 : 0x00; +#else + switch (romset) { + case ROM_IBMPS1_2011: + case ROM_IBMPS1_2121: + case ROM_IBMPS1_2121_ISA: + return fdd_is_525(current_drive) ? 0x40 : 0x00; - return(0); + default: + break; + } + + return(0x00); +#endif } @@ -149,6 +161,7 @@ fdc_ctrl_reset(void *priv) fdc->lock = 0; fdc->head = 0; fdc->abort = 0; + fdc->step = 0; if (! (fdc->flags & FDC_FLAG_AT)) fdc->rate = 2; } @@ -214,8 +227,8 @@ static void fdc_rate(fdc_t *fdc, int drive); int fdc_get_perp(fdc_t *fdc) { - if (!(fdc->flags & FDC_FLAG_AT) || - (fdc->flags & FDC_FLAG_PCJR) || (fdc->flags & FDC_FLAG_PS1)) return(0); + if (!(fdc->flags & FDC_FLAG_AT) || (fdc->flags & FDC_FLAG_PCJR)) + return(0); return(fdc->perp); } @@ -226,8 +239,8 @@ fdc_get_gap2(fdc_t *fdc, int drive) { int auto_gap2 = 22; - if (!(fdc->flags & FDC_FLAG_AT) || - (fdc->flags & FDC_FLAG_PCJR) || (fdc->flags & FDC_FLAG_PS1)) return(22); + if (!(fdc->flags & FDC_FLAG_AT) || (fdc->flags & FDC_FLAG_PCJR)) + return(22); if (fdc->perp & 3) return(((fdc->perp & 3) == 3) ? 41 : 22); @@ -425,7 +438,7 @@ fdc_get_rwc(fdc_t *fdc, int drive) void fdc_update_rwc(fdc_t *fdc, int drive, int rwc) { - fdc_log("FDC: %c: new RWC is %i\n", 0x41 + drive, rwc); + DEBUG("FDC: %c: new RWC is %i\n", 0x41 + drive, rwc); fdc->rwc[drive] = rwc; fdc_rate(fdc, drive); } @@ -448,7 +461,7 @@ fdc_update_boot_drive(fdc_t *fdc, int boot_drive) void fdc_update_densel_polarity(fdc_t *fdc, int densel_polarity) { - fdc_log("FDC: new DENSEL polarity is %i\n", densel_polarity); + DEBUG("FDC: new DENSEL polarity is %i\n", densel_polarity); fdc->densel_polarity = densel_polarity; fdc_update_rates(fdc); } @@ -464,7 +477,7 @@ fdc_get_densel_polarity(fdc_t *fdc) void fdc_update_densel_force(fdc_t *fdc, int densel_force) { - fdc_log("FDC: new DENSEL force is %i\n", densel_force); + DEBUG("FDC: new DENSEL force is %i\n", densel_force); fdc->densel_force = densel_force; fdc_update_rates(fdc); } @@ -473,7 +486,7 @@ fdc_update_densel_force(fdc_t *fdc, int densel_force) void fdc_update_drvrate(fdc_t *fdc, int drive, int drvrate) { - fdc_log("FDD %c: new drive rate is %i\n", 0x41 + drive, drvrate); + DEBUG("FDD %c: new drive rate is %i\n", 0x41 + drive, drvrate); fdc->drvrate[drive] = drvrate; fdc_rate(fdc, drive); } @@ -622,10 +635,10 @@ fdc_rate(fdc_t *fdc, int drive) fdd_set_rate(drive, fdc->drvrate[drive], fdc->rate); - fdc_log("FDD %c: setting rate: %i, %i, %i (%i, %i)\n", - 0x41 + drive, fdc->drvrate[drive], fdc->rate, - fdc_get_densel(fdc, drive), - fdc->rwc[drive], fdc->densel_force); + DEBUG("FDD %c: setting rate: %i, %i, %i (%i, %i)\n", + 'A' + drive, fdc->drvrate[drive], fdc->rate, + fdc_get_densel(fdc, drive), + fdc->rwc[drive], fdc->densel_force); fdd_set_densel(fdc_get_densel(fdc, drive)); } @@ -646,7 +659,7 @@ fdc_seek(fdc_t *fdc, int drive, int params) { fdd_seek(real_drive(fdc, drive), params); - fdc->time = 5000LL * (1 << TIMER_SHIFT); + fdc->time = 5000LL * (1LL << TIMER_SHIFT); fdc->stat |= (1 << fdc->drive); } @@ -731,7 +744,7 @@ fdc_sis(fdc_t *fdc) fdc->res[10] = fdc->pcn[fdc->res[9] & 3]; - fdc_log("FDC: sense interrupt status: 2 parameters to go\n"); + DEBUG("FDC: sense interrupt status: 2 parameters to go\n"); fdc->paramstogo = 2; } @@ -743,7 +756,7 @@ fdc_write(uint16_t addr, uint8_t val, void *priv) int drive, i, drive_num; - fdc_log("FDC: write %04X %02X\n", addr, val); + DBGLOG(2, "FDC: write %04X %02X\n", addr, val); cycles -= ISA_CYCLES(8); @@ -753,7 +766,7 @@ fdc_write(uint16_t addr, uint8_t val, void *priv) return; case 2: /*DOR*/ - if ((fdc->flags & FDC_FLAG_PCJR)) { + if (fdc->flags & FDC_FLAG_PCJR) { if ((fdc->dor & 0x40) && !(val & 0x40)) { fdc->watchdog_timer = 1000LL * TIMER_USEC; fdc->watchdog_count = 1000LL; @@ -764,8 +777,13 @@ fdc_write(uint16_t addr, uint8_t val, void *priv) fdc->time = 128LL * (1LL << TIMER_SHIFT); timer_update_outstanding(); fdc->interrupt = -1; +//FIXME: why not |drive ?? --FvK ui_sb_icon_update(SB_FLOPPY | 0, 0); fdc_ctrl_reset(fdc); + fdd_changed[0] = 1; + fdd_changed[1] = 1; + fdd_changed[2] = 1; + fdd_changed[3] = 1; } if (!fdd_get_flags(0)) val &= 0xfe; @@ -793,6 +811,7 @@ fdc_write(uint16_t addr, uint8_t val, void *priv) fdc->interrupt = -1; fdc->perp &= 0xfc; +//FIXME: see above- there, too? --FvK for (i = 0; i < FDD_NUM; i++) ui_sb_icon_update(SB_FLOPPY | i, 0); @@ -833,6 +852,10 @@ fdc_write(uint16_t addr, uint8_t val, void *priv) fdc->perp &= 0xfc; fdc_ctrl_reset(fdc); } +#if 0 + if (fdc->flags & FDC_FLAG_PS1) + fdc->rate = val & 0x03; +#endif return; case 5: /*Command register*/ @@ -847,10 +870,10 @@ fdc_write(uint16_t addr, uint8_t val, void *priv) } break; } - if (fdc->pnum==fdc->ptot) { + if (fdc->pnum == fdc->ptot) { if ((fdc->stat & 0xf0) != 0x80) { /* If bit 4 of the MSR is set, or the MSR is 0x00, - the fdc_t is NOT in the command phase, therefore + the FDC is NOT in the command phase, therefore do NOT accept commands. */ return; } @@ -862,7 +885,7 @@ fdc_write(uint16_t addr, uint8_t val, void *priv) fdc->command = val; fdc->stat |= 0x10; - fdc_log("FDC: starting command %02X\n",fdc->command); + DEBUG("FDC: starting command %02X\n",fdc->command); switch (fdc->command & 0x1f) { case 0x01: /*Mode*/ @@ -937,7 +960,7 @@ fdc_write(uint16_t addr, uint8_t val, void *priv) break; case 0x08: /*Sense interrupt status*/ - fdc_log("FDC: fintr = %i, fdc->reset_stat = %i\n", fdc->fintr, fdc->reset_stat); + DEBUG("FDC: fintr = %i, fdc->reset_stat = %i\n", fdc->fintr, fdc->reset_stat); fdc->lastdrive = fdc->drive; fdc->pos = 0; fdc_sis(fdc); @@ -989,7 +1012,7 @@ fdc_write(uint16_t addr, uint8_t val, void *priv) break; case 0x12: /*Set perpendicular mode*/ - if ((fdc->flags & FDC_FLAG_AT) && !(fdc->flags & FDC_FLAG_PCJR) && !(fdc->flags & FDC_FLAG_PS1)) { + if ((fdc->flags & FDC_FLAG_AT) && !(fdc->flags & FDC_FLAG_PCJR)) { fdc->pnum = 0; fdc->ptot = 1; fdc->stat |= 0x90; @@ -1024,7 +1047,7 @@ fdc_write(uint16_t addr, uint8_t val, void *priv) } } if (fdc->pnum == fdc->ptot) { - fdc_log("FDC: got all params %02X\n", fdc->command); + DEBUG("FDC: got all params %02X\n", fdc->command); fdc->interrupt = fdc->command & 0x1F; timer_clock(); fdc->time = 1024LL * (1LL << TIMER_SHIFT); @@ -1098,10 +1121,10 @@ fdc_write(uint16_t addr, uint8_t val, void *priv) fdc_noidam(fdc); return; } - fdc_log("FDC: reading sector (drive %i) (%i) (%i %i %i %i) (%i %i %i)\n", fdc->drive, fdc->params[0], fdc->params[1], fdc->params[2], fdc->params[3], fdc->params[4], fdc->params[5], fdc->params[6], fdc->params[7]); + DEBUG("FDC: reading sector (drive %i) (%i) (%i %i %i %i) (%i %i %i)\n", fdc->drive, fdc->params[0], fdc->params[1], fdc->params[2], fdc->params[3], fdc->params[4], fdc->params[5], fdc->params[6], fdc->params[7]); if (((dma_mode(2) & 0x0C) == 0x00) && !(fdc->flags & FDC_FLAG_PCJR) && fdc->dma) { /* DMA is in verify mode, treat this like a VERIFY command. */ - fdc_log("FDC: verify-mode read!\n"); + DEBUG("FDC: verify-mode read!\n"); fdc->tc = 1; fdc->deleted |= 2; } @@ -1117,7 +1140,7 @@ fdc_write(uint16_t addr, uint8_t val, void *priv) drive_num = real_drive(fdc, fdc->drive); /* Three conditions under which the command should fail. */ if (!fdd_get_flags(drive_num) || (drive_num >= FDD_NUM) || !motoron[drive_num] || fdd_track0(drive_num)) { - fdc_log("FDC: failed recalibrate\n"); + DEBUG("FDC: failed recalibrate\n"); if (!fdd_get_flags(drive_num) || (drive_num >= FDD_NUM) || !motoron[drive_num]) fdc->st0 = 0x70 | (fdc->params[0] & 3); else @@ -1131,8 +1154,9 @@ fdc_write(uint16_t addr, uint8_t val, void *priv) } if ((real_drive(fdc, fdc->drive) != 1) || fdc->drv2en) fdc_seek(fdc, fdc->drive, -fdc->max_track); - fdc_log("FDC: recalibrating...\n"); - fdc->time = 5000LL * (1 << TIMER_SHIFT); + DEBUG("FDC: recalibrating...\n"); + fdc->time = 5000LL * (1LL << TIMER_SHIFT); + fdc->step = fdc->seek_dir = 1; break; case 0x0d: /*Format*/ @@ -1178,14 +1202,18 @@ fdc_write(uint16_t addr, uint8_t val, void *priv) if (fdc->params[1]) { if (fdc->command & 0x40) { /* Relative seek inwards. */ + fdc->seek_dir = 0; fdc_seek(fdc, fdc->drive, fdc->params[1]); fdc->pcn[fdc->params[0] & 3] += fdc->params[1]; } else { /* Relative seek outwards. */ + + fdc->seek_dir = 1; fdc_seek(fdc, fdc->drive, -fdc->params[1]); fdc->pcn[fdc->params[0] & 3] -= fdc->params[1]; } - fdc->time = 5000LL * (1 << TIMER_SHIFT); + fdc->time = 5000LL * (1LL << TIMER_SHIFT); + fdc->step = 1; } else { fdc->st0 = 0x20 | (fdc->params[0] & 7); fdc->interrupt = -3; @@ -1195,9 +1223,9 @@ fdc_write(uint16_t addr, uint8_t val, void *priv) break; } } else { - fdc_log("FDC: seeking to track %i (PCN = %i)...\n", fdc->params[1], fdc->pcn[fdc->params[0] & 3]); + DEBUG("FDC: seeking to track %i (PCN = %i)...\n", fdc->params[1], fdc->pcn[fdc->params[0] & 3]); if ((fdc->params[1] - fdc->pcn[fdc->params[0] & 3]) == 0) { - fdc_log("FDC: failed seek\n"); + DEBUG("FDC: failed seek\n"); fdc->st0 = 0x20 | (fdc->params[0] & 7); fdc->interrupt = -3; timer_clock(); @@ -1205,9 +1233,14 @@ fdc_write(uint16_t addr, uint8_t val, void *priv) timer_update_outstanding(); break; } + if (fdc->params[1] > fdc->pcn[fdc->params[0] & 3]) + fdc->seek_dir = 0; + else + fdc->seek_dir = 1; fdc_seek(fdc, fdc->drive, fdc->params[1] - fdc->pcn[fdc->params[0] & 3]); fdc->pcn[fdc->params[0] & 3] = fdc->params[1]; - fdc->time = 5000LL * (1 << TIMER_SHIFT); + fdc->time = 5000LL * (1LL << TIMER_SHIFT); + fdc->step = 1; } break; @@ -1235,7 +1268,9 @@ fdc_write(uint16_t addr, uint8_t val, void *priv) case 7: if (!(fdc->flags & FDC_FLAG_AT) && !(fdc->flags & FDC_FLAG_TOSHIBA)) return; - fdc->rate = val & 3; + fdc->rate = val & 0x03; + if (fdc->flags & FDC_FLAG_PS1) + fdc->noprec = !!(val & 0x04); return; } } @@ -1252,27 +1287,57 @@ fdc_read(uint16_t addr, void *priv) switch (addr&7) { case 0: /* STA */ - ret = 0x7f; - if (fdc->fintr || fdc->reset_stat) - ret |= 0x80; + if (fdc->flags & FDC_FLAG_PS1) { + drive = real_drive(fdc, fdc->dor & 3); + ret = 0x00; + /* TODO: + Bit 2: INDEX (best return always 0 as it goes by very fast) + Bit 6: DRQ + */ + if (writeprot[drive]) /* WRITEPROT */ + ret |= 0x01; + if (fdc->seek_dir) /* nDIRECTION */ + ret |= 0x02; + if (!fdd_get_head(drive)) /* nHDSEL */ + ret |= 0x08; + if (fdd_track0(drive)) /* TRK0 */ + ret |= 0x10; + if (fdc->step) /* STEP */ + ret |= 0x20; + if (fdc->fintr || fdc->reset_stat) /* INTR */ + ret |= 0x80; + } else + ret = 0xff; break; case 1: /* STB */ - if (is486) - break; - drive = real_drive(fdc, fdc->dor & 3); - if (! fdc->enable_3f1) - break; - ret = 0x70; - if (drive) - ret &= ~0x40; - else - ret &= ~0x20; - - if (fdc->dor & 0x10) - ret |= 1; - if (fdc->dor & 0x20) - ret |= 2; + if (fdc->flags & FDC_FLAG_PS1) { + drive = real_drive(fdc, fdc->dor & 3); + ret = 0x00; + /* -Drive 2 Installed */ + if (!fdd_get_type(1)) + ret |= 80; + /* -Drive Select 1,0 */ + if (drive) + ret |= 0x20; + else + ret |= 0x40; + } else { + if (is486) + return 0xff; + drive = real_drive(fdc, fdc->dor & 3); + if (!fdc->enable_3f1) + ret = 0xff; + ret = 0x70; //FIXME: ?? + if (drive) + ret &= ~0x40; + else + ret &= ~0x20; + if (fdc->dor & 0x10) + ret |= 1; + if (fdc->dor & 0x20) + ret |= 2; + } break; case 2: @@ -1322,7 +1387,7 @@ fdc_read(uint16_t addr, void *priv) } fdc->stat &= ~0x80; if (fdc->paramstogo) { - fdc_log("FDC: %i parameters to go\n", fdc->paramstogo); + DEBUG("FDC: %i parameters to go\n", fdc->paramstogo); fdc->paramstogo--; ret = fdc->res[10 - fdc->paramstogo]; if (!fdc->paramstogo) @@ -1345,6 +1410,7 @@ fdc_read(uint16_t addr, void *priv) if (fdc->dor & (0x10 << drive)) { ret = (fdd_changed[drive] || drive_empty[drive]) ? 0x00 : 0x80; ret |= (fdc->dor & 0x08); + ret |= (fdc->noprec << 2); ret |= (fdc->rate & 0x03); } else ret = 0x00; @@ -1371,12 +1437,14 @@ fdc_read(uint16_t addr, void *priv) } else ret |= 0x01; } + fdc->step = 0; break; default: break; } - fdc_log("FDC: read %04X %02X\n", addr, ret); + + DBGLOG(2, "FDC: read %04X %02X\n", addr, ret); return(ret); } @@ -1387,7 +1455,8 @@ fdc_poll_common_finish(fdc_t *fdc, int compare, int st5) { fdc_int(fdc); - fdc->fintr = 0; + if (!(fdc->flags & FDC_FLAG_PS1)) + fdc->fintr = 0; fdc->stat = 0xD0; fdc->st0 = fdc->res[4] = (fdd_get_head(real_drive(fdc, fdc->drive)) ? 4 : 0) | fdc->rw_drive; fdc->res[5] = st5; @@ -1424,7 +1493,7 @@ fdc_poll_common_finish(fdc_t *fdc, int compare, int st5) fdc->res[8]=fdc->head; fdc->res[9]=fdc->sector; fdc->res[10]=fdc->params[4]; - fdc_log("FDC: read/write finish (%02X %02X %02X %02X %02X %02X %02X)\n" , fdc->res[4], fdc->res[5], fdc->res[6], fdc->res[7], fdc->res[8], fdc->res[9], fdc->res[10]); + DBGLOG(1, "FDC: read/write finish (%02X %02X %02X %02X %02X %02X %02X)\n" , fdc->res[4], fdc->res[5], fdc->res[6], fdc->res[7], fdc->res[8], fdc->res[9], fdc->res[10]); ui_sb_icon_update(SB_FLOPPY | fdc->drive, 0); fdc->paramstogo = 7; } @@ -1458,7 +1527,8 @@ fdc_callback(void *priv) int old_sector = 0; fdc->time = 0LL; - fdc_log("FDC: callback(%i)\n", fdc->interrupt); + DBGLOG(1, "FDC: callback(%i)\n", fdc->interrupt); + switch (fdc->interrupt) { case -3: /*End of command with interrupt*/ fdc_int(fdc); @@ -1662,7 +1732,8 @@ fdc_callback(void *priv) } else { fdc->interrupt = -2; fdc_int(fdc); - fdc->fintr = 0; + if (!(fdc->flags & FDC_FLAG_PS1)) + fdc->fintr = 0; fdc->stat = 0xD0; fdc->st0 = fdc->res[4] = (fdd_get_head(real_drive(fdc, fdc->drive)) ? 4 : 0) | fdc->drive; fdc->res[5] = fdc->res[6] = 0; @@ -1697,9 +1768,11 @@ fdc_callback(void *priv) drive_num = real_drive(fdc, fdc->rw_drive); fdc->st0 = 0x20 | (fdc->params[0] & 7); fdc->interrupt = -3; - /* timer_clock(); +#if 0 + timer_clock(); fdc->time = 2048LL * (1LL << TIMER_SHIFT); - timer_update_outstanding(); */ + timer_update_outstanding(); +#endif fdc->stat = 0x80 | (1 << fdc->drive); fdc_callback(fdc); return; @@ -1751,17 +1824,16 @@ fdc_error(fdc_t *fdc, int st5, int st6) fdc_int(fdc); - fdc->fintr = 0; + if (!(fdc->flags & FDC_FLAG_PS1)) + fdc->fintr = 0; fdc->stat = 0xD0; fdc->st0 = fdc->res[4] = 0x40 | (fdd_get_head(real_drive(fdc, fdc->drive)) ? 4 : 0) | fdc->rw_drive; - if (fdc->head && !fdd_is_double_sided(real_drive(fdc, fdc->drive))) { - fdc_log("FDC: head 1 on 1-sided drive\n"); + if (fdc->head && !fdd_is_double_sided(real_drive(fdc, fdc->drive))) fdc->st0 |= 0x08; - } fdc->res[5] = st5; fdc->res[6] = st6; - fdc_log("FDC: ERROR: %02X %02X %02X\n", fdc->res[4], fdc->res[5], fdc->res[6]); + DEBUG("FDC: ERROR: %02X %02X %02X\n", fdc->res[4], fdc->res[5], fdc->res[6]); switch(fdc->interrupt) { case 0x02: case 0x05: @@ -2104,8 +2176,8 @@ fdc_set_base(fdc_t *fdc, int base) } fdc->base_address = base; - fdc_log("FDC: base address set%s (%04X)\n", - super_io ? " for Super I/O" : "", fdc->base_address); + DEBUG("FDC: base address set%s (%04X)\n", + super_io ? " for Super I/O" : "", fdc->base_address); } @@ -2127,10 +2199,11 @@ fdc_remove(fdc_t *fdc) io_removehandler(fdc->base_address+5, 1, fdc_read,NULL,NULL, fdc_write,NULL,NULL, fdc); if (fdc->flags & FDC_FLAG_TOSHIBA) - io_removehandler(fdc->base_address+7, 1, fdc_read,NULL,NULL, fdc_write,NULL,NULL, fdc); + io_removehandler(fdc->base_address+7, 1, + fdc_read,NULL,NULL, fdc_write,NULL,NULL, fdc); } - fdc_log("FDC: removed (%04X)\n", fdc->base_address); + DEBUG("FDC: removed (%04X)\n", fdc->base_address); } @@ -2147,7 +2220,10 @@ fdc_reset(void *priv) fdc_update_is_nsc(fdc, 0); fdc_update_enh_mode(fdc, 0); - fdc_update_densel_polarity(fdc, 1); + if (fdc->flags & FDC_FLAG_PS1) + fdc_update_densel_polarity(fdc, 0); + else + fdc_update_densel_polarity(fdc, 1); fdc_update_densel_force(fdc, 0); fdc_update_rwc(fdc, 0, default_rwc); fdc_update_rwc(fdc, 1, default_rwc); @@ -2162,7 +2238,7 @@ fdc_reset(void *priv) fdc->fifo = 0; fdc->tfifo = 1; - if ((fdc->flags & FDC_FLAG_PCJR)) { + if (fdc->flags & FDC_FLAG_PCJR) { fdc->dma = 0; fdc->specify[1] = 1; } else { @@ -2209,7 +2285,7 @@ fdc_close(void *priv) static void * fdc_init(const device_t *info) { - fdc_t *fdc = (fdc_t *)malloc(sizeof(fdc_t)); + fdc_t *fdc = (fdc_t *)mem_alloc(sizeof(fdc_t)); memset(fdc, 0x00, sizeof(fdc_t)); @@ -2223,7 +2299,7 @@ fdc_init(const device_t *info) else fdc->dma_ch = 2; - fdc_log("FDC: %04X (flags: %08X)\n", fdc->base_address, fdc->flags); + DEBUG("FDC: %04X (flags: %08X)\n", fdc->base_address, fdc->flags); timer_add(fdc_callback, &fdc->time, &fdc->time, fdc); @@ -2256,15 +2332,6 @@ const device_t fdc_xt_device = { NULL }; -const device_t fdc_xt_toshiba_device = { - "Toshiba TC8565 Floppy Drive Controller", - 0, - FDC_FLAG_TOSHIBA, - fdc_init, fdc_close, fdc_reset, - NULL, NULL, NULL, NULL, - NULL -}; - const device_t fdc_pcjr_device = { "PCjr Floppy Drive Controller", 0, @@ -2329,3 +2396,12 @@ const device_t fdc_at_nsc_device = { NULL, NULL, NULL, NULL, NULL }; + +const device_t fdc_toshiba_device = { + "Toshiba TC8565 Floppy Drive Controller", + 0, + FDC_FLAG_TOSHIBA, + fdc_init, fdc_close, fdc_reset, + NULL, NULL, NULL, NULL, + NULL +}; diff --git a/src/devices/floppy/fdc.h b/src/devices/floppy/fdc.h index 7e01a63..2d434f1 100644 --- a/src/devices/floppy/fdc.h +++ b/src/devices/floppy/fdc.h @@ -49,7 +49,7 @@ #define FDC_FLAG_START_RWC_1 0x20 /* W83877F, W83977F */ #define FDC_FLAG_MORE_TRACKS 0x40 /* W83877F, W83977F, PC87306, PC87309 */ #define FDC_FLAG_NSC 0x80 /* PC87306, PC87309 */ -#define FDC_FLAG_TOSHIBA 0x100 /* Toshiba TC8565 */ +#define FDC_FLAG_TOSHIBA 0x100 /* Toshiba TC8565 (T1200) */ typedef struct { @@ -71,6 +71,8 @@ typedef struct { int abort; int format_state, format_n; int tc, written; + int step, seek_dir; + int noprec; int data_ready, inread; int bitcell_period, enh_mode; @@ -102,6 +104,20 @@ typedef struct { } fdc_t; +#ifdef EMU_DEVICE_H +extern const device_t fdc_xt_device; +extern const device_t fdc_toshiba_device; +extern const device_t fdc_pcjr_device; +extern const device_t fdc_at_device; +extern const device_t fdc_at_actlow_device; +extern const device_t fdc_at_ps1_device; +extern const device_t fdc_at_smc_device; +extern const device_t fdc_at_winbond_device; +extern const device_t fdc_at_nsc_device; +#endif + + +extern void fdc_log(int level, const char *fmt, ...); extern void fdc_remove(fdc_t *fdc); extern void fdc_poll(fdc_t *fdc); extern void fdc_abort(fdc_t *fdc); @@ -180,17 +196,5 @@ extern void fdc_reset(void *priv); extern uint8_t fdc_ps1_525(void); -#ifdef EMU_DEVICE_H -extern const device_t fdc_xt_device; -extern const device_t fdc_xt_toshiba_device; -extern const device_t fdc_pcjr_device; -extern const device_t fdc_at_device; -extern const device_t fdc_at_actlow_device; -extern const device_t fdc_at_ps1_device; -extern const device_t fdc_at_smc_device; -extern const device_t fdc_at_winbond_device; -extern const device_t fdc_at_nsc_device; -#endif - #endif /*EMU_FDC_H*/ diff --git a/src/devices/floppy/fdd.c b/src/devices/floppy/fdd.c index 3f69a55..b6d6142 100644 --- a/src/devices/floppy/fdd.c +++ b/src/devices/floppy/fdd.c @@ -8,7 +8,7 @@ * * Implementation of the floppy drive emulation. * - * Version: @(#)fdd.c 1.0.13 2018/05/14 + * Version: @(#)fdd.c 1.0.14 2018/10/05 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -42,11 +42,8 @@ #include #include #define HAVE_STDARG_H +#define dbglog fdd_log #include "../../emu.h" -#include "../../machines/machine.h" -#include "../../mem.h" -#include "../../rom.h" -#include "../../config.h" #include "../../timer.h" #include "../../ui/ui.h" #include "../../plat.h" @@ -108,6 +105,7 @@ static const struct { { L"BIN", img_load, img_close, -1 }, { L"CQ", img_load, img_close, -1 }, { L"CQM", img_load, img_close, -1 }, + { L"DDI", img_load, img_close, -1 }, { L"DSK", img_load, img_close, -1 }, { L"FDI", fdi_load, fdi_close, -1 }, { L"FDF", img_load, img_close, -1 }, @@ -222,13 +220,12 @@ static const struct void -fdd_log(const char *fmt, ...) +fdd_log(int level, const char *fmt, ...) { #ifdef ENABLE_FDC_LOG va_list ap; - if (fdd_do_log) - { + if (fdd_do_log >= level) { va_start(ap, fmt); pclog_ex(fmt, ap); va_end(ap); @@ -474,9 +471,7 @@ int fdd_load(int drive, const wchar_t *fn) wchar_t *p; FILE *f; -#ifdef ENABLE_FDD_LOG - fdd_log("FDD: loading drive %d with '%ls'\n", drive, fn); -#endif + DEBUG("FDD: loading drive %d with '%ls'\n", drive, fn); if (!fn) return(0); p = plat_get_extension(fn); @@ -505,9 +500,7 @@ int fdd_load(int drive, const wchar_t *fn) c++; } no_load: -#ifdef ENABLE_FDD_LOG - fdd_log("FDD: could not load '%ls' %s\n",fn,p); -#endif + DEBUG("FDD: could not load '%ls' %s\n",fn,p); drive_empty[drive] = 1; fdd_set_head(drive, 0); memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); @@ -518,13 +511,17 @@ no_load: void fdd_close(int drive) { -#ifdef ENABLE_FDD_LOG - fdd_log("FDD: closing drive %d\n", drive); -#endif + DEBUG("FDD: closing drive %d\n", drive); +pclog(0,"FDD: close(%d)\n",drive); + /* Make sure the 86F poll is back to idle state. */ + d86f_stop(drive); + +pclog(0,"FDD: close(%d) 1\n",drive); if (loaders[driveloaders[drive]].close) loaders[driveloaders[drive]].close(drive); +pclog(0,"FDD: close(%d) 2\n",drive); drive_empty[drive] = 1; fdd_set_head(drive, 0); @@ -542,9 +539,12 @@ void fdd_close(int drive) drives[drive].byteperiod = NULL; drives[drive].stop = NULL; +pclog(0,"FDD: close(%d) 3\n",drive); d86f_destroy(drive); +pclog(0,"FDD: close(%d) 4\n",drive); ui_sb_icon_state(drive, 1); +pclog(0,"FDD: close(%d) 5\n",drive); } int fdd_notfound = 0; diff --git a/src/devices/floppy/fdd.h b/src/devices/floppy/fdd.h index 5f45caf..a7051c1 100644 --- a/src/devices/floppy/fdd.h +++ b/src/devices/floppy/fdd.h @@ -8,7 +8,7 @@ * * Definitions for the floppy drive emulation. * - * Version: @(#)fdd.h 1.0.6 2018/05/14 + * Version: @(#)fdd.h 1.0.8 2018/09/19 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -78,7 +78,10 @@ extern int64_t floppytime; extern int fdd_swap; -extern void fdd_log(const char *fmt, ...); +extern void d86f_log(int level, const char *fmt, ...); + +extern void fdd_log(int level, const char *fmt, ...); + extern void fdd_do_seek(int drive, int track); extern void fdd_forced_seek(int drive, int track_diff); extern void fdd_seek(int drive, int track_diff); @@ -133,7 +136,6 @@ extern void fdd_format(int drive, int side, int density, uint8_t fill); extern int fdd_hole(int drive); extern double fdd_byteperiod(int drive); extern void fdd_stop(int drive); -extern int fdd_empty(int drive); extern void fdd_set_rate(int drive, int drvden, int rate); extern int motorspin; diff --git a/src/devices/floppy/fdd_86f.c b/src/devices/floppy/fdd_86f.c index ccd6585..84b5114 100644 --- a/src/devices/floppy/fdd_86f.c +++ b/src/devices/floppy/fdd_86f.c @@ -10,7 +10,7 @@ * data in the form of FM/MFM-encoded transitions) which also * forms the core of the emulator's floppy disk emulation. * - * Version: @(#)fdd_86f.c 1.0.12 2018/09/03 + * Version: @(#)fdd_86f.c 1.0.13 2018/10/05 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -41,9 +41,9 @@ #include #include #include -#include #include #define HAVE_STDARG_H +#define dbglog d86f_log #include "../../emu.h" #include "../../nvr.h" #include "../../random.h" @@ -53,7 +53,9 @@ #include "fdd.h" #include "fdc.h" #include "fdd_86f.h" -#include "lzf/lzf.h" +#ifdef D86F_COMPRESS +# include "lzf/lzf.h" +#endif /* @@ -169,9 +171,9 @@ typedef union { split_byte_t nibbles; } decoded_t; -typedef struct { +typedef struct _sector_ { uint8_t c, h, r, n; - void *prev; + struct _sector_ *prev; } sector_t; /* Disk flags: @@ -224,7 +226,9 @@ typedef struct { uint16_t current_bit[2]; int cur_track; uint32_t error_condition; +#ifdef D86F_COMPRESS int is_compressed; +#endif int id_found; wchar_t original_file_name[2048]; uint8_t *filebuf; @@ -268,23 +272,23 @@ uint64_t poly = 0x42F0E1EBA9EA3693ll; /* ECMA normal */ uint64_t table[256]; -uint16_t d86f_side_flags(int drive); -int d86f_is_mfm(int drive); -void d86f_writeback(int drive); -uint8_t d86f_poll_read_data(int drive, int side, uint16_t pos); -void d86f_poll_write_data(int drive, int side, uint16_t pos, uint8_t data); -int d86f_format_conditions(int drive); +uint16_t d86f_side_flags(int drive); +int d86f_is_mfm(int drive); +void d86f_writeback(int drive); +uint8_t d86f_poll_read_data(int drive, int side, uint16_t pos); +void d86f_poll_write_data(int drive, int side, uint16_t pos, uint8_t data); +int d86f_format_conditions(int drive); -static void -d86f_log(const char *format, ...) +void +d86f_log(int level, const char *fmt, ...) { #ifdef ENABLE_D86F_LOG va_list ap; - if (d86f_do_log) { - va_start(ap, format); - pclog_ex(format, ap); + if (d86f_do_log >= level) { + va_start(ap, fmt); + pclog_ex(fmt, ap); va_end(ap); } #endif @@ -638,6 +642,7 @@ d86f_get_array_size(int drive, int side) int hole, rm; rm = d86f_get_rpm_mode(drive); + hole = (d86f_handler[drive].disk_flags(drive) & 6) >> 1; switch (hole) { case 0: @@ -738,9 +743,12 @@ d86f_valid_bit_rate(int drive) case 3: /* ED with 2000 kbps support */ if (rate < 3) return 0; return 1; + + default: + break; } - return 1; //FIXME: should be 0 for error? + return 0; } @@ -1077,7 +1085,7 @@ d86f_get_bit(int drive, int side) } /* - * In some cases, misindentification occurs so we need + * In some cases, misidentification occurs so we need * to make sure the surface data array is not not NULL. */ if (d86f_has_surface_desc(drive) && @@ -1429,7 +1437,7 @@ d86f_read_sector_id(int drive, int side, int match) /* We've got the ID. */ if (dev->calc_crc.word != dev->track_crc.word) { dev->id_find.sync_marks = dev->id_find.bits_obtained = dev->id_find.bytes_obtained = 0; - d86f_log("86F: ID CRC error: %04X != %04X (%08X)\n", dev->track_crc.word, dev->calc_crc.word, dev->last_sector.dword); + DEBUG("86F: ID CRC error: %04X != %04X (%08X)\n", dev->track_crc.word, dev->calc_crc.word, dev->last_sector.dword); if ((dev->state != STATE_02_READ_ID) && (dev->state != STATE_0A_READ_ID)) { dev->error_condition = 0; dev->state = STATE_IDLE; @@ -1549,6 +1557,7 @@ d86f_read_sector_data(int drive, int side) if (dev->data_find.bits_obtained) { if (!(dev->data_find.bits_obtained & 15)) { /* We've got a byte. */ + DEBUG("86F: We've got a byte.\n"); if (dev->data_find.bytes_obtained < sector_len) { data = decodefm(drive, dev->last_word[side]); if (dev->state == STATE_11_SCAN_DATA) { @@ -1559,9 +1568,8 @@ d86f_read_sector_data(int drive, int side) if (dev->data_find.bytes_obtained < d86f_get_data_len(drive)) { if (dev->state != STATE_16_VERIFY_DATA) { read_status = fdc_data(d86f_fdc, data); - if (read_status == -1) { + if (read_status == -1) dev->dma_over++; - } } } } @@ -1572,29 +1580,9 @@ d86f_read_sector_data(int drive, int side) dev->data_find.bytes_obtained++; if (dev->data_find.bytes_obtained == (crc_pos + fdc_get_gap(d86f_fdc))) { -#if 0 - /* - * This code causes errors on Wyse UNIX - * System V/386 V3.2.1A and was disabled - * at Miran Grca's request. --FvK - */ /* We've got the data. */ - if (dev->dma_over > 1) { - dev->data_find.sync_marks = dev->data_find.bits_obtained = dev->data_find.bytes_obtained = 0; - dev->error_condition = 0; - dev->state = STATE_IDLE; - fdc_finishread(d86f_fdc); - fdc_overrun(d86f_fdc); - - d86f_get_bit(drive, side); - - dev->data_find.bits_obtained++; - return; - } -#endif - if ((dev->calc_crc.word != dev->track_crc.word) && (dev->state != STATE_02_READ_DATA)) { - d86f_log("86F: Data CRC error: %04X != %04X (%08X)\n", dev->track_crc.word, dev->calc_crc.word, dev->last_sector.dword); + DEBUG("86F: Data CRC error: %04X != %04X (%08X)\n", dev->track_crc.word, dev->calc_crc.word, dev->last_sector.dword); dev->data_find.sync_marks = dev->data_find.bits_obtained = dev->data_find.bytes_obtained = 0; dev->error_condition = 0; dev->state = STATE_IDLE; @@ -1607,15 +1595,14 @@ d86f_read_sector_data(int drive, int side) fdc_track_finishread(d86f_fdc, dev->error_condition); } else { /* CRC is valid. */ + DEBUG("86F: Data CRC OK: %04X != %04X (%08X)\n", dev->track_crc.word, dev->calc_crc.word, dev->last_sector.dword); dev->data_find.sync_marks = dev->data_find.bits_obtained = dev->data_find.bytes_obtained = 0; dev->error_condition = 0; - if (dev->state == STATE_11_SCAN_DATA) { - dev->state = STATE_IDLE; + dev->state = STATE_IDLE; + if (dev->state == STATE_11_SCAN_DATA) fdc_sector_finishcompare(d86f_fdc, (dev->satisfying_bytes == ((128 << ((uint32_t) dev->last_sector.id.n)) - 1)) ? 1 : 0); - } else { - dev->state = STATE_IDLE; + else fdc_sector_finishread(d86f_fdc); - } } } } @@ -1713,24 +1700,6 @@ d86f_write_sector_data(int drive, int side, int mfm, uint16_t am) dev->data_find.bytes_obtained++; if (dev->data_find.bytes_obtained == (crc_pos + fdc_get_gap(d86f_fdc))) { -#if 0 - /* - * This code causes errors on Wyse UNIX - * System V/386 V3.2.1A and was disabled - * at Miran Grca's request. --FvK - */ - if (dev->dma_over > 1) { - dev->data_find.sync_marks = dev->data_find.bits_obtained = dev->data_find.bytes_obtained = 0; - dev->error_condition = 0; - dev->state = STATE_IDLE; - fdc_finishread(d86f_fdc); - fdc_overrun(d86f_fdc); - - dev->data_find.bits_obtained++; - return; - } -#endif - /* We've written the data. */ dev->data_find.sync_marks = dev->data_find.bits_obtained = dev->data_find.bytes_obtained = 0; dev->error_condition = 0; @@ -1746,7 +1715,8 @@ d86f_write_sector_data(int drive, int side, int mfm, uint16_t am) } -void d86f_advance_bit(int drive, int side) +void +d86f_advance_bit(int drive, int side) { d86f_t *dev = d86f[drive]; @@ -2159,22 +2129,6 @@ d86f_turbo_read(int drive, int side) } } -#if 0 - /* - * This code causes errors on Wyse UNIX - * System V/386 V3.2.1A and was disabled - * at Miran Grca's request. --FvK - */ - if (dev->dma_over > 1) { - dev->data_find.sync_marks = dev->data_find.bits_obtained = dev->data_find.bytes_obtained = 0; - dev->error_condition = 0; - dev->state = STATE_IDLE; - fdc_finishread(d86f_fdc); - fdc_overrun(d86f_fdc); - return; - } -#endif - if (dev->turbo_pos >= (128 << dev->last_sector.id.n)) { /* CRC is valid. */ dev->data_find.sync_marks = dev->data_find.bits_obtained = dev->data_find.bytes_obtained = 0; @@ -2597,7 +2551,8 @@ d86f_poll(int drive) fdc_wrongcylinder(d86f_fdc); else fdc_nosector(d86f_fdc); - } + } else + fdc_nosector(d86f_fdc); } else { fdc_noidam(d86f_fdc); } @@ -2697,7 +2652,7 @@ d86f_prepare_sector(int drive, int side, int prev_pos, uint8_t *id_buf, uint8_t uint16_t datadam_mfm = 0x4A55; if (fdd_get_turbo(drive) && (dev->version == 0x0063)) { - s = (sector_t *) malloc(sizeof(sector_t)); + s = (sector_t *) mem_alloc(sizeof(sector_t)); memset(s, 0, sizeof(sector_t)); s->c = id_buf[0]; s->h = id_buf[1]; @@ -3113,9 +3068,11 @@ d86f_writeback(int drive) d86f_t *dev = d86f[drive]; uint8_t header[32]; int header_size; +#ifdef D86F_COMPRESS uint32_t len; int ret = 0; FILE *cf; +#endif header_size = d86f_header_size(drive); if (! dev->f) return; @@ -3129,6 +3086,7 @@ d86f_writeback(int drive) d86f_write_tracks(drive, &dev->f, NULL); +#ifdef D86F_COMPRESS if (dev->is_compressed) { /* The image is compressed. */ @@ -3145,18 +3103,20 @@ d86f_writeback(int drive) fseek(dev->f, header_size, SEEK_SET); /* Compress data from the temporary uncompressed file to the original, compressed file. */ - dev->filebuf = (uint8_t *) malloc(len); - dev->outbuf = (uint8_t *) malloc(len - 1); + dev->filebuf = (uint8_t *) mem_alloc(len); + dev->outbuf = (uint8_t *) mem_alloc(len - 1); fread(dev->filebuf, 1, len, dev->f); ret = lzf_compress(dev->filebuf, len, dev->outbuf, len - 1); - if (! ret) - d86f_log("86F: Error compressing file\n"); + if (! ret) { + DEBUG("86F: Error compressing file\n"); + } fwrite(dev->outbuf, 1, ret, cf); free(dev->outbuf); free(dev->filebuf); } +#endif } @@ -3165,7 +3125,8 @@ d86f_stop(int drive) { d86f_t *dev = d86f[drive]; - dev->state = STATE_IDLE; + if (dev != NULL) + dev->state = STATE_IDLE; } @@ -3174,7 +3135,7 @@ d86f_common_command(int drive, int sector, int track, int side, int rate, int se { d86f_t *dev = d86f[drive]; - d86f_log("d86f_common_command (drive %i): fdc_period=%i img_period=%i rate=%i sector=%i track=%i side=%i\n", drive, fdc_get_bitcell_period(d86f_fdc), d86f_get_bitcell_period(drive), rate, sector, track, side); + DEBUG("d86f_common_command (drive %i): fdc_period=%i img_period=%i rate=%i sector=%i track=%i side=%i\n", drive, fdc_get_bitcell_period(d86f_fdc), d86f_get_bitcell_period(drive), rate, sector, track, side); dev->req_sector.id.c = track; dev->req_sector.id.h = side; @@ -3211,7 +3172,8 @@ d86f_readsector(int drive, int sector, int track, int side, int rate, int sector int ret = 0; ret = d86f_common_command(drive, sector, track, side, rate, sector_size); - if (! ret) return; + if (! ret) + return; if (sector == SECTOR_FIRST) dev->state = STATE_02_SPIN_TO_INDEX; @@ -3434,7 +3396,7 @@ d86f_export(int drive, const wchar_t *fn) return 0; /* Allocate a temporary drive for conversion. */ - temp86 = (d86f_t *)malloc(sizeof(d86f_t)); + temp86 = (d86f_t *)mem_alloc(sizeof(d86f_t)); memcpy(temp86, dev, sizeof(d86f_t)); fwrite(&magic, 4, 1, f); @@ -3479,13 +3441,15 @@ d86f_export(int drive, const wchar_t *fn) int d86f_load(int drive, const wchar_t *fn) { - wchar_t temp_file_name[2048]; d86f_t *dev = d86f[drive]; uint32_t magic = 0; uint32_t len = 0; +#ifdef D86F_COMPRESS + wchar_t temp_file_name[2048]; uint16_t temp = 0; - int i = 0; FILE *tf; + int i; +#endif d86f_unregister(drive); @@ -3522,7 +3486,7 @@ d86f_load(int drive, const wchar_t *fn) if ((magic != 0x46423638) && (magic != 0x66623638)) { /* File is not of the valid format, abort. */ - d86f_log("86F: Unrecognized magic bytes: %08X\n", magic); + ERRLOG("86F: Unrecognized magic bytes: %08X\n", magic); fclose(dev->f); free(dev); return(0); @@ -3532,23 +3496,27 @@ d86f_load(int drive, const wchar_t *fn) if (dev->version != D86FVER) { /* File is not of a recognized format version, abort. */ if (dev->version == 0x0063) { - d86f_log("86F: File has emulator-internal version 0.99, this version is not valid in a file\n"); + ERRLOG("86F: File has emulator-internal version 0.99, this version is not valid in a file\n"); } else if ((dev->version >= 0x0100) && (dev->version < D86FVER)) { - d86f_log("86F: No longer supported development file version: %i.%02i\n", dev->version >> 8, dev->version & 0xff); + ERRLOG("86F: No longer supported development file version: %i.%02i\n", dev->version >> 8, dev->version & 0xff); } else { - d86f_log("86F: Unrecognized file version: %i.%02i\n", dev->version >> 8, dev->version & 0xff); + ERRLOG("86F: Unrecognized file version: %i.%02i\n", dev->version >> 8, dev->version & 0xff); } fclose(dev->f); dev->f = NULL; free(dev); return(0); } else { - d86f_log("86F: Recognized file version: %i.%02i\n", dev->version >> 8, dev->version & 0xff); + DEBUG("86F: Recognized file version: %i.%02i\n", dev->version >> 8, dev->version & 0xff); } fread(&(dev->disk_flags), 2, 1, dev->f); +#ifdef D86F_COMPRESS dev->is_compressed = (magic == 0x66623638) ? 1 : 0; if ((len < 51052) && !dev->is_compressed) { +#else + if (len < 51052) { +#endif /* File too small, abort. */ fclose(dev->f); dev->f = NULL; @@ -3564,14 +3532,14 @@ d86f_load(int drive, const wchar_t *fn) crc64 = 0xffffffffffffffff; - dev->filebuf = malloc(len); + dev->filebuf = mem_alloc(len); fread(dev->filebuf, 1, len, dev->f); *(uint64_t *) &(dev->filebuf[8]) = 0xffffffffffffffff; crc64 = (uint64_t) crc64speed(0, dev->filebuf, len); free(dev->filebuf); if (crc64 != read_crc64) { - d86f_log("86F: CRC64 error\n"); + ERRLOG("86F: CRC64 error\n"); fclose(dev->f); dev->f = NULL; free(dev); @@ -3579,6 +3547,7 @@ d86f_load(int drive, const wchar_t *fn) } #endif +#ifdef D86F_COMPRESS if (dev->is_compressed) { memcpy(temp_file_name, drive ? nvr_path(L"TEMP$$$1.$$$") : nvr_path(L"TEMP$$$0.$$$"), 256); memcpy(dev->original_file_name, fn, (wcslen(fn) << 1) + 2); @@ -3588,7 +3557,7 @@ d86f_load(int drive, const wchar_t *fn) dev->f = plat_fopen(temp_file_name, L"wb"); if (! dev->f) { - d86f_log("86F: Unable to create temporary decompressed file\n"); + ERRLOG("86F: Unable to create temporary decompressed file\n"); free(dev); return(0); } @@ -3600,8 +3569,8 @@ d86f_load(int drive, const wchar_t *fn) fwrite(&temp, 1, 2, dev->f); } - dev->filebuf = (uint8_t *) malloc(len); - dev->outbuf = (uint8_t *) malloc(67108864); + dev->filebuf = (uint8_t *) mem_alloc(len); + dev->outbuf = (uint8_t *) mem_alloc(67108864); fread(dev->filebuf, 1, len, tf); temp = lzf_decompress(dev->filebuf, len, dev->outbuf, 67108864); if (temp) { @@ -3615,7 +3584,7 @@ d86f_load(int drive, const wchar_t *fn) dev->f = NULL; if (! temp) { - d86f_log("86F: Error decompressing file\n"); + ERRLOG("86F: Error decompressing file\n"); plat_remove(temp_file_name); free(dev); return(0); @@ -3623,26 +3592,30 @@ d86f_load(int drive, const wchar_t *fn) dev->f = plat_fopen(temp_file_name, L"rb+"); } +#endif if (dev->disk_flags & 0x100) { /* Zoned disk. */ - d86f_log("86F: Disk is zoned (Apple or Sony)\n"); + ERRLOG("86F: Disk is zoned (Apple or Sony)\n"); fclose(dev->f); dev->f = NULL; - if (dev->is_compressed) { +#ifdef D86F_COMPRESS + if (dev->is_compressed) plat_remove(temp_file_name); - } +#endif free(dev); return(0); } if (dev->disk_flags & 0x600) { /* Zone type is not 0 but the disk is fixed-RPM. */ - d86f_log("86F: Disk is fixed-RPM but zone type is not 0\n"); + ERRLOG("86F: Disk is fixed-RPM but zone type is not 0\n"); fclose(dev->f); dev->f = NULL; +#ifdef D86F_COMPRESS if (dev->is_compressed) plat_remove(temp_file_name); +#endif free(dev); return(0); } @@ -3656,9 +3629,11 @@ d86f_load(int drive, const wchar_t *fn) fclose(dev->f); dev->f = NULL; +#ifdef D86F_COMPRESS if (dev->is_compressed) dev->f = plat_fopen(temp_file_name, L"rb"); else +#endif dev->f = plat_fopen(fn, L"rb"); } @@ -3671,7 +3646,7 @@ d86f_load(int drive, const wchar_t *fn) if (! (dev->track_offset[0])) { /* File has no track 0 side 0, abort. */ - d86f_log("86F: No Track 0 side 0\n"); + ERRLOG("86F: No Track 0 side 0\n"); fclose(dev->f); dev->f = NULL; free(dev); @@ -3681,7 +3656,7 @@ d86f_load(int drive, const wchar_t *fn) if ((d86f_get_sides(drive) == 2) && !(dev->track_offset[1])) { /* File is 2-sided but has no track 0 side 1, abort. */ - d86f_log("86F: No Track 0 side 1\n"); + ERRLOG("86F: No Track 0 side 1\n"); fclose(dev->f); dev->f = NULL; free(dev); @@ -3741,9 +3716,13 @@ d86f_load(int drive, const wchar_t *fn) d86f_common_handlers(drive); drives[drive].format = d86f_format; - d86f_log("86F: Disk is %scompressed and does%s have surface description data\n", +#ifdef D86F_COMPRESS + DEBUG("86F: Disk is %scompressed and does%s have surface description data\n", dev->is_compressed ? "" : "not ", +#else + DEBUG("86F: Disk does%s have surface description data\n", d86f_has_surface_desc(drive) ? "" : " not"); +#endif /* All good. */ return(1); @@ -3772,20 +3751,26 @@ d86f_set_fdc(void *fdc) void d86f_close(int drive) { - wchar_t temp_file_name[2048]; +#ifdef D86F_COMPRESS + wchar_t temp[2048]; +#endif d86f_t *dev = d86f[drive]; /* Make sure the drive is alive. */ if (dev == NULL) return; - memcpy(temp_file_name, drive ? nvr_path(L"TEMP$$$1.$$$") : nvr_path(L"TEMP$$$0.$$$"), 26); - if (dev->f) { fclose(dev->f); dev->f = NULL; } - if (dev->is_compressed) - plat_remove(temp_file_name); + +#ifdef D86F_COMPRESS + if (dev->is_compressed) { + memcpy(temp, drive ? nvr_path(L"TEMP$$$1.$$$") + : nvr_path(L"TEMP$$$0.$$$"), 26); + plat_remove(temp); + } +#endif } @@ -3796,7 +3781,7 @@ d86f_setup(int drive) d86f_t *dev; /* Allocate a drive structure. */ - dev = (d86f_t *)malloc(sizeof(d86f_t)); + dev = (d86f_t *)mem_alloc(sizeof(d86f_t)); memset(dev, 0x00, sizeof(d86f_t)); dev->state = STATE_IDLE; diff --git a/src/devices/floppy/fdd_common.c b/src/devices/floppy/fdd_common.c index fbc9c1d..dfab57d 100644 --- a/src/devices/floppy/fdd_common.c +++ b/src/devices/floppy/fdd_common.c @@ -8,7 +8,7 @@ * * Shared code for all the floppy modules. * - * Version: @(#)fdd_common.c 1.0.4 2018/05/06 + * Version: @(#)fdd_common.c 1.0.5 2018/09/13 * * Author: Fred N. van Kempen, * @@ -37,6 +37,7 @@ #include #include #include +#define dbglog fdd_log #include "../../emu.h" #include "fdd.h" #include "fdd_common.h" diff --git a/src/devices/floppy/fdd_fdi.c b/src/devices/floppy/fdd_fdi.c index 1ad62d8..9b754dc 100644 --- a/src/devices/floppy/fdd_fdi.c +++ b/src/devices/floppy/fdd_fdi.c @@ -9,7 +9,7 @@ * Implementation of the FDI floppy stream image format * interface to the FDI2RAW module. * - * Version: @(#)fdd_fdi.c 1.0.5 2018/05/14 + * Version: @(#)fdd_fdi.c 1.0.6 2018/09/22 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -42,6 +42,7 @@ #include #include #include +#define dbglog fdd_log #include "../../emu.h" #include "../../plat.h" #include "fdd.h" @@ -320,7 +321,7 @@ fdi_load(int drive, const wchar_t *fn) fdi_t *dev; /* Allocate a drive block. */ - dev = (fdi_t *)malloc(sizeof(fdi_t)); + dev = (fdi_t *)mem_alloc(sizeof(fdi_t)); memset(dev, 0x00, sizeof(fdi_t)); dev->f = plat_fopen(fn, L"rb"); @@ -338,7 +339,7 @@ fdi_load(int drive, const wchar_t *fn) header[25] = 0; if (strcmp(header, "Formatted Disk Image file") != 0) { /* This is a Japanese FDI file. */ - fdd_log("FDI: Japanese FDI file detected, redirecting to IMG loader\n"); + DEBUG("FDI: Japanese FDI file detected, redirecting to IMG loader\n"); fclose(dev->f); free(dev); return(img_load(drive, fn)); diff --git a/src/devices/floppy/fdd_imd.c b/src/devices/floppy/fdd_imd.c index 6fc9ec3..43bb941 100644 --- a/src/devices/floppy/fdd_imd.c +++ b/src/devices/floppy/fdd_imd.c @@ -8,7 +8,7 @@ * * Implementation of the IMD floppy image format. * - * Version: @(#)fdd_imd.c 1.0.9 2018/05/14 + * Version: @(#)fdd_imd.c 1.0.10 2018/10/05 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -39,6 +39,7 @@ #include #include #include +#define dbglog fdd_log #include "../../emu.h" #include "../../plat.h" #include "fdd.h" @@ -595,7 +596,7 @@ imd_load(int drive, const wchar_t *fn) d86f_unregister(drive); /* Allocate a drive block. */ - dev = (imd_t *)malloc(sizeof(imd_t)); + dev = (imd_t *)mem_alloc(sizeof(imd_t)); memset(dev, 0x00, sizeof(imd_t)); dev->f = plat_fopen(fn, L"rb+"); @@ -615,34 +616,34 @@ imd_load(int drive, const wchar_t *fn) fseek(dev->f, 0, SEEK_SET); fread(&magic, 1, 4, dev->f); if (magic != 0x20444D49) { - fdd_log("IMD: not a valid ImageDisk image\n"); + ERRLOG("IMD: not a valid ImageDisk image\n"); fclose(dev->f); free(dev);; return(0); } else { - fdd_log("IMD: valid ImageDisk image\n"); + DEBUG("IMD: valid ImageDisk image\n"); } fseek(dev->f, 0, SEEK_END); fsize = ftell(dev->f); fseek(dev->f, 0, SEEK_SET); - dev->buffer = malloc(fsize); + dev->buffer = (char *)mem_alloc(fsize); fread(dev->buffer, 1, fsize, dev->f); buffer = dev->buffer; buffer2 = strchr(buffer, 0x1A); if (buffer2 == NULL) { - fdd_log("IMD: no ASCII EOF found!\n"); + ERRLOG("IMD: no ASCII EOF found!\n"); fclose(dev->f); free(dev); return(0); } else { - fdd_log("IMD: ASCII EOF found at offset %08X\n", buffer2 - buffer); + DEBUG("IMD: ASCII EOF found at offset %08X\n", buffer2 - buffer); } buffer2++; if ((buffer2 - buffer) == fsize) { - fdd_log("IMD: file ends after ASCII EOF\n"); + ERRLOG("IMD: file ends after ASCII EOF\n"); fclose(dev->f); free(dev); return(0); @@ -757,7 +758,7 @@ imd_load(int drive, const wchar_t *fn) dev->disk_flags |= (3 << 5); if ((raw_tsize - track_total + (mfm ? 146 : 73)) < (minimum_gap3 + minimum_gap4)) { /* If we can't fit the sectors with a reasonable minimum gap even at 2% slower RPM, abort. */ - fdd_log("IMD: unable to fit the %i sectors in a track\n", track_spt); + ERRLOG("IMD: unable to fit the %i sectors in a track\n", track_spt); fclose(dev->f); free(dev); imd[drive] = NULL; diff --git a/src/devices/floppy/fdd_img.c b/src/devices/floppy/fdd_img.c index bf1bd6f..49b75a3 100644 --- a/src/devices/floppy/fdd_img.c +++ b/src/devices/floppy/fdd_img.c @@ -13,7 +13,7 @@ * re-merged with the other files. Much of it is generic to * all formats. * - * Version: @(#)fdd_img.c 1.0.12 2018/05/14 + * Version: @(#)fdd_img.c 1.0.13 2018/10/05 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -604,7 +604,7 @@ img_load(int drive, const wchar_t *fn) uint8_t bpb_mid; /* Media type ID. */ uint8_t bpb_sectors; uint8_t bpb_sides; - uint8_t cqm, fdf, fdi; + uint8_t cqm, ddi, fdf, fdi; uint16_t comment_len = 0; int16_t block_len = 0; uint32_t cur_pos = 0; @@ -625,7 +625,7 @@ img_load(int drive, const wchar_t *fn) d86f_unregister(drive); /* Allocate a drive block. */ - dev = (img_t *)malloc(sizeof(img_t)); + dev = (img_t *)mem_alloc(sizeof(img_t)); memset(dev, 0x00, sizeof(img_t)); dev->f = plat_fopen(fn, L"rb+"); @@ -644,13 +644,19 @@ img_load(int drive, const wchar_t *fn) fwriteprot[drive] = writeprot[drive]; /* Clear ALL subtypes. */ - cqm = fdf = fdi = 0; + cqm = ddi = fdf = fdi = 0; dev->interleave = dev->skew = 0; + if (! wcscasecmp(ext, L"DDI")) { + ddi = 1; + dev->base = 0x2400; + } else + dev->base = 0; + if (! wcscasecmp(ext, L"FDI")) { /* This is a Japanese FDI image, so let's read the header */ - fdd_log("FDD: image file type is Japanese FDI\n"); + DEBUG("FDD: image file type is Japanese FDI\n"); fseek(dev->f, 0x10, SEEK_SET); (void)fread(&bpb_bps, 1, 2, dev->f); fseek(dev->f, 0x0C, SEEK_SET); @@ -685,7 +691,7 @@ img_load(int drive, const wchar_t *fn) if ((first_byte == 0x1A) && (second_byte == 'F') && (third_byte == 'D') && (fourth_byte == 'F')) { /* This is a FDF image. */ - fdd_log("FDD: image file type is FDF\n"); + DEBUG("FDD: image file type is FDF\n"); fwriteprot[drive] = writeprot[drive] = 1; fclose(dev->f); dev->f = plat_fopen(fn, L"rb"); @@ -706,10 +712,10 @@ img_load(int drive, const wchar_t *fn) /* Skip first 3 bytes - their meaning is unknown to us but could be a checksum. */ first_byte = fgetc(dev->f); fread(&track_bytes, 1, 2, dev->f); - fdd_log("FDD: block header: %02X %04X ", first_byte, track_bytes); + DEBUG("FDD: block header: %02X %04X ", first_byte, track_bytes); /* Read the length of encoded data block. */ fread(&track_bytes, 1, 2, dev->f); - fdd_log("%04X\n", track_bytes); + DEBUG("%04X\n", track_bytes); } if (feof(dev->f)) break; @@ -729,7 +735,7 @@ img_load(int drive, const wchar_t *fn) } else { /* Literal. */ track_bytes -= (run & 0x7f); - literal = (uint8_t *)malloc(run & 0x7f); + literal = (uint8_t *)mem_alloc(run & 0x7f); fread(literal, 1, (run & 0x7f), dev->f); free(literal); } @@ -739,7 +745,7 @@ img_load(int drive, const wchar_t *fn) } else { /* Literal block. */ size += (track_bytes - fdf_suppress_final_byte); - literal = (uint8_t *)malloc(track_bytes); + literal = (uint8_t *)mem_alloc(track_bytes); fread(literal, 1, track_bytes, dev->f); free(literal); track_bytes = 0; @@ -749,7 +755,7 @@ img_load(int drive, const wchar_t *fn) } /* Allocate the buffer. */ - dev->disk_data = (uint8_t *)malloc(size); + dev->disk_data = (uint8_t *)mem_alloc(size); /* Decode the entire file - pass 2, write to buffer. */ fseek(dev->f, 0x80, SEEK_SET); @@ -760,10 +766,10 @@ img_load(int drive, const wchar_t *fn) /* Skip first 3 bytes - their meaning is unknown to us but could be a checksum. */ first_byte = fgetc(dev->f); fread(&track_bytes, 1, 2, dev->f); - fdd_log("FDD: block header: %02X %04X ", first_byte, track_bytes); + DEBUG("FDD: block header: %02X %04X ", first_byte, track_bytes); /* Read the length of encoded data block. */ fread(&track_bytes, 1, 2, dev->f); - fdd_log("%04X\n", track_bytes); + DEBUG("%04X\n", track_bytes); } if (feof(dev->f)) break; @@ -788,7 +794,7 @@ img_load(int drive, const wchar_t *fn) } else { /* Literal. */ track_bytes -= real_run; - literal = (uint8_t *) malloc(real_run); + literal = (uint8_t *) mem_alloc(real_run); fread(literal, 1, real_run, dev->f); if (! track_bytes) real_run -= fdf_suppress_final_byte; @@ -799,7 +805,7 @@ img_load(int drive, const wchar_t *fn) bpos += real_run; } else { /* Literal block. */ - literal = (uint8_t *) malloc(track_bytes); + literal = (uint8_t *) mem_alloc(track_bytes); fread(literal, 1, track_bytes, dev->f); memcpy(bpos, literal, track_bytes - fdf_suppress_final_byte); free(literal); @@ -824,7 +830,7 @@ img_load(int drive, const wchar_t *fn) if (((first_byte == 'C') && (second_byte == 'Q')) || ((first_byte == 'c') && (second_byte == 'q'))) { - fdd_log("FDD: image file type is CopyQM\n"); + DEBUG("FDD: image file type is CopyQM\n"); fwriteprot[drive] = writeprot[drive] = 1; fclose(dev->f); dev->f = plat_fopen(fn, L"rb"); @@ -849,7 +855,7 @@ img_load(int drive, const wchar_t *fn) fseek(dev->f, 0x76, SEEK_SET); dev->skew = fgetc(dev->f); - dev->disk_data = (uint8_t *) malloc(((uint32_t) bpb_total) * ((uint32_t) bpb_bps)); + dev->disk_data = (uint8_t *) mem_alloc(((uint32_t) bpb_total) * ((uint32_t) bpb_bps)); memset(dev->disk_data, 0xf6, ((uint32_t) bpb_total) * ((uint32_t) bpb_bps)); fseek(dev->f, 0x6F, SEEK_SET); @@ -894,33 +900,41 @@ img_load(int drive, const wchar_t *fn) dev->disk_at_once = 1; first_byte = *dev->disk_data; } else { - fdd_log("FDD: image file type is RAW\n"); + if (ddi) { + DEBUG("FDD: image file is DDI\n"); + fwriteprot[drive] = writeprot[drive] = 1; + } else + DEBUG("FDD: image file type is RAW\n"); + dev->disk_at_once = 0; /* Read the BPB */ - fseek(dev->f, 0x0B, SEEK_SET); + fseek(dev->f, dev->base + 0x0B, SEEK_SET); fread(&bpb_bps, 1, 2, dev->f); - fseek(dev->f, 0x13, SEEK_SET); + fseek(dev->f, dev->base + 0x13, SEEK_SET); fread(&bpb_total, 1, 2, dev->f); - fseek(dev->f, 0x15, SEEK_SET); + fseek(dev->f, dev->base + 0x15, SEEK_SET); bpb_mid = fgetc(dev->f); - fseek(dev->f, 0x18, SEEK_SET); + fseek(dev->f, dev->base + 0x18, SEEK_SET); bpb_sectors = fgetc(dev->f); - fseek(dev->f, 0x1A, SEEK_SET); + fseek(dev->f, dev->base + 0x1A, SEEK_SET); bpb_sides = fgetc(dev->f); } fseek(dev->f, -1, SEEK_END); size = ftell(dev->f) + 1; + if (ddi) + size -= 0x2400; jump_if_fdf: - dev->base = 0; + if (! ddi) + dev->base = 0; } dev->sides = 2; dev->sector_size = 2; - fdd_log("FDD: BPB reports %i sides, %i bytes per sector (%i sectors total)\n", + DEBUG("FDD: BPB reports %i sides, %i bytes per sector (%i sectors total)\n", bpb_sides, bpb_bps, bpb_total); guess = (bpb_sides < 1); @@ -1046,7 +1060,7 @@ jump_if_fdf: dev->sectors = 42; dev->tracks = 86; } else { - fdd_log("FDD: image file size too large; ejecting\n"); + ERRLOG("FDD: image file size too large; ejecting\n"); fclose(dev->f); free(dev); return(0); @@ -1095,13 +1109,13 @@ jump_if_fdf: dev->dmf = 0; } - fdd_log("FDD: image parameters: bit rate 300: %f, temporary rate: %i, hole: %i, DMF: %i, XDF type: %i\n", bit_rate_300, temp_rate, dev->disk_flags >> 1, dev->dmf, dev->xdf_type); + DEBUG("FDD: image parameters: bit rate 300: %f, temporary rate: %i, hole: %i, DMF: %i, XDF type: %i\n", bit_rate_300, temp_rate, dev->disk_flags >> 1, dev->dmf, dev->xdf_type); break; } } if (temp_rate == 0xFF) { - fdd_log("FDD: invalid media configuration; ejecting\n"); + ERRLOG("FDD: invalid media configuration; ejecting\n"); fclose(dev->f); free(dev); return(0); @@ -1113,7 +1127,7 @@ jump_if_fdf: else dev->gap3_size = gap3_sizes[temp_rate][dev->sector_size][dev->sectors]; if (! dev->gap3_size) { - fdd_log("FDD: unknown media format in drive %c:\n", drive + 0x41); + ERRLOG("FDD: unknown media format in drive %c:\n", drive + 0x41); fclose(dev->f); free(dev); return(0); @@ -1136,8 +1150,8 @@ jump_if_fdf: dev->is_cqm = cqm; - fdd_log("FDD: disk flags: %02x, track flags: %02x\n", - dev->disk_flags, dev->track_flags); + DEBUG("FDD: disk flags: %02x, track flags: %02x\n", + dev->disk_flags, dev->track_flags); /* Set up the drive unit. */ img[drive] = dev; diff --git a/src/devices/floppy/fdd_json.c b/src/devices/floppy/fdd_json.c index 81dc37a..b5be261 100644 --- a/src/devices/floppy/fdd_json.c +++ b/src/devices/floppy/fdd_json.c @@ -8,7 +8,7 @@ * * Implementation of the PCjs JSON floppy image format. * - * Version: @(#)fdd_json.c 1.0.7 2018/05/14 + * Version: @(#)fdd_json.c 1.0.8 2018/10/05 * * Author: Fred N. van Kempen, * @@ -49,6 +49,7 @@ #include #include #include +#define dbglog fdd_log #include "../../emu.h" #include "../../plat.h" #include "fdd.h" @@ -120,7 +121,7 @@ handle(json_t *dev, char *name, char *str) if (name == NULL) { /* If no buffer, assume one with 00's. */ if (sec->data == NULL) { - sec->data = (uint8_t *)malloc(sec->size); + sec->data = (uint8_t *)mem_alloc(sec->size); memset(sec->data, 0x00, sec->size); } @@ -143,7 +144,7 @@ handle(json_t *dev, char *name, char *str) pat = atol(str); if (sec->data == NULL) - sec->data = (uint8_t *)malloc(sec->size); + sec->data = (uint8_t *)mem_alloc(sec->size); p = sec->data; s = (sec->size / sizeof(uint32_t)); for (i=0; idata == NULL) - sec->data = (uint8_t *)malloc(sec->size); + sec->data = (uint8_t *)mem_alloc(sec->size); p = sec->data; while (str && *str) { sp = strchr(str, ','); @@ -182,7 +183,7 @@ handle(json_t *dev, char *name, char *str) static int unexpect(int c, int state, int level) { - fdd_log("JSON: unexpected '%c' in state %d/%d.\n", c, state, level); + ERRLOG("JSON: unexpected '%c' in state %d/%d.\n", c, state, level); return(-1); } @@ -196,7 +197,7 @@ load_image(json_t *dev) char *ptr; if (dev->f == NULL) { - fdd_log("JSON: no file loaded!\n"); + ERRLOG("JSON: no file loaded!\n"); return(0); } @@ -373,7 +374,7 @@ json_seek(int drive, int track) int interleave_type; if (dev->f == NULL) { - fdd_log("JSON: seek: no file loaded!\n"); + ERRLOG("JSON: seek: no file loaded!\n"); return; } @@ -397,15 +398,15 @@ json_seek(int drive, int track) return; } - for (side=0; sidesides; side++) { + for (side = 0; side < dev->sides; side++) { /* Get transfer rate for this side. */ rate = dev->track_flags & 0x07; if (!rate && (dev->track_flags & 0x20)) rate = 4; /* Get correct GAP3 value for this side. */ gap3 = fdd_get_gap3_size(rate, - dev->sects[track][side][0].size, - dev->spt[track][side]); + dev->sects[track][side][0].size, + dev->spt[track][side]); /* Get correct GAP2 value for this side. */ gap2 = ((dev->track_flags & 0x07) >= 3) ? 41 : 22; @@ -424,7 +425,7 @@ json_seek(int drive, int track) id[1] = side; id[2] = rsec; if (dev->sects[track][side][asec].size > 255) - perror("fdd_json.c: json_seek: sector size too big."); + ERRLOG("JSON: seek: sector size too big."); id[3] = dev->sects[track][side][asec].size & 0xff; ssize = fdd_sector_code_size(dev->sects[track][side][asec].size & 0xff); @@ -517,7 +518,7 @@ json_load(int drive, const wchar_t *fn) d86f_unregister(drive); /* Allocate a drive block. */ - dev = (json_t *)malloc(sizeof(json_t)); + dev = (json_t *)mem_alloc(sizeof(json_t)); memset(dev, 0x00, sizeof(json_t)); /* Open the image file. */ @@ -535,15 +536,15 @@ json_load(int drive, const wchar_t *fn) /* Load all sectors from the image file. */ if (! load_image(dev)) { - fdd_log("JSON: failed to initialize\n"); + ERRLOG("JSON: failed to initialize\n"); (void)fclose(dev->f); free(dev); images[drive] = NULL; return(0); } - fdd_log("JSON(%d): %ls (%i tracks, %i sides, %i sectors)\n", - drive, fn, dev->tracks, dev->sides, dev->spt[0][0]); + DEBUG("JSON(%d): %ls (%i tracks, %i sides, %i sectors)\n", + drive, fn, dev->tracks, dev->sides, dev->spt[0][0]); /* * If the image has more than 43 tracks, then @@ -599,7 +600,7 @@ json_load(int drive, const wchar_t *fn) } if (temp_rate == 0xff) { - fdd_log("JSON: invalid image (temp_rate=0xff)\n"); + ERRLOG("JSON: invalid image (temp_rate=0xff)\n"); (void)fclose(dev->f); dev->f = NULL; free(dev); @@ -619,8 +620,8 @@ json_load(int drive, const wchar_t *fn) dev->gap3_len = fdd_get_gap3_size(temp_rate,sec->size,dev->spt[0][0]); if (! dev->gap3_len) { - fdd_log("JSON: image of unknown format was inserted into drive %c:!\n", - 'C'+drive); + ERRLOG("JSON: image of unknown format was inserted into drive %c:!\n", + 'A'+drive); (void)fclose(dev->f); dev->f = NULL; free(dev); @@ -632,10 +633,10 @@ json_load(int drive, const wchar_t *fn) if (temp_rate & 0x04) dev->track_flags |= 0x20; /* RPM */ - fdd_log(" disk_flags: 0x%02x, track_flags: 0x%02x, GAP3 length: %i\n", - dev->disk_flags, dev->track_flags, dev->gap3_len); - fdd_log(" bit rate 300: %.2f, temporary rate: %i, hole: %i, DMF: %i\n", - bit_rate, temp_rate, (dev->disk_flags >> 1), dev->dmf); + DEBUG(" disk_flags: 0x%02x, track_flags: 0x%02x, GAP3 length: %i\n", + dev->disk_flags, dev->track_flags, dev->gap3_len); + DEBUG(" bit rate 300: %.2f, temporary rate: %i, hole: %i, DMF: %i\n", + bit_rate, temp_rate, (dev->disk_flags >> 1), dev->dmf); /* Set up handlers for 86F layer. */ d86f_handler[drive].disk_flags = disk_flags; diff --git a/src/devices/floppy/fdd_td0.c b/src/devices/floppy/fdd_td0.c index 4061433..2c8f823 100644 --- a/src/devices/floppy/fdd_td0.c +++ b/src/devices/floppy/fdd_td0.c @@ -8,7 +8,7 @@ * * Implementation of the Teledisk floppy image format. * - * Version: @(#)fdd_td0.c 1.0.8 2018/05/14 + * Version: @(#)fdd_td0.c 1.0.9 2018/10/05 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -51,6 +51,7 @@ #include #include #include +#define dbglog fdd_log #include "../../emu.h" #include "../../plat.h" #include "fdd.h" @@ -611,7 +612,7 @@ td0_initialize(int drive) int i, j, k; if (dev->f == NULL) { - fdd_log("TD0: attempted to initialize without loading a file first\n"); + ERRLOG("TD0: attempted to initialize without loading a file first\n"); return(0); } @@ -619,12 +620,12 @@ td0_initialize(int drive) file_size = ftell(dev->f); if (file_size < 12) { - fdd_log("TD0: file is too small to even contain the header\n"); + ERRLOG("TD0: file is too small to even contain the header\n"); return(0); } if (file_size > TD0_MAX_BUFSZ) { - fdd_log("TD0: file exceeds the maximum size\n"); + ERRLOG("TD0: file exceeds the maximum size\n"); return(0); } @@ -633,13 +634,13 @@ td0_initialize(int drive) head_count = header[9]; if (header[0] == 't') { - fdd_log("TD0: file is compressed\n"); + DEBUG("TD0: file is compressed\n"); disk_decode.fdd_file = dev->f; state_init_Decode(&disk_decode); disk_decode.fdd_file_offset = 12; state_Decode(&disk_decode, dev->imagebuf, TD0_MAX_BUFSZ); } else { - fdd_log("TD0: file is uncompressed\n"); + DEBUG("TD0: file is uncompressed\n"); fseek(dev->f, 12, SEEK_SET); fread(dev->imagebuf, 1, file_size - 12, dev->f); } @@ -650,14 +651,14 @@ td0_initialize(int drive) track_spt = dev->imagebuf[offset]; if (track_spt == 255) { /* Empty file? */ - fdd_log("TD0: file has no tracks\n"); + ERRLOG("TD0: file has no tracks\n"); return(0); } density = (header[5] >> 1) & 3; if (density == 3) { - fdd_log("TD0: unknown density\n"); + ERRLOG("TD0: unknown density\n"); return(0); } @@ -725,7 +726,7 @@ td0_initialize(int drive) size = 128 << hs[3]; if ((total_size + size) >= TD0_MAX_BUFSZ) { - fdd_log("TD0: processed buffer overflow\n"); + ERRLOG("TD0: processed buffer overflow\n"); return(0); } @@ -735,7 +736,7 @@ td0_initialize(int drive) offset += 3; switch (hs[8]) { default: - fdd_log("TD0: image uses an unsupported sector data encoding\n"); + ERRLOG("TD0: image uses an unsupported sector data encoding\n"); return(0); case 0: @@ -803,7 +804,7 @@ td0_initialize(int drive) dev->disk_flags |= (3 << 5); if ((raw_tsize - track_size + (fm ? 73 : 146)) < (minimum_gap3 + minimum_gap4)) { /* If we can't fit the sectors with a reasonable minimum gap even at 2% slower RPM, abort. */ - fdd_log("TD0: unable to fit the %i sectors in a track\n", track_spt); + ERRLOG("TD0: unable to fit the %i sectors in a track\n", track_spt); return 0; } } @@ -814,7 +815,7 @@ td0_initialize(int drive) } if ((dev->disk_flags & 0x60) == 0x60) - fdd_log("TD0: disk will rotate 2% below perfect RPM\n"); + DEBUG("TD0: disk will rotate 2% below perfect RPM\n"); dev->tracks = track_count + 1; @@ -836,7 +837,7 @@ td0_initialize(int drive) dev->current_side_flags[0] = dev->side_flags[0][0]; dev->current_side_flags[1] = dev->side_flags[0][1]; - fdd_log("TD0: file loaded: %i tracks, %i sides, disk flags: %02X, side flags: %02X, %02X, GAP3 length: %02X\n", dev->tracks, dev->sides, dev->disk_flags, dev->current_side_flags[0], dev->current_side_flags[1], dev->gap3_len); + DEBUG("TD0: file loaded: %i tracks, %i sides, disk flags: %02X, side flags: %02X, %02X, GAP3 length: %02X\n", dev->tracks, dev->sides, dev->disk_flags, dev->current_side_flags[0], dev->current_side_flags[1], dev->gap3_len); return(1); } @@ -1123,7 +1124,7 @@ td0_load(int drive, const wchar_t *fn) writeprot[drive] = 1; - dev = (td0_t *)malloc(sizeof(td0_t)); + dev = (td0_t *)mem_alloc(sizeof(td0_t)); memset(dev, 0x00, sizeof(td0_t)); td0[drive] = dev; @@ -1135,23 +1136,23 @@ td0_load(int drive, const wchar_t *fn) fwriteprot[drive] = writeprot[drive]; if (! dsk_identify(drive)) { - fdd_log("TD0: not a valid Teledisk image\n"); + ERRLOG("TD0: not a valid Teledisk image\n"); fclose(dev->f); dev->f = NULL; return(0); } else { - fdd_log("TD0: valid Teledisk image\n"); + DEBUG("TD0: valid Teledisk image\n"); } /* Allocate the processing buffers. */ i = 1024UL * 1024UL * 4UL; - dev->imagebuf = (uint8_t *)malloc(i); + dev->imagebuf = (uint8_t *)mem_alloc(i); memset(dev->imagebuf, 0x00, i); - dev->processed_buf = (uint8_t *)malloc(i); + dev->processed_buf = (uint8_t *)mem_alloc(i); memset(dev->processed_buf, 0x00, i); if (! td0_initialize(drive)) { - fdd_log("TD0: failed to initialize\n"); + ERRLOG("TD0: failed to initialize\n"); fclose(dev->f); free(dev->imagebuf); free(dev->processed_buf); diff --git a/src/devices/floppy/fdi2raw.c b/src/devices/floppy/fdi2raw.c index 9601b6b..3c64ef9 100644 --- a/src/devices/floppy/fdi2raw.c +++ b/src/devices/floppy/fdi2raw.c @@ -12,7 +12,7 @@ * addition of get_last_head and C++ callability by Thomas * Harte. * - * Version: @(#)fdi2raw.c 1.0.4 2018/05/06 + * Version: @(#)fdi2raw.c 1.0.5 2018/09/22 * * Authors: Toni Wilen, * and Vincent Joguin, @@ -46,14 +46,14 @@ #include #include #include +#define dbglog fdd_log #include "../../emu.h" +#include "fdd.h" +#include "fdc.h" #include "fdi2raw.h" -#undef _DEBUG - - -#ifdef _DEBUG +#ifdef _LOGGING static char *datalog(uae_u8 *src, int len) { static char buf[1000]; @@ -63,7 +63,7 @@ static char *datalog(uae_u8 *src, int len) offset2 = offset; buf[offset++]='\''; while(len--) { - sprintf (buf + offset, "%02.2X", src[i]); + sprintf (buf + offset, "%02X", src[i]); offset += 2; i++; if (i > 10) break; @@ -73,15 +73,13 @@ static char *datalog(uae_u8 *src, int len) if (offset >= 900) offset = 0; return buf + offset2; } -#else -static char *datalog(uae_u8 *src, int len) { return ""; } #endif -#define outlog pclog -#define debuglog pclog -static int fdi_allocated; #ifdef _DEBUG +static int fdi_allocated; + + static void fdi_free (void *p) { int size; @@ -89,20 +87,21 @@ static void fdi_free (void *p) return; size = ((int*)p)[-1]; fdi_allocated -= size; - write_log ("%d freed (%d)\n", size, fdi_allocated); + DEBUG("FDI2RAW: %d freed (%d)\n", size, fdi_allocated); free ((int*)p - 1); } + static void *fdi_malloc (int size) { - void *p = malloc (size + sizeof (int)); + void *p = mem_alloc (size + sizeof (int)); ((int*)p)[0] = size; fdi_allocated += size; - write_log ("%d allocated (%d)\n", size, fdi_allocated); + DEBUG("FDI2RAW: %d allocated (%d)\n", size, fdi_allocated); return (int*)p + 1; } #else -#define fdi_free free -#define fdi_malloc malloc +# define fdi_free free +# define fdi_malloc mem_alloc #endif #define MAX_SRC_BUFFER 4194304 @@ -190,10 +189,10 @@ static uae_u8 *expand_tree (uae_u8 *stream, NODE *node) temp = *stream++; temp2 = 0x80; } - node->left = fdi_malloc (sizeof (NODE)); + node->left = (NODE *)fdi_malloc (sizeof (NODE)); memset (node->left, 0, sizeof (NODE)); stream_temp = expand_tree (stream, node->left); - node->right = fdi_malloc (sizeof (NODE)); + node->right = (NODE *)fdi_malloc (sizeof (NODE)); memset (node->right, 0, sizeof (NODE)); return expand_tree (stream_temp, node->right); } @@ -324,13 +323,13 @@ static int decode_raw_track (FDI *fdi) /* unknown track */ static void zxx (FDI *fdi) { - outlog ("track %d: unknown track type 0x%02.2X\n", fdi->current_track, fdi->track_type); + DEBUG("FDI2RAW: track %d: unknown track type 0x%02.2X\n", fdi->current_track, fdi->track_type); } /* unsupported track */ #if 0 static void zyy (FDI *fdi) { - outlog ("track %d: unsupported track type 0x%02.2X\n", fdi->current_track, fdi->track_type); + DEBUG("FDI2RAW: track %d: unsupported track type 0x%02.2X\n", fdi->current_track, fdi->track_type); } #endif /* empty track */ @@ -342,14 +341,14 @@ static void track_empty (FDI *fdi) /* unknown sector described type */ static void dxx (FDI *fdi) { - outlog ("\ntrack %d: unknown sector described type 0x%02.2X\n", fdi->current_track, fdi->track_type); + DEBUG("\ntrack %d: unknown sector described type 0x%02.2X\n", fdi->current_track, fdi->track_type); fdi->err = 1; } /* unsupported sector described type */ #if 0 static void dyy (FDI *fdi) { - outlog ("\ntrack %d: unsupported sector described 0x%02.2X\n", fdi->current_track, fdi->track_type); + DEBUG("\ntrack %d: unsupported sector described 0x%02.2X\n", fdi->current_track, fdi->track_type); fdi->err = 1; } #endif @@ -362,12 +361,12 @@ static void add_mfm_sync_bit (FDI *fdi) } fdi->mfmsync_buffer[fdi->mfmsync_offset++] = fdi->out; if (fdi->out == 0) { - outlog ("illegal position for mfm sync bit, offset=%d\n",fdi->out); + DEBUG("illegal position for mfm sync bit, offset=%d\n",fdi->out); fdi->err = 1; } if (fdi->mfmsync_offset >= MAX_MFM_SYNC_BUFFER) { fdi->mfmsync_offset = 0; - outlog ("mfmsync buffer overflow\n"); + DEBUG("mfmsync buffer overflow\n"); fdi->err = 1; } fdi->out++; @@ -388,7 +387,7 @@ static void bit_add (FDI *fdi, int bit) fdi->track_dst[BIT_BYTEOFFSET] |= (1 << BIT_BITOFFSET); fdi->out++; if (fdi->out >= MAX_DST_BUFFER * 8) { - outlog ("destination buffer overflow\n"); + DEBUG("destination buffer overflow\n"); fdi->err = 1; fdi->out = 1; } @@ -403,13 +402,13 @@ static void bit_mfm_add (FDI *fdi, int bit) static void bit_drop_next (FDI *fdi) { if (fdi->nextdrop > 0) { - outlog("multiple bit_drop_next() called"); + DEBUG("multiple bit_drop_next() called"); } else if (fdi->nextdrop < 0) { fdi->nextdrop = 0; - debuglog(":DNN:"); + DEBUG(":DNN:"); return; } - debuglog(":DN:"); + DEBUG(":DN:"); fdi->nextdrop = 1; } @@ -417,10 +416,10 @@ static void bit_drop_next (FDI *fdi) static void bit_dedrop (FDI *fdi) { if (fdi->nextdrop) { - outlog("bit_drop_next called before bit_dedrop"); + DEBUG("bit_drop_next called before bit_dedrop"); } fdi->nextdrop = -1; - debuglog(":BDD:"); + DEBUG(":BDD:"); } /* add one byte */ @@ -473,7 +472,7 @@ static void s08(FDI *fdi) int bytes = *fdi->track_src++; uae_u8 byte = *fdi->track_src++; if (bytes == 0) bytes = 256; - debuglog ("s08:len=%d,data=%02.2X",bytes,byte); + DEBUG("s08:len=%d,data=%02.2X",bytes,byte); while(bytes--) byte_add (fdi, byte); } /* RLE MFM-decoded data */ @@ -483,7 +482,7 @@ static void s09(FDI *fdi) uae_u8 byte = *fdi->track_src++; if (bytes == 0) bytes = 256; bit_drop_next (fdi); - debuglog ("s09:len=%d,data=%02.2X",bytes,byte); + DEBUG("s09:len=%d,data=%02.2X",bytes,byte); while(bytes--) byte_mfm_add (fdi, byte); } /* MFM-encoded data */ @@ -492,7 +491,7 @@ static void s0a(FDI *fdi) int i, bits = (fdi->track_src[0] << 8) | fdi->track_src[1]; uae_u8 b; fdi->track_src += 2; - debuglog ("s0a:bits=%d,data=%s", bits, datalog(fdi->track_src, (bits + 7) / 8)); + DEBUG("s0a:bits=%d,data=%s", bits, datalog(fdi->track_src, (bits + 7) / 8)); while (bits >= 8) { byte_add (fdi, *fdi->track_src++); bits -= 8; @@ -512,7 +511,7 @@ static void s0b(FDI *fdi) int i, bits = ((fdi->track_src[0] << 8) | fdi->track_src[1]) + 65536; uae_u8 b; fdi->track_src += 2; - debuglog ("s0b:bits=%d,data=%s", bits, datalog(fdi->track_src, (bits + 7) / 8)); + DEBUG("s0b:bits=%d,data=%s", bits, datalog(fdi->track_src, (bits + 7) / 8)); while (bits >= 8) { byte_add (fdi, *fdi->track_src++); bits -= 8; @@ -533,7 +532,7 @@ static void s0c(FDI *fdi) uae_u8 b; fdi->track_src += 2; bit_drop_next (fdi); - debuglog ("s0c:bits=%d,data=%s", bits, datalog(fdi->track_src, (bits + 7) / 8)); + DEBUG("s0c:bits=%d,data=%s", bits, datalog(fdi->track_src, (bits + 7) / 8)); while (bits >= 8) { byte_mfm_add (fdi, *fdi->track_src++); bits -= 8; @@ -554,7 +553,7 @@ static void s0d(FDI *fdi) uae_u8 b; fdi->track_src += 2; bit_drop_next (fdi); - debuglog ("s0d:bits=%d,data=%s", bits, datalog(fdi->track_src, (bits + 7) / 8)); + DEBUG("s0d:bits=%d,data=%s", bits, datalog(fdi->track_src, (bits + 7) / 8)); while (bits >= 8) { byte_mfm_add (fdi, *fdi->track_src++); bits -= 8; @@ -875,7 +874,7 @@ static void amiga_sector_header (FDI *fdi, uae_u8 *header, uae_u8 *data, int sec static void s20(FDI *fdi) { bit_drop_next (fdi); - debuglog ("s20:header=%s,data=%s", datalog(fdi->track_src, 4), datalog(fdi->track_src + 4, 16)); + DEBUG("s20:header=%s,data=%s", datalog(fdi->track_src, 4), datalog(fdi->track_src + 4, 16)); amiga_sector_header (fdi, fdi->track_src, fdi->track_src + 4, 0, 0); fdi->track_src += 4 + 16; } @@ -883,7 +882,7 @@ static void s20(FDI *fdi) static void s21(FDI *fdi) { bit_drop_next (fdi); - debuglog ("s21:header=%s", datalog(fdi->track_src, 4)); + DEBUG("s21:header=%s", datalog(fdi->track_src, 4)); amiga_sector_header (fdi, fdi->track_src, 0, 0, 0); fdi->track_src += 4; } @@ -891,14 +890,14 @@ static void s21(FDI *fdi) static void s22(FDI *fdi) { bit_drop_next (fdi); - debuglog("s22:sector=%d,untilgap=%d", fdi->track_src[0], fdi->track_src[1]); + DEBUG("s22:sector=%d,untilgap=%d", fdi->track_src[0], fdi->track_src[1]); amiga_sector_header (fdi, 0, 0, fdi->track_src[0], fdi->track_src[1]); fdi->track_src += 2; } /* standard 512-byte, CRC-correct Amiga data */ static void s23(FDI *fdi) { - debuglog("s23:data=%s", datalog (fdi->track_src, 512)); + DEBUG("s23:data=%s", datalog (fdi->track_src, 512)); amiga_data (fdi, fdi->track_src); fdi->track_src += 512; } @@ -906,7 +905,7 @@ static void s23(FDI *fdi) static void s24(FDI *fdi) { int shift = *fdi->track_src++; - debuglog("s24:shift=%d,data=%s", shift, datalog (fdi->track_src, 128 << shift)); + DEBUG("s24:shift=%d,data=%s", shift, datalog (fdi->track_src, 128 << shift)); amiga_data_raw (fdi, fdi->track_src, 0, 128 << shift); fdi->track_src += 128 << shift; } @@ -914,7 +913,7 @@ static void s24(FDI *fdi) static void s25(FDI *fdi) { int shift = *fdi->track_src++; - debuglog("s25:shift=%d,crc=%s,data=%s", shift, datalog (fdi->track_src, 4), datalog (fdi->track_src + 4, 128 << shift)); + DEBUG("s25:shift=%d,crc=%s,data=%s", shift, datalog (fdi->track_src, 4), datalog (fdi->track_src + 4, 128 << shift)); amiga_data_raw (fdi, fdi->track_src + 4, fdi->track_src, 128 << shift); fdi->track_src += 4 + (128 << shift); } @@ -922,7 +921,7 @@ static void s25(FDI *fdi) static void s26(FDI *fdi) { s21 (fdi); - debuglog("s26:data=%s", datalog (fdi->track_src, 512)); + DEBUG("s26:data=%s", datalog (fdi->track_src, 512)); amiga_data (fdi, fdi->track_src); fdi->track_src += 512; } @@ -930,7 +929,7 @@ static void s26(FDI *fdi) static void s27(FDI *fdi) { s22 (fdi); - debuglog("s27:data=%s", datalog (fdi->track_src, 512)); + DEBUG("s27:data=%s", datalog (fdi->track_src, 512)); amiga_data (fdi, fdi->track_src); fdi->track_src += 512; } @@ -1051,14 +1050,14 @@ static void s12(FDI *fdi) static void s13(FDI *fdi) { bit_drop_next (fdi); - debuglog ("s13:header=%s", datalog (fdi->track_src, 4)); + DEBUG("s13:header=%s", datalog (fdi->track_src, 4)); ibm_sector_header (fdi, fdi->track_src, 0, -1, 1); fdi->track_src += 4; } /* standard mini-extended IBM sector header */ static void s14(FDI *fdi) { - debuglog ("s14:header=%s", datalog (fdi->track_src, 4)); + DEBUG("s14:header=%s", datalog (fdi->track_src, 4)); ibm_sector_header (fdi, fdi->track_src, 0, -1, 0); fdi->track_src += 4; } @@ -1066,33 +1065,33 @@ static void s14(FDI *fdi) static void s15(FDI *fdi) { bit_drop_next (fdi); - debuglog ("s15:sector=%d", *fdi->track_src); + DEBUG("s15:sector=%d", *fdi->track_src); ibm_sector_header (fdi, 0, 0, *fdi->track_src++, 1); } /* standard mini-short IBM sector header */ static void s16(FDI *fdi) { - debuglog ("s16:track=%d", *fdi->track_src); + DEBUG("s16:track=%d", *fdi->track_src); ibm_sector_header (fdi, 0, 0, *fdi->track_src++, 0); } /* standard CRC-incorrect mini-extended IBM sector header */ static void s17(FDI *fdi) { - debuglog ("s17:header=%s,crc=%s", datalog (fdi->track_src, 4), datalog (fdi->track_src + 4, 2)); + DEBUG("s17:header=%s,crc=%s", datalog (fdi->track_src, 4), datalog (fdi->track_src + 4, 2)); ibm_sector_header (fdi, fdi->track_src, fdi->track_src + 4, -1, 0); fdi->track_src += 4 + 2; } /* standard CRC-incorrect mini-short IBM sector header */ static void s18(FDI *fdi) { - debuglog ("s18:sector=%d,header=%s", *fdi->track_src, datalog (fdi->track_src + 1, 4)); + DEBUG("s18:sector=%d,header=%s", *fdi->track_src, datalog (fdi->track_src + 1, 4)); ibm_sector_header (fdi, 0, fdi->track_src + 1, *fdi->track_src, 0); fdi->track_src += 1 + 4; } /* standard 512-byte CRC-correct IBM data */ static void s19(FDI *fdi) { - debuglog ("s19:data=%s", datalog (fdi->track_src , 512)); + DEBUG("s19:data=%s", datalog (fdi->track_src , 512)); ibm_data (fdi, fdi->track_src, 0, 512); fdi->track_src += 512; } @@ -1100,7 +1099,7 @@ static void s19(FDI *fdi) static void s1a(FDI *fdi) { int shift = *fdi->track_src++; - debuglog ("s1a:shift=%d,data=%s", shift, datalog (fdi->track_src , 128 << shift)); + DEBUG("s1a:shift=%d,data=%s", shift, datalog (fdi->track_src , 128 << shift)); ibm_data (fdi, fdi->track_src, 0, 128 << shift); fdi->track_src += 128 << shift; } @@ -1108,7 +1107,7 @@ static void s1a(FDI *fdi) static void s1b(FDI *fdi) { int shift = *fdi->track_src++; - debuglog ("s1b:shift=%d,crc=%s,data=%s", shift, datalog (fdi->track_src + (128 << shift), 2), datalog (fdi->track_src , 128 << shift)); + DEBUG("s1b:shift=%d,crc=%s,data=%s", shift, datalog (fdi->track_src + (128 << shift), 2), datalog (fdi->track_src , 128 << shift)); ibm_data (fdi, fdi->track_src, fdi->track_src + (128 << shift), 128 << shift); fdi->track_src += (128 << shift) + 2; } @@ -1308,31 +1307,37 @@ static void fix_mfm_sync (FDI *fdi) static int handle_sectors_described_track (FDI *fdi) { +#ifdef _LOGGING int oldout; - uae_u8 *start_src = fdi->track_src ; + uae_u8 *start_src = fdi->track_src; +#endif fdi->encoding_type = *fdi->track_src++; fdi->index_offset = get_u32(fdi->track_src); fdi->index_offset >>= 8; fdi->track_src += 3; - outlog ("sectors_described, index offset: %d\n",fdi->index_offset); + DEBUG("sectors_described, index offset: %d\n",fdi->index_offset); do { fdi->track_type = *fdi->track_src++; - outlog ("%06.6X %06.6X %02.2X:",fdi->track_src - start_src + 0x200, fdi->out/8, fdi->track_type); + DEBUG("%06.6X %06.6X %02.2X:",fdi->track_src - start_src + 0x200, fdi->out/8, fdi->track_type); +#ifdef _LOGGING oldout = fdi->out; +#endif decode_sectors_described_track[fdi->track_type](fdi); - outlog(" %d\n", fdi->out - oldout); + DEBUG(" %d\n", fdi->out - oldout); +#ifdef _LOGGING oldout = fdi->out; +#endif if (fdi->out < 0 || fdi->err) { - outlog ("\nin %d bytes, out %d bits\n", fdi->track_src - fdi->track_src_buffer, fdi->out); + DEBUG("\nin %d bytes, out %d bits\n", fdi->track_src - fdi->track_src_buffer, fdi->out); return -1; } if (fdi->track_src - fdi->track_src_buffer >= fdi->track_src_len) { - outlog ("source buffer overrun, previous type: %02.2X\n", fdi->track_type); + DEBUG("source buffer overrun, previous type: %02.2X\n", fdi->track_type); return -1; } } while (fdi->track_type != 0xff); - outlog("\n"); + DEBUG("\n"); fix_mfm_sync (fdi); return fdi->out; } @@ -1356,7 +1361,7 @@ static uae_u8 *fdi_decompress (int pulses, uae_u8 *sizep, uae_u8 *src, int *dofr src += 4; } } else if (mode == 1) { - dst = fdi_malloc (pulses *4); + dst = (uae_u8 *)fdi_malloc (pulses *4); *dofree = 1; fdi_decode (src, pulses, dst); } else { @@ -1563,7 +1568,7 @@ static void fdi2_decode (FDI *fdi, uint32_t totalavg, uae_u32 *avgp, uae_u32 *mi || (minp[i] < (standard_MFM_2_bit_cell_size - (standard_MFM_2_bit_cell_size / 4))) ) ) i++; if (i == pulses) { - outlog ("FDI: No stable and long-enough pulse in track.\n"); + DEBUG("FDI: No stable and long-enough pulse in track.\n"); return; } nexti = i; @@ -1640,12 +1645,12 @@ static void fdi2_decode (FDI *fdi, uint32_t totalavg, uae_u32 *avgp, uae_u32 *mi } avg_pulse += jitter; if ((avg_pulse < min_pulse) || (avg_pulse > max_pulse)) { - outlog ("FDI: avg_pulse outside bounds! avg=%u min=%u max=%u\n", avg_pulse, min_pulse, max_pulse); - outlog ("FDI: avgp=%u (%u) minp=%u (%u) maxp=%u (%u) jitter=%d i=%d ni=%d\n", + DEBUG("FDI: avg_pulse outside bounds! avg=%u min=%u max=%u\n", avg_pulse, min_pulse, max_pulse); + DEBUG("FDI: avgp=%u (%u) minp=%u (%u) maxp=%u (%u) jitter=%d i=%d ni=%d\n", avgp[i], avgp[nexti], minp[i], minp[nexti], maxp[i], maxp[nexti], jitter, i, nexti); } if (avg_pulse < ref_pulse) - outlog ("FDI: avg_pulse < ref_pulse! (%u < %u)\n", avg_pulse, ref_pulse); + DEBUG("FDI: avg_pulse < ref_pulse! (%u < %u)\n", avg_pulse, ref_pulse); pulse += avg_pulse - ref_pulse; ref_pulse = 0; if (i == eodat) @@ -1857,7 +1862,7 @@ static int decode_lowlevel_track (FDI *fdi, int track, struct fdi_cache *cache) idx_off3 = 4; } } else { - idxp = fdi_malloc (pulses * 2); + idxp = (uae_u8 *)fdi_malloc (pulses * 2); idx_free = 1; for (i = 0; i < pulses; i++) { idxp[i * 2 + 0] = 2; @@ -1961,7 +1966,9 @@ void fdi2raw_header_free (FDI *fdi) fdi_free (c->maxp); } fdi_free (fdi); - debuglog ("FREE: memory allocated %d\n", fdi_allocated); +#ifdef _DEBUG + DEBUG("FREE: memory allocated %d\n", fdi_allocated); +#endif } int fdi2raw_get_last_track (FDI *fdi) @@ -2012,8 +2019,10 @@ FDI *fdi2raw_header(FILE *f) uae_u8 type, size; FDI *fdi; - debuglog ("ALLOC: memory allocated %d\n", fdi_allocated); - fdi = fdi_malloc(sizeof(FDI)); +#ifdef _DEBUG + DEBUG("ALLOC: memory allocated %d\n", fdi_allocated); +#endif + fdi = (FDI *)fdi_malloc(sizeof(FDI)); memset (fdi, 0, sizeof (FDI)); fdi->file = f; oldseek = ftell (fdi->file); @@ -2029,10 +2038,10 @@ FDI *fdi2raw_header(FILE *f) return NULL; } - fdi->mfmsync_buffer = fdi_malloc (MAX_MFM_SYNC_BUFFER * sizeof(int)); - fdi->track_src_buffer = fdi_malloc (MAX_SRC_BUFFER); - fdi->track_dst_buffer = fdi_malloc (MAX_DST_BUFFER); - fdi->track_dst_buffer_timing = fdi_malloc (MAX_TIMING_BUFFER); + fdi->mfmsync_buffer = (int *)fdi_malloc (MAX_MFM_SYNC_BUFFER * sizeof(int)); + fdi->track_src_buffer = (uae_u8 *)fdi_malloc (MAX_SRC_BUFFER); + fdi->track_dst_buffer = (uae_u8 *)fdi_malloc (MAX_DST_BUFFER); + fdi->track_dst_buffer_timing = (uae_u16 *)fdi_malloc (MAX_TIMING_BUFFER); fdi->last_track = ((fdi->header[142] << 8) + fdi->header[143]) + 1; fdi->last_track *= fdi->header[144] + 1; @@ -2042,8 +2051,8 @@ FDI *fdi2raw_header(FILE *f) fdi->disk_type = fdi->header[145]; fdi->rotation_speed = fdi->header[146] + 128; fdi->write_protect = fdi->header[147] & 1; - outlog ("FDI version %d.%d\n", fdi->header[140], fdi->header[141]); - outlog ("last_track=%d rotation_speed=%d\n",fdi->last_track,fdi->rotation_speed); + DEBUG("FDI version %d.%d\n", fdi->header[140], fdi->header[141]); + DEBUG("last_track=%d rotation_speed=%d\n",fdi->last_track,fdi->rotation_speed); offset = 512; i = fdi->last_track; @@ -2182,4 +2191,3 @@ int fdi2raw_loadtrack (FDI *fdi, uae_u16 *mfmbuf, uae_u16 *tracktiming, int trac } return outlen; } - diff --git a/src/devices/input/game/js_sw_pad.c b/src/devices/input/game/js_sw_pad.c index aec2d20..d09d02b 100644 --- a/src/devices/input/game/js_sw_pad.c +++ b/src/devices/input/game/js_sw_pad.c @@ -29,7 +29,7 @@ * - Some DOS stuff will write to 0x201 while a packet is * being transferred. This seems to be ignored. * - * Version: @(#)js_sw_pad.c 1.0.8 2018/05/06 + * Version: @(#)js_sw_pad.c 1.0.9 2018/09/22 * * Authors: Fred N. van Kempen, * Sarah Walker, @@ -67,14 +67,14 @@ typedef struct { - int64_t poll_time; - int64_t poll_left; - int64_t poll_clock; - uint64_t poll_data; - int64_t poll_mode; + int64_t poll_time; + int64_t poll_left; + int64_t poll_clock; + uint64_t poll_data; + int64_t poll_mode; - int64_t trigger_time; - int64_t data_mode; + int64_t trigger_time; + int64_t data_mode; } sw_data; @@ -130,15 +130,17 @@ sw_parity(uint16_t data) static void * sw_init(void) { - sw_data *sw = (sw_data *)malloc(sizeof(sw_data)); + sw_data *sw; -pclog("SideWinder: initializing..\n"); + INFO("SideWinder: initializing..\n"); + + sw = (sw_data *)mem_alloc(sizeof(sw_data)); memset(sw, 0x00, sizeof(sw_data)); timer_add(timer_over, &sw->poll_time, &sw->poll_time, sw); timer_add(trigger_timer_over, &sw->trigger_time, &sw->trigger_time, sw); - return sw; + return(sw); } @@ -147,7 +149,8 @@ sw_close(void *priv) { sw_data *sw = (sw_data *)priv; -pclog("SideWinder: closing.\n"); + INFO("SideWinder: closing.\n"); + free(sw); } @@ -158,7 +161,8 @@ sw_read(void *priv) sw_data *sw = (sw_data *)priv; uint8_t temp = 0; -pclog("SideWinder: read(): %d\n", !!JOYSTICK_PRESENT(0)); + DEBUG("SideWinder: read(): %d\n", !!JOYSTICK_PRESENT(0)); + if (! JOYSTICK_PRESENT(0)) return(0xff); if (sw->poll_time) { @@ -184,8 +188,11 @@ sw_write(void *priv) { sw_data *sw = (sw_data *)priv; int64_t time_since_last = sw->trigger_time / TIMER_USEC; + uint16_t data; + int b, c; + + DEBUG("SideWinder: write(): %d\n", !!JOYSTICK_PRESENT(0)); -pclog("SideWinder: write(): %d\n", !!JOYSTICK_PRESENT(0)); if (! JOYSTICK_PRESENT(0)) return; timer_process(); @@ -197,10 +204,8 @@ pclog("SideWinder: write(): %d\n", !!JOYSTICK_PRESENT(0)); if (time_since_last > 9900 && time_since_last < 9940) { sw->poll_mode = 0; sw->poll_left = 49; - sw->poll_data = 0x2400ull | (0x1830ull << 15) | (0x19b0ull << 30); + sw->poll_data = 0x2400ULL | (0x1830ULL << 15) | (0x19b0ULL << 30); } else { - int c; - sw->poll_mode = sw->data_mode; sw->data_mode = !sw->data_mode; @@ -213,8 +218,7 @@ pclog("SideWinder: write(): %d\n", !!JOYSTICK_PRESENT(0)); } for (c = 0; c < 4; c++) { - uint16_t data = 0x3fff; - int b; + data = 0x3fff; if (! JOYSTICK_PRESENT(c)) break; @@ -256,9 +260,10 @@ static int sw_axis(void *priv, int axis) { if (! JOYSTICK_PRESENT(0)) - return AXIS_NOT_PRESENT; + return(AXIS_NOT_PRESENT); - return 0LL; /*No analogue support on Sidewinder game pad*/ + /* No analog support on Sidewinder game pad. */ + return(0); } diff --git a/src/devices/input/keyboard.c b/src/devices/input/keyboard.c index 73d7c24..c7e8f26 100644 --- a/src/devices/input/keyboard.c +++ b/src/devices/input/keyboard.c @@ -8,7 +8,7 @@ * * General keyboard driver interface. * - * Version: @(#)keyboard.c 1.0.6 2018/05/06 + * Version: @(#)keyboard.c 1.0.8 2018/09/30 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -42,8 +42,11 @@ #include #include #define HAVE_STDARG_H +#define dbglog kbd_log #include "../../emu.h" #include "../../machines/machine.h" +#include "../plat.h" +#include "../ui/ui.h" #include "keyboard.h" @@ -66,12 +69,12 @@ static uint8_t shift = 0; void -kbd_log(const char *fmt, ...) +kbd_log(int level, const char *fmt, ...) { #ifdef ENABLE_KEYBOARD_LOG va_list ap; - if (keyboard_do_log) { + if (keyboard_do_log >= level) { va_start(ap, fmt); pclog_ex(fmt, ap); va_end(ap); @@ -80,6 +83,7 @@ kbd_log(const char *fmt, ...) } +/* Reset the keyboard driver. */ void keyboard_init(void) { @@ -95,6 +99,18 @@ keyboard_init(void) } +void +keyboard_reset(void) +{ + uint8_t i; + + /* Initialize the key states from the platform keyboard. */ + i = plat_kbd_state() & 0xff; + + keyboard_set_state(i); +} + + void keyboard_set_table(const scancode *ptr) { @@ -165,6 +181,8 @@ key_process(uint16_t scan, int down) void keyboard_input(int down, uint16_t scan) { + int uiflag = 0; + /* Translate E0 xx scan codes to 01xx because we use 512-byte arrays for states and scan code sets. */ if ((scan >> 8) == 0xe0) { @@ -203,8 +221,8 @@ keyboard_input(int down, uint16_t scan) case 0x138: /* Right Alt */ shift |= 0x30; break; - } - } else { + } + } else { switch(scan & 0x1ff) { case 0x01c: /* Left Ctrl */ shift &= ~0x01; @@ -232,19 +250,35 @@ keyboard_input(int down, uint16_t scan) case 0x03a: /* Caps Lock */ caps_lock ^= 1; + uiflag++; break; case 0x045: num_lock ^= 1; + uiflag++; break; case 0x046: scroll_lock ^= 1; + uiflag++; break; } } } + if (uiflag) { + /* One of the toggle keys changed, update UI. */ + uiflag = 0; + if (caps_lock) + uiflag |= KBD_FLAG_CAPS; + if (num_lock) + uiflag |= KBD_FLAG_NUM; + if (scroll_lock) + uiflag |= KBD_FLAG_SCROLL; + ui_sb_kbstate(uiflag); +//pclog(0,"KBD: input: caps=%d num=%d scrl=%d\n", caps_lock,num_lock,scroll_lock); + } + /* * NOTE: Shouldn't this be some sort of bit shift? * An array of 8 unsigned 64-bit integers should be enough. @@ -253,10 +287,7 @@ keyboard_input(int down, uint16_t scan) recv_key[scan >> 6] |= ((uint64_t) down << ((uint64_t) scan & 0x3fLL)); #endif -#ifdef ENABLE_KEYBOARD_LOG - kbd_log("Received scan code: %03X (%s)\n", - scan & 0x1ff, down ? "down" : "up"); -#endif + DEBUG("Received scan code: %03X (%s)\n",scan & 0x1ff, down ? "down" : "up"); recv_key[scan & 0x1ff] = down; @@ -281,20 +312,6 @@ keyboard_do_break(uint16_t scan) } -/* - * Also called by the emulated keyboard controller to update the states - * of Caps Lock, Num Lock, and Scroll Lock when receving the "Set LEDs" - * keyboard command. - */ -void -keyboard_update_states(uint8_t cl, uint8_t nl, uint8_t sl) -{ - caps_lock = cl; - num_lock = nl; - scroll_lock = sl; -} - - uint8_t keyboard_get_shift(void) { @@ -302,30 +319,36 @@ keyboard_get_shift(void) } -void -keyboard_get_states(uint8_t *cl, uint8_t *nl, uint8_t *sl) +uint8_t +keyboard_get_state(void) { - if (cl) - *cl = caps_lock; - if (nl) - *nl = num_lock; - if (sl) - *sl = scroll_lock; + uint8_t ret = 0x00; + + if (caps_lock) + ret |= KBD_FLAG_CAPS; + if (num_lock) + ret |= KBD_FLAG_NUM; + if (scroll_lock) + ret |= KBD_FLAG_SCROLL; + +//pclog(0,"KBD state: caps=%d num=%d scrl=%d\n", caps_lock,num_lock,scroll_lock); + return(ret); } /* - * Called by the UI to update the states of Caps Lock, - * Num Lock, and Scroll Lock. + * Called by the UI to update the states of + * Caps Lock, Num Lock, and Scroll Lock. */ void -keyboard_set_states(uint8_t cl, uint8_t nl, uint8_t sl) +keyboard_set_state(uint8_t flags) { const scancode *codes = scan_table; + int i, f; - int i; - - if (caps_lock != cl) { + f = !!(flags & KBD_FLAG_CAPS); + if (caps_lock != f) { +#if 0 i = 0; while (codes[0x03a].mk[i] != -1) keyboard_send(codes[0x03a].mk[i++]); @@ -334,9 +357,13 @@ keyboard_set_states(uint8_t cl, uint8_t nl, uint8_t sl) while (codes[0x03a].brk[i] != -1) keyboard_send(codes[0x03a].brk[i++]); } +#endif + caps_lock = f; } - if (num_lock != nl) { + f = !!(flags & KBD_FLAG_NUM); + if (num_lock != f) { +#if 0 i = 0; while (codes[0x045].mk[i] != -1) keyboard_send(codes[0x045].mk[i++]); @@ -345,9 +372,13 @@ keyboard_set_states(uint8_t cl, uint8_t nl, uint8_t sl) while (codes[0x045].brk[i] != -1) keyboard_send(codes[0x045].brk[i++]); } +#endif + num_lock = f; } - if (scroll_lock != sl) { + f = !!(flags & KBD_FLAG_SCROLL); + if (scroll_lock != f) { +#if 0 i = 0; while (codes[0x046].mk[i] != -1) keyboard_send(codes[0x046].mk[i++]); @@ -356,9 +387,9 @@ keyboard_set_states(uint8_t cl, uint8_t nl, uint8_t sl) while (codes[0x046].brk[i] != -1) keyboard_send(codes[0x046].brk[i++]); } +#endif + scroll_lock = f; } - - keyboard_update_states(cl, nl, sl); } @@ -370,7 +401,7 @@ keyboard_recv(uint16_t key) /* Insert keystrokes into the machine's keyboard buffer. */ -void +static void keyboard_send_scan(uint8_t val) { if (AT) @@ -380,42 +411,42 @@ keyboard_send_scan(uint8_t val) } -/* Send the machine a Control-Alt-DEL sequence. */ -void -keyboard_send_cad(void) +/* Send the machine a Control-Alt sequence. */ +static void +keyboard_ca(uint8_t sc) { keyboard_send_scan(29); /* Ctrl key pressed */ keyboard_send_scan(56); /* Alt key pressed */ - keyboard_send_scan(83); /* Delete key pressed */ - keyboard_send_scan(157); /* Ctrl key released */ + + keyboard_send_scan(sc); /* press */ + keyboard_send_scan(sc | 0x80); /* release */ + keyboard_send_scan(184); /* Alt key released */ - keyboard_send_scan(211); /* Delete key released */ + keyboard_send_scan(157); /* Ctrl key released */ +} + + +/* Send the machine a Control-Alt-DEL sequence. */ +void +keyboard_cad(void) +{ + keyboard_ca(83); /* Delete */ } /* Send the machine a Control-Alt-ESC sequence. */ void -keyboard_send_cae(void) +keyboard_cae(void) { - keyboard_send_scan(29); /* Ctrl key pressed */ - keyboard_send_scan(56); /* Alt key pressed */ - keyboard_send_scan(1); /* Esc key pressed */ - keyboard_send_scan(129); /* Esc key released */ - keyboard_send_scan(184); /* Alt key released */ - keyboard_send_scan(157); /* Ctrl key released */ + keyboard_ca(1); /* Esc */ } /* Send the machine a Control-Alt-Break sequence. */ void -keyboard_send_cab(void) +keyboard_cab(void) { - keyboard_send_scan(29); /* Ctrl key pressed */ - keyboard_send_scan(56); /* Alt key pressed */ - keyboard_send_scan(1); /* Esc key pressed */ - keyboard_send_scan(157); /* Ctrl key released */ - keyboard_send_scan(184); /* Alt key released */ - keyboard_send_scan(129); /* Esc key released */ + keyboard_ca(1); /* Break (FIXME: Esc) */ } @@ -438,6 +469,7 @@ keyboard_ismsexit(void) return( recv_key[0x042] && recv_key[0x058] ); #else /* WxWidgets cannot do two regular keys.. CTRL+END */ - return( (recv_key[0x01D] || recv_key[0x11D]) && (recv_key[0x04F] || recv_key[0x14F]) ); + return( (recv_key[0x01D] || recv_key[0x11D]) && + (recv_key[0x04F] || recv_key[0x14F]) ); #endif } diff --git a/src/devices/input/keyboard.h b/src/devices/input/keyboard.h index cc1a281..1adf912 100644 --- a/src/devices/input/keyboard.h +++ b/src/devices/input/keyboard.h @@ -8,7 +8,7 @@ * * Definitions for the keyboard interface. * - * Version: @(#)keyboard.h 1.0.5 2018/04/01 + * Version: @(#)keyboard.h 1.0.7 2018/09/28 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -40,11 +40,11 @@ # define EMU_KEYBOARD_H -typedef struct { - int mk[9]; - int brk[9]; -} scancode; - +/* Keyboard State bits. */ +#define KBD_FLAG_CAPS 0x01 /* CAPS LOCK currently on */ +#define KBD_FLAG_NUM 0x02 /* NUM LOCK currently on */ +#define KBD_FLAG_SCROLL 0x04 /* SCROLL LOCK currently on */ +#define KBD_FLAG_PAUSE 0x10 /* PAUSE currently on */ #define STATE_SHIFT_MASK 0x22 #define STATE_RSHIFT 0x20 @@ -62,55 +62,66 @@ typedef struct { extern "C" { #endif -extern uint8_t keyboard_mode; -extern int keyboard_scan; -extern int64_t keyboard_delay; +typedef struct { + int mk[9]; + int brk[9]; +} scancode; -extern void (*keyboard_send)(uint16_t val); -extern void kbd_adddata_process(uint16_t val, void (*adddata)(uint16_t val)); -extern const scancode scancode_xt[512]; +extern uint8_t keyboard_mode; +extern int keyboard_scan; +extern int64_t keyboard_delay; -extern uint8_t keyboard_set3_flags[512]; -extern uint8_t keyboard_set3_all_repeat; -extern uint8_t keyboard_set3_all_break; -extern int mouse_queue_start, mouse_queue_end; -extern int mouse_scan; +extern uint8_t keyboard_set3_flags[512]; +extern uint8_t keyboard_set3_all_repeat; +extern uint8_t keyboard_set3_all_break; +extern int mouse_queue_start, mouse_queue_end; +extern int mouse_scan; + +extern const scancode scancode_xt[512]; #ifdef EMU_DEVICE_H +extern const device_t keyboard_pc_device; extern const device_t keyboard_xt_device; +extern const device_t keyboard_xt_lxt3_device; extern const device_t keyboard_tandy_device; extern const device_t keyboard_at_device; extern const device_t keyboard_at_ami_device; extern const device_t keyboard_at_toshiba_device; extern const device_t keyboard_ps2_device; +extern const device_t keyboard_ps2_xi8088_device; extern const device_t keyboard_ps2_ami_device; extern const device_t keyboard_ps2_mca_device; extern const device_t keyboard_ps2_mca_2_device; extern const device_t keyboard_ps2_quadtel_device; +extern const device_t keyboard_ps2_pci_device; +extern const device_t keyboard_ps2_ami_pci_device; #endif -extern void kbd_log(const char *fmt, ...); +extern void (*keyboard_send)(uint16_t val); + + +extern void kbd_adddata_process(uint16_t val, void (*adddata)(uint16_t val)); + +extern void kbd_log(int level, const char *fmt, ...); extern void keyboard_init(void); +extern void keyboard_reset(void); extern void keyboard_close(void); extern void keyboard_set_table(const scancode *ptr); extern void keyboard_poll_host(void); extern void keyboard_process(void); extern uint16_t keyboard_convert(int ch); extern void keyboard_input(int down, uint16_t scan); -extern void keyboard_update_states(uint8_t cl, uint8_t nl, uint8_t sl); extern uint8_t keyboard_get_shift(void); -extern void keyboard_get_states(uint8_t *cl, uint8_t *nl, uint8_t *sl); -extern void keyboard_set_states(uint8_t cl, uint8_t nl, uint8_t sl); +extern uint8_t keyboard_get_state(void); +extern void keyboard_set_state(uint8_t); extern int keyboard_recv(uint16_t key); -extern void keyboard_send_scan(uint8_t val); -extern void keyboard_send_cad(void); -extern void keyboard_send_cae(void); -extern void keyboard_send_cab(void); +extern void keyboard_cad(void); +extern void keyboard_cae(void); +extern void keyboard_cab(void); extern int keyboard_isfsexit(void); extern int keyboard_ismsexit(void); -extern void keyboard_at_reset(void); extern void keyboard_at_adddata_keyboard_raw(uint8_t val); extern void keyboard_at_adddata_mouse(uint8_t val); extern void keyboard_at_set_mouse(void (*mouse_write)(uint8_t val,void *), void *); diff --git a/src/devices/input/keyboard_at.c b/src/devices/input/keyboard_at.c index ff879d6..07e8e0d 100644 --- a/src/devices/input/keyboard_at.c +++ b/src/devices/input/keyboard_at.c @@ -11,7 +11,7 @@ * NOTE: Several changes to disable Mode1 for now, as this breaks * the TSX32 operating system. More cleanups needed.. * - * Version: @(#)keyboard_at.c 1.0.16 2018/09/11 + * Version: @(#)keyboard_at.c 1.0.16 2018/10/05 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -44,6 +44,7 @@ #include #include #include +#define dbglog kbd_log #include "../../emu.h" #include "../../cpu/cpu.h" #include "../../machines/machine.h" @@ -99,6 +100,7 @@ #define KBC_VEN_IBM_MCA 0x08 #define KBC_VEN_QUADTEL 0x0c #define KBC_VEN_TOSHIBA 0x10 +#define KBC_VEN_XI8088 0x14 #define KBC_VEN_MASK 0x1c @@ -638,9 +640,7 @@ kbd_poll(void *priv) if ((kbd->out_new != -1) && !kbd->last_irq) { kbd->wantirq = 0; if (kbd->out_new & 0x100) { -#ifdef ENABLE_KEYBOARD_LOG - kbd_log("ATkbd: want mouse data\n"); -#endif + DEBUG("ATkbd: want mouse data\n"); if (kbd->mem[0] & 0x02) picint(0x1000); kbd->out = kbd->out_new & 0xff; @@ -650,9 +650,7 @@ kbd_poll(void *priv) kbd->status |= STAT_MFULL; kbd->last_irq = 0x1000; } else { -#ifdef ENABLE_KEYBOARD_LOG - kbd_log("ATkbd: want keyboard data\n"); -#endif + DEBUG("ATkbd: want keyboard data\n"); if (kbd->mem[0] & 0x01) picint(2); kbd->out = kbd->out_new & 0xff; @@ -707,12 +705,8 @@ kbd_adddata_vals(uint8_t *val, uint8_t len) uint8_t or = 0; uint8_t send; -#if 0 - translate = translate || (keyboard_mode & 0x40) && !xt_mode; -#else translate = translate || (keyboard_mode & 0x40) || xt_mode; translate = translate || ((CurrentKbd->flags & KBC_TYPE_MASK) == KBC_TYPE_PS2_2); -#endif for (i = 0; i < len; i++) { if (translate) { @@ -725,25 +719,21 @@ kbd_adddata_vals(uint8_t *val, uint8_t len) or = 0; } else send = val[i]; -#ifdef ENABLE_KEYBOARD_LOG - kbd_log("%02X", send); -#endif + DEBUG("%02X", send); kbd_adddata(send); -#ifdef ENABLE_KEYBOARD_LOG - if (i < (len - 1)) kbd_log(" "); -#endif + if (i < (len - 1)) DEBUG(" "); } -#ifdef ENABLE_KEYBOARD_LOG +#ifdef _DEBUG if (translate) { - kbd_log(" original: ("); + DEBUG(" original: ("); for (i = 0; i < len; i++) { - kbd_log("%02X", val[i]); - if (i < (len - 1)) kbd_log(" "); + DEBUG("%02X", val[i]); + if (i < (len - 1)) DEBUG(" "); } - kbd_log(")"); + DEBUG(")"); } - kbd_log("\n"); + DEBUG("\n"); #endif } @@ -756,68 +746,54 @@ kbd_adddata_keyboard(uint16_t val) uint8_t fake_shift[4]; uint8_t num_lock = 0, shift_states = 0; -#if 0 - translate = translate || (keyboard_mode & 0x40) && !xt_mode; -#else translate = translate || (keyboard_mode & 0x40) || xt_mode; translate = translate || ((CurrentKbd->flags & KBC_TYPE_MASK) == KBC_TYPE_PS2_2); -#endif - keyboard_get_states(NULL, &num_lock, NULL); + num_lock = !!(keyboard_get_state() & KBD_FLAG_NUM); shift_states = keyboard_get_shift() & STATE_SHIFT_MASK; /* Allow for scan code translation. */ if (translate && (val == 0xf0)) { -#ifdef ENABLE_KEYBOARD_LOG - kbd_log("ATkbd: translate is on, F0 prefix detected\n"); -#endif + DEBUG("ATkbd: translate is on, F0 prefix detected\n"); sc_or = 0x80; return; } /* Skip break code if translated make code has bit 7 set. */ if (translate && (sc_or == 0x80) && (val & 0x80)) { -#ifdef ENABLE_KEYBOARD_LOG - kbd_log("ATkbd: translate is on, skipping scan code: %02X (original: F0 %02X)\n", nont_to_t[val], val); -#endif + DEBUG("ATkbd: translate is on, skipping scan code: %02X (original: F0 %02X)\n", nont_to_t[val], val); sc_or = 0; return; } /* Test for T3100E 'Fn' key (Right Alt / Right Ctrl) */ - if (romset == ROM_T3100E && (keyboard_recv(0xb8) || keyboard_recv(0x9d))) { - switch (val) { - case 0x4f: t3100e_notify_set(0x01); break; /* End */ - case 0x50: t3100e_notify_set(0x02); break; /* Down */ - case 0x51: t3100e_notify_set(0x03); break; /* PgDn */ - case 0x52: t3100e_notify_set(0x04); break; /* Ins */ - case 0x53: t3100e_notify_set(0x05); break; /* Del */ - case 0x54: t3100e_notify_set(0x06); break; /* SysRQ */ - case 0x45: t3100e_notify_set(0x07); break; /* NumLock */ - case 0x46: t3100e_notify_set(0x08); break; /* ScrLock */ - case 0x47: t3100e_notify_set(0x09); break; /* Home */ - case 0x48: t3100e_notify_set(0x0A); break; /* Up */ - case 0x49: t3100e_notify_set(0x0B); break; /* PgUp */ - case 0x4A: t3100e_notify_set(0x0C); break; /* Keypad -*/ - case 0x4B: t3100e_notify_set(0x0D); break; /* Left */ - case 0x4C: t3100e_notify_set(0x0E); break; /* KP 5 */ - case 0x4D: t3100e_notify_set(0x0F); break; /* Right */ - } + if ((CurrentKbd != NULL) && + ((CurrentKbd->flags & KBC_VEN_MASK) == KBC_VEN_TOSHIBA) && + (keyboard_recv(0xb8) || keyboard_recv(0x9d))) switch (val) { + case 0x4f: t3100e_notify_set(0x01); break; /* End */ + case 0x50: t3100e_notify_set(0x02); break; /* Down */ + case 0x51: t3100e_notify_set(0x03); break; /* PgDn */ + case 0x52: t3100e_notify_set(0x04); break; /* Ins */ + case 0x53: t3100e_notify_set(0x05); break; /* Del */ + case 0x54: t3100e_notify_set(0x06); break; /* SysRQ */ + case 0x45: t3100e_notify_set(0x07); break; /* NumLock */ + case 0x46: t3100e_notify_set(0x08); break; /* ScrLock */ + case 0x47: t3100e_notify_set(0x09); break; /* Home */ + case 0x48: t3100e_notify_set(0x0A); break; /* Up */ + case 0x49: t3100e_notify_set(0x0B); break; /* PgUp */ + case 0x4A: t3100e_notify_set(0x0C); break; /* Keypad -*/ + case 0x4B: t3100e_notify_set(0x0D); break; /* Left */ + case 0x4C: t3100e_notify_set(0x0E); break; /* KP 5 */ + case 0x4D: t3100e_notify_set(0x0F); break; /* Right */ } -#ifdef ENABLE_KEYBOARD_LOG - kbd_log("ATkbd: translate is %s, ", translate ? "on" : "off"); -#endif + DEBUG("ATkbd: translate is %s, ", translate ? "on" : "off"); switch(val) { case FAKE_LSHIFT_ON: -#ifdef ENABLE_KEYBOARD_LOG - kbd_log("fake left shift on, scan code: "); -#endif + DEBUG("fake left shift on, scan code: "); if (num_lock) { if (shift_states) { -#ifdef ENABLE_KEYBOARD_LOG - kbd_log("N/A (one or both shifts on)\n"); -#endif + DEBUG("N/A (one or both shifts on)\n"); break; } else { /* Num lock on and no shifts are pressed, send non-inverted fake shift. */ @@ -831,9 +807,7 @@ kbd_adddata_keyboard(uint16_t val) kbd_adddata_vals(fake_shift, 2); break; default: -#ifdef ENABLE_KEYBOARD_LOG - kbd_log("N/A (scan code set %i)\n", keyboard_mode & 0x02); -#endif + DEBUG("N/A (scan code set %i)\n", keyboard_mode & 0x02); break; } } @@ -850,9 +824,7 @@ kbd_adddata_keyboard(uint16_t val) kbd_adddata_vals(fake_shift, 3); break; default: -#ifdef ENABLE_KEYBOARD_LOG - kbd_log("N/A (scan code set %i)\n", keyboard_mode & 0x02); -#endif + DEBUG("N/A (scan code set %i)\n", keyboard_mode & 0x02); break; } } @@ -868,27 +840,20 @@ kbd_adddata_keyboard(uint16_t val) kbd_adddata_vals(fake_shift, 3); break; default: -#ifdef ENABLE_KEYBOARD_LOG - kbd_log("N/A (scan code set %i)\n", keyboard_mode & 0x02); -#endif + DEBUG("N/A (scan code set %i)\n", keyboard_mode & 0x02); break; } } -#ifdef ENABLE_KEYBOARD_LOG - if (!shift_states) - kbd_log("N/A (both shifts off)\n"); -#endif + if (! shift_states) { + DEBUG("N/A (both shifts off)\n"); + } } break; case FAKE_LSHIFT_OFF: -#ifdef ENABLE_KEYBOARD_LOG - kbd_log("fake left shift on, scan code: "); -#endif + DEBUG("fake left shift on, scan code: "); if (num_lock) { if (shift_states) { -#ifdef ENABLE_KEYBOARD_LOG - kbd_log("N/A (one or both shifts on)\n"); -#endif + DEBUG("N/A (one or both shifts on)\n"); break; } else { /* Num lock on and no shifts are pressed, send non-inverted fake shift. */ @@ -902,9 +867,7 @@ kbd_adddata_keyboard(uint16_t val) kbd_adddata_vals(fake_shift, 3); break; default: -#ifdef ENABLE_KEYBOARD_LOG - kbd_log("N/A (scan code set %i)\n", keyboard_mode & 0x02); -#endif + DEBUG("N/A (scan code set %i)\n", keyboard_mode & 0x02); break; } } @@ -921,9 +884,7 @@ kbd_adddata_keyboard(uint16_t val) kbd_adddata_vals(fake_shift, 2); break; default: -#ifdef ENABLE_KEYBOARD_LOG - kbd_log("N/A (scan code set %i)\n", keyboard_mode & 0x02); -#endif + DEBUG("N/A (scan code set %i)\n", keyboard_mode & 0x02); break; } } @@ -939,28 +900,25 @@ kbd_adddata_keyboard(uint16_t val) kbd_adddata_vals(fake_shift, 2); break; default: -#ifdef ENABLE_KEYBOARD_LOG - kbd_log("N/A (scan code set %i)\n", keyboard_mode & 0x02); -#endif + DEBUG("N/A (scan code set %i)\n", keyboard_mode & 0x02); break; } } -#ifdef ENABLE_KEYBOARD_LOG - if (!shift_states) - kbd_log("N/A (both shifts off)\n"); -#endif + if (! shift_states) { + DEBUG("N/A (both shifts off)\n"); + } } break; default: -#ifdef ENABLE_KEYBOARD_LOG - kbd_log("scan code: "); +#ifdef _DEBUG + DEBUG("scan code: "); if (translate) { - kbd_log("%02X (original: ", (nont_to_t[val] | sc_or)); + DEBUG("%02X (original: ", (nont_to_t[val] | sc_or)); if (sc_or == 0x80) - kbd_log("F0 "); - kbd_log("%02X)\n", val); + DEBUG("F0 "); + DEBUG("%02X)\n", val); } else - kbd_log("%02X\n", val); + DEBUG("%02X\n", val); #endif key_queue[key_queue_end] = (translate ? (nont_to_t[val] | sc_or) : val); @@ -975,9 +933,8 @@ kbd_adddata_keyboard(uint16_t val) static void kbd_output_write(atkbd_t *kbd, uint8_t val) { -#ifdef ENABLE_KEYBOARD_LOG - kbd_log("ATkbd: write output port: %02X (old: %02X)\n", val, kbd->output_port); -#endif + DBGLOG(1, "ATkbd: write output port: %02X (old: %02X)\n", val, kbd->output_port); + if ((kbd->output_port ^ val) & 0x20) { /*IRQ 12*/ if (val & 0x20) picint(1 << 12); @@ -1009,9 +966,7 @@ kbd_output_write(atkbd_t *kbd, uint8_t val) static void kbd_cmd_write(atkbd_t *kbd, uint8_t val) { -#ifdef ENABLE_KEYBOARD_LOG - kbd_log("ATkbd: write command byte: %02X (old: %02X)\n", val, kbd->mem[0]); -#endif + DBGLOG(1, "ATkbd: write command byte: %02X (old: %02X)\n", val, kbd->mem[0]); if ((val & 1) && (kbd->status & STAT_OFULL)) kbd->wantirq = 1; @@ -1029,10 +984,8 @@ kbd_cmd_write(atkbd_t *kbd, uint8_t val) keyboard_mode |= (val & MODE_MASK); keyboard_scan = !(val & 0x10); -#ifdef ENABLE_KEYBOARD_LOG - kbd_log("ATkbd: keyboard is now %s\n", keyboard_scan ? "enabled" : "disabled"); - kbd_log("ATkbd: keyboard interrupt is now %s\n", (val & 0x01) ? "enabled" : "disabled"); -#endif + DEBUG("ATkbd: keyboard is now %s\n", keyboard_scan ? "enabled" : "disabled"); + DEBUG("ATkbd: keyboard interrupt is now %s\n", (val & 0x01) ? "enabled" : "disabled"); /* ISA AT keyboard controllers use bit 5 for keyboard mode (1 = PC/XT, 2 = AT); PS/2 (and EISA/PCI) keyboard controllers use it as the PS/2 mouse enable switch. */ @@ -1041,14 +994,12 @@ kbd_cmd_write(atkbd_t *kbd, uint8_t val) keyboard_mode &= ~CCB_PCMODE; mouse_scan = !(val & 0x20); -#ifdef ENABLE_KEYBOARD_LOG - kbd_log("ATkbd: mouse is now %s\n", mouse_scan ? "enabled" : "disabled"); + DEBUG("ATkbd: mouse is now %s\n", mouse_scan ? "enabled" : "disabled"); - kbd_log("ATkbd: mouse interrupt is now %s\n", (val & 0x02) ? "enabled" : "disabled"); -#endif + DEBUG("ATkbd: mouse interrupt is now %s\n", (val & 0x02) ? "enabled" : "disabled"); } - kbd_log("Command byte now: %02X (%02X)\n", kbd->mem[0], val); + DBGLOG(1, "Command byte now: %02X (%02X)\n", kbd->mem[0], val); } @@ -1079,6 +1030,11 @@ kbd_keyboard_set(atkbd_t *kbd, uint8_t enable) kbd->mem[0] &= 0xef; kbd->mem[0] |= (enable ? 0x00 : 0x10); + if (enable) + kbd->status |= STAT_UNLOCKED; + else + kbd->status &= ~STAT_UNLOCKED; + keyboard_scan = enable; } @@ -1100,84 +1056,61 @@ kbd_write64_generic(void *p, uint8_t val) switch (val) { case 0xa4: /*Check if password installed*/ if ((kbd->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_1) { -#ifdef ENABLE_KEYBOARD_LOG - kbd_log("ATkbd: check if password installed\n"); -#endif + DEBUG("ATkbd: check if password installed\n"); kbd_adddata(0xf1); return 0; + } else { + ERRLOG("ATkbd: bad command A4\n"); } -#ifdef ENABLE_KEYBOARD_LOG - else - kbd_log("ATkbd: bad command A4\n"); -#endif break; case 0xa7: /*Disable mouse port*/ if ((kbd->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_1) { -#ifdef ENABLE_KEYBOARD_LOG - kbd_log("ATkbd: disable mouse port\n"); -#endif + DEBUG("ATkbd: disable mouse port\n"); kbd_mouse_set(kbd, 0); return 0; + } else { + ERRLOG("ATkbd: bad command A7\n"); } -#ifdef ENABLE_KEYBOARD_LOG - else - kbd_log("ATkbd: bad command A7\n"); -#endif break; case 0xa8: /*Enable mouse port*/ if ((kbd->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_1) { -#ifdef ENABLE_KEYBOARD_LOG - kbd_log("ATkbd: enable mouse port\n"); -#endif + DEBUG("ATkbd: enable mouse port\n"); kbd_mouse_set(kbd, 1); return 0; + } else { + ERRLOG("ATkbd: bad command A8\n"); } -#ifdef ENABLE_KEYBOARD_LOG - else - kbd_log("ATkbd: bad command A8\n"); -#endif break; case 0xa9: /*Test mouse port*/ -#ifdef ENABLE_KEYBOARD_LOG - kbd_log("ATkbd: test mouse port\n"); -#endif + DEBUG("ATkbd: test mouse port\n"); if ((kbd->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_1) { if (mouse_write) kbd_adddata(0x00); /*no error*/ else kbd_adddata(0xff); /*no mouse*/ return 0; + } else { + ERRLOG("ATkbd: bad command A9\n"); } -#ifdef ENABLE_KEYBOARD_LOG - else - kbd_log("ATkbd: bad command A9\n"); -#endif break; case 0xaf: /*Read keyboard version*/ -#ifdef ENABLE_KEYBOARD_LOG - kbd_log("ATkbd: read keyboard version\n"); -#endif + DEBUG("ATkbd: read keyboard version\n"); kbd_adddata(0x00); return 0; case 0xc0: /*Read input port*/ -#ifdef ENABLE_KEYBOARD_LOG - kbd_log("ATkbd: read input port\n"); -#endif - + DEBUG("ATkbd: read input port\n"); kbd_adddata(kbd->input_port | 4 | fdc_ps1_525()); kbd->input_port = ((kbd->input_port + 1) & 3) | (kbd->input_port & 0xfc) | fdc_ps1_525(); return 0; case 0xd3: /*Write mouse output buffer*/ if ((kbd->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_1) { -#ifdef ENABLE_KEYBOARD_LOG - kbd_log("ATkbd: write mouse output buffer\n"); -#endif + DEBUG("ATkbd: write mouse output buffer\n"); kbd->want60 = 1; return 0; } @@ -1185,9 +1118,7 @@ kbd_write64_generic(void *p, uint8_t val) case 0xd4: /*Write to mouse*/ if ((kbd->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_1) { -#ifdef ENABLE_KEYBOARD_LOG - kbd_log("ATkbd: write to mouse\n"); -#endif + DEBUG("ATkbd: write to mouse\n"); kbd->want60 = 1; return 0; } @@ -1197,9 +1128,7 @@ kbd_write64_generic(void *p, uint8_t val) case 0xf4: case 0xf5: case 0xf6: case 0xf7: case 0xf8: case 0xf9: case 0xfa: case 0xfb: case 0xfc: case 0xfd: case 0xfe: case 0xff: -#ifdef ENABLE_KEYBOARD_LOG - // kbd_log("ATkbd: pulse %01X\n", val & 0x0f); -#endif + DBGLOG(1, "ATkbd: pulse %01X\n", val & 0x0f); kbd_output_pulse(kbd, val & 0x0f); return 0; } @@ -1223,18 +1152,14 @@ kbd_write60_ami(void *p, uint8_t val) case 0x54: case 0x55: case 0x56: case 0x57: case 0x58: case 0x59: case 0x5a: case 0x5b: case 0x5c: case 0x5d: case 0x5e: case 0x5f: -#ifdef ENABLE_KEYBOARD_LOG - kbd_log("ATkbd: AMI - alias write to %08X\n", kbd->command); -#endif + DEBUG("ATkbd: AMI - alias write to %08X\n", kbd->command); kbd->mem[kbd->command & 0x1f] = val; if (kbd->command == 0x60) kbd_cmd_write(kbd, val); return 0; case 0xaf: /*AMI - set extended controller RAM*/ -#ifdef ENABLE_KEYBOARD_LOG - kbd_log("ATkbd: AMI - set extended controller RAM\n"); -#endif + DEBUG("ATkbd: AMI - set extended controller RAM\n"); if (kbd->secr_phase == 1) { kbd->mem_addr = val; kbd->want60 = 1; @@ -1246,9 +1171,7 @@ kbd_write60_ami(void *p, uint8_t val) return 0; case 0xcb: /*AMI - set keyboard mode*/ -#ifdef ENABLE_KEYBOARD_LOG - kbd_log("ATkbd: AMI - set keyboard mode\n"); -#endif + DEBUG("ATkbd: AMI - set keyboard mode\n"); return 0; } @@ -1270,9 +1193,7 @@ kbd_write64_ami(void *p, uint8_t val) case 0x14: case 0x15: case 0x16: case 0x17: case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c: case 0x1d: case 0x1e: case 0x1f: -#ifdef ENABLE_KEYBOARD_LOG - kbd_log("ATkbd: AMI - alias read from %08X\n", val); -#endif + DEBUG("ATkbd: AMI - alias read from %08X\n", val); kbd_adddata(kbd->mem[val]); return 0; @@ -1284,23 +1205,17 @@ kbd_write64_ami(void *p, uint8_t val) case 0x54: case 0x55: case 0x56: case 0x57: case 0x58: case 0x59: case 0x5a: case 0x5b: case 0x5c: case 0x5d: case 0x5e: case 0x5f: -#ifdef ENABLE_KEYBOARD_LOG - kbd_log("ATkbd: AMI - alias write to %08X\n", kbd->command); -#endif + DEBUG("ATkbd: AMI - alias write to %08X\n", kbd->command); kbd->want60 = 1; return 0; case 0xa1: /*AMI - get controller version*/ -#ifdef ENABLE_KEYBOARD_LOG - kbd_log("ATkbd: AMI - get controller version\n"); -#endif + DEBUG("ATkbd: AMI - get controller version\n"); return 0; case 0xa2: /*AMI - reset keyboard controller lines P22 and P23 low*/ if ((kbd->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_1) { -#ifdef ENABLE_KEYBOARD_LOG - kbd_log("ATkbd: AMI - clear KBC lines P22 and P23\n"); -#endif + DEBUG("ATkbd: AMI - clear KBC lines P22 and P23\n"); kbd_output_write(kbd, kbd->output_port & 0xf3); kbd_adddata(0x00); return 0; @@ -1309,9 +1224,7 @@ kbd_write64_ami(void *p, uint8_t val) case 0xa3: /*AMI - set keyboard controller lines P22 and P23 high*/ if ((kbd->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_1) { -#ifdef ENABLE_KEYBOARD_LOG - kbd_log("ATkbd: AMI - set KBC lines P22 and P23\n"); -#endif + DEBUG("ATkbd: AMI - set KBC lines P22 and P23\n"); kbd_output_write(kbd, kbd->output_port | 0x0c); kbd_adddata(0x00); return 0; @@ -1320,9 +1233,7 @@ kbd_write64_ami(void *p, uint8_t val) case 0xa4: /* AMI - write clock = low */ if ((kbd->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_1) { -#ifdef ENABLE_KEYBOARD_LOG - kbd_log("ATkbd: AMI - write clock = low\n"); -#endif + DEBUG("ATkbd: AMI - write clock = low\n"); kbd->ami_stat &= 0xfe; return 0; } @@ -1330,9 +1241,7 @@ kbd_write64_ami(void *p, uint8_t val) case 0xa5: /* AMI - write clock = high */ if ((kbd->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_1) { -#ifdef ENABLE_KEYBOARD_LOG - kbd_log("ATkbd: AMI - write clock = high\n"); -#endif + DEBUG("ATkbd: AMI - write clock = high\n"); kbd->ami_stat |= 0x01; return 0; } @@ -1340,9 +1249,7 @@ kbd_write64_ami(void *p, uint8_t val) case 0xa6: /* AMI - read clock */ if ((kbd->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_1) { -#ifdef ENABLE_KEYBOARD_LOG - kbd_log("ATkbd: AMI - read clock\n"); -#endif + DEBUG("ATkbd: AMI - read clock\n"); kbd_adddata(!!(kbd->ami_stat & 1)); return 0; } @@ -1350,9 +1257,7 @@ kbd_write64_ami(void *p, uint8_t val) case 0xa7: /* AMI - write cache bad */ if ((kbd->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_1) { -#ifdef ENABLE_KEYBOARD_LOG - kbd_log("ATkbd: AMI - write cache bad\n"); -#endif + DEBUG("ATkbd: AMI - write cache bad\n"); kbd->ami_stat &= 0xfd; return 0; } @@ -1360,9 +1265,7 @@ kbd_write64_ami(void *p, uint8_t val) case 0xa8: /* AMI - write cache good */ if ((kbd->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_1) { -#ifdef ENABLE_KEYBOARD_LOG - kbd_log("ATkbd: AMI - write cache good\n"); -#endif + DEBUG("ATkbd: AMI - write cache good\n"); kbd->ami_stat |= 0x02; return 0; } @@ -1370,86 +1273,76 @@ kbd_write64_ami(void *p, uint8_t val) case 0xa9: /* AMI - read cache */ if ((kbd->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_1) { -#ifdef ENABLE_KEYBOARD_LOG - kbd_log("ATkbd: AMI - read cache\n"); -#endif + DEBUG("ATkbd: AMI - read cache\n"); kbd_adddata(!!(kbd->ami_stat & 2)); return 0; } break; case 0xaf: /*Set extended controller RAM*/ -#ifdef ENABLE_KEYBOARD_LOG - kbd_log("ATkbd: set extended controller RAM\n"); -#endif + DEBUG("ATkbd: set extended controller RAM\n"); kbd->want60 = 1; kbd->secr_phase = 1; return 0; case 0xb0: case 0xb1: case 0xb2: case 0xb3: /*Set keyboard controller line P10-P13 (input port bits 0-3) low*/ - if (!PCI || (val > 0xb1)) + if (!PCI || (val > 0xb1)) { kbd->input_port &= ~(1 << (val & 0x03)); - kbd_adddata(0x00); + kbd_adddata(0x00); + } return 0; case 0xb4: case 0xb5: /*Set keyboard controller line P22-P23 (output port bits 2-3) low*/ - if (!PCI) + if (! PCI) { kbd_output_write(kbd, kbd->output_port & ~(4 << (val & 0x01))); - kbd_adddata(0x00); + kbd_adddata(0x00); + } return 0; case 0xb8: case 0xb9: case 0xba: case 0xbb: /*Set keyboard controller line P10-P13 (input port bits 0-3) high*/ - if (!PCI || (val > 0xb9)) + if (!PCI || (val > 0xb9)) { kbd->input_port |= (1 << (val & 0x03)); - kbd_adddata(0x00); + kbd_adddata(0x00); + } return 0; case 0xbc: case 0xbd: /*Set keyboard controller line P22-P23 (output port bits 2-3) high*/ - if (!PCI) + if (! PCI) { kbd_output_write(kbd, kbd->output_port | (4 << (val & 0x01))); - kbd_adddata(0x00); + kbd_adddata(0x00); + } return 0; case 0xc8: /*AMI - unblock keyboard controller lines P22 and P23 (allow command D1 to change bits 2 and 3 of the output port)*/ -#ifdef ENABLE_KEYBOARD_LOG - kbd_log("ATkbd: AMI - unblock KBC lines P22 and P23\n"); -#endif + DEBUG("ATkbd: AMI - unblock KBC lines P22 and P23\n"); kbd->output_locked = 1; return 0; case 0xc9: /*AMI - block keyboard controller lines P22 and P23 (prevent command D1 from changing bits 2 and 3 of the output port)*/ -#ifdef ENABLE_KEYBOARD_LOG - kbd_log("ATkbd: AMI - block KBC lines P22 and P23\n"); -#endif + DEBUG("ATkbd: AMI - block KBC lines P22 and P23\n"); kbd->output_locked = 1; return 0; case 0xca: /*AMI - read keyboard mode*/ -#ifdef ENABLE_KEYBOARD_LOG - kbd_log("ATkbd: AMI - read keyboard mode\n"); -#endif + DEBUG("ATkbd: AMI - read keyboard mode\n"); kbd_adddata(0x00); /*ISA mode*/ return 0; case 0xcb: /*AMI - set keyboard mode*/ -#ifdef ENABLE_KEYBOARD_LOG - kbd_log("ATkbd: AMI - set keyboard mode\n"); -#endif + DEBUG("ATkbd: AMI - set keyboard mode\n"); kbd->want60 = 1; return 0; case 0xef: /*??? - sent by AMI486*/ -#ifdef ENABLE_KEYBOARD_LOG - kbd_log("ATkbd: ??? - sent by AMI486\n"); -#endif + DEBUG("ATkbd: ??? - sent by AMI486\n"); return 0; } @@ -1464,34 +1357,26 @@ kbd_write64_ibm_mca(void *p, uint8_t val) switch (val) { case 0xc1: /*Copy bits 0 to 3 of input port to status bits 4 to 7*/ -#ifdef ENABLE_KEYBOARD_LOG - kbd_log("ATkbd: copy bits 0 to 3 of input port to status bits 4 to 7\n"); -#endif + DEBUG("ATkbd: copy bits 0 to 3 of input port to status bits 4 to 7\n"); kbd->status &= 0xf; kbd->status |= ((((kbd->input_port & 0xfc) | 0x84 | fdc_ps1_525()) & 0xf) << 4); return 0; case 0xc2: /*Copy bits 4 to 7 of input port to status bits 4 to 7*/ -#ifdef ENABLE_KEYBOARD_LOG - kbd_log("ATkbd: copy bits 4 to 7 of input port to status bits 4 to 7\n"); -#endif + DEBUG("ATkbd: copy bits 4 to 7 of input port to status bits 4 to 7\n"); kbd->status &= 0xf; kbd->status |= (((kbd->input_port & 0xfc) | 0x84 | fdc_ps1_525()) & 0xf0); return 0; case 0xaf: -#ifdef ENABLE_KEYBOARD_LOG - kbd_log("ATkbd: bad KBC command AF\n"); -#endif + DEBUG("ATkbd: bad KBC command AF\n"); return 1; case 0xf0: case 0xf1: case 0xf2: case 0xf3: case 0xf4: case 0xf5: case 0xf6: case 0xf7: case 0xf8: case 0xf9: case 0xfa: case 0xfb: case 0xfc: case 0xfd: case 0xfe: case 0xff: -#ifdef ENABLE_KEYBOARD_LOG - kbd_log("ATkbd: pulse: %01X\n", (val & 0x03) | 0x0c); -#endif + DEBUG("ATkbd: pulse: %01X\n", (val & 0x03) | 0x0c); kbd_output_pulse(kbd, (val & 0x03) | 0x0c); return 0; } @@ -1507,9 +1392,7 @@ kbd_write60_quadtel(void *p, uint8_t val) switch(kbd->command) { case 0xcf: /*??? - sent by MegaPC BIOS*/ -#ifdef ENABLE_KEYBOARD_LOG - kbd_log("ATkbd: ??? - sent by MegaPC BIOS\n"); -#endif + DEBUG("ATkbd: ??? - sent by MegaPC BIOS\n"); return 0; } @@ -1524,15 +1407,11 @@ kbd_write64_quadtel(void *p, uint8_t val) switch (val) { case 0xaf: -#ifdef ENABLE_KEYBOARD_LOG - kbd_log("ATkbd: bad KBC command AF\n"); -#endif + DEBUG("ATkbd: bad KBC command AF\n"); return 1; case 0xcf: /*??? - sent by MegaPC BIOS*/ -#ifdef ENABLE_KEYBOARD_LOG - kbd_log("ATkbd: ??? - sent by MegaPC BIOS\n"); -#endif + DEBUG("ATkbd: ??? - sent by MegaPC BIOS\n"); kbd->want60 = 1; return 0; } @@ -1563,9 +1442,7 @@ kbd_write64_toshiba(void *p, uint8_t val) switch (val) { case 0xaf: -#ifdef ENABLE_KEYBOARD_LOG - kbd_log("ATkbd: bad KBC command AF\n"); -#endif + DEBUG("ATkbd: bad KBC command AF\n"); return 1; case 0xb0: /* T3100e: Turbo on */ @@ -1615,9 +1492,7 @@ kbd_write64_toshiba(void *p, uint8_t val) return 0; case 0xc0: /*Read input port*/ -#ifdef ENABLE_KEYBOARD_LOG - kbd_log("ATkbd: read input port\n"); -#endif + DEBUG("ATkbd: read input port\n"); /* The T3100e returns all bits set except bit 6 which * is set by t3100e_mono_set() */ @@ -1639,12 +1514,11 @@ kbd_write(uint16_t port, uint8_t val, void *priv) int bad = 1; uint8_t mask; - if (romset == ROM_XI8088 && port == 0x63) + if (((kbd->flags & KBC_VEN_MASK) == KBC_VEN_XI8088) && (port == 0x63)) port = 0x61; -#ifdef _DEBUG - kbd_log("ATkbd: write(%04X, %02X)\n", port, val); -#endif + DBGLOG(2, "ATkbd: write(%04X, %02X)\n", port, val); + switch (port) { case 0x60: if (kbd->want60) { @@ -1665,9 +1539,7 @@ kbd_write(uint16_t port, uint8_t val, void *priv) break; case 0xd1: /*Write output port*/ -#ifdef ENABLE_KEYBOARD_LOG - // kbd_log("ATkbd: write output port\n"); -#endif + DEBUG("ATkbd: write output port\n"); if (kbd->output_locked) { /*If keyboard controller lines P22-P23 are blocked, we force them to remain unchanged.*/ @@ -1678,33 +1550,23 @@ kbd_write(uint16_t port, uint8_t val, void *priv) break; case 0xd2: /*Write to keyboard output buffer*/ -#ifdef ENABLE_KEYBOARD_LOG - kbd_log("ATkbd: write to keyboard output buffer\n"); -#endif + DEBUG("ATkbd: write to keyboard output buffer\n"); kbd_adddata_keyboard(val); break; case 0xd3: /*Write to mouse output buffer*/ -#ifdef ENABLE_KEYBOARD_LOG - kbd_log("ATkbd: write to mouse output buffer\n"); -#endif + DEBUG("ATkbd: write to mouse output buffer\n"); if (mouse_write && ((kbd->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_1)) keyboard_at_adddata_mouse(val); break; case 0xd4: /*Write to mouse*/ -#ifdef ENABLE_KEYBOARD_LOG - kbd_log("ATkbd: write to mouse (%02X)\n", val); -#endif + DEBUG("ATkbd: write to mouse (%02X)\n", val); kbd_mouse_set(kbd, 1); if (mouse_write && ((kbd->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_1)) mouse_write(val, mouse_p); - else if (!mouse_write && ((kbd->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_1)) { -#ifdef ENABLE_KEYBOARD_LOG - kbd_log("ATkbd: adding 0xFF to queue\n"); -#endif + else if (!mouse_write && ((kbd->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_1)) keyboard_at_adddata_mouse(0xff); - } break; default: @@ -1713,12 +1575,9 @@ kbd_write(uint16_t port, uint8_t val, void *priv) if (kbd->write60_ven) bad = kbd->write60_ven(kbd, val); -#ifdef ENABLE_KEYBOARD_LOG - if (bad) - kbd_log("ATkbd: bad keyboard controller 0060 write %02X command %02X\n", val, kbd->command); -#else - (void)bad; -#endif + if (bad) { + ERRLOG("ATkbd: bad keyboard controller 0060 write %02X command %02X\n", val, kbd->command); + } } } else { /*Write to keyboard*/ @@ -1736,13 +1595,13 @@ kbd_write(uint16_t port, uint8_t val, void *priv) case 0xf0: /*Get/set scancode set*/ kbd_adddata_keyboard(0xfa); if (val == 0) { - kbd_log("ATkbd: get scan code set: %02X\n", keyboard_mode & 3); + DEBUG("ATkbd: get scan code set: %02X\n", keyboard_mode & 3); kbd_adddata_keyboard(keyboard_mode & 3); } else { if ((val <= 3) && (val != 1)) { keyboard_mode &= 0xfc; keyboard_mode |= (val & 3); - kbd_log("ATkbd: scan code set now: %02X\n", val); + DEBUG("ATkbd: scan code set now: %02X\n", val); } kbd_setmap(kbd); } @@ -1753,9 +1612,7 @@ kbd_write(uint16_t port, uint8_t val, void *priv) break; default: -#ifdef ENABLE_KEYBOARD_LOG - kbd_log("ATkbd: bad keyboard 0060 write %02X command %02X\n", val, kbd->key_command); -#endif + DEBUG("ATkbd: bad keyboard 0060 write %02X command %02X\n", val, kbd->key_command); break; } @@ -1770,30 +1627,22 @@ do_command: switch (val) { case 0x00: -#ifdef ENABLE_KEYBOARD_LOG - kbd_log("ATkbd: command 00\n"); -#endif + DEBUG("ATkbd: command 00\n"); kbd_adddata_keyboard(0xfa); break; case 0x05: /*??? - sent by NT 4.0*/ -#ifdef ENABLE_KEYBOARD_LOG - kbd_log("ATkbd: NT4.0 command FE\n"); -#endif + DEBUG("ATkbd: NT4.0 command FE\n"); kbd_adddata_keyboard(0xfe); break; case 0x71: /*These two commands are sent by Pentium-era AMI BIOS'es.*/ case 0x82: -#ifdef ENABLE_KEYBOARD_LOG - kbd_log("ATkbd: Pentium-era AMI BIOS command %02X\n", val); -#endif + DEBUG("ATkbd: Pentium-era AMI BIOS command %02X\n", val); break; case 0xed: /*Set/reset LEDs*/ -#ifdef ENABLE_KEYBOARD_LOG - kbd_log("ATkbd: set/reset leds\n"); -#endif + DEBUG("ATkbd: set/reset leds\n"); kbd_adddata_keyboard(0xfa); kbd->key_wantdata = 1; @@ -1801,22 +1650,16 @@ do_command: break; case 0xee: /*Diagnostic echo*/ -#ifdef ENABLE_KEYBOARD_LOG - kbd_log("ATkbd: ECHO\n"); -#endif + DEBUG("ATkbd: ECHO\n"); kbd_adddata_keyboard(0xee); break; case 0xef: /*NOP (No OPeration). Reserved for future use.*/ -#ifdef ENABLE_KEYBOARD_LOG - kbd_log("ATkbd: NOP\n"); -#endif + DEBUG("ATkbd: NOP\n"); break; case 0xf0: /*Get/set scan code set*/ -#ifdef ENABLE_KEYBOARD_LOG - kbd_log("ATkbd: scan code set\n"); -#endif + DEBUG("ATkbd: scan code set\n"); kbd_adddata_keyboard(0xfa); kbd->key_wantdata = 1; kbd->key_command = val; @@ -1824,37 +1667,27 @@ do_command: case 0xf2: /*Read ID*/ /* Fixed as translation will be done in kbd_adddata_keyboard(). */ -#ifdef ENABLE_KEYBOARD_LOG - kbd_log("ATkbd: read keyboard id\n"); -#endif + DEBUG("ATkbd: read keyboard id\n"); kbd_adddata_keyboard(0xfa); -#if 0 kbd_adddata_keyboard(0xab); kbd_adddata_keyboard(0x83); -#endif break; case 0xf3: /*Set typematic rate/delay*/ -#ifdef ENABLE_KEYBOARD_LOG - kbd_log("ATkbd: set typematic rate/delay\n"); -#endif + DEBUG("ATkbd: set typematic rate/delay\n"); kbd_adddata_keyboard(0xfa); kbd->key_wantdata = 1; kbd->key_command = val; break; case 0xf4: /*Enable keyboard*/ -#ifdef ENABLE_KEYBOARD_LOG - kbd_log("ATkbd: enable keyboard via keyboard\n"); -#endif + DEBUG("ATkbd: enable keyboard via keyboard\n"); kbd_adddata_keyboard(0xfa); keyboard_scan = 1; break; case 0xf5: /*Disable keyboard*/ -#ifdef ENABLE_KEYBOARD_LOG - kbd_log("ATkbd: disable keyboard via keyboard\n"); -#endif + DEBUG("ATkbd: disable keyboard via keyboard\n"); kbd_adddata_keyboard(0xfa); keyboard_scan = 0; @@ -1866,62 +1699,48 @@ do_command: /*FALLTHROUGH*/ case 0xf6: /*Set defaults*/ -#ifdef ENABLE_KEYBOARD_LOG - kbd_log("ATkbd: set defaults\n"); -#endif + DEBUG("ATkbd: set defaults\n"); kbd_adddata_keyboard(0xfa); keyboard_set3_all_break = 0; keyboard_set3_all_repeat = 0; memset(keyboard_set3_flags, 0, 512); - keyboard_mode = (keyboard_mode & 0xFC) | 0x02; + keyboard_mode = (keyboard_mode & 0xfc) | 0x02; kbd_setmap(kbd); break; case 0xf7: /*Set all keys to repeat*/ -#ifdef ENABLE_KEYBOARD_LOG - kbd_log("ATkbd: set all keys to repeat\n"); -#endif + DEBUG("ATkbd: set all keys to repeat\n"); kbd_adddata_keyboard(0xfa); keyboard_set3_all_break = 1; break; case 0xf8: /*Set all keys to give make/break codes*/ -#ifdef ENABLE_KEYBOARD_LOG - kbd_log("ATkbd: set all keys to give make/break codes\n"); -#endif + DEBUG("ATkbd: set all keys to give make/break codes\n"); kbd_adddata_keyboard(0xfa); keyboard_set3_all_break = 1; break; case 0xf9: /*Set all keys to give make codes only*/ -#ifdef ENABLE_KEYBOARD_LOG - kbd_log("ATkbd: set all keys to give make codes only\n"); -#endif + DEBUG("ATkbd: set all keys to give make codes only\n"); kbd_adddata_keyboard(0xfa); keyboard_set3_all_break = 0; break; case 0xfa: /*Set all keys to repeat and give make/break codes*/ -#ifdef ENABLE_KEYBOARD_LOG - kbd_log("ATkbd: set all keys to repeat and give make/break codes\n"); -#endif + DEBUG("ATkbd: set all keys to repeat and give make/break codes\n"); kbd_adddata_keyboard(0xfa); keyboard_set3_all_repeat = 1; keyboard_set3_all_break = 1; break; case 0xfe: /*Resend last scan code*/ -#ifdef ENABLE_KEYBOARD_LOG - kbd_log("ATkbd: reset last scan code\n"); -#endif + DEBUG("ATkbd: reset last scan code\n"); kbd_adddata_keyboard(kbd->last_scan_code); break; case 0xff: /*Reset*/ -#ifdef ENABLE_KEYBOARD_LOG - kbd_log("ATkbd: kbd reset\n"); -#endif + DEBUG("ATkbd: kbd reset\n"); key_queue_start = key_queue_end = 0; /*Clear key queue*/ kbd_adddata_keyboard(0xfa); kbd_adddata_keyboard(0xaa); @@ -1932,9 +1751,7 @@ do_command: break; default: -#ifdef ENABLE_KEYBOARD_LOG - kbd_log("ATkbd: bad keyboard command %02X\n", val); -#endif + ERRLOG("ATkbd: bad keyboard command %02X\n", val); kbd_adddata_keyboard(0xfe); } } @@ -1954,7 +1771,7 @@ do_command: was_speaker_enable = 1; pit_set_gate(&pit, 2, val & 1); - if (romset == ROM_XI8088) { + if ((kbd->flags & KBC_VEN_MASK) == KBC_VEN_XI8088) { if (val & 0x04) xi8088_turbo_set(1); else @@ -1970,7 +1787,7 @@ do_command: * keyboard-command data mode, abort that... */ if (kbd->key_wantdata || kbd->key_command) { - kbd_log("ATkbd: *** BUG ALERT *** aborting previous keyboard command 0x%02X (data %d)\n", kbd->key_command, kbd->key_wantdata); + ERRLOG("ATkbd: *** BUG ALERT *** aborting previous keyboard command 0x%02X (data %d)\n", kbd->key_command, kbd->key_wantdata); /* If they were waiting for data.. */ kbd_adddata(0xfa); @@ -2008,9 +1825,7 @@ do_command: break; case 0xaa: /*Self-test*/ -#ifdef ENABLE_KEYBOARD_LOG - kbd_log("ATkbd: self-test\n"); -#endif + DEBUG("ATkbd: self-test\n"); if ((kbd->flags & KBC_VEN_MASK) == KBC_VEN_TOSHIBA) kbd->status |= STAT_IFULL; if (! kbd->initialized) { @@ -2028,16 +1843,12 @@ do_command: break; case 0xab: /*Interface test*/ -#ifdef ENABLE_KEYBOARD_LOG - kbd_log("ATkbd: interface test\n"); -#endif + DEBUG("ATkbd: interface test\n"); kbd_adddata(0x00); /*no error*/ break; case 0xac: /*Diagnostic dump*/ -#ifdef ENABLE_KEYBOARD_LOG - kbd_log("ATkbd: diagnostic dump\n"); -#endif + DEBUG("ATkbd: diagnostic dump\n"); for (i = 0; i < 16; i++) kbd_adddata(kbd->mem[i]); kbd_adddata((kbd->input_port & 0xf0) | 0x80); @@ -2046,23 +1857,17 @@ do_command: break; case 0xad: /*Disable keyboard*/ -#ifdef ENABLE_KEYBOARD_LOG - kbd_log("ATkbd: disable keyboard\n"); -#endif + DEBUG("ATkbd: disable keyboard\n"); kbd_keyboard_set(kbd, 0); break; case 0xae: /*Enable keyboard*/ -#ifdef ENABLE_KEYBOARD_LOG - kbd_log("ATkbd: enable keyboard\n"); -#endif + DEBUG("ATkbd: enable keyboard\n"); kbd_keyboard_set(kbd, 1); break; case 0xd0: /*Read output port*/ -#ifdef ENABLE_KEYBOARD_LOG - kbd_log("ATkbd: read output port\n"); -#endif + DEBUG("ATkbd: read output port\n"); mask = 0xff; if (! keyboard_scan) mask &= 0xbf; @@ -2072,37 +1877,27 @@ do_command: break; case 0xd1: /*Write output port*/ -#ifdef ENABLE_KEYBOARD_LOG - kbd_log("ATkbd: write output port\n"); -#endif + DEBUG("ATkbd: write output port\n"); kbd->want60 = 1; break; case 0xd2: /*Write keyboard output buffer*/ -#ifdef ENABLE_KEYBOARD_LOG - kbd_log("ATkbd: write keyboard output buffer\n"); -#endif + DEBUG("ATkbd: write keyboard output buffer\n"); kbd->want60 = 1; break; case 0xdd: /* Disable A20 Address Line */ -#ifdef ENABLE_KEYBOARD_LOG - kbd_log("ATkbd: disable A20\n"); -#endif + DEBUG("ATkbd: disable A20\n"); kbd_output_write(kbd, kbd->output_port & 0xfd); break; case 0xdf: /* Enable A20 Address Line */ -#ifdef ENABLE_KEYBOARD_LOG - kbd_log("ATkbd: enable A20\n"); -#endif + DEBUG("ATkbd: enable A20\n"); kbd_output_write(kbd, kbd->output_port | 0x02); break; case 0xe0: /*Read test inputs*/ -#ifdef ENABLE_KEYBOARD_LOG - kbd_log("ATkbd: read test inputs\n"); -#endif + DEBUG("ATkbd: read test inputs\n"); kbd_adddata(0x00); break; @@ -2112,10 +1907,9 @@ do_command: if (kbd->write64_ven) bad = kbd->write64_ven(kbd, val); -#ifdef ENABLE_KEYBOARD_LOG - if (bad) - kbd_log("ATkbd: bad controller command %02X\n", val); -#endif + if (bad) { + DEBUG("ATkbd: bad controller command %02X\n", val); + } } break; } @@ -2128,7 +1922,7 @@ kbd_read(uint16_t port, void *priv) atkbd_t *kbd = (atkbd_t *)priv; uint8_t ret = 0xff; - if (romset == ROM_XI8088 && port == 0x63) + if (((kbd->flags & KBC_VEN_MASK) == KBC_VEN_XI8088) && (port == 0x63)) port = 0x61; switch (port) { @@ -2151,7 +1945,7 @@ kbd_read(uint16_t port, void *priv) else ret &= ~0x10; } - if (romset == ROM_XI8088){ + if ((kbd->flags & KBC_VEN_MASK) == KBC_VEN_XI8088) { if (xi8088_turbo_get()) ret |= 0x04; else @@ -2168,9 +1962,7 @@ kbd_read(uint16_t port, void *priv) break; } -#ifdef _DEBUG - kbd_log("ATkbd: read(%04X) = %02X\n", port, ret); -#endif + DBGLOG(2, "ATkbd: read(%04X) = %02X\n", port, ret); return(ret); } @@ -2198,7 +1990,7 @@ kbd_reset(void *priv) kbd->mem[0] = 0x01; kbd->wantirq = 0; kbd_output_write(kbd, 0xcf); - kbd->input_port = (video_is_mda()) ? 0xf0 : 0xb0; + kbd->input_port = (video_type() == VID_TYPE_MDA) ? 0xf0 : 0xb0; kbd->out_new = -1; kbd->last_irq = 0; kbd->secr_phase = 0; @@ -2210,7 +2002,9 @@ kbd_reset(void *priv) kbd_mouse_set(kbd, 0); sc_or = 0; +#if 0 keyboard_update_states(0, 0, 0); +#endif memset(keyboard_set3_flags, 0, 512); @@ -2223,7 +2017,7 @@ kbd_init(const device_t *info) { atkbd_t *kbd; - kbd = (atkbd_t *)malloc(sizeof(atkbd_t)); + kbd = (atkbd_t *)mem_alloc(sizeof(atkbd_t)); memset(kbd, 0x00, sizeof(atkbd_t)); kbd->flags = info->local; @@ -2316,91 +2110,100 @@ const device_t keyboard_at_device = { "PC/AT Keyboard", 0, KBC_TYPE_ISA | KBC_VEN_GENERIC, - kbd_init, - kbd_close, - kbd_reset, - NULL, NULL, NULL, NULL + kbd_init, kbd_close, kbd_reset, + NULL, NULL, NULL, NULL, + NULL }; const device_t keyboard_at_ami_device = { "PC/AT Keyboard (AMI)", 0, KBC_TYPE_ISA | KBC_VEN_AMI, - kbd_init, - kbd_close, - kbd_reset, - NULL, NULL, NULL, NULL + kbd_init, kbd_close, kbd_reset, + NULL, NULL, NULL, NULL, + NULL }; const device_t keyboard_at_toshiba_device = { "PC/AT Keyboard (Toshiba)", 0, KBC_TYPE_ISA | KBC_VEN_TOSHIBA, - kbd_init, - kbd_close, - kbd_reset, - NULL, NULL, NULL, NULL + kbd_init, kbd_close, kbd_reset, + NULL, NULL, NULL, NULL, + NULL }; const device_t keyboard_ps2_device = { "PS/2 Keyboard", 0, KBC_TYPE_PS2_1 | KBC_VEN_GENERIC, - kbd_init, - kbd_close, - kbd_reset, - NULL, NULL, NULL, NULL + kbd_init, kbd_close, kbd_reset, + NULL, NULL, NULL, NULL, + NULL +}; + +const device_t keyboard_ps2_xi8088_device = { + "PS/2 Keyboard (Xi8088)", + 0, + KBC_TYPE_PS2_1 | KBC_VEN_XI8088, + kbd_init, kbd_close, kbd_reset, + NULL, NULL, NULL, NULL, + NULL }; const device_t keyboard_ps2_ami_device = { "PS/2 Keyboard (AMI)", 0, KBC_TYPE_PS2_1 | KBC_VEN_AMI, - kbd_init, - kbd_close, - kbd_reset, - NULL, NULL, NULL, NULL + kbd_init, kbd_close, kbd_reset, + NULL, NULL, NULL, NULL, + NULL }; const device_t keyboard_ps2_mca_device = { "PS/2 Keyboard", 0, KBC_TYPE_PS2_1 | KBC_VEN_IBM_MCA, - kbd_init, - kbd_close, - kbd_reset, - NULL, NULL, NULL, NULL + kbd_init, kbd_close, kbd_reset, + NULL, NULL, NULL, NULL, + NULL }; const device_t keyboard_ps2_mca_2_device = { "PS/2 Keyboard", 0, KBC_TYPE_PS2_2 | KBC_VEN_IBM_MCA, - kbd_init, - kbd_close, - kbd_reset, - NULL, NULL, NULL, NULL + kbd_init, kbd_close, kbd_reset, + NULL, NULL, NULL, NULL, + NULL }; const device_t keyboard_ps2_quadtel_device = { "PS/2 Keyboard (Quadtel/MegaPC)", 0, KBC_TYPE_PS2_1 | KBC_VEN_QUADTEL, - kbd_init, - kbd_close, - kbd_reset, - NULL, NULL, NULL, NULL + kbd_init, kbd_close, kbd_reset, + NULL, NULL, NULL, NULL, + NULL }; +const device_t keyboard_ps2_pci_device = { + "PS/2 Keyboard", + DEVICE_PCI, + KBC_TYPE_PS2_1 | KBC_VEN_GENERIC, + kbd_init, kbd_close, kbd_reset, + NULL, NULL, NULL, NULL, + NULL +}; -void -keyboard_at_reset(void) -{ - atkbd_t *kbd = CurrentKbd; - - if (kbd != NULL) - kbd_reset(kbd); -} +const device_t keyboard_ps2_ami_pci_device = { + "PS/2 Keyboard (AMI)", + DEVICE_PCI, + KBC_TYPE_PS2_1 | KBC_VEN_AMI, + kbd_init, kbd_close, kbd_reset, + NULL, NULL, NULL, NULL, + NULL +}; void @@ -2437,9 +2240,7 @@ keyboard_at_set_mouse_scan(uint8_t val) kbd_mouse_set(kbd, val ? 1 : 0); -#ifdef ENABLE_KEYBOARD_LOG - kbd_log("ATkbd: mouse scan %sabled via PCI\n", mouse_scan ? "en" : "dis"); -#endif + INFO("ATkbd: mouse scan %sabled via PCI\n", mouse_scan ? "en" : "dis"); } diff --git a/src/devices/input/keyboard_xt.c b/src/devices/input/keyboard_xt.c index fd9a004..d346c0e 100644 --- a/src/devices/input/keyboard_xt.c +++ b/src/devices/input/keyboard_xt.c @@ -8,7 +8,7 @@ * * Implementation of the XT-style keyboard. * - * Version: @(#)keyboard_xt.c 1.0.7 2018/05/06 + * Version: @(#)keyboard_xt.c 1.0.8 2018/10/05 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -41,6 +41,7 @@ #include #include #include +#define dbglog kbd_log #include "../../emu.h" #include "../../machines/machine.h" #include "../../io.h" @@ -66,12 +67,11 @@ typedef struct { - int blocked; + int8_t blocked; + uint8_t type; - uint8_t pa; - uint8_t pb; - - int tandy; + uint8_t pa; + uint8_t pb; } xtkbd_t; @@ -351,10 +351,8 @@ kbd_poll(void *priv) if (key_queue_start != key_queue_end && !kbd->blocked) { kbd->pa = key_queue[key_queue_start]; picint(2); -#ifdef ENABLE_KEYBOARD_LOG - kbd_log("XTkbd: reading %02X from the key queue at %i\n", - kbd->pa, key_queue_start); -#endif + DBGLOG(1, "XTkbd: reading %02X from the key queue at %i\n", + kbd->pa, key_queue_start); key_queue_start = (key_queue_start + 1) & 0x0f; kbd->blocked = 1; } @@ -365,10 +363,9 @@ static void kbd_adddata(uint16_t val) { key_queue[key_queue_end] = val & 0xff; -#ifdef ENABLE_KEYBOARD_LOG - kbd_log("XTkbd: %02X added to key queue at %i\n", + + DBGLOG(1, "XTkbd: %02X added to key queue at %i\n", val, key_queue_end); -#endif key_queue_end = (key_queue_end + 1) & 0x0f; } @@ -378,10 +375,9 @@ kbd_adddata_process(uint16_t val, void (*adddata)(uint16_t val)) { uint8_t num_lock = 0, shift_states = 0; - if (!adddata) - return; + if (adddata == NULL) return; - keyboard_get_states(NULL, &num_lock, NULL); + num_lock = !!(keyboard_get_state() & KBD_FLAG_NUM); shift_states = keyboard_get_shift() & STATE_SHIFT_MASK; switch(val) { @@ -443,9 +439,7 @@ kbd_write(uint16_t port, uint8_t val, void *priv) if (port != 0x61) return; if (!(kbd->pb & 0x40) && (val & 0x40)) { /*Reset keyboard*/ -#ifdef ENABLE_KEYBOARD_LOG - kbd_log("XTkbd: reset keyboard\n"); -#endif + DEBUG("XTkbd: reset keyboard\n"); key_queue_end = key_queue_start; kbd_adddata(0xaa); } @@ -475,16 +469,18 @@ kbd_read(uint16_t port, void *priv) { xtkbd_t *kbd = (xtkbd_t *)priv; uint8_t ret = 0xff; + int vid; switch (port) { case 0x60: - if ((romset == ROM_IBMPC) && (kbd->pb & 0x80)) { - if (video_is_ega_vga()) - ret = 0x4d; - else if (video_is_mda()) - ret = 0x7d; + if ((kbd->type == 0) && (kbd->pb & 0x80)) { + vid = video_type(); + if (vid == VID_TYPE_SPEC) + ret = 0x4d; /* EGA/VGA */ + else if (vid == VID_TYPE_MDA) + ret = 0x7d; /* MDA/Hercules */ else - ret = 0x6d; + ret = 0x6d; /* CGA */ } else ret = kbd->pa; break; @@ -494,41 +490,39 @@ kbd_read(uint16_t port, void *priv) break; case 0x62: - if (romset == ROM_IBMPC) { + if (kbd->type == 0) { if (kbd->pb & 0x04) ret = ((mem_size-64) / 32) & 0x0f; else ret = ((mem_size-64) / 32) >> 4; + } else if (kbd->pb & 0x08) { + vid = video_type(); + if (vid == VID_TYPE_SPEC) + ret = 0x4; /* EGA/VGA */ + else if (vid == VID_TYPE_MDA) + ret = 0x7; /* MDA/Hercules */ + else + ret = 0x6; /* CGA */ } else { - if (kbd->pb & 0x08) { - if (video_is_ega_vga()) - ret = 0x4; - else if (video_is_mda()) - ret = 0x7; - else - ret = 0x6; - } else { - /* LaserXT = Always 512k RAM; - LaserXT/3 = Bit 0: set = 512k, clear = 256k. */ + /* LaserXT = Always 512k RAM; + LaserXT/3 = Bit 0: set = 512k, clear = 256k. */ #if defined(DEV_BRANCH) && defined(USE_LASERXT) - if (romset == ROM_LXT3) - ret = (mem_size == 512) ? 0x0d : 0x0c; - else + if (kbd->type == 3) + ret = (mem_size == 512) ? 0x0d : 0x0c; + else #endif - ret = 0x0d; - } + ret = 0x0d; } + ret |= (ppispeakon ? 0x20 : 0); - if (kbd->tandy) + if (kbd->type == 2) ret |= (tandy1k_eeprom_read() ? 0x10 : 0); break; default: -#ifdef ENABLE_KEYBOARD_LOG - kbd_log("XTkbd: bad read %04X\n", port); -#endif - ret = 0xff; + ERRLOG("XTkbd: bad read %04X\n", port); + break; } return(ret); @@ -554,20 +548,19 @@ kbd_init(const device_t *info) { xtkbd_t *kbd; - kbd = (xtkbd_t *)malloc(sizeof(xtkbd_t)); + kbd = (xtkbd_t *)mem_alloc(sizeof(xtkbd_t)); memset(kbd, 0x00, sizeof(xtkbd_t)); + kbd->type = info->local; keyboard_set_table(scancode_xt); - if (info->local == 1) { - kbd->tandy = 1; - } - keyboard_scan = 1; io_sethandler(0x0060, 4, kbd_read, NULL, NULL, kbd_write, NULL, NULL, kbd); + keyboard_send = kbd_adddata_ex; + timer_add(kbd_poll, &keyboard_delay, TIMER_ALWAYS_ENABLED, kbd); return(kbd); @@ -594,22 +587,38 @@ kbd_close(void *priv) } +const device_t keyboard_pc_device = { + "IBM PC Keyboard", + 0, + 0, + kbd_init, kbd_close, kbd_reset, + NULL, NULL, NULL, NULL, + NULL +}; + const device_t keyboard_xt_device = { - "PC/XT Keyboard", + "IBM PC/XT Keyboard", 0, - 0, - kbd_init, - kbd_close, - kbd_reset, - NULL, NULL, NULL, NULL + 1, + kbd_init, kbd_close, kbd_reset, + NULL, NULL, NULL, NULL, + NULL }; const device_t keyboard_tandy_device = { "Tandy 1000 Keyboard", 0, - 1, - kbd_init, - kbd_close, - kbd_reset, - NULL, NULL, NULL, NULL + 2, + kbd_init, kbd_close, kbd_reset, + NULL, NULL, NULL, NULL, + NULL +}; + +const device_t keyboard_xt_lxt3_device = { + "VTech Laser XT3 Keyboard", + 0, + 3, + kbd_init, kbd_close, kbd_reset, + NULL, NULL, NULL, NULL, + NULL }; diff --git a/src/devices/input/mouse.c b/src/devices/input/mouse.c index d06ceb4..d37a469 100644 --- a/src/devices/input/mouse.c +++ b/src/devices/input/mouse.c @@ -10,7 +10,7 @@ * * TODO: Add the Genius bus- and serial mouse. * - * Version: @(#)mouse.c 1.0.11 2018/05/06 + * Version: @(#)mouse.c 1.0.12 2018/10/05 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -51,7 +51,10 @@ #include #include #include +#include #include +#define HAVE_STDARG_H +#define dbglog mouse_log #include "../../emu.h" #include "../../device.h" #include "mouse.h" @@ -110,6 +113,21 @@ static int mouse_nbut; static device_t mouse_dev; +void +mouse_log(int level, const char *fmt, ...) +{ +#ifdef ENABLE_MOUSE_LOG + va_list ap; + + if (mouse_do_log >= level) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +#endif +} + + /* Initialize the mouse module. */ void mouse_init(void) @@ -138,8 +156,8 @@ mouse_reset(void) /* Nothing to do if no mouse, or a machine-internal one. */ if (mouse_type <= MOUSE_INTERNAL) return; - pclog("MOUSE: reset(type=%d, '%s')\n", - mouse_type, mouse_devices[mouse_type].device->name); + INFO("MOUSE: reset(type=%d, '%s')\n", + mouse_type, mouse_devices[mouse_type].device->name); /* Clear local data. */ mouse_x = mouse_y = mouse_z = 0; @@ -166,6 +184,7 @@ void mouse_process(void) { static int poll_delay = 2; + int (*func)(int, int, int, int, void *); if ((mouse_priv == NULL) || /* no or no active device */ (mouse_type == MOUSE_NONE)) return; @@ -174,12 +193,13 @@ mouse_process(void) mouse_poll(); - if (mouse_dev.available != NULL) { - if (! mouse_dev.available(mouse_x,mouse_y,mouse_z,mouse_buttons, mouse_priv)) { + func = mouse_dev.ms_poll; + if (func != NULL) { + if (! func(mouse_x,mouse_y,mouse_z,mouse_buttons, mouse_priv)) { /* Poll failed, maybe port closed? */ mouse_close(); - pclog("MOUSE: device closed, mouse disabled!\n"); + ERRLOG("MOUSE: device closed, mouse disabled!\n"); return; } @@ -197,7 +217,7 @@ mouse_set_poll(int (*func)(int,int,int,int,void *), void *arg) { if (mouse_type != MOUSE_INTERNAL) return; - mouse_dev.available = func; + mouse_dev.ms_poll = func; mouse_priv = arg; } @@ -205,7 +225,10 @@ mouse_set_poll(int (*func)(int,int,int,int,void *), void *arg) const char * mouse_get_name(int mouse) { - return(mouse_devices[mouse].device->name); + if (mouse_devices[mouse].device != NULL) + return(mouse_devices[mouse].device->name); + + return(NULL); } @@ -235,9 +258,10 @@ mouse_get_from_internal_name(const char *s) int mouse_has_config(int mouse) { - if (mouse_devices[mouse].device == NULL) return(0); + if (mouse_devices[mouse].device != NULL) + return(mouse_devices[mouse].device->config ? 1 : 0); - return(mouse_devices[mouse].device->config ? 1 : 0); + return(0); } diff --git a/src/devices/input/mouse.h b/src/devices/input/mouse.h index 3282be0..e64d712 100644 --- a/src/devices/input/mouse.h +++ b/src/devices/input/mouse.h @@ -8,7 +8,7 @@ * * Definitions for the mouse driver. * - * Version: @(#)mouse.h 1.0.6 2018/06/06 + * Version: @(#)mouse.h 1.0.8 2018/09/13 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -92,6 +92,7 @@ extern const device_t mouse_mswhserial_device; extern const device_t mouse_ps2_device; #endif +extern void mouse_log(int level, const char *fmt, ...); extern void mouse_init(void); extern void mouse_close(void); extern void mouse_reset(void); diff --git a/src/devices/input/mouse_bus.c b/src/devices/input/mouse_bus.c index 21756f3..9279957 100644 --- a/src/devices/input/mouse_bus.c +++ b/src/devices/input/mouse_bus.c @@ -14,46 +14,51 @@ * although alike enough to be handled in the same driver, they * are not the same. * - * This code is based on my Minix driver for the Logitech(-mode) - * interface. Although that driver blindly took IRQ5, the board - * seems to be able to tell the driver what IRQ it is set for. - * When testing on MS-DOS (6.22), the 'mouse.exe' driver did not - * want to start, and only after disassembling it and inspecting - * the code it was discovered that driver actually does use the - * IRQ reporting feature. In a really, really weird way, too: it - * sets up the board, and then reads the CTRL register which is - * supposed to return that IRQ value. Depending on whether or - * not the FREEZE bit is set, it has to return either the two's - * complemented (negated) value, or (if clear) just the value. - * The mouse.com driver reads both values 10,000 times, and - * then makes up its mind. Maybe an effort to 'debounce' the - * reading of the DIP switches? Oh-well. + * NOTES: Ported from Bochs with extensive modifications per testing + * of the real hardware, testing of drivers, and the old code. * - * NOTES: Verified with: - * AMI WinBIOS 486 (5A, no IRQ detect, OK, IRQ5 only) - * Microsoft Mouse.com V2.00 (DOS V6.22, 5A, OK) - * Microsoft Mouse.exe V9.1 (DOS V6.22, A5, OK) - * Logitech LMouse.com V6.02 (DOS V6.22) - * Logitech LMouse.com V6.43 (DOS V6.22) - * Microsoft WfW V3.11 on DOS V6.22 - * GEOS V1.0 (OK, IRQ5 only) - * GEOS V2.0 (OK, IRQ5 only) - * Microsoft Windows 95 OSR2 - * Microsoft Windows 98 SE + * Logitech Bus Mouse verified with: + * Logitech LMouse.com 3.12 + * Logitech LMouse.com 3.30 + * Logitech LMouse.com 3.41 + * Logitech LMouse.com 3.42 + * Logitech LMouse.com 4.00 + * Logitech LMouse.com 5.00 + * Logitech LMouse.com 6.00 + * Logitech LMouse.com 6.02 Beta + * Logitech LMouse.com 6.02 + * Logitech LMouse.com 6.12 + * Logitech LMouse.com 6.20 + * Logitech LMouse.com 6.23 + * Logitech LMouse.com 6.30 + * Logitech LMouse.com 6.31E + * Logitech LMouse.com 6.34 + * Logitech Mouse.exe 6.40 + * Logitech Mouse.exe 6.41 + * Logitech Mouse.exe 6.44 + * Logitech Mouse.exe 6.46 + * Logitech Mouse.exe 6.50 + * Microsoft Mouse.com 2.00 + * Microsoft Mouse.sys 3.00 + * Microsoft Windows 1.00 DR5 + * Microsoft Windows 3.10.026 * Microsoft Windows NT 3.1 - * Microsoft Windows NT 3.51 + * Microsoft Windows 95 * - * The polling frequency for InPort controllers has to - * be changed to programmable. Microsoft uses 30Hz, - * but ATIXL ports are programmable 30-200Hz. + * InPort verified with: + * Logitech LMouse.com 6.12 + * Logitech LMouse.com 6.41 + * Microsoft Windows NT 3.1 + * Microsoft Windows 98 SE * - * Based on an early driver for MINIX 1.5. + * Version: @(#)mouse_bus.c 1.1.0 2018/10/05 * - * Version: @(#)mouse_bus.c 1.0.8 2018/06/06 - * - * Author: Fred N. van Kempen, + * Authors: Fred N. van Kempen, + * Miran Grca, * * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2017,2018 Miran Grca. + * Copyright 200?-2018 Bochs. * * Redistribution and use in source and binary forms, with * or without modification, are permitted provided that the @@ -90,377 +95,196 @@ #include #include #include +#define dbglog mouse_log #include "../../emu.h" -#include "../../config.h" #include "../../io.h" #include "../../timer.h" #include "../../device.h" +#include "../../random.h" #include "../system/pic.h" #include "mouse.h" -#define MOUSE_PORT 0x023c /* default */ -#define MOUSE_IRQ 5 /* default */ -#define MOUSE_IRQ_INTERNAL 2 /* IRQ for internal mice */ -#define MOUSE_BUTTONS 2 /* default */ -#define MOUSE_DEBUG 0 +#define IRQ_MASK ((1 << 5) >> dev->irq) + +/* MS Inport Bus Mouse Adapter */ +#define INP_PORT_CONTROL 0 +#define INP_PORT_DATA 1 +#define INP_PORT_SIGNATURE 2 +#define INP_PORT_CONFIG 3 + +#define INP_CTRL_READ_BUTTONS 0x00 +#define INP_CTRL_READ_X 0x01 +#define INP_CTRL_READ_Y 0x02 +#define INP_CTRL_COMMAND 0x07 +#define INP_CTRL_RAISE_IRQ 0x16 +#define INP_CTRL_RESET 0x80 + +#define INP_HOLD_COUNTER (1 << 5) +#define INP_ENABLE_TIMER_IRQ (1 << 4) +#define INP_ENABLE_DATA_IRQ (1 << 3) +#define INP_PERIOD_MASK 0x07 + +/* MS/Logictech Standard Bus Mouse Adapter */ +#define BUSM_PORT_DATA 0 +#define BUSM_PORT_SIGNATURE 1 +#define BUSM_PORT_CONTROL 2 +#define BUSM_PORT_CONFIG 3 + +#define HOLD_COUNTER (1 << 7) +#define READ_X (0 << 6) +#define READ_Y (1 << 6) +#define READ_LOW (0 << 5) +#define READ_HIGH (1 << 5) +#define DISABLE_IRQ (1 << 4) + +#define DEVICE_ACTIVE (1 << 7) + +#define READ_X_LOW (READ_X | READ_LOW) +#define READ_X_HIGH (READ_X | READ_HIGH) +#define READ_Y_LOW (READ_Y | READ_LOW) +#define READ_Y_HIGH (READ_Y | READ_HIGH) + +#define FLAG_INPORT (1 << 0) +#define FLAG_ENABLED (1 << 1) +#define FLAG_HOLD (1 << 2) +#define FLAG_TIMER_INT (1 << 3) +#define FLAG_DATA_INT (1 << 4) + +static const double periods[4] = { 30.0, 50.0, 100.0, 200.0 }; /* Our mouse device. */ typedef struct mouse { - const char *name; /* name of this device */ - int8_t type; /* type of this device */ - int8_t irq; /* IRQ channel to use */ - uint8_t flags; /* device flags */ + const char *name; - uint8_t r_magic, /* MAGIC register */ - r_ctrl, /* CONTROL register (WR) */ - r_conf, /* CONFIG register */ - r_cmd; /* (MS) current command */ + uint16_t base; + int8_t irq, + bn; + uint8_t flags; - uint8_t seq; /* general counter */ + int delayed_dx, delayed_dy, + buttons, + buttons_last, - uint8_t but, /* current mouse status */ - but_last; - uint8_t cur_but; - int8_t x, y; - int x_delay, - y_delay; - uint8_t need_upd; - uint8_t irq_num; + curr_x, curr_y, + curr_b; - int64_t timer; /* mouse event timer */ + uint8_t ctrl, conf, sig, + cmd, toggle; - uint8_t (*read)(struct mouse *, uint16_t); - void (*write)(struct mouse *, uint16_t, uint8_t); + double period; + + int64_t timer_enabled; + int64_t timer; } mouse_t; -#define FLAG_INPORT 0x80 /* device is MS InPort */ -#define FLAG_3BTN 0x20 /* enable 3-button mode */ -#define FLAG_SCALED 0x10 /* enable delta scaling */ -#define FLAG_INTR 0x04 /* dev can send interrupts */ -#define FLAG_FROZEN 0x02 /* do not update counters */ -#define FLAG_ENABLED 0x01 /* dev is enabled for use */ -/* Definitions for Logitech. */ -#define LTMOUSE_DATA 0 /* DATA register */ -#define LTMOUSE_MAGIC 1 /* signature magic register */ -# define LTMAGIC_BYTE1 0xa5 /* most drivers use this */ -# define LTMAGIC_BYTE2 0x5a /* some drivers use this */ -#define LTMOUSE_CTRL 2 /* CTRL register */ -# define LTCTRL_FREEZE 0x80 /* do not sample when set */ -# define LTCTRL_RD_Y_HI 0x60 -# define LTCTRL_RD_Y_LO 0x40 -# define LTCTRL_RD_X_HI 0x20 -# define LTCTRL_RD_X_LO 0x00 -# define LTCTRL_RD_MASK 0x60 -# define LTCTRL_IDIS 0x10 -# define LTCTRL_IENB 0x00 -#define LTMOUSE_CONFIG 3 /* CONFIG register */ - -/* Definitions for Microsoft. */ -#define MSMOUSE_CTRL 0 /* CTRL register */ -# define MSCTRL_RESET 0x80 /* reset controller */ -# define MSCTRL_FREEZE 0x20 /* HOLD- freeze data */ -# define MSCTRL_IENB_A 0x08 /* ATIXL intr enable */ -# define MSCTRL_IENB_M 0x01 /* MS intr enable */ -# define MSCTRL_COMMAND 0x07 -# define MSCTRL_RD_Y 0x02 -# define MSCTRL_RD_X 0x01 -# define MSCTRL_RD_BUT 0x00 -#define MSMOUSE_DATA 1 /* DATA register */ -# define MSDATA_IRQ 0x16 -# define MSDATA_BASE 0x10 /* MS InPort: 30Hz */ -# define MSDATA_HZ30 0x01 /* ATIXL 30Hz */ -# define MSDATA_HZ50 0x02 /* ATIXL 50Hz */ -# define MSDATA_HZ100 0x03 /* ATIXL 100Hz */ -# define MSDATA_HZ200 0x04 /* ATIXL 200Hz */ -#define MSMOUSE_MAGIC 2 /* MAGIC register */ -# define MAGIC_MSBYTE1 0xde /* indicates MS InPort */ -// # define MAGIC_MSBYTE2 0x12 -# define MAGIC_MSBYTE2 0x22 /* According to the Bochs code, this sould be 0x22, not 0x12. */ -#define MSMOUSE_CONFIG 3 /* CONFIG register */ - - -/* Reset the controller state. */ -static void -ms_reset(mouse_t *dev) +/* Handle a READ operation from one of the Logitech registers. */ +static uint8_t +lt_read(uint16_t port, void *priv) { - dev->r_ctrl = 0x00; - dev->r_cmd = 0x00; + mouse_t *dev = (mouse_t *)priv; + uint8_t ret = 0xff; - dev->seq = 0; - - dev->x = dev->y = 0; - dev->but = 0x00; - - dev->flags &= 0xf0; - dev->flags |= (FLAG_INTR | FLAG_ENABLED); - - dev->x_delay = dev->y_delay = 0; - dev->need_upd = 0; - - dev->cur_but = 0x00; -} - - -static void -ms_update_data(mouse_t *dev) -{ - int delta_x, delta_y; - - if (dev->x_delay > 127) { - delta_x = 127; - dev->x_delay -= 127; - } else if (dev->x_delay < -128) { - delta_x = -128; - dev->x_delay += 128; - } else { - delta_x = dev->x_delay; - dev->x_delay = 0; - } - - if (dev->y_delay > 127) { - delta_y = 127; - dev->y_delay -= 127; - } else if (dev->y_delay < -128) { - delta_y = -128; - dev->x_delay += 128; - } else { - delta_y = dev->y_delay; - dev->y_delay = 0; - } - - if ((dev->x_delay == 0) && (dev->y_delay == 0)) - dev->need_upd = 0; - - dev->x = (int8_t) delta_x; - dev->y = (int8_t) delta_y; - dev->cur_but = dev->but; -} - - -/* Handle a WRITE to an InPort register. */ -static void -ms_write(mouse_t *dev, uint16_t port, uint8_t val) -{ - switch (port) { - case MSMOUSE_CTRL: - switch (val) { - case MSCTRL_RESET: - ms_reset(dev); + switch (port & 0x0003) { + case BUSM_PORT_DATA: + /* + * Testing and another source confirm that the + * buttons are *ALWAYS* present, so I'm going + * to change this a bit. + */ + switch (dev->ctrl & 0x60) { + case READ_X_LOW: + ret = dev->curr_x & 0x0f; break; - case MSCTRL_COMMAND: - case MSCTRL_RD_BUT: - case MSCTRL_RD_X: - case MSCTRL_RD_Y: - dev->r_ctrl = val & 0x07; + case READ_X_HIGH: + ret = (dev->curr_x >> 4) & 0x0f; break; - case 0x87: - ms_reset(dev); - dev->r_ctrl = MSCTRL_COMMAND; + case READ_Y_LOW: + ret = dev->curr_y & 0x0f; break; - } - break; - case MSMOUSE_DATA: - picintc(1 << dev->irq); - if (val == MSDATA_IRQ) { - picint(1<irq); - } else switch (dev->r_ctrl) { - case MSCTRL_COMMAND: - if (val & MSCTRL_FREEZE) { - /* Hold the sampling. */ - ms_update_data(dev); - } else { - /* Reset current state. */ - picintc(1 << dev->irq); - } - - if (val & (MSCTRL_IENB_M | MSCTRL_IENB_A)) - dev->flags |= FLAG_INTR; - else - dev->flags &= ~FLAG_INTR; - - dev->r_cmd = val; + case READ_Y_HIGH: + ret = (dev->curr_y >> 4) & 0x0f; break; default: - break; + ERRLOG("MOUSE: READ data in mode %02x\n", dev->ctrl); } + ret |= ((dev->curr_b ^ 7) << 5); break; - case MSMOUSE_MAGIC: + case BUSM_PORT_SIGNATURE: + ret = dev->sig; break; - case MSMOUSE_CONFIG: + case BUSM_PORT_CONTROL: + ret = dev->ctrl; + dev->ctrl |= 0x0f; + + /* + * If the conditions are right, simulate the + * flakiness of the correct IRQ bit. + */ + if (dev->flags & FLAG_TIMER_INT) + dev->ctrl = (dev->ctrl & ~IRQ_MASK) | \ + (random_generate() & IRQ_MASK); + break; + + case BUSM_PORT_CONFIG: + /* + * Read from config port returns ctrl in the upper 4 bits + * when enabled, possibly solid interrupt readout in the + * lower 4 bits, 0xff when not (at power-up). + */ + if (dev->flags & FLAG_ENABLED) + ret = (dev->ctrl | 0x0f) & ~IRQ_MASK; break; } -} - -/* Handle a READ from an InPort register. */ -static uint8_t -ms_read(mouse_t *dev, uint16_t port) -{ - uint8_t ret = 0x00; - - switch (port) { - case MSMOUSE_CTRL: - ret = dev->r_ctrl; - break; - - case MSMOUSE_DATA: - switch (dev->r_ctrl) { - case MSCTRL_RD_BUT: - ret = dev->cur_but; - break; - - case MSCTRL_RD_X: - ret = dev->x; - break; - - case MSCTRL_RD_Y: - ret = dev->y; - break; - - case MSCTRL_COMMAND: - ret = dev->r_cmd; - break; - } - break; - - case MSMOUSE_MAGIC: - if (dev->seq & 0x01) - ret = MAGIC_MSBYTE2; - else - ret = MAGIC_MSBYTE1; - dev->seq ^= 1; - break; - - case MSMOUSE_CONFIG: - /* Not really present in real hardware. */ - break; - } + DBGLOG(2, "MOUSE: read(%04x) = %02x\n", port, ret); return(ret); } -/* Reset the controller state. */ +/* Handle a WRITE operation to one of the Logitech registers. */ static void -lt_reset(mouse_t *dev) -{ - dev->r_magic = 0x00; - dev->r_ctrl = (LTCTRL_IENB); - dev->r_conf = 0x00; - - dev->seq = 0; - - dev->x = dev->y = 0; - dev->but = 0x00; - - dev->flags &= 0xf0; - dev->flags |= FLAG_INTR; - - dev->irq_num = 0; -} - - -/* Called at 30hz */ -static void -bm_timer(void *priv) +lt_write(uint16_t port, uint8_t val, void *priv) { mouse_t *dev = (mouse_t *)priv; - if (dev->flags & FLAG_INPORT) { - dev->timer = ((1000000LL * TIMER_USEC) / 30LL); + DBGLOG(2, "MOUSE: write(%04x, %02x)\n", port, val); - if ((dev->flags & FLAG_INTR) && dev->need_upd) { - picint(1 << dev->irq); - /* pclog("IRQ %i raised\n", dev->irq); */ - } - } else { - picint(1 << dev->irq); - - if (dev->irq_num == 5) { - /* pclog("5th IRQ, enabling mouse...\n"); */ - lt_reset(dev); - dev->flags |= FLAG_ENABLED; - } - - if (dev->irq_num == 4) { - /* pclog("4th IRQ, going for the 5th...\n"); */ - dev->irq_num++; - dev->timer = ((1000000LL * TIMER_USEC) / 30LL); - } else { - /* pclog("IRQ before the 4th, disabling timer...\n"); */ - dev->timer = 0; - } - } -} - - -/* Handle a WRITE to a Logitech register. */ -static void -lt_write(mouse_t *dev, uint16_t port, uint8_t val) -{ - uint8_t b; - - switch (port) { - case LTMOUSE_DATA: /* [00] data register */ + switch (port & 0x0003) { + case BUSM_PORT_DATA: + ERRLOG("MOUSE: R/O reg %04x write (value %02x)\n", port, val); break; - case LTMOUSE_MAGIC: /* [01] magic data register */ - switch(val) { - case LTMAGIC_BYTE1: - case LTMAGIC_BYTE2: - lt_reset(dev); - dev->r_magic = val; - dev->flags |= FLAG_ENABLED; - break; - } + case BUSM_PORT_SIGNATURE: + dev->sig = val; break; - case LTMOUSE_CTRL: /* [02] control register */ - if (!(dev->flags & FLAG_ENABLED)) { - dev->irq_num++; - dev->timer = ((1000000LL * TIMER_USEC) / 30LL); - break; - } + case BUSM_PORT_CONTROL: + dev->ctrl = val | 0x0f; + if (! (val & DISABLE_IRQ)) + dev->flags |= FLAG_TIMER_INT; + else + dev->flags &= ~FLAG_TIMER_INT; - b = (dev->r_ctrl ^ val); - if (b & LTCTRL_FREEZE) { - if (val & LTCTRL_FREEZE) { - /* Hold the sampling while we do something. */ - dev->flags |= FLAG_FROZEN; - } else { - /* Reset current state. */ - dev->flags &= ~FLAG_FROZEN; - dev->x = dev->y = 0; - if (dev->but) - dev->but |= 0x80; - } - } + if (val & HOLD_COUNTER) + dev->flags |= FLAG_HOLD; + else + dev->flags &= ~FLAG_HOLD; - if (b & LTCTRL_IDIS) { - /* Disable or enable interrupts. */ - if (val & LTCTRL_IDIS) - dev->flags &= ~FLAG_INTR; - else - dev->flags |= FLAG_INTR; - } - - /* Save new register value. */ - dev->r_ctrl = val; - - /* Clear any pending interrupts. */ picintc(1 << dev->irq); + break; - case LTMOUSE_CONFIG: /* [03] config register */ + case BUSM_PORT_CONFIG: /* * The original Logitech design was based on using a * 8255 parallel I/O chip. This chip has to be set up @@ -488,128 +312,164 @@ lt_write(mouse_t *dev, uint16_t port, uint8_t val) * being an output port and lower 4 bits an input port, and * enable the sucker. Courtesy Intel 8255 databook. Lars */ - dev->r_conf = val; - break; - - default: + dev->conf = val; + if (val & DEVICE_ACTIVE) { + dev->flags |= (FLAG_ENABLED | FLAG_TIMER_INT); + dev->ctrl = 0x0F & ~IRQ_MASK; + dev->timer = ((int64_t) dev->period) * TIMER_USEC; + dev->timer_enabled = 1LL; + } else { + dev->flags &= ~(FLAG_ENABLED | FLAG_TIMER_INT); + dev->timer = 0LL; + dev->timer_enabled = 0LL; + } break; } } -/* Handle a READ from a Logitech register. */ +/* Handle a READ operation from one of the MS InPort registers. */ static uint8_t -lt_read(mouse_t *dev, uint16_t port) +ms_read(uint16_t port, void *priv) { + mouse_t *dev = (mouse_t *)priv; uint8_t ret = 0xff; - /* The GEOS drivers actually check this. */ - if (! (dev->flags & FLAG_ENABLED)) return(ret); + switch (port & 0x0003) { + case INP_PORT_CONTROL: + ret = dev->ctrl; + break; - switch (port) { - case LTMOUSE_DATA: /* [00] data register */ - ret = 0x07; - if (dev->but & 0x01) /* LEFT */ - ret &= ~0x04; - if (dev->but & 0x02) /* RIGHT */ - ret &= ~0x01; - if (dev->flags & FLAG_3BTN) - if (dev->but & 0x04) /* MIDDLE */ - ret &= ~0x02; - ret <<= 5; - - switch(dev->r_ctrl & LTCTRL_RD_MASK) { - case LTCTRL_RD_X_LO: /* X, low bits */ - ret |= (dev->x & 0x0f); + case INP_PORT_DATA: + switch (dev->cmd) { + case INP_CTRL_READ_BUTTONS: + ret = dev->curr_b | 0x80; break; - case LTCTRL_RD_X_HI: /* X, high bits */ - ret |= (dev->x >> 4) & 0x0f; + case INP_CTRL_READ_X: + ret = dev->curr_x; break; - case LTCTRL_RD_Y_LO: /* Y, low bits */ - ret |= (dev->y & 0x0f); + case INP_CTRL_READ_Y: + ret = dev->curr_y; break; - case LTCTRL_RD_Y_HI: /* Y, high bits */ - ret |= (dev->y >> 4) & 0x0f; + case INP_CTRL_COMMAND: + ret = dev->ctrl; break; + + default: + ERRLOG("MOUSE: reading data port in unsupported mode %02x\n", dev->ctrl); } break; - case LTMOUSE_MAGIC: /* [01] magic data register */ - /* - * Drivers write a magic byte to this register, usually - * this is either 5A (AMI WinBIOS, MS Mouse 2.0) or - * A5 (MS Mouse 9.1, Windows drivers, UNIX/Linux/Minix.) - */ - ret = dev->r_magic; + case INP_PORT_SIGNATURE: + if (dev->toggle) + ret = 0x12; + else + ret = 0xDE; + dev->toggle ^= 1; break; - case LTMOUSE_CTRL: /* [02] control register */ - ret = 0x0f; - if (!(dev->r_ctrl & LTCTRL_IDIS) && (dev->seq++ == 0)) { - /* !IDIS, return DIP switch setting. */ - switch(dev->irq) { - case 2: - ret &= ~0x08; - break; - - case 3: - ret &= ~0x04; - break; - - case 4: - ret &= ~0x02; - break; - - case 5: - ret &= ~0x01; - break; - } - } - break; - - case LTMOUSE_CONFIG: /* [03] config register */ - ret = dev->r_conf; - break; - - default: + case INP_PORT_CONFIG: + ERRLOG("MOUSE: READ from port %04x\n", port); break; } + DBGLOG(2, "MOUSE: read(%04x) = %02x\n", port, ret); + return(ret); } -/* Handle a WRITE operation to one of our registers. */ +/* Handle a WRITE operation to one of the MS InPort registers. */ static void -bm_write(uint16_t port, uint8_t val, void *priv) +ms_write(uint16_t port, uint8_t val, void *priv) { mouse_t *dev = (mouse_t *)priv; -#if MOUSE_DEBUG - pclog("%s: write(%d,%02x)\n", dev->name, port-MOUSE_PORT, val); -#endif + DBGLOG(2, "MOUSE: write(%04x, %02x)\n", port, val); - dev->write(dev, port-MOUSE_PORT, val); -} + switch (port & 0x0003) { + case INP_PORT_CONTROL: + /* Bit 7 is RESET. */ + if (val & INP_CTRL_RESET) + dev->ctrl = 0x00; + /* Bits 2:0 are the internal register index. */ + switch (val & 0x07) { + case INP_CTRL_COMMAND: + case INP_CTRL_READ_BUTTONS: + case INP_CTRL_READ_X: + case INP_CTRL_READ_Y: + dev->cmd = val & 0x07; + break; -/* Handle a READ operation from one of our registers. */ -static uint8_t -bm_read(uint16_t port, void *priv) -{ - mouse_t *dev = (mouse_t *)priv; - uint8_t ret; + default: + ERRLOG("MOUSE: write cmd %02x to port %04x\n", val, port); + } + break; - ret = dev->read(dev, port-MOUSE_PORT); + case INP_PORT_DATA: + picintc(1 << dev->irq); + switch (dev->cmd) { + case INP_CTRL_COMMAND: + if (val & INP_HOLD_COUNTER) + dev->flags |= FLAG_HOLD; + else + dev->flags &= ~FLAG_HOLD; -#if MOUSE_DEBUG > 1 - pclog("%s: read(%d): %02x\n", dev->name, port-MOUSE_PORT, ret); -#endif + if (val & INP_ENABLE_TIMER_IRQ) + dev->flags |= FLAG_TIMER_INT; + else + dev->flags &= ~FLAG_TIMER_INT; - return(ret); + if (val & INP_ENABLE_DATA_IRQ) + dev->flags |= FLAG_DATA_INT; + else + dev->flags &= ~FLAG_DATA_INT; + + switch (val & INP_PERIOD_MASK) { + case 0: + dev->period = 0.0; + dev->timer = 0LL; + dev->timer_enabled = 0LL; + break; + + case 1: + case 2: + case 3: + case 4: + dev->period = 1000000.0 / periods[(val & INP_PERIOD_MASK) - 1]; + dev->timer = ((int64_t) dev->period) * TIMER_USEC; + dev->timer_enabled = (val & INP_ENABLE_TIMER_IRQ) ? 1LL : 0LL; + DBGLOG(1, "MOUSE timer is now %sabled at period %i\n", (val & INP_ENABLE_TIMER_IRQ) ? "en" : "dis", (int32_t) dev->period); + break; + + case 6: + if (val & INP_ENABLE_TIMER_IRQ) + picint(1 << dev->irq); + dev->ctrl &= INP_PERIOD_MASK; + dev->ctrl |= (val & ~INP_PERIOD_MASK); + break; + + default: + ERRLOG("MOUSE: WRITE per %02 to %04x\n", port, val); + } + + dev->ctrl = val; + break; + + default: + ERRLOG("MOUSE: WRITE %02x to port %04x\n", val, port); + } + break; + + case INP_PORT_SIGNATURE: + case INP_PORT_CONFIG: + ERRLOG("MOUSE: WRITE %02x to port %04x\n", val, port); + break; + } } @@ -618,70 +478,153 @@ static int bm_poll(int x, int y, int z, int b, void *priv) { mouse_t *dev = (mouse_t *)priv; + int xor; - /* Return early if nothing to do. */ - if (!x && !y && !z && (dev->but == b)) - return(1); + /* Is the mouse even enabled? */ + if (! (dev->flags & FLAG_ENABLED)) return(1); - /* If we are not enabled, return. */ - if (! (dev->flags & FLAG_ENABLED)) { - pclog("bm_poll(): Mouse not enabled\n"); + /* Has its state changed? */ + if (!x && !y && !((b ^ dev->buttons_last) & 0x07)) { + dev->buttons_last = b; return(1); } -#if 0 - pclog("%s: poll(%d,%d,%d,%02x) %d\n", - dev->name, x, y, z, b, !!(dev->flags & FLAG_FROZEN)); -#endif + /* Convert button states from MRL to LMR. */ + dev->buttons = (uint8_t) (((b & 1) << 2) | ((b & 2) >> 1)); + if (dev->bn == 3) + dev->buttons |= ((b & 4) >> 1); - if (dev->flags & FLAG_SCALED) { - /* Scale down the motion. */ - if ((x < -1) || (x > 1)) x >>= 1; - if ((y < -1) || (y > 1)) y >>= 1; + if ((dev->flags & FLAG_INPORT) && !dev->timer_enabled) { + /* + * This is an InPort mouse in data interrupt + * mode, so update bits 6-3 here. + * + * If the mouse has moved, set bit 6. + */ + if (x || y) + dev->buttons |= 0x40; + + /* Set bits 3-5 according to button state changes. */ + xor = ((dev->curr_b ^ dev->buttons) & 0x07) << 3; + dev->buttons |= xor; + } + + dev->buttons_last = b; + + /* Clamp x and y to between -128 and 127 (int8_t range). */ + if (x > 127) x = 127; + if (x < -128) x = -128; + if (y > 127) y = 127; + if (y < -128) y = -128; + + if (dev->timer_enabled) { + /* Update delayed coordinates. */ + dev->delayed_dx += x; + dev->delayed_dy += y; + } else { + /* If the counters are not frozen, update them. */ + if (! (dev->flags & FLAG_HOLD)) { + dev->curr_x = (int8_t) x; + dev->curr_y = (int8_t) y; + + dev->curr_b = dev->buttons; + } + + /* Send interrupt. */ + if (dev->flags & FLAG_DATA_INT) { + picint(1 << dev->irq); + DBGLOG(1, "MOUSE: Data Interrupt fired\n"); + } + } + + return(0); +} + + +/* + * The timer calls us on every tick if the mouse is in + * timer mode (InPort mouse is so configured, MS/Logitech + * Bus mouse always). + */ +static void +bm_update_data(mouse_t *dev) +{ + int delta_x, delta_y; + int xor; + + /* Update the deltas and the delays. */ + if (dev->delayed_dx > 127) { + delta_x = 127; + dev->delayed_dx -= 127; + } else if (dev->delayed_dx < -128) { + delta_x = -128; + dev->delayed_dx += 128; + } else { + delta_x = dev->delayed_dx; + dev->delayed_dx = 0; + } + + if (dev->delayed_dy > 127) { + delta_y = 127; + dev->delayed_dy -= 127; + } else if (dev->delayed_dy < -128) { + delta_y = -128; + dev->delayed_dy += 128; + } else { + delta_y = dev->delayed_dy; + dev->delayed_dy = 0; + } + + /* If the counters are not frozen, update them. */ + if (! (dev->flags & FLAG_HOLD)) { + dev->curr_x = (uint8_t) delta_x; + dev->curr_y = (uint8_t) delta_y; } if (dev->flags & FLAG_INPORT) { - if (x > 127) x = 127; - if (y > 127) y = 127; - if (x < -128) x = -128; - if (y < -128) y = -128; + /* + * This is an InPort mouse in timer mode, so always update + * curr_b, and update bits 6:3 (mouse moved and button state + * changed) here. + */ + xor = ((dev->curr_b ^ dev->buttons) & 0x07) << 3; + dev->curr_b = (dev->buttons & 0x87) | xor; + if (delta_x || delta_y) + dev->curr_b |= 0x40; + } else if (! (dev->flags & FLAG_HOLD)) { + /* + * This is a MS/Logitech Bus Mouse, so only + * update curr_b if the counters are frozen. + */ + dev->curr_b = dev->buttons; + } +} - dev->x_delay += x; - dev->y_delay += y; - dev->but = (uint8_t)(0x40 | ((b & 1) << 2) | ((b & 2) >> 1)); - if (dev->flags & FLAG_3BTN) - dev->but |= ((b & 4) >> 1); - dev->need_upd = 1; - } else { - /* If we are frozen, do not update the state. */ - if (! (dev->flags & FLAG_FROZEN)) { - /* Add the delta to our state. */ - x += dev->x; - if (x > 127) - x = 127; - if (x < -128) - x = -128; - dev->x = (int8_t)x; - y += dev->y; - if (y > 127) - y = 127; - if (y < -1287) - y = -1287; - dev->y = (int8_t)y; +/* + * Called at the configured period (InPort mouse) or at + * 45 times per second (MS/Logitech Bus mouse). + */ +static void +bm_timer(void *priv) +{ + mouse_t *dev = (mouse_t *)priv; - dev->x_delay += x; - dev->y_delay += y; + DBGLOG(1, "MOUSE: Timer Tick (flags=%08x)\n", dev->flags); - dev->but = b; - } + /* + * The period is configured either via emulator settings + * (for MS/Logitech Bus mouse) or via software (for + * InPort mouse). + */ + dev->timer += ((int64_t) dev->period) * TIMER_USEC; - /* Either way, generate an interrupt. */ - if ((dev->flags & FLAG_INTR) && !(dev->flags & FLAG_INPORT)) - picint(1 << dev->irq); + if (dev->flags & FLAG_TIMER_INT) { + picint(1 << dev->irq); + DBGLOG(1, "MOUSE: Timer Interrupt fired\n"); } - return(1); + bm_update_data(dev); } @@ -691,11 +634,8 @@ bm_close(void *priv) { mouse_t *dev = (mouse_t *)priv; - /* Release our I/O range. */ - io_removehandler(MOUSE_PORT, 4, - bm_read, NULL, NULL, bm_write, NULL, NULL, dev); - - free(dev); + if (dev != NULL) + free(dev); } @@ -704,65 +644,95 @@ static void * bm_init(const device_t *info) { mouse_t *dev; - int i; - dev = (mouse_t *)malloc(sizeof(mouse_t)); + dev = (mouse_t *)mem_alloc(sizeof(mouse_t)); memset(dev, 0x00, sizeof(mouse_t)); dev->name = info->name; - dev->type = info->local; - if (info->config != NULL) { - dev->irq = device_get_config_int("irq"); - i = device_get_config_int("buttons"); - if (i > 2) - dev->flags |= FLAG_3BTN; + + switch(info->local) { + case 0: /* original Logitech controller */ + dev->flags = 0; + dev->base = device_get_config_hex16("base"); + dev->irq = device_get_config_int("irq"); + break; + + case 1: /* on-board controller, Logitech compatible */ + dev->base = 0x023c; + dev->irq = 2; + break; + + case 10: /* Microsoft InPort controller */ + dev->flags = FLAG_INPORT; + dev->base = device_get_config_hex16("base"); + dev->irq = device_get_config_int("irq"); + break; + } + + dev->bn = device_get_config_int("buttons"); + mouse_set_buttons(dev->bn); + + dev->timer_enabled = 0; + dev->timer = 0LL; + + dev->delayed_dx = 0; + dev->delayed_dy = 0; + dev->buttons = 0; + dev->buttons_last = 0; + dev->curr_x = 0; + dev->curr_y = 0; + dev->curr_b = 0; + + dev->sig = 0; /* the signature port value */ + dev->cmd = 0; /* command byte */ + dev->toggle = 0; /* signature byte / IRQ bit toggle */ + if (dev->flags & FLAG_INPORT) { + dev->ctrl = 0; /* the control port value */ + dev->flags |= FLAG_ENABLED; + dev->period = 0.0; + + io_sethandler(dev->base, 4, + ms_read,NULL,NULL, ms_write,NULL,NULL, dev); } else { - dev->irq = MOUSE_IRQ_INTERNAL; /*hardwired*/ - i = 2; + dev->ctrl = 0x0f; /* the control port value */ + dev->conf = 0x0e; /* the config port value */ + dev->period = 1000000.0 / ((double) device_get_config_int("hz")); + + io_sethandler(dev->base, 4, + lt_read,NULL,NULL, lt_write,NULL,NULL, dev); } - pclog("MOUSE: %s (I/O=%04x, IRQ=%d, buttons=%d)\n", - dev->name, MOUSE_PORT, dev->irq, i); + timer_add(bm_timer, &dev->timer, &dev->timer_enabled, dev); - switch(dev->type) { - case MOUSE_LOGIBUS: - lt_reset(dev); + INFO("MOUSE: %s (I/O=%04x, IRQ=%d, buttons=%d\n", + dev->name, dev->base, dev->irq, dev->bn); - /* Initialize I/O handlers. */ - dev->read = lt_read; - dev->write = lt_write; - - dev->timer = 0; - timer_add(bm_timer, &dev->timer, &dev->timer, dev); - break; - - case MOUSE_INPORT: - dev->flags |= FLAG_INPORT; - ms_reset(dev); - - /* Initialize I/O handlers. */ - dev->read = ms_read; - dev->write = ms_write; - - dev->timer = (33334LL * TIMER_USEC); - timer_add(bm_timer, &dev->timer, TIMER_ALWAYS_ENABLED, dev); - break; - } - - /* Request an I/O range. */ - io_sethandler(MOUSE_PORT, 4, - bm_read, NULL, NULL, bm_write, NULL, NULL, dev); - - /* Tell them how many buttons we have. */ - mouse_set_buttons((dev->flags & FLAG_3BTN) ? 3 : 2); - - /* Return our private data to the I/O layer. */ return(dev); } -static const device_config_t bm_config[] = { +static const device_config_t lt_config[] = { { - "irq", "IRQ", CONFIG_SELECTION, "", MOUSE_IRQ, { + "base", "Address", CONFIG_HEX16, "", 0x23c, + { + { + "0x230", 0x230 + }, + { + "0x234", 0x234 + }, + { + "0x238", 0x238 + }, + { + "0x23C", 0x23c + }, + { + "" + } + } + }, + { + "irq", "IRQ", CONFIG_SELECTION, "", 5, { { "IRQ 2", 2 }, @@ -781,7 +751,82 @@ static const device_config_t bm_config[] = { } }, { - "buttons", "Buttons", CONFIG_SELECTION, "", MOUSE_BUTTONS, { + "hz", "Hz", CONFIG_SELECTION, "", 45, { + { + "30 Hz (JMP2 = 1)", 30 + }, + { + "45 Hz (JMP2 not populated)", 45 + }, + { + "60 Hz (JMP 2 = 2)", 60 + }, + { + "" + } + } + }, + { + "buttons", "Buttons", CONFIG_SELECTION, "", 2, { + { + "Two", 2 + }, + { + "Three", 3 + }, + { + "" + } + } + }, + { + "", "", -1 + } +}; + + +static const device_config_t ms_config[] = { + { + "base", "Address", CONFIG_HEX16, "", 0x23c, + { + { + "0x230", 0x230 + }, + { + "0x234", 0x234 + }, + { + "0x238", 0x238 + }, + { + "0x23C", 0x23c + }, + { + "" + } + } + }, + { + "irq", "IRQ", CONFIG_SELECTION, "", 5, { + { + "IRQ 2", 2 + }, + { + "IRQ 3", 3 + }, + { + "IRQ 4", 4 + }, + { + "IRQ 5", 5 + }, + { + "" + } + } + }, + { + "buttons", "Buttons", CONFIG_SELECTION, "", 2, { { "Two", 2 }, @@ -802,16 +847,17 @@ static const device_config_t bm_config[] = { const device_t mouse_logibus_device = { "Logitech Bus Mouse", DEVICE_ISA, - MOUSE_LOGIBUS, + 0, bm_init, bm_close, NULL, - bm_poll, NULL, NULL, NULL, - bm_config + bm_poll, + NULL, NULL, NULL, + lt_config }; const device_t mouse_logibus_internal_device = { "Logitech Bus Mouse (Internal)", - DEVICE_ISA, - MOUSE_LOGIBUS, + 0, + 2, bm_init, bm_close, NULL, bm_poll, NULL, NULL, NULL, NULL @@ -820,8 +866,9 @@ const device_t mouse_logibus_internal_device = { const device_t mouse_msinport_device = { "Microsoft Bus Mouse (InPort)", DEVICE_ISA, - MOUSE_INPORT, + 1, bm_init, bm_close, NULL, - bm_poll, NULL, NULL, NULL, - bm_config + bm_poll, + NULL, NULL, NULL, + ms_config }; diff --git a/src/devices/input/mouse_ps2.c b/src/devices/input/mouse_ps2.c index ef880d4..dbb68a1 100644 --- a/src/devices/input/mouse_ps2.c +++ b/src/devices/input/mouse_ps2.c @@ -8,7 +8,7 @@ * * Implementation of PS/2 series Mouse devices. * - * Version: @(#)mouse_ps2.c 1.0.7 2018/05/06 + * Version: @(#)mouse_ps2.c 1.0.8 2018/10/05 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -41,8 +41,8 @@ #include #include #include +#define dbglog mouse_log #include "../../emu.h" -#include "../../config.h" #include "../../device.h" #include "keyboard.h" #include "mouse.h" @@ -58,14 +58,12 @@ enum { typedef struct { const char *name; /* name of this device */ int8_t type; /* type of this device */ - - int mode; - uint8_t flags; uint8_t resolution; uint8_t sample_rate; uint8_t command; + int mode; int x, y, z, b; @@ -78,7 +76,7 @@ typedef struct { #define FLAG_CTRLDAT 0x08 /* ctrl or data mode */ -int mouse_scan = 0; +int mouse_scan = 0; static void @@ -98,7 +96,7 @@ ps2_write(uint8_t val, void *priv) case 0xf3: /* set sample rate */ dev->sample_rate = val; - keyboard_at_adddata_mouse(0xfa); + keyboard_at_adddata_mouse(0xfa); /* command response */ break; default: @@ -125,7 +123,7 @@ ps2_write(uint8_t val, void *priv) case 0xe9: /* status request */ keyboard_at_adddata_mouse(0xfa); - temp = (dev->flags & 0x3f); + temp = (dev->flags & 0x30); if (mouse_buttons & 0x01) temp |= 0x01; if (mouse_buttons & 0x02) @@ -147,7 +145,7 @@ ps2_write(uint8_t val, void *priv) case 0xf3: /* set command mode */ dev->flags |= FLAG_CTRLDAT; - keyboard_at_adddata_mouse(0xfa); + keyboard_at_adddata_mouse(0xfa); /* ACK for command byte */ break; case 0xf4: /* enable */ @@ -162,7 +160,7 @@ ps2_write(uint8_t val, void *priv) case 0xff: /* reset */ dev->mode = MODE_STREAM; - dev->flags &= 0x80; + dev->flags &= 0x88; keyboard_at_adddata_mouse(0xfa); keyboard_at_adddata_mouse(0xaa); keyboard_at_adddata_mouse(0x00); @@ -174,7 +172,7 @@ ps2_write(uint8_t val, void *priv) } if (dev->flags & FLAG_INTELLI) { - for (temp=0; temp<5; temp++) + for (temp = 0; temp < 5; temp++) dev->last_data[temp] = dev->last_data[temp+1]; dev->last_data[5] = val; @@ -189,20 +187,22 @@ ps2_write(uint8_t val, void *priv) static int ps2_poll(int x, int y, int z, int b, void *priv) { + uint8_t buff[3] = { 0x08, 0x00, 0x00 }; mouse_t *dev = (mouse_t *)priv; - uint8_t buff[3]; if (!x && !y && !z && b == dev->b) return(1); +#if 0 if (! (dev->flags & FLAG_ENABLED)) return(1); +#endif if (! mouse_scan) return(1); dev->x += x; dev->y -= y; dev->z -= z; - if ((dev->mode == MODE_STREAM) && - ((mouse_queue_end-mouse_queue_start) & 0x0f) < 13) { + if ((dev->mode == MODE_STREAM) && (dev->flags & FLAG_ENABLED) && + (((mouse_queue_end - mouse_queue_start) & 0x0f) < 13)) { dev->b = b; if (dev->x > 255) dev->x = 255; @@ -212,8 +212,6 @@ ps2_poll(int x, int y, int z, int b, void *priv) if (dev->z < -8) dev->z = -8; if (dev->z > 7) dev->z = 7; - memset(buff, 0x00, sizeof(buff)); - buff[0] = 0x08; if (dev->x < 0) buff[0] |= 0x10; if (dev->y < 0) @@ -232,7 +230,7 @@ ps2_poll(int x, int y, int z, int b, void *priv) keyboard_at_adddata_mouse(buff[0]); keyboard_at_adddata_mouse(buff[1]); keyboard_at_adddata_mouse(buff[2]); - if (dev->flags & FLAG_INTELLI) + if (dev->flags & FLAG_INTMODE) keyboard_at_adddata_mouse(dev->z); dev->x = dev->y = dev->z = 0; @@ -253,7 +251,7 @@ mouse_ps2_init(const device_t *info) mouse_t *dev; int i; - dev = (mouse_t *)malloc(sizeof(mouse_t)); + dev = (mouse_t *)mem_alloc(sizeof(mouse_t)); memset(dev, 0x00, sizeof(mouse_t)); dev->name = info->name; dev->type = info->local; @@ -266,8 +264,8 @@ mouse_ps2_init(const device_t *info) /* Hook into the general AT Keyboard driver. */ keyboard_at_set_mouse(ps2_write, dev); - pclog("MOUSE: %s (buttons=%d)\n", - dev->name, (dev->flags & FLAG_INTELLI)? 3 : 2); + INFO("MOUSE: %s (buttons=%d)\n", + dev->name, (dev->flags & FLAG_INTELLI) ? 3 : 2); /* Tell them how many buttons we have. */ mouse_set_buttons((dev->flags & FLAG_INTELLI) ? 3 : 2); diff --git a/src/devices/input/mouse_serial.c b/src/devices/input/mouse_serial.c index c8ec2d9..0786490 100644 --- a/src/devices/input/mouse_serial.c +++ b/src/devices/input/mouse_serial.c @@ -10,7 +10,7 @@ * * TODO: Add the Genius Serial Mouse. * - * Version: @(#)mouse_serial.c 1.0.9 2018/05/06 + * Version: @(#)mouse_serial.c 1.0.10 2018/10/05 * * Author: Fred N. van Kempen, * @@ -51,8 +51,8 @@ #include #include #include +#define dbglog mouse_log #include "../../emu.h" -#include "../../config.h" #include "../../device.h" #include "../../timer.h" #include "../ports/serial.h" @@ -128,7 +128,7 @@ ser_timer(void *priv) break; default: - pclog("%s: unsupported mouse type %d?\n", dev->type); + ERRLOG("MOUSE: unsupported mouse type %d?\n", dev->type); } } @@ -142,9 +142,7 @@ ser_poll(int x, int y, int z, int b, void *priv) if (!x && !y && b == dev->oldb) return(1); -#if 0 - pclog("%s: poll(%d,%d,%d,%02x)\n", dev->name, x, y, z, b); -#endif + DBGLOG(1, "MOUSE: poll(%d,%d,%d,%02x)\n", x, y, z, b); dev->oldb = b; @@ -221,7 +219,7 @@ ser_init(const device_t *info) mouse_t *dev; int i; - dev = (mouse_t *)malloc(sizeof(mouse_t)); + dev = (mouse_t *)mem_alloc(sizeof(mouse_t)); memset(dev, 0x00, sizeof(mouse_t)); dev->name = info->name; dev->type = info->local; @@ -235,13 +233,13 @@ ser_init(const device_t *info) /* Attach a serial port to the mouse. */ dev->serial = serial_attach(dev->port + 1, ser_callback, dev); if (dev->serial == NULL) { - pclog("MOUSE: %s (port=COM%d, butons=%d) port disabled!\n", + ERRLOG("MOUSE: %s (port=COM%d, butons=%d) port disabled!\n", dev->name, dev->port+1, i); free(dev); return(NULL); } - pclog("MOUSE: %s (port=COM%d, butons=%d)\n", dev->name, dev->port+1, i); + INFO("MOUSE: %s (port=COM%d, butons=%d)\n", dev->name, dev->port+1, i); timer_add(ser_timer, &dev->delay, &dev->delay, dev); diff --git a/src/devices/misc/bugger.c b/src/devices/misc/bugger.c index 6f95896..2dd4bd5 100644 --- a/src/devices/misc/bugger.c +++ b/src/devices/misc/bugger.c @@ -44,7 +44,7 @@ * configuration register (CTRL_SPCFG bit set) but have to * remember that stuff first... * - * Version: @(#)bugger.c 1.0.7 2018/05/07 + * Version: @(#)bugger.c 1.0.8 2018/09/29 * * Author: Fred N. van Kempen, * @@ -105,187 +105,189 @@ # define CTRL_RESET 0xff /* this resets the board */ #define BUG_DATA 1 - -static uint8_t bug_ctrl, /* control register */ - bug_data, /* data register */ - bug_ledr, bug_ledg, /* RED and GREEN LEDs */ - bug_seg1, bug_seg2, /* LEFT and RIGHT 7SEG displays */ - bug_spcfg; /* serial port configuration */ -# define FIFO_LEN 256 -static uint8_t bug_buff[FIFO_LEN], /* serial port data buffer */ - *bug_bptr; -# define UISTR_LEN 24 +#define FIFO_LEN 256 +#define UISTR_LEN 24 -extern void ui_sb_bugui(char *__str); +typedef struct { + const char *name; + uint16_t base; + + uint8_t ctrl, /* control register */ + data, /* data register */ + ledr, /* RED and GREEN LEDs */ + ledg, + seg1, /* LEFT and RIGHT 7SEG displays */ + seg2, + spcfg; /* serial port configuration */ + uint8_t buff[FIFO_LEN], /* serial port data buffer */ + *bptr; +} bugger_t; /* Update the system's UI with the actual Bugger status. */ static void -bug_setui(void) +bug_update(bugger_t *dev) { - wchar_t temp[128]; - char bug_str[UISTR_LEN]; + char temp[UISTR_LEN]; /* Format all current info in a string. */ - sprintf(bug_str, "%02X:%02X %c%c%c%c%c%c%c%c-%c%c%c%c%c%c%c%c", - bug_seg2, bug_seg1, - (bug_ledg&0x80)?'G':'g', (bug_ledg&0x40)?'G':'g', - (bug_ledg&0x20)?'G':'g', (bug_ledg&0x10)?'G':'g', - (bug_ledg&0x08)?'G':'g', (bug_ledg&0x04)?'G':'g', - (bug_ledg&0x02)?'G':'g', (bug_ledg&0x01)?'G':'g', - (bug_ledr&0x80)?'R':'r', (bug_ledr&0x40)?'R':'r', - (bug_ledr&0x20)?'R':'r', (bug_ledr&0x10)?'R':'r', - (bug_ledr&0x08)?'R':'r', (bug_ledr&0x04)?'R':'r', - (bug_ledr&0x02)?'R':'r', (bug_ledr&0x01)?'R':'r'); - - /* Convert to Unicode. */ - mbstowcs(temp, bug_str, sizeof_w(temp)); + sprintf(temp, "%02X:%02X %c%c%c%c%c%c%c%c-%c%c%c%c%c%c%c%c", + dev->seg2, dev->seg1, + (dev->ledg&0x80)?'G':'g', (dev->ledg&0x40)?'G':'g', + (dev->ledg&0x20)?'G':'g', (dev->ledg&0x10)?'G':'g', + (dev->ledg&0x08)?'G':'g', (dev->ledg&0x04)?'G':'g', + (dev->ledg&0x02)?'G':'g', (dev->ledg&0x01)?'G':'g', + (dev->ledr&0x80)?'R':'r', (dev->ledr&0x40)?'R':'r', + (dev->ledr&0x20)?'R':'r', (dev->ledr&0x10)?'R':'r', + (dev->ledr&0x08)?'R':'r', (dev->ledr&0x04)?'R':'r', + (dev->ledr&0x02)?'R':'r', (dev->ledr&0x01)?'R':'r'); /* Send formatted string to the UI. */ - ui_sb_text_set_w(temp); + ui_sb_text_set(SB_TEXT|1, temp); } /* Flush the serial port. */ static void -bug_spflsh(void) +bug_spflsh(bugger_t *dev) { - *bug_bptr = '\0'; - pclog("BUGGER- serial port [%s]\n", bug_buff); - bug_bptr = bug_buff; + *dev->bptr = '\0'; + INFO("BUGGER: serial port [%s]\n", dev->buff); + dev->bptr = dev->buff; } /* Handle a write to the Serial Port Data register. */ static void -bug_wsport(uint8_t val) +bug_wsport(bugger_t *dev, uint8_t val) { - uint8_t old = bug_ctrl; + uint8_t old = dev->ctrl; + + DEBUG("BUGGER: sport %02x\n", val); /* Clear the SPORT bit to indicate we are busy. */ - bug_ctrl &= ~CTRL_SPORT; + dev->ctrl &= ~CTRL_SPORT; /* Delay while processing byte.. */ - if (bug_bptr == &bug_buff[FIFO_LEN-1]) { + if (dev->bptr == &dev->buff[FIFO_LEN-1]) { /* Buffer full, gotta flush. */ - bug_spflsh(); + bug_spflsh(dev); } /* Write (store) the byte. */ - *bug_bptr++ = val; + *dev->bptr++ = val; /* Restore the SPORT bit. */ - bug_ctrl |= (old & CTRL_SPORT); - - pclog("BUGGER- sport %02x\n", val); + dev->ctrl |= (old & CTRL_SPORT); } /* Handle a write to the Serial Port Configuration register. */ static void -bug_wspcfg(uint8_t val) +bug_wspcfg(bugger_t *dev, uint8_t val) { - bug_spcfg = val; + dev->spcfg = val; - pclog("BUGGER- spcfg %02x\n", bug_spcfg); + DEBUG("BUGGER: spcfg %02x\n", dev->spcfg); } /* Handle a write to the control register. */ static void -bug_wctrl(uint8_t val) +bug_wctrl(bugger_t *dev, uint8_t val) { if (val == CTRL_RESET) { /* User wants us to reset. */ - bug_ctrl = CTRL_INIT; - bug_spcfg = 0x00; - bug_bptr = NULL; + dev->ctrl = CTRL_INIT; + dev->spcfg = 0x00; + dev->bptr = NULL; } else { /* If turning off the serial port, flush it. */ - if ((bug_ctrl & CTRL_SPORT) && !(val & CTRL_SPORT)) - bug_spflsh(); + if ((dev->ctrl & CTRL_SPORT) && !(val & CTRL_SPORT)) + bug_spflsh(dev); /* FIXME: did they do this using an XOR of operation bits? --FvK */ if (val & CTRL_SPCFG) { /* User wants to configure the serial port. */ - bug_ctrl &= ~(CTRL_SPORT|CTRL_SEG2|CTRL_SEG1|CTRL_GLED); - bug_ctrl |= CTRL_SPCFG; + dev->ctrl &= ~(CTRL_SPORT|CTRL_SEG2|CTRL_SEG1|CTRL_GLED); + dev->ctrl |= CTRL_SPCFG; } else if (val & CTRL_SPORT) { /* User wants to talk to the serial port. */ - bug_ctrl &= ~(CTRL_SPCFG|CTRL_SEG2|CTRL_SEG1|CTRL_GLED); - bug_ctrl |= CTRL_SPORT; - if (bug_bptr == NULL) - bug_bptr = bug_buff; + dev->ctrl &= ~(CTRL_SPCFG|CTRL_SEG2|CTRL_SEG1|CTRL_GLED); + dev->ctrl |= CTRL_SPORT; + if (dev->bptr == NULL) + dev->bptr = dev->buff; } else if (val & CTRL_SEG2) { /* User selected SEG2 (LEFT, Plus only) for output. */ - bug_ctrl &= ~(CTRL_SPCFG|CTRL_SPORT|CTRL_SEG1|CTRL_GLED); - bug_ctrl |= CTRL_SEG2; + dev->ctrl &= ~(CTRL_SPCFG|CTRL_SPORT|CTRL_SEG1|CTRL_GLED); + dev->ctrl |= CTRL_SEG2; } else if (val & CTRL_SEG1) { /* User selected SEG1 (RIGHT) for output. */ - bug_ctrl &= ~(CTRL_SPCFG|CTRL_SPORT|CTRL_SEG2|CTRL_GLED); - bug_ctrl |= CTRL_SEG1; + dev->ctrl &= ~(CTRL_SPCFG|CTRL_SPORT|CTRL_SEG2|CTRL_GLED); + dev->ctrl |= CTRL_SEG1; } else if (val & CTRL_GLED) { /* User selected the GREEN LEDs for output. */ - bug_ctrl &= ~(CTRL_SPCFG|CTRL_SPORT|CTRL_SEG2|CTRL_SEG1); - bug_ctrl |= CTRL_GLED; + dev->ctrl &= ~(CTRL_SPCFG|CTRL_SPORT|CTRL_SEG2|CTRL_SEG1); + dev->ctrl |= CTRL_GLED; } else { /* User selected the RED LEDs for output. */ - bug_ctrl &= + dev->ctrl &= ~(CTRL_SPCFG|CTRL_SPORT|CTRL_SEG2|CTRL_SEG1|CTRL_GLED); } } /* Update the UI with active settings. */ - pclog("BUGGER- ctrl %02x\n", bug_ctrl); - bug_setui(); + DBGLOG(1, "BUGGER: ctrl %02x\n", dev->ctrl); + + bug_update(dev); } /* Handle a write to the data register. */ static void -bug_wdata(uint8_t val) +bug_wdata(bugger_t *dev, uint8_t val) { - bug_data = val; + dev->data = val; - if (bug_ctrl & CTRL_SPCFG) - bug_wspcfg(val); - else if (bug_ctrl & CTRL_SPORT) - bug_wsport(val); + if (dev->ctrl & CTRL_SPCFG) + bug_wspcfg(dev, val); + else if (dev->ctrl & CTRL_SPORT) + bug_wsport(dev, val); else { - if (bug_ctrl & CTRL_SEG2) - bug_seg2 = val; - else if (bug_ctrl & CTRL_SEG1) - bug_seg1 = val; - else if (bug_ctrl & CTRL_GLED) - bug_ledg = val; + if (dev->ctrl & CTRL_SEG2) + dev->seg2 = val; + else if (dev->ctrl & CTRL_SEG1) + dev->seg1 = val; + else if (dev->ctrl & CTRL_GLED) + dev->ledg = val; else - bug_ledr = val; + dev->ledr = val; - pclog("BUGGER- data %02x\n", bug_data); + DBGLOG(1, "BUGGER: data %02x\n", dev->data); } /* Update the UI with active settings. */ - bug_setui(); + bug_update(dev); } /* Reset the ISA BusBugger controller. */ static void -bug_reset(void) +bug_reset(bugger_t *dev) { /* Clear the data register. */ - bug_data = 0x00; + dev->data = 0x00; /* Clear the RED and GREEN LEDs. */ - bug_ledr = 0x00; bug_ledg = 0x00; + dev->ledr = 0x00; dev->ledg = 0x00; /* Clear both 7SEG displays. */ - bug_seg1 = 0x00; bug_seg2 = 0x00; + dev->seg1 = 0x00; dev->seg2 = 0x00; /* Reset the control register (updates UI.) */ - bug_wctrl(CTRL_RESET); + bug_wctrl(dev, CTRL_RESET); } @@ -293,20 +295,22 @@ bug_reset(void) static void bug_write(uint16_t port, uint8_t val, UNUSED(void *priv)) { - switch (port-BUGGER_ADDR) { + bugger_t *dev = (bugger_t *)priv; + + switch (port - dev->base) { case BUG_CTRL: /* control register */ if (val == CTRL_RESET) { /* Perform a full reset. */ - bug_reset(); - } else if (bug_ctrl & CTRL_INIT) { + bug_reset(dev); + } else if (dev->ctrl & CTRL_INIT) { /* Only allow writes if initialized. */ - bug_wctrl(val); + bug_wctrl(dev, val); } break; case BUG_DATA: /* data register */ - if (bug_ctrl & CTRL_INIT) { - bug_wdata(val); + if (dev->ctrl & CTRL_INIT) { + bug_wdata(dev, val); } break; @@ -318,21 +322,22 @@ bug_write(uint16_t port, uint8_t val, UNUSED(void *priv)) static uint8_t bug_read(uint16_t port, UNUSED(void *priv)) { + bugger_t *dev = (bugger_t *)priv; uint8_t ret = 0xff; - if (bug_ctrl & CTRL_INIT) switch (port-BUGGER_ADDR) { + if (dev->ctrl & CTRL_INIT) switch (port - dev->base) { case BUG_CTRL: /* control register */ - ret = bug_ctrl; + ret = dev->ctrl; break; case BUG_DATA: /* data register */ - if (bug_ctrl & CTRL_SPCFG) { - ret = bug_spcfg; - } else if (bug_ctrl & CTRL_SPORT) { + if (dev->ctrl & CTRL_SPCFG) { + ret = dev->spcfg; + } else if (dev->ctrl & CTRL_SPORT) { ret = 0x00; /* input not supported */ } else { /* Just read the DIP switch. */ - ret = bug_data; + ret = dev->data; } break; @@ -348,31 +353,41 @@ bug_read(uint16_t port, UNUSED(void *priv)) static void * bug_init(const device_t *info) { - pclog("%s, I/O=%04x\n", info->name, BUGGER_ADDR); + bugger_t *dev; + + dev = (bugger_t *)mem_alloc(sizeof(bugger_t)); + memset(dev, 0x00, sizeof(bugger_t)); + dev->name = info->name; + dev->base = BUGGER_ADDR; + + INFO("BUGGER: %s (I/O=%04x)\n", dev->name, dev->base); /* Initialize local registers. */ - bug_reset(); + bug_reset(dev); - io_sethandler(BUGGER_ADDR, BUGGER_ADDRLEN, - bug_read, NULL, NULL, bug_write, NULL, NULL, NULL); + io_sethandler(dev->base, 2, + bug_read,NULL,NULL, bug_write,NULL,NULL, dev); - /* Just so its not NULL. */ - return((void *)info); + return(dev); } /* Remove the ISA BusBugger emulator from the system. */ static void -bug_close(UNUSED(void *priv)) +bug_close(void *priv) { - io_removehandler(BUGGER_ADDR, BUGGER_ADDRLEN, - bug_read, NULL, NULL, bug_write, NULL, NULL, NULL); + bugger_t *dev = (bugger_t *)priv; + + io_removehandler(dev->base, 2, + bug_read,NULL,NULL, bug_write,NULL,NULL, dev); + + free(dev); } const device_t bugger_device = { "ISA/PCI Bus Bugger", - DEVICE_ISA | DEVICE_AT, + DEVICE_ISA, 0, bug_init, bug_close, NULL, NULL, NULL, NULL, NULL, diff --git a/src/devices/misc/bugger.h b/src/devices/misc/bugger.h index 228583a..1837b47 100644 --- a/src/devices/misc/bugger.h +++ b/src/devices/misc/bugger.h @@ -8,7 +8,7 @@ * * Definitions for the BUGGER card. * - * Version: @(#)bugger.h 1.0.2 2018/03/15 + * Version: @(#)bugger.h 1.0.3 2018/09/13 * * Authors: Fred N. van Kempen, * @@ -50,7 +50,6 @@ /* I/O port range used. */ #define BUGGER_ADDR 0x007a -#define BUGGER_ADDRLEN 4 #ifdef __cplusplus diff --git a/src/devices/misc/isamem.c b/src/devices/misc/isamem.c index aa91a22..5ea8197 100644 --- a/src/devices/misc/isamem.c +++ b/src/devices/misc/isamem.c @@ -32,7 +32,7 @@ * TODO: The EV159 is supposed to support 16b EMS transfers, but the * EMM.sys driver for it doesn't seem to want to do that.. * - * Version: @(#)isamem.c 1.0.4 2018/09/02 + * Version: @(#)isamem.c 1.0.5 2018/09/22 * * Author: Fred N. van Kempen, * @@ -84,8 +84,6 @@ #include "isamem.h" -#define ISAMEM_DEBUG 0 - #define RAM_TOPMEM (640 << 10) /* end of low memory */ #define RAM_UMAMEM (384 << 10) /* upper memory block */ #define RAM_EXTMEM (1024 << 10) /* start of high memory */ @@ -101,7 +99,7 @@ typedef struct { uint8_t frame; /* (varies with board) */ char pad; uint8_t *addr; /* start addr in EMS RAM */ - mem_mapping_t mapping; /* mapping entry for page */ + mem_map_t mapping; /* mapping entry for page */ } emsreg_t; typedef struct { @@ -126,8 +124,8 @@ typedef struct { uint8_t *ram; /* allocated RAM buffer */ - mem_mapping_t low_mapping; /* mapping for low mem */ - mem_mapping_t high_mapping; /* mapping for high mem */ + mem_map_t low_mapping; /* mapping for low mem */ + mem_map_t high_mapping; /* mapping for high mem */ emsreg_t ems[EMS_MAXPAGE]; /* EMS controller registers */ } memdev_t; @@ -146,7 +144,7 @@ static const device_t *instance[ISAMEM_MAX] = { static uint8_t ram_readb(uint32_t addr, void *priv) { - mem_mapping_t *map = (mem_mapping_t *)priv; + mem_map_t *map = (mem_map_t *)priv; memdev_t *dev = (memdev_t *)map->dev; uint8_t ret = 0xff; @@ -161,7 +159,7 @@ ram_readb(uint32_t addr, void *priv) static uint16_t ram_readw(uint32_t addr, void *priv) { - mem_mapping_t *map = (mem_mapping_t *)priv; + mem_map_t *map = (mem_map_t *)priv; memdev_t *dev = (memdev_t *)map->dev; uint16_t ret = 0xffff; @@ -176,7 +174,7 @@ ram_readw(uint32_t addr, void *priv) static void ram_writeb(uint32_t addr, uint8_t val, void *priv) { - mem_mapping_t *map = (mem_mapping_t *)priv; + mem_map_t *map = (mem_map_t *)priv; memdev_t *dev = (memdev_t *)map->dev; /* Write the data. */ @@ -188,7 +186,7 @@ ram_writeb(uint32_t addr, uint8_t val, void *priv) static void ram_writew(uint32_t addr, uint16_t val, void *priv) { - mem_mapping_t *map = (mem_mapping_t *)priv; + mem_map_t *map = (mem_map_t *)priv; memdev_t *dev = (memdev_t *)map->dev; /* Write the data. */ @@ -200,7 +198,7 @@ ram_writew(uint32_t addr, uint16_t val, void *priv) static uint8_t ems_readb(uint32_t addr, void *priv) { - mem_mapping_t *map = (mem_mapping_t *)priv; + mem_map_t *map = (mem_map_t *)priv; memdev_t *dev = (memdev_t *)map->dev; uint8_t ret = 0xff; int vpage; @@ -210,9 +208,6 @@ ems_readb(uint32_t addr, void *priv) /* Grab the data. */ ret = *(uint8_t *)(dev->ems[vpage].addr + (addr - map->base)); -#if ISAMEM_DEBUG - if ((addr % 4096)==0) pclog("EMS readb(%06x) = %02x\n",addr-map->base,ret); -#endif return(ret); } @@ -222,7 +217,7 @@ ems_readb(uint32_t addr, void *priv) static uint16_t ems_readw(uint32_t addr, void *priv) { - mem_mapping_t *map = (mem_mapping_t *)priv; + mem_map_t *map = (mem_map_t *)priv; memdev_t *dev = (memdev_t *)map->dev; uint16_t ret = 0xffff; int vpage; @@ -232,9 +227,6 @@ ems_readw(uint32_t addr, void *priv) /* Grab the data. */ ret = *(uint16_t *)(dev->ems[vpage].addr + (addr - map->base)); -#if ISAMEM_DEBUG - if ((addr % 4096)==0) pclog("EMS readw(%06x) = %04x\n",addr-map->base,ret); -#endif return(ret); } @@ -244,7 +236,7 @@ ems_readw(uint32_t addr, void *priv) static void ems_writeb(uint32_t addr, uint8_t val, void *priv) { - mem_mapping_t *map = (mem_mapping_t *)priv; + mem_map_t *map = (mem_map_t *)priv; memdev_t *dev = (memdev_t *)map->dev; int vpage; @@ -252,9 +244,6 @@ ems_writeb(uint32_t addr, uint8_t val, void *priv) vpage = ((addr & 0xffff) / EMS_PGSIZE); /* Write the data. */ -#if ISAMEM_DEBUG - if ((addr % 4096)==0) pclog("EMS writeb(%06x, %02x)\n",addr-map->base,val); -#endif *(uint8_t *)(dev->ems[vpage].addr + (addr - map->base)) = val; } @@ -263,7 +252,7 @@ ems_writeb(uint32_t addr, uint8_t val, void *priv) static void ems_writew(uint32_t addr, uint16_t val, void *priv) { - mem_mapping_t *map = (mem_mapping_t *)priv; + mem_map_t *map = (mem_map_t *)priv; memdev_t *dev = (memdev_t *)map->dev; int vpage; @@ -271,9 +260,6 @@ ems_writew(uint32_t addr, uint16_t val, void *priv) vpage = ((addr & 0xffff) / EMS_PGSIZE); /* Write the data. */ -#if ISAMEM_DEBUG - if ((addr % 4096)==0) pclog("EMS writew(%06x, %04x)\n",addr-map->base,val); -#endif *(uint16_t *)(dev->ems[vpage].addr + (addr - map->base)) = val; } @@ -301,9 +287,7 @@ ems_read(uint16_t port, void *priv) break; } -#if ISAMEM_DEBUG - pclog("ISAMEM: read(%04x) = %02x)\n", port, ret); -#endif + DBGLOG(2, "ISAMEM: read(%04x) = %02x)\n", port, ret); return(ret); } @@ -320,9 +304,7 @@ ems_write(uint16_t port, uint8_t val, void *priv) vpage = (port / EMS_PGSIZE); port &= (EMS_PGSIZE - 1); -#if ISAMEM_DEBUG - pclog("ISAMEM: write(%04x, %02x) page=%d\n", port, val, vpage); -#endif + DBGLOG(2, "ISAMEM: write(%04x, %02x) page=%d\n", port, val, vpage); switch(port - dev->base_addr) { case 0x0000: /* page mapping registers */ @@ -342,14 +324,14 @@ ems_write(uint16_t port, uint8_t val, void *priv) if (dev->ems[vpage].enabled) { /* Update the EMS RAM address for this page. */ - mem_mapping_set_exec(&dev->ems[vpage].mapping, - dev->ems[vpage].addr); + mem_map_set_exec(&dev->ems[vpage].mapping, + dev->ems[vpage].addr); /* Enable this page. */ - mem_mapping_enable(&dev->ems[vpage].mapping); + mem_map_enable(&dev->ems[vpage].mapping); } else { /* Disable this page. */ - mem_mapping_disable(&dev->ems[vpage].mapping); + mem_map_disable(&dev->ems[vpage].mapping); } } break; @@ -373,7 +355,7 @@ ems_write(uint16_t port, uint8_t val, void *priv) * 80 c0 e0 DC000 * 80 c0 e0 E0000 */ -pclog("EMS: write(%02x) to register 1 !\n"); +DEBUG("EMS: write(%02x) to register 1 !\n"); dev->ems[vpage].frame = val; if (val) dev->flags |= FLAG_CONFIG; @@ -396,7 +378,7 @@ isamem_init(const device_t *info) /* Find our device and create an instance. */ for (i = 0; i < ISAMEM_MAX; i++) if (instance[i] == info) break; - dev = (memdev_t *)malloc(sizeof(memdev_t)); + dev = (memdev_t *)mem_alloc(sizeof(memdev_t)); memset(dev, 0x00, sizeof(memdev_t)); dev->name = info->name; dev->board = info->local; @@ -456,31 +438,31 @@ dev->frame_addr = 0xE0000; dev->start_addr <<= 10; /* Say hello! */ - pclog("ISAMEM: %s (%iKB", info->name, dev->total_size); + INFO("ISAMEM: %s (%iKB", info->name, dev->total_size); if (tot && (dev->total_size != tot)) - pclog(", %iKB for RAM", tot); - if (dev->flags & FLAG_FAST) pclog(", FAST"); - if (dev->flags & FLAG_WIDE) pclog(", 16BIT"); - pclog(")\n"); + INFO(", %iKB for RAM", tot); + if (dev->flags & FLAG_FAST) INFO(", FAST"); + if (dev->flags & FLAG_WIDE) INFO(", 16BIT"); + INFO(")\n"); /* Force (back to) 8-bit bus if needed. */ if (dev->flags & FLAG_WIDE) { if (AT) { if (! cpu_16bitbus) - pclog("ISAMEM: *WARNING* this board will slow down your PC!\n"); + INFO("ISAMEM: *WARNING* this board will slow down your PC!\n"); } else { - pclog("ISAMEM: not AT+ system, forcing 8-bit mode!\n"); + INFO("ISAMEM: not AT+ system, forcing 8-bit mode!\n"); dev->flags &= ~FLAG_WIDE; } } else { if (AT) { - pclog("ISAMEM: *WARNING* this board will slow down your PC!\n"); + INFO("ISAMEM: *WARNING* this board will slow down your PC!\n"); } } /* Allocate and initialize our RAM. */ k = dev->total_size << 10; - dev->ram = (uint8_t *)malloc(k); + dev->ram = (uint8_t *)mem_alloc(k); memset(dev->ram, 0x00, k); ptr = dev->ram; @@ -510,18 +492,18 @@ dev->frame_addr = 0xE0000; */ if (t > tot) t = tot; - pclog("ISAMEM: RAM at %05iKB (%iKB)\n", addr>>10, t>>10); + INFO("ISAMEM: RAM at %05iKB (%iKB)\n", addr>>10, t>>10); /* Create, initialize and enable the low-memory mapping. */ - mem_mapping_add(&dev->low_mapping, addr, t, - ram_readb, - (dev->flags&FLAG_WIDE) ? ram_readw : NULL, - NULL, - ram_writeb, - (dev->flags&FLAG_WIDE) ? ram_writew : NULL, - NULL, - ptr, MEM_MAPPING_EXTERNAL, &dev->low_mapping); - mem_mapping_set_dev(&dev->low_mapping, dev); + mem_map_add(&dev->low_mapping, addr, t, + ram_readb, + (dev->flags&FLAG_WIDE) ? ram_readw : NULL, + NULL, + ram_writeb, + (dev->flags&FLAG_WIDE) ? ram_writew : NULL, + NULL, + ptr, MEM_MAPPING_EXTERNAL, &dev->low_mapping); + mem_map_set_dev(&dev->low_mapping, dev); /* Tell the memory system this is external RAM. */ mem_set_mem_state(addr, t, @@ -543,19 +525,17 @@ dev->frame_addr = 0xE0000; */ t = RAM_UMAMEM; /* 384KB */ - pclog("ISAMEM: RAM at %05iKB (%iKB)\n", addr>>10, t>>10); + INFO("ISAMEM: RAM at %05iKB (%iKB)\n", addr>>10, t>>10); /* Update and enable the remap. */ - mem_mapping_del(&ram_remapped_mapping); - mem_mapping_add(&ram_remapped_mapping, - addr + tot, t, - ram_readb, ram_readw, NULL, - ram_writeb, ram_writew, NULL, - ptr, MEM_MAPPING_EXTERNAL, - &ram_remapped_mapping); - mem_mapping_set_exec(&ram_remapped_mapping, ptr); - mem_mapping_set_dev(&ram_remapped_mapping, dev); - mem_mapping_disable(&ram_remapped_mapping); + mem_map_del(&ram_remapped_mapping); + mem_map_add(&ram_remapped_mapping, addr + tot, t, + ram_readb, ram_readw, NULL, + ram_writeb, ram_writew, NULL, + ptr, MEM_MAPPING_EXTERNAL, &ram_remapped_mapping); + mem_map_set_exec(&ram_remapped_mapping, ptr); + mem_map_set_dev(&ram_remapped_mapping, dev); + mem_map_disable(&ram_remapped_mapping); /* Tell the memory system this is external RAM. */ mem_set_mem_state(addr + tot, t, @@ -577,14 +557,13 @@ dev->frame_addr = 0xE0000; */ if (AT && addr > 0 && tot > 0) { t = tot; - pclog("ISAMEM: RAM at %05iKB (%iKB)\n", addr>>10, t>>10); + INFO("ISAMEM: RAM at %05iKB (%iKB)\n", addr>>10, t>>10); /* Create, initialize and enable the high-memory mapping. */ - mem_mapping_add(&dev->high_mapping, addr, t, - ram_readb, ram_readw, NULL, - ram_writeb, ram_writew, NULL, - ptr, MEM_MAPPING_EXTERNAL, &dev->high_mapping); - mem_mapping_set_dev(&dev->high_mapping, dev); + mem_map_add(&dev->high_mapping, addr, t, + ram_readb, ram_readw, NULL, ram_writeb, ram_writew, NULL, + ptr, MEM_MAPPING_EXTERNAL, &dev->high_mapping); + mem_map_set_dev(&dev->high_mapping, dev); /* Tell the memory system this is external RAM. */ mem_set_mem_state(addr, t, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); @@ -606,11 +585,11 @@ dev->frame_addr = 0xE0000; dev->ems_start = ptr - dev->ram; dev->ems_size = t >> 10; dev->ems_pages = t / EMS_PGSIZE; - pclog("ISAMEM: EMS enabled, I/O=%04XH, %iKB (%i pages)", + INFO("ISAMEM: EMS enabled, I/O=%04XH, %iKB (%i pages)", dev->base_addr, dev->ems_size, dev->ems_pages); if (dev->frame_addr > 0) - pclog(", Frame=%05XH", dev->frame_addr); - pclog("\n"); + INFO(", Frame=%05XH", dev->frame_addr); + INFO("\n"); /* * For each supported page (we can have a maximum of 4), @@ -619,20 +598,20 @@ dev->frame_addr = 0xE0000; */ for (i = 0; i < EMS_MAXPAGE; i++) { /* Create and initialize a page mapping. */ - mem_mapping_add(&dev->ems[i].mapping, - dev->frame_addr + (EMS_PGSIZE*i), EMS_PGSIZE, - ems_readb, - (dev->flags&FLAG_WIDE) ? ems_readw : NULL, - NULL, - ems_writeb, - (dev->flags&FLAG_WIDE) ? ems_writew : NULL, - NULL, - ptr, MEM_MAPPING_EXTERNAL, - &dev->ems[i].mapping); - mem_mapping_set_dev(&dev->ems[i].mapping, dev); + mem_map_add(&dev->ems[i].mapping, + dev->frame_addr + (EMS_PGSIZE*i), EMS_PGSIZE, + ems_readb, + (dev->flags&FLAG_WIDE) ? ems_readw : NULL, + NULL, + ems_writeb, + (dev->flags&FLAG_WIDE) ? ems_writew : NULL, + NULL, + ptr, MEM_MAPPING_EXTERNAL, + &dev->ems[i].mapping); + mem_map_set_dev(&dev->ems[i].mapping, dev); /* For now, disable it. */ - mem_mapping_disable(&dev->ems[i].mapping); + mem_map_disable(&dev->ems[i].mapping); /* Set up an I/O port handler. */ io_sethandler(dev->base_addr + (EMS_PGSIZE*i), 2, diff --git a/src/devices/misc/isartc.c b/src/devices/misc/isartc.c index 312441b..a7f0cec 100644 --- a/src/devices/misc/isartc.c +++ b/src/devices/misc/isartc.c @@ -28,7 +28,7 @@ * NOTE: The IRQ functionalities have been implemented, but not yet * tested, as I need to write test software for them first :) * - * Version: @(#)isartc.c 1.0.4 2018/08/31 + * Version: @(#)isartc.c 1.0.5 2018/09/22 * * Author: Fred N. van Kempen, * @@ -69,6 +69,7 @@ #include #include #include +#include #include "../../emu.h" #include "../../cpu/cpu.h" #include "../../machines/machine.h" @@ -81,9 +82,6 @@ #include "isartc.h" -#define ISARTC_DEBUG 0 - - typedef struct { const char *name; /* board name */ uint8_t board; /* board type */ @@ -285,9 +283,7 @@ mm67_time_get(nvr_t *nvr, struct tm *tm) #ifdef MM67_CENTURY tm->tm_year += (regs[MM67_CENTURY] * 100) - 1900; #endif -#if ISARTC_DEBUG > 1 - pclog("ISARTC: get_time: year=%i [%02x]\n", tm->tm_year, regs[dev->year]); -#endif + DBGLOG(1, "ISARTC: get_time: year=%i [%02x]\n", tm->tm_year, regs[dev->year]); } } @@ -318,9 +314,7 @@ mm67_time_set(nvr_t *nvr, struct tm *tm) #ifdef MM67_CENTURY regs[MM67_CENTURY] = (year + 1900) / 100; #endif -#if ISARTC_DEBUG > 1 - pclog("ISARTC: set_time: [%02x] year=%i (%i)\n", regs[dev->year], year, tm->tm_year); -#endif + DBGLOG(1, "ISARTC: set_time: [%02x] year=%i (%i)\n", regs[dev->year], year, tm->tm_year); } } @@ -331,7 +325,7 @@ mm67_start(nvr_t *nvr) struct tm tm; /* Initialize the internal and chip times. */ - if (enable_sync) { + if (time_sync != TIME_SYNC_DISABLED) { /* Use the internal clock's time. */ nvr_time_get(&tm); mm67_time_set(nvr, &tm); @@ -382,9 +376,7 @@ mm67_read(uint16_t port, void *priv) break; } -#if ISARTC_DEBUG - pclog("ISARTC: read(%04x) = %02x\n", port-dev->base_addr, ret); -#endif + DBGLOG(2, "ISARTC: read(%04x) = %02x\n", port-dev->base_addr, ret); return(ret); } @@ -398,9 +390,7 @@ mm67_write(uint16_t port, uint8_t val, void *priv) int reg = port - dev->base_addr; int i; -#if ISARTC_DEBUG - pclog("ISARTC: write(%04x, %02x)\n", port-dev->base_addr, val); -#endif + DBGLOG(2, "ISARTC: write(%04x, %02x)\n", port-dev->base_addr, val); /* This chip is directly mapped on I/O. */ cycles -= ISA_CYCLES(4); @@ -443,15 +433,15 @@ mm67_write(uint16_t port, uint8_t val, void *priv) break; case MM67_GOCMD: -pclog("RTC: write gocmd=%02x\n", val); +DEBUG("RTC: write gocmd=%02x\n", val); break; case MM67_STBYIRQ: -pclog("RTC: write stby=%02x\n", val); +DEBUG("RTC: write stby=%02x\n", val); break; case MM67_TEST: -pclog("RTC: write test=%02x\n", val); +DEBUG("RTC: write test=%02x\n", val); break; default: @@ -474,7 +464,7 @@ isartc_init(const device_t *info) rtcdev_t *dev; /* Create a device instance. */ - dev = (rtcdev_t *)malloc(sizeof(rtcdev_t)); + dev = (rtcdev_t *)mem_alloc(sizeof(rtcdev_t)); memset(dev, 0x00, sizeof(rtcdev_t)); dev->name = info->name; dev->board = info->local; @@ -528,10 +518,10 @@ isartc_init(const device_t *info) } /* Say hello! */ - pclog("ISARTC: %s (I/O=%04XH", info->name, dev->base_addr); + INFO("ISARTC: %s (I/O=%04XH", info->name, dev->base_addr); if (dev->irq != -1) - pclog(", IRQ%i", dev->irq); - pclog(")\n"); + INFO(", IRQ%i", dev->irq); + INFO(")\n"); /* Set up an I/O port handler. */ io_sethandler(dev->base_addr, dev->base_addrsz, @@ -543,7 +533,7 @@ isartc_init(const device_t *info) nvr_init(&dev->nvr); /* Let them know our device instance. */ - return((void *)dev); + return(dev); } diff --git a/src/devices/network/net_3c503.c b/src/devices/network/net_3c503.c new file mode 100644 index 0000000..c3cf77d --- /dev/null +++ b/src/devices/network/net_3c503.c @@ -0,0 +1,1660 @@ +/* + * 86Box An emulator of (mostly) x86-based PC systems and devices, + * using the ISA, EISA, VLB, MCA, and PCI system buses, + * roughly spanning the era between 1981 and 1995. + * + * This file is part of the 86Box Project. + * + * Implementation of the following network controllers: + * - 3Com Etherlink II 3c503 (ISA 8-bit). + * + * Version: @(#)net_3c503.c 1.0.2 2018/10/05 + * + * Based on @(#)3c503.cpp Carl (MAME) + * + * Authors: TheCollector1995, + * Miran Grca, + * Fred N. van Kempen, + * Carl, + * + * Copyright 2018 TheCollector1995. + * Copyright 2018 Miran Grca. + * Copyright 2017,2018 Fred N. van Kempen. + * Portions Copyright (C) 2018 MAME Project + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the: + * + * Free Software Foundation, Inc. + * 59 Temple Place - Suite 330 + * Boston, MA 02111-1307 + * USA. + */ +#include +#include +#include +#include +#include +#include +#define dbglog network_dev_log +#include "../../emu.h" +#include "../../io.h" +#include "../../mem.h" +#include "../../random.h" +#include "../../device.h" +#include "../../ui/ui.h" +#include "../../plat.h" +#include "../system/dma.h" +#include "../system/pic.h" +#include "network.h" +#include "net_dp8390.h" +#include "net_3com.h" +#include "bswap.h" + + +typedef struct { + uint16_t base_address; + int8_t base_irq; + int8_t dma_channel; + uint32_t bios_addr; + + mem_map_t ram_mapping; + + dp8390_t dp8390; + + uint8_t maclocal[6]; /* configured MAC (local) address */ + uint8_t prom[32]; + + struct { + uint8_t pstr; + uint8_t pspr; + uint8_t dqtr; + uint8_t bcfr; + uint8_t pcfr; + uint8_t gacfr; + uint8_t ctrl; + uint8_t streg; + uint8_t idcfr; + uint16_t da; + uint32_t vptr; + uint8_t rfmsb; + uint8_t rflsb; + } regs; +} tc503_t; + + +static void tc503_rx(void *, uint8_t *, int); +static void tc503_tx(tc503_t *, uint32_t); + + +static void +tc503_interrupt(tc503_t *dev, int set) +{ + switch (dev->base_irq) { + case 2: + dev->regs.idcfr = 0x10; + break; + + case 3: + dev->regs.idcfr = 0x20; + break; + + case 4: + dev->regs.idcfr = 0x40; + break; + + case 5: + dev->regs.idcfr = 0x80; + break; + } + + if (set) + picint(1 << dev->base_irq); + else + picintc(1 << dev->base_irq); +} + + +static void +tc503_ram_write(uint32_t addr, uint8_t val, void *priv) +{ + tc503_t *dev = (tc503_t *)priv; + + if ((addr & 0x3fff) >= 0x2000) + return; + + dev->dp8390.mem[addr & 0x1fff] = val; +} + + +static uint8_t +tc503_ram_read(uint32_t addr, void *priv) +{ + tc503_t *dev = (tc503_t *)priv; + + if ((addr & 0x3fff) >= 0x2000) + return(0xff); + + return(dev->dp8390.mem[addr & 0x1fff]); +} + + +static void +tc503_set_drq(tc503_t *dev) +{ + switch (dev->dma_channel) { + case 1: + dev->regs.idcfr = 1; + break; + + case 2: + dev->regs.idcfr = 2; + break; + + case 3: + dev->regs.idcfr = 4; + break; + } +} + + +/* Restore state to power-up, cancelling all I/O. */ +static void +tc503_reset(void *priv) +{ + tc503_t *dev = (tc503_t *)priv; + int i; + + DEBUG("3C503: reset\n"); + + /* Initialize the MAC address area by doubling the physical address. */ + dev->prom[0] = dev->dp8390.physaddr[0]; + dev->prom[1] = dev->dp8390.physaddr[1]; + dev->prom[2] = dev->dp8390.physaddr[2]; + dev->prom[3] = dev->dp8390.physaddr[3]; + dev->prom[4] = dev->dp8390.physaddr[4]; + dev->prom[5] = dev->dp8390.physaddr[5]; + +//FIXME: why?? --Fvk + /* NE1K signature. */ + for (i = 6; i < 16; i++) + dev->prom[i] = 0x57; + + /* Zero out registers and memory. */ + memset(&dev->dp8390.CR, 0x00, sizeof(dev->dp8390.CR) ); + memset(&dev->dp8390.ISR, 0x00, sizeof(dev->dp8390.ISR)); + memset(&dev->dp8390.IMR, 0x00, sizeof(dev->dp8390.IMR)); + memset(&dev->dp8390.DCR, 0x00, sizeof(dev->dp8390.DCR)); + memset(&dev->dp8390.TCR, 0x00, sizeof(dev->dp8390.TCR)); + memset(&dev->dp8390.TSR, 0x00, sizeof(dev->dp8390.TSR)); + memset(&dev->dp8390.RSR, 0x00, sizeof(dev->dp8390.RSR)); + + dev->dp8390.tx_timer_active = 0; + dev->dp8390.local_dma = 0; + dev->dp8390.page_start = 0; + dev->dp8390.page_stop = 0; + dev->dp8390.bound_ptr = 0; + dev->dp8390.tx_page_start = 0; + dev->dp8390.num_coll = 0; + dev->dp8390.tx_bytes = 0; + dev->dp8390.fifo = 0; + dev->dp8390.remote_dma = 0; + dev->dp8390.remote_start = 0; + dev->dp8390.remote_bytes = 0; + dev->dp8390.tallycnt_0 = 0; + dev->dp8390.tallycnt_1 = 0; + dev->dp8390.tallycnt_2 = 0; + + dev->dp8390.curr_page = 0; + + dev->dp8390.rempkt_ptr = 0; + dev->dp8390.localpkt_ptr = 0; + dev->dp8390.address_cnt = 0; + + memset(&dev->dp8390.mem, 0x00, sizeof(dev->dp8390.mem)); + + /* Set power-up conditions. */ + dev->dp8390.CR.stop = 1; + dev->dp8390.CR.rdma_cmd = 4; + dev->dp8390.ISR.reset = 1; + dev->dp8390.DCR.longaddr = 1; + + memset(&dev->regs, 0, sizeof(dev->regs)); + + dev->regs.ctrl = 0x0a; + + tc503_interrupt(dev, 0); +} + + +/* + * Access the 32K private RAM. + * + * The NE2000 memory is accessed through the data port of the + * ASIC (offset 0) after setting up a remote-DMA transfer. + * Both byte and word accesses are allowed. + * The first 16 bytes contains the MAC address at even locations, + * and there is 16K of buffer memory starting at 16K. + */ +static uint32_t +tc503_chipmem_read(tc503_t *dev, uint32_t addr, unsigned int len) +{ + uint32_t retval = 0; + + if (addr <= 15) { + retval = dev->prom[addr % 16]; + if (len == 2) + retval |= (dev->prom[(addr + 1) % 16] << 8); + return(retval); + } + + if ((addr >= DP8390_WORD_MEMSTART) && (addr < DP8390_WORD_MEMEND)) { + retval = dev->dp8390.mem[addr - DP8390_WORD_MEMSTART]; + if (len == 2) + retval |= (dev->dp8390.mem[addr - DP8390_WORD_MEMSTART + 1] << 8); + return(retval); + } + + DEBUG("3C503: out-of-bounds chipmem read, %04X\n", addr); + + return(0xff); +} + + +static void +tc503_chipmem_write(tc503_t *dev, uint32_t addr, uint32_t val, unsigned len) +{ + if ((addr >= DP8390_WORD_MEMSTART) && (addr < DP8390_WORD_MEMEND)) { + dev->dp8390.mem[addr-DP8390_WORD_MEMSTART] = val & 0xff; + if (len == 2) + dev->dp8390.mem[addr-DP8390_WORD_MEMSTART+1] = val >> 8; + } else + DEBUG("3C503: out-of-bounds chipmem write, %04X\n", addr); +} + + +/* Handle reads/writes to the 'zeroth' page of the DS8390 register file. */ +static uint32_t +tc503_page0_read(tc503_t *dev, uint32_t off, unsigned int len) +{ + uint8_t retval = 0; + + if (len > 1) { + /* encountered with win98 hardware probe */ + DEBUG("3C503: bad length! Page0 read from register 0x%02x, len=%u\n", + off, len); + return(retval); + } + + switch(off) { + case 0x01: /* CLDA0 */ + retval = (dev->dp8390.local_dma & 0xff); + break; + + case 0x02: /* CLDA1 */ + retval = (dev->dp8390.local_dma >> 8); + break; + + case 0x03: /* BNRY */ + retval = dev->dp8390.bound_ptr; + break; + + case 0x04: /* TSR */ + retval = ((dev->dp8390.TSR.ow_coll << 7) | + (dev->dp8390.TSR.cd_hbeat << 6) | + (dev->dp8390.TSR.fifo_ur << 5) | + (dev->dp8390.TSR.no_carrier << 4) | + (dev->dp8390.TSR.aborted << 3) | + (dev->dp8390.TSR.collided << 2) | + (dev->dp8390.TSR.tx_ok)); + break; + + case 0x05: /* NCR */ + retval = dev->dp8390.num_coll; + break; + + case 0x06: /* FIFO */ + /* reading FIFO is only valid in loopback mode */ + DEBUG("3C503: reading FIFO not supported yet\n"); + retval = dev->dp8390.fifo; + break; + + case 0x07: /* ISR */ + retval = ((dev->dp8390.ISR.reset << 7) | + (dev->dp8390.ISR.rdma_done << 6) | + (dev->dp8390.ISR.cnt_oflow << 5) | + (dev->dp8390.ISR.overwrite << 4) | + (dev->dp8390.ISR.tx_err << 3) | + (dev->dp8390.ISR.rx_err << 2) | + (dev->dp8390.ISR.pkt_tx << 1) | + (dev->dp8390.ISR.pkt_rx)); + break; + + case 0x08: /* CRDA0 */ + retval = (dev->dp8390.remote_dma & 0xff); + break; + + case 0x09: /* CRDA1 */ + retval = (dev->dp8390.remote_dma >> 8); + break; + + case 0x0a: /* reserved / RTL8029ID0 */ + DEBUG("3C503: reserved Page0 read - 0x0a\n"); + retval = 0xff; + break; + + case 0x0b: /* reserved / RTL8029ID1 */ + DEBUG("3C503: reserved Page0 read - 0x0b\n"); + retval = 0xff; + break; + + case 0x0c: /* RSR */ + retval = ((dev->dp8390.RSR.deferred << 7) | + (dev->dp8390.RSR.rx_disabled << 6) | + (dev->dp8390.RSR.rx_mbit << 5) | + (dev->dp8390.RSR.rx_missed << 4) | + (dev->dp8390.RSR.fifo_or << 3) | + (dev->dp8390.RSR.bad_falign << 2) | + (dev->dp8390.RSR.bad_crc << 1) | + (dev->dp8390.RSR.rx_ok)); + break; + + case 0x0d: /* CNTR0 */ + retval = dev->dp8390.tallycnt_0; + break; + + case 0x0e: /* CNTR1 */ + retval = dev->dp8390.tallycnt_1; + break; + + case 0x0f: /* CNTR2 */ + retval = dev->dp8390.tallycnt_2; + break; + + default: + DEBUG("3C503: Page0 register 0x%02x out of range\n", off); + break; + } + + DEBUG("3C503: Page0 read from register 0x%02x, val=0x%02x\n", off, retval); + + return(retval); +} + + +static void +tc503_page0_write(tc503_t *dev, uint32_t off, uint32_t val, unsigned len) +{ + uint8_t val2; + + /* It appears to be a common practice to use outw on page0 regs... */ + + /* break up outw into two outb's */ + if (len == 2) { + tc503_page0_write(dev, off, (val & 0xff), 1); + if (off < 0x0f) + tc503_page0_write(dev, off+1, ((val>>8)&0xff), 1); + return; + } + + DEBUG("3C503: Page0 write to register 0x%02x, val=0x%02x\n", off, val); + + switch(off) { + case 0x01: /* PSTART */ + dev->dp8390.page_start = val; + break; + + case 0x02: /* PSTOP */ + dev->dp8390.page_stop = val; + break; + + case 0x03: /* BNRY */ + dev->dp8390.bound_ptr = val; + break; + + case 0x04: /* TPSR */ + dev->dp8390.tx_page_start = val; + break; + + case 0x05: /* TBCR0 */ + /* Clear out low byte and re-insert */ + dev->dp8390.tx_bytes &= 0xff00; + dev->dp8390.tx_bytes |= (val & 0xff); + break; + + case 0x06: /* TBCR1 */ + /* Clear out high byte and re-insert */ + dev->dp8390.tx_bytes &= 0x00ff; + dev->dp8390.tx_bytes |= ((val & 0xff) << 8); + break; + + case 0x07: /* ISR */ + val &= 0x7f; /* clear RST bit - status-only bit */ + /* All other values are cleared iff the ISR bit is 1 */ + dev->dp8390.ISR.pkt_rx &= !((int)((val & 0x01) == 0x01)); + dev->dp8390.ISR.pkt_tx &= !((int)((val & 0x02) == 0x02)); + dev->dp8390.ISR.rx_err &= !((int)((val & 0x04) == 0x04)); + dev->dp8390.ISR.tx_err &= !((int)((val & 0x08) == 0x08)); + dev->dp8390.ISR.overwrite &= !((int)((val & 0x10) == 0x10)); + dev->dp8390.ISR.cnt_oflow &= !((int)((val & 0x20) == 0x20)); + dev->dp8390.ISR.rdma_done &= !((int)((val & 0x40) == 0x40)); + val = ((dev->dp8390.ISR.rdma_done << 6) | + (dev->dp8390.ISR.cnt_oflow << 5) | + (dev->dp8390.ISR.overwrite << 4) | + (dev->dp8390.ISR.tx_err << 3) | + (dev->dp8390.ISR.rx_err << 2) | + (dev->dp8390.ISR.pkt_tx << 1) | + (dev->dp8390.ISR.pkt_rx)); + val &= ((dev->dp8390.IMR.rdma_inte << 6) | + (dev->dp8390.IMR.cofl_inte << 5) | + (dev->dp8390.IMR.overw_inte << 4) | + (dev->dp8390.IMR.txerr_inte << 3) | + (dev->dp8390.IMR.rxerr_inte << 2) | + (dev->dp8390.IMR.tx_inte << 1) | + (dev->dp8390.IMR.rx_inte)); + if (val == 0x00) + tc503_interrupt(dev, 0); + break; + + case 0x08: /* RSAR0 */ + /* Clear out low byte and re-insert */ + dev->dp8390.remote_start &= 0xff00; + dev->dp8390.remote_start |= (val & 0xff); + dev->dp8390.remote_dma = dev->dp8390.remote_start; + break; + + case 0x09: /* RSAR1 */ + /* Clear out high byte and re-insert */ + dev->dp8390.remote_start &= 0x00ff; + dev->dp8390.remote_start |= ((val & 0xff) << 8); + dev->dp8390.remote_dma = dev->dp8390.remote_start; + break; + + case 0x0a: /* RBCR0 */ + /* Clear out low byte and re-insert */ + dev->dp8390.remote_bytes &= 0xff00; + dev->dp8390.remote_bytes |= (val & 0xff); + break; + + case 0x0b: /* RBCR1 */ + /* Clear out high byte and re-insert */ + dev->dp8390.remote_bytes &= 0x00ff; + dev->dp8390.remote_bytes |= ((val & 0xff) << 8); + break; + + case 0x0c: /* RCR */ + /* Check if the reserved bits are set */ + if (val & 0xc0) { + DEBUG("3C503: RCR write, reserved bits set\n"); + } + + /* Set all other bit-fields */ + dev->dp8390.RCR.errors_ok = ((val & 0x01) == 0x01); + dev->dp8390.RCR.runts_ok = ((val & 0x02) == 0x02); + dev->dp8390.RCR.broadcast = ((val & 0x04) == 0x04); + dev->dp8390.RCR.multicast = ((val & 0x08) == 0x08); + dev->dp8390.RCR.promisc = ((val & 0x10) == 0x10); + dev->dp8390.RCR.monitor = ((val & 0x20) == 0x20); + + /* Monitor bit is a little suspicious... */ + if (val & 0x20) { + DEBUG("3C503: RCR write, monitor bit set!\n"); + } + break; + + case 0x0d: /* TCR */ + /* Check reserved bits */ + if (val & 0xe0) { + DEBUG("3C503: TCR write, reserved bits set\n"); + } + + /* Test loop mode (not supported) */ + if (val & 0x06) { + dev->dp8390.TCR.loop_cntl = (val & 0x6) >> 1; + DEBUG("3C503: TCR write, loop mode %d not supported\n", + dev->dp8390.TCR.loop_cntl); + } else { + dev->dp8390.TCR.loop_cntl = 0; + } + + /* Inhibit-CRC not supported. */ + if (val & 0x01) { + DEBUG("3C503: TCR write, inhibit-CRC not supported\n"); + } + + /* Auto-transmit disable very suspicious */ + if (val & 0x08) { + DEBUG("3C503: TCR write, auto transmit disable not supported\n"); + } + + /* Allow collision-offset to be set, although not used */ + dev->dp8390.TCR.coll_prio = ((val & 0x08) == 0x08); + break; + + case 0x0e: /* DCR */ + /* the loopback mode is not suppported yet */ + if (! (val & 0x08)) { + DEBUG("3C503: DCR write, loopback mode selected\n"); + } + + /* It is questionable to set longaddr and auto_rx, since + * they are not supported on the NE2000. Print a warning + * and continue. */ + if (val & 0x04) { + DEBUG("3C503: DCR write - LAS set ???\n"); + } + if (val & 0x10) { + DEBUG("3C503: DCR write - AR set ???\n"); + } + + /* Set other values. */ + dev->dp8390.DCR.wdsize = ((val & 0x01) == 0x01); + dev->dp8390.DCR.endian = ((val & 0x02) == 0x02); + dev->dp8390.DCR.longaddr = ((val & 0x04) == 0x04); /* illegal ? */ + dev->dp8390.DCR.loop = ((val & 0x08) == 0x08); + dev->dp8390.DCR.auto_rx = ((val & 0x10) == 0x10); /* also illegal ? */ + dev->dp8390.DCR.fifo_size = (val & 0x50) >> 5; + break; + + case 0x0f: /* IMR */ + /* Check for reserved bit */ + if (val & 0x80) { + DEBUG("3C503: IMR write, reserved bit set\n"); + } + + /* Set other values */ + dev->dp8390.IMR.rx_inte = ((val & 0x01) == 0x01); + dev->dp8390.IMR.tx_inte = ((val & 0x02) == 0x02); + dev->dp8390.IMR.rxerr_inte = ((val & 0x04) == 0x04); + dev->dp8390.IMR.txerr_inte = ((val & 0x08) == 0x08); + dev->dp8390.IMR.overw_inte = ((val & 0x10) == 0x10); + dev->dp8390.IMR.cofl_inte = ((val & 0x20) == 0x20); + dev->dp8390.IMR.rdma_inte = ((val & 0x40) == 0x40); + val2 = ((dev->dp8390.ISR.rdma_done << 6) | + (dev->dp8390.ISR.cnt_oflow << 5) | + (dev->dp8390.ISR.overwrite << 4) | + (dev->dp8390.ISR.tx_err << 3) | + (dev->dp8390.ISR.rx_err << 2) | + (dev->dp8390.ISR.pkt_tx << 1) | + (dev->dp8390.ISR.pkt_rx)); + if (((val & val2) & 0x7f) == 0) + tc503_interrupt(dev, 0); + else + tc503_interrupt(dev, 1); + break; + + default: + DEBUG("3C503: Page0 write, bad register 0x%02x\n", off); + break; + } +} + + +/* Handle reads/writes to the first page of the DS8390 register file. */ +static uint32_t +tc503_page1_read(tc503_t *dev, uint32_t off, unsigned int len) +{ + DBGLOG(2, "3C503: Page1 read from register 0x%02x, len=%u\n", off, len); + + switch(off) { + case 0x01: /* PAR0-5 */ + case 0x02: + case 0x03: + case 0x04: + case 0x05: + case 0x06: + return(dev->dp8390.physaddr[off - 1]); + + case 0x07: /* CURR */ + DBGLOG(1, "3C503: returning current page: 0x%02x\n", + (dev->dp8390.curr_page)); + return(dev->dp8390.curr_page); + + case 0x08: /* MAR0-7 */ + case 0x09: + case 0x0a: + case 0x0b: + case 0x0c: + case 0x0d: + case 0x0e: + case 0x0f: + return(dev->dp8390.mchash[off - 8]); + + default: + DEBUG("3C503: Page1 read register 0x%02x out of range\n", off); + return(0); + } +} + + +static void +tc503_page1_write(tc503_t *dev, uint32_t off, uint32_t val, unsigned len) +{ + DBGLOG(2, "3C503: Page1 write to register 0x%02x, len=%u, value=0x%04x\n", + off, len, val); + switch(off) { + case 0x01: /* PAR0-5 */ + case 0x02: + case 0x03: + case 0x04: + case 0x05: + case 0x06: + dev->dp8390.physaddr[off - 1] = val; + if (off == 6) { + DEBUG("3C503: physical address set to %02x:%02x:%02x:%02x:%02x:%02x\n", + dev->dp8390.physaddr[0], dev->dp8390.physaddr[1], + dev->dp8390.physaddr[2], dev->dp8390.physaddr[3], + dev->dp8390.physaddr[4], dev->dp8390.physaddr[5]); + } + break; + + case 0x07: /* CURR */ + dev->dp8390.curr_page = val; + break; + + case 0x08: /* MAR0-7 */ + case 0x09: + case 0x0a: + case 0x0b: + case 0x0c: + case 0x0d: + case 0x0e: + case 0x0f: + dev->dp8390.mchash[off - 8] = val; + break; + + default: + DEBUG("3C503: Page1 write register 0x%02x out of range\n", off); + break; + } +} + + +/* Handle reads/writes to the second page of the DS8390 register file. */ +static uint32_t +tc503_page2_read(tc503_t *dev, uint32_t off, unsigned int len) +{ + DBGLOG(2, "3C503: Page2 read from register 0x%02x, len=%u\n", off, len); + + switch(off) { + case 0x01: /* PSTART */ + return(dev->dp8390.page_start); + + case 0x02: /* PSTOP */ + return(dev->dp8390.page_stop); + + case 0x03: /* Remote Next-packet pointer */ + return(dev->dp8390.rempkt_ptr); + + case 0x04: /* TPSR */ + return(dev->dp8390.tx_page_start); + + case 0x05: /* Local Next-packet pointer */ + return(dev->dp8390.localpkt_ptr); + + case 0x06: /* Address counter (upper) */ + return(dev->dp8390.address_cnt >> 8); + + case 0x07: /* Address counter (lower) */ + return(dev->dp8390.address_cnt & 0xff); + + case 0x08: /* Reserved */ + case 0x09: + case 0x0a: + case 0x0b: + DEBUG("3C503: reserved Page2 read - register 0x%02x\n", off); + return(0xff); + + case 0x0c: /* RCR */ + return ((dev->dp8390.RCR.monitor << 5) | + (dev->dp8390.RCR.promisc << 4) | + (dev->dp8390.RCR.multicast << 3) | + (dev->dp8390.RCR.broadcast << 2) | + (dev->dp8390.RCR.runts_ok << 1) | + (dev->dp8390.RCR.errors_ok)); + + case 0x0d: /* TCR */ + return ((dev->dp8390.TCR.coll_prio << 4) | + (dev->dp8390.TCR.ext_stoptx << 3) | + ((dev->dp8390.TCR.loop_cntl & 0x3) << 1) | + (dev->dp8390.TCR.crc_disable)); + + case 0x0e: /* DCR */ + return (((dev->dp8390.DCR.fifo_size & 0x3) << 5) | + (dev->dp8390.DCR.auto_rx << 4) | + (dev->dp8390.DCR.loop << 3) | + (dev->dp8390.DCR.longaddr << 2) | + (dev->dp8390.DCR.endian << 1) | + (dev->dp8390.DCR.wdsize)); + + case 0x0f: /* IMR */ + return ((dev->dp8390.IMR.rdma_inte << 6) | + (dev->dp8390.IMR.cofl_inte << 5) | + (dev->dp8390.IMR.overw_inte << 4) | + (dev->dp8390.IMR.txerr_inte << 3) | + (dev->dp8390.IMR.rxerr_inte << 2) | + (dev->dp8390.IMR.tx_inte << 1) | + (dev->dp8390.IMR.rx_inte)); + + default: + DEBUG("3C503: Page2 register 0x%02x out of range\n", off); + break; + } + + return(0); +} + + +/* Maybe all writes here should be BX_PANIC()'d, since they + affect internal operation, but let them through for now + and print a warning. */ +static void +tc503_page2_write(tc503_t *dev, uint32_t off, uint32_t val, unsigned len) +{ + DBGLOG(2, "3C503: Page2 write to register 0x%02x, len=%u, value=0x%04x\n", + off, len, val); + switch(off) { + case 0x01: /* CLDA0 */ + /* Clear out low byte and re-insert */ + dev->dp8390.local_dma &= 0xff00; + dev->dp8390.local_dma |= (val & 0xff); + break; + + case 0x02: /* CLDA1 */ + /* Clear out high byte and re-insert */ + dev->dp8390.local_dma &= 0x00ff; + dev->dp8390.local_dma |= ((val & 0xff) << 8); + break; + + case 0x03: /* Remote Next-pkt pointer */ + dev->dp8390.rempkt_ptr = val; + break; + + case 0x04: + DEBUG("page 2 write to reserved register 0x04\n"); + break; + + case 0x05: /* Local Next-packet pointer */ + dev->dp8390.localpkt_ptr = val; + break; + + case 0x06: /* Address counter (upper) */ + /* Clear out high byte and re-insert */ + dev->dp8390.address_cnt &= 0x00ff; + dev->dp8390.address_cnt |= ((val & 0xff) << 8); + break; + + case 0x07: /* Address counter (lower) */ + /* Clear out low byte and re-insert */ + dev->dp8390.address_cnt &= 0xff00; + dev->dp8390.address_cnt |= (val & 0xff); + break; + + case 0x08: + case 0x09: + case 0x0a: + case 0x0b: + case 0x0c: + case 0x0d: + case 0x0e: + case 0x0f: + DEBUG("3C503: Page2 write to reserved register 0x%02x\n", off); + break; + + default: + DEBUG("3C503: Page2 write, illegal register 0x%02x\n", off); + break; + } +} + + +/* Routines for handling reads/writes to the Command Register. */ +static uint32_t +tc503_read_cr(tc503_t *dev) +{ + uint32_t retval; + + retval = (((dev->dp8390.CR.pgsel & 0x03) << 6) | + ((dev->dp8390.CR.rdma_cmd & 0x07) << 3) | + (dev->dp8390.CR.tx_packet << 2) | + (dev->dp8390.CR.start << 1) | + (dev->dp8390.CR.stop)); + + DBGLOG(1, "3C503: read CR returns 0x%02x\n", retval); + + return(retval); +} + + +static void +tc503_write_cr(tc503_t *dev, uint32_t val) +{ + DBGLOG(1, "3C503: wrote 0x%02x to CR\n", val); + + /* Validate remote-DMA */ + if ((val & 0x38) == 0x00) { + DEBUG("3C503: CR write - invalid rDMA value 0\n"); + val |= 0x20; /* dma_cmd == 4 is a safe default */ + } + + /* Check for s/w reset */ + if (val & 0x01) { + dev->dp8390.ISR.reset = 1; + dev->dp8390.CR.stop = 1; + } else + dev->dp8390.CR.stop = 0; + + dev->dp8390.CR.rdma_cmd = (val & 0x38) >> 3; + + /* If start command issued, the RST bit in the ISR */ + /* must be cleared */ + if ((val & 0x02) && !dev->dp8390.CR.start) + dev->dp8390.ISR.reset = 0; + + dev->dp8390.CR.start = ((val & 0x02) == 0x02); + dev->dp8390.CR.pgsel = (val & 0xc0) >> 6; + + /* Check for send-packet command */ + if (dev->dp8390.CR.rdma_cmd == 3) { + /* Set up DMA read from receive ring */ + dev->dp8390.remote_start = dev->dp8390.remote_dma = dev->dp8390.bound_ptr * 256; + dev->dp8390.remote_bytes = (uint16_t) tc503_chipmem_read(dev, dev->dp8390.bound_ptr * 256 + 2, 2); + DEBUG("3C503: sending buffer %x length %d\n", + dev->dp8390.remote_start, dev->dp8390.remote_bytes); + } + + /* Check for start-tx */ + if ((val & 0x04) && dev->dp8390.TCR.loop_cntl) { + if (dev->dp8390.TCR.loop_cntl != 1) { + DEBUG("3C503: loop mode %d not supported\n", + dev->dp8390.TCR.loop_cntl); + } else { + tc503_rx(dev, + &dev->dp8390.mem[dev->dp8390.tx_page_start*256 - DP8390_WORD_MEMSTART], + dev->dp8390.tx_bytes); + } + } else if (val & 0x04) { + if (dev->dp8390.CR.stop || (!dev->dp8390.CR.start)) { + if (dev->dp8390.tx_bytes == 0) /* njh@bandsman.co.uk */ + return; /* Solaris9 probe */ + DEBUG("3C503: CR write - tx start, dev in reset\n"); + } + + if (dev->dp8390.tx_bytes == 0) + DEBUG("3C503: CR write - tx start, tx bytes == 0\n"); + + /* Send the packet to the system driver */ + dev->dp8390.CR.tx_packet = 1; + network_tx(&dev->dp8390.mem[dev->dp8390.tx_page_start*256 - DP8390_WORD_MEMSTART], + dev->dp8390.tx_bytes); + + /* some more debug */ + if (dev->dp8390.tx_timer_active) { + DEBUG("3C503: CR write, tx timer still active\n"); + } + + tc503_tx(dev, val); + } + + /* Linux probes for an interrupt by setting up a remote-DMA read + * of 0 bytes with remote-DMA completion interrupts enabled. + * Detect this here */ + if (dev->dp8390.CR.rdma_cmd == 0x01 && dev->dp8390.CR.start && dev->dp8390.remote_bytes == 0) { + dev->dp8390.ISR.rdma_done = 1; + if (dev->dp8390.IMR.rdma_inte) { + tc503_interrupt(dev, 1); + tc503_interrupt(dev, 0); + } + } +} + + +static uint8_t +tc503_lo_read(uint16_t addr, void *priv) +{ + tc503_t *dev = (tc503_t *)priv; + uint8_t retval = 0; + int off = addr - dev->base_address; + + switch ((dev->regs.ctrl >> 2) & 3) { + case 0x00: + DEBUG(0, "Read offset=%04x\n", off); + if (off == 0x00) + retval = tc503_read_cr(dev); + else switch(dev->dp8390.CR.pgsel) { + case 0x00: + retval = tc503_page0_read(dev, off, 1); + break; + + case 0x01: + retval = tc503_page1_read(dev, off, 1); + break; + + case 0x02: + retval = tc503_page2_read(dev, off, 1); + break; + + case 0x03: + retval = 0xff; + break; + } + break; + + case 0x01: + retval = dev->prom[off]; + break; + + case 0x02: + retval = dev->prom[off + 0x10]; + break; + + case 0x03: + retval = 0xff; + break; + } + + return(retval); +} + + +static void +tc503_lo_write(uint16_t addr, uint8_t val, void *priv) +{ + tc503_t *dev = (tc503_t *)priv; + int off = addr - dev->base_address; + + switch ((dev->regs.ctrl >> 2) & 3) { + case 0x00: + /* The high 16 bytes of i/o space are for the ne2000 asic - + the low 16 bytes are for the DS8390, with the current + page being selected by the PS0,PS1 registers in the + command register */ + if (off == 0x00) + tc503_write_cr(dev, val); + else switch(dev->dp8390.CR.pgsel) { + case 0x00: + tc503_page0_write(dev, off, val, 1); + break; + + case 0x01: + tc503_page1_write(dev, off, val, 1); + break; + + case 0x02: + tc503_page2_write(dev, off, val, 1); + break; + + case 0x03: + break; + } + break; + + case 0x01: + case 0x02: + case 0x03: + break; + } + + DEBUG("3C503: write addr %x, value %x\n", addr, val); +} + + +static uint8_t +tc503_hi_read(uint16_t addr, void *priv) +{ + tc503_t *dev = (tc503_t *)priv; + + DEBUG("3C503: Read GA address=%04x\n", addr); + + switch (addr & 0x0f) { + case 0x00: + return dev->regs.pstr; + + case 0x01: + return dev->regs.pspr; + + case 0x02: + return dev->regs.dqtr; + + case 0x03: + switch (dev->base_address) { + default: + case 0x300: + dev->regs.bcfr = 0x80; + break; + + case 0x310: + dev->regs.bcfr = 0x40; + break; + + case 0x330: + dev->regs.bcfr = 0x20; + break; + + case 0x350: + dev->regs.bcfr = 0x10; + break; + + case 0x250: + dev->regs.bcfr = 0x08; + break; + + case 0x280: + dev->regs.bcfr = 0x04; + break; + + case 0x2a0: + dev->regs.bcfr = 0x02; + break; + + case 0x2e0: + dev->regs.bcfr = 0x01; + break; + } + return dev->regs.bcfr; + + case 0x04: + switch (dev->bios_addr) { + case 0xdc000: + dev->regs.pcfr = 0x80; + break; + + case 0xd8000: + dev->regs.pcfr = 0x40; + break; + + case 0xcc000: + dev->regs.pcfr = 0x20; + break; + + case 0xc8000: + dev->regs.pcfr = 0x10; + break; + } + return dev->regs.pcfr; + + case 0x05: + return dev->regs.gacfr; + + case 0x06: + return dev->regs.ctrl; + + case 0x07: + return dev->regs.streg; + + case 0x08: + return dev->regs.idcfr; + + case 0x09: + return (dev->regs.da >> 8); + + case 0x0a: + return (dev->regs.da & 0xff); + + case 0x0b: + return (dev->regs.vptr >> 12) & 0xff; + + case 0x0c: + return (dev->regs.vptr >> 4) & 0xff; + + case 0x0d: + return (dev->regs.vptr & 0x0f) << 4; + + case 0x0e: + case 0x0f: + if (!(dev->regs.ctrl & 0x80)) + return 0xff; + + tc503_set_drq(dev); + + return tc503_chipmem_read(dev, dev->regs.da++, 1); + } + + return 0; +} + + +static void +tc503_hi_write(uint16_t addr, uint8_t val, void *priv) +{ + tc503_t *dev = (tc503_t *)priv; + + DEBUG("3C503: Write GA address=%04x, val=%04x\n", addr, val); + + switch (addr & 0x0f) { + case 0x00: + dev->regs.pstr = val; + break; + + case 0x01: + dev->regs.pspr = val; + break; + + case 0x02: + dev->regs.dqtr = val; + break; + + case 0x05: + if ((dev->regs.gacfr & 0x0f) != (val & 0x0f)) { + mem_map_disable(&dev->ram_mapping); + + switch (val & 0x0f) { + case 0: /*ROM mapping*/ + /* FIXME: Implement this when a BIOS is found/generated. */ + break; + + case 9: /*RAM mapping*/ + mem_map_enable(&dev->ram_mapping); + break; + + default: /*No ROM mapping*/ + break; + } + } + + if (!(val & 0x80)) + tc503_interrupt(dev, 1); + else + tc503_interrupt(dev, 0); + + dev->regs.gacfr = val; + break; + + case 0x06: + if (val & 1) { + tc503_reset(dev); + dev->dp8390.ISR.reset = 1; + dev->regs.ctrl = 0x0b; + return; + } + + if ((val & 0x80) != (dev->regs.ctrl & 0x80)) { + if (val & 0x80) + dev->regs.streg |= 0x88; + else + dev->regs.streg &= ~0x88; + dev->regs.streg &= ~0x10; + } + dev->regs.ctrl = val; + break; + + case 0x08: + switch (val & 0xf0) { + case 0x00: + case 0x10: + case 0x20: + case 0x40: + case 0x80: + dev->regs.idcfr = (dev->regs.idcfr & 0x0f) | (val & 0xf0); + break; + + default: + DEBUG("Trying to set multiple IRQs: %02x\n", val); + break; + } + + switch (val & 0x0f) { + case 0x00: + case 0x01: + case 0x02: + case 0x04: + dev->regs.idcfr = (dev->regs.idcfr & 0xf0) | (val & 0x0f); + break; + + case 0x08: + break; + + default: + DEBUG("Trying to set multiple DMA channels: %02x\n", val); + break; + } + break; + + case 0x09: + dev->regs.da = (val << 8) | (dev->regs.da & 0xff); + break; + + case 0x0a: + dev->regs.da = (dev->regs.da & 0xff00) | val; + break; + + case 0x0b: + dev->regs.vptr = (val << 12) | (dev->regs.vptr & 0xfff); + break; + + case 0x0c: + dev->regs.vptr = (val << 4) | (dev->regs.vptr & 0xff00f); + break; + + case 0x0d: + dev->regs.vptr = (val << 4) | (dev->regs.vptr & 0xffff0); + break; + + case 0x0e: + case 0x0f: + if (!(dev->regs.ctrl & 0x80)) + return; + + tc503_set_drq(dev); + + tc503_chipmem_write(dev, dev->regs.da++, val, 1); + break; + } +} + + +static void +tc503_ioremove(tc503_t *dev, uint16_t addr) +{ + io_removehandler(addr, 16, + tc503_lo_read, NULL, NULL, + tc503_lo_write, NULL, NULL, dev); + + io_removehandler(addr+0x400, 16, + tc503_hi_read, NULL, NULL, + tc503_hi_write, NULL, NULL, dev); +} + + +static void +tc503_ioset(tc503_t *dev, uint16_t addr) +{ + io_sethandler(addr, 16, + tc503_lo_read, NULL, NULL, + tc503_lo_write, NULL, NULL, dev); + + io_sethandler(addr+0x400, 16, + tc503_hi_read, NULL, NULL, + tc503_hi_write, NULL, NULL, dev); +} + + +static void +tc503_tx(tc503_t *dev, uint32_t val) +{ + dev->dp8390.CR.tx_packet = 0; + dev->dp8390.TSR.tx_ok = 1; + dev->dp8390.ISR.pkt_tx = 1; + + /* Generate an interrupt if not masked */ + if (dev->dp8390.IMR.tx_inte) + tc503_interrupt(dev, 1); + + dev->dp8390.tx_timer_active = 0; +} + + +/* + * Called by the platform-specific code when an Ethernet frame + * has been received. The destination address is tested to see + * if it should be accepted, and if the RX ring has enough room, + * it is copied into it and the receive process is updated. + */ +static void +tc503_rx(void *priv, uint8_t *buf, int io_len) +{ + static uint8_t bcast_addr[6] = {0xff,0xff,0xff,0xff,0xff,0xff}; + tc503_t *dev = (tc503_t *)priv; + uint8_t pkthdr[4]; + uint8_t *startptr; + int rx_pages, avail; + int idx, nextpage; + int endbytes; + + /* FIXME: move to upper layer */ + ui_sb_icon_update(SB_NETWORK, 1); + + if (io_len != 60) { + DEBUG("3C503: rx_frame with length %d\n", io_len); + } + + if ((dev->dp8390.CR.stop != 0) || (dev->dp8390.page_start == 0)) return; + + /* + * Add the pkt header + CRC to the length, and work + * out how many 256-byte pages the frame would occupy. + */ + rx_pages = (io_len + sizeof(pkthdr) + sizeof(uint32_t) + 255)/256; + if (dev->dp8390.curr_page < dev->dp8390.bound_ptr) { + avail = dev->dp8390.bound_ptr - dev->dp8390.curr_page; + } else { + avail = (dev->dp8390.page_stop - dev->dp8390.page_start) - + (dev->dp8390.curr_page - dev->dp8390.bound_ptr); + } + + /* + * Avoid getting into a buffer overflow condition by + * not attempting to do partial receives. The emulation + * to handle this condition seems particularly painful. + */ + if ((avail < rx_pages) +#if DP8390_NEVER_FULL_RING + || (avail == rx_pages) +#endif + ) { + DEBUG("3C503: no space\n"); + + /* FIXME: move to upper layer */ + ui_sb_icon_update(SB_NETWORK, 0); + return; + } + + if ((io_len < 40/*60*/) && !dev->dp8390.RCR.runts_ok) { + DEBUG("3C503: rejected small packet, length %d\n", io_len); + + /* FIXME: move to upper layer */ + ui_sb_icon_update(SB_NETWORK, 0); + return; + } + + /* Some computers don't care... */ + if (io_len < 60) + io_len = 60; + + DBGLOG(1, "3C503: RX %x:%x:%x:%x:%x:%x > %x:%x:%x:%x:%x:%x len %d\n", + buf[6], buf[7], buf[8], buf[9], buf[10], buf[11], + buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], io_len); + + /* Do address filtering if not in promiscuous mode. */ + if (! dev->dp8390.RCR.promisc) { + /* If this is a broadcast frame.. */ + if (! memcmp(buf, bcast_addr, 6)) { + /* Broadcast not enabled, we're done. */ + if (! dev->dp8390.RCR.broadcast) { + DEBUG("3C503: RX BC disabled\n"); + + /* FIXME: move to upper layer */ + ui_sb_icon_update(SB_NETWORK, 0); + return; + } + } + + /* If this is a multicast frame.. */ + else if (buf[0] & 0x01) { + /* Multicast not enabled, we're done. */ + if (! dev->dp8390.RCR.multicast) { + DEBUG("3C503: RX MC disabled\n"); + + /* FIXME: move to upper layer */ + ui_sb_icon_update(SB_NETWORK, 0); + return; + } + + /* Are we listening to this multicast address? */ + idx = mcast_index(buf); + if (! (dev->dp8390.mchash[idx>>3] & (1<<(idx&0x7)))) { + DEBUG("3C503: RX MC not listed\n"); + + /* FIXME: move to upper layer */ + ui_sb_icon_update(SB_NETWORK, 0); + return; + } + } + + /* Unicast, must be for us.. */ + else if (memcmp(buf, dev->dp8390.physaddr, 6)) return; + } else { + DEBUG("3C503: RX promiscuous receive\n"); + } + + nextpage = dev->dp8390.curr_page + rx_pages; + if (nextpage >= dev->dp8390.page_stop) + nextpage -= (dev->dp8390.page_stop - dev->dp8390.page_start); + + /* Set up packet header. */ + pkthdr[0] = 0x01; /* RXOK - packet is OK */ + if (buf[0] & 0x01) + pkthdr[0] |= 0x20; /* MULTICAST packet */ + pkthdr[1] = nextpage; /* ptr to next packet */ + pkthdr[2] = (io_len + sizeof(pkthdr))&0xff; /* length-low */ + pkthdr[3] = (io_len + sizeof(pkthdr))>>8; /* length-hi */ + DBGLOG(1, "3C503: RX pkthdr [%02x %02x %02x %02x]\n", + pkthdr[0], pkthdr[1], pkthdr[2], pkthdr[3]); + + /* Copy into buffer, update curpage, and signal interrupt if config'd */ + startptr = &dev->dp8390.mem[(dev->dp8390.curr_page * 256) - DP8390_WORD_MEMSTART]; + memcpy(startptr, pkthdr, sizeof(pkthdr)); + if ((nextpage > dev->dp8390.curr_page) || + ((dev->dp8390.curr_page + rx_pages) == dev->dp8390.page_stop)) { + memcpy(startptr+sizeof(pkthdr), buf, io_len); + } else { + endbytes = (dev->dp8390.page_stop - dev->dp8390.curr_page) * 256; + memcpy(startptr+sizeof(pkthdr), buf, endbytes-sizeof(pkthdr)); + startptr = &dev->dp8390.mem[(dev->dp8390.page_start * 256) - DP8390_WORD_MEMSTART]; + memcpy(startptr, buf+endbytes-sizeof(pkthdr), io_len-endbytes+8); + } + dev->dp8390.curr_page = nextpage; + + dev->dp8390.RSR.rx_ok = 1; + dev->dp8390.RSR.rx_mbit = (buf[0] & 0x01) ? 1 : 0; + dev->dp8390.ISR.pkt_rx = 1; + + if (dev->dp8390.IMR.rx_inte) + tc503_interrupt(dev, 1); + + /* FIXME: move to upper layer */ + ui_sb_icon_update(SB_NETWORK, 0); +} + + +static void * +tc503_init(const device_t *info) +{ + uint32_t mac; + tc503_t *dev; + + dev = (tc503_t *)mem_alloc(sizeof(tc503_t)); + memset(dev, 0x00, sizeof(tc503_t)); + dev->maclocal[0] = 0x02; /* 02:60:8C (3Com OID) */ + dev->maclocal[1] = 0x60; + dev->maclocal[2] = 0x8C; + + dev->base_address = device_get_config_hex16("base"); + dev->base_irq = device_get_config_int("irq"); + dev->dma_channel = device_get_config_int("dma"); + dev->bios_addr = device_get_config_hex20("bios_addr"); + + /* See if we have a local MAC address configured. */ + mac = device_get_config_mac("mac", -1); + + /* + * Make this device known to the I/O system. + * + * PnP and PCI devices start with address spaces inactive. + */ + tc503_ioset(dev, dev->base_address); + + /* Set up our BIA. */ + if (mac & 0xff000000) { + /* Generate new local MAC. */ + dev->maclocal[3] = random_generate(); + dev->maclocal[4] = random_generate(); + dev->maclocal[5] = random_generate(); + mac = (((int) dev->maclocal[3]) << 16); + mac |= (((int) dev->maclocal[4]) << 8); + mac |= ((int) dev->maclocal[5]); + device_set_config_mac("mac", mac); + } else { + dev->maclocal[3] = (mac>>16) & 0xff; + dev->maclocal[4] = (mac>>8) & 0xff; + dev->maclocal[5] = (mac & 0xff); + } + memcpy(dev->dp8390.physaddr, dev->maclocal, sizeof(dev->maclocal)); + + INFO("I/O=%04x, IRQ=%d, MAC=%02x:%02x:%02x:%02x:%02x:%02x\n", + dev->base_address, dev->base_irq, + dev->dp8390.physaddr[0], dev->dp8390.physaddr[1], dev->dp8390.physaddr[2], + dev->dp8390.physaddr[3], dev->dp8390.physaddr[4], dev->dp8390.physaddr[5]); + + /* Reset the board. */ + tc503_reset(dev); + + /* Attach ourselves to the network module. */ + network_attach(dev, dev->dp8390.physaddr, tc503_rx); + + /* Map this system into the memory map. */ + mem_map_add(&dev->ram_mapping, dev->bios_addr, 0x4000, + tc503_ram_read, NULL, NULL, + tc503_ram_write, NULL, NULL, + NULL, MEM_MAPPING_EXTERNAL, dev); + mem_map_disable(&dev->ram_mapping); + + return(dev); +} + + +static void +tc503_close(void *priv) +{ + tc503_t *dev = (tc503_t *)priv; + + /* Make sure the platform layer is shut down. */ + network_close(); + + tc503_ioremove(dev, dev->base_address); + + DEBUG("3C503: closed\n"); + + free(dev); +} + + +static const device_config_t tc503_config[] = { + { + "base", "Address", CONFIG_HEX16, "", 0x300, + { + { + "0x250", 0x250 + }, + { + "0x280", 0x280 + }, + { + "0x2a0", 0x2a0 + }, + { + "0x2e0", 0x2e0 + }, + { + "0x300", 0x300 + }, + { + "0x310", 0x310 + }, + { + "0x330", 0x330 + }, + { + "0x350", 0x350 + }, + { + "", 0 + } + }, + { { NULL, { NULL } } }, + { 0, 0, 0 } + }, + { + "irq", "IRQ", CONFIG_SELECTION, "", 3, + { + { + "IRQ 2", 2 + }, + { + "IRQ 3", 3 + }, + { + "IRQ 4", 4 + }, + { + "IRQ 5", 5 + }, + { + "", 0 + } + }, + { { NULL, { NULL } } }, + { 0, 0, 0 } + }, + { + "dma", "DMA", CONFIG_SELECTION, "", 3, + { + { + "DMA 1", 1 + }, + { + "DMA 2", 2 + }, + { + "DMA 3", 3 + }, + { + "", 0 + } + }, + { { NULL, { NULL } } }, + { 0, 0, 0 } + }, + { + "mac", "MAC Address", CONFIG_MAC, "", -1, + { + { + "", 0 + } + }, + { { NULL, { NULL } } }, + { 0, 0, 0 } + }, + { + "bios_addr", "BIOS address", CONFIG_HEX20, "", 0xCC000, + { + { + "DC00", 0xDC000 + }, + { + "D800", 0xD8000 + }, + { + "C800", 0xC8000 + }, + { + "CC00", 0xCC000 + }, + { + "", 0 + } + }, + { { NULL, { NULL } } }, + { 0, 0, 0 } + }, + { + "", "", -1, "", -1, + { + { + "", 0 + } + }, + { { NULL, { NULL } } }, + { 0, 0, 0 } + } +}; + + +const device_t tc503_device = { + "3Com EtherLink II", + DEVICE_ISA, + 0, + tc503_init, tc503_close, NULL, + NULL, NULL, NULL, NULL, + tc503_config +}; diff --git a/src/devices/video/vid_bt485_ramdac.h b/src/devices/network/net_3com.h similarity index 57% rename from src/devices/video/vid_bt485_ramdac.h rename to src/devices/network/net_3com.h index e365446..7111428 100644 --- a/src/devices/video/vid_bt485_ramdac.h +++ b/src/devices/network/net_3com.h @@ -6,17 +6,13 @@ * * This file is part of the VARCem Project. * - * Definitions for the BT485 driver. + * Definitions for the 3Com series of ethernet controllers. * - * Version: @(#)vid_bt485_ramdac.h 1.0.1 2018/02/14 + * Version: @(#)net_3com.h 1.0.1 2018/09/07 * - * Authors: Fred N. van Kempen, - * Miran Grca, - * Sarah Walker, + * Author: Fred N. van Kempen, * * Copyright 2017,2018 Fred N. van Kempen. - * Copyright 2016-2018 Miran Grca. - * Copyright 2008-2018 Sarah Walker. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -36,25 +32,11 @@ * Boston, MA 02111-1307 * USA. */ -#ifndef VIDEO_BT485_RAMDAC_H -# define VIDEO_BT485_RAMDAC_H +#ifndef NET_3COME_H +# define NET_3COM_H -typedef struct bt485_ramdac_t -{ - int magic_count; - uint8_t command; - int windex, rindex; - uint16_t regs[256]; - int reg_ff; - int rs2; - int rs3; -} bt485_ramdac_t; - -void bt485_ramdac_out(uint16_t addr, uint8_t val, bt485_ramdac_t *ramdac, svga_t *svga); -uint8_t bt485_ramdac_in(uint16_t addr, bt485_ramdac_t *ramdac, svga_t *svga); - -float bt485_getclock(int clock, void *p); +extern const device_t tc503_device; -#endif /*VIDEO_BT485_RAMDAC_H*/ +#endif /*NET_3COM_H*/ diff --git a/src/devices/network/net_dp8390.c b/src/devices/network/net_dp8390.c new file mode 100644 index 0000000..7f8f9e4 --- /dev/null +++ b/src/devices/network/net_dp8390.c @@ -0,0 +1,78 @@ +/* + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. + * + * This file is part of the VARCem Project. + * + * Handling of the NatSemi DP8390 ethernet controller chip. + * + * Version: @(#)net_dp8390.c 1.0.1 2018/09/14 + * + * Authors: Fred N. van Kempen, + * Peter Grehan, + * + * Copyright 2017,2018 Fred N. van Kempen. + * Portions Copyright (C) 2002 MandrakeSoft S.A. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the: + * + * Free Software Foundation, Inc. + * 59 Temple Place - Suite 330 + * Boston, MA 02111-1307 + * USA. + */ +#include +#include +#include +#include +#include +#define dbglog network_dev_log +#include "../../emu.h" +#include "../../device.h" +#include "../../ui/ui.h" +#include "../../plat.h" +#include "network.h" +#include "net_dp8390.h" +#include "bswap.h" + + +/* + * Return the 6-bit index into the multicast table. + * + * Stolen unashamedly from FreeBSD's if_ed.c + */ +int +mcast_index(const void *dst) +{ +#define POLYNOMIAL 0x04c11db6 + uint32_t crc = 0xffffffffL; + int carry, i, j; + uint8_t b; + uint8_t *ep = (uint8_t *)dst; + + for (i=6; --i>=0;) { + b = *ep++; + for (j = 8; --j >= 0;) { + carry = ((crc & 0x80000000L) ? 1 : 0) ^ (b & 0x01); + crc <<= 1; + b >>= 1; + if (carry) + crc = ((crc ^ POLYNOMIAL) | carry); + } + } + return(crc >> 26); +#undef POLYNOMIAL +} diff --git a/src/devices/network/net_dp8390.h b/src/devices/network/net_dp8390.h new file mode 100644 index 0000000..b70460c --- /dev/null +++ b/src/devices/network/net_dp8390.h @@ -0,0 +1,196 @@ +/* + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. + * + * This file is part of the VARCem Project. + * + * Definitions for the NatSemi DP8390 handler. + * + * Version: @(#)net_dp8390.h 1.0.1 2018/09/07 + * + * Author: Fred N. van Kempen, + * + * Copyright 2017,2018 Fred N. van Kempen. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the: + * + * Free Software Foundation, Inc. + * 59 Temple Place - Suite 330 + * Boston, MA 02111-1307 + * USA. + */ +#ifndef NET_DP8390_H +# define NET_DP8390_H + + +/* Never completely fill the ne2k ring so that we never + hit the unclear completely full buffer condition. */ +#define DP8390_NEVER_FULL_RING (1) + +#define DP8390_DWORD_MEMSIZ (32*1024) +#define DP8390_DWORD_MEMSTART (16*1024) +#define DP8390_DWORD_MEMEND (DP8390_DWORD_MEMSTART+DP8390_DWORD_MEMSIZ) + +#define DP8390_WORD_MEMSIZ (16*1024) +#define DP8390_WORD_MEMSTART (8*1024) +#define DP8390_WORD_MEMEND (DP8390_WORD_MEMSTART+DP8390_WORD_MEMSIZ) + + +typedef struct { + /* Page 0 */ + + /* Command Register - 00h read/write */ + struct CR_t { + int stop; /* STP - Software Reset command */ + int start; /* START - start the NIC */ + int tx_packet; /* TXP - initiate packet transmission */ + uint8_t rdma_cmd; /* RD0,RD1,RD2 - Remote DMA command */ + uint8_t pgsel; /* PS0,PS1 - Page select */ + } CR; + + /* Interrupt Status Register - 07h read/write */ + struct ISR_t { + int pkt_rx; /* PRX - packet received with no errors */ + int pkt_tx; /* PTX - packet txed with no errors */ + int rx_err; /* RXE - packet rxed with 1 or more errors */ + int tx_err; /* TXE - packet txed " " " " " */ + int overwrite; /* OVW - rx buffer resources exhausted */ + int cnt_oflow; /* CNT - network tally counter MSB's set */ + int rdma_done; /* RDC - remote DMA complete */ + int reset; /* RST - reset status */ + } ISR; + + /* Interrupt Mask Register - 0fh write */ + struct IMR_t { + int rx_inte; /* PRXE - packet rx interrupt enable */ + int tx_inte; /* PTXE - packet tx interrput enable */ + int rxerr_inte; /* RXEE - rx error interrupt enable */ + int txerr_inte; /* TXEE - tx error interrupt enable */ + int overw_inte; /* OVWE - overwrite warn int enable */ + int cofl_inte; /* CNTE - counter o'flow int enable */ + int rdma_inte; /* RDCE - remote DMA complete int enable */ + int reserved; /* D7 - reserved */ + } IMR; + + /* Data Configuration Register - 0eh write */ + struct DCR_t { + int wdsize; /* WTS - 8/16-bit select */ + int endian; /* BOS - byte-order select */ + int longaddr; /* LAS - long-address select */ + int loop; /* LS - loopback select */ + int auto_rx; /* AR - auto-remove rx pkts with remote DMA */ + uint8_t fifo_size; /* FT0,FT1 - fifo threshold */ + } DCR; + + /* Transmit Configuration Register - 0dh write */ + struct TCR_t { + int crc_disable; /* CRC - inhibit tx CRC */ + uint8_t loop_cntl; /* LB0,LB1 - loopback control */ + int ext_stoptx; /* ATD - allow tx disable by external mcast */ + int coll_prio; /* OFST - backoff algorithm select */ + uint8_t reserved; /* D5,D6,D7 - reserved */ + } TCR; + + /* Transmit Status Register - 04h read */ + struct TSR_t { + int tx_ok; /* PTX - tx complete without error */ + int reserved; /* D1 - reserved */ + int collided; /* COL - tx collided >= 1 times */ + int aborted; /* ABT - aborted due to excessive collisions */ + int no_carrier; /* CRS - carrier-sense lost */ + int fifo_ur; /* FU - FIFO underrun */ + int cd_hbeat; /* CDH - no tx cd-heartbeat from transceiver */ + int ow_coll; /* OWC - out-of-window collision */ + } TSR; + + /* Receive Configuration Register - 0ch write */ + struct RCR_t { + int errors_ok; /* SEP - accept pkts with rx errors */ + int runts_ok; /* AR - accept < 64-byte runts */ + int broadcast; /* AB - accept eth broadcast address */ + int multicast; /* AM - check mcast hash array */ + int promisc; /* PRO - accept all packets */ + int monitor; /* MON - check pkts, but don't rx */ + uint8_t reserved; /* D6,D7 - reserved */ + } RCR; + + /* Receive Status Register - 0ch read */ + struct RSR_t { + int rx_ok; /* PRX - rx complete without error */ + int bad_crc; /* CRC - Bad CRC detected */ + int bad_falign; /* FAE - frame alignment error */ + int fifo_or; /* FO - FIFO overrun */ + int rx_missed; /* MPA - missed packet error */ + int rx_mbit; /* PHY - unicast or mcast/bcast address match */ + int rx_disabled; /* DIS - set when in monitor mode */ + int deferred; /* DFR - collision active */ + } RSR; + + uint16_t local_dma; /* 01,02h read ; current local DMA addr */ + uint8_t page_start; /* 01h write ; page start regr */ + uint8_t page_stop; /* 02h write ; page stop regr */ + uint8_t bound_ptr; /* 03h read/write ; boundary pointer */ + uint8_t tx_page_start; /* 04h write ; transmit page start reg */ + uint8_t num_coll; /* 05h read ; number-of-collisions reg */ + uint16_t tx_bytes; /* 05,06h write ; transmit byte-count reg */ + uint8_t fifo; /* 06h read ; FIFO */ + uint16_t remote_dma; /* 08,09h read ; current remote DMA addr */ + uint16_t remote_start; /* 08,09h write ; remote start address reg */ + uint16_t remote_bytes; /* 0a,0bh write ; remote byte-count reg */ + uint8_t tallycnt_0; /* 0dh read ; tally ctr 0 (frame align errs) */ + uint8_t tallycnt_1; /* 0eh read ; tally ctr 1 (CRC errors) */ + uint8_t tallycnt_2; /* 0fh read ; tally ctr 2 (missed pkt errs) */ + + /* Page 1 */ + + /* Command Register 00h (repeated) */ + + uint8_t physaddr[6]; /* 01-06h read/write ; MAC address */ + uint8_t curr_page; /* 07h read/write ; current page register */ + uint8_t mchash[8]; /* 08-0fh read/write ; multicast hash array */ + + /* Page 2 - diagnostic use only */ + + /* Command Register 00h (repeated) */ + + /* Page Start Register 01h read (repeated) + * Page Stop Register 02h read (repeated) + * Current Local DMA Address 01,02h write (repeated) + * Transmit Page start address 04h read (repeated) + * Receive Configuration Register 0ch read (repeated) + * Transmit Configuration Register 0dh read (repeated) + * Data Configuration Register 0eh read (repeated) + * Interrupt Mask Register 0fh read (repeated) + */ + uint8_t rempkt_ptr; /* 03h read/write ; rmt next-pkt ptr */ + uint8_t localpkt_ptr; /* 05h read/write ; lcl next-pkt ptr */ + uint16_t address_cnt; /* 06,07h read/write ; address cter */ + + /* Page 3 - should never be modified. */ + + /* Novell ASIC state */ + uint8_t mem[DP8390_DWORD_MEMSIZ]; /* on-chip packet memory */ + + int tx_timer_index; + int tx_timer_active; + +} dp8390_t; + + +extern int mcast_index(const void *dst); + + +#endif /*NET_DP8390_H*/ diff --git a/src/devices/network/net_ne2000.c b/src/devices/network/net_ne2000.c index 5e79c1a..10288a1 100644 --- a/src/devices/network/net_ne2000.c +++ b/src/devices/network/net_ne2000.c @@ -9,10 +9,14 @@ * Implementation of the following network controllers: * - Novell NE1000 (ISA 8-bit); * - Novell NE2000 (ISA 16-bit); + * - Novell NE/2 (MCA 16-bit); + * - NetWorth Ethernext/MC (MCA 16-bit); * - Realtek RTL8019AS (ISA 16-bit, PnP); * - Realtek RTL8029AS (PCI). * - * Version: @(#)net_ne2000.c 1.0.10 2018/05/06 + * FIXME: move statbar calls to upper layer + * + * Version: @(#)net_ne2000.c 1.0.12 2018/10/05 * * Based on @(#)ne2k.cc v1.56.2.1 2004/02/02 22:37:22 cbothamy * @@ -47,13 +51,10 @@ #include #include #include -#include #include #include -#define HAVE_STDARG_H +#define dbglog network_dev_log #include "../../emu.h" -#include "../../config.h" -#include "../../machines/machine.h" #include "../../io.h" #include "../../mem.h" #include "../../rom.h" @@ -61,18 +62,29 @@ #include "../../device.h" #include "../../ui/ui.h" #include "../../plat.h" +#include "../system/mca.h" #include "../system/pci.h" #include "../system/pic.h" #include "network.h" #include "net_ne2000.h" +#include "net_dp8390.h" #include "bswap.h" enum { - PNP_PHASE_WAIT_FOR_KEY = 0, - PNP_PHASE_CONFIG, - PNP_PHASE_ISOLATION, - PNP_PHASE_SLEEP + NE2K_NE1000 = 0, /* 8-bit ISA NE1000 */ + NE2K_NE2000, /* 16-bit ISA NE2000 */ + NE2K_NE2_MCA, /* 16-bit MCA NE/2 */ + NE2K_NE2_ENEXT_MCA, /* 16-bit MCA NE/2 */ + NE2K_RTL8019AS, /* 16-bit ISA PnP Realtek 8019AS */ + NE2K_RTL8029AS /* 32-bit PCI Realtek 8029AS */ +}; + +enum { + PNP_PHASE_WAIT_FOR_KEY = 0, + PNP_PHASE_CONFIG, + PNP_PHASE_ISOLATION, + PNP_PHASE_SLEEP }; @@ -90,179 +102,49 @@ enum { #define PCI_REGSIZE 256 /* size of PCI space */ -/* Never completely fill the ne2k ring so that we never - hit the unclear completely full buffer condition. */ -#define NE2K_NEVER_FULL_RING (1) +/* ISA-PNP data. */ +static const uint8_t pnp_init_key[32] = { + 0x6a, 0xb5, 0xda, 0xed, 0xf6, 0xfb, 0x7d, 0xbe, + 0xdf, 0x6f, 0x37, 0x1b, 0x0d, 0x86, 0xc3, 0x61, + 0xb0, 0x58, 0x2c, 0x16, 0x8b, 0x45, 0xa2, 0xd1, + 0xe8, 0x74, 0x3a, 0x9d, 0xce, 0xe7, 0x73, 0x39 +}; -#define NE2K_MEMSIZ (32*1024) -#define NE2K_MEMSTART (16*1024) -#define NE2K_MEMEND (NE2K_MEMSTART+NE2K_MEMSIZ) - -#define NE1K_MEMSIZ (16*1024) -#define NE1K_MEMSTART (8*1024) -#define NE1K_MEMEND (NE1K_MEMSTART+NE1K_MEMSIZ) - -uint8_t pnp_init_key[32] = { 0x6A, 0xB5, 0xDA, 0xED, 0xF6, 0xFB, 0x7D, 0xBE, - 0xDF, 0x6F, 0x37, 0x1B, 0x0D, 0x86, 0xC3, 0x61, - 0xB0, 0x58, 0x2C, 0x16, 0x8B, 0x45, 0xA2, 0xD1, - 0xE8, 0x74, 0x3A, 0x9D, 0xCE, 0xE7, 0x73, 0x39 }; +/* Define the usable resources. */ +typedef struct { + uint16_t bases[10]; + int8_t irqs[10]; +} rsl_t; typedef struct { - /* Page 0 */ - - /* Command Register - 00h read/write */ - struct CR_t { - int stop; /* STP - Software Reset command */ - int start; /* START - start the NIC */ - int tx_packet; /* TXP - initiate packet transmission */ - uint8_t rdma_cmd; /* RD0,RD1,RD2 - Remote DMA command */ - uint8_t pgsel; /* PS0,PS1 - Page select */ - } CR; - - /* Interrupt Status Register - 07h read/write */ - struct ISR_t { - int pkt_rx; /* PRX - packet received with no errors */ - int pkt_tx; /* PTX - packet txed with no errors */ - int rx_err; /* RXE - packet rxed with 1 or more errors */ - int tx_err; /* TXE - packet txed " " " " " */ - int overwrite; /* OVW - rx buffer resources exhausted */ - int cnt_oflow; /* CNT - network tally counter MSB's set */ - int rdma_done; /* RDC - remote DMA complete */ - int reset; /* RST - reset status */ - } ISR; - - /* Interrupt Mask Register - 0fh write */ - struct IMR_t { - int rx_inte; /* PRXE - packet rx interrupt enable */ - int tx_inte; /* PTXE - packet tx interrput enable */ - int rxerr_inte; /* RXEE - rx error interrupt enable */ - int txerr_inte; /* TXEE - tx error interrupt enable */ - int overw_inte; /* OVWE - overwrite warn int enable */ - int cofl_inte; /* CNTE - counter o'flow int enable */ - int rdma_inte; /* RDCE - remote DMA complete int enable */ - int reserved; /* D7 - reserved */ - } IMR; - - /* Data Configuration Register - 0eh write */ - struct DCR_t { - int wdsize; /* WTS - 8/16-bit select */ - int endian; /* BOS - byte-order select */ - int longaddr; /* LAS - long-address select */ - int loop; /* LS - loopback select */ - int auto_rx; /* AR - auto-remove rx pkts with remote DMA */ - uint8_t fifo_size; /* FT0,FT1 - fifo threshold */ - } DCR; - - /* Transmit Configuration Register - 0dh write */ - struct TCR_t { - int crc_disable; /* CRC - inhibit tx CRC */ - uint8_t loop_cntl; /* LB0,LB1 - loopback control */ - int ext_stoptx; /* ATD - allow tx disable by external mcast */ - int coll_prio; /* OFST - backoff algorithm select */ - uint8_t reserved; /* D5,D6,D7 - reserved */ - } TCR; - - /* Transmit Status Register - 04h read */ - struct TSR_t { - int tx_ok; /* PTX - tx complete without error */ - int reserved; /* D1 - reserved */ - int collided; /* COL - tx collided >= 1 times */ - int aborted; /* ABT - aborted due to excessive collisions */ - int no_carrier; /* CRS - carrier-sense lost */ - int fifo_ur; /* FU - FIFO underrun */ - int cd_hbeat; /* CDH - no tx cd-heartbeat from transceiver */ - int ow_coll; /* OWC - out-of-window collision */ - } TSR; - - /* Receive Configuration Register - 0ch write */ - struct RCR_t { - int errors_ok; /* SEP - accept pkts with rx errors */ - int runts_ok; /* AR - accept < 64-byte runts */ - int broadcast; /* AB - accept eth broadcast address */ - int multicast; /* AM - check mcast hash array */ - int promisc; /* PRO - accept all packets */ - int monitor; /* MON - check pkts, but don't rx */ - uint8_t reserved; /* D6,D7 - reserved */ - } RCR; - - /* Receive Status Register - 0ch read */ - struct RSR_t { - int rx_ok; /* PRX - rx complete without error */ - int bad_crc; /* CRC - Bad CRC detected */ - int bad_falign; /* FAE - frame alignment error */ - int fifo_or; /* FO - FIFO overrun */ - int rx_missed; /* MPA - missed packet error */ - int rx_mbit; /* PHY - unicast or mcast/bcast address match */ - int rx_disabled; /* DIS - set when in monitor mode */ - int deferred; /* DFR - collision active */ - } RSR; - - uint16_t local_dma; /* 01,02h read ; current local DMA addr */ - uint8_t page_start; /* 01h write ; page start regr */ - uint8_t page_stop; /* 02h write ; page stop regr */ - uint8_t bound_ptr; /* 03h read/write ; boundary pointer */ - uint8_t tx_page_start; /* 04h write ; transmit page start reg */ - uint8_t num_coll; /* 05h read ; number-of-collisions reg */ - uint16_t tx_bytes; /* 05,06h write ; transmit byte-count reg */ - uint8_t fifo; /* 06h read ; FIFO */ - uint16_t remote_dma; /* 08,09h read ; current remote DMA addr */ - uint16_t remote_start; /* 08,09h write ; remote start address reg */ - uint16_t remote_bytes; /* 0a,0bh write ; remote byte-count reg */ - uint8_t tallycnt_0; /* 0dh read ; tally ctr 0 (frame align errs) */ - uint8_t tallycnt_1; /* 0eh read ; tally ctr 1 (CRC errors) */ - uint8_t tallycnt_2; /* 0fh read ; tally ctr 2 (missed pkt errs) */ - - /* Page 1 */ - - /* Command Register 00h (repeated) */ - - uint8_t physaddr[6]; /* 01-06h read/write ; MAC address */ - uint8_t curr_page; /* 07h read/write ; current page register */ - uint8_t mchash[8]; /* 08-0fh read/write ; multicast hash array */ - - /* Page 2 - diagnostic use only */ - - /* Command Register 00h (repeated) */ - - /* Page Start Register 01h read (repeated) - * Page Stop Register 02h read (repeated) - * Current Local DMA Address 01,02h write (repeated) - * Transmit Page start address 04h read (repeated) - * Receive Configuration Register 0ch read (repeated) - * Transmit Configuration Register 0dh read (repeated) - * Data Configuration Register 0eh read (repeated) - * Interrupt Mask Register 0fh read (repeated) - */ - uint8_t rempkt_ptr; /* 03h read/write ; rmt next-pkt ptr */ - uint8_t localpkt_ptr; /* 05h read/write ; lcl next-pkt ptr */ - uint16_t address_cnt; /* 06,07h read/write ; address cter */ - - /* Page 3 - should never be modified. */ - - /* Novell ASIC state */ - uint8_t macaddr[32]; /* ASIC ROM'd MAC address, even bytes */ - uint8_t mem[NE2K_MEMSIZ]; /* on-chip packet memory */ - - int board; - int is_pci, is_8bit; const char *name; - uint32_t base_address; - int base_irq; + int board; + const rsl_t *res; + + uint16_t base_address; + int8_t base_irq; + int8_t is_pci, + is_mca, + is_8bit, + has_bios; uint32_t bios_addr, bios_size, bios_mask; - uint8_t pnp_regs[256]; - uint8_t pnp_res_data[256]; + rom_t bios_rom; + + /* RTL8019AS/RTL8029AS registers */ + uint8_t config0, config2, config3; + uint8_t _9346cr; + + /* PCI data. */ + int card; /* PCI card slot */ bar_t pci_bar[2]; uint8_t pci_regs[PCI_REGSIZE]; - int tx_timer_index; - int tx_timer_active; - uint8_t maclocal[6]; /* configured MAC (local) address */ - uint8_t eeprom[128]; /* for RTL8029AS */ - rom_t bios_rom; - int card; /* PCI card slot */ - int has_bios; + + /* ISA PNP data. */ + uint8_t pnp_regs[256]; + uint8_t pnp_res_data[256]; uint8_t pnp_phase; uint8_t pnp_magic_count; uint8_t pnp_address; @@ -278,35 +160,22 @@ typedef struct { uint8_t pnp_serial_read_pair; uint8_t pnp_serial_read; - /* RTL8019AS/RTL8029AS registers */ - uint8_t config0, config2, config3; - uint8_t _9346cr; + /* MCA POS registers */ + uint8_t pos_regs[8]; + + /* NatSemi DP8390 state. */ + dp8390_t dp8390; + + uint8_t maclocal[6]; /* configured MAC (local) address */ + uint8_t macaddr[32]; /* for NE1000/NE2000 probing */ + uint8_t eeprom[128]; /* for RTL8029AS */ } nic_t; -static void nic_rx(void *, uint8_t *, int); -static void nic_tx(nic_t *, uint32_t); - - -static void -nelog(int lvl, const char *fmt, ...) -{ -#ifdef ENABLE_NETWORK_DEV_LOG - va_list ap; - - if (network_dev_do_log >= lvl) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); - } -#endif -} - - static void nic_interrupt(nic_t *dev, int set) { - if (PCI && dev->is_pci) { + if (dev->is_pci) { if (set) pci_set_irq(dev->card, PCI_INTA); else @@ -320,84 +189,87 @@ nic_interrupt(nic_t *dev, int set) } -/* reset - restore state to power-up, cancelling all i/o */ +/* Restore state to power-up, cancelling all I/O .*/ static void nic_reset(void *priv) { nic_t *dev = (nic_t *)priv; + dp8390_t *dp = &dev->dp8390; int i; - nelog(1, "%s: reset\n", dev->name); + DBGLOG(1, "%s: reset\n", dev->name); - if (dev->board >= NE2K_NE2000) { - /* Initialize the MAC address area by doubling the physical address */ - dev->macaddr[0] = dev->physaddr[0]; - dev->macaddr[1] = dev->physaddr[0]; - dev->macaddr[2] = dev->physaddr[1]; - dev->macaddr[3] = dev->physaddr[1]; - dev->macaddr[4] = dev->physaddr[2]; - dev->macaddr[5] = dev->physaddr[2]; - dev->macaddr[6] = dev->physaddr[3]; - dev->macaddr[7] = dev->physaddr[3]; - dev->macaddr[8] = dev->physaddr[4]; - dev->macaddr[9] = dev->physaddr[4]; - dev->macaddr[10] = dev->physaddr[5]; - dev->macaddr[11] = dev->physaddr[5]; + switch(dev->board) { + case NE2K_NE1000: + /* Initialize the MAC address. */ + dev->macaddr[0] = dp->physaddr[0]; + dev->macaddr[1] = dp->physaddr[1]; + dev->macaddr[2] = dp->physaddr[2]; + dev->macaddr[3] = dp->physaddr[3]; + dev->macaddr[4] = dp->physaddr[4]; + dev->macaddr[5] = dp->physaddr[5]; - /* ne2k signature */ - for (i=12; i<32; i++) - dev->macaddr[i] = 0x57; - } else { - /* Initialize the MAC address area by doubling the physical address */ - dev->macaddr[0] = dev->physaddr[0]; - dev->macaddr[1] = dev->physaddr[1]; - dev->macaddr[2] = dev->physaddr[2]; - dev->macaddr[3] = dev->physaddr[3]; - dev->macaddr[4] = dev->physaddr[4]; - dev->macaddr[5] = dev->physaddr[5]; + /* NE1K signature. */ + for (i = 6; i < 16; i++) + dev->macaddr[i] = 0x57; + break; - /* ne1k signature */ - for (i=6; i<16; i++) - dev->macaddr[i] = 0x57; + default: + /* Initialize the MAC address. */ + dev->macaddr[0] = dp->physaddr[0]; + dev->macaddr[1] = dp->physaddr[0]; + dev->macaddr[2] = dp->physaddr[1]; + dev->macaddr[3] = dp->physaddr[1]; + dev->macaddr[4] = dp->physaddr[2]; + dev->macaddr[5] = dp->physaddr[2]; + dev->macaddr[6] = dp->physaddr[3]; + dev->macaddr[7] = dp->physaddr[3]; + dev->macaddr[8] = dp->physaddr[4]; + dev->macaddr[9] = dp->physaddr[4]; + dev->macaddr[10] = dp->physaddr[5]; + dev->macaddr[11] = dp->physaddr[5]; + + /* NE2K signature. */ + for (i = 12; i < 32; i++) + dev->macaddr[i] = 0x57; + break; } - /* Zero out registers and memory */ - memset(&dev->CR, 0x00, sizeof(dev->CR) ); - memset(&dev->ISR, 0x00, sizeof(dev->ISR)); - memset(&dev->IMR, 0x00, sizeof(dev->IMR)); - memset(&dev->DCR, 0x00, sizeof(dev->DCR)); - memset(&dev->TCR, 0x00, sizeof(dev->TCR)); - memset(&dev->TSR, 0x00, sizeof(dev->TSR)); - memset(&dev->RSR, 0x00, sizeof(dev->RSR)); - dev->tx_timer_active = 0; - dev->local_dma = 0; - dev->page_start = 0; - dev->page_stop = 0; - dev->bound_ptr = 0; - dev->tx_page_start = 0; - dev->num_coll = 0; - dev->tx_bytes = 0; - dev->fifo = 0; - dev->remote_dma = 0; - dev->remote_start = 0; - dev->remote_bytes = 0; - dev->tallycnt_0 = 0; - dev->tallycnt_1 = 0; - dev->tallycnt_2 = 0; + /* Zero out registers and memory. */ +//FIXME: do this in a dp8390_reset() function? --FvK + memset(&dp->CR, 0x00, sizeof(dp->CR) ); + memset(&dp->ISR, 0x00, sizeof(dp->ISR)); + memset(&dp->IMR, 0x00, sizeof(dp->IMR)); + memset(&dp->DCR, 0x00, sizeof(dp->DCR)); + memset(&dp->TCR, 0x00, sizeof(dp->TCR)); + memset(&dp->TSR, 0x00, sizeof(dp->TSR)); + memset(&dp->RSR, 0x00, sizeof(dp->RSR)); + dp->tx_timer_active = 0; + dp->local_dma = 0; + dp->page_start = 0; + dp->page_stop = 0; + dp->bound_ptr = 0; + dp->tx_page_start = 0; + dp->num_coll = 0; + dp->tx_bytes = 0; + dp->fifo = 0; + dp->remote_dma = 0; + dp->remote_start = 0; + dp->remote_bytes = 0; + dp->tallycnt_0 = 0; + dp->tallycnt_1 = 0; + dp->tallycnt_2 = 0; + dp->curr_page = 0; + dp->rempkt_ptr = 0; + dp->localpkt_ptr = 0; + dp->address_cnt = 0; + memset(&dp->mem, 0x00, sizeof(dp->mem)); - dev->curr_page = 0; - - dev->rempkt_ptr = 0; - dev->localpkt_ptr = 0; - dev->address_cnt = 0; - - memset(&dev->mem, 0x00, sizeof(dev->mem)); - - /* Set power-up conditions */ - dev->CR.stop = 1; - dev->CR.rdma_cmd = 4; - dev->ISR.reset = 1; - dev->DCR.longaddr = 1; + /* Set power-up conditions. */ + dp->CR.stop = 1; + dp->CR.rdma_cmd = 4; + dp->ISR.reset = 1; + dp->DCR.longaddr = 1; nic_interrupt(dev, 0); } @@ -407,9 +279,176 @@ static void nic_soft_reset(void *priv) { nic_t *dev = (nic_t *)priv; + dp8390_t *dp = &dev->dp8390; - memset(&(dev->ISR), 0x00, sizeof(dev->ISR)); - dev->ISR.reset = 1; + memset(&dp->ISR, 0x00, sizeof(dp->ISR)); + dp->ISR.reset = 1; +} + + +/* + * Stuff a new packet into the DP8390. + * + * Called by the platform-specific code when an Ethernet frame + * has been received. The destination address is tested to see + * if it should be accepted, and if the RX ring has enough room, + * it is copied into it and the receive process is updated. + */ +static void +nic_rx(void *priv, uint8_t *buf, int io_len) +{ + static uint8_t bcast_addr[6] = {0xff,0xff,0xff,0xff,0xff,0xff}; + nic_t *dev = (nic_t *)priv; + dp8390_t *dp = &dev->dp8390; + uint8_t pkthdr[4]; + uint8_t *startptr; + int npg, avail; + int idx, nextpage; + int endbytes; + + //FIXME: move to upper layer.. + ui_sb_icon_update(SB_NETWORK, 1); + + if (io_len != 60) { + DBGLOG(1, "%s: rx_frame with length %d\n", dev->name, io_len); + } + + if ((dp->CR.stop != 0) || (dp->page_start == 0)) goto rx_done; + + /* + * Add the pkt header + CRC to the length, and work + * out how many 256-byte pages the frame would occupy. + */ + npg = (io_len + sizeof(pkthdr) + sizeof(uint32_t) + 255)/256; + if (dp->curr_page < dp->bound_ptr) { + avail = dp->bound_ptr - dp->curr_page; + } else { + avail = (dp->page_stop - dp->page_start) - + (dp->curr_page - dp->bound_ptr); + } + + /* + * Avoid getting into a buffer overflow condition by + * not attempting to do partial receives. The emulation + * to handle this condition seems particularly painful. + */ + if ((avail < npg) +#if DP8390_NEVER_FULL_RING + || (avail == npg) +#endif + ) { + DBGLOG(1, "%s: no space\n", dev->name); + + goto rx_done; + } + + if ((io_len < 40/*60*/) && !dp->RCR.runts_ok) { + DEBUG("%s: rejected small packet, length %d\n", dev->name, io_len); + goto rx_done; + } + + /* Some computers don't care... */ + if (io_len < 60) + io_len = 60; + + DBGLOG(1, "%s: RX %x:%x:%x:%x:%x:%x > %x:%x:%x:%x:%x:%x len %d\n", + dev->name, buf[6], buf[7], buf[8], buf[9], buf[10], buf[11], + buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], io_len); + + /* Do address filtering if not in promiscuous mode. */ + if (! dp->RCR.promisc) { + /* If this is a broadcast frame.. */ + if (! memcmp(buf, bcast_addr, 6)) { + /* Broadcast not enabled, we're done. */ + if (! dp->RCR.broadcast) { + DBGLOG(1, "%s: RX BC disabled\n", dev->name); + goto rx_done; + } + } + + /* If this is a multicast frame.. */ + else if (buf[0] & 0x01) { + /* Multicast not enabled, we're done. */ + if (! dp->RCR.multicast) { + DBGLOG(1, "%s: RX MC disabled\n", dev->name); + goto rx_done; + } + + /* Are we listening to this multicast address? */ + idx = mcast_index(buf); + if (! (dp->mchash[idx>>3] & (1<<(idx&0x7)))) { + DBGLOG(1, "%s: RX MC not listed\n", dev->name); + goto rx_done; + } + } else + if (memcmp(buf, dp->physaddr, 6)) return; + + /* Unicast, must be for us.. */ + } else { + DBGLOG(1, "%s: RX promiscuous receive\n", dev->name); + } + + nextpage = dp->curr_page + npg; + if (nextpage >= dp->page_stop) + nextpage -= (dp->page_stop - dp->page_start); + + /* Set up packet header. */ + pkthdr[0] = 0x01; /* RXOK - packet is OK */ + if (buf[0] & 0x01) + pkthdr[0] |= 0x20; /* MULTICAST packet */ + pkthdr[1] = nextpage; /* ptr to next packet */ + pkthdr[2] = (io_len + sizeof(pkthdr))&0xff; /* length-low */ + pkthdr[3] = (io_len + sizeof(pkthdr))>>8; /* length-hi */ + DBGLOG(1, "%s: RX pkthdr [%02x %02x %02x %02x]\n", + dev->name, pkthdr[0], pkthdr[1], pkthdr[2], pkthdr[3]); + + /* Copy into buffer, update curpage, and signal interrupt if config'd */ + if (dev->board >= NE2K_NE2000) + startptr = &dp->mem[(dp->curr_page * 256) - DP8390_DWORD_MEMSTART]; + else + startptr = &dp->mem[(dp->curr_page * 256) - DP8390_WORD_MEMSTART]; + memcpy(startptr, pkthdr, sizeof(pkthdr)); + if ((nextpage > dp->curr_page) || + ((dp->curr_page + npg) == dp->page_stop)) { + memcpy(startptr+sizeof(pkthdr), buf, io_len); + } else { + endbytes = (dp->page_stop - dp->curr_page) * 256; + memcpy(startptr+sizeof(pkthdr), buf, endbytes-sizeof(pkthdr)); + if (dev->board >= NE2K_NE2000) + startptr = &dp->mem[(dp->page_start * 256) - DP8390_DWORD_MEMSTART]; + else + startptr = &dp->mem[(dp->page_start * 256) - DP8390_WORD_MEMSTART]; + memcpy(startptr, buf+endbytes-sizeof(pkthdr), io_len-endbytes+8); + } + dp->curr_page = nextpage; + + dp->RSR.rx_ok = 1; + dp->RSR.rx_mbit = (buf[0] & 0x01) ? 1 : 0; + dp->ISR.pkt_rx = 1; + + if (dp->IMR.rx_inte) + nic_interrupt(dev, 1); + +rx_done: + //FIXME: move to upper layer.. + ui_sb_icon_update(SB_NETWORK, 0); +} + + +static void +nic_tx(nic_t *dev, uint32_t val) +{ + dp8390_t *dp = &dev->dp8390; + + dp->CR.tx_packet = 0; + dp->TSR.tx_ok = 1; + dp->ISR.pkt_tx = 1; + + dp->tx_timer_active = 0; + + /* Generate an interrupt if not masked */ + if (dp->IMR.tx_inte) + nic_interrupt(dev, 1); } @@ -419,20 +458,21 @@ nic_soft_reset(void *priv) * The NE2000 memory is accessed through the data port of the * ASIC (offset 0) after setting up a remote-DMA transfer. * Both byte and word accesses are allowed. - * The first 16 bytes contains the MAC address at even locations, + * The first 16 bytes contain the MAC address at even locations, * and there is 16K of buffer memory starting at 16K. */ static uint32_t chipmem_read(nic_t *dev, uint32_t addr, unsigned int len) { + dp8390_t *dp = &dev->dp8390; uint32_t retval = 0; if ((len == 2) && (addr & 0x1)) { - nelog(3, "%s: unaligned chipmem word read\n", dev->name); + DEBUG("%s: unaligned chipmem word read\n", dev->name); } /* ROM'd MAC address */ - if (dev->board >= NE2K_NE2000) { + if (dev->board != NE2K_NE1000) { if (addr <= 31) { retval = dev->macaddr[addr % 32]; if ((len == 2) || (len == 4)) { @@ -445,14 +485,13 @@ chipmem_read(nic_t *dev, uint32_t addr, unsigned int len) return(retval); } - if ((addr >= NE2K_MEMSTART) && (addr < NE2K_MEMEND)) { - retval = dev->mem[addr - NE2K_MEMSTART]; - if ((len == 2) || (len == 4)) { - retval |= (dev->mem[addr - NE2K_MEMSTART + 1] << 8); - } + if ((addr >= DP8390_DWORD_MEMSTART) && (addr < DP8390_DWORD_MEMEND)) { + retval = dp->mem[addr - DP8390_DWORD_MEMSTART]; + if ((len == 2) || (len == 4)) + retval |= (dp->mem[addr - DP8390_DWORD_MEMSTART + 1] << 8); if (len == 4) { - retval |= (dev->mem[addr - NE2K_MEMSTART + 2] << 16); - retval |= (dev->mem[addr - NE2K_MEMSTART + 3] << 24); + retval |= (dp->mem[addr - DP8390_DWORD_MEMSTART + 2] << 16); + retval |= (dp->mem[addr - DP8390_DWORD_MEMSTART + 3] << 24); } return(retval); } @@ -465,26 +504,25 @@ chipmem_read(nic_t *dev, uint32_t addr, unsigned int len) return(retval); } - if ((addr >= NE1K_MEMSTART) && (addr < NE1K_MEMEND)) { - retval = dev->mem[addr - NE1K_MEMSTART]; - if (len == 2) { - retval |= (dev->mem[addr - NE1K_MEMSTART + 1] << 8); - } + if ((addr >= DP8390_WORD_MEMSTART) && (addr < DP8390_WORD_MEMEND)) { + retval = dp->mem[addr - DP8390_WORD_MEMSTART]; + if (len == 2) + retval |= (dp->mem[addr - DP8390_WORD_MEMSTART + 1] << 8); return(retval); } } - nelog(3, "%s: out-of-bounds chipmem read, %04X\n", dev->name, addr); + DEBUG("%s: out-of-bounds chipmem read, %04X\n", dev->name, addr); - if (dev->is_pci) { + if (dev->is_pci) return(0xff); - } else { - switch(len) { - case 1: - return(0xff); - case 2: - return(0xffff); - } + + switch(len) { + case 1: + return(0xff); + + case 2: + return(0xffff); } return(0xffff); @@ -494,31 +532,33 @@ chipmem_read(nic_t *dev, uint32_t addr, unsigned int len) static void chipmem_write(nic_t *dev, uint32_t addr, uint32_t val, unsigned len) { + dp8390_t *dp = &dev->dp8390; + if ((len == 2) && (addr & 0x1)) { - nelog(3, "%s: unaligned chipmem word write\n", dev->name); + DEBUG("%s: unaligned chipmem word write\n", dev->name); } - if (dev->board >= NE2K_NE2000) { - if ((addr >= NE2K_MEMSTART) && (addr < NE2K_MEMEND)) { - dev->mem[addr-NE2K_MEMSTART] = val & 0xff; - if ((len == 2) || (len == 4)) { - dev->mem[addr-NE2K_MEMSTART+1] = val >> 8; - } + if (dev->board != NE2K_NE1000) { + if ((addr >= DP8390_DWORD_MEMSTART) && (addr < DP8390_DWORD_MEMEND)) { + dp->mem[addr - DP8390_DWORD_MEMSTART] = val & 0xff; + if ((len == 2) || (len == 4)) + dp->mem[addr - DP8390_DWORD_MEMSTART+1] = val >> 8; if (len == 4) { - dev->mem[addr-NE2K_MEMSTART+2] = val >> 16; - dev->mem[addr-NE2K_MEMSTART+3] = val >> 24; + dp->mem[addr - DP8390_DWORD_MEMSTART+2] = val >> 16; + dp->mem[addr - DP8390_DWORD_MEMSTART+3] = val >> 24; } } else { - nelog(3, "%s: out-of-bounds chipmem write, %04X\n", dev->name, addr); + DEBUG("%s: out-of-bounds chipmem write, %04X\n", + dev->name, addr); } } else { - if ((addr >= NE1K_MEMSTART) && (addr < NE1K_MEMEND)) { - dev->mem[addr-NE1K_MEMSTART] = val & 0xff; - if (len == 2) { - dev->mem[addr-NE1K_MEMSTART+1] = val >> 8; - } + if ((addr >= DP8390_WORD_MEMSTART) && (addr < DP8390_WORD_MEMEND)) { + dp->mem[addr - DP8390_WORD_MEMSTART] = val & 0xff; + if (len == 2) + dp->mem[addr - DP8390_WORD_MEMSTART+1] = val >> 8; } else { - nelog(3, "%s: out-of-bounds chipmem write, %04X\n", dev->name, addr); + DEBUG("%s: out-of-bounds chipmem write, %04X\n", + dev->name, addr); } } } @@ -540,50 +580,47 @@ chipmem_write(nic_t *dev, uint32_t addr, uint32_t val, unsigned len) static uint32_t asic_read(nic_t *dev, uint32_t off, unsigned int len) { - uint32_t retval = 0; + dp8390_t *dp = &dev->dp8390; + uint32_t ret = 0; switch(off) { case 0x00: /* Data register */ /* A read remote-DMA command must have been issued, and the source-address and length registers must have been initialised. */ - if (len > dev->remote_bytes) { - nelog(3, "%s: DMA read underrun iolen=%d remote_bytes=%d\n", - dev->name, len, dev->remote_bytes); + if (len > dp->remote_bytes) { + DEBUG("%s: DMA read underrun iolen=%d remote_bytes=%d\n", + dev->name, len, dp->remote_bytes); } - nelog(3, "%s: DMA read: addr=%4x remote_bytes=%d\n", - dev->name, dev->remote_dma,dev->remote_bytes); - retval = chipmem_read(dev, dev->remote_dma, len); + DBGLOG(2, "%s: DMA read: addr=%4x remote_bytes=%d\n", + dev->name, dp->remote_dma, dp->remote_bytes); + ret = chipmem_read(dev, dp->remote_dma, len); /* The 8390 bumps the address and decreases the byte count by the selected word size after every access, not by the amount of data requested by the host (io_len). */ - if (len == 4) { - dev->remote_dma += len; - } else { - dev->remote_dma += (dev->DCR.wdsize + 1); - } + if (len == 4) + dp->remote_dma += len; + else + dp->remote_dma += (dp->DCR.wdsize + 1); - if (dev->remote_dma == dev->page_stop << 8) { - dev->remote_dma = dev->page_start << 8; - } + if (dp->remote_dma == dp->page_stop << 8) + dp->remote_dma = dp->page_start << 8; - /* keep s.remote_bytes from underflowing */ - if (dev->remote_bytes > dev->DCR.wdsize) { - if (len == 4) { - dev->remote_bytes -= len; - } else { - dev->remote_bytes -= (dev->DCR.wdsize + 1); - } - } else { - dev->remote_bytes = 0; - } + /* keep remote_bytes from underflowing */ + if (dp->remote_bytes > dp->DCR.wdsize) { + if (len == 4) + dp->remote_bytes -= len; + else + dp->remote_bytes -= (dp->DCR.wdsize + 1); + } else + dp->remote_bytes = 0; - /* If all bytes have been written, signal remote-DMA complete */ - if (dev->remote_bytes == 0) { - dev->ISR.rdma_done = 1; - if (dev->IMR.rdma_inte) + /* All bytes written, signal remote-DMA complete. */ + if (dp->remote_bytes == 0) { + dp->ISR.rdma_done = 1; + if (dp->IMR.rdma_inte) nic_interrupt(dev, 1); } break; @@ -592,53 +629,75 @@ asic_read(nic_t *dev, uint32_t off, unsigned int len) nic_soft_reset(dev); break; + case 0x10: + case 0x11: + case 0x12: + case 0x13: + case 0x14: + case 0x15: + case 0x16: + case 0x17: + case 0x18: + case 0x19: + case 0x1a: + case 0x1b: + case 0x1c: + case 0x1d: + case 0x1e: + case 0x1f: + ret = 0; + break; + default: - nelog(3, "%s: ASIC read invalid address %04x\n", - dev->name, (unsigned)off); + DEBUG("%s: ASIC read invalid address %04x\n", + dev->name, (unsigned)off); break; } - return(retval); + return(ret); } static void asic_write(nic_t *dev, uint32_t off, uint32_t val, unsigned len) { - nelog(3, "%s: ASIC write addr=0x%02x, value=0x%04x\n", - dev->name, (unsigned)off, (unsigned) val); + dp8390_t *dp = &dev->dp8390; + + DBGLOG(2, "%s: ASIC write addr=0x%02x, value=0x%04x\n", + dev->name, (unsigned)off, (unsigned)val); switch(off) { case 0x00: /* Data register - see asic_read for a description */ - if ((len > 1) && (dev->DCR.wdsize == 0)) { - nelog(3, "%s: DMA write length %d on byte mode operation\n", + if ((len > 1) && (dp->DCR.wdsize == 0)) { + DEBUG("%s: DMA write length %d on byte mode operation\n", dev->name, len); break; } - if (dev->remote_bytes == 0) - nelog(3, "%s: DMA write, byte count 0\n", dev->name); + if (dp->remote_bytes == 0) { + DEBUG("%s: DMA write, byte count 0\n", dev->name); + } - chipmem_write(dev, dev->remote_dma, val, len); + chipmem_write(dev, dp->remote_dma, val, len); if (len == 4) - dev->remote_dma += len; + dp->remote_dma += len; else - dev->remote_dma += (dev->DCR.wdsize + 1); + dp->remote_dma += (dp->DCR.wdsize + 1); - if (dev->remote_dma == dev->page_stop << 8) - dev->remote_dma = dev->page_start << 8; + if (dp->remote_dma == dp->page_stop << 8) + dp->remote_dma = dp->page_start << 8; if (len == 4) - dev->remote_bytes -= len; + dp->remote_bytes -= len; else - dev->remote_bytes -= (dev->DCR.wdsize + 1); + dp->remote_bytes -= (dp->DCR.wdsize + 1); - if (dev->remote_bytes > NE2K_MEMSIZ) - dev->remote_bytes = 0; + if (dp->remote_bytes > DP8390_DWORD_MEMSIZ) + dp->remote_bytes = 0; - /* If all bytes have been written, signal remote-DMA complete */ - if (dev->remote_bytes == 0) { - dev->ISR.rdma_done = 1; - if (dev->IMR.rdma_inte) + /* All bytes read, signal remote-DMA complete. */ + if (dp->remote_bytes == 0) { + dp->ISR.rdma_done = 1; + if (dp->IMR.rdma_inte) nic_interrupt(dev, 1); } break; @@ -647,8 +706,26 @@ asic_write(nic_t *dev, uint32_t off, uint32_t val, unsigned len) /* end of reset pulse */ break; + case 0x10: + case 0x11: + case 0x12: + case 0x13: + case 0x14: + case 0x15: + case 0x16: + case 0x17: + case 0x18: + case 0x19: + case 0x1a: + case 0x1b: + case 0x1c: + case 0x1d: + case 0x1e: + case 0x1f: + break; + default: /* this is invalid, but happens under win95 device detection */ - nelog(3, "%s: ASIC write invalid address %04x, ignoring\n", + DEBUG("%s: ASIC write invalid address %04x, ignoring\n", dev->name, (unsigned)off); break; } @@ -659,133 +736,136 @@ asic_write(nic_t *dev, uint32_t off, uint32_t val, unsigned len) static uint32_t page0_read(nic_t *dev, uint32_t off, unsigned int len) { - uint8_t retval = 0; + dp8390_t *dp = &dev->dp8390; + uint8_t ret = 0; if (len > 1) { /* encountered with win98 hardware probe */ - nelog(3, "%s: bad length! Page0 read from register 0x%02x, len=%u\n", + DEBUG("%s: bad length! Page0 read from register 0x%02x, len=%u\n", dev->name, off, len); - return(retval); + return(ret); } switch(off) { case 0x01: /* CLDA0 */ - retval = (dev->local_dma & 0xff); + ret = (dp->local_dma & 0xff); break; case 0x02: /* CLDA1 */ - retval = (dev->local_dma >> 8); + ret = (dp->local_dma >> 8); break; case 0x03: /* BNRY */ - retval = dev->bound_ptr; + ret = dp->bound_ptr; break; case 0x04: /* TSR */ - retval = ((dev->TSR.ow_coll << 7) | - (dev->TSR.cd_hbeat << 6) | - (dev->TSR.fifo_ur << 5) | - (dev->TSR.no_carrier << 4) | - (dev->TSR.aborted << 3) | - (dev->TSR.collided << 2) | - (dev->TSR.tx_ok)); + ret = ((dp->TSR.ow_coll << 7) | + (dp->TSR.cd_hbeat << 6) | + (dp->TSR.fifo_ur << 5) | + (dp->TSR.no_carrier << 4) | + (dp->TSR.aborted << 3) | + (dp->TSR.collided << 2) | + (dp->TSR.tx_ok)); break; case 0x05: /* NCR */ - retval = dev->num_coll; + ret = dp->num_coll; break; case 0x06: /* FIFO */ /* reading FIFO is only valid in loopback mode */ - nelog(3, "%s: reading FIFO not supported yet\n", dev->name); - retval = dev->fifo; + DEBUG("%s: reading FIFO not supported yet\n", dev->name); + ret = dp->fifo; break; case 0x07: /* ISR */ - retval = ((dev->ISR.reset << 7) | - (dev->ISR.rdma_done << 6) | - (dev->ISR.cnt_oflow << 5) | - (dev->ISR.overwrite << 4) | - (dev->ISR.tx_err << 3) | - (dev->ISR.rx_err << 2) | - (dev->ISR.pkt_tx << 1) | - (dev->ISR.pkt_rx)); + ret = ((dp->ISR.reset << 7) | + (dp->ISR.rdma_done << 6) | + (dp->ISR.cnt_oflow << 5) | + (dp->ISR.overwrite << 4) | + (dp->ISR.tx_err << 3) | + (dp->ISR.rx_err << 2) | + (dp->ISR.pkt_tx << 1) | + (dp->ISR.pkt_rx)); break; case 0x08: /* CRDA0 */ - retval = (dev->remote_dma & 0xff); + ret = (dp->remote_dma & 0xff); break; case 0x09: /* CRDA1 */ - retval = (dev->remote_dma >> 8); + ret = (dp->remote_dma >> 8); break; case 0x0a: /* reserved / RTL8029ID0 */ if (dev->board == NE2K_RTL8019AS) { - retval = 0x50; + ret = 0x50; } else if (dev->board == NE2K_RTL8029AS) { - retval = 0x50; + ret = 0x50; } else { - nelog(3, "%s: reserved Page0 read - 0x0a\n", dev->name); - retval = 0xff; + DEBUG("%s: reserved Page0 read - 0x0a\n", dev->name); + ret = 0xff; } break; case 0x0b: /* reserved / RTL8029ID1 */ if (dev->board == NE2K_RTL8019AS) { - retval = 0x70; + ret = 0x70; } else if (dev->board == NE2K_RTL8029AS) { - retval = 0x43; + ret = 0x43; } else { - nelog(3, "%s: reserved Page0 read - 0x0b\n", dev->name); - retval = 0xff; + DEBUG("%s: reserved Page0 read - 0x0b\n", dev->name); + ret = 0xff; } break; case 0x0c: /* RSR */ - retval = ((dev->RSR.deferred << 7) | - (dev->RSR.rx_disabled << 6) | - (dev->RSR.rx_mbit << 5) | - (dev->RSR.rx_missed << 4) | - (dev->RSR.fifo_or << 3) | - (dev->RSR.bad_falign << 2) | - (dev->RSR.bad_crc << 1) | - (dev->RSR.rx_ok)); + ret = ((dp->RSR.deferred << 7) | + (dp->RSR.rx_disabled << 6) | + (dp->RSR.rx_mbit << 5) | + (dp->RSR.rx_missed << 4) | + (dp->RSR.fifo_or << 3) | + (dp->RSR.bad_falign << 2) | + (dp->RSR.bad_crc << 1) | + (dp->RSR.rx_ok)); break; case 0x0d: /* CNTR0 */ - retval = dev->tallycnt_0; + ret = dp->tallycnt_0; break; case 0x0e: /* CNTR1 */ - retval = dev->tallycnt_1; + ret = dp->tallycnt_1; break; case 0x0f: /* CNTR2 */ - retval = dev->tallycnt_2; + ret = dp->tallycnt_2; break; default: - nelog(3, "%s: Page0 register 0x%02x out of range\n", - dev->name, off); + DEBUG("%s: Page0 register 0x%02x out of range\n", + dev->name, off); break; } - nelog(3, "%s: Page0 read from register 0x%02x, value=0x%02x\n", - dev->name, off, retval); - - return(retval); + DBGLOG(2, "%s: Page0 read from register 0x%02x, value=0x%02x\n", + dev->name, off, ret); + return(ret); } static void page0_write(nic_t *dev, uint32_t off, uint32_t val, unsigned len) { + dp8390_t *dp = &dev->dp8390; uint8_t val2; - /* It appears to be a common practice to use outw on page0 regs... */ - - /* break up outw into two outb's */ + /* + * It appears to be a common practice to use outw on page0 regs. + * + * Break up outw into two outb's. + */ if (len == 2) { page0_write(dev, off, (val & 0xff), 1); if (off < 0x0f) @@ -793,181 +873,189 @@ page0_write(nic_t *dev, uint32_t off, uint32_t val, unsigned len) return; } - nelog(3, "%s: Page0 write to register 0x%02x, value=0x%02x\n", + DBGLOG(2, "%s: Page0 write to register 0x%02x, value=0x%02x\n", dev->name, off, val); - switch(off) { case 0x01: /* PSTART */ - dev->page_start = val; + dp->page_start = val; break; case 0x02: /* PSTOP */ - dev->page_stop = val; + dp->page_stop = val; break; case 0x03: /* BNRY */ - dev->bound_ptr = val; + dp->bound_ptr = val; break; case 0x04: /* TPSR */ - dev->tx_page_start = val; + dp->tx_page_start = val; break; case 0x05: /* TBCR0 */ /* Clear out low byte and re-insert */ - dev->tx_bytes &= 0xff00; - dev->tx_bytes |= (val & 0xff); + dp->tx_bytes &= 0xff00; + dp->tx_bytes |= (val & 0xff); break; case 0x06: /* TBCR1 */ /* Clear out high byte and re-insert */ - dev->tx_bytes &= 0x00ff; - dev->tx_bytes |= ((val & 0xff) << 8); + dp->tx_bytes &= 0x00ff; + dp->tx_bytes |= ((val & 0xff) << 8); break; case 0x07: /* ISR */ val &= 0x7f; /* clear RST bit - status-only bit */ /* All other values are cleared iff the ISR bit is 1 */ - dev->ISR.pkt_rx &= !((int)((val & 0x01) == 0x01)); - dev->ISR.pkt_tx &= !((int)((val & 0x02) == 0x02)); - dev->ISR.rx_err &= !((int)((val & 0x04) == 0x04)); - dev->ISR.tx_err &= !((int)((val & 0x08) == 0x08)); - dev->ISR.overwrite &= !((int)((val & 0x10) == 0x10)); - dev->ISR.cnt_oflow &= !((int)((val & 0x20) == 0x20)); - dev->ISR.rdma_done &= !((int)((val & 0x40) == 0x40)); - val = ((dev->ISR.rdma_done << 6) | - (dev->ISR.cnt_oflow << 5) | - (dev->ISR.overwrite << 4) | - (dev->ISR.tx_err << 3) | - (dev->ISR.rx_err << 2) | - (dev->ISR.pkt_tx << 1) | - (dev->ISR.pkt_rx)); - val &= ((dev->IMR.rdma_inte << 6) | - (dev->IMR.cofl_inte << 5) | - (dev->IMR.overw_inte << 4) | - (dev->IMR.txerr_inte << 3) | - (dev->IMR.rxerr_inte << 2) | - (dev->IMR.tx_inte << 1) | - (dev->IMR.rx_inte)); + dp->ISR.pkt_rx &= !((int)((val & 0x01) == 0x01)); + dp->ISR.pkt_tx &= !((int)((val & 0x02) == 0x02)); + dp->ISR.rx_err &= !((int)((val & 0x04) == 0x04)); + dp->ISR.tx_err &= !((int)((val & 0x08) == 0x08)); + dp->ISR.overwrite &= !((int)((val & 0x10) == 0x10)); + dp->ISR.cnt_oflow &= !((int)((val & 0x20) == 0x20)); + dp->ISR.rdma_done &= !((int)((val & 0x40) == 0x40)); + val = ((dp->ISR.rdma_done << 6) | + (dp->ISR.cnt_oflow << 5) | + (dp->ISR.overwrite << 4) | + (dp->ISR.tx_err << 3) | + (dp->ISR.rx_err << 2) | + (dp->ISR.pkt_tx << 1) | + (dp->ISR.pkt_rx)); + val &= ((dp->IMR.rdma_inte << 6) | + (dp->IMR.cofl_inte << 5) | + (dp->IMR.overw_inte << 4) | + (dp->IMR.txerr_inte << 3) | + (dp->IMR.rxerr_inte << 2) | + (dp->IMR.tx_inte << 1) | + (dp->IMR.rx_inte)); if (val == 0x00) nic_interrupt(dev, 0); break; case 0x08: /* RSAR0 */ /* Clear out low byte and re-insert */ - dev->remote_start &= 0xff00; - dev->remote_start |= (val & 0xff); - dev->remote_dma = dev->remote_start; + dp->remote_start &= 0xff00; + dp->remote_start |= (val & 0xff); + dp->remote_dma = dp->remote_start; break; case 0x09: /* RSAR1 */ /* Clear out high byte and re-insert */ - dev->remote_start &= 0x00ff; - dev->remote_start |= ((val & 0xff) << 8); - dev->remote_dma = dev->remote_start; + dp->remote_start &= 0x00ff; + dp->remote_start |= ((val & 0xff) << 8); + dp->remote_dma = dp->remote_start; break; case 0x0a: /* RBCR0 */ /* Clear out low byte and re-insert */ - dev->remote_bytes &= 0xff00; - dev->remote_bytes |= (val & 0xff); + dp->remote_bytes &= 0xff00; + dp->remote_bytes |= (val & 0xff); break; case 0x0b: /* RBCR1 */ /* Clear out high byte and re-insert */ - dev->remote_bytes &= 0x00ff; - dev->remote_bytes |= ((val & 0xff) << 8); + dp->remote_bytes &= 0x00ff; + dp->remote_bytes |= ((val & 0xff) << 8); break; case 0x0c: /* RCR */ /* Check if the reserved bits are set */ if (val & 0xc0) { - nelog(3, "%s: RCR write, reserved bits set\n", - dev->name); + DEBUG("%s: RCR write, reserved bits set\n", dev->name); } /* Set all other bit-fields */ - dev->RCR.errors_ok = ((val & 0x01) == 0x01); - dev->RCR.runts_ok = ((val & 0x02) == 0x02); - dev->RCR.broadcast = ((val & 0x04) == 0x04); - dev->RCR.multicast = ((val & 0x08) == 0x08); - dev->RCR.promisc = ((val & 0x10) == 0x10); - dev->RCR.monitor = ((val & 0x20) == 0x20); + dp->RCR.errors_ok = ((val & 0x01) == 0x01); + dp->RCR.runts_ok = ((val & 0x02) == 0x02); + dp->RCR.broadcast = ((val & 0x04) == 0x04); + dp->RCR.multicast = ((val & 0x08) == 0x08); + dp->RCR.promisc = ((val & 0x10) == 0x10); + dp->RCR.monitor = ((val & 0x20) == 0x20); /* Monitor bit is a little suspicious... */ - if (val & 0x20) nelog(3, "%s: RCR write, monitor bit set!\n", - dev->name); + if (val & 0x20) { + DEBUG("%s: RCR write, monitor bit set!\n", dev->name); + } break; case 0x0d: /* TCR */ /* Check reserved bits */ - if (val & 0xe0) nelog(3, "%s: TCR write, reserved bits set\n", - dev->name); + if (val & 0xe0) { + DEBUG("%s: TCR write, reserved bits set\n", dev->name); + } /* Test loop mode (not supported) */ if (val & 0x06) { - dev->TCR.loop_cntl = (val & 0x6) >> 1; - nelog(3, "%s: TCR write, loop mode %d not supported\n", - dev->name, dev->TCR.loop_cntl); + dp->TCR.loop_cntl = (val & 0x6) >> 1; + DEBUG("%s: TCR write, loop mode %d not supported\n", + dev->name, dp->TCR.loop_cntl); } else { - dev->TCR.loop_cntl = 0; + dp->TCR.loop_cntl = 0; } /* Inhibit-CRC not supported. */ - if (val & 0x01) nelog(3, - "%s: TCR write, inhibit-CRC not supported\n",dev->name); + if (val & 0x01) { + DEBUG("%s: TCR write, inhibit-CRC not supported\n", + dev->name); + } /* Auto-transmit disable very suspicious */ - if (val & 0x08) nelog(3, - "%s: TCR write, auto transmit disable not supported\n", + if (val & 0x08) { + DEBUG("%s: TCR write, auto transmit disable not supported\n", dev->name); + } /* Allow collision-offset to be set, although not used */ - dev->TCR.coll_prio = ((val & 0x08) == 0x08); + dp->TCR.coll_prio = ((val & 0x08) == 0x08); break; case 0x0e: /* DCR */ /* the loopback mode is not suppported yet */ - if (! (val & 0x08)) nelog(3, - "%s: DCR write, loopback mode selected\n", dev->name); + if (! (val & 0x08)) { + DEBUG("%s: DCR write, loopback mode selected\n", + dev->name); + } /* It is questionable to set longaddr and auto_rx, since * they are not supported on the NE2000. Print a warning * and continue. */ - if (val & 0x04) - nelog(3, "%s: DCR write - LAS set ???\n", dev->name); - if (val & 0x10) - nelog(3, "%s: DCR write - AR set ???\n", dev->name); + if (val & 0x04) { + DEBUG("%s: DCR write - LAS set ???\n", dev->name); + } + if (val & 0x10) { + DEBUG("%s: DCR write - AR set ???\n", dev->name); + } /* Set other values. */ - dev->DCR.wdsize = ((val & 0x01) == 0x01); - dev->DCR.endian = ((val & 0x02) == 0x02); - dev->DCR.longaddr = ((val & 0x04) == 0x04); /* illegal ? */ - dev->DCR.loop = ((val & 0x08) == 0x08); - dev->DCR.auto_rx = ((val & 0x10) == 0x10); /* also illegal ? */ - dev->DCR.fifo_size = (val & 0x50) >> 5; + dp->DCR.wdsize = ((val & 0x01) == 0x01); + dp->DCR.endian = ((val & 0x02) == 0x02); + dp->DCR.longaddr = ((val & 0x04) == 0x04); /* illegal ? */ + dp->DCR.loop = ((val & 0x08) == 0x08); + dp->DCR.auto_rx = ((val & 0x10) == 0x10); /* also illegal ? */ + dp->DCR.fifo_size = (val & 0x50) >> 5; break; case 0x0f: /* IMR */ /* Check for reserved bit */ - if (val & 0x80) - nelog(3, "%s: IMR write, reserved bit set\n",dev->name); + if (val & 0x80) { + DEBUG("%s: IMR write, reserved bit set\n", dev->name); + } /* Set other values */ - dev->IMR.rx_inte = ((val & 0x01) == 0x01); - dev->IMR.tx_inte = ((val & 0x02) == 0x02); - dev->IMR.rxerr_inte = ((val & 0x04) == 0x04); - dev->IMR.txerr_inte = ((val & 0x08) == 0x08); - dev->IMR.overw_inte = ((val & 0x10) == 0x10); - dev->IMR.cofl_inte = ((val & 0x20) == 0x20); - dev->IMR.rdma_inte = ((val & 0x40) == 0x40); - val2 = ((dev->ISR.rdma_done << 6) | - (dev->ISR.cnt_oflow << 5) | - (dev->ISR.overwrite << 4) | - (dev->ISR.tx_err << 3) | - (dev->ISR.rx_err << 2) | - (dev->ISR.pkt_tx << 1) | - (dev->ISR.pkt_rx)); + dp->IMR.rx_inte = ((val & 0x01) == 0x01); + dp->IMR.tx_inte = ((val & 0x02) == 0x02); + dp->IMR.rxerr_inte = ((val & 0x04) == 0x04); + dp->IMR.txerr_inte = ((val & 0x08) == 0x08); + dp->IMR.overw_inte = ((val & 0x10) == 0x10); + dp->IMR.cofl_inte = ((val & 0x20) == 0x20); + dp->IMR.rdma_inte = ((val & 0x40) == 0x40); + val2 = ((dp->ISR.rdma_done << 6) | + (dp->ISR.cnt_oflow << 5) | + (dp->ISR.overwrite << 4) | + (dp->ISR.tx_err << 3) | + (dp->ISR.rx_err << 2) | + (dp->ISR.pkt_tx << 1) | + (dp->ISR.pkt_rx)); if (((val & val2) & 0x7f) == 0) nic_interrupt(dev, 0); else @@ -975,8 +1063,7 @@ page0_write(nic_t *dev, uint32_t off, uint32_t val, unsigned len) break; default: - nelog(3, "%s: Page0 write, bad register 0x%02x\n", - dev->name, off); + DEBUG("%s: Page0 write, bad register 0x%02x\n", dev->name, off); break; } } @@ -986,9 +1073,10 @@ page0_write(nic_t *dev, uint32_t off, uint32_t val, unsigned len) static uint32_t page1_read(nic_t *dev, uint32_t off, unsigned int len) { - nelog(3, "%s: Page1 read from register 0x%02x, len=%u\n", - dev->name, off, len); + dp8390_t *dp = &dev->dp8390; + DBGLOG(2, "%s: Page1 read from register 0x%02x, len=%u\n", + dev->name, off, len); switch(off) { case 0x01: /* PAR0-5 */ case 0x02: @@ -996,12 +1084,12 @@ page1_read(nic_t *dev, uint32_t off, unsigned int len) case 0x04: case 0x05: case 0x06: - return(dev->physaddr[off - 1]); + return(dp->physaddr[off - 1]); case 0x07: /* CURR */ - nelog(3, "%s: returning current page: 0x%02x\n", - dev->name, (dev->curr_page)); - return(dev->curr_page); + DBGLOG(1, "%s: returning current page: 0x%02x\n", + dev->name, (dp->curr_page)); + return(dp->curr_page); case 0x08: /* MAR0-7 */ case 0x09: @@ -1011,10 +1099,10 @@ page1_read(nic_t *dev, uint32_t off, unsigned int len) case 0x0d: case 0x0e: case 0x0f: - return(dev->mchash[off - 8]); + return(dp->mchash[off - 8]); default: - nelog(3, "%s: Page1 read register 0x%02x out of range\n", + DEBUG("%s: Page1 read register 0x%02x out of range\n", dev->name, off); return(0); } @@ -1024,9 +1112,10 @@ page1_read(nic_t *dev, uint32_t off, unsigned int len) static void page1_write(nic_t *dev, uint32_t off, uint32_t val, unsigned len) { - nelog(3, "%s: Page1 write to register 0x%02x, len=%u, value=0x%04x\n", - dev->name, off, len, val); + dp8390_t *dp = &dev->dp8390; + DBGLOG(2, "%s: Page1 write to register 0x%02x, len=%u, value=0x%04x\n", + dev->name, off, len, val); switch(off) { case 0x01: /* PAR0-5 */ case 0x02: @@ -1034,17 +1123,17 @@ page1_write(nic_t *dev, uint32_t off, uint32_t val, unsigned len) case 0x04: case 0x05: case 0x06: - dev->physaddr[off - 1] = val; - if (off == 6) nelog(3, - "%s: physical address set to %02x:%02x:%02x:%02x:%02x:%02x\n", - dev->name, - dev->physaddr[0], dev->physaddr[1], - dev->physaddr[2], dev->physaddr[3], - dev->physaddr[4], dev->physaddr[5]); + dp->physaddr[off - 1] = val; + if (off == 6) { + DBGLOG(1, "%s: physical address set to %02x:%02x:%02x:%02x:%02x:%02x\n", + dev->name, dp->physaddr[0], dp->physaddr[1], + dp->physaddr[2], dp->physaddr[3], + dp->physaddr[4], dp->physaddr[5]); + } break; case 0x07: /* CURR */ - dev->curr_page = val; + dp->curr_page = val; break; case 0x08: /* MAR0-7 */ @@ -1055,11 +1144,11 @@ page1_write(nic_t *dev, uint32_t off, uint32_t val, unsigned len) case 0x0d: case 0x0e: case 0x0f: - dev->mchash[off - 8] = val; + dp->mchash[off - 8] = val; break; default: - nelog(3, "%s: Page1 write register 0x%02x out of range\n", + DEBUG("%s: Page1 write register 0x%02x out of range\n", dev->name, off); break; } @@ -1070,123 +1159,139 @@ page1_write(nic_t *dev, uint32_t off, uint32_t val, unsigned len) static uint32_t page2_read(nic_t *dev, uint32_t off, unsigned int len) { - nelog(3, "%s: Page2 read from register 0x%02x, len=%u\n", - dev->name, off, len); + dp8390_t *dp = &dev->dp8390; + uint32_t ret = 0; + DBGLOG(2, "%s: Page2 read from register 0x%02x, len=%u\n", + dev->name, off, len); switch(off) { case 0x01: /* PSTART */ - return(dev->page_start); + ret = dp->page_start; + break; case 0x02: /* PSTOP */ - return(dev->page_stop); + ret = dp->page_stop; + break; case 0x03: /* Remote Next-packet pointer */ - return(dev->rempkt_ptr); + ret = dp->rempkt_ptr; + break; case 0x04: /* TPSR */ - return(dev->tx_page_start); + ret = dp->tx_page_start; + break; case 0x05: /* Local Next-packet pointer */ - return(dev->localpkt_ptr); + ret = dp->localpkt_ptr; + break; case 0x06: /* Address counter (upper) */ - return(dev->address_cnt >> 8); + ret = dp->address_cnt >> 8; + break; case 0x07: /* Address counter (lower) */ - return(dev->address_cnt & 0xff); + ret = dp->address_cnt & 0xff; + break; case 0x08: /* Reserved */ case 0x09: case 0x0a: case 0x0b: - nelog(3, "%s: reserved Page2 read - register 0x%02x\n", - dev->name, off); - return(0xff); + DEBUG("%s: reserved Page2 read - register 0x%02x\n", + dev->name, off); + ret = 0xff; + break; case 0x0c: /* RCR */ - return ((dev->RCR.monitor << 5) | - (dev->RCR.promisc << 4) | - (dev->RCR.multicast << 3) | - (dev->RCR.broadcast << 2) | - (dev->RCR.runts_ok << 1) | - (dev->RCR.errors_ok)); + ret = ((dp->RCR.monitor << 5) | + (dp->RCR.promisc << 4) | + (dp->RCR.multicast << 3) | + (dp->RCR.broadcast << 2) | + (dp->RCR.runts_ok << 1) | + (dp->RCR.errors_ok)); + break; case 0x0d: /* TCR */ - return ((dev->TCR.coll_prio << 4) | - (dev->TCR.ext_stoptx << 3) | - ((dev->TCR.loop_cntl & 0x3) << 1) | - (dev->TCR.crc_disable)); + ret = ((dp->TCR.coll_prio << 4) | + (dp->TCR.ext_stoptx << 3) | + ((dp->TCR.loop_cntl & 0x3) << 1) | + (dp->TCR.crc_disable)); + break; case 0x0e: /* DCR */ - return (((dev->DCR.fifo_size & 0x3) << 5) | - (dev->DCR.auto_rx << 4) | - (dev->DCR.loop << 3) | - (dev->DCR.longaddr << 2) | - (dev->DCR.endian << 1) | - (dev->DCR.wdsize)); + ret = (((dp->DCR.fifo_size & 0x3) << 5) | + (dp->DCR.auto_rx << 4) | + (dp->DCR.loop << 3) | + (dp->DCR.longaddr << 2) | + (dp->DCR.endian << 1) | + (dp->DCR.wdsize)); + break; case 0x0f: /* IMR */ - return ((dev->IMR.rdma_inte << 6) | - (dev->IMR.cofl_inte << 5) | - (dev->IMR.overw_inte << 4) | - (dev->IMR.txerr_inte << 3) | - (dev->IMR.rxerr_inte << 2) | - (dev->IMR.tx_inte << 1) | - (dev->IMR.rx_inte)); + ret = ((dp->IMR.rdma_inte << 6) | + (dp->IMR.cofl_inte << 5) | + (dp->IMR.overw_inte << 4) | + (dp->IMR.txerr_inte << 3) | + (dp->IMR.rxerr_inte << 2) | + (dp->IMR.tx_inte << 1) | + (dp->IMR.rx_inte)); + break; default: - nelog(3, "%s: Page2 register 0x%02x out of range\n", + DEBUG("%s: Page2 register 0x%02x out of range\n", dev->name, off); break; } - return(0); + return(ret); } -static void -page2_write(nic_t *dev, uint32_t off, uint32_t val, unsigned len) -{ /* Maybe all writes here should be BX_PANIC()'d, since they affect internal operation, but let them through for now and print a warning. */ - nelog(3, "%s: Page2 write to register 0x%02x, len=%u, value=0x%04x\n", +static void +page2_write(nic_t *dev, uint32_t off, uint32_t val, unsigned len) +{ + dp8390_t *dp = &dev->dp8390; + + DBGLOG(2, "%s: Page2 write to register 0x%02x, len=%u, value=0x%04x\n", dev->name, off, len, val); switch(off) { case 0x01: /* CLDA0 */ /* Clear out low byte and re-insert */ - dev->local_dma &= 0xff00; - dev->local_dma |= (val & 0xff); + dp->local_dma &= 0xff00; + dp->local_dma |= (val & 0xff); break; case 0x02: /* CLDA1 */ /* Clear out high byte and re-insert */ - dev->local_dma &= 0x00ff; - dev->local_dma |= ((val & 0xff) << 8); + dp->local_dma &= 0x00ff; + dp->local_dma |= ((val & 0xff) << 8); break; case 0x03: /* Remote Next-pkt pointer */ - dev->rempkt_ptr = val; + dp->rempkt_ptr = val; break; case 0x04: - nelog(3, "page 2 write to reserved register 0x04\n"); + DEBUG("page 2 write to reserved register 0x04\n"); break; case 0x05: /* Local Next-packet pointer */ - dev->localpkt_ptr = val; + dp->localpkt_ptr = val; break; case 0x06: /* Address counter (upper) */ /* Clear out high byte and re-insert */ - dev->address_cnt &= 0x00ff; - dev->address_cnt |= ((val & 0xff) << 8); + dp->address_cnt &= 0x00ff; + dp->address_cnt |= ((val & 0xff) << 8); break; case 0x07: /* Address counter (lower) */ /* Clear out low byte and re-insert */ - dev->address_cnt &= 0xff00; - dev->address_cnt |= (val & 0xff); + dp->address_cnt &= 0xff00; + dp->address_cnt |= (val & 0xff); break; case 0x08: @@ -1197,50 +1302,61 @@ page2_write(nic_t *dev, uint32_t off, uint32_t val, unsigned len) case 0x0d: case 0x0e: case 0x0f: - nelog(3, "%s: Page2 write to reserved register 0x%02x\n", + DEBUG("%s: Page2 write to reserved register 0x%02x\n", dev->name, off); break; default: - nelog(3, "%s: Page2 write, illegal register 0x%02x\n", - dev->name, off); + DEBUG("%s: Page2 write, illegal register 0x%02x\n", + dev->name, off); break; } } -/* Writes to this page are illegal. */ static uint32_t page3_read(nic_t *dev, uint32_t off, unsigned int len) { + uint32_t ret = 0; + if (dev->board >= NE2K_RTL8019AS) switch(off) { - case 0x1: /* 9346CR */ - return(dev->_9346cr); + case 0x01: /* 9346CR */ + ret = dev->_9346cr; + break; - case 0x3: /* CONFIG0 */ - return(0x00); /* Cable not BNC */ + case 0x03: /* CONFIG0 */ + ret = 0x00; /* Cable not BNC */ + break; - case 0x5: /* CONFIG2 */ - return(dev->config2 & 0xe0); + case 0x05: /* CONFIG2 */ + ret = dev->config2 & 0xe0; + break; - case 0x6: /* CONFIG3 */ - return(dev->config3 & 0x46); + case 0x06: /* CONFIG3 */ + ret = dev->config3 & 0x46; + break; - case 0x8: /* CSNSAV */ - return((dev->board == NE2K_RTL8019AS) ? dev->pnp_csnsav : 0x00); + case 0x08: /* CSNSAV */ + ret = (dev->board == NE2K_RTL8019AS) ? dev->pnp_csnsav : 0x00; + break; - case 0xe: /* 8029ASID0 */ - return(0x29); + case 0x0e: /* 8029ASID0 */ + ret = 0x29; + break; - case 0xf: /* 8029ASID1 */ - return(0x08); + case 0x0f: /* 8029ASID1 */ + ret = 0x08; + break; default: + DEBUG("%s: Page3 read register 0x%02x attempted\n", + dev->name, off); break; + } else { + DEBUG("%s: Page3 read register 0x%02x attempted\n", dev->name, off); } - nelog(3, "%s: Page3 read register 0x%02x attempted\n", dev->name, off); - return(0x00); + return(ret); } @@ -1248,32 +1364,32 @@ static void page3_write(nic_t *dev, uint32_t off, uint32_t val, unsigned len) { if (dev->board >= NE2K_RTL8019AS) { - nelog(3, "%s: Page2 write to register 0x%02x, len=%u, value=0x%04x\n", - dev->name, off, len, val); - + DBGLOG(2, "%s: Page3 write to register 0x%02x, len=%u, value=0x%04x\n", + dev->name, off, len, val); switch(off) { case 0x01: /* 9346CR */ - dev->_9346cr = (val & 0xfe); + dev->_9346cr = val & 0xfe; break; case 0x05: /* CONFIG2 */ - dev->config2 = (val & 0xe0); + dev->config2 = val & 0xe0; break; case 0x06: /* CONFIG3 */ - dev->config3 = (val & 0x46); + dev->config3 = val & 0x46; break; case 0x09: /* HLTCLK */ break; default: - nelog(3, "%s: Page3 write to reserved register 0x%02x\n", - dev->name, off); + DEBUG("%s: Page3 write to reserved register 0x%02x\n", + dev->name, off); break; } - } else - nelog(3, "%s: Page3 write register 0x%02x attempted\n", dev->name, off); + } else { + DEBUG("%s: Page3 write register 0x%02x attempted\n", dev->name, off); + } } @@ -1281,97 +1397,102 @@ page3_write(nic_t *dev, uint32_t off, uint32_t val, unsigned len) static uint32_t read_cr(nic_t *dev) { - uint32_t retval; + dp8390_t *dp = &dev->dp8390; + uint32_t ret; - retval = (((dev->CR.pgsel & 0x03) << 6) | - ((dev->CR.rdma_cmd & 0x07) << 3) | - (dev->CR.tx_packet << 2) | - (dev->CR.start << 1) | - (dev->CR.stop)); - nelog(3, "%s: read CR returns 0x%02x\n", dev->name, retval); + ret = (((dp->CR.pgsel & 0x03) << 6) | + ((dp->CR.rdma_cmd & 0x07) << 3) | + (dp->CR.tx_packet << 2) | + (dp->CR.start << 1) | + (dp->CR.stop)); - return(retval); + DBGLOG(1, "%s: read CR returns 0x%02x\n", dev->name, ret); + + return(ret); } static void write_cr(nic_t *dev, uint32_t val) { - nelog(3, "%s: wrote 0x%02x to CR\n", dev->name, val); + dp8390_t *dp = &dev->dp8390; + + DBGLOG(1, "%s: wrote 0x%02x to CR\n", dev->name, val); /* Validate remote-DMA */ if ((val & 0x38) == 0x00) { - nelog(3, "%s: CR write - invalid rDMA value 0\n", dev->name); + DBGLOG(1, "%s: CR write - invalid rDMA value 0\n", dev->name); val |= 0x20; /* dma_cmd == 4 is a safe default */ } /* Check for s/w reset */ if (val & 0x01) { - dev->ISR.reset = 1; - dev->CR.stop = 1; - } else { - dev->CR.stop = 0; - } + dp->ISR.reset = 1; + dp->CR.stop = 1; + } else + dp->CR.stop = 0; - dev->CR.rdma_cmd = (val & 0x38) >> 3; + dp->CR.rdma_cmd = (val & 0x38) >> 3; /* If start command issued, the RST bit in the ISR */ /* must be cleared */ - if ((val & 0x02) && !dev->CR.start) - dev->ISR.reset = 0; + if ((val & 0x02) && !dp->CR.start) + dp->ISR.reset = 0; - dev->CR.start = ((val & 0x02) == 0x02); - dev->CR.pgsel = (val & 0xc0) >> 6; + dp->CR.start = ((val & 0x02) == 0x02); + dp->CR.pgsel = (val & 0xc0) >> 6; /* Check for send-packet command */ - if (dev->CR.rdma_cmd == 3) { + if (dp->CR.rdma_cmd == 3) { /* Set up DMA read from receive ring */ - dev->remote_start = dev->remote_dma = dev->bound_ptr * 256; - dev->remote_bytes = (uint16_t) chipmem_read(dev, dev->bound_ptr * 256 + 2, 2); - nelog(3, "%s: sending buffer #x%x length %d\n", - dev->name, dev->remote_start, dev->remote_bytes); + dp->remote_start = dp->remote_dma = dp->bound_ptr * 256; + dp->remote_bytes = (uint16_t)chipmem_read(dev, dp->bound_ptr * 256 + 2, 2); + DBGLOG(1, "%s: sending buffer #x%x length %d\n", + dev->name, dp->remote_start, dp->remote_bytes); } /* Check for start-tx */ - if ((val & 0x04) && dev->TCR.loop_cntl) { - if (dev->TCR.loop_cntl != 1) { - nelog(3, "%s: loop mode %d not supported\n", - dev->name, dev->TCR.loop_cntl); + if ((val & 0x04) && dp->TCR.loop_cntl) { + if (dp->TCR.loop_cntl != 1) { + DEBUG("%s: loop mode %d not supported\n", + dev->name, dp->TCR.loop_cntl); } else { if (dev->board >= NE2K_NE2000) { nic_rx(dev, - &dev->mem[dev->tx_page_start*256 - NE2K_MEMSTART], - dev->tx_bytes); + &dp->mem[dp->tx_page_start*256 - DP8390_DWORD_MEMSTART], + dp->tx_bytes); } else { nic_rx(dev, - &dev->mem[dev->tx_page_start*256 - NE1K_MEMSTART], - dev->tx_bytes); + &dp->mem[dp->tx_page_start*256 - DP8390_WORD_MEMSTART], + dp->tx_bytes); } } } else if (val & 0x04) { - if (dev->CR.stop || (!dev->CR.start && (dev->board < NE2K_RTL8019AS))) { - if (dev->tx_bytes == 0) /* njh@bandsman.co.uk */ { + if (dp->CR.stop || (!dp->CR.start && (dev->board < NE2K_RTL8019AS))) { + if (dp->tx_bytes == 0) /* njh@bandsman.co.uk */ { return; /* Solaris9 probe */ } - nelog(3, "%s: CR write - tx start, dev in reset\n", dev->name); + DEBUG("%s: CR write - tx start, dev in reset\n", dev->name); } - if (dev->tx_bytes == 0) - nelog(3, "%s: CR write - tx start, tx bytes == 0\n", dev->name); + if (dp->tx_bytes == 0) { + DEBUG("%s: CR write - tx start, tx bytes == 0\n", dev->name); + } /* Send the packet to the system driver */ - dev->CR.tx_packet = 1; + dp->CR.tx_packet = 1; if (dev->board >= NE2K_NE2000) { - network_tx(&dev->mem[dev->tx_page_start*256 - NE2K_MEMSTART], - dev->tx_bytes); + network_tx(&dp->mem[dp->tx_page_start*256 - DP8390_DWORD_MEMSTART], + dp->tx_bytes); } else { - network_tx(&dev->mem[dev->tx_page_start*256 - NE1K_MEMSTART], - dev->tx_bytes); + network_tx(&dp->mem[dp->tx_page_start*256 - DP8390_WORD_MEMSTART], + dp->tx_bytes); } /* some more debug */ - if (dev->tx_timer_active) - nelog(3, "%s: CR write, tx timer still active\n", dev->name); + if (dp->tx_timer_active) { + DEBUG("%s: CR write, tx timer still active\n", dev->name); + } nic_tx(dev, val); } @@ -1379,9 +1500,9 @@ write_cr(nic_t *dev, uint32_t val) /* Linux probes for an interrupt by setting up a remote-DMA read * of 0 bytes with remote-DMA completion interrupts enabled. * Detect this here */ - if (dev->CR.rdma_cmd == 0x01 && dev->CR.start && dev->remote_bytes == 0) { - dev->ISR.rdma_done = 1; - if (dev->IMR.rdma_inte) { + if (dp->CR.rdma_cmd == 0x01 && dp->CR.start && dp->remote_bytes == 0) { + dp->ISR.rdma_done = 1; + if (dp->IMR.rdma_inte) { nic_interrupt(dev, 1); if (! dev->is_pci) nic_interrupt(dev, 0); @@ -1393,39 +1514,39 @@ write_cr(nic_t *dev, uint32_t val) static uint32_t nic_read(nic_t *dev, uint32_t addr, unsigned len) { - uint32_t retval = 0; int off = addr - dev->base_address; + uint32_t ret = 0; - nelog(3, "%s: read addr %x, len %d\n", dev->name, addr, len); + DBGLOG(2, "%s: read addr %x, len %d\n", dev->name, addr, len); if (off >= 0x10) { - retval = asic_read(dev, off - 0x10, len); + ret = asic_read(dev, off - 0x10, len); } else if (off == 0x00) { - retval = read_cr(dev); - } else switch(dev->CR.pgsel) { + ret = read_cr(dev); + } else switch(dev->dp8390.CR.pgsel) { case 0x00: - retval = page0_read(dev, off, len); + ret = page0_read(dev, off, len); break; case 0x01: - retval = page1_read(dev, off, len); + ret = page1_read(dev, off, len); break; case 0x02: - retval = page2_read(dev, off, len); + ret = page2_read(dev, off, len); break; case 0x03: - retval = page3_read(dev, off, len); + ret = page3_read(dev, off, len); break; default: - nelog(3, "%s: unknown value of pgsel in read - %d\n", - dev->name, dev->CR.pgsel); + DEBUG("%s: unknown value of pgsel in read - %d\n", + dev->name, dev->dp8390.CR.pgsel); break; } - return(retval); + return(ret); } @@ -1441,10 +1562,10 @@ nic_readw(uint16_t addr, void *priv) { nic_t *dev = (nic_t *)priv; - if (dev->DCR.wdsize & 1) + if (dev->dp8390.DCR.wdsize & 1) return(nic_read(dev, addr, 2)); - else - return(nic_read(dev, addr, 1)); + + return(nic_read(dev, addr, 1)); } @@ -1460,7 +1581,7 @@ nic_write(nic_t *dev, uint32_t addr, uint32_t val, unsigned len) { int off = addr - dev->base_address; - nelog(3, "%s: write addr %x, value %x len %d\n", dev->name, addr, val, len); + DBGLOG(2, "%s: write(%08x, %08x) len %d\n", dev->name, addr, val, len); /* The high 16 bytes of i/o space are for the ne2000 asic - the low 16 bytes are for the DS8390, with the current @@ -1470,7 +1591,7 @@ nic_write(nic_t *dev, uint32_t addr, uint32_t val, unsigned len) asic_write(dev, off - 0x10, val, len); } else if (off == 0x00) { write_cr(dev, val); - } else switch(dev->CR.pgsel) { + } else switch(dev->dp8390.CR.pgsel) { case 0x00: page0_write(dev, off, val, len); break; @@ -1488,8 +1609,8 @@ nic_write(nic_t *dev, uint32_t addr, uint32_t val, unsigned len) break; default: - nelog(3, "%s: unknown value of pgsel in write - %d\n", - dev->name, dev->CR.pgsel); + DEBUG("%s: unknown value of pgsel in write - %d\n", + dev->name, dev->dp8390.CR.pgsel); break; } } @@ -1507,7 +1628,7 @@ nic_writew(uint16_t addr, uint16_t val, void *priv) { nic_t *dev = (nic_t *)priv; - if (dev->DCR.wdsize & 1) + if (dev->dp8390.DCR.wdsize & 1) nic_write(dev, addr, val, 2); else nic_write(dev, addr, val, 1); @@ -1530,7 +1651,7 @@ static void nic_ioremove(nic_t *dev, uint16_t addr); static uint8_t nic_pnp_io_check_readb(uint16_t addr, void *priv) { - nic_t *dev = (nic_t *) priv; + nic_t *dev = (nic_t *)priv; return((dev->pnp_io_check & 0x01) ? 0x55 : 0xAA); } @@ -1539,9 +1660,9 @@ nic_pnp_io_check_readb(uint16_t addr, void *priv) static uint8_t nic_pnp_readb(uint16_t addr, void *priv) { - nic_t *dev = (nic_t *) priv; + nic_t *dev = (nic_t *)priv; uint8_t bit, next_shift; - uint8_t ret = 0xFF; + uint8_t ret = 0xff; /* Plug and Play Registers */ switch(dev->pnp_address) { @@ -1561,7 +1682,7 @@ nic_pnp_readb(uint16_t addr, void *priv) if (!dev->pnp_serial_read_pos) { dev->pnp_res_pos = 0x1B; dev->pnp_phase = PNP_PHASE_CONFIG; - nelog(1, "\nASSIGN CSN phase\n"); + DBGLOG(1, "\nASSIGN CSN phase\n"); } } else { if (dev->pnp_serial_read_pos < 64) { @@ -1580,27 +1701,33 @@ nic_pnp_readb(uint16_t addr, void *priv) dev->pnp_serial_read_pair ^= 1; ret = dev->pnp_serial_read; break; + case 0x04: /* Resource Data */ ret = dev->eeprom[dev->pnp_res_pos]; dev->pnp_res_pos++; break; + case 0x05: /* Status */ ret = 0x01; break; + case 0x06: /* Card Select Number (CSN) */ - nelog(1, "Card Select Number (CSN)\n"); + DBGLOG(1, "Card Select Number (CSN)\n"); ret = dev->pnp_csn; break; + case 0x07: /* Logical Device Number */ - nelog(1, "Logical Device Number\n"); + DBGLOG(1, "Logical Device Number\n"); ret = 0x00; break; + case 0x30: /* Activate */ - nelog(1, "Activate\n"); + DBGLOG(1, "Activate\n"); ret = dev->pnp_activate; break; + case 0x31: /* I/O Range Check */ - nelog(1, "I/O Range Check\n"); + DBGLOG(1, "I/O Range Check\n"); ret = dev->pnp_io_check; break; @@ -1618,6 +1745,7 @@ nic_pnp_readb(uint16_t addr, void *priv) case 0x60: /* I/O base address bits[15:8] */ ret = (dev->base_address >> 8); break; + case 0x61: /* I/O base address bits[7:0] */ ret = (dev->base_address & 0xFF); break; @@ -1626,6 +1754,7 @@ nic_pnp_readb(uint16_t addr, void *priv) case 0x70: /* IRQ level */ ret = dev->base_irq; break; + case 0x71: /* IRQ type */ ret = 0x02; /* high, edge */ break; @@ -1641,18 +1770,21 @@ nic_pnp_readb(uint16_t addr, void *priv) case 0xF1: /* CONFIG1 */ ret = 0x00; break; + case 0xF2: /* CONFIG2 */ ret = (dev->config2 & 0xe0); break; + case 0xF3: /* CONFIG3 */ ret = (dev->config3 & 0x46); break; + case 0xF5: /* CSNSAV */ ret = (dev->pnp_csnsav); break; } + DBGLOG(1, "nic_pnp_readb(%04X) = %02X\n", addr, ret); - nelog(1, "nic_pnp_readb(%04X) = %02X\n", addr, ret); return(ret); } @@ -1664,10 +1796,10 @@ static void nic_pnp_io_remove(nic_t *dev); static void nic_pnp_writeb(uint16_t addr, uint8_t val, void *priv) { - nic_t *dev = (nic_t *) priv; + nic_t *dev = (nic_t *)priv; uint16_t new_addr = 0; - nelog(1, "nic_pnp_writeb(%04X, %02X)\n", addr, val); + DBGLOG(1, "nic_pnp_writeb(%04X, %02X)\n", addr, val); /* Plug and Play Registers */ switch(dev->pnp_address) { @@ -1678,28 +1810,30 @@ nic_pnp_writeb(uint16_t addr, uint8_t val, void *priv) new_addr |= 3; nic_pnp_io_remove(dev); nic_pnp_io_set(dev, new_addr); - nelog(1, "PnP read data address now: %04X\n", new_addr); + DBGLOG(1, "PnP read data address now: %04X\n", new_addr); break; + case 0x02: /* Config Control */ if (val & 0x01) { /* Reset command */ nic_pnp_io_remove(dev); memset(dev->pnp_regs, 0, 256); - nelog(1, "All logical devices reset\n"); + DBGLOG(1, "All logical devices reset\n"); } if (val & 0x02) { /* Wait for Key command */ dev->pnp_phase = PNP_PHASE_WAIT_FOR_KEY; - nelog(1, "WAIT FOR KEY phase\n"); + DBGLOG(1, "WAIT FOR KEY phase\n"); } if (val & 0x04) { /* PnP Reset CSN command */ dev->pnp_csn = dev->pnp_csnsav = 0; - nelog(1, "CSN reset\n"); + DBGLOG(1, "CSN reset\n"); } break; + case 0x03: /* Wake[CSN] */ - nelog(1, "Wake[%02X]\n", val); + DBGLOG(1, "Wake[%02X]\n", val); if (val == dev->pnp_csn) { dev->pnp_res_pos = 0x12; dev->pnp_id_checksum = 0x6A; @@ -1711,28 +1845,33 @@ nic_pnp_writeb(uint16_t addr, uint8_t val, void *priv) dev->pnp_phase = PNP_PHASE_SLEEP; } break; + case 0x06: /* Card Select Number (CSN) */ dev->pnp_csn = dev->pnp_csnsav = val; dev->pnp_phase = PNP_PHASE_CONFIG; - nelog(1, "CSN set to %02X\n", dev->pnp_csn); + DBGLOG(1, "CSN set to %02X\n", dev->pnp_csn); break; + case 0x30: /* Activate */ if ((dev->pnp_activate ^ val) & 0x01) { nic_ioremove(dev, dev->base_address); if (val & 0x01) nic_ioset(dev, dev->base_address); - nelog(1, "I/O range %sabled\n", val & 0x02 ? "en" : "dis"); + DBGLOG(1, "I/O range %sabled\n", + val & 0x02 ? "en" : "dis"); } dev->pnp_activate = val; break; + case 0x31: /* I/O Range Check */ if ((dev->pnp_io_check ^ val) & 0x02) { nic_iocheckremove(dev, dev->base_address); if (val & 0x02) nic_iocheckset(dev, dev->base_address); - nelog(1, "I/O range check %sabled\n", val & 0x02 ? "en" : "dis"); + DBGLOG(1, "I/O range check %sabled\n", + val & 0x02 ? "en" : "dis"); } dev->pnp_io_check = val; break; @@ -1750,8 +1889,9 @@ nic_pnp_writeb(uint16_t addr, uint8_t val, void *priv) dev->base_address |= (((uint16_t) val) << 8); if ((dev->pnp_activate & 0x01) || (dev->pnp_io_check & 0x02)) nic_ioset(dev, dev->base_address); - nelog(1, "Base address now: %04X\n", dev->base_address); + DBGLOG(1, "Base address now: %04X\n", dev->base_address); break; + case 0x61: /* I/O base address bits[7:0] */ if ((dev->pnp_activate & 0x01) || (dev->pnp_io_check & 0x02)) nic_ioremove(dev, dev->base_address); @@ -1759,13 +1899,13 @@ nic_pnp_writeb(uint16_t addr, uint8_t val, void *priv) dev->base_address |= val; if ((dev->pnp_activate & 0x01) || (dev->pnp_io_check & 0x02)) nic_ioset(dev, dev->base_address); - nelog(1, "Base address now: %04X\n", dev->base_address); + DBGLOG(1, "Base address now: %04X\n", dev->base_address); break; /* Interrupt Configuration Registers */ case 0x70: /* IRQ level */ dev->base_irq = val; - nelog(1, "IRQ now: %02i\n", dev->base_irq); + DBGLOG(1, "IRQ now: %02i\n", dev->base_irq); break; /* Vendor Defined Registers */ @@ -1780,23 +1920,22 @@ nic_pnp_writeb(uint16_t addr, uint8_t val, void *priv) static void nic_pnp_io_set(nic_t *dev, uint16_t read_addr) { - if ((read_addr >= 0x0200) && (read_addr <= 0x03FF)) { - io_sethandler(read_addr, 1, - nic_pnp_readb, NULL, NULL, - NULL, NULL, NULL, dev); - } - dev->pnp_read = read_addr; + if ((read_addr >= 0x0200) && (read_addr <= 0x03FF)) { + io_sethandler(read_addr, 1, + nic_pnp_readb,NULL,NULL, NULL,NULL,NULL, dev); + } + + dev->pnp_read = read_addr; } static void nic_pnp_io_remove(nic_t *dev) { - if ((dev->pnp_read >= 0x0200) && (dev->pnp_read <= 0x03FF)) { - io_removehandler(dev->pnp_read, 1, - nic_pnp_readb, NULL, NULL, - NULL, NULL, NULL, dev); - } + if ((dev->pnp_read >= 0x0200) && (dev->pnp_read <= 0x03FF)) { + io_removehandler(dev->pnp_read, 1, + nic_pnp_readb,NULL,NULL, NULL,NULL,NULL, dev); + } } @@ -1805,7 +1944,7 @@ nic_pnp_address_writeb(uint16_t addr, uint8_t val, void *priv) { nic_t *dev = (nic_t *) priv; - /* nelog(1, "nic_pnp_address_writeb(%04X, %02X)\n", addr, val); */ + /* DBGLOG(2, "nic_pnp_address_writeb(%04X, %02X)\n", addr, val); */ switch(dev->pnp_phase) { case PNP_PHASE_WAIT_FOR_KEY: @@ -1816,6 +1955,7 @@ nic_pnp_address_writeb(uint16_t addr, uint8_t val, void *priv) } else dev->pnp_magic_count = 0; break; + default: dev->pnp_address = val; break; @@ -1845,7 +1985,17 @@ nic_iocheckremove(nic_t *dev, uint16_t addr) static void nic_ioset(nic_t *dev, uint16_t addr) { - if (dev->is_pci) { + if (dev->is_mca) { + io_sethandler(addr, 16, + nic_readb, nic_readw, nic_readl, + nic_writeb, nic_writew, nic_writel, dev); + io_sethandler(addr+16, 16, + nic_readb, nic_readw, nic_readl, + nic_writeb, nic_writew, nic_writel, dev); + io_sethandler(addr+0x1f, 16, + nic_readb, nic_readw, nic_readl, + nic_writeb, nic_writew, nic_writel, dev); + } else if (dev->is_pci) { io_sethandler(addr, 16, nic_readb, nic_readw, nic_readl, nic_writeb, nic_writew, nic_writel, dev); @@ -1857,20 +2007,17 @@ nic_ioset(nic_t *dev, uint16_t addr) nic_writeb, nic_writew, nic_writel, dev); } else { io_sethandler(addr, 16, - nic_readb, NULL, NULL, - nic_writeb, NULL, NULL, dev); - if (dev->is_8bit) { + nic_readb,NULL,NULL, nic_writeb,NULL,NULL, dev); + if (dev->is_8bit) io_sethandler(addr+16, 16, - nic_readb, NULL, NULL, - nic_writeb, NULL, NULL, dev); - } else { + nic_readb, NULL, NULL, + nic_writeb, NULL, NULL, dev); + else io_sethandler(addr+16, 16, - nic_readb, nic_readw, NULL, - nic_writeb, nic_writew, NULL, dev); - } + nic_readb, nic_readw, NULL, + nic_writeb, nic_writew, NULL, dev); io_sethandler(addr+0x1f, 1, - nic_readb, NULL, NULL, - nic_writeb, NULL, NULL, dev); + nic_readb, NULL, NULL, nic_writeb, NULL, NULL, dev); } } @@ -1878,7 +2025,17 @@ nic_ioset(nic_t *dev, uint16_t addr) static void nic_ioremove(nic_t *dev, uint16_t addr) { - if (dev->is_pci) { + if (dev->is_mca) { + io_removehandler(addr, 16, + nic_readb, nic_readw, nic_readl, + nic_writeb, nic_writew, nic_writel, dev); + io_removehandler(addr+16, 16, + nic_readb, nic_readw, nic_readl, + nic_writeb, nic_writew, nic_writel, dev); + io_removehandler(addr+0x1f, 16, + nic_readb, nic_readw, nic_readl, + nic_writeb, nic_writew, nic_writel, dev); + } else if (dev->is_pci) { io_removehandler(addr, 16, nic_readb, nic_readw, nic_readl, nic_writeb, nic_writew, nic_writel, dev); @@ -1892,15 +2049,14 @@ nic_ioremove(nic_t *dev, uint16_t addr) io_removehandler(addr, 16, nic_readb, NULL, NULL, nic_writeb, NULL, NULL, dev); - if (dev->is_8bit) { + if (dev->is_8bit) io_removehandler(addr+16, 16, nic_readb, NULL, NULL, nic_writeb, NULL, NULL, dev); - } else { + else io_removehandler(addr+16, 16, nic_readb, nic_readw, NULL, nic_writeb, nic_writew, NULL, dev); - } io_removehandler(addr+0x1f, 1, nic_readb, NULL, NULL, nic_writeb, NULL, NULL, dev); @@ -1917,17 +2073,17 @@ nic_update_bios(nic_t *dev) if (! dev->has_bios) return; - if (PCI && dev->is_pci) + if (dev->is_pci) reg_bios_enable = dev->pci_bar[1].addr_regs[0] & 0x01; /* PCI BIOS stuff, just enable_disable. */ if (reg_bios_enable) { - mem_mapping_set_addr(&dev->bios_rom.mapping, - dev->bios_addr, dev->bios_size); - nelog(1, "%s: BIOS now at: %06X\n", dev->name, dev->bios_addr); + mem_map_set_addr(&dev->bios_rom.mapping, + dev->bios_addr, dev->bios_size); + INFO("%s: BIOS now at: %06X\n", dev->name, dev->bios_addr); } else { - nelog(1, "%s: BIOS disabled\n", dev->name); - mem_mapping_disable(&dev->bios_rom.mapping); + INFO("%s: BIOS disabled\n", dev->name); + mem_map_disable(&dev->bios_rom.mapping); } } @@ -2034,7 +2190,7 @@ nic_pci_read(int func, int addr, void *priv) break; } - nelog(2, "%s: PCI_Read(%d, %04x) = %02x\n", dev->name, func, addr, ret); + DBGLOG(2, "%s: PCI_Read(%d, %04x) = %02x\n", dev->name, func, addr, ret); return(ret); } @@ -2046,7 +2202,7 @@ nic_pci_write(int func, int addr, uint8_t val, void *priv) nic_t *dev = (nic_t *)priv; uint8_t valxor; - nelog(2, "%s: PCI_Write(%d, %04x, %02x)\n", dev->name, func, addr, val); + DBGLOG(2, "%s: PCI_Write(%d, %04x, %02x)\n", dev->name, func, addr, val); switch(addr) { case 0x04: /* PCI_COMMAND_LO */ @@ -2103,15 +2259,12 @@ nic_pci_write(int func, int addr, uint8_t val, void *priv) dev->base_address = dev->pci_bar[0].addr & 0xffe0; /* Log the new base. */ - nelog(1, "%s: PCI: new I/O base is %04X\n", + DBGLOG(1, "%s: PCI: new I/O base is %04X\n", dev->name, dev->base_address); /* We're done, so get out of the here. */ - if (dev->pci_regs[4] & PCI_COMMAND_IO) - { + if (dev->pci_regs[4] & PCI_COMMAND_IO) { if (dev->base_address != 0) - { nic_ioset(dev, dev->base_address); - } } break; @@ -2127,7 +2280,7 @@ nic_pci_write(int func, int addr, uint8_t val, void *priv) return; case 0x3C: /* PCI_ILR */ - nelog(1, "%s: IRQ now: %i\n", dev->name, val); + DBGLOG(1, "%s: IRQ now: %i\n", dev->name, val); dev->base_irq = val; dev->pci_regs[addr] = dev->base_irq; return; @@ -2135,210 +2288,6 @@ nic_pci_write(int func, int addr, uint8_t val, void *priv) } -/* - * Return the 6-bit index into the multicast - * table. Stolen unashamedly from FreeBSD's if_ed.c - */ -static int -mcast_index(const void *dst) -{ -#define POLYNOMIAL 0x04c11db6 - uint32_t crc = 0xffffffffL; - int carry, i, j; - uint8_t b; - uint8_t *ep = (uint8_t *)dst; - - for (i=6; --i>=0;) { - b = *ep++; - for (j = 8; --j >= 0;) { - carry = ((crc & 0x80000000L) ? 1 : 0) ^ (b & 0x01); - crc <<= 1; - b >>= 1; - if (carry) - crc = ((crc ^ POLYNOMIAL) | carry); - } - } - return(crc >> 26); -#undef POLYNOMIAL -} - - -static void -nic_tx(nic_t *dev, uint32_t val) -{ - dev->CR.tx_packet = 0; - dev->TSR.tx_ok = 1; - dev->ISR.pkt_tx = 1; - - /* Generate an interrupt if not masked */ - if (dev->IMR.tx_inte) - nic_interrupt(dev, 1); - dev->tx_timer_active = 0; -} - - -/* - * Called by the platform-specific code when an Ethernet frame - * has been received. The destination address is tested to see - * if it should be accepted, and if the RX ring has enough room, - * it is copied into it and the receive process is updated. - */ -static void -nic_rx(void *priv, uint8_t *buf, int io_len) -{ - static uint8_t bcast_addr[6] = {0xff,0xff,0xff,0xff,0xff,0xff}; - nic_t *dev = (nic_t *)priv; - uint8_t pkthdr[4]; - uint8_t *startptr; - int npg, avail; - int idx, nextpage; - int endbytes; - - //FIXME: move to upper layer - ui_sb_icon_update(SB_NETWORK, 1); - - if (io_len != 60) - nelog(2, "%s: rx_frame with length %d\n", dev->name, io_len); - - if ((dev->CR.stop != 0) || (dev->page_start == 0)) return; - - /* - * Add the pkt header + CRC to the length, and work - * out how many 256-byte pages the frame would occupy. - */ - npg = (io_len + sizeof(pkthdr) + sizeof(uint32_t) + 255)/256; - if (dev->curr_page < dev->bound_ptr) { - avail = dev->bound_ptr - dev->curr_page; - } else { - avail = (dev->page_stop - dev->page_start) - - (dev->curr_page - dev->bound_ptr); - } - - /* - * Avoid getting into a buffer overflow condition by - * not attempting to do partial receives. The emulation - * to handle this condition seems particularly painful. - */ - if ((avail < npg) -#if NE2K_NEVER_FULL_RING - || (avail == npg) -#endif - ) { - nelog(1, "%s: no space\n", dev->name); - - //FIXME: move to upper layer - ui_sb_icon_update(SB_NETWORK, 0); - return; - } - - if ((io_len < 40/*60*/) && !dev->RCR.runts_ok) { - nelog(1, "%s: rejected small packet, length %d\n", dev->name, io_len); - - //FIXME: move to upper layer - ui_sb_icon_update(SB_NETWORK, 0); - return; - } - - /* Some computers don't care... */ - if (io_len < 60) - io_len = 60; - - nelog(2, "%s: RX %x:%x:%x:%x:%x:%x > %x:%x:%x:%x:%x:%x len %d\n", - dev->name, - buf[6], buf[7], buf[8], buf[9], buf[10], buf[11], - buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], - io_len); - - /* Do address filtering if not in promiscuous mode. */ - if (! dev->RCR.promisc) { - /* If this is a broadcast frame.. */ - if (! memcmp(buf, bcast_addr, 6)) { - /* Broadcast not enabled, we're done. */ - if (! dev->RCR.broadcast) { - nelog(2, "%s: RX BC disabled\n", dev->name); - - //FIXME: move to upper layer - ui_sb_icon_update(SB_NETWORK, 0); - return; - } - } - - /* If this is a multicast frame.. */ - else if (buf[0] & 0x01) { - /* Multicast not enabled, we're done. */ - if (! dev->RCR.multicast) { -#if 1 - nelog(2, "%s: RX MC disabled\n", dev->name); -#endif - - //FIXME: move to upper layer - ui_sb_icon_update(SB_NETWORK, 0); - return; - } - - /* Are we listening to this multicast address? */ - idx = mcast_index(buf); - if (! (dev->mchash[idx>>3] & (1<<(idx&0x7)))) { - nelog(2, "%s: RX MC not listed\n", dev->name); - - //FIXME: move to upper layer - ui_sb_icon_update(SB_NETWORK, 0); - return; - } - } - - /* Unicast, must be for us.. */ - else if (memcmp(buf, dev->physaddr, 6)) return; - } else { - nelog(2, "%s: RX promiscuous receive\n", dev->name); - } - - nextpage = dev->curr_page + npg; - if (nextpage >= dev->page_stop) - nextpage -= (dev->page_stop - dev->page_start); - - /* Set up packet header. */ - pkthdr[0] = 0x01; /* RXOK - packet is OK */ - if (buf[0] & 0x01) - pkthdr[0] |= 0x20; /* MULTICAST packet */ - pkthdr[1] = nextpage; /* ptr to next packet */ - pkthdr[2] = (io_len + sizeof(pkthdr))&0xff; /* length-low */ - pkthdr[3] = (io_len + sizeof(pkthdr))>>8; /* length-hi */ - nelog(2, "%s: RX pkthdr [%02x %02x %02x %02x]\n", - dev->name, pkthdr[0], pkthdr[1], pkthdr[2], pkthdr[3]); - - /* Copy into buffer, update curpage, and signal interrupt if config'd */ - if (dev->board >= NE2K_NE2000) - startptr = &dev->mem[(dev->curr_page * 256) - NE2K_MEMSTART]; - else - startptr = &dev->mem[(dev->curr_page * 256) - NE1K_MEMSTART]; - memcpy(startptr, pkthdr, sizeof(pkthdr)); - if ((nextpage > dev->curr_page) || - ((dev->curr_page + npg) == dev->page_stop)) { - memcpy(startptr+sizeof(pkthdr), buf, io_len); - } else { - endbytes = (dev->page_stop - dev->curr_page) * 256; - memcpy(startptr+sizeof(pkthdr), buf, endbytes-sizeof(pkthdr)); - if (dev->board >= NE2K_NE2000) - startptr = &dev->mem[(dev->page_start * 256) - NE2K_MEMSTART]; - else - startptr = &dev->mem[(dev->page_start * 256) - NE1K_MEMSTART]; - memcpy(startptr, buf+endbytes-sizeof(pkthdr), io_len-endbytes+8); - } - dev->curr_page = nextpage; - - dev->RSR.rx_ok = 1; - dev->RSR.rx_mbit = (buf[0] & 0x01) ? 1 : 0; - dev->ISR.pkt_rx = 1; - - if (dev->IMR.rx_inte) - nic_interrupt(dev, 1); - - //FIXME: move to upper layer - ui_sb_icon_update(SB_NETWORK, 0); -} - - static void nic_rom_init(nic_t *dev, wchar_t *s) { @@ -2372,68 +2321,148 @@ nic_rom_init(nic_t *dev, wchar_t *s) rom_init(&dev->bios_rom, s, dev->bios_addr, dev->bios_size, dev->bios_size-1, 0, MEM_MAPPING_EXTERNAL); - nelog(1, "%s: BIOS configured at %06lX (size %ld)\n", - dev->name, dev->bios_addr, dev->bios_size); + INFO("%s: BIOS configured at %06lX (size %lu)\n", + dev->name, dev->bios_addr, dev->bios_size); +} + + +static uint8_t +nic_mca_read(int port, void *priv) +{ + nic_t *dev = (nic_t *)priv; + + return(dev->pos_regs[port & 0x07]); +} + + +static void +nic_mca_write(int port, uint8_t val, void *priv) +{ + nic_t *dev = (nic_t *)priv; + + /* MCA does not write registers below 0x0100. */ + if (port < 0x0102) return; + + /* Save the MCA register value. */ + dev->pos_regs[port & 0x07] = val; + + /* This is always necessary so that the old handler doesn't remain. */ + nic_ioremove(dev, dev->base_address); + + /* Get the new assigned I/O base address. */ + dev->base_address = dev->res->bases[((dev->pos_regs[2] & 0x0e) >> 1) - 1]; + + /* Save the new IRQ values. */ + dev->base_irq = dev->res->irqs[(dev->pos_regs[2] & 0x60) >> 5]; + dev->bios_addr = 0x0000; + dev->has_bios = 0; + + /* + * The PS/2 Model 80 BIOS always enables a card if it finds one, + * even if no resources were assigned yet (because we only added + * the card, but have not run AutoConfig yet...) + * + * So, remove current address, if any. + */ + + /* Initialize the device if fully configured. */ + if (dev->pos_regs[2] & 0x01) { + /* Card enabled; register (new) I/O handler. */ + nic_ioset(dev, dev->base_address); + + nic_reset(dev); + + DBGLOG(1, "%s: I/O=%04x, IRQ=%d\n", + dev->name, dev->base_address, dev->base_irq); + } } static void * nic_init(const device_t *info) { + char *ansi_id = "REALTEK PLUG & PLAY ETHERNET CARD"; uint32_t mac; wchar_t *fn; nic_t *dev; -#ifdef ENABLE_NETWORK_DEV_LOG - int i; -#endif int c; - char *ansi_id = "REALTEK PLUG & PLAY ETHERNET CARD"; - uint64_t *eeprom_pnp_id; - /* Get the desired debug level. */ -#ifdef ENABLE_NETWORK_DEV_LOG - i = device_get_config_int("debug"); - if (i > 0) network_dev_do_log = i; -#endif - - dev = malloc(sizeof(nic_t)); + dev = (nic_t *)mem_alloc(sizeof(nic_t)); memset(dev, 0x00, sizeof(nic_t)); dev->name = info->name; dev->board = info->local; + fn = NULL; switch(dev->board) { case NE2K_NE1000: dev->is_8bit = 1; - /*FALLTHROUGH*/ + dev->maclocal[0] = 0x00; /* 00:00:D8 (Novell OID) */ + dev->maclocal[1] = 0x00; + dev->maclocal[2] = 0xD8; + break; case NE2K_NE2000: dev->maclocal[0] = 0x00; /* 00:00:D8 (Novell OID) */ dev->maclocal[1] = 0x00; dev->maclocal[2] = 0xD8; - fn = (dev->board == NE2K_NE1000) ? NULL : ROM_PATH_NE2000; + fn = ROM_PATH_NE2000; + break; + + case NE2K_NE2_MCA: + case NE2K_NE2_ENEXT_MCA: + dev->is_mca = 1; + dev->res = (const rsl_t *)info->mca_reslist; + fn = NULL; + switch(dev->board) { + case NE2K_NE2_MCA: + dev->maclocal[0] = 0x00; /* (Novell OID) */ + dev->maclocal[1] = 0x00; + dev->maclocal[2] = 0xD8; + + dev->pos_regs[0] = 0x54; + dev->pos_regs[1] = 0x71; + break; + + case NE2K_NE2_ENEXT_MCA: + dev->maclocal[0] = 0x00; /* (NetWorth OID) */ + dev->maclocal[1] = 0x00; + dev->maclocal[2] = 0x79; + + dev->pos_regs[0] = 0x1F; + dev->pos_regs[1] = 0x61; + break; + } break; case NE2K_RTL8019AS: - case NE2K_RTL8029AS: - dev->is_pci = (dev->board == NE2K_RTL8029AS) ? 1 : 0; dev->maclocal[0] = 0x00; /* 00:E0:4C (Realtek OID) */ dev->maclocal[1] = 0xE0; dev->maclocal[2] = 0x4C; - fn = (dev->board == NE2K_RTL8019AS) ? ROM_PATH_RTL8019 : ROM_PATH_RTL8029; + fn = ROM_PATH_RTL8019; + break; + + case NE2K_RTL8029AS: + dev->is_pci = 1; + dev->maclocal[0] = 0x00; /* 00:E0:4C (Realtek OID) */ + dev->maclocal[1] = 0xE0; + dev->maclocal[2] = 0x4C; + fn = ROM_PATH_RTL8029; break; } if (dev->board >= NE2K_RTL8019AS) { + /* Default settings, PNP/PCI will do actual config. */ dev->base_address = 0x340; dev->base_irq = 12; if (dev->board == NE2K_RTL8029AS) { dev->bios_addr = 0xD0000; dev->has_bios = device_get_config_int("bios"); - } else { - dev->bios_addr = 0x00000; - dev->has_bios = 0; } + } else if (dev->is_mca) { + /* Let MCA do its thing. */ + mca_add(nic_mca_read, nic_mca_write, dev); } else { + /* Manual configuration. */ dev->base_address = device_get_config_hex16("base"); dev->base_irq = device_get_config_int("irq"); if (dev->board == NE2K_NE2000) { @@ -2445,19 +2474,20 @@ nic_init(const device_t *info) } } - /* See if we have a local MAC address configured. */ - mac = device_get_config_mac("mac", -1); - /* * Make this device known to the I/O system. - * PnP and PCI devices start with address spaces inactive. + * + * PnP, MCA and PCI devices start with address spaces inactive. */ - if (dev->board < NE2K_RTL8019AS) + if ((dev->board < NE2K_RTL8019AS) && !dev->is_mca) nic_ioset(dev, dev->base_address); /* Set up our BIOS ROM space, if any. */ nic_rom_init(dev, fn); + /* See if we have a local MAC address configured. */ + mac = device_get_config_mac("mac", -1); + /* Set up our BIA. */ if (mac & 0xff000000) { /* Generate new local MAC. */ @@ -2467,18 +2497,19 @@ nic_init(const device_t *info) mac = (((int) dev->maclocal[3]) << 16); mac |= (((int) dev->maclocal[4]) << 8); mac |= ((int) dev->maclocal[5]); + + /* Save this for next time. */ device_set_config_mac("mac", mac); } else { dev->maclocal[3] = (mac>>16) & 0xff; dev->maclocal[4] = (mac>>8) & 0xff; dev->maclocal[5] = (mac & 0xff); } - memcpy(dev->physaddr, dev->maclocal, sizeof(dev->maclocal)); - nelog(0, "%s: I/O=%04x, IRQ=%d, MAC=%02x:%02x:%02x:%02x:%02x:%02x\n", - dev->name, dev->base_address, dev->base_irq, - dev->physaddr[0], dev->physaddr[1], dev->physaddr[2], - dev->physaddr[3], dev->physaddr[4], dev->physaddr[5]); + INFO("%s: I/O=%04x, IRQ=%d, MAC=%02x:%02x:%02x:%02x:%02x:%02x\n", + dev->name, dev->base_address, dev->base_irq, + dev->maclocal[0], dev->maclocal[1], dev->maclocal[2], + dev->maclocal[3], dev->maclocal[4], dev->maclocal[5]); if (dev->board >= NE2K_RTL8019AS) { if (dev->is_pci) { @@ -2488,7 +2519,6 @@ nic_init(const device_t *info) * We do this here, so the I/O routines are generic. */ memset(dev->pci_regs, 0, PCI_REGSIZE); - dev->pci_regs[0x00] = (PCI_VENDID&0xff); dev->pci_regs[0x01] = (PCI_VENDID>>8); dev->pci_regs[0x02] = (PCI_DEVID&0xff); @@ -2522,7 +2552,7 @@ nic_init(const device_t *info) dev->bios_size = 0; } - mem_mapping_disable(&dev->bios_rom.mapping); + mem_map_disable(&dev->bios_rom.mapping); /* Add device to the PCI bus, keep its slot number. */ dev->card = pci_add_card(PCI_ADD_NORMAL, @@ -2542,8 +2572,10 @@ nic_init(const device_t *info) memset(dev->eeprom, 0x00, sizeof(dev->eeprom)); if (dev->board == NE2K_RTL8029AS) { + /* Write our (current) MAC into the EEPROM. */ memcpy(&dev->eeprom[0x02], dev->maclocal, 6); + /* Write our PNP or PCI ID into the EEPROM> */ dev->eeprom[0x76] = dev->eeprom[0x7A] = dev->eeprom[0x7E] = (PCI_DEVID&0xff); @@ -2555,8 +2587,8 @@ nic_init(const device_t *info) dev->eeprom[0x79] = dev->eeprom[0x7D] = (PCI_VENDID>>8); } else { - eeprom_pnp_id = (uint64_t *) &dev->eeprom[0x12]; - *eeprom_pnp_id = dev->pnp_id; + /* Set the PNP ID into the EEPROM. */ + memcpy(&dev->eeprom[0x12], &dev->pnp_id, 8); /* TAG: Plug and Play Version Number. */ dev->eeprom[0x1B] = 0x0A; /* Item byte */ @@ -2579,7 +2611,7 @@ nic_init(const device_t *info) dev->eeprom[0x49] = 0x00; /* Flag 1 */ /* TAG: Compatible Device ID (NE2000) */ - dev->eeprom[0x4A] = 0x1C; /* Item byte */ + dev->eeprom[0x4A] = 0x1C; /* Item byte */ dev->eeprom[0x4B] = 0x41; /* Compatible ID0 */ dev->eeprom[0x4C] = 0xD0; /* Compatible ID1 */ dev->eeprom[0x4D] = 0x80; /* Compatible ID2 */ @@ -2613,14 +2645,17 @@ nic_init(const device_t *info) } } + /* Write our current MAC into the DP8390. */ + memcpy(dev->dp8390.physaddr, dev->maclocal, sizeof(dev->maclocal)); + /* Reset the board. */ nic_reset(dev); /* Attach ourselves to the network module. */ - network_attach(dev, dev->physaddr, nic_rx); + network_attach(dev, dev->dp8390.physaddr, nic_rx); - nelog(1, "%s: %s attached IO=0x%X IRQ=%d\n", dev->name, - dev->is_pci?"PCI":"ISA", dev->base_address, dev->base_irq); + INFO("%s: %s attached IO=0x%X IRQ=%d\n", dev->name, + dev->is_pci?"PCI":"ISA", dev->base_address, dev->base_irq); return(dev); } @@ -2636,14 +2671,13 @@ nic_close(void *priv) nic_ioremove(dev, dev->base_address); - nelog(1, "%s: closed\n", dev->name); + DEBUG("%s: closed\n", dev->name); free(dev); } -static const device_config_t ne1000_config[] = -{ +static const device_config_t ne1000_config[] = { { "base", "Address", CONFIG_HEX16, "", 0x300, { @@ -2701,8 +2735,7 @@ static const device_config_t ne1000_config[] = } }; -static const device_config_t ne2000_config[] = -{ +static const device_config_t ne2000_config[] = { { "base", "Address", CONFIG_HEX16, "", 0x300, { @@ -2786,8 +2819,26 @@ static const device_config_t ne2000_config[] = } }; -static const device_config_t rtl8019as_config[] = -{ +static const device_config_t ne2_mca_config[] = { + { + "mac", "MAC Address", CONFIG_MAC, "", -1 + }, + { + "", "", -1 + } +}; +static const rsl_t ne2_mca_rsl = { + { 0x1000, 0x2020, 0x8020, 0xa0a0, 0xb0b0, + 0xc0c0, 0xc3d0 }, + { 3, 4, 5, 9 } +}; +static const rsl_t ne2_enext_mca_rsl = { + { 0x0300, 0x0340, 0x0320, 0x0360, 0x1300, + 0x1340, 0x1320, 0x1360 }, + { 2, 3, 4, 5, 10, 11, 12, 15 } +}; + +static const device_config_t rtl8019as_config[] = { { "mac", "MAC Address", CONFIG_MAC, "", -1 }, @@ -2796,8 +2847,7 @@ static const device_config_t rtl8019as_config[] = } }; -static const device_config_t rtl8029as_config[] = -{ +static const device_config_t rtl8029as_config[] = { { "bios", "Enable BIOS", CONFIG_BINARY, "", 0 }, @@ -2828,6 +2878,26 @@ const device_t ne2000_device = { ne2000_config }; +const device_t ne2_mca_device = { + "Novell NE/2", + DEVICE_MCA, + NE2K_NE2_MCA, + nic_init, nic_close, NULL, + NULL, NULL, NULL, + (void *)&ne2_mca_rsl, + ne2_mca_config +}; + +const device_t ne2_enext_mca_device = { + "NetWorth Ethernet/MC", + DEVICE_MCA, + NE2K_NE2_ENEXT_MCA, + nic_init, nic_close, NULL, + NULL, NULL, NULL, + (void *)&ne2_enext_mca_rsl, + ne2_mca_config +}; + const device_t rtl8019as_device = { "Realtek RTL8019AS", DEVICE_ISA | DEVICE_AT, diff --git a/src/devices/network/net_ne2000.h b/src/devices/network/net_ne2000.h index 0453a3b..e11ade9 100644 --- a/src/devices/network/net_ne2000.h +++ b/src/devices/network/net_ne2000.h @@ -8,7 +8,7 @@ * * Definitions for the NE2000 ethernet controller. * - * Version: @(#)net_ne2000.h 1.0.2 2018/03/15 + * Version: @(#)net_ne2000.h 1.0.3 2018/09/09 * * Authors: Fred N. van Kempen, * @@ -36,17 +36,10 @@ # define NET_NE2000_H -enum { - NE2K_NONE = 0, - NE2K_NE1000, /* 8-bit ISA NE1000 */ - NE2K_NE2000, /* 16-bit ISA NE2000 */ - NE2K_RTL8019AS, /* 16-bit ISA PnP Realtek 8019AS */ - NE2K_RTL8029AS /* 32-bit PCI Realtek 8029AS */ -}; - - extern const device_t ne1000_device; extern const device_t ne2000_device; +extern const device_t ne2_mca_device; +extern const device_t ne2_enext_mca_device; extern const device_t rtl8019as_device; extern const device_t rtl8029as_device; diff --git a/src/devices/network/net_pcap.c b/src/devices/network/net_pcap.c index 2864389..e30ce93 100644 --- a/src/devices/network/net_pcap.c +++ b/src/devices/network/net_pcap.c @@ -8,7 +8,7 @@ * * Handle WinPcap library processing. * - * Version: @(#)net_pcap.c 1.0.6 2018/05/06 + * Version: @(#)net_pcap.c 1.0.7 2018/10/05 * * Author: Fred N. van Kempen, * @@ -53,8 +53,11 @@ # define WIN32 #endif #include +#ifdef ERROR +# undef ERROR +#endif +#define dbglog network_log #include "../../emu.h" -#include "../../config.h" #include "../../device.h" #include "../../plat.h" #include "network.h" @@ -103,7 +106,7 @@ poll_thread(void *arg) uint16_t mac_cmp16[2]; event_t *evt; - pclog("PCAP: polling started.\n"); + INFO("PCAP: thread started.\n"); thread_set_event(poll_state); /* Create a waitable event. */ @@ -150,9 +153,9 @@ poll_thread(void *arg) /* No longer needed. */ if (evt != NULL) thread_destroy_event(evt); - - pclog("PCAP: polling stopped.\n"); thread_set_event(poll_state); + + INFO("PCAP: thread stopped.\n"); } @@ -183,11 +186,11 @@ net_pcap_prepare(netdev_t *list) /* Retrieve the device list from the local machine */ if (f_pcap_findalldevs(&devlist, errbuf) == -1) { - pclog("PCAP: error in pcap_findalldevs: %s\n", errbuf); + ERRLOG("PCAP: error in pcap_findalldevs: %s\n", errbuf); return(-1); } - for (dev=devlist; dev!=NULL; dev=dev->next) { + for (dev = devlist; dev != NULL; dev=dev->next) { strcpy(list->device, dev->name); if (dev->description) strcpy(list->description, dev->description); @@ -218,26 +221,16 @@ net_pcap_init(void) /* Did we already load the library? */ if (pcap_handle == NULL) return(-1); -#if 0 - // no, we don't.. - /* Load the DLL if needed. We already know it exists. */ -#ifdef _WIN32 - pcap_handle = dynld_module("wpcap.dll", pcap_imports); -#else - pcap_handle = dynld_module("libpcap.so", pcap_imports); -#endif - if (pcap_handle == NULL) return(-1); -#endif /* Get the PCAP library name and version. */ strcpy(errbuf, f_pcap_lib_version()); str = strchr(errbuf, '('); if (str != NULL) *(str-1) = '\0'; - pclog("PCAP: initializing, %s\n", errbuf); + INFO("PCAP: initializing, %s\n", errbuf); /* Get the value of our capture interface. */ if ((network_host[0] == '\0') || !strcmp(network_host, "none")) { - pclog("PCAP: no interface configured!\n"); + ERRLOG("PCAP: no interface configured!\n"); return(-1); } @@ -257,7 +250,7 @@ net_pcap_close(void) if (pcap == NULL) return; - pclog("PCAP: closing.\n"); + INFO("PCAP: closing.\n"); /* Tell the polling thread to shut down. */ pc = (pcap_t *)pcap; pcap = NULL; @@ -267,9 +260,9 @@ net_pcap_close(void) network_busy(0); /* Wait for the thread to finish. */ - pclog("PCAP: waiting for thread to end...\n"); + INFO("PCAP: waiting for thread to end...\n"); thread_wait_event(poll_state, -1); - pclog("PCAP: thread ended\n"); + INFO("PCAP: thread ended\n"); thread_destroy_event(poll_state); poll_tid = NULL; @@ -281,14 +274,7 @@ net_pcap_close(void) f_pcap_close(pc); pcap = NULL; -#if 0 - // no, we don't.. - /* Unload the DLL if possible. */ - if (pcap_handle != NULL) { - dynld_close((void *)pcap_handle); - pcap_handle = NULL; - } -#endif + INFO("PCAP: closed.\n"); } @@ -316,13 +302,13 @@ net_pcap_reset(const netcard_t *card, uint8_t *mac) 1, /* promiscuous mode? */ 10, /* timeout in msec */ errbuf)) == NULL) { /* error buffer */ - pclog(" Unable to open device: %s!\n", network_host); + ERRLOG(" Unable to open device: %s!\n", network_host); return(-1); } - pclog("PCAP: interface: %s\n", network_host); + DEBUG("PCAP: interface: %s\n", network_host); /* Create a MAC address based packet filter. */ - pclog("PCAP: installing filter for MAC=%02x:%02x:%02x:%02x:%02x:%02x\n", + DEBUG("PCAP: installing filter for MAC=%02x:%02x:%02x:%02x:%02x:%02x\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); sprintf(filter_exp, "( ((ether dst ff:ff:ff:ff:ff:ff) or (ether dst %02x:%02x:%02x:%02x:%02x:%02x)) and not (ether src %02x:%02x:%02x:%02x:%02x:%02x) )", @@ -330,12 +316,12 @@ net_pcap_reset(const netcard_t *card, uint8_t *mac) mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); if (f_pcap_compile((pcap_t *)pcap, &fp, filter_exp, 0, 0xffffffff) != -1) { if (f_pcap_setfilter((pcap_t *)pcap, &fp) != 0) { - pclog("PCAP: error installing filter (%s) !\n", filter_exp); + ERRLOG("PCAP: error installing filter (%s) !\n", filter_exp); f_pcap_close((pcap_t *)pcap); return(-1); } } else { - pclog("PCAP: could not compile filter (%s) !\n", filter_exp); + ERRLOG("PCAP: could not compile filter (%s) !\n", filter_exp); f_pcap_close((pcap_t *)pcap); return(-1); } @@ -343,7 +329,6 @@ net_pcap_reset(const netcard_t *card, uint8_t *mac) /* Save the callback info. */ poll_card = card; - pclog("PCAP: starting thread..\n"); poll_state = thread_create_event(); poll_tid = thread_create(poll_thread, mac); thread_wait_event(poll_state, -1); diff --git a/src/devices/network/net_slirp.c b/src/devices/network/net_slirp.c index c45e491..60a5b15 100644 --- a/src/devices/network/net_slirp.c +++ b/src/devices/network/net_slirp.c @@ -8,7 +8,7 @@ * * Handle SLiRP library processing. * - * Version: @(#)net_slirp.c 1.0.3 2018/05/06 + * Version: @(#)net_slirp.c 1.0.4 2018/10/05 * * Author: Fred N. van Kempen, * @@ -51,8 +51,11 @@ #include #include "slirp/slirp.h" #include "slirp/queue.h" +#define netdbg network_log +#ifdef ERROR +# undef ERROR +#endif #include "../../emu.h" -#include "../../config.h" #include "../../device.h" #include "../../plat.h" #include "network.h" @@ -100,7 +103,7 @@ poll_thread(UNUSED(void *arg)) struct queuepacket *qp; event_t *evt; - pclog("SLiRP: polling started.\n"); + INFO("SLiRP: thread started.\n"); thread_set_event(poll_state); /* Create a waitable event. */ @@ -123,10 +126,8 @@ poll_thread(UNUSED(void *arg)) if (QueuePeek(slirpq) != 0) { /* Grab a packet from the queue. */ qp = QueueDelete(slirpq); -#if 0 - pclog("SLiRP: inQ:%d got a %dbyte packet @%08lx\n", + DBGLOG(1, "SLiRP: inQ:%d got a %dbyte packet @%08lx\n", QueuePeek(slirpq), qp->len, qp); -#endif poll_card->rx(poll_card->priv, (uint8_t *)qp->data, qp->len); @@ -144,9 +145,9 @@ poll_thread(UNUSED(void *arg)) /* No longer needed. */ if (evt != NULL) thread_destroy_event(evt); - - pclog("SLiRP: polling stopped.\n"); thread_set_event(poll_state); + + INFO("SLiRP: thread stopped.\n"); } @@ -154,10 +155,10 @@ poll_thread(UNUSED(void *arg)) int net_slirp_init(void) { - pclog("SLiRP: initializing..\n"); + INFO("SLiRP: initializing..\n"); if (slirp_init() != 0) { - pclog("SLiRP could not be initialized!\n"); + ERRLOG("SLiRP could not be initialized!\n"); return(-1); } @@ -178,7 +179,6 @@ net_slirp_reset(const netcard_t *card, uint8_t *mac) /* Save the callback info. */ poll_card = card; - pclog("SLiRP: creating thread..\n"); poll_state = thread_create_event(); poll_tid = thread_create(poll_thread, mac); thread_wait_event(poll_state, -1); @@ -194,7 +194,7 @@ net_slirp_close(void) if (slirpq == NULL) return; - pclog("SLiRP: closing.\n"); + INFO("SLiRP: closing.\n"); /* Tell the polling thread to shut down. */ sl = slirpq; slirpq = NULL; @@ -204,9 +204,9 @@ net_slirp_close(void) network_busy(0); /* Wait for the thread to finish. */ - pclog("SLiRP: waiting for thread to end...\n"); + INFO("SLiRP: waiting for thread to end...\n"); thread_wait_event(poll_state, -1); - pclog("SLiRP: thread ended\n"); + INFO("SLiRP: thread ended\n"); thread_destroy_event(poll_state); poll_tid = NULL; @@ -217,6 +217,8 @@ net_slirp_close(void) /* OK, now shut down SLiRP itself. */ QueueDestroy(sl); slirp_exit(0); + + INFO("SLiRP: closed.\n"); } @@ -241,7 +243,7 @@ slirp_output(const uint8_t *pkt, int pkt_len) struct queuepacket *qp; if (slirpq != NULL) { - qp = (struct queuepacket *)malloc(sizeof(struct queuepacket)); + qp = (struct queuepacket *)mem_alloc(sizeof(struct queuepacket)); qp->len = pkt_len; memcpy(qp->data, pkt, pkt_len); QueueEnter(slirpq, qp); diff --git a/src/devices/network/net_wd80x3.c b/src/devices/network/net_wd80x3.c new file mode 100644 index 0000000..6178eb2 --- /dev/null +++ b/src/devices/network/net_wd80x3.c @@ -0,0 +1,1679 @@ +/* + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. + * + * This file is part of the VARCem Project. + * + * Implementation of the following network controllers: + * - SMC/WD 8003E (ISA 8-bit); + * - SMC/WD 8013EBT (ISA 16-bit); + * - SMC/WD 8013EP/A (MCA). + * + * Version: @(#)net_wd80x3.c 1.0.2 2018/10/05 + * + * Authors: Fred N. van Kempen, + * TheCollector1995, + * Miran Grca, + * + * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2016-2018 Miran Grca. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the: + * + * Free Software Foundation, Inc. + * 59 Temple Place - Suite 330 + * Boston, MA 02111-1307 + * USA. + */ +#include +#include +#include +#include +#include +#include +#define dbglog network_dev_log +#include "../../emu.h" +#include "../../io.h" +#include "../../mem.h" +#include "../../rom.h" +#include "../../random.h" +#include "../../device.h" +#include "../../ui/ui.h" +#include "../../plat.h" +#include "../system/mca.h" +#include "../system/pci.h" +#include "../system/pic.h" +#include "network.h" +#include "net_ne2000.h" +#include "net_dp8390.h" +#include "bswap.h" + + +enum { + WD8003E = 0, /* 8-bit ISA WD8003E */ + WD8013EBT, /* 16-bit ISA WD8013EBT */ + WD8013EPA /* MCA WD8013EP/A */ +}; + + +/* Board type codes in card ID */ +#define WE_WD8003 0x01 +#define WE_WD8003S 0x02 +#define WE_WD8003E 0x03 +#define WE_WD8013EBT 0x05 +#define WE_TOSHIBA1 0x11 /* named PCETA1 */ +#define WE_TOSHIBA2 0x12 /* named PCETA2 */ +#define WE_TOSHIBA3 0x13 /* named PCETB */ +#define WE_TOSHIBA4 0x14 /* named PCETC */ +#define WE_WD8003W 0x24 +#define WE_WD8003EB 0x25 +#define WE_WD8013W 0x26 +#define WE_WD8013EP 0x27 +#define WE_WD8013WC 0x28 +#define WE_WD8013EPC 0x29 +#define WE_SMC8216T 0x2a +#define WE_SMC8216C 0x2b +#define WE_WD8013EBP 0x2c + + +typedef struct { + const char *name; + int board; + uint32_t base_address; + int base_irq; + + mem_map_t ram_mapping; + + /* POS registers, MCA boards only */ + uint8_t pos_regs[8]; + + dp8390_t dp8390; + + uint32_t ram_addr, + ram_size; + + uint8_t macaddr[32]; /* ASIC ROM'd MAC address, even bytes */ + uint8_t maclocal[6]; /* configured MAC (local) address */ + + /* Memory for WD cards*/ + uint8_t reg1; + uint8_t reg5; + uint8_t if_chip; + uint8_t board_chip; +} nic_t; + + +static void wd_rx(void *, uint8_t *, int); +static void nic_tx(nic_t *, uint32_t); + + +static void +wd_interrupt(nic_t *dev, int set) +{ + if (set) + picint(1<base_irq); + else + picintc(1<base_irq); +} + + +/* reset - restore state to power-up, cancelling all i/o */ +static void +wd_reset(void *priv) +{ + nic_t *dev = (nic_t *)priv; + + DEBUG("%s: reset\n", dev->name); + + /* Initialize the MAC address area by doubling the physical address */ + dev->macaddr[0] = dev->dp8390.physaddr[0]; + dev->macaddr[1] = dev->dp8390.physaddr[1]; + dev->macaddr[2] = dev->dp8390.physaddr[2]; + dev->macaddr[3] = dev->dp8390.physaddr[3]; + dev->macaddr[4] = dev->dp8390.physaddr[4]; + dev->macaddr[5] = dev->dp8390.physaddr[5]; + + /* Zero out registers and memory */ + memset(&dev->dp8390.CR, 0x00, sizeof(dev->dp8390.CR) ); + memset(&dev->dp8390.ISR, 0x00, sizeof(dev->dp8390.ISR)); + memset(&dev->dp8390.IMR, 0x00, sizeof(dev->dp8390.IMR)); + memset(&dev->dp8390.DCR, 0x00, sizeof(dev->dp8390.DCR)); + memset(&dev->dp8390.TCR, 0x00, sizeof(dev->dp8390.TCR)); + memset(&dev->dp8390.TSR, 0x00, sizeof(dev->dp8390.TSR)); + memset(&dev->dp8390.RSR, 0x00, sizeof(dev->dp8390.RSR)); + dev->dp8390.tx_timer_active = 0; + dev->dp8390.local_dma = 0; + dev->dp8390.page_start = 0; + dev->dp8390.page_stop = 0; + dev->dp8390.bound_ptr = 0; + dev->dp8390.tx_page_start = 0; + dev->dp8390.num_coll = 0; + dev->dp8390.tx_bytes = 0; + dev->dp8390.fifo = 0; + dev->dp8390.remote_dma = 0; + dev->dp8390.remote_start = 0; + dev->dp8390.remote_bytes = 0; + dev->dp8390.tallycnt_0 = 0; + dev->dp8390.tallycnt_1 = 0; + dev->dp8390.tallycnt_2 = 0; + dev->dp8390.curr_page = 0; + dev->dp8390.rempkt_ptr = 0; + dev->dp8390.localpkt_ptr = 0; + dev->dp8390.address_cnt = 0; + + memset(&dev->dp8390.mem, 0x00, sizeof(dev->dp8390.mem)); + + /* Set power-up conditions */ + dev->dp8390.CR.stop = 1; + dev->dp8390.CR.rdma_cmd = 4; + dev->dp8390.ISR.reset = 1; + dev->dp8390.DCR.longaddr = 1; + + wd_interrupt(dev, 0); +} + + +static uint32_t +wd_chipmem_read(nic_t *dev, uint32_t addr, unsigned int len) +{ + uint32_t retval = 0; + + if ((len == 2) && (addr & 0x1)) { + DEBUG("%s: unaligned chipmem word read\n", dev->name); + } + + /* ROM'd MAC address */ + if (dev->board == WD8003E) { + if (addr <= 15) { + retval = dev->macaddr[addr % 16]; + if (len == 2) + retval |= (dev->macaddr[(addr + 1) % 16] << 8); + return(retval); + } + } + + return(0xff); +} + + +static uint32_t +wd_ram_read(uint32_t addr, unsigned len, void *priv) +{ + nic_t *dev = (nic_t *)priv; + uint32_t ret; + + if ((addr & 0x3fff) >= 0x2000) { + if (len == 2) + return 0xffff; + else if (len == 1) + return 0xff; + else + return 0xffffffff; + } + + ret = dev->dp8390.mem[addr & 0x1fff]; + + if (len == 2 || len == 4) + ret |= dev->dp8390.mem[(addr+1) & 0x1fff] << 8; + + if (len == 4) { + ret |= dev->dp8390.mem[(addr+2) & 0x1fff] << 16; + ret |= dev->dp8390.mem[(addr+3) & 0x1fff] << 24; + } + + return ret; +} + + +static uint8_t +wd_ram_readb(uint32_t addr, void *priv) +{ + nic_t *dev = (nic_t *)priv; + + return wd_ram_read(addr, 1, dev); +} + + +static uint16_t +wd_ram_readw(uint32_t addr, void *priv) +{ + nic_t *dev = (nic_t *)priv; + + return wd_ram_read(addr, 2, dev); +} + + +static uint32_t +wd_ram_readl(uint32_t addr, void *priv) +{ + nic_t *dev = (nic_t *)priv; + + return wd_ram_read(addr, 4, dev); +} + + +static void +wd_ram_write(uint32_t addr, uint32_t val, unsigned len, void *priv) +{ + nic_t *dev = (nic_t *)priv; + + if ((addr & 0x3fff) >= 0x2000) + return; + + dev->dp8390.mem[addr & 0x1fff] = val & 0xff; + if (len == 2 || len == 4) + dev->dp8390.mem[(addr+1) & 0x1fff] = val >> 8; + if (len == 4) { + dev->dp8390.mem[(addr+2) & 0x1fff] = val >> 16; + dev->dp8390.mem[(addr+3) & 0x1fff] = val >> 24; + } +} + + +static void +wd_ram_writeb(uint32_t addr, uint8_t val, void *priv) +{ + nic_t *dev = (nic_t *)priv; + + wd_ram_write(addr, val, 1, dev); +} + + +static void +wd_ram_writew(uint32_t addr, uint16_t val, void *priv) +{ + nic_t *dev = (nic_t *)priv; + + wd_ram_write(addr, val, 2, dev); +} + + +static void +wd_ram_writel(uint32_t addr, uint32_t val, void *priv) +{ + nic_t *dev = (nic_t *)priv; + + wd_ram_write(addr, val, 4, dev); +} + + +static uint32_t +wd_smc_read(nic_t *dev, uint32_t off) +{ + uint32_t sum; + uint32_t ret = 0; + + switch(off) { + case 0x00: + break; + + case 0x01: + if (dev->board == WD8003E) + ret = dev->dp8390.physaddr[0]; + if (dev->board == WD8013EPA) + ret = dev->reg1; + break; + + case 0x02: + if (dev->board == WD8003E) + ret = dev->dp8390.physaddr[1]; + break; + + case 0x03: + if (dev->board == WD8003E) + ret = dev->dp8390.physaddr[2]; + break; + + case 0x04: + if (dev->board == WD8003E) + ret = dev->dp8390.physaddr[3]; + break; + + case 0x05: + if (dev->board == WD8003E) + ret = dev->dp8390.physaddr[4]; + if (dev->board == WD8013EPA) + ret = dev->reg5; + break; + + case 0x06: + if (dev->board == WD8003E) + ret = dev->dp8390.physaddr[5]; + break; + + case 0x07: + if (dev->board == WD8013EPA) { + if (dev->if_chip != 0x35 && dev->if_chip != 0x3A) { + ret = 0; + break; + } + + ret = dev->if_chip; + } + break; + + case 0x08: + case 0x09: + case 0x0a: + case 0x0b: + case 0x0c: + case 0x0d: + ret = dev->dp8390.physaddr[off - 8]; + break; + + case 0x0e: + ret = dev->board_chip; + break; + + case 0x0f: + /*This has to return the byte that adds up to 0xFF*/ + sum = (dev->dp8390.physaddr[0] + \ + dev->dp8390.physaddr[1] + \ + dev->dp8390.physaddr[2] + \ + dev->dp8390.physaddr[3] + \ + dev->dp8390.physaddr[4] + \ + dev->dp8390.physaddr[5] + \ + dev->board_chip); + + ret = 0xff - (sum & 0xff); + break; + } + + DBGLOG(2, "%s: ASIC read addr=0x%02x, value=0x%04x\n", + dev->name, (unsigned)off, (unsigned)ret); + + return(ret); +} + + +static void +wd_smc_write(nic_t *dev, uint32_t off, uint32_t val) +{ + DBGLOG(2, "%s: ASIC write addr=0x%02x, value=0x%04x\n", + dev->name, (unsigned)off, (unsigned)val); + + switch(off) { + case 0x00: /* WD Control register */ + if (val & 0x80) { + dev->dp8390.ISR.reset = 1; + return; + } + + mem_map_disable(&dev->ram_mapping); + + if (val & 0x40) + mem_map_enable(&dev->ram_mapping); + break; + + case 0x01: + dev->reg1 = val; + break; + + case 0x04: + break; + + case 0x05: + dev->reg5 = val; + break; + + case 0x06: + break; + + case 0x07: + dev->if_chip = val; + break; + + default: + /* Invalid, but happens under Win95 device detection. */ + DEBUG("%s: ASIC write invalid address %04x, ignoring\n", + dev->name, (unsigned)off); + break; + } +} + + +/* Handle reads/writes to the 'zeroth' page of the DS8390 register file. */ +static uint8_t +page0_read(nic_t *dev, uint32_t off) +{ + uint8_t retval = 0; + + switch(off) { + case 0x01: /* CLDA0 */ + retval = (dev->dp8390.local_dma & 0xff); + break; + + case 0x02: /* CLDA1 */ + retval = (dev->dp8390.local_dma >> 8); + break; + + case 0x03: /* BNRY */ + retval = dev->dp8390.bound_ptr; + break; + + case 0x04: /* TSR */ + retval = ((dev->dp8390.TSR.ow_coll << 7) | + (dev->dp8390.TSR.cd_hbeat << 6) | + (dev->dp8390.TSR.fifo_ur << 5) | + (dev->dp8390.TSR.no_carrier << 4) | + (dev->dp8390.TSR.aborted << 3) | + (dev->dp8390.TSR.collided << 2) | + (dev->dp8390.TSR.tx_ok)); + break; + + case 0x05: /* NCR */ + retval = dev->dp8390.num_coll; + break; + + case 0x06: /* FIFO */ + /* reading FIFO is only valid in loopback mode */ + DEBUG("%s: reading FIFO not supported yet\n", dev->name); + retval = dev->dp8390.fifo; + break; + + case 0x07: /* ISR */ + retval = ((dev->dp8390.ISR.reset << 7) | + (dev->dp8390.ISR.rdma_done << 6) | + (dev->dp8390.ISR.cnt_oflow << 5) | + (dev->dp8390.ISR.overwrite << 4) | + (dev->dp8390.ISR.tx_err << 3) | + (dev->dp8390.ISR.rx_err << 2) | + (dev->dp8390.ISR.pkt_tx << 1) | + (dev->dp8390.ISR.pkt_rx)); + break; + + case 0x08: /* CRDA0 */ + retval = (dev->dp8390.remote_dma & 0xff); + break; + + case 0x09: /* CRDA1 */ + retval = (dev->dp8390.remote_dma >> 8); + break; + + case 0x0a: /* reserved */ + DEBUG("%s: reserved Page0 read - 0x0a\n", dev->name); + retval = 0xff; + break; + + case 0x0b: /* reserved */ + DEBUG("%s: reserved Page0 read - 0x0b\n", dev->name); + retval = 0xff; + break; + + case 0x0c: /* RSR */ + retval = ((dev->dp8390.RSR.deferred << 7) | + (dev->dp8390.RSR.rx_disabled << 6) | + (dev->dp8390.RSR.rx_mbit << 5) | + (dev->dp8390.RSR.rx_missed << 4) | + (dev->dp8390.RSR.fifo_or << 3) | + (dev->dp8390.RSR.bad_falign << 2) | + (dev->dp8390.RSR.bad_crc << 1) | + (dev->dp8390.RSR.rx_ok)); + break; + + case 0x0d: /* CNTR0 */ + retval = dev->dp8390.tallycnt_0; + break; + + case 0x0e: /* CNTR1 */ + retval = dev->dp8390.tallycnt_1; + break; + + case 0x0f: /* CNTR2 */ + retval = dev->dp8390.tallycnt_2; + break; + + default: + DEBUG("%s: Page0 register 0x%02x out of range\n", + dev->name, off); + break; + } + + DBGLOG(2, "%s: Page0 read from register 0x%02x, value=0x%02x\n", + dev->name, off, retval); + return(retval); +} + + +static void +page0_write(nic_t *dev, uint32_t off, uint8_t val) +{ + uint8_t val2; + + DBGLOG(2, "%s: Page0 write to register 0x%02x, value=0x%02x\n", + dev->name, off, val); + switch(off) { + case 0x01: /* PSTART */ + dev->dp8390.page_start = val; + break; + + case 0x02: /* PSTOP */ + dev->dp8390.page_stop = val; + break; + + case 0x03: /* BNRY */ + dev->dp8390.bound_ptr = val; + break; + + case 0x04: /* TPSR */ + dev->dp8390.tx_page_start = val; + break; + + case 0x05: /* TBCR0 */ + /* Clear out low byte and re-insert */ + dev->dp8390.tx_bytes &= 0xff00; + dev->dp8390.tx_bytes |= (val & 0xff); + break; + + case 0x06: /* TBCR1 */ + /* Clear out high byte and re-insert */ + dev->dp8390.tx_bytes &= 0x00ff; + dev->dp8390.tx_bytes |= ((val & 0xff) << 8); + break; + + case 0x07: /* ISR */ + val &= 0x7f; /* clear RST bit - status-only bit */ + /* All other values are cleared iff the ISR bit is 1 */ + dev->dp8390.ISR.pkt_rx &= !((int)((val & 0x01) == 0x01)); + dev->dp8390.ISR.pkt_tx &= !((int)((val & 0x02) == 0x02)); + dev->dp8390.ISR.rx_err &= !((int)((val & 0x04) == 0x04)); + dev->dp8390.ISR.tx_err &= !((int)((val & 0x08) == 0x08)); + dev->dp8390.ISR.overwrite &= !((int)((val & 0x10) == 0x10)); + dev->dp8390.ISR.cnt_oflow &= !((int)((val & 0x20) == 0x20)); + dev->dp8390.ISR.rdma_done &= !((int)((val & 0x40) == 0x40)); + val = ((dev->dp8390.ISR.rdma_done << 6) | + (dev->dp8390.ISR.cnt_oflow << 5) | + (dev->dp8390.ISR.overwrite << 4) | + (dev->dp8390.ISR.tx_err << 3) | + (dev->dp8390.ISR.rx_err << 2) | + (dev->dp8390.ISR.pkt_tx << 1) | + (dev->dp8390.ISR.pkt_rx)); + val &= ((dev->dp8390.IMR.rdma_inte << 6) | + (dev->dp8390.IMR.cofl_inte << 5) | + (dev->dp8390.IMR.overw_inte << 4) | + (dev->dp8390.IMR.txerr_inte << 3) | + (dev->dp8390.IMR.rxerr_inte << 2) | + (dev->dp8390.IMR.tx_inte << 1) | + (dev->dp8390.IMR.rx_inte)); + if (val == 0x00) + wd_interrupt(dev, 0); + break; + + case 0x08: /* RSAR0 */ + /* Clear out low byte and re-insert */ + dev->dp8390.remote_start &= 0xff00; + dev->dp8390.remote_start |= (val & 0xff); + dev->dp8390.remote_dma = dev->dp8390.remote_start; + break; + + case 0x09: /* RSAR1 */ + /* Clear out high byte and re-insert */ + dev->dp8390.remote_start &= 0x00ff; + dev->dp8390.remote_start |= ((val & 0xff) << 8); + dev->dp8390.remote_dma = dev->dp8390.remote_start; + break; + + case 0x0a: /* RBCR0 */ + /* Clear out low byte and re-insert */ + dev->dp8390.remote_bytes &= 0xff00; + dev->dp8390.remote_bytes |= (val & 0xff); + break; + + case 0x0b: /* RBCR1 */ + /* Clear out high byte and re-insert */ + dev->dp8390.remote_bytes &= 0x00ff; + dev->dp8390.remote_bytes |= ((val & 0xff) << 8); + break; + + case 0x0c: /* RCR */ + /* Check if the reserved bits are set */ + if (val & 0xc0) { + DEBUG("%s: RCR write, reserved bits set\n", dev->name); + } + + /* Set all other bit-fields */ + dev->dp8390.RCR.errors_ok = ((val & 0x01) == 0x01); + dev->dp8390.RCR.runts_ok = ((val & 0x02) == 0x02); + dev->dp8390.RCR.broadcast = ((val & 0x04) == 0x04); + dev->dp8390.RCR.multicast = ((val & 0x08) == 0x08); + dev->dp8390.RCR.promisc = ((val & 0x10) == 0x10); + dev->dp8390.RCR.monitor = ((val & 0x20) == 0x20); + + /* Monitor bit is a little suspicious... */ + if (val & 0x20) { + DEBUG("%s: RCR write, monitor bit set!\n", dev->name); + } + break; + + case 0x0d: /* TCR */ + /* Check reserved bits */ + if (val & 0xe0) { + DEBUG("%s: TCR write, reserved bits set\n", dev->name); + } + + /* Test loop mode (not supported) */ + if (val & 0x06) { + dev->dp8390.TCR.loop_cntl = (val & 0x6) >> 1; + DEBUG("%s: TCR write, loop mode %d not supported\n", + dev->name, dev->dp8390.TCR.loop_cntl); + } else { + dev->dp8390.TCR.loop_cntl = 0; + } + + /* Inhibit-CRC not supported. */ + if (val & 0x01) { + DEBUG("%s: TCR write, inhibit-CRC not supported\n", + dev->name); + } + + /* Auto-transmit disable very suspicious */ + if (val & 0x08) { + DEBUG("%s: TCR write, auto transmit disable not supported\n", + dev->name); + } + + /* Allow collision-offset to be set, although not used */ + dev->dp8390.TCR.coll_prio = ((val & 0x08) == 0x08); + break; + + case 0x0e: /* DCR */ + /* the loopback mode is not suppported yet */ + if (! (val & 0x08)) { + DEBUG("%s: DCR write, loopback mode selected\n", + dev->name); + } + + /* It is questionable to set longaddr and auto_rx, since + * they are not supported on the NE2000. Print a warning + * and continue. */ + if (val & 0x04) { + DEBUG("%s: DCR write - LAS set ???\n", dev->name); + } + if (val & 0x10) { + DEBUG("%s: DCR write - AR set ???\n", dev->name); + } + + /* Set other values. */ + dev->dp8390.DCR.wdsize = ((val & 0x01) == 0x01); + dev->dp8390.DCR.endian = ((val & 0x02) == 0x02); + dev->dp8390.DCR.longaddr = ((val & 0x04) == 0x04); /* illegal ? */ + dev->dp8390.DCR.loop = ((val & 0x08) == 0x08); + dev->dp8390.DCR.auto_rx = ((val & 0x10) == 0x10); /* also illegal ? */ + dev->dp8390.DCR.fifo_size = (val & 0x50) >> 5; + break; + + case 0x0f: /* IMR */ + /* Check for reserved bit */ + if (val & 0x80) { + DEBUG("%s: IMR write, reserved bit set\n",dev->name); + } + + /* Set other values */ + dev->dp8390.IMR.rx_inte = ((val & 0x01) == 0x01); + dev->dp8390.IMR.tx_inte = ((val & 0x02) == 0x02); + dev->dp8390.IMR.rxerr_inte = ((val & 0x04) == 0x04); + dev->dp8390.IMR.txerr_inte = ((val & 0x08) == 0x08); + dev->dp8390.IMR.overw_inte = ((val & 0x10) == 0x10); + dev->dp8390.IMR.cofl_inte = ((val & 0x20) == 0x20); + dev->dp8390.IMR.rdma_inte = ((val & 0x40) == 0x40); + val2 = ((dev->dp8390.ISR.rdma_done << 6) | + (dev->dp8390.ISR.cnt_oflow << 5) | + (dev->dp8390.ISR.overwrite << 4) | + (dev->dp8390.ISR.tx_err << 3) | + (dev->dp8390.ISR.rx_err << 2) | + (dev->dp8390.ISR.pkt_tx << 1) | + (dev->dp8390.ISR.pkt_rx)); + if (((val & val2) & 0x7f) == 0) + wd_interrupt(dev, 0); + else + wd_interrupt(dev, 1); + break; + + default: + DEBUG("%s: Page0 write, bad register 0x%02x\n", + dev->name, off); + break; + } +} + + +/* Handle reads/writes to the first page of the DS8390 register file. */ +static uint8_t +page1_read(nic_t *dev, uint32_t off) +{ + DBGLOG(2, "%s: Page1 read from register 0x%02x\n", dev->name, off); + + switch(off) { + case 0x01: /* PAR0-5 */ + case 0x02: + case 0x03: + case 0x04: + case 0x05: + case 0x06: + return(dev->dp8390.physaddr[off - 1]); + + case 0x07: /* CURR */ + DBGLOG(1, "%s: returning current page: 0x%02x\n", + dev->name, (dev->dp8390.curr_page)); + return(dev->dp8390.curr_page); + + case 0x08: /* MAR0-7 */ + case 0x09: + case 0x0a: + case 0x0b: + case 0x0c: + case 0x0d: + case 0x0e: + case 0x0f: + return(dev->dp8390.mchash[off - 8]); + + default: + DEBUG("%s: Page1 read register 0x%02x out of range\n", + dev->name, off); + return(0); + } +} + + +static void +page1_write(nic_t *dev, uint32_t off, uint8_t val) +{ + DBGLOG(2, "%s: Page1 write to register 0x%02x, value=0x%04x\n", + dev->name, off, val); + switch(off) { + case 0x01: /* PAR0-5 */ + case 0x02: + case 0x03: + case 0x04: + case 0x05: + case 0x06: + dev->dp8390.physaddr[off - 1] = val; + if (off == 6) { + DEBUG("%s: physical address set to %02x:%02x:%02x:%02x:%02x:%02x\n", + dev->name, + dev->dp8390.physaddr[0], dev->dp8390.physaddr[1], + dev->dp8390.physaddr[2], dev->dp8390.physaddr[3], + dev->dp8390.physaddr[4], dev->dp8390.physaddr[5]); + } + break; + + case 0x07: /* CURR */ + dev->dp8390.curr_page = val; + break; + + case 0x08: /* MAR0-7 */ + case 0x09: + case 0x0a: + case 0x0b: + case 0x0c: + case 0x0d: + case 0x0e: + case 0x0f: + dev->dp8390.mchash[off - 8] = val; + break; + + default: + DEBUG("%s: Page1 write register 0x%02x out of range\n", + dev->name, off); + break; + } +} + + +/* Handle reads/writes to the second page of the DS8390 register file. */ +static uint8_t +page2_read(nic_t *dev, uint32_t off) +{ + DBGLOG(2, "%s: Page2 read from register 0x%02x\n", dev->name, off); + + switch(off) { + case 0x01: /* PSTART */ + return(dev->dp8390.page_start); + + case 0x02: /* PSTOP */ + return(dev->dp8390.page_stop); + + case 0x03: /* Remote Next-packet pointer */ + return(dev->dp8390.rempkt_ptr); + + case 0x04: /* TPSR */ + return(dev->dp8390.tx_page_start); + + case 0x05: /* Local Next-packet pointer */ + return(dev->dp8390.localpkt_ptr); + + case 0x06: /* Address counter (upper) */ + return(dev->dp8390.address_cnt >> 8); + + case 0x07: /* Address counter (lower) */ + return(dev->dp8390.address_cnt & 0xff); + + case 0x08: /* Reserved */ + case 0x09: + case 0x0a: + case 0x0b: + DEBUG("%s: reserved Page2 read - register 0x%02x\n", + dev->name, off); + return(0xff); + + case 0x0c: /* RCR */ + return ((dev->dp8390.RCR.monitor << 5) | + (dev->dp8390.RCR.promisc << 4) | + (dev->dp8390.RCR.multicast << 3) | + (dev->dp8390.RCR.broadcast << 2) | + (dev->dp8390.RCR.runts_ok << 1) | + (dev->dp8390.RCR.errors_ok)); + + case 0x0d: /* TCR */ + return ((dev->dp8390.TCR.coll_prio << 4) | + (dev->dp8390.TCR.ext_stoptx << 3) | + ((dev->dp8390.TCR.loop_cntl & 0x3) << 1) | + (dev->dp8390.TCR.crc_disable)); + + case 0x0e: /* DCR */ + return (((dev->dp8390.DCR.fifo_size & 0x3) << 5) | + (dev->dp8390.DCR.auto_rx << 4) | + (dev->dp8390.DCR.loop << 3) | + (dev->dp8390.DCR.longaddr << 2) | + (dev->dp8390.DCR.endian << 1) | + (dev->dp8390.DCR.wdsize)); + + case 0x0f: /* IMR */ + return ((dev->dp8390.IMR.rdma_inte << 6) | + (dev->dp8390.IMR.cofl_inte << 5) | + (dev->dp8390.IMR.overw_inte << 4) | + (dev->dp8390.IMR.txerr_inte << 3) | + (dev->dp8390.IMR.rxerr_inte << 2) | + (dev->dp8390.IMR.tx_inte << 1) | + (dev->dp8390.IMR.rx_inte)); + + default: + DEBUG("%s: Page2 register 0x%02x out of range\n", + dev->name, off); + break; + } + + return(0); +} + + +#if 0 +static void +page2_write(nic_t *dev, uint32_t off, uint8_t val) +{ +/* Maybe all writes here should be BX_PANIC()'d, since they + affect internal operation, but let them through for now + and print a warning. */ + DBGLOG(2, "%s: Page2 write to register 0x%02x, value=0x%04x\n", + dev->name, off, val); + switch(off) { + case 0x01: /* CLDA0 */ + /* Clear out low byte and re-insert */ + dev->dp8390.local_dma &= 0xff00; + dev->dp8390.local_dma |= (val & 0xff); + break; + + case 0x02: /* CLDA1 */ + /* Clear out high byte and re-insert */ + dev->dp8390.local_dma &= 0x00ff; + dev->dp8390.local_dma |= ((val & 0xff) << 8); + break; + + case 0x03: /* Remote Next-pkt pointer */ + dev->dp8390.rempkt_ptr = val; + break; + + case 0x04: + DEBUG("page 2 write to reserved register 0x04\n"); + break; + + case 0x05: /* Local Next-packet pointer */ + dev->dp8390.localpkt_ptr = val; + break; + + case 0x06: /* Address counter (upper) */ + /* Clear out high byte and re-insert */ + dev->dp8390.address_cnt &= 0x00ff; + dev->dp8390.address_cnt |= ((val & 0xff) << 8); + break; + + case 0x07: /* Address counter (lower) */ + /* Clear out low byte and re-insert */ + dev->dp8390.address_cnt &= 0xff00; + dev->dp8390.address_cnt |= (val & 0xff); + break; + + case 0x08: + case 0x09: + case 0x0a: + case 0x0b: + case 0x0c: + case 0x0d: + case 0x0e: + case 0x0f: + DEBUG(3, "%s: Page2 write to reserved register 0x%02x\n", + dev->name, off); + break; + + default: + DEBUG(3, "%s: Page2 write, illegal register 0x%02x\n", + dev->name, off); + break; + } +} +#endif + + +/* Routines for handling reads/writes to the Command Register. */ +static uint8_t +read_cr(nic_t *dev) +{ + uint32_t retval; + + retval = (((dev->dp8390.CR.pgsel & 0x03) << 6) | + ((dev->dp8390.CR.rdma_cmd & 0x07) << 3) | + (dev->dp8390.CR.tx_packet << 2) | + (dev->dp8390.CR.start << 1) | + (dev->dp8390.CR.stop)); + + DBGLOG(1, "%s: read CR returns 0x%02x\n", dev->name, retval); + + return(retval); +} + + +static void +write_cr(nic_t *dev, uint8_t val) +{ + DBGLOG(1, "%s: wrote 0x%02x to CR\n", dev->name, val); + + /* Validate remote-DMA */ + if ((val & 0x38) == 0x00) { + DEBUG("%s: CR write - invalid rDMA value 0\n", dev->name); + val |= 0x20; /* dma_cmd == 4 is a safe default */ + } + + /* Check for s/w reset */ + if (val & 0x01) { + dev->dp8390.ISR.reset = 1; + dev->dp8390.CR.stop = 1; + } else { + dev->dp8390.CR.stop = 0; + } + + dev->dp8390.CR.rdma_cmd = (val & 0x38) >> 3; + + /* If start command issued, the RST bit in the ISR */ + /* must be cleared */ + if ((val & 0x02) && !dev->dp8390.CR.start) + dev->dp8390.ISR.reset = 0; + + dev->dp8390.CR.start = ((val & 0x02) == 0x02); + dev->dp8390.CR.pgsel = (val & 0xc0) >> 6; + + /* Check for send-packet command */ + if (dev->dp8390.CR.rdma_cmd == 3) { + /* Set up DMA read from receive ring */ + dev->dp8390.remote_start = dev->dp8390.remote_dma = dev->dp8390.bound_ptr * 256; + dev->dp8390.remote_bytes = (uint16_t) wd_chipmem_read(dev, dev->dp8390.bound_ptr * 256 + 2, 2); + DBGLOG(1, "%s: sending buffer #x%x length %d\n", + dev->name, dev->dp8390.remote_start, dev->dp8390.remote_bytes); + } + + /* Check for start-tx */ + if ((val & 0x04) && dev->dp8390.TCR.loop_cntl) { + if (dev->dp8390.TCR.loop_cntl) { + wd_rx(dev, &dev->dp8390.mem[dev->dp8390.tx_page_start*256 - DP8390_WORD_MEMSTART], + dev->dp8390.tx_bytes); + } + } else if (val & 0x04) { + if (dev->dp8390.CR.stop) { + if (dev->dp8390.tx_bytes == 0) /* njh@bandsman.co.uk */ { + return; /* Solaris9 probe */ + } + DEBUG("%s: CR write - tx start, dev in reset\n", dev->name); + } + + if (dev->dp8390.tx_bytes == 0) { + DEBUG("%s: CR write - tx start, tx bytes == 0\n", dev->name); + } + + /* Send the packet to the system driver */ + dev->dp8390.CR.tx_packet = 1; + + network_tx(dev->dp8390.mem, dev->dp8390.tx_bytes); + + nic_tx(dev, val); + } + + /* Linux probes for an interrupt by setting up a remote-DMA read + * of 0 bytes with remote-DMA completion interrupts enabled. + * Detect this here */ + if (dev->dp8390.CR.rdma_cmd == 0x01 && dev->dp8390.CR.start && dev->dp8390.remote_bytes == 0) { + dev->dp8390.ISR.rdma_done = 1; + if (dev->dp8390.IMR.rdma_inte) { + wd_interrupt(dev, 1); + wd_interrupt(dev, 0); + } + } +} + + +static uint8_t +wd_readb(uint16_t addr, void *priv) +{ + nic_t *dev = (nic_t *)priv; + int off = addr - dev->base_address; + uint8_t retval = 0; + + DBGLOG(2, "%s: read addr %x\n", dev->name, addr); + + if (off == 0x10) + retval = read_cr(dev); + else if (off >= 0x00 && off <= 0x0f) + retval = wd_smc_read(dev, off); + else switch(dev->dp8390.CR.pgsel) { + case 0x00: + retval = page0_read(dev, off - 0x10); + break; + + case 0x01: + retval = page1_read(dev, off - 0x10); + break; + + case 0x02: + retval = page2_read(dev, off - 0x10); + break; + + default: + DEBUG("%s: unknown value of pgsel in read - %d\n", + dev->name, dev->dp8390.CR.pgsel); + break; + } + + return(retval); +} + + +static void +wd_writeb(uint16_t addr, uint8_t val, void *priv) +{ + nic_t *dev = (nic_t *)priv; + int off = addr - dev->base_address; + + DBGLOG(2, "%s: write addr %x, value %x\n", dev->name, addr, val); + + if (off == 0x10) + write_cr(dev, val); + else if (off >= 0x00 && off <= 0x0f) + wd_smc_write(dev, off, val); + else switch(dev->dp8390.CR.pgsel) { + case 0x00: + page0_write(dev, off - 0x10, val); + break; + + case 0x01: + page1_write(dev, off - 0x10, val); + break; + + default: + DEBUG("%s: unknown value of pgsel in write - %d\n", + dev->name, dev->dp8390.CR.pgsel); + break; + } +} + + +static void +wd_ioset(nic_t *dev, uint16_t addr) +{ + io_sethandler(addr, 0x20, + wd_readb, NULL, NULL, wd_writeb, NULL, NULL, dev); +} + + +static void +wd_ioremove(nic_t *dev, uint16_t addr) +{ + io_removehandler(addr, 0x20, + wd_readb, NULL, NULL, wd_writeb, NULL, NULL, dev); +} + + +/* + * Called by the platform-specific code when an Ethernet frame + * has been received. The destination address is tested to see + * if it should be accepted, and if the RX ring has enough room, + * it is copied into it and the receive process is updated. + */ +static void +wd_rx(void *priv, uint8_t *buf, int io_len) +{ + static uint8_t bcast_addr[6] = {0xff,0xff,0xff,0xff,0xff,0xff}; + nic_t *dev = (nic_t *)priv; + uint8_t pkthdr[4]; + uint8_t *startptr; + int pages, avail; + int idx, nextpage; + int endbytes; + + //FIXME: move to upper layer + ui_sb_icon_update(SB_NETWORK, 1); + + if (io_len != 60) { + DBGLOG(1, "%s: rx_frame with length %d\n", dev->name, io_len); + } + + if ((dev->dp8390.CR.stop != 0) || (dev->dp8390.page_start == 0)) return; + + /* + * Add the pkt header + CRC to the length, and work + * out how many 256-byte pages the frame would occupy. + */ + pages = (io_len + sizeof(pkthdr) + sizeof(uint32_t) + 255)/256; + if (dev->dp8390.curr_page < dev->dp8390.bound_ptr) { + avail = dev->dp8390.bound_ptr - dev->dp8390.curr_page; + } else { + avail = (dev->dp8390.page_stop - dev->dp8390.page_start) - + (dev->dp8390.curr_page - dev->dp8390.bound_ptr); + } + + /* + * Avoid getting into a buffer overflow condition by + * not attempting to do partial receives. The emulation + * to handle this condition seems particularly painful. + */ + if ((avail < pages) +#if DP8390_NEVER_FULL_RING + || (avail == pages) +#endif + ) { + DEBUG("%s: no space\n", dev->name); + ui_sb_icon_update(SB_NETWORK, 0); + return; + } + + if ((io_len < 40/*60*/) && !dev->dp8390.RCR.runts_ok) { + DEBUG("%s: rejected small packet, length %d\n", dev->name, io_len); + ui_sb_icon_update(SB_NETWORK, 0); + return; + } + + /* Some computers don't care... */ + if (io_len < 60) + io_len = 60; + + DBGLOG(1, "%s: RX %x:%x:%x:%x:%x:%x > %x:%x:%x:%x:%x:%x len %d\n", + dev->name, buf[6], buf[7], buf[8], buf[9], buf[10], buf[11], + buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], io_len); + + /* Do address filtering if not in promiscuous mode. */ + if (! dev->dp8390.RCR.promisc) { + /* If this is a broadcast frame.. */ + if (! memcmp(buf, bcast_addr, 6)) { + /* Broadcast not enabled, we're done. */ + if (! dev->dp8390.RCR.broadcast) { + DEBUG("%s: RX BC disabled\n", dev->name); + ui_sb_icon_update(SB_NETWORK, 0); + return; + } + } + + /* If this is a multicast frame.. */ + else if (buf[0] & 0x01) { + /* Multicast not enabled, we're done. */ + if (! dev->dp8390.RCR.multicast) { + DEBUG("%s: RX MC disabled\n", dev->name); + ui_sb_icon_update(SB_NETWORK, 0); + return; + } + + /* Are we listening to this multicast address? */ + idx = mcast_index(buf); + if (! (dev->dp8390.mchash[idx>>3] & (1<<(idx&0x7)))) { + DEBUG("%s: RX MC not listed\n", dev->name); + ui_sb_icon_update(SB_NETWORK, 0); + return; + } + } + + /* Unicast, must be for us.. */ + else if (memcmp(buf, dev->dp8390.physaddr, 6)) return; + } else { + DBGLOG(1, "%s: RX promiscuous receive\n", dev->name); + } + + nextpage = dev->dp8390.curr_page + pages; + if (nextpage >= dev->dp8390.page_stop) + nextpage -= (dev->dp8390.page_stop - dev->dp8390.page_start); + + /* Set up packet header. */ + pkthdr[0] = 0x01; /* RXOK - packet is OK */ + pkthdr[1] = nextpage; /* ptr to next packet */ + pkthdr[2] = (io_len + sizeof(pkthdr))&0xff; /* length-low */ + pkthdr[3] = (io_len + sizeof(pkthdr))>>8; /* length-hi */ + DBGLOG(1, "%s: RX pkthdr [%02x %02x %02x %02x]\n", + dev->name, pkthdr[0], pkthdr[1], pkthdr[2], pkthdr[3]); + + /* Copy into buffer, update curpage, and signal interrupt if config'd */ + startptr = dev->dp8390.mem + (dev->dp8390.curr_page * 256); + memcpy(startptr, pkthdr, sizeof(pkthdr)); + if ((nextpage > dev->dp8390.curr_page) || + ((dev->dp8390.curr_page + pages) == dev->dp8390.page_stop)) { + memcpy(startptr+sizeof(pkthdr), buf, io_len); + } else { + endbytes = (dev->dp8390.page_stop - dev->dp8390.curr_page) * 256; + memcpy(startptr+sizeof(pkthdr), buf, endbytes-sizeof(pkthdr)); + startptr = dev->dp8390.mem + (dev->dp8390.page_start * 256); + memcpy(startptr, buf+endbytes-sizeof(pkthdr), io_len-endbytes+8); + } + dev->dp8390.curr_page = nextpage; + + dev->dp8390.RSR.rx_ok = 1; + dev->dp8390.RSR.rx_mbit = (buf[0] & 0x01) ? 1 : 0; + dev->dp8390.ISR.pkt_rx = 1; + + if (dev->dp8390.IMR.rx_inte) + wd_interrupt(dev, 1); + + ui_sb_icon_update(SB_NETWORK, 0); +} + + +static void +nic_tx(nic_t *dev, uint32_t val) +{ + dev->dp8390.CR.tx_packet = 0; + dev->dp8390.TSR.tx_ok = 1; + dev->dp8390.ISR.pkt_tx = 1; + + /* Generate an interrupt if not masked */ + if (dev->dp8390.IMR.tx_inte) + wd_interrupt(dev, 1); + + dev->dp8390.tx_timer_active = 0; +} + + +static uint8_t +wd_mca_read(int port, void *priv) +{ + nic_t *dev = (nic_t *)priv; + + return(dev->pos_regs[port & 7]); +} + + +static void +wd_mca_write(int port, uint8_t val, void *priv) +{ + nic_t *dev = (nic_t *)priv; + int8_t irqs[4] = { 3, 4, 10, 15 }; + uint32_t ram_size = 0; + + /* MCA does not write registers below 0x0100. */ + if (port < 0x0102) return; + + /* Save the MCA register value. */ + dev->pos_regs[port & 7] = val; + + wd_ioremove(dev, dev->base_address); + + dev->base_address = 0x800 + (((dev->pos_regs[2] & 0xf0) >> 4) * 0x1000); + dev->base_irq = irqs[(dev->pos_regs[5] & 0x0c) >> 2]; + + dev->ram_addr = 0xC0000 + ((dev->pos_regs[3] & 0x0f) * 0x2000) + ((dev->pos_regs[3] & 0x80) ? 0xF00000 : 0); + ram_size = (dev->pos_regs[3] & 0x10) ? 0x4000 : 0x2000; + + /* + * The PS/2 Model 80 BIOS always enables a card if it finds one, + * even if no resources were assigned yet (because we only added + * the card, but have not run AutoConfig yet...) + * + * So, remove current address, if any. + */ + + /* Initialize the device if fully configured. */ + if (dev->pos_regs[2] & 0x01) { + /* Card enabled; register (new) I/O handler. */ + wd_ioset(dev, dev->base_address); + + wd_reset(dev); + + mem_map_add(&dev->ram_mapping, dev->ram_addr, ram_size, + wd_ram_readb, wd_ram_readw, wd_ram_readl, + wd_ram_writeb, wd_ram_writew, wd_ram_writel, + NULL, MEM_MAPPING_EXTERNAL, dev); + + mem_map_disable(&dev->ram_mapping); + + INFO("%s: attached IO=0x%X IRQ=%d, RAM=0x%06X\n", + dev->name, dev->base_address, dev->base_irq, dev->ram_addr); + } +} + + +static void * +wd_init(const device_t *info) +{ + uint32_t mac; + nic_t *dev; + + dev = (nic_t *)mem_alloc(sizeof(nic_t)); + memset(dev, 0x00, sizeof(nic_t)); + dev->name = info->name; + dev->board = info->local; + + switch(dev->board) { + case WD8003E: + dev->board_chip = WE_WD8003E; + dev->maclocal[0] = 0x00; /* 00:00:C0 (WD/SMC OID) */ + dev->maclocal[1] = 0x00; + dev->maclocal[2] = 0xC0; + break; + + case WD8013EBT: + dev->board_chip = WE_WD8013EBT; + dev->maclocal[0] = 0x00; /* 00:00:C0 (WD/SMC OID) */ + dev->maclocal[1] = 0x00; + dev->maclocal[2] = 0xC0; + break; + + case WD8013EPA: + dev->board_chip = WE_WD8013EP | 0x80; + dev->maclocal[0] = 0x00; /* 00:00:C0 (WD/SMC OID) */ + dev->maclocal[1] = 0x00; + dev->maclocal[2] = 0xC0; + dev->pos_regs[0] = 0xC8; + dev->pos_regs[1] = 0x61; + break; + } + + if (dev->board != WD8013EPA) { + dev->base_address = device_get_config_hex16("base"); + dev->base_irq = device_get_config_int("irq"); + dev->ram_addr = device_get_config_hex20("ram_addr"); + } else { + mca_add(wd_mca_read, wd_mca_write, dev); + } + + /* See if we have a local MAC address configured. */ + mac = device_get_config_mac("mac", -1); + + /* + * Make this device known to the I/O system. + * PnP and PCI devices start with address spaces inactive. + */ + if (dev->board != WD8013EPA) + wd_ioset(dev, dev->base_address); + + /* Set up our BIA. */ + if (mac & 0xff000000) { + /* Generate new local MAC. */ + dev->maclocal[3] = random_generate(); + dev->maclocal[4] = random_generate(); + dev->maclocal[5] = random_generate(); + mac = (((int) dev->maclocal[3]) << 16); + mac |= (((int) dev->maclocal[4]) << 8); + mac |= ((int) dev->maclocal[5]); + device_set_config_mac("mac", mac); + } else { + dev->maclocal[3] = (mac>>16) & 0xff; + dev->maclocal[4] = (mac>>8) & 0xff; + dev->maclocal[5] = (mac & 0xff); + } + memcpy(dev->dp8390.physaddr, dev->maclocal, sizeof(dev->maclocal)); + + INFO("%s: I/O=%04x, IRQ=%d, MAC=%02x:%02x:%02x:%02x:%02x:%02x\n", + dev->name, dev->base_address, dev->base_irq, + dev->dp8390.physaddr[0], dev->dp8390.physaddr[1], + dev->dp8390.physaddr[2], dev->dp8390.physaddr[3], + dev->dp8390.physaddr[4], dev->dp8390.physaddr[5]); + + /* Reset the board. */ + if (dev->board != WD8013EPA) + wd_reset(dev); + + /* Attach ourselves to the network module. */ + network_attach(dev, dev->dp8390.physaddr, wd_rx); + + /* Map this system into the memory map. */ + if (dev->board != WD8013EPA) { + mem_map_add(&dev->ram_mapping, dev->ram_addr, 0x4000, + wd_ram_readb, NULL, NULL, + wd_ram_writeb, NULL, NULL, + NULL, MEM_MAPPING_EXTERNAL, dev); + mem_map_disable(&dev->ram_mapping); + + INFO("%s: attached IO=0x%X IRQ=%d, RAM addr=0x%06x\n", + dev->name, dev->base_address, dev->base_irq, dev->ram_addr); + } + + return(dev); +} + + +static void +wd_close(void *priv) +{ + nic_t *dev = (nic_t *)priv; + + /* Make sure the platform layer is shut down. */ + network_close(); + + wd_ioremove(dev, dev->base_address); + + DEBUG("%s: closed\n", dev->name); + + free(dev); +} + + +static const device_config_t wd8003_config[] = { + { + "base", "Address", CONFIG_HEX16, "", 0x300, + { + { + "0x240", 0x240 + }, + { + "0x280", 0x280 + }, + { + "0x300", 0x300 + }, + { + "0x380", 0x380 + }, + { + "" + } + }, + }, + { + "irq", "IRQ", CONFIG_SELECTION, "", 3, + { + { + "IRQ 2", 2 + }, + { + "IRQ 3", 3 + }, + { + "IRQ 5", 5 + }, + { + "IRQ 7", 7 + }, + { + "" + } + }, + }, + { + "mac", "MAC Address", CONFIG_MAC, "", -1 + }, + { + "ram_addr", "RAM address", CONFIG_HEX20, "", 0xD0000, + { + { + "C800", 0xC8000 + }, + { + "CC00", 0xCC000 + }, + { + "D000", 0xD0000 + }, + { + "D400", 0xD4000 + }, + { + "D800", 0xD8000 + }, + { + "DC00", 0xDC000 + }, + { + "" + } + }, + }, + { + "", "", -1 + } +}; + +static const device_config_t wd8013_config[] = { + { + "base", "Address", CONFIG_HEX16, "", 0x300, + { + { + "0x240", 0x240 + }, + { + "0x280", 0x280 + }, + { + "0x300", 0x300 + }, + { + "0x380", 0x380 + }, + { + "" + } + }, + }, + { + "irq", "IRQ", CONFIG_SELECTION, "", 3, + { + { + "IRQ 2", 2 + }, + { + "IRQ 3", 3 + }, + { + "IRQ 5", 5 + }, + { + "IRQ 7", 7 + }, + { + "IRQ 10", 10 + }, + { + "IRQ 11", 11 + }, + { + "IRQ 15", 15 + }, + { + "" + } + }, + }, + { + "mac", "MAC Address", CONFIG_MAC, "", -1 + }, + { + "ram_addr", "RAM address", CONFIG_HEX20, "", 0xD0000, + { + { + "C800", 0xC8000 + }, + { + "CC00", 0xCC000 + }, + { + "D000", 0xD0000 + }, + { + "D400", 0xD4000 + }, + { + "D800", 0xD8000 + }, + { + "DC00", 0xDC000 + }, + { + "" + } + }, + }, + { + "", "", -1 + } +}; + +static const device_config_t mca_config[] = { + { + "mac", "MAC Address", CONFIG_MAC, "", -1 + }, + { + "", "", -1 + } +}; + + +const device_t wd8003e_device = { + "Western Digital WD8003E", + DEVICE_ISA, + WD8003E, + wd_init, wd_close, NULL, + NULL, NULL, NULL, NULL, + wd8003_config +}; + +const device_t wd8013ebt_device = { + "Western Digital WD8013EBT", + DEVICE_ISA, + WD8013EBT, + wd_init, wd_close, NULL, + NULL, NULL, NULL, NULL, + wd8013_config +}; + +const device_t wd8013epa_device = { + "Western Digital WD8013EP/A", + DEVICE_MCA, + WD8013EPA, + wd_init, wd_close, NULL, + NULL, NULL, NULL, NULL, + mca_config +}; diff --git a/src/devices/network/net_wd80x3.h b/src/devices/network/net_wd80x3.h new file mode 100644 index 0000000..a334174 --- /dev/null +++ b/src/devices/network/net_wd80x3.h @@ -0,0 +1,44 @@ +/* + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. + * + * This file is part of the VARCem Project. + * + * Definitions for the WD80x3 ethernet controller. + * + * Version: @(#)net_wd80x3.h 1.0.1 2018/09/08 + * + * Author: Fred N. van Kempen, + * + * Copyright 2017,2018 Fred N. van Kempen. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the: + * + * Free Software Foundation, Inc. + * 59 Temple Place - Suite 330 + * Boston, MA 02111-1307 + * USA. + */ +#ifndef NET_WD8003_H +# define NET_WD8003_H + + +extern const device_t wd8003e_device; +extern const device_t wd8013ebt_device; +extern const device_t wd8013epa_device; + + +#endif /*NET_WD8003_H*/ diff --git a/src/devices/network/network.c b/src/devices/network/network.c index 085a467..fbaca43 100644 --- a/src/devices/network/network.c +++ b/src/devices/network/network.c @@ -12,7 +12,7 @@ * it should be malloc'ed and then linked to the NETCARD def. * Will be done later. * - * Version: @(#)network.c 1.0.11 2018/06/10 + * Version: @(#)network.c 1.0.12 2018/09/14 * * Author: Fred N. van Kempen, * @@ -58,29 +58,39 @@ # include #endif #define HAVE_STDARG_H +#define dbglog network_log #include "../../emu.h" #include "../../device.h" #include "../../ui/ui.h" #include "../../plat.h" #include "network.h" #include "net_ne2000.h" +#include "net_wd80x3.h" +#include "net_3com.h" static netcard_t net_cards[] = { - {"Disabled", "none", NULL, NULL}, - {"[ISA] Novell NE1000", "ne1k", &ne1000_device, NULL}, - {"[ISA] Novell NE2000", "ne2k", &ne2000_device, NULL}, - {"[ISA] Realtek RTL8019AS", "ne2kpnp", &rtl8019as_device, NULL}, - {"[PCI] Realtek RTL8029AS", "ne2kpci", &rtl8029as_device, NULL}, - {NULL, NULL, NULL, NULL} + { "none", NULL, NULL }, + + { "ne1k", &ne1000_device, NULL }, + { "ne2k", &ne2000_device, NULL }, + { "3c503", &tc503_device, NULL }, + { "ne2kpnp", &rtl8019as_device, NULL }, + { "wd8003e", &wd8003e_device, NULL }, + { "wd8013ebt", &wd8013ebt_device, NULL }, + + { "ne2", &ne2_mca_device, NULL }, + { "ne2_enext", &ne2_enext_mca_device, NULL }, + { "wd8013epa", &wd8013epa_device, NULL }, + + { "ne2kpci", &rtl8029as_device, NULL }, + + { NULL, NULL, NULL } }; /* Global variables. */ -int network_type; int network_ndev; -int network_card; -char network_pcap[512]; netdev_t network_devs[32]; #ifdef ENABLE_NETWORK_LOG int network_do_log = ENABLE_NETWORK_LOG; @@ -146,13 +156,28 @@ hexdump_p(char *ptr, uint8_t *bufp, int len) #endif -static void -net_log(int lvl, const char *fmt, ...) +void +network_log(int level, const char *fmt, ...) { #ifdef ENABLE_NETWORK_LOG va_list ap; - if (network_do_log >= lvl) { + if (network_do_log >= level) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +#endif +} + + +void +network_dev_log(int level, const char *fmt, ...) +{ +#ifdef ENABLE_NETWORK_DEV_LOG + va_list ap; + + if (network_dev_do_log >= level) { va_start(ap, fmt); pclog_ex(fmt, ap); va_end(ap); @@ -288,7 +313,7 @@ network_close(void) network_mutex = NULL; network_mac = NULL; - net_log(1, "NETWORK: closed.\n"); + INFO("NETWORK: closed.\n"); } @@ -306,11 +331,11 @@ network_reset(void) int i = -1; #ifdef ENABLE_NETWORK_LOG - pclog("NETWORK: reset (type=%d, card=%d) debug=%d\n", - network_type, network_card, network_do_log); + INFO("NETWORK: reset (type=%d, card=%d) debug=%d\n", + network_type, network_card, network_do_log); #else - pclog("NETWORK: reset (type=%d, card=%d)\n", - network_type, network_card); + INFO("NETWORK: reset (type=%d, card=%d)\n", + network_type, network_card); #endif ui_sb_icon_update(SB_NETWORK, 0); @@ -347,14 +372,14 @@ network_reset(void) return; } - net_log(0, "NETWORK: set up for %s, card='%s'\n", - (network_type==NET_TYPE_SLIRP)?"SLiRP":"Pcap", - net_cards[network_card].name); + INFO("NETWORK: set up for %s, card='%s'\n", + (network_type==NET_TYPE_SLIRP)?"SLiRP":"Pcap", + network_card_getname(network_card)); /* Add the (new?) card to the I/O system. */ if (net_cards[network_card].device) { - net_log(1, "NETWORK: adding device '%s'\n", - net_cards[network_card].name); + INFO("NETWORK: adding device '%s'\n", + network_card_getname(network_card)); device_add(net_cards[network_card].device); } } @@ -370,7 +395,7 @@ network_tx(uint8_t *bufp, int len) { char temp[8192]; hexdump_p(temp, bufp, len); - pclog("NETWORK: >> len=%d\n%s\n", len, temp); + DBGLOG(2, "NETWORK: >> len=%d\n%s\n", len, temp); } #endif @@ -418,7 +443,7 @@ network_available(void) int network_card_available(int card) { - if (net_cards[card].device) + if (net_cards[card].device != NULL) return(device_available(net_cards[card].device)); return(1); @@ -429,7 +454,10 @@ network_card_available(int card) const char * network_card_getname(int card) { - return(net_cards[card].name); + if (net_cards[card].device != NULL) + return(net_cards[card].device->name); + + return(NULL); } @@ -445,9 +473,10 @@ network_card_getdevice(int card) int network_card_has_config(int card) { - if (! net_cards[card].device) return(0); + if (net_cards[card].device != NULL) + return(net_cards[card].device->config ? 1 : 0); - return(net_cards[card].device->config ? 1 : 0); + return(0); } diff --git a/src/devices/network/network.h b/src/devices/network/network.h index 80daaa0..6d8468d 100644 --- a/src/devices/network/network.h +++ b/src/devices/network/network.h @@ -8,7 +8,7 @@ * * Definitions for the network module. * - * Version: @(#)network.h 1.0.4 2018/04/29 + * Version: @(#)network.h 1.0.5 2018/09/12 * * Author: Fred N. van Kempen, * @@ -50,17 +50,10 @@ /* Network provider types. */ -#define NET_TYPE_NONE 0 /* networking disabled */ -#define NET_TYPE_PCAP 1 /* use the (Win)Pcap API */ -#define NET_TYPE_SLIRP 2 /* use the SLiRP port forwarder */ - -/* Supported network cards. */ enum { - NONE = 0, - NE1000, - NE2000, - RTL8019AS, - RTL8029AS + NET_TYPE_NONE = 0, /* networking disabled */ + NET_TYPE_PCAP, /* use the (Win)Pcap API */ + NET_TYPE_SLIRP /* use the SLiRP port forwarder */ }; @@ -68,7 +61,6 @@ typedef void (*NETRXCB)(void *, uint8_t *, int); typedef struct { - const char *name; const char *internal_name; const device_t *device; void *priv; @@ -88,7 +80,7 @@ extern "C" { /* Global variables. */ extern int network_do_log, /* config */ - network_dev_log; + network_dev_do_log; extern int network_ndev; extern netdev_t network_devs[32]; @@ -117,6 +109,8 @@ extern int net_slirp_reset(const netcard_t *, uint8_t *); extern void net_slirp_close(void); extern void net_slirp_in(uint8_t *, int); +extern void network_log(int lvl, const char *fmt, ...); +extern void network_dev_log(int lvl, const char *fmt, ...); extern int network_dev_to_id(const char *); extern int network_card_available(int); extern const char *network_card_getname(int); diff --git a/src/devices/network/pcap_if.c b/src/devices/network/pcap_if.c index b8e777f..3479bb1 100644 --- a/src/devices/network/pcap_if.c +++ b/src/devices/network/pcap_if.c @@ -10,7 +10,7 @@ * * Based on the "libpcap" examples. * - * Version: @(#)pcap_if.c 1.0.4 2018/05/06 + * Version: @(#)pcap_if.c 1.0.5 2018/09/15 * * Author: Fred N. van Kempen, * @@ -57,6 +57,9 @@ #endif #include #include +#ifdef ERROR +# undef ERROR +#endif #include "../../emu.h" #include "../../plat.h" @@ -252,10 +255,12 @@ show_devs(capdev_t *list, int num) void -pclog(const char *fmt, ...) +pclog(int level, const char *fmt, ...) { va_list ap; + (void)level; + va_start(ap, fmt); vfprintf(stderr, fmt, ap); va_end(ap); diff --git a/src/devices/network/slirp/debug.c b/src/devices/network/slirp/debug.c index 503727a..e49a436 100644 --- a/src/devices/network/slirp/debug.c +++ b/src/devices/network/slirp/debug.c @@ -30,9 +30,7 @@ extern int slirp_tty_restore; void -debug_init(file, dbg) - char *file; - int dbg; +debug_init(char *file, int dbg) { /* Close the old debugging file */ if (dfd) @@ -57,9 +55,7 @@ debug_init(file, dbg) */ #ifdef SLIRP_DEBUG void -dump_packet(dat, n) - void *dat; - int n; +dump_packet(void *dat, int n) { u_char *pptr = (u_char *)dat; int j,k; @@ -86,8 +82,7 @@ dump_packet(dat, n) */ void -ttystats(ttyp) - struct ttys *ttyp; +ttystats(struct ttys *ttyp) { struct slirp_ifstats *is = &ttyp->ifstats; char buff[512]; @@ -125,7 +120,7 @@ ttystats(ttyp) } void -allttystats() +allttystats(void) { struct ttys *ttyp; @@ -135,7 +130,7 @@ allttystats() #endif void -ipstats() +ipstats(void) { lprint(" \r\n"); @@ -160,7 +155,7 @@ ipstats() #if 0 void -vjstats() +vjstats(void) { lprint(" \r\n"); @@ -178,7 +173,7 @@ vjstats() #endif void -tcpstats() +tcpstats(void) { lprint(" \r\n"); @@ -246,7 +241,7 @@ tcpstats() } void -udpstats() +udpstats(void) { lprint(" \r\n"); @@ -260,7 +255,7 @@ udpstats() } void -icmpstats() +icmpstats(void) { lprint(" \r\n"); lprint("ICMP stats:\r\n"); @@ -273,7 +268,7 @@ icmpstats() } void -mbufstats() +mbufstats(void) { struct SLIRPmbuf *m; int i; @@ -396,8 +391,7 @@ void purgesocks(void) #if 1 void -slirp_exit(exit_status) - int exit_status; +slirp_exit(int exit_status) { // struct ttys *ttyp; diff --git a/src/devices/network/slirp/if.c b/src/devices/network/slirp/if.c index 24f1b99..0f4ef4a 100644 --- a/src/devices/network/slirp/if.c +++ b/src/devices/network/slirp/if.c @@ -21,8 +21,7 @@ struct SLIRPmbuf *next_m; /* Pointer to next SLIRPmbuf to output */ #define ifs_init(ifm) ((ifm)->ifs_next = (ifm)->ifs_prev = (ifm)) void -ifs_insque(ifm, ifmhead) - struct SLIRPmbuf *ifm, *ifmhead; +ifs_insque(struct SLIRPmbuf *ifm, struct SLIRPmbuf *ifmhead) { ifm->ifs_next = ifmhead->ifs_next; ifmhead->ifs_next = ifm; @@ -31,15 +30,14 @@ ifs_insque(ifm, ifmhead) } void -ifs_remque(ifm) - struct SLIRPmbuf *ifm; +ifs_remque(struct SLIRPmbuf *ifm) { ifm->ifs_prev->ifs_next = ifm->ifs_next; ifm->ifs_next->ifs_prev = ifm->ifs_prev; } void -if_init() +if_init(void) { #if 0 /* @@ -70,10 +68,7 @@ if_init() * we don't expect any signals, but what the hell.. */ inline int -writen(fd, bptr, n) - int fd; - char *bptr; - int n; +writen(int fd, char *bptr, int n) { int ret; int total; @@ -102,8 +97,7 @@ writen(fd, bptr, n) */ #define INBUFF_SIZE 2048 /* XXX */ void -if_input(ttyp) - struct ttys *ttyp; +if_input(struct ttys *tty); { u_char if_inbuff[INBUFF_SIZE]; int if_n; @@ -157,9 +151,7 @@ if_input(ttyp) * it'll temporarily get downgraded to the batchq) */ void -if_output(so, ifm) - struct SLIRPsocket *so; - struct SLIRPmbuf *ifm; +if_output(struct SLIRPsocket *so, struct SLIRPmbuf *ifm) { struct SLIRPmbuf *ifq; int on_fastq = 1; diff --git a/src/devices/network/slirp/ip_icmp.c b/src/devices/network/slirp/ip_icmp.c index 2aead29..5a4ddde 100644 --- a/src/devices/network/slirp/ip_icmp.c +++ b/src/devices/network/slirp/ip_icmp.c @@ -66,9 +66,7 @@ static int icmp_flush[19] = { * Process a received ICMP message. */ void -icmp_input(m, hlen) - struct SLIRPmbuf *m; - int hlen; +icmp_input(struct SLIRPmbuf *m, int hlen) { register struct icmp *icp; register struct ip *ip=mtod(m, struct ip *); @@ -316,8 +314,7 @@ end_error: * Reflect the ip packet back to the source */ void -icmp_reflect(m) - struct SLIRPmbuf *m; +icmp_reflect(struct SLIRPmbuf *m) { register struct ip *ip = mtod(m, struct ip *); int hlen = ip->ip_hl << 2; diff --git a/src/devices/network/slirp/ip_input.c b/src/devices/network/slirp/ip_input.c index c2337f8..cd7ef4e 100644 --- a/src/devices/network/slirp/ip_input.c +++ b/src/devices/network/slirp/ip_input.c @@ -65,8 +65,7 @@ ip_init() * try to reassemble. Process options. Pass to next level. */ void -ip_input(m) - struct SLIRPmbuf *m; +ip_input(struct SLIRPmbuf *m) { register struct ip *ip; u_int hlen; @@ -233,9 +232,7 @@ bad: * is given as fp; otherwise have to make a chain. */ struct ip * -ip_reass(ip, fp) - register struct ipasfrag *ip; - register struct ipq *fp; +ip_reass(register struct ipasfrag *ip, register struct ipq *fp) { register struct SLIRPmbuf *m = dtom(ip); register struct ipasfrag *q; @@ -392,8 +389,7 @@ dropfrag: * associated datagrams. */ void -ip_freef(fp) - struct ipq *fp; +ip_freef(struct ipq *fp) { register struct ipasfrag *q, *p; @@ -412,8 +408,7 @@ ip_freef(fp) * Like insque, but pointers in middle of structure. */ void -ip_enq(p, prev) - register struct ipasfrag *p, *prev; +ip_enq(struct ipasfrag *p, struct ipasfrag *prev) { DEBUG_CALL("ip_enq"); DEBUG_ARG("prev = %lx", (long)prev); @@ -427,8 +422,7 @@ ip_enq(p, prev) * To ip_enq as remque is to insque. */ void -ip_deq(p) - register struct ipasfrag *p; +ip_deq(register struct ipasfrag *p) { ((struct ipasfrag *)(p->ipf_prev))->ipf_next = p->ipf_next; ((struct ipasfrag *)(p->ipf_next))->ipf_prev = p->ipf_prev; @@ -440,7 +434,7 @@ ip_deq(p) * queue, discard it. */ void -ip_slowtimo() +ip_slowtimo(void) { register struct ipq *fp; @@ -471,8 +465,7 @@ ip_slowtimo() #ifdef notdef int -ip_dooptions(m) - struct SLIRPmbuf *m; +ip_dooptions(struct SLIRPmbuf *m) { register struct ip *ip = mtod(m, struct ip *); register u_char *cp; @@ -675,9 +668,7 @@ bad: * (XXX) should be deleted; last arg currently ignored. */ void -ip_stripoptions(m, mopt) - struct SLIRPmbuf *m; - struct SLIRPmbuf *mopt; +ip_stripoptions(struct SLIRPmbuf *m, struct SLIRPmbuf *mopt) { register int i; struct ip *ip = mtod(m, struct ip *); diff --git a/src/devices/network/slirp/ip_output.c b/src/devices/network/slirp/ip_output.c index c3f243e..8ea4c3e 100644 --- a/src/devices/network/slirp/ip_output.c +++ b/src/devices/network/slirp/ip_output.c @@ -49,9 +49,7 @@ u_int16_t ip_id; * The SLIRPmbuf opt, if present, will not be freed. */ int -ip_output(so, m0) - struct SLIRPsocket *so; - struct SLIRPmbuf *m0; +ip_output(struct SLIRPsocket *so, struct SLIRPmbuf *m0) { struct ip *ip; struct SLIRPmbuf *m = m0; diff --git a/src/devices/network/slirp/mbuf.c b/src/devices/network/slirp/mbuf.c index c7f3f3f..91e5872 100644 --- a/src/devices/network/slirp/mbuf.c +++ b/src/devices/network/slirp/mbuf.c @@ -27,14 +27,14 @@ int mbuf_max = 0; size_t msize; void -m_init() +m_init(void) { m_freelist.m_next = m_freelist.m_prev = &m_freelist; m_usedlist.m_next = m_usedlist.m_prev = &m_usedlist; msize_init(); } -void msize_init() +void msize_init(void) { /* * Find a nice value for msize @@ -52,7 +52,7 @@ void msize_init() * free old mbufs, we mark all mbufs above mbuf_thresh as M_DOFREE, * which tells m_free to actually free() it */ -struct SLIRPmbuf * m_get() +struct SLIRPmbuf * m_get(void) { struct SLIRPmbuf *m; int flags = 0; @@ -89,8 +89,7 @@ end_error: //For some reason this fails in GDB saying tehre is no m_flags member void -m_free(m) - struct SLIRPmbuf *m; +m_free(struct SLIRPmbuf *m) { DEBUG_CALL("m_free"); @@ -126,8 +125,7 @@ m_free(m) * an M_EXT data segment */ void -m_cat(m, n) - struct SLIRPmbuf *m, *n; +m_cat(struct SLIRPmbuf *m, struct SLIRPmbuf *n) { /* * If there's no room, realloc @@ -144,9 +142,7 @@ m_cat(m, n) /* make m size bytes large */ void -m_inc(m, size) - struct SLIRPmbuf *m; - int size; +m_inc(struct SLIRPmbuf *m, int size) { int datasize; @@ -181,9 +177,7 @@ m_inc(m, size) void -m_adj(m, len) - struct SLIRPmbuf *m; - int len; +m_adj(struct SLIRPmbuf *m, int len) { if (m == NULL) return; @@ -203,9 +197,7 @@ m_adj(m, len) * Copy len bytes from m, starting off bytes into n */ int -m_copy(n, m, off, len) - struct SLIRPmbuf *n, *m; - int off, len; +m_copy(struct SLIRPmbuf *n, struct SLIRPmbuf *m, int off, int len) { if (len > M_FREEROOM(n)) return -1; @@ -222,8 +214,7 @@ m_copy(n, m, off, len) * Fortunately, it's not used often */ struct SLIRPmbuf * -dtom(dat) - void *dat; +dtom(void *dat) { struct SLIRPmbuf *m; diff --git a/src/devices/network/slirp/sbuf.c b/src/devices/network/slirp/sbuf.c index b9baa41..f457e6c 100644 --- a/src/devices/network/slirp/sbuf.c +++ b/src/devices/network/slirp/sbuf.c @@ -17,16 +17,13 @@ */ void -sbfree(sb) - struct sbuf *sb; +sbfree(struct sbuf *sb) { free(sb->sb_data); } void -sbdrop(sb, num) - struct sbuf *sb; - int num; +sbdrop(struct sbuf *sb, int num) { /* * We can only drop how much we have @@ -42,9 +39,7 @@ sbdrop(sb, num) } void -sbreserve(sb, size) - struct sbuf *sb; - int size; +sbreserve(struct sbuf *sb, int size) { if (sb->sb_data) { /* Already alloced, realloc if necessary */ @@ -73,9 +68,7 @@ sbreserve(sb, size) * (the socket is non-blocking, so we won't hang) */ void -sbappend(so, m) - struct SLIRPsocket *so; - struct SLIRPmbuf *m; +sbappend(struct SLIRPsocket *so, struct SLIRPmbuf *m) { int ret = 0; @@ -135,9 +128,7 @@ sbappend(so, m) * The caller is responsible to make sure there's enough room */ void -sbappendsb(sb, m) - struct sbuf *sb; - struct SLIRPmbuf *m; +sbappendsb(struct sbuf *sb, struct SLIRPmbuf *m) { int len, n, nn; @@ -174,11 +165,7 @@ sbappendsb(sb, m) * done in sbdrop when the data is acked */ void -sbcopy(sb, off, len, to) - struct sbuf *sb; - int off; - int len; - char *to; +sbcopy(struct sbuf *sb, int off, int len, char *to) { char *from; diff --git a/src/devices/network/slirp/slirp.c b/src/devices/network/slirp/slirp.c index 7457f13..fff95ab 100644 --- a/src/devices/network/slirp/slirp.c +++ b/src/devices/network/slirp/slirp.c @@ -26,11 +26,9 @@ struct ex_list *exec_list; fd_set *global_readfds, *global_writefds, *global_xfds; -extern void pclog(const char *, ...); +extern void pclog(int level, const char *, ...); extern int config_get_int(char *, char *, int); -#define printf pclog - #ifdef _WIN32 static int get_dns_addr(struct in_addr *pdns_addr) @@ -49,11 +47,11 @@ static int get_dns_addr(struct in_addr *pdns_addr) GlobalFree(FixedInfo); FixedInfo = NULL; } - FixedInfo = GlobalAlloc(GPTR, BufLen); + FixedInfo = (FIXED_INFO *)GlobalAlloc(GPTR, BufLen); } if ((ret = GetNetworkParams(FixedInfo, &BufLen)) != ERROR_SUCCESS) { - printf("GetNetworkParams failed. ret = %08x\n", (u_int)ret ); + pclog(0, "GetNetworkParams failed. ret = %08x\n", (u_int)ret ); if (FixedInfo) { GlobalFree(FixedInfo); FixedInfo = NULL; @@ -64,9 +62,9 @@ static int get_dns_addr(struct in_addr *pdns_addr) pIPAddr = &(FixedInfo->DnsServerList); inet_aton(pIPAddr->IpAddress.String, &tmp_addr); *pdns_addr = tmp_addr; - printf( " DNS Servers:\n" ); + pclog(1, " DNS Servers:\n" ); while ( pIPAddr ) { - printf( " Address: %s\n", pIPAddr ->IpAddress.String ); + pclog(1, " Address: %s\n", pIPAddr ->IpAddress.String ); pIPAddr = pIPAddr ->Next; } if (FixedInfo) { @@ -134,7 +132,7 @@ slirp_init(void) int i = 0, udp, from, to; int rc; - pclog("%s initializing..\n", category); + pclog(1, "%s initializing..\n", category); #ifdef SLIRP_DEBUG // debug_init("/tmp/slirp.log", DEBUG_DEFAULT); @@ -182,9 +180,9 @@ debug_init("slirplog.txt",DEBUG_DEFAULT); rc = slirp_redir(udp, from, myaddr, to); if (rc == 0) - pclog("slirp redir %d -> %d successful\n", from, to); + pclog(1, "slirp redir %d -> %d successful\n", from, to); else - pclog("slirp redir %d -> %d failed (%d)\n", from, to, rc); + pclog(1, "slirp redir %d -> %d failed (%d)\n", from, to, rc); i++; } diff --git a/src/devices/network/slirp/slirp.h b/src/devices/network/slirp/slirp.h index 02b7d16..ad2678a 100644 --- a/src/devices/network/slirp/slirp.h +++ b/src/devices/network/slirp/slirp.h @@ -132,8 +132,8 @@ #undef HAVE_SYS_TYPES32_H /* Define if you have */ #ifdef _WIN32 +# include # ifdef __GNUC__ /* MINGW? */ -# include typedef uint8_t u_int8_t; typedef uint16_t u_int16_t; typedef uint32_t u_int32_t; @@ -143,14 +143,14 @@ typedef int socklen_t; typedef unsigned long ioctlsockopt_t; # else typedef unsigned char u_int8_t; -typedef char int8_t; -typedef unsigned char uint8_t; +//typedef char int8_t; +//typedef unsigned char uint8_t; typedef unsigned short u_int16_t; -typedef unsigned short uint16_t; -typedef short int16_t; +//typedef unsigned short uint16_t; +//typedef short int16_t; typedef unsigned int u_int32_t; -typedef unsigned int uint32_t; -typedef int int32_t; +//typedef unsigned int uint32_t; +//typedef int int32_t; typedef unsigned __int64 u_int64_t; typedef char *SLIRPcaddr_t; diff --git a/src/devices/network/slirp/slirp_misc.c b/src/devices/network/slirp/slirp_misc.c index ae86bb3..e4ff90f 100644 --- a/src/devices/network/slirp/slirp_misc.c +++ b/src/devices/network/slirp/slirp_misc.c @@ -73,9 +73,7 @@ redir_x(inaddr, start_port, display, screen) #ifndef HAVE_INET_ATON int -inet_aton(cp, ia) - const char *cp; - struct in_addr *ia; +inet_aton(const char *cp, struct in_addr *ia) { u_int32_t addr = inet_addr(cp); if (addr == 0xffffffff) @@ -86,14 +84,12 @@ inet_aton(cp, ia) #endif -extern void pclog(char *fmt, ...); - - +extern void pclog(int, const char *, ...); /* * Get our IP address and put it in our_addr */ void -getouraddr() +getouraddr(void) { char buff[512]; struct hostent *he = NULL; @@ -122,7 +118,7 @@ getouraddr() our_addr.s_addr = loopback_addr.s_addr; #endif #undef ANCIENT - pclog(" Our IP address: %s (%s)\n", inet_ntoa(our_addr), buff); + pclog(1, " Our IP address: %s (%s)\n", inet_ntoa(our_addr), buff); } //#if SIZEOF_CHAR_P == 8 @@ -134,9 +130,7 @@ struct quehead_32 { }; inline void -insque_32(a, b) - void *a; - void *b; +insque_32(void *a, void *b) { register struct quehead_32 *element = (struct quehead_32 *) a; register struct quehead_32 *head = (struct quehead_32 *) b; @@ -148,8 +142,7 @@ insque_32(a, b) } inline void -remque_32(a) - void *a; +remque_32(void *a) { register struct quehead_32 *element = (struct quehead_32 *) a; ((struct quehead_32 *)(element->qh_link))->qh_rlink = element->qh_rlink; @@ -166,8 +159,7 @@ struct quehead { }; void -insque(a, b) - void *a, *b; +insque(void *a, void *b) { register struct quehead *element = (struct quehead *) a; register struct quehead *head = (struct quehead *) b; @@ -179,8 +171,7 @@ insque(a, b) } void -remque(a) - void *a; +remque(void *a) { register struct quehead *element = (struct quehead *) a; ((struct quehead *)(element->qh_link))->qh_rlink = element->qh_rlink; @@ -193,12 +184,7 @@ remque(a) int -add_exec(ex_ptr, do_pty, exec, addr, port) - struct ex_list **ex_ptr; - int do_pty; - char *exec; - int addr; - int port; +add_exec(struct ex_list **ex_ptr, int do_pty, char *exec, int addr, int port) { struct ex_list *tmp_ptr; @@ -224,8 +210,7 @@ add_exec(ex_ptr, do_pty, exec, addr, port) * For systems with no strerror */ char * -SLIRPstrerror(error) - int error; +SLIRPstrerror(int error) { if (error < sys_nerr) return sys_errlist[error]; @@ -239,10 +224,7 @@ SLIRPstrerror(error) #ifdef _WIN32 int -fork_exec(so, ex, do_pty) - struct SLIRPsocket *so; - char *ex; - int do_pty; +fork_exec(struct SLIRPsocket *so, char *ex, int do_pty) { /* not implemented */ return 0; @@ -251,8 +233,7 @@ fork_exec(so, ex, do_pty) #else int -slirp_openpty(amaster, aslave) - int *amaster, *aslave; +slirp_openpty(int *amaster, int *aslave) { register int master, slave; @@ -327,10 +308,7 @@ slirp_openpty(amaster, aslave) * do_ptr = 2 Fork/exec using pty */ int -fork_exec(so, ex, do_pty) - struct SLIRPsocket *so; - char *ex; - int do_pty; +fork_exec(struct SLIRPsocket *so, char *ex, int do_pty) { int s; struct sockaddr_in addr; @@ -499,8 +477,7 @@ char * strdup(char *str) #if 0 void -snooze_hup(num) - int num; +snooze_hup(int num) { int s, ret; #ifndef NO_UNIX_SOCKETS @@ -541,7 +518,7 @@ snooze_hup(num) void -snooze() +snooze(void) { sigset_t s; int i; @@ -566,8 +543,7 @@ snooze() } void -relay(s) - int s; +relay(int s) { char buf[8192]; int n; @@ -699,8 +675,7 @@ lprint(va_alist) va_dcl } void -add_emu(buff) - char *buff; +add_emu(char *buff) { u_int lport, fport; u_int8_t tos = 0, emu = 0; @@ -793,10 +768,7 @@ add_emu(buff) */ int -vsprintf_len(string, format, args) - char *string; - const char *format; - va_list args; +vsprintf_len(char *string, const char *format, va_list args) { vsprintf(string, format, args); return strlen(string); @@ -826,8 +798,7 @@ sprintf_len(va_alist) va_dcl #endif void -u_sleep(usec) - int usec; +u_sleep(int usec) { struct timeval t; fd_set fdset; @@ -845,8 +816,7 @@ u_sleep(usec) */ void -fd_nonblock(fd) - int fd; +fd_nonblock(int fd) { #if defined USE_FIONBIO && defined FIONBIO ioctlsockopt_t opt = 1; @@ -862,8 +832,7 @@ fd_nonblock(fd) } void -fd_block(fd) - int fd; +fd_block(int fd) { #if defined USE_FIONBIO && defined FIONBIO ioctlsockopt_t opt = 0; diff --git a/src/devices/network/slirp/socket.c b/src/devices/network/slirp/socket.c index db27bdf..6b36930 100644 --- a/src/devices/network/slirp/socket.c +++ b/src/devices/network/slirp/socket.c @@ -22,19 +22,18 @@ #endif void -so_init() +so_init(void) { /* Nothing yet */ } struct SLIRPsocket * -solookup(head, laddr, lport, faddr, fport) - struct SLIRPsocket *head; - struct in_addr laddr; - u_int lport; - struct in_addr faddr; - u_int fport; +solookup(struct SLIRPsocket *head, + struct in_addr laddr, + u_int lport, + struct in_addr faddr, + u_int fport) { struct SLIRPsocket *so; @@ -58,7 +57,7 @@ solookup(head, laddr, lport, faddr, fport) * insque() it into the correct linked-list */ struct SLIRPsocket * -socreate() +socreate(void) { struct SLIRPsocket *so; @@ -75,11 +74,10 @@ socreate() * remque and free a socket, clobber cache */ void -sofree(so) - struct SLIRPsocket *so; +sofree(struct SLIRPsocket *so) { if (so->so_emu==EMU_RSH && so->extra) { - sofree(so->extra); + sofree((struct SLIRPsocket *)so->extra); so->extra=NULL; } if (so == tcp_last_so) @@ -102,8 +100,7 @@ sofree(so) * a read() of 0 (or less) means it's disconnected */ int -soread(so) - struct SLIRPsocket *so; +soread(struct SLIRPsocket *so) { int n, nn, lss, total; struct sbuf *sb = &so->so_snd; @@ -217,8 +214,7 @@ soread(so) * in the send buffer is sent as urgent data */ void -sorecvoob(so) - struct SLIRPsocket *so; +sorecvoob(struct SLIRPsocket *so) { struct tcpcb *tp = sototcpcb(so); @@ -245,8 +241,7 @@ sorecvoob(so) * There's a lot duplicated code here, but... */ int -sosendoob(so) - struct SLIRPsocket *so; +sosendoob(struct SLIRPsocket *so) { struct sbuf *sb = &so->so_rcv; char buff[2048]; /* XXX Shouldn't be sending more oob data than this */ @@ -304,8 +299,7 @@ sosendoob(so) * updating all sbuf field as necessary */ int -sowrite(so) - struct SLIRPsocket *so; +sowrite(struct SLIRPsocket *so) { int n,nn; struct sbuf *sb = &so->so_rcv; @@ -397,8 +391,7 @@ sowrite(so) * recvfrom() a UDP socket */ void -sorecvfrom(so) - struct SLIRPsocket *so; +sorecvfrom(struct SLIRPsocket *so) { struct sockaddr_in addr; socklen_t addrlen = sizeof(struct sockaddr_in); @@ -498,9 +491,7 @@ sorecvfrom(so) * sendto() a socket */ int -sosendto(so, m) - struct SLIRPsocket *so; - struct SLIRPmbuf *m; +sosendto(struct SLIRPsocket *so, struct SLIRPmbuf *m) { int ret; struct sockaddr_in addr; @@ -547,11 +538,7 @@ sosendto(so, m) * XXX This should really be tcp_listen */ struct SLIRPsocket * -solisten(port, laddr, lport, flags) - u_int port; - u_int32_t laddr; - u_int lport; - int flags; +solisten(u_int port, u_int32_t laddr, u_int lport, int flags) { struct sockaddr_in addr; struct SLIRPsocket *so; @@ -631,8 +618,7 @@ solisten(port, laddr, lport, flags) * XXX not yet... */ void -sorwakeup(so) - struct SLIRPsocket *so; +sorwakeup(struct SLIRPsocket *so) { /* sowrite(so); */ /* FD_CLR(so->s,&writefds); */ @@ -644,8 +630,7 @@ sorwakeup(so) * For now, don't read, it'll be done in the main loop */ void -sowwakeup(so) - struct SLIRPsocket *so; +sowwakeup(struct SLIRPsocket *so) { /* Nothing, yet */ } @@ -657,8 +642,7 @@ sowwakeup(so) * times each when only 1 was needed */ void -soisfconnecting(so) - register struct SLIRPsocket *so; +soisfconnecting(register struct SLIRPsocket *so) { so->so_state &= ~(SS_NOFDREF|SS_ISFCONNECTED|SS_FCANTRCVMORE| SS_FCANTSENDMORE|SS_FWDRAIN); @@ -666,16 +650,14 @@ soisfconnecting(so) } void -soisfconnected(so) - register struct SLIRPsocket *so; +soisfconnected(register struct SLIRPsocket *so) { so->so_state &= ~(SS_ISFCONNECTING|SS_FWDRAIN|SS_NOFDREF); so->so_state |= SS_ISFCONNECTED; /* Clobber other states */ } void -sofcantrcvmore(so) - struct SLIRPsocket *so; +sofcantrcvmore(struct SLIRPsocket *so) { if ((so->so_state & SS_NOFDREF) == 0) { shutdown(so->s,0); @@ -691,8 +673,7 @@ sofcantrcvmore(so) } void -sofcantsendmore(so) - struct SLIRPsocket *so; +sofcantsendmore(struct SLIRPsocket *so) { if ((so->so_state & SS_NOFDREF) == 0) { shutdown(so->s,1); /* send FIN to fhost */ @@ -711,8 +692,7 @@ sofcantsendmore(so) } void -soisfdisconnected(so) - struct SLIRPsocket *so; +soisfdisconnected(struct SLIRPsocket *so) { /* so->so_state &= ~(SS_ISFCONNECTING|SS_ISFCONNECTED); */ /* close(so->s); */ @@ -727,8 +707,7 @@ soisfdisconnected(so) * Set CANTSENDMORE once all data has been write()n */ void -sofwdrain(so) - struct SLIRPsocket *so; +sofwdrain(struct SLIRPsocket *so) { if (so->so_rcv.sb_cc) so->so_state |= SS_FWDRAIN; diff --git a/src/devices/network/slirp/tcp_input.c b/src/devices/network/slirp/tcp_input.c index 9718778..e0c2751 100644 --- a/src/devices/network/slirp/tcp_input.c +++ b/src/devices/network/slirp/tcp_input.c @@ -110,10 +110,7 @@ tcp_seq tcp_iss; /* tcp initial send seq # */ #endif int -tcp_reass(tp, ti, m) - struct tcpcb *tp; - struct tcpiphdr *ti; - struct SLIRPmbuf *m; +tcp_reass(struct tcpcb *tp, struct tcpiphdr *ti, struct SLIRPmbuf *m) { struct tcpiphdr *q; struct SLIRPsocket *so = tp->t_socket; @@ -229,10 +226,7 @@ present: * protocol specification dated September, 1981 very closely. */ void -tcp_input(m, iphlen, inso) - struct SLIRPmbuf *m; - int iphlen; - struct SLIRPsocket *inso; +tcp_input(struct SLIRPmbuf *m, int iphlen, struct SLIRPsocket *inso) { struct ip save_ip, *ip; struct tcpiphdr *ti; @@ -1487,11 +1481,7 @@ drop: * u_int32_t *ts_val, *ts_ecr; */ void -tcp_dooptions(tp, cp, cnt, ti) - struct tcpcb *tp; - u_char *cp; - int cnt; - struct tcpiphdr *ti; +tcp_dooptions(struct tcpcb *tp, u_char *cp, int cnt, struct tcpiphdr *ti) { u_int16_t mss; int opt, optlen; @@ -1568,10 +1558,7 @@ tcp_dooptions(tp, cp, cnt, ti) #ifdef notdef void -tcp_pulloutofband(so, ti, m) - struct SLIRPsocket *so; - struct tcpiphdr *ti; - struct SLIRPmbuf *m; +tcp_pulloutofband(struct SLIRPsocket *so, struct tcpiphdr *ti, struct SLIRPmbuf *m) { int cnt = ti->ti_urp - 1; @@ -1602,9 +1589,7 @@ tcp_pulloutofband(so, ti, m) */ void -tcp_xmit_timer(tp, rtt) - struct tcpcb *tp; - int rtt; +tcp_xmit_timer(struct tcpcb *tp, int rtt) { short delta; @@ -1692,9 +1677,7 @@ tcp_xmit_timer(tp, rtt) */ int -tcp_mss(tp, offer) - struct tcpcb *tp; - u_int offer; +tcp_mss(struct tcpcb *tp, u_int offer) { struct SLIRPsocket *so = tp->t_socket; int mss; diff --git a/src/devices/network/slirp/tcp_output.c b/src/devices/network/slirp/tcp_output.c index 7d75b64..ba78011 100644 --- a/src/devices/network/slirp/tcp_output.c +++ b/src/devices/network/slirp/tcp_output.c @@ -64,8 +64,7 @@ u_char tcp_outflags[TCP_NSTATES] = { * Tcp output routine: figure out what should be sent and send it. */ int -tcp_output(tp) - struct tcpcb *tp; +tcp_output(struct tcpcb *tp) { struct SLIRPsocket *so = tp->t_socket; register long len, win; @@ -582,8 +581,7 @@ out: } void -tcp_setpersist(tp) - struct tcpcb *tp; +tcp_setpersist(struct tcpcb *tp) { int t = ((tp->t_srtt >> 2) + tp->t_rttvar) >> 1; diff --git a/src/devices/network/slirp/tcp_subr.c b/src/devices/network/slirp/tcp_subr.c index 5f04b07..2612a15 100644 --- a/src/devices/network/slirp/tcp_subr.c +++ b/src/devices/network/slirp/tcp_subr.c @@ -56,7 +56,7 @@ int tcp_sndspace; /* Keep small if you have an error prone link */ * Tcp initialization */ void -tcp_init() +tcp_init(void) { tcp_iss = 1; /* wrong */ tcb.so_next = tcb.so_prev = &tcb; @@ -78,8 +78,7 @@ tcp_init() */ /* struct tcpiphdr * */ void -tcp_template(tp) - struct tcpcb *tp; +tcp_template(struct tcpcb *tp) { struct SLIRPsocket *so = tp->t_socket; struct tcpiphdr *n = &tp->t_template; @@ -117,12 +116,7 @@ tcp_template(tp) * segment are as specified by the parameters. */ void -tcp_respond(tp, ti, m, ack, seq, flags) - struct tcpcb *tp; - struct tcpiphdr *ti; - struct SLIRPmbuf *m; - tcp_seq ack, seq; - int flags; +tcp_respond(struct tcpcb *tp, struct tcpiphdr *ti, struct SLIRPmbuf *m, tcp_seq ack, tcp_seq seq, int flags) { register int tlen; int win = 0; @@ -197,8 +191,7 @@ tcp_respond(tp, ti, m, ack, seq, flags) * protocol control block. */ struct tcpcb * -tcp_newtcpcb(so) - struct SLIRPsocket *so; +tcp_newtcpcb(struct SLIRPsocket *so) { struct tcpcb *tp; @@ -272,8 +265,7 @@ struct tcpcb *tcp_drop(struct tcpcb *tp, int err) * wake up any sleepers */ struct tcpcb * -tcp_close(tp) - struct tcpcb *tp; +tcp_close(struct tcpcb *tp) { struct tcpiphdr *t; struct SLIRPsocket *so = tp->t_socket; @@ -310,7 +302,7 @@ tcp_close(tp) } void -tcp_drain() +tcp_drain(void) { /* XXX */ } @@ -323,9 +315,7 @@ tcp_drain() #ifdef notdef void -tcp_quench(i, errno) - - int errno; +tcp_quench(int i, int errno) { struct tcpcb *tp = intotcpcb(inp); @@ -350,8 +340,7 @@ tcp_quench(i, errno) * We can let the user exit from the close as soon as the FIN is acked. */ void -tcp_sockclosed(tp) - struct tcpcb *tp; +tcp_sockclosed(struct tcpcb *tp) { DEBUG_CALL("tcp_sockclosed"); @@ -392,8 +381,7 @@ tcp_sockclosed(tp) * nonblocking. Connect returns after the SYN is sent, and does * not wait for ACK+SYN. */ -int tcp_fconnect(so) - struct SLIRPsocket *so; +int tcp_fconnect(struct SLIRPsocket *so) { int ret=0; @@ -456,8 +444,7 @@ int tcp_fconnect(so) * here and SYN the local-host. */ void -tcp_connect(inso) - struct SLIRPsocket *inso; +tcp_connect(struct SLIRPsocket *inso) { struct SLIRPsocket *so; struct sockaddr_in addr; @@ -543,8 +530,7 @@ tcp_connect(inso) * Attach a TCPCB to a socket. */ int -tcp_attach(so) - struct SLIRPsocket *so; +tcp_attach(struct SLIRPsocket *so) { if ((so->so_tcpcb = tcp_newtcpcb(so)) == NULL) return -1; @@ -579,8 +565,7 @@ struct emu_t *tcpemu = 0; * Return TOS according to the above table */ u_int8_t -tcp_tos(so) - struct SLIRPsocket *so; +tcp_tos(struct SLIRPsocket *so) { int i = 0; struct emu_t *emup; @@ -633,9 +618,7 @@ int do_echo = -1; * NOTE: if you return 0 you MUST m_free() the SLIRPmbuf! */ int -tcp_emu(so, m) - struct SLIRPsocket *so; - struct SLIRPmbuf *m; +tcp_emu(struct SLIRPsocket *so, struct SLIRPmbuf *m) { u_int n1, n2, n3, n4, n5, n6; char buff[256]; @@ -1249,8 +1232,7 @@ do_prompt: * return 2 if this is a command-line connection */ int -tcp_ctl(so) - struct SLIRPsocket *so; +tcp_ctl(struct SLIRPsocket *so) { struct sbuf *sb = &so->so_snd; int command; diff --git a/src/devices/network/slirp/tcp_timer.c b/src/devices/network/slirp/tcp_timer.c index 892b222..c502c18 100644 --- a/src/devices/network/slirp/tcp_timer.c +++ b/src/devices/network/slirp/tcp_timer.c @@ -114,8 +114,7 @@ tpgone: * Cancel all timers for TCP tp. */ void -tcp_canceltimers(tp) - struct tcpcb *tp; +tcp_canceltimers(struct tcpcb *tp) { register int i; @@ -130,9 +129,7 @@ int tcp_backoff[TCP_MAXRXTSHIFT + 1] = * TCP timer processing. */ struct tcpcb * -tcp_timers(tp, timer) - struct tcpcb *tp; - int timer; +tcp_timers(struct tcpcb *tp, int timer) { int rexmt; diff --git a/src/devices/network/slirp/udp.c b/src/devices/network/slirp/udp.c index f847c51..09da87f 100644 --- a/src/devices/network/slirp/udp.c +++ b/src/devices/network/slirp/udp.c @@ -62,7 +62,7 @@ int udpcksum = 0; /* XXX */ struct SLIRPsocket *udp_last_so = &udb; void -udp_init() +udp_init(void) { udb.so_next = udb.so_prev = &udb; } @@ -71,9 +71,7 @@ udp_init() * ip->ip_len length data (IPDU) */ void -udp_input(m, iphlen) - struct SLIRPmbuf *m; - int iphlen; +udp_input(struct SLIRPmbuf *m, int iphlen) { struct ip *ip; struct udphdr *uh; @@ -327,8 +325,7 @@ int udp_output(struct SLIRPsocket *so, struct SLIRPmbuf *m, } int -udp_attach(so) - struct SLIRPsocket *so; +udp_attach(struct SLIRPsocket *so) { struct sockaddr_in addr; @@ -361,8 +358,7 @@ udp_attach(so) } void -udp_detach(so) - struct SLIRPsocket *so; +udp_detach(struct SLIRPsocket *so) { closesocket(so->s); /* if (so->so_m) m_free(so->so_m); done by sofree */ @@ -379,8 +375,7 @@ struct tos_t udptos[] = { }; u_int8_t -udp_tos(so) - struct SLIRPsocket *so; +udp_tos(struct SLIRPsocket *so) { int i = 0; @@ -404,9 +399,7 @@ udp_tos(so) * Here, talk/ytalk/ntalk requests must be emulated */ void -udp_emu(so, m) - struct SLIRPsocket *so; - struct SLIRPmbuf *m; +udp_emu(struct SLIRPsocket *so, struct SLIRPmbuf *m) { struct sockaddr_in addr; socklen_t addrlen = sizeof(addr); @@ -632,11 +625,7 @@ struct cu_header { } struct SLIRPsocket * -udp_listen(port, laddr, lport, flags) - u_int port; - u_int32_t laddr; - u_int lport; - int flags; +udp_listen(u_int port, u_int32_t laddr, u_int lport, int flags) { struct sockaddr_in addr; struct SLIRPsocket *so; diff --git a/src/devices/ports/game.c b/src/devices/ports/game.c index 65d3729..11c783c 100644 --- a/src/devices/ports/game.c +++ b/src/devices/ports/game.c @@ -8,7 +8,7 @@ * * Implementation of a generic Game Port. * - * Version: @(#)game.c 1.0.14 2018/05/06 + * Version: @(#)game.c 1.0.15 2018/09/22 * * Authors: Fred N. van Kempen, * Sarah Walker, @@ -41,6 +41,7 @@ #include #include #define HAVE_STDARG_H +#define dbglog game_log #include "../../emu.h" #include "../../machines/machine.h" #include "../../cpu/cpu.h" @@ -67,21 +68,21 @@ typedef struct _game_ { } game_t; +static game_t *game_global = NULL; + + #ifdef ENABLE_GAME_LOG int game_do_log = ENABLE_GAME_LOG; #endif -static game_t *game_global = NULL; - - -static void -gamelog(const char *fmt, ...) +void +game_log(int level, const char *fmt, ...) { -#ifdef ENABLE_GAME_LOG va_list ap; - if (game_do_log) { +#ifdef ENABLE_GAME_LOG + if (game_do_log >= level) { va_start(ap, fmt); pclog_ex(fmt, ap); va_end(ap); @@ -109,9 +110,7 @@ game_write(uint16_t addr, uint8_t val, void *priv) game_t *dev = (game_t *)priv; int i; -#ifdef ENABLE_GAME_LOG - gamelog("GAME: write(%04x, %02x)\n", addr, val); -#endif + DBGLOG(2, "GAME: write(%04x, %02x)\n", addr, val); timer_clock(); @@ -145,9 +144,7 @@ game_read(uint16_t addr, void *priv) cycles -= ISA_CYCLES(8); -#ifdef ENABLE_GAME_LOG - gamelog("GAME: read(%04x) = %02x\n", addr, ret); -#endif + DBGLOG(2, "GAME: read(%04x) = %02x\n", addr, ret); return(ret); } @@ -174,9 +171,9 @@ game_init(const device_t *info) game_t *dev; int i; - pclog("GAME: initializing, type=%d\n", joystick_type); + INFO("GAME: initializing, type=%d\n", joystick_type); - dev = (game_t *)malloc(sizeof(game_t)); + dev = (game_t *)mem_alloc(sizeof(game_t)); memset(dev, 0x00, sizeof(game_t)); game_global = dev; diff --git a/src/devices/ports/game.h b/src/devices/ports/game.h index ec11748..fcbc216 100644 --- a/src/devices/ports/game.h +++ b/src/devices/ports/game.h @@ -8,7 +8,7 @@ * * Definitions for the generic game port handlers. * - * Version: @(#)game.h 1.0.6 2018/04/26 + * Version: @(#)game.h 1.0.7 2018/09/19 * * Authors: Fred N. van Kempen, * Sarah Walker, @@ -47,6 +47,7 @@ extern const device_t game_device; extern const device_t game_201_device; #endif +extern void game_log(int level, const char *fmt, ...); extern void game_update_joystick_type(void); #ifdef __cplusplus diff --git a/src/devices/ports/parallel.c b/src/devices/ports/parallel.c index bfeb037..2d7f7d7 100644 --- a/src/devices/ports/parallel.c +++ b/src/devices/ports/parallel.c @@ -8,7 +8,7 @@ * * Implementation of the "LPT" style parallel ports. * - * Version: @(#)parallel.c 1.0.10 2018/05/06 + * Version: @(#)parallel.c 1.0.11 2018/09/19 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -42,6 +42,7 @@ #include #include #define HAVE_STDARG_H +#define dbglog parallel_log #include "../../emu.h" #include "../../io.h" #include "../../device.h" @@ -78,13 +79,13 @@ int parallel_do_log = ENABLE_PARALLEL_LOG; static parallel_t ports[PARALLEL_MAX]; /* the ports */ -static void -parlog(const char *fmt, ...) +void +parallel_log(int level, const char *fmt, ...) { #ifdef ENABLE_PARALLEL_LOG va_list ap; - if (parallel_do_log) { + if (parallel_do_log >= level) { va_start(ap, fmt); pclog_ex(fmt, ap); va_end(ap); @@ -99,9 +100,7 @@ parallel_write(uint16_t port, uint8_t val, void *priv) { parallel_t *dev = (parallel_t *)priv; -#ifdef ENABLE_PARALLEL_LOG - parlog("PARALLEL: write(%04X, %02X)\n", port, val); -#endif + DBGLOG(2, "PARALLEL: write(%04X, %02X)\n", port, val); switch (port & 3) { case 0: @@ -141,9 +140,8 @@ parallel_read(uint16_t port, void *priv) ret = dev->ctrl; break; } -#ifdef ENABLE_PARALLEL_LOG - parlog("PARALLEL: read(%04X) => %02X\n", port, ret); -#endif + + DBGLOG(2, "PARALLEL: read(%04X) => %02X\n", port, ret); return(ret); } @@ -173,7 +171,7 @@ parallel_init(const device_t *info) dev->dev_ps = dev->dev_ts->init(dev->dev_ts); } - pclog("PARALLEL: LPT%d (I/O=%04X, device=%d)\n", + INFO("PARALLEL: LPT%d (I/O=%04X, device=%d)\n", info->local+1, dev->base, parallel_device[info->local]); return(dev); @@ -240,10 +238,8 @@ parallel_reset(void) parallel_t *dev; int i; -#ifdef ENABLE_PARALLEL_LOG - parlog("PARALLEL: reset ([%d] [%d] [%d])\n", - parallel_enabled[0], parallel_enabled[1], parallel_enabled[2]); -#endif + DEBUG("PARALLEL: reset ([%d] [%d] [%d])\n", + parallel_enabled[0], parallel_enabled[1], parallel_enabled[2]); for (i = 0; i < PARALLEL_MAX; i++) { dev = &ports[i]; @@ -261,10 +257,8 @@ parallel_setup(int id, uint16_t port) { parallel_t *dev = &ports[id-1]; -#if defined(ENABLE_PARALLEL_LOG) && defined(_DEBUG) - parlog("PARALLEL: setting up LPT%d as %04X [enabled=%d]\n", + DEBUG("PARALLEL: setting up LPT%d as %04X [enabled=%d]\n", id, port, parallel_enabled[id-1]); -#endif if (! parallel_enabled[id-1]) return; dev->base = port; diff --git a/src/devices/ports/parallel.h b/src/devices/ports/parallel.h index 3c99e56..74e46cd 100644 --- a/src/devices/ports/parallel.h +++ b/src/devices/ports/parallel.h @@ -8,7 +8,7 @@ * * Definitions for the "LPT" parallel port handlerss. * - * Version: @(#)parallel.h 1.0.4 2018/04/07 + * Version: @(#)parallel.h 1.0.5 2018/09/19 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -54,6 +54,7 @@ extern const device_t parallel_3_device; #endif +extern void parallel_log(int level, const char *fmt, ...); extern void parallel_reset(void); extern void parallel_setup(int id, uint16_t port); diff --git a/src/devices/ports/serial.c b/src/devices/ports/serial.c index 37130fa..3197a2d 100644 --- a/src/devices/ports/serial.c +++ b/src/devices/ports/serial.c @@ -8,7 +8,7 @@ * * Implementation of 8250-style serial port. * - * Version: @(#)serial.c 1.0.7 2018/05/06 + * Version: @(#)serial.c 1.0.8 2018/09/19 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -43,8 +43,8 @@ #include #include #define HAVE_STDARG_H +#define dbglog serial_log #include "../../emu.h" -#include "../../machines/machine.h" #include "../../io.h" #include "../../mem.h" #include "../../rom.h" @@ -78,13 +78,13 @@ static const struct { static SERIAL ports[SERIAL_MAX]; /* the ports */ -static void -serlog(const char *fmt, ...) +void +serial_log(int level, const char *fmt, ...) { #ifdef ENABLE_SERIAL_LOG va_list ap; - if (serial_do_log) { + if (serial_do_log >= level) { va_start(ap, fmt); pclog_ex(fmt, ap); va_end(ap); @@ -105,7 +105,7 @@ update_ints(SERIAL *dev) stat = 1; dev->iir = 6; } else if ((dev->ier & 1) && (dev->int_status & SERIAL_INT_RECEIVE)) { - /*Recieved data available*/ + /*Received data available*/ stat = 1; dev->iir = 4; } else if ((dev->ier & 2) && (dev->int_status & SERIAL_INT_TRANSMIT)) { @@ -118,7 +118,7 @@ update_ints(SERIAL *dev) dev->iir = 0; } - if (stat && ((dev->mcr & 8) || PCJR)) + if (stat && ((dev->mcr & 8) || dev->pcjr)) picintlevel(1 << dev->irq); else picintc(1 << dev->irq); @@ -356,6 +356,10 @@ serial_init(const device_t *info) /* Get the correct device. */ dev = &ports[info->local - 1]; + /* Set up local/weird stuff. */ + if (info->local & 128) + dev->pcjr = 1; + /* Set up callback functions. */ dev->clear_fifo = clear_fifo; dev->write_fifo = write_fifo; @@ -369,8 +373,8 @@ serial_init(const device_t *info) timer_add(receive_callback, &dev->delay, &dev->delay, dev); - pclog("SERIAL: COM%d (I/O=%04X, IRQ=%d)\n", - info->local, dev->base, dev->irq); + INFO("SERIAL: COM%d (I/O=%04X, IRQ=%d)\n", + info->local & 127, dev->base, dev->irq); return(dev); } @@ -400,6 +404,16 @@ const device_t serial_1_device = { }; +const device_t serial_1_pcjr_device = { + "COM1:", + 0, + 128+1, + serial_init, serial_close, NULL, + NULL, NULL, NULL, NULL, + NULL +}; + + const device_t serial_2_device = { "COM2:", 0, @@ -417,9 +431,7 @@ serial_reset(void) SERIAL *dev; int i; -#ifdef ENABLE_SERIAL_LOG - serlog("SERIAL: reset ([%d] [%d])\n", serial_enabled[0], serial_enabled[1]); -#endif + DEBUG("SERIAL: reset ([%d] [%d])\n", serial_enabled[0], serial_enabled[1]); for (i = 0; i < SERIAL_MAX; i++) { dev = &ports[i]; @@ -441,10 +453,9 @@ serial_setup(int id, uint16_t port, int8_t irq) { SERIAL *dev = &ports[id-1]; -#if defined(ENABLE_SERIAL_LOG) && defined(_DEBUG) - serlog("SERIAL: setting up COM%d as %04X [enabled=%d]\n", + INFO("SERIAL: setting up COM%d as %04X [enabled=%d]\n", id, port, serial_enabled[id-1]); -#endif + if (! serial_enabled[id-1]) return; dev->base = port; @@ -465,7 +476,7 @@ serial_attach(int port, void *func, void *arg) dev = &ports[port-1]; /* Set up callback info. */ - dev->rts_callback = func; + dev->rts_callback = (void (*)(struct SERIAL *, void *))func; dev->rts_callback_p = arg; return(dev); diff --git a/src/devices/ports/serial.h b/src/devices/ports/serial.h index f9b3baf..3b12058 100644 --- a/src/devices/ports/serial.h +++ b/src/devices/ports/serial.h @@ -8,7 +8,7 @@ * * Definitions for the SERIAL card. * - * Version: @(#)serial.h 1.0.4 2018/04/20 + * Version: @(#)serial.h 1.0.5 2018/09/19 * * Author: Fred N. van Kempen, * @@ -70,6 +70,7 @@ typedef struct SERIAL { int8_t irq; /* IRQ channel used */ uint16_t base; /* I/O address used */ + int8_t pcjr; /* PCjr UART (fixed OUT2) */ int8_t type; /* UART type */ uint8_t int_status; @@ -104,11 +105,13 @@ typedef struct SERIAL { /* Global variables. */ #ifdef EMU_DEVICE_H extern const device_t serial_1_device; +extern const device_t serial_1_pcjr_device; extern const device_t serial_2_device; #endif /* Functions. */ +extern void serial_log(int level, const char *fmt, ...); extern void serial_reset(void); extern void serial_setup(int port, uint16_t addr, int8_t irq); extern SERIAL *serial_attach(int port, void *func, void *priv); diff --git a/src/devices/printer/prt_cpmap.c b/src/devices/printer/prt_cpmap.c index f58739a..1ae3bc5 100644 --- a/src/devices/printer/prt_cpmap.c +++ b/src/devices/printer/prt_cpmap.c @@ -8,7 +8,7 @@ * * Various ASCII to Unicode maps, for the various codepages. * - * Version: @(#)prt_cpmap.c 1.0.1 2018/08/31 + * Version: @(#)prt_cpmap.c 1.0.2 2018/10/05 * * Authors: Michael Dring, * Fred N. van Kempen, @@ -583,7 +583,7 @@ select_codepage(uint16_t code) if (code == 0) return(maps[0].map); - pclog("ESC/P: unsupported code page %i, using CP437...\n", code); + ERRLOG("CPMAP: unsupported code page %i, using CP437...\n", code); return(maps[0].map); } diff --git a/src/devices/printer/prt_escp.c b/src/devices/printer/prt_escp.c index 3d32bfd..d0fe932 100644 --- a/src/devices/printer/prt_escp.c +++ b/src/devices/printer/prt_escp.c @@ -8,7 +8,7 @@ * * Implementation of the Generic ESC/P Dot-Matrix printer. * - * Version: @(#)prt_escp.c 1.0.1 2018/09/02 + * Version: @(#)prt_escp.c 1.0.2 2018/10/05 * * Authors: Michael Dring, * Fred N. van Kempen, @@ -48,7 +48,6 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include #include #include #include @@ -64,6 +63,7 @@ #include "../../mem.h" #include "../../rom.h" #include "../../plat.h" +#include "../ui/ui.h" #include "../../png.h" #include "../ports/parallel_dev.h" #include "printer.h" @@ -81,7 +81,11 @@ #define PAGE_LPI 6.0 /* standard 6 lpi */ -#define PATH_FREETYPE_DLL "freetype.dll" +#ifdef _WIN32 +# define PATH_FREETYPE_DLL "freetype.dll" +#else +# define PATH_FREETYPE_DLL "libfreetype.so.6" +#endif /* FreeType library handles - global so they can be shared. */ @@ -414,8 +418,8 @@ update_font(escp_t *dev) /* Load the new font. */ if (ft_New_Face(ft_lib, temp, 0, &dev->fontface)) { - pclog("ESC/P: unable to load font '%s'\n", temp); - pclog("ESC/P: text printing disabled\n"); + ERRLOG("ESC/P: unable to load font '%s'\n", temp); + ERRLOG("ESC/P: text printing disabled\n"); dev->fontface = 0; } @@ -494,7 +498,7 @@ dump_pgm(const wchar_t *fn, int inv, uint8_t *pix, int16_t w, int16_t h) /* Create the image file. */ fp = plat_fopen(fn, L"wb"); if (fp == NULL) { - pclog("ESC/P: unable to create print page '%ls'\n", fn); + ERRLOG("ESC/P: unable to create print page '%ls'\n", fn); return(0); } @@ -620,9 +624,9 @@ reset_printer(escp_t *dev) update_font(dev); - pclog("ESC/P: width=%.1fin,height=%.1fin dpi=%i cpi=%i lpi=%i\n", - dev->page_width, dev->page_height, - (int)dev->dpi, (int)dev->cpi, (int)dev->lpi); + INFO("ESC/P: width=%.1fin,height=%.1fin dpi=%i cpi=%i lpi=%i\n", + dev->page_width, dev->page_height, + (int)dev->dpi, (int)dev->cpi, (int)dev->lpi); } @@ -729,7 +733,7 @@ setup_bit_image(escp_t *dev, uint8_t density, uint16_t num_columns) break; default: - pclog("ESC/P: Unsupported bit image density %d.\n", density); + ERRLOG("ESC/P: Unsupported bit image density %d.\n", density); } dev->bg_remaining_bytes = num_columns * dev->bg_bytes_per_column; @@ -836,7 +840,7 @@ process_char(escp_t *dev, uint8_t ch) case 0x25: // Select user-defined set (ESC %) case 0x26: // Define user-defined characters (ESC &) case 0x3a: // Copy ROM to RAM (ESC :) - pclog("ESC/P: User-defined characters not supported.\n"); + ERRLOG("ESC/P: User-defined characters not supported.\n"); return 1; case 0x28: // Two bytes sequence @@ -844,12 +848,12 @@ process_char(escp_t *dev, uint8_t ch) return 1; default: - pclog("ESC/P: Unknown command ESC %c (0x%02x). Unable to skip parameters.\n", - dev->esc_pending >= 0x20 ? dev->esc_pending : '?', + ERRLOG("ESC/P: Unknown command ESC %c (0x%02x). Unable to skip parameters.\n", + dev->esc_pending >= 0x20 ? dev->esc_pending : '?', dev->esc_pending); - dev->esc_parms_req = 0; - dev->esc_pending = 0; - return 1; + dev->esc_parms_req = 0; + dev->esc_pending = 0; + return 1; } if (dev->esc_parms_req > 0) { @@ -889,9 +893,9 @@ process_char(escp_t *dev, uint8_t ch) default: // ESC ( commands are always followed by a "number of parameters" word parameter - pclog("ESC/P: Skipping unsupported extended command ESC ( %c (0x%02x).\n", - dev->esc_pending >= 0x20 ? dev->esc_pending : '?', - dev->esc_pending); + ERRLOG("ESC/P: Skipping unsupported extended command ESC ( %c (0x%02x).\n", + dev->esc_pending >= 0x20 ? dev->esc_pending : '?', + dev->esc_pending); dev->esc_parms_req = 2; dev->esc_pending = 0x101; /* dummy value to be checked later */ return 1; @@ -1008,7 +1012,7 @@ process_char(escp_t *dev, uint8_t ch) break; case 0x23: /* cancel MSB control (ESC #) */ - dev->msb = 255; + dev->msb = -1; break; case 0x24: /* set abs horizontal print position (ESC $) */ @@ -1312,7 +1316,7 @@ process_char(escp_t *dev, uint8_t ch) case 0x72: /* select printing color (ESC r) */ if (dev->esc_parms[0]) - pclog("ESC/P: Color printing not yet supported.\n"); + ERRLOG("ESC/P: Color printing not yet supported.\n"); break; case 0x73: /* select low-speed mode (ESC s) */ @@ -1384,7 +1388,7 @@ process_char(escp_t *dev, uint8_t ch) break; case 0x0242: /* bar code setup and print (ESC (B) */ - pclog("ESC/P: Bardcode printing not supported.\n"); + ERRLOG("ESC/P: Barcode printing not supported.\n"); /* Find out how many bytes to skip. */ dev->esc_parms_req = PARAM16(0); @@ -1441,7 +1445,7 @@ process_char(escp_t *dev, uint8_t ch) break; default: - pclog("ESC/P: Unhandled ESC command.\n"); + ERRLOG("ESC/P: Unhandled ESC command.\n"); break; } @@ -1795,6 +1799,10 @@ write_data(uint8_t val, void *priv) { escp_t *dev = (escp_t *)priv; + DBGLOG(1, "ESC/P: data(%02x)\n", val); + + if (dev == NULL) return; + dev->data = val; } @@ -1804,6 +1812,10 @@ write_ctrl(uint8_t val, void *priv) { escp_t *dev = (escp_t *)priv; + DEBUG("ESC/P: ctrl(%02x)\n", val); + + if (dev == NULL) return; + /* set autofeed value */ dev->autofeed = val & 0x02 ? 1 : 0; @@ -1833,32 +1845,42 @@ static uint8_t read_status(void *priv) { escp_t *dev = (escp_t *)priv; + uint8_t ret = 0xff; - uint8_t status = (dev->ack ? 0x00 : 0x40) | - (dev->select ? 0x10 : 0x00) | - (dev->busy ? 0x00 : 0x80) | - (dev->int_pending ? 0x00 : 0x04) | - (dev->error ? 0x00 : 0x08); + if (dev == NULL) return(ret); + + ret = (dev->ack ? 0x00 : 0x40) | + (dev->select ? 0x10 : 0x00) | + (dev->busy ? 0x00 : 0x80) | + (dev->int_pending ? 0x00 : 0x04) | + (dev->error ? 0x00 : 0x08); /* Clear ACK after reading status. */ dev->ack = 0; - return(status); + DEBUG("ESC/P: status(%02x)\n", ret); + + return(ret); } static void * escp_init(const lpt_device_t *info) { + wchar_t temp[512]; + const char *fn = PATH_FREETYPE_DLL; escp_t *dev; - pclog("ESC/P: LPT printer '%s' initializing\n", info->name); + INFO("ESC/P: LPT printer '%s' initializing\n", info->name); /* Dynamically load FreeType. */ if (ft_handle == NULL) { - ft_handle = dynld_module(PATH_FREETYPE_DLL, ft_imports); + ft_handle = dynld_module(fn, ft_imports); if (ft_handle == NULL) { - pclog("ESC/P: unable to load FreeType DLL !\n"); + swprintf(temp, sizeof_w(temp), + get_string(IDS_ERR_NOLIB), "FreeType", fn); + ui_msgbox(MBX_ERROR, temp); + ERRLOG("ESC/P: unable to load FreeType DLL !\n"); return(NULL); } } @@ -1866,14 +1888,18 @@ escp_init(const lpt_device_t *info) /* Initialize FreeType. */ if (ft_lib == NULL) { if (ft_Init_FreeType(&ft_lib)) { - pclog("ESC/P: error initializing FreeType !\n"); + swprintf(temp, sizeof_w(temp), + get_string(IDS_ERR_NOLIB), "FreeType", fn); + ui_msgbox(MBX_ERROR, temp); + ERRLOG("ESC/P: error initializing FreeType !\n"); + dynld_close(ft_lib); ft_lib = NULL; return(NULL); } } /* Initialize a device instance. */ - dev = malloc(sizeof(escp_t)); + dev = (escp_t *)mem_alloc(sizeof(escp_t)); memset(dev, 0x00, sizeof(escp_t)); dev->name = info->name; @@ -1893,18 +1919,15 @@ escp_init(const lpt_device_t *info) reset_printer(dev); /* Create 8-bit grayscale buffer for the page. */ - dev->page = (psurface_t *)malloc(sizeof(psurface_t)); + dev->page = (psurface_t *)mem_alloc(sizeof(psurface_t)); dev->page->w = (int)(dev->dpi * dev->page_width); dev->page->h = (int)(dev->dpi * dev->page_height); dev->page->pitch = dev->page->w; - dev->page->pixels = (uint8_t *)malloc(dev->page->pitch * dev->page->h); + dev->page->pixels = (uint8_t *)mem_alloc(dev->page->pitch * dev->page->h); memset(dev->page->pixels, 0x00, dev->page->pitch * dev->page->h); -#if 0 - pclog("ESC/P: created a virtual page of dimensions %d x %d pixels.\n", + DEBUG("ESC/P: created a virtual page of dimensions %d x %d pixels.\n", dev->page->w, dev->page->h); -#endif - return(dev); } diff --git a/src/devices/printer/prt_text.c b/src/devices/printer/prt_text.c index 3bae6c5..3aec5c0 100644 --- a/src/devices/printer/prt_text.c +++ b/src/devices/printer/prt_text.c @@ -15,7 +15,7 @@ * printer mechanics. This would lead to a page being 66 lines * of 80 characters each. * - * Version: @(#)prt_text.c 1.0.2 2018/09/02 + * Version: @(#)prt_text.c 1.0.3 2018/10/05 * * Author: Fred N. van Kempen, * @@ -149,7 +149,7 @@ dump_page(prnt_t *dev) /* Create the file. */ fp = plat_fopen(path, L"a"); if (fp == NULL) { - pclog("PRNT: unable to create print page '%ls'\n", path); + ERRLOG("PRNT: unable to create print page '%ls'\n", path); return; } fseek(fp, 0, SEEK_END); @@ -207,9 +207,9 @@ reset_printer(prnt_t *dev) dev->max_chars = (int) ((dev->page_width - dev->left_margin - dev->right_margin) * dev->cpi); dev->max_lines = (int) ((dev->page_height -dev->top_margin - dev->bot_margin) * dev->lpi); - pclog("PRNT: width=%.1fin,height=%.1fin cpi=%i lpi=%i cols=%i lines=%i\n", - dev->page_width, dev->page_height, (int)dev->cpi, - (int)dev->lpi, dev->max_chars, dev->max_lines); + INFO("PRNT: width=%.1fin,height=%.1fin cpi=%i lpi=%i cols=%i lines=%i\n", + dev->page_width, dev->page_height, (int)dev->cpi, + (int)dev->lpi, dev->max_chars, dev->max_lines); dev->curr_x = dev->curr_y = 0; @@ -338,6 +338,8 @@ write_data(uint8_t val, void *priv) { prnt_t *dev = (prnt_t *)priv; + if (dev == NULL) return; + dev->data = val; } @@ -347,6 +349,8 @@ write_ctrl(uint8_t val, void *priv) { prnt_t *dev = (prnt_t *)priv; + if (dev == NULL) return; + /* set autofeed value */ dev->autofeed = val & 0x02 ? 1 : 0; @@ -376,17 +380,20 @@ static uint8_t read_status(void *priv) { prnt_t *dev = (prnt_t *)priv; + uint8_t ret = 0xff; - uint8_t status = (dev->ack ? 0x00 : 0x40) | - (dev->select ? 0x10 : 0x00) | - (dev->busy ? 0x00 : 0x80) | - (dev->int_pending ? 0x00 : 0x04) | - (dev->error ? 0x00 : 0x08); + if (dev == NULL) return(ret); + + ret = (dev->ack ? 0x00 : 0x40) | + (dev->select ? 0x10 : 0x00) | + (dev->busy ? 0x00 : 0x80) | + (dev->int_pending ? 0x00 : 0x04) | + (dev->error ? 0x00 : 0x08); /* Clear ACK after reading status. */ dev->ack = 0; - return(status); + return(ret); } @@ -396,26 +403,23 @@ prnt_init(const lpt_device_t *info) prnt_t *dev; /* Initialize a device instance. */ - dev = malloc(sizeof(prnt_t)); + dev = (prnt_t *)mem_alloc(sizeof(prnt_t)); memset(dev, 0x00, sizeof(prnt_t)); dev->name = info->name; - pclog("PRNT: LPT printer '%s' initializing\n", dev->name); + INFO("PRNT: LPT printer '%s' initializing\n", dev->name); /* Initialize parameters. */ reset_printer(dev); /* Create a page buffer. */ - dev->page = (psurface_t *)malloc(sizeof(psurface_t)); + dev->page = (psurface_t *)mem_alloc(sizeof(psurface_t)); dev->page->w = dev->max_chars; dev->page->h = dev->max_lines; - dev->page->chars = (char *)malloc(dev->page->w * dev->page->h); + dev->page->chars = (char *)mem_alloc(dev->page->w * dev->page->h); memset(dev->page->chars, 0x00, dev->page->w * dev->page->h); -#if 0 - pclog("PRNT: created a virtual %ix%i page.\n", - dev->page->w, dev->page->h); -#endif + DEBUG("PRNT: created a virtual %ix%i page.\n", dev->page->w, dev->page->h); return(dev); } diff --git a/src/devices/scsi/scsi.c b/src/devices/scsi/scsi.c index 8c6ca4a..4e6728c 100644 --- a/src/devices/scsi/scsi.c +++ b/src/devices/scsi/scsi.c @@ -8,7 +8,7 @@ * * Handling of the SCSI controllers. * - * Version: @(#)scsi.c 1.0.10 2018/05/12 + * Version: @(#)scsi.c 1.0.11 2018/10/05 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -42,16 +42,17 @@ #include #include #define HAVE_STDARG_H +#define dbglog scsi_log #include "../../emu.h" -#include "../../mem.h" -#include "../../rom.h" -#include "../../timer.h" #include "../../device.h" #include "../../plat.h" #include "../disk/hdc.h" -#include "../disk/zip.h" -#include "../cdrom/cdrom.h" +#include "../disk/hdd.h" #include "scsi.h" +#include "scsi_device.h" +#include "scsi_disk.h" +#include "../cdrom/cdrom.h" +#include "../disk/zip.h" #include "scsi_aha154x.h" #include "scsi_buslogic.h" #include "scsi_ncr5380.h" @@ -59,104 +60,50 @@ #ifdef USE_WD33C93 # include "scsi_wd33c93.h" #endif -#include "scsi_x54x.h" +#ifdef ENABLE_SCSI_LOG +int scsi_do_log = ENABLE_SCSI_LOG; +#endif #ifdef ENABLE_SCSI_DEV_LOG int scsi_dev_do_log = ENABLE_SCSI_DEV_LOG; #endif scsi_device_t SCSIDevices[SCSI_ID_MAX][SCSI_LUN_MAX]; -#if 0 -uint8_t SCSIPhase = 0xff; -uint8_t SCSIStatus = SCSI_STATUS_OK; -#endif -char scsi_fn[SCSI_NUM][512]; -uint16_t scsi_hd_location[SCSI_NUM]; uint32_t SCSI_BufferLength; -static volatile -mutex_t *scsiMutex; -typedef struct { - const char *name; +static struct { const char *internal_name; const device_t *device; - void (*reset)(void *p); -} scsidev_t; +} scsi_cards[] = { + { "none", NULL }, - -static const scsidev_t scsi_cards[] = { - { "None", "none", NULL, NULL }, - { "[ISA] Adaptec AHA-1540B","aha1540b", &aha1540b_device, x54x_device_reset }, - { "[ISA] Adaptec AHA-1542C","aha1542c", &aha1542c_device, x54x_device_reset }, - { "[ISA] Adaptec AHA-1542CF","aha1542cf", &aha1542cf_device, x54x_device_reset }, - { "[ISA] BusLogic BT-542BH","bt542bh", &buslogic_device, BuslogicDeviceReset }, - { "[ISA] BusLogic BT-545S", "bt545s", &buslogic_545s_device,BuslogicDeviceReset }, - { "[ISA] Longshine LCS-6821N","lcs6821n", &scsi_lcs6821n_device,NULL }, - { "[ISA] Ranco RT1000B", "rt1000b", &scsi_rt1000b_device, NULL }, - { "[ISA] Trantor T130B", "t130b", &scsi_t130b_device, NULL }, - { "[ISA] Sumo SCSI-AT", "scsiat", &scsi_scsiat_device, NULL }, + { "aha1540b", &aha1540b_device }, + { "aha1542c", &aha1542c_device }, + { "aha1542cf", &aha1542cf_device }, + { "bt542bh", &buslogic_device }, + { "bt545s", &buslogic_545s_device }, + { "lcs6821n", &scsi_lcs6821n_device }, + { "rt1000b", &scsi_rt1000b_device }, + { "t130b", &scsi_t130b_device }, + { "scsiat", &scsi_scsiat_device }, #ifdef USE_WD33C93 - { "[ISA] Generic WDC33C93", "wd33c93", &scsi_wd33c93_device, NULL }, + { "wd33c93", &scsi_wd33c93_device }, #endif - { "[MCA] Adaptec AHA-1640", "aha1640", &aha1640_device, x54x_device_reset }, - { "[MCA] BusLogic BT-640A", "bt640a", &buslogic_640a_device,BuslogicDeviceReset }, - { "[PCI] BusLogic BT-958D", "bt958d", &buslogic_pci_device, BuslogicDeviceReset }, - { "[PCI] NCR 53C810", "ncr53c810", &ncr53c810_pci_device,NULL }, - { "[VLB] BusLogic BT-445S", "bt445s", &buslogic_445s_device,BuslogicDeviceReset }, - { NULL, NULL, NULL, NULL }, + + { "aha1640", &aha1640_device }, + { "bt640a", &buslogic_640a_device }, + + { "bt958d", &buslogic_pci_device }, + { "ncr53c810", &ncr53c810_pci_device }, + + { "bt445s", &buslogic_445s_device }, + + { NULL, NULL } }; -void -scsi_dev_log(const char *fmt, ...) -{ -#ifdef ENABLE_SCSI_DEV_LOG - va_list ap; - - if (scsi_dev_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); - } -#endif -} - - -int -scsi_card_available(int card) -{ - if (scsi_cards[card].device) - return(device_available(scsi_cards[card].device)); - - return(1); -} - - -const char * -scsi_card_getname(int card) -{ - return(scsi_cards[card].name); -} - - -const device_t * -scsi_card_getdevice(int card) -{ - return(scsi_cards[card].device); -} - - -int -scsi_card_has_config(int card) -{ - if (! scsi_cards[card].device) return(0); - - return(scsi_cards[card].device->config ? 1 : 0); -} - - const char * scsi_card_get_internal_name(int card) { @@ -180,13 +127,70 @@ scsi_card_get_from_internal_name(const char *s) } -void -scsi_mutex(uint8_t start) +const char * +scsi_card_getname(int card) { - if (start) - scsiMutex = thread_create_mutex(L"VARCem.SCSIMutex"); - else - thread_close_mutex((mutex_t *) scsiMutex); + if (scsi_cards[card].device != NULL) + return(scsi_cards[card].device->name); + + return(NULL); +} + + +const device_t * +scsi_card_getdevice(int card) +{ + return(scsi_cards[card].device); +} + + +int +scsi_card_has_config(int card) +{ + if (scsi_cards[card].device != NULL) + return(scsi_cards[card].device->config ? 1 : 0); + + return(0); +} + + +void +scsi_log(int level, const char *fmt, ...) +{ +#ifdef ENABLE_SCSI_LOG + va_list ap; + + if (scsi_do_log >= level) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +#endif +} + + +void +scsi_dev_log(int level, const char *fmt, ...) +{ +#ifdef ENABLE_SCSI_DEV_LOG + va_list ap; + + if (scsi_dev_do_log >= level) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +#endif +} + + +int +scsi_card_available(int card) +{ + if (scsi_cards[card].device) + return(device_available(scsi_cards[card].device)); + + return(1); } @@ -195,85 +199,31 @@ scsi_card_init(void) { int i, j; - pclog("SCSI: building hard disk map...\n"); - build_scsi_hd_map(); + if (! scsi_cards[scsi_card].device) return; - pclog("SCSI: building CD-ROM map...\n"); + DEBUG("SCSI: building hard disk map...\n"); + build_scsi_disk_map(); + + DEBUG("SCSI: building CD-ROM map...\n"); build_scsi_cdrom_map(); - pclog("SCSI: building ZIP map...\n"); - build_scsi_zip_map(); + DEBUG("SCSI: building ZIP map...\n"); + zip_build_scsi_map(); - for (i=0; i * Miran Grca, @@ -39,277 +39,7 @@ #define EMU_SCSI_H -#define SCSI_TIME (5 * 100 * (1 << TIMER_SHIFT)) - - -/* Configuration. */ -#define SCSI_ID_MAX 16 /* 16 on wide buses */ -#define SCSI_LUN_MAX 8 /* always 8 */ - - -/* SCSI commands. */ -#define GPCMD_TEST_UNIT_READY 0x00 -#define GPCMD_REZERO_UNIT 0x01 -#define GPCMD_REQUEST_SENSE 0x03 -#define GPCMD_FORMAT_UNIT 0x04 -#define GPCMD_IOMEGA_SENSE 0x06 -#define GPCMD_READ_6 0x08 -#define GPCMD_WRITE_6 0x0a -#define GPCMD_SEEK_6 0x0b -#define GPCMD_IOMEGA_SET_PROTECTION_MODE 0x0c -#define GPCMD_IOMEGA_EJECT 0x0d /* ATAPI only? */ -#define GPCMD_INQUIRY 0x12 -#define GPCMD_VERIFY_6 0x13 -#define GPCMD_MODE_SELECT_6 0x15 -#define GPCMD_SCSI_RESERVE 0x16 -#define GPCMD_SCSI_RELEASE 0x17 -#define GPCMD_MODE_SENSE_6 0x1a -#define GPCMD_START_STOP_UNIT 0x1b -#define GPCMD_SEND_DIAGNOSTIC 0x1d -#define GPCMD_PREVENT_REMOVAL 0x1e -#define GPCMD_READ_FORMAT_CAPACITIES 0x23 -#define GPCMD_READ_CDROM_CAPACITY 0x25 -#define GPCMD_READ_10 0x28 -#define GPCMD_WRITE_10 0x2a -#define GPCMD_SEEK_10 0x2b -#define GPCMD_WRITE_AND_VERIFY_10 0x2e -#define GPCMD_VERIFY_10 0x2f -#define GPCMD_READ_BUFFER 0x3c -#define GPCMD_WRITE_SAME_10 0x41 -#define GPCMD_READ_SUBCHANNEL 0x42 -#define GPCMD_READ_TOC_PMA_ATIP 0x43 -#define GPCMD_READ_HEADER 0x44 -#define GPCMD_PLAY_AUDIO_10 0x45 -#define GPCMD_GET_CONFIGURATION 0x46 -#define GPCMD_PLAY_AUDIO_MSF 0x47 -#define GPCMD_PLAY_AUDIO_TRACK_INDEX 0x48 -#define GPCMD_GET_EVENT_STATUS_NOTIFICATION 0x4a -#define GPCMD_PAUSE_RESUME 0x4b -#define GPCMD_STOP_PLAY_SCAN 0x4e -#define GPCMD_READ_DISC_INFORMATION 0x51 -#define GPCMD_READ_TRACK_INFORMATION 0x52 -#define GPCMD_MODE_SELECT_10 0x55 -#define GPCMD_MODE_SENSE_10 0x5a -#define GPCMD_PLAY_AUDIO_12 0xa5 -#define GPCMD_READ_12 0xa8 -#define GPCMD_WRITE_12 0xaa -#define GPCMD_READ_DVD_STRUCTURE 0xad /* For reading. */ -#define GPCMD_WRITE_AND_VERIFY_12 0xae -#define GPCMD_VERIFY_12 0xaf -#define GPCMD_PLAY_CD_OLD 0xb4 -#define GPCMD_READ_CD_OLD 0xb8 -#define GPCMD_READ_CD_MSF 0xb9 -#define GPCMD_SCAN 0xba -#define GPCMD_SET_SPEED 0xbb -#define GPCMD_PLAY_CD 0xbc -#define GPCMD_MECHANISM_STATUS 0xbd -#define GPCMD_READ_CD 0xbe -#define GPCMD_SEND_DVD_STRUCTURE 0xbf /* This is for writing only, irrelevant to PCem. */ -#define GPCMD_PAUSE_RESUME_ALT 0xc2 -#define GPCMD_SCAN_ALT 0xcd /* Should be equivalent to 0xba */ -#define GPCMD_SET_SPEED_ALT 0xda /* Should be equivalent to 0xbb */ - -/* Mode page codes for mode sense/set */ -#define GPMODE_R_W_ERROR_PAGE 0x01 -#define GPMODE_CDROM_PAGE 0x0d -#define GPMODE_CDROM_AUDIO_PAGE 0x0e -#define GPMODE_CAPABILITIES_PAGE 0x2a -#define GPMODE_ALL_PAGES 0x3f - -/* SCSI Status Codes */ -#define SCSI_STATUS_OK 0 -#define SCSI_STATUS_CHECK_CONDITION 2 - -/* SCSI Sense Keys */ -#define SENSE_NONE 0 -#define SENSE_NOT_READY 2 -#define SENSE_ILLEGAL_REQUEST 5 -#define SENSE_UNIT_ATTENTION 6 - -/* SCSI Additional Sense Codes */ -#define ASC_AUDIO_PLAY_OPERATION 0x00 -#define ASC_NOT_READY 0x04 -#define ASC_ILLEGAL_OPCODE 0x20 -#define ASC_LBA_OUT_OF_RANGE 0x21 -#define ASC_INV_FIELD_IN_CMD_PACKET 0x24 -#define ASC_INV_LUN 0x25 -#define ASC_INV_FIELD_IN_PARAMETER_LIST 0x26 -#define ASC_WRITE_PROTECTED 0x27 -#define ASC_MEDIUM_MAY_HAVE_CHANGED 0x28 -#define ASC_CAPACITY_DATA_CHANGED 0x2A -#define ASC_INCOMPATIBLE_FORMAT 0x30 -#define ASC_MEDIUM_NOT_PRESENT 0x3a -#define ASC_DATA_PHASE_ERROR 0x4b -#define ASC_ILLEGAL_MODE_FOR_THIS_TRACK 0x64 - -#define ASCQ_UNIT_IN_PROCESS_OF_BECOMING_READY 0x01 -#define ASCQ_INITIALIZING_COMMAND_REQUIRED 0x02 -#define ASCQ_CAPACITY_DATA_CHANGED 0x09 -#define ASCQ_AUDIO_PLAY_OPERATION_IN_PROGRESS 0x11 -#define ASCQ_AUDIO_PLAY_OPERATION_PAUSED 0x12 -#define ASCQ_AUDIO_PLAY_OPERATION_COMPLETED 0x13 - -/* Tell RISC OS that we have a 4x CD-ROM drive (600kb/sec data, 706kb/sec raw). - Not that it means anything */ -#define CDROM_SPEED 706 /* 0x2C2 */ - -#define BUFFER_SIZE (256*1024) - -#define RW_DELAY (TIMER_USEC * 500) - -/* Some generally useful CD-ROM information */ -#define CD_MINS 75 /* max. minutes per CD */ -#define CD_SECS 60 /* seconds per minute */ -#define CD_FRAMES 75 /* frames per second */ -#define CD_FRAMESIZE 2048 /* bytes per frame, "cooked" mode */ -#define CD_MAX_BYTES (CD_MINS * CD_SECS * CD_FRAMES * CD_FRAMESIZE) -#define CD_MAX_SECTORS (CD_MAX_BYTES / 512) - -/* Event notification classes for GET EVENT STATUS NOTIFICATION */ -#define GESN_NO_EVENTS 0 -#define GESN_OPERATIONAL_CHANGE 1 -#define GESN_POWER_MANAGEMENT 2 -#define GESN_EXTERNAL_REQUEST 3 -#define GESN_MEDIA 4 -#define GESN_MULTIPLE_HOSTS 5 -#define GESN_DEVICE_BUSY 6 - -/* Event codes for MEDIA event status notification */ -#define MEC_NO_CHANGE 0 -#define MEC_EJECT_REQUESTED 1 -#define MEC_NEW_MEDIA 2 -#define MEC_MEDIA_REMOVAL 3 /* only for media changers */ -#define MEC_MEDIA_CHANGED 4 /* only for media changers */ -#define MEC_BG_FORMAT_COMPLETED 5 /* MRW or DVD+RW b/g format completed */ -#define MEC_BG_FORMAT_RESTARTED 6 /* MRW or DVD+RW b/g format restarted */ -#define MS_TRAY_OPEN 1 -#define MS_MEDIA_PRESENT 2 - -/* - * The MMC values are not IDE specific and might need to be moved - * to a common header if they are also needed for the SCSI emulation - */ - -/* Profile list from MMC-6 revision 1 table 91 */ -#define MMC_PROFILE_NONE 0x0000 -#define MMC_PROFILE_CD_ROM 0x0008 -#define MMC_PROFILE_CD_R 0x0009 -#define MMC_PROFILE_CD_RW 0x000A -#define MMC_PROFILE_DVD_ROM 0x0010 -#define MMC_PROFILE_DVD_R_SR 0x0011 -#define MMC_PROFILE_DVD_RAM 0x0012 -#define MMC_PROFILE_DVD_RW_RO 0x0013 -#define MMC_PROFILE_DVD_RW_SR 0x0014 -#define MMC_PROFILE_DVD_R_DL_SR 0x0015 -#define MMC_PROFILE_DVD_R_DL_JR 0x0016 -#define MMC_PROFILE_DVD_RW_DL 0x0017 -#define MMC_PROFILE_DVD_DDR 0x0018 -#define MMC_PROFILE_DVD_PLUS_RW 0x001A -#define MMC_PROFILE_DVD_PLUS_R 0x001B -#define MMC_PROFILE_DVD_PLUS_RW_DL 0x002A -#define MMC_PROFILE_DVD_PLUS_R_DL 0x002B -#define MMC_PROFILE_BD_ROM 0x0040 -#define MMC_PROFILE_BD_R_SRM 0x0041 -#define MMC_PROFILE_BD_R_RRM 0x0042 -#define MMC_PROFILE_BD_RE 0x0043 -#define MMC_PROFILE_HDDVD_ROM 0x0050 -#define MMC_PROFILE_HDDVD_R 0x0051 -#define MMC_PROFILE_HDDVD_RAM 0x0052 -#define MMC_PROFILE_HDDVD_RW 0x0053 -#define MMC_PROFILE_HDDVD_R_DL 0x0058 -#define MMC_PROFILE_HDDVD_RW_DL 0x005A -#define MMC_PROFILE_INVALID 0xFFFF - -#define SCSI_ONLY 32 -#define ATAPI_ONLY 16 -#define IMPLEMENTED 8 -#define NONDATA 4 -#define CHECK_READY 2 -#define ALLOW_UA 1 - - -extern uint8_t SCSICommandTable[0x100]; -extern uint8_t mode_sense_pages[0x40]; -extern int readcdmode; - -/* Mode sense/select stuff. */ -extern uint8_t mode_pages_in[256][256]; -extern uint8_t page_flags[256]; -extern uint8_t prefix_len; -extern uint8_t page_current; -#define PAGE_CHANGEABLE 1 -#define PAGE_CHANGED 2 - -struct _scsisense_ { - uint8_t SenseBuffer[18]; - uint8_t SenseLength; - uint8_t UnitAttention; - uint8_t SenseKey; - uint8_t Asc; - uint8_t Ascq; -} SCSISense; - -extern int cd_status; -extern int prev_status; - -enum { - SCSI_NONE = 0, - SCSI_DISK, - SCSI_CDROM, - SCSI_ZIP -}; - -#define MSFtoLBA(m,s,f) ((((m*60)+s)*75)+f) - -#define MSG_COMMAND_COMPLETE 0x00 - -#define BUS_DBP 0x01 -#define BUS_SEL 0x02 -#define BUS_IO 0x04 -#define BUS_CD 0x08 -#define BUS_MSG 0x10 -#define BUS_REQ 0x20 -#define BUS_BSY 0x40 -#define BUS_RST 0x80 -#define BUS_ACK 0x200 -#define BUS_ATN 0x200 -#define BUS_ARB 0x8000 -#define BUS_SETDATA(val) ((uint32_t)val << 16) -#define BUS_GETDATA(val) ((val >> 16) & 0xff) -#define BUS_DATAMASK 0xff0000 - -#define BUS_IDLE (1 << 31) - -#define SCSI_PHASE_DATA_OUT 0 -#define SCSI_PHASE_DATA_IN BUS_IO -#define SCSI_PHASE_COMMAND BUS_CD -#define SCSI_PHASE_STATUS (BUS_CD | BUS_IO) -#define SCSI_PHASE_MESSAGE_OUT (BUS_MSG | BUS_CD) -#define SCSI_PHASE_MESSAGE_IN (BUS_MSG | BUS_CD | BUS_IO) - -typedef struct { - uint8_t *CmdBuffer; - int LunType; - int32_t BufferLength; - uint8_t Status; - uint8_t Phase; -} scsi_device_t; - - -extern scsi_device_t SCSIDevices[SCSI_ID_MAX][SCSI_LUN_MAX]; - -extern void SCSIReset(uint8_t id, uint8_t lun); - -extern int cdrom_add_error_and_subchannel(uint8_t *b, int real_sector_type); -extern int cdrom_LBAtoMSF_accurate(void); - -extern int mode_select_init(uint8_t command, uint16_t pl_length, uint8_t do_save); -extern int mode_select_terminate(int force); -extern int mode_select_write(uint8_t val); - -extern uint8_t scsi_disks[16][8]; - -extern void scsi_dev_log(const char *fmt, ...); +extern void scsi_log(int level, const char *fmt, ...); extern int scsi_card_available(int card); extern const char *scsi_card_getname(int card); @@ -319,67 +49,7 @@ extern const device_t *scsi_card_getdevice(int card); extern int scsi_card_has_config(int card); extern const char *scsi_card_get_internal_name(int card); extern int scsi_card_get_from_internal_name(const char *s); -extern void scsi_mutex(uint8_t start); -extern void scsi_mutex_wait(uint8_t wait); extern void scsi_card_init(void); -extern void scsi_card_reset(void); - -extern int scsi_hd_err_stat_to_scsi(uint8_t id); -extern int scsi_hd_phase_to_scsi(uint8_t id); -extern int find_hdc_for_scsi_id(uint8_t scsi_id, uint8_t scsi_lun); -extern void build_scsi_hd_map(void); -extern void scsi_hd_reset(uint8_t id); -extern void scsi_hd_request_sense_for_scsi(uint8_t id, uint8_t *buffer, uint8_t alloc_length); -extern void scsi_hd_command(uint8_t id, uint8_t *cdb); -extern void scsi_hd_callback(uint8_t id); - - -#pragma pack(push,1) -typedef struct { - uint8_t hi; - uint8_t mid; - uint8_t lo; -} addr24; -#pragma pack(pop) - -#define ADDR_TO_U32(x) (((x).hi<<16)|((x).mid<<8)|((x).lo&0xFF)) -#define U32_TO_ADDR(a,x) do {(a).hi=(x)>>16;(a).mid=(x)>>8;(a).lo=(x)&0xFF;}while(0) - - -/* - * - * Scatter/Gather Segment List Definitions - * - * Adapter limits - */ -#define MAX_SG_DESCRIPTORS 32 /* Always make the array 32 elements long, if less are used, that's not an issue. */ - -#pragma pack(push,1) -typedef struct { - uint32_t Segment; - uint32_t SegmentPointer; -} SGE32; -#pragma pack(pop) - -#pragma pack(push,1) -typedef struct { - addr24 Segment; - addr24 SegmentPointer; -} SGE; -#pragma pack(pop) - -#pragma pack(push,1) -typedef struct { - uint8_t pages[0x40][0x40]; -} mode_sense_pages_t; -#pragma pack(pop) - - -#define MODE_SELECT_PHASE_IDLE 0 -#define MODE_SELECT_PHASE_HEADER 1 -#define MODE_SELECT_PHASE_BLOCK_DESC 2 -#define MODE_SELECT_PHASE_PAGE_HEADER 3 -#define MODE_SELECT_PHASE_PAGE 4 #endif /*EMU_SCSI_H*/ diff --git a/src/devices/scsi/scsi_aha154x.c b/src/devices/scsi/scsi_aha154x.c index 62d5348..206eafb 100644 --- a/src/devices/scsi/scsi_aha154x.c +++ b/src/devices/scsi/scsi_aha154x.c @@ -10,7 +10,7 @@ * made by Adaptec, Inc. These controllers were designed for * the ISA bus. * - * Version: @(#)scsi_aha154x.c 1.0.9 2018/05/06 + * Version: @(#)scsi_aha154x.c 1.0.10 2018/10/05 * * Based on original code from TheCollector1995 and Miran Grca. * @@ -44,6 +44,7 @@ #include #include #include +#define dbglog scsi_dev_log #include "../../emu.h" #include "../../io.h" #include "../../mem.h" @@ -55,13 +56,11 @@ #include "../system/dma.h" #include "../system/pic.h" #include "../system/mca.h" -#include "scsi.h" +#include "scsi_device.h" #include "scsi_aha154x.h" #include "scsi_x54x.h" -#define aha_log scsi_dev_log - #define AHA1540B_330_BIOS_PATH L"scsi/adaptec/aha1540b320_330.bin" #define AHA1540B_334_BIOS_PATH L"scsi/adaptec/aha1540b320_334.bin" #define AHA1540C_BIOS_PATH L"scsi/adaptec/aha1542c102.bin" @@ -163,13 +162,12 @@ shram_cmd(x54x_t *dev, uint8_t cmd) static void eeprom_save(x54x_t *dev) { - FILE *f; + FILE *fp; - f = plat_fopen(nvr_path(dev->nvr_path), L"wb"); - if (f != NULL) { - fwrite(dev->nvr, 1, NVR_SIZE, f); - fclose(f); - f = NULL; + fp = plat_fopen(nvr_path(dev->nvr_path), L"wb"); + if (fp != NULL) { + fwrite(dev->nvr, 1, NVR_SIZE, fp); + fclose(fp); } } @@ -180,7 +178,7 @@ eeprom_cmd(x54x_t *dev, uint8_t cmd,uint8_t arg,uint8_t len,uint8_t off,uint8_t uint8_t r = 0xff; int c; - aha_log("%s: EEPROM cmd=%02x, arg=%02x len=%d, off=%02x\n", + DEBUG("%s: EEPROM cmd=%02x, arg=%02x len=%d, off=%02x\n", dev->name, cmd, arg, len, off); /* Only if we can handle it.. */ @@ -210,7 +208,7 @@ eeprom_cmd(x54x_t *dev, uint8_t cmd,uint8_t arg,uint8_t len,uint8_t off,uint8_t static uint8_t mmap_cmd(x54x_t *dev, uint8_t cmd) { - aha_log("%s: MEMORY cmd=%02x\n", dev->name, cmd); + DEBUG("%s: MEMORY cmd=%02x\n", dev->name, cmd); switch(cmd) { case 0x26: @@ -229,36 +227,36 @@ mmap_cmd(x54x_t *dev, uint8_t cmd) static uint8_t -get_host_id(void *p) +get_host_id(void *priv) { - x54x_t *dev = (x54x_t *)p; + x54x_t *dev = (x54x_t *)priv; return(dev->nvr[0] & 0x07); } static uint8_t -get_irq(void *p) +get_irq(void *priv) { - x54x_t *dev = (x54x_t *)p; + x54x_t *dev = (x54x_t *)priv; return((dev->nvr[1] & 0x07) + 9); } static uint8_t -get_dma(void *p) +get_dma(void *priv) { - x54x_t *dev = (x54x_t *)p; + x54x_t *dev = (x54x_t *)priv; return((dev->nvr[1] >> 4) & 0x07); } static uint8_t -cmd_is_fast(void *p) +cmd_is_fast(void *priv) { - x54x_t *dev = (x54x_t *)p; + x54x_t *dev = (x54x_t *)priv; if (dev->Command == CMD_BIOS_SCSI) return(1); @@ -268,9 +266,9 @@ cmd_is_fast(void *p) static uint8_t -fast_cmds(void *p, uint8_t cmd) +fast_cmds(void *priv, uint8_t cmd) { - x54x_t *dev = (x54x_t *)p; + x54x_t *dev = (x54x_t *)priv; if (cmd == CMD_BIOS_SCSI) { dev->BIOSMailboxReq++; @@ -282,9 +280,9 @@ fast_cmds(void *p, uint8_t cmd) static uint8_t -param_len(void *p) +param_len(void *priv) { - x54x_t *dev = (x54x_t *)p; + x54x_t *dev = (x54x_t *)priv; switch (dev->Command) { case CMD_BIOS_MBINIT: @@ -322,7 +320,7 @@ aha_cmds(void *priv) if (dev->CmdParamLeft) return(0); - aha_log("Running Operation Code 0x%02X\n", dev->Command); + DEBUG("Running Operation Code 0x%02X\n", dev->Command); switch (dev->Command) { case CMD_WR_EEPROM: /* write EEPROM */ /* Sent by CF BIOS. */ @@ -373,10 +371,8 @@ aha_cmds(void *priv) dev->BIOSMailboxCount = mbi->Count; dev->BIOSMailboxOutAddr = ADDR_TO_U32(mbi->Address); - aha_log("Initialize BIOS Mailbox: MBO=0x%08lx, %d entries at 0x%08lx\n", - dev->BIOSMailboxOutAddr, - mbi->Count, - ADDR_TO_U32(mbi->Address)); + DEBUG("Initialize BIOS Mailbox: MBO=0x%08lx, %d entries at 0x%08lx\n", + dev->BIOSMailboxOutAddr, mbi->Count, ADDR_TO_U32(mbi->Address)); dev->Status &= ~STAT_INIT; dev->DataReplyLeft = 0; @@ -452,7 +448,7 @@ do_bios_mail(x54x_t *dev) dev->MailboxIsBIOS = 1; if (! dev->BIOSMailboxCount) { - aha_log("aha_do_bios_mail(): No BIOS Mailboxes\n"); + DEBUG("aha_do_bios_mail(): No BIOS Mailboxes\n"); return; } @@ -559,7 +555,7 @@ aha_mca_write(int port, uint8_t val, void *priv) * * So, remove current address, if any. */ - mem_mapping_disable(&dev->bios.mapping); + mem_map_disable(&dev->bios.mapping); /* Initialize the device if fully configured. */ if (dev->pos_regs[2] & 0x01) { @@ -571,13 +567,14 @@ aha_mca_write(int port, uint8_t val, void *priv) /* Enable or disable the BIOS ROM. */ if (dev->rom_addr != 0x000000) { - mem_mapping_enable(&dev->bios.mapping); - mem_mapping_set_addr(&dev->bios.mapping, dev->rom_addr, ROM_SIZE); + mem_map_enable(&dev->bios.mapping); + mem_map_set_addr(&dev->bios.mapping, dev->rom_addr, ROM_SIZE); } /* Say hello. */ - pclog("AHA-1640: I/O=%04x, IRQ=%d, DMA=%d, BIOS @%05X, HOST ID %i\n", - dev->Base, dev->Irq, dev->DmaChannel, dev->rom_addr, dev->HostID); + INFO("%s: I/O=%04x, IRQ=%d, DMA=%d, BIOS @%05X, HOST ID %i\n", + dev->name, dev->Base, dev->Irq, dev->DmaChannel, + dev->rom_addr, dev->HostID); } } @@ -589,16 +586,16 @@ set_bios(x54x_t *dev) uint32_t size; uint32_t mask; uint32_t temp; - FILE *f; + FILE *fp; int i; /* Only if this device has a BIOS ROM. */ if (dev->bios_path == NULL) return; /* Open the BIOS image file and make sure it exists. */ - aha_log("%s: loading BIOS from '%ls'\n", dev->name, dev->bios_path); - if ((f = plat_fopen(rom_path(dev->bios_path), L"rb")) == NULL) { - aha_log("%s: BIOS ROM not found!\n", dev->name); + DEBUG("%s: loading BIOS from '%ls'\n", dev->name, dev->bios_path); + if ((fp = plat_fopen(rom_path(dev->bios_path), L"rb")) == NULL) { + ERRLOG("%s: BIOS ROM not found!\n", dev->name); return; } @@ -609,33 +606,33 @@ set_bios(x54x_t *dev) * this special case, we can't: we may need WRITE access to the * memory later on. */ - (void)fseek(f, 0L, SEEK_END); - temp = ftell(f); - (void)fseek(f, 0L, SEEK_SET); + (void)fseek(fp, 0L, SEEK_END); + temp = ftell(fp); + (void)fseek(fp, 0L, SEEK_SET); /* Load first chunk of BIOS (which is the main BIOS, aka ROM1.) */ - dev->rom1 = malloc(ROM_SIZE); - (void)fread(dev->rom1, ROM_SIZE, 1, f); + dev->rom1 = (uint8_t *)mem_alloc(ROM_SIZE); + (void)fread(dev->rom1, ROM_SIZE, 1, fp); temp -= ROM_SIZE; if (temp > 0) { - dev->rom2 = malloc(ROM_SIZE); - (void)fread(dev->rom2, ROM_SIZE, 1, f); + dev->rom2 = (uint8_t *)mem_alloc(ROM_SIZE); + (void)fread(dev->rom2, ROM_SIZE, 1, fp); temp -= ROM_SIZE; } else { dev->rom2 = NULL; } if (temp != 0) { - aha_log("%s: BIOS ROM size invalid!\n", dev->name); + ERRLOG("%s: BIOS ROM size invalid!\n", dev->name); free(dev->rom1); if (dev->rom2 != NULL) free(dev->rom2); - (void)fclose(f); + (void)fclose(fp); return; } - temp = ftell(f); + temp = ftell(fp); if (temp > ROM_SIZE) temp = ROM_SIZE; - (void)fclose(f); + (void)fclose(fp); /* Adjust BIOS size in chunks of 2K, as per BIOS spec. */ size = 0x10000; @@ -646,8 +643,8 @@ set_bios(x54x_t *dev) if (temp <= 0x2000) size = 0x2000; mask = (size - 1); - aha_log("%s: BIOS at 0x%06lX, size %lu, mask %08lx\n", - dev->name, dev->rom_addr, size, mask); + INFO("%s: BIOS at 0x%06lX, size %lu, mask %08lx\n", + dev->name, dev->rom_addr, size, mask); /* Initialize the ROM entry for this BIOS. */ memset(&dev->bios, 0x00, sizeof(rom_t)); @@ -659,11 +656,11 @@ set_bios(x54x_t *dev) dev->bios.mask = mask; /* Map this system into the memory map. */ - mem_mapping_add(&dev->bios.mapping, dev->rom_addr, size, - mem_read, NULL, NULL, /* aha_mem_readw, aha_mem_readl, */ - mem_write, NULL, NULL, - dev->bios.rom, MEM_MAPPING_EXTERNAL, dev); - mem_mapping_disable(&dev->bios.mapping); + mem_map_add(&dev->bios.mapping, dev->rom_addr, size, + mem_read, NULL, NULL, /* aha_mem_readw, aha_mem_readl, */ + mem_write, NULL, NULL, + dev->bios.rom, MEM_MAPPING_EXTERNAL, dev); + mem_map_disable(&dev->bios.mapping); /* * Patch the ROM BIOS image for stuff Adaptec deliberately @@ -676,10 +673,10 @@ set_bios(x54x_t *dev) */ if (dev->rom_ioaddr != 0x0000) { /* Look up the I/O address in the table. */ - for (i=0; i<8; i++) + for (i = 0; i < 8; i++) if (aha_ports[i] == dev->Base) break; if (i == 8) { - aha_log("%s: invalid I/O address %04x selected!\n", + ERRLOG("%s: invalid I/O address %04x selected!\n", dev->name, dev->Base); return; } @@ -712,20 +709,19 @@ init_nvr(x54x_t *dev) static void set_nvr(x54x_t *dev) { - FILE *f; + FILE *fp; /* Only if this device has an EEPROM. */ if (dev->nvr_path == NULL) return; /* Allocate and initialize the EEPROM. */ - dev->nvr = (uint8_t *)malloc(NVR_SIZE); + dev->nvr = (uint8_t *)mem_alloc(NVR_SIZE); memset(dev->nvr, 0x00, NVR_SIZE); - f = plat_fopen(nvr_path(dev->nvr_path), L"rb"); - if (f != NULL) { - (void)fread(dev->nvr, 1, NVR_SIZE, f); - fclose(f); - f = NULL; + fp = plat_fopen(nvr_path(dev->nvr_path), L"rb"); + if (fp != NULL) { + (void)fread(dev->nvr, 1, NVR_SIZE, fp); + fclose(fp); } else { init_nvr(dev); } @@ -739,7 +735,7 @@ aha_init(const device_t *info) x54x_t *dev; /* Call common initializer. */ - dev = x54x_init(info); + dev = (x54x_t *)x54x_init(info); /* * Set up the (initial) I/O address, IRQ and DMA info. @@ -866,8 +862,8 @@ aha_init(const device_t *info) /* Enable the memory. */ if (dev->rom_addr != 0x000000) { - mem_mapping_enable(&dev->bios.mapping); - mem_mapping_set_addr(&dev->bios.mapping, dev->rom_addr, ROM_SIZE); + mem_map_enable(&dev->bios.mapping); + mem_map_set_addr(&dev->bios.mapping, dev->rom_addr, ROM_SIZE); } } } @@ -877,232 +873,232 @@ aha_init(const device_t *info) static const device_config_t aha_154xb_config[] = { + { + "base", "Address", CONFIG_HEX16, "", 0x334, { - "base", "Address", CONFIG_HEX16, "", 0x334, { - { - "None", 0 - }, - { - "0x330", 0x330 - }, - { - "0x334", 0x334 - }, - { - "0x230", 0x230 - }, - { - "0x234", 0x234 - }, - { - "0x130", 0x130 - }, - { - "0x134", 0x134 - }, - { - "" - } + "None", 0 }, - }, + { + "0x330", 0x330 + }, + { + "0x334", 0x334 + }, + { + "0x230", 0x230 + }, + { + "0x234", 0x234 + }, + { + "0x130", 0x130 + }, + { + "0x134", 0x134 + }, + { + "" + } + } + }, + { + "irq", "IRQ", CONFIG_SELECTION, "", 9, { - "irq", "IRQ", CONFIG_SELECTION, "", 9, { - { - "IRQ 9", 9 - }, - { - "IRQ 10", 10 - }, - { - "IRQ 11", 11 - }, - { - "IRQ 12", 12 - }, - { - "IRQ 14", 14 - }, - { - "IRQ 15", 15 - }, - { - "" - } + "IRQ 9", 9 }, - }, + { + "IRQ 10", 10 + }, + { + "IRQ 11", 11 + }, + { + "IRQ 12", 12 + }, + { + "IRQ 14", 14 + }, + { + "IRQ 15", 15 + }, + { + "" + } + } + }, + { + "dma", "DMA channel", CONFIG_SELECTION, "", 6, { - "dma", "DMA channel", CONFIG_SELECTION, "", 6, { - { - "DMA 5", 5 - }, - { - "DMA 6", 6 - }, - { - "DMA 7", 7 - }, - { - "" - } + "DMA 5", 5 }, - }, + { + "DMA 6", 6 + }, + { + "DMA 7", 7 + }, + { + "" + } + } + }, + { + "hostid", "Host ID", CONFIG_SELECTION, "", 7, { - "hostid", "Host ID", CONFIG_SELECTION, "", 7, { - { - "0", 0 - }, - { - "1", 1 - }, - { - "2", 2 - }, - { - "3", 3 - }, - { - "4", 4 - }, - { - "5", 5 - }, - { - "6", 6 - }, - { - "7", 7 - }, - { - "" - } + "0", 0 }, - }, + { + "1", 1 + }, + { + "2", 2 + }, + { + "3", 3 + }, + { + "4", 4 + }, + { + "5", 5 + }, + { + "6", 6 + }, + { + "7", 7 + }, + { + "" + } + } + }, + { + "bios_addr", "BIOS Address", CONFIG_HEX20, "", 0, { - "bios_addr", "BIOS Address", CONFIG_HEX20, "", 0, { - { - "Disabled", 0 - }, - { - "C800H", 0xc8000 - }, - { - "D000H", 0xd0000 - }, - { - "D800H", 0xd8000 - }, - { - "" - } + "Disabled", 0 }, - }, - { - "", "", -1 - } + { + "C800H", 0xc8000 + }, + { + "D000H", 0xd0000 + }, + { + "D800H", 0xd8000 + }, + { + "" + } + } + }, + { + "", "", -1 + } }; static const device_config_t aha_154x_config[] = { + { + "base", "Address", CONFIG_HEX16, "", 0x334, { - "base", "Address", CONFIG_HEX16, "", 0x334, { - { - "None", 0 - }, - { - "0x330", 0x330 - }, - { - "0x334", 0x334 - }, - { - "0x230", 0x230 - }, - { - "0x234", 0x234 - }, - { - "0x130", 0x130 - }, - { - "0x134", 0x134 - }, - { - "" - } + "None", 0 }, - }, + { + "0x330", 0x330 + }, + { + "0x334", 0x334 + }, + { + "0x230", 0x230 + }, + { + "0x234", 0x234 + }, + { + "0x130", 0x130 + }, + { + "0x134", 0x134 + }, + { + "" + } + } + }, + { + "irq", "IRQ", CONFIG_SELECTION, "", 9, { - "irq", "IRQ", CONFIG_SELECTION, "", 9, { - { - "IRQ 9", 9 - }, - { - "IRQ 10", 10 - }, - { - "IRQ 11", 11 - }, - { - "IRQ 12", 12 - }, - { - "IRQ 14", 14 - }, - { - "IRQ 15", 15 - }, - { - "" - } + "IRQ 9", 9 }, - }, + { + "IRQ 10", 10 + }, + { + "IRQ 11", 11 + }, + { + "IRQ 12", 12 + }, + { + "IRQ 14", 14 + }, + { + "IRQ 15", 15 + }, + { + "" + } + } + }, + { + "dma", "DMA channel", CONFIG_SELECTION, "", 6, { - "dma", "DMA channel", CONFIG_SELECTION, "", 6, { - { - "DMA 5", 5 - }, - { - "DMA 6", 6 - }, - { - "DMA 7", 7 - }, - { - "" - } + "DMA 5", 5 }, - }, + { + "DMA 6", 6 + }, + { + "DMA 7", 7 + }, + { + "" + } + } + }, + { + "bios_addr", "BIOS Address", CONFIG_HEX20, "", 0, { - "bios_addr", "BIOS Address", CONFIG_HEX20, "", 0, { - { - "Disabled", 0 - }, - { - "C800H", 0xc8000 - }, - { - "D000H", 0xd0000 - }, - { - "D800H", 0xd8000 - }, - { - "" - } + "Disabled", 0 }, - }, - { - "", "", -1 - } + { + "C800H", 0xc8000 + }, + { + "D000H", 0xd0000 + }, + { + "D800H", 0xd8000 + }, + { + "" + } + } + }, + { + "", "", -1 + } }; diff --git a/src/devices/scsi/scsi_bus.c b/src/devices/scsi/scsi_bus.c deleted file mode 100644 index 68f2c3c..0000000 --- a/src/devices/scsi/scsi_bus.c +++ /dev/null @@ -1,389 +0,0 @@ -/* - * VARCem Virtual ARchaeological Computer EMulator. - * An emulator of (mostly) x86-based PC systems and devices, - * using the ISA,EISA,VLB,MCA and PCI system buses, roughly - * spanning the era between 1981 and 1995. - * - * This file is part of the VARCem Project. - * - * The generic SCSI bus operations handler. - * - * NOTES: For now ported from PCem with some modifications - * but at least it's a start. - * - * Version: @(#)scsi_bus.c 1.0.3 2018/09/21 - * - * Authors: Fred N. van Kempen, - * Miran Grca, - * TheCollector1995, - * - * Copyright 2017,2018 Fred N. van Kempen. - * Copyright 2016-2018 Miran Grca. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the: - * - * Free Software Foundation, Inc. - * 59 Temple Place - Suite 330 - * Boston, MA 02111-1307 - * USA. - */ -#include -#include -#include -#include -#include -#include -#define HAVE_STDARG_H -#include "../../emu.h" -#include "scsi.h" -#include "scsi_device.h" - - -#define STATE_IDLE 0 -#define STATE_COMMAND 1 -#define STATE_COMMANDWAIT 2 -#define STATE_DATAIN 3 -#define STATE_DATAOUT 4 -#define STATE_STATUS 5 -#define STATE_MESSAGEIN 6 -#define STATE_PHASESEL 7 - -#define SET_BUS_STATE(bus, state) bus->bus_out = (bus->bus_out & ~(SCSI_PHASE_MESSAGE_IN)) | (state & (SCSI_PHASE_MESSAGE_IN)) - -uint32_t SCSI_BufferLength; -#ifdef ENABLE_SCSI_BUS_LOG -int scsi_bus_do_log = ENABLE_SCSI_BUS_LOG; -#endif - - -static void -scsi_bus_log(const char *fmt, ...) -{ -#ifdef ENABLE_SCSI_BUS_LOG - va_list ap; - - if (scsi_bus_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); - } -#endif -} - - -/* get the length of a SCSI command based on its command byte type */ -static int get_cmd_len(int cbyte) -{ - int len = -1; - int group; - - group = (cbyte>>5) & 7; - - if (group == 0) len = 6; - if (group == 1 || group == 2) len = 10; - if (group == 5) len = 12; - -// scsi_bus_log("Command group %d, length %d\n", group, len); - - return(len); -} - - -static int -get_dev_id(uint8_t data) -{ - int c; - - for (c = 0; c < SCSI_ID_MAX; c++) { - if (data & (1 << c)) return(c); - } - - return(-1); -} - - -int -scsi_bus_update(scsi_bus_t *bus, int bus_assert) -{ - scsi_device_t *dev; - uint8_t lun = 0; - - if (bus_assert & BUS_ARB) - bus->state = STATE_IDLE; - - switch (bus->state) { - case STATE_IDLE: - scsi_bus_log("State Idle\n"); - bus->clear_req = bus->change_state_delay = bus->new_req_delay = 0; - if ((bus_assert & BUS_SEL) && !(bus_assert & BUS_BSY)) { - uint8_t sel_data = BUS_GETDATA(bus_assert); - - bus->dev_id = get_dev_id(sel_data); - - if ((bus->dev_id != -1) && scsi_device_present(bus->dev_id, 0)) { - bus->bus_out |= BUS_BSY; - bus->state = STATE_PHASESEL; - } - //scsi_bus_log("Device id %i\n", bus->dev_id); - break; - } - break; - - case STATE_PHASESEL: - scsi_bus_log("State Phase Sel\n"); - if (! (bus_assert & BUS_SEL)) { - if (! (bus_assert & BUS_ATN)) { - if ((bus->dev_id != -1) && - scsi_device_present(bus->dev_id, 0)) { - bus->state = STATE_COMMAND; - bus->bus_out = BUS_BSY | BUS_REQ; - bus->command_pos = 0; - SET_BUS_STATE(bus, SCSI_PHASE_COMMAND); - } else { - bus->state = STATE_IDLE; - bus->bus_out = 0; - } - } else - fatal("dropped sel %x\n", bus_assert & BUS_ATN); - } - break; - - case STATE_COMMAND: - if ((bus_assert & BUS_ACK) && !(bus->bus_in & BUS_ACK)) { - scsi_bus_log("State Command\n"); - bus->command[bus->command_pos++] = BUS_GETDATA(bus_assert); - - bus->clear_req = 3; - bus->new_state = bus->bus_out & SCSI_PHASE_MESSAGE_IN; - bus->bus_out &= ~BUS_REQ; - - if (get_cmd_len(bus->command[0]) == bus->command_pos) { - lun = (bus->command[1] >> 5) & 7; - bus->data_pos = 0; - - dev = &SCSIDevices[bus->dev_id][lun]; - - scsi_bus_log("Command 0x%02X\n", bus->command[0]); - - dev->BufferLength = -1; - - scsi_device_command_phase0(bus->dev_id, lun, - get_cmd_len(bus->command[0]), - bus->command); - - scsi_bus_log("(%02X:%02X): Command %02X: Buffer Length %i, SCSI Phase %02X\n", bus->dev_id, lun, bus->command[0], dev->BufferLength, dev->Phase); - - if ((dev->Phase == SCSI_PHASE_DATA_IN) || - (dev->Phase == SCSI_PHASE_DATA_OUT)) { - scsi_bus_log("dev->CmdBuffer = %08X\n", dev->CmdBuffer); - dev->CmdBuffer = (uint8_t *) malloc(dev->BufferLength); - scsi_bus_log("dev->CmdBuffer = %08X\n", dev->CmdBuffer); - } - - if (dev->Phase == SCSI_PHASE_DATA_OUT) { - /* Write direction commands have delayed execution - only execute them after the bus has gotten all the data from the host. */ - scsi_bus_log("Next state is data out\n"); - - bus->state = STATE_COMMANDWAIT; - bus->clear_req = 0; - } else { - /* Other command - execute immediately. */ - bus->new_state = dev->Phase; - if (dev->Phase == SCSI_PHASE_DATA_IN) { - scsi_device_command_phase1(bus->dev_id, lun); - } - - bus->change_state_delay = 4; - } - } - } - break; - - case STATE_COMMANDWAIT: - bus->new_state = SCSI_PHASE_DATA_OUT; - bus->change_state_delay = 4; - bus->clear_req = 4; - break; - - case STATE_DATAIN: - if ((bus_assert & BUS_ACK) && !(bus->bus_in & BUS_ACK)) { - scsi_bus_log("State Data In\n"); - - /* This seems to be read, so we first execute the command, then we return the bytes to the host. */ - - lun = (bus->command[1] >> 5) & 7; - - dev = &SCSIDevices[bus->dev_id][lun]; - - if (bus->data_pos >= SCSIDevices[bus->dev_id][lun].BufferLength) { - free(dev->CmdBuffer); - dev->CmdBuffer = NULL; - bus->bus_out &= ~BUS_REQ; - bus->new_state = SCSI_PHASE_STATUS; - bus->change_state_delay = 4; - bus->new_req_delay = 8; - } else { - uint8_t val = dev->CmdBuffer[bus->data_pos++]; - - bus->bus_out = (bus->bus_out & ~BUS_DATAMASK) | BUS_SETDATA(val) | BUS_DBP | BUS_REQ; - bus->clear_req = 3; - bus->bus_out &= ~BUS_REQ; - bus->new_state = SCSI_PHASE_DATA_IN; - } - } - break; - - case STATE_DATAOUT: - if ((bus_assert & BUS_ACK) && !(bus->bus_in & BUS_ACK)) { - scsi_bus_log("State Data Out\n"); - - lun = (bus->command[1] >> 5) & 7; - - dev = &SCSIDevices[bus->dev_id][lun]; - - /* This is write, so first get the data from the host, then execute the last phase of the command. */ - dev->CmdBuffer[bus->data_pos++] = BUS_GETDATA(bus_assert); - - if (bus->data_pos >= SCSIDevices[bus->dev_id][lun].BufferLength) { - /* scsi_bus_log("%04X bytes written (%02X %02X)\n", bus->data_pos, bus->command[0], bus->command[1]); */ - scsi_bus_log("Actually executing write command\n"); - scsi_device_command_phase1(bus->dev_id, lun); - free(dev->CmdBuffer); - dev->CmdBuffer = NULL; - bus->bus_out &= ~BUS_REQ; - bus->new_state = SCSI_PHASE_STATUS; - bus->change_state_delay = 4; - bus->new_req_delay = 8; - } else { - bus->bus_out |= BUS_REQ; - } - } - break; - - case STATE_STATUS: - scsi_bus_log("State Status\n"); - - if ((bus_assert & BUS_ACK) && !(bus->bus_in & BUS_ACK)) { - /* scsi_bus_log("Preparing for message in\n"); */ - bus->bus_out &= ~BUS_REQ; - bus->new_state = SCSI_PHASE_MESSAGE_IN; - bus->change_state_delay = 4; - bus->new_req_delay = 8; - } - break; - - case STATE_MESSAGEIN: - scsi_bus_log("State Message In\n"); - - if ((bus_assert & BUS_ACK) && !(bus->bus_in & BUS_ACK)) { - bus->bus_out &= ~BUS_REQ; - bus->new_state = BUS_IDLE; - bus->change_state_delay = 4; - } - break; - } - - bus->bus_in = bus_assert; - - return(bus->bus_out | bus->bus_in); -} - - -int -scsi_bus_read(scsi_bus_t *bus) -{ - scsi_device_t *dev; - uint8_t lun = 0; - - if (bus->clear_req) { - bus->clear_req--; - if (!bus->clear_req) { - scsi_bus_log("Clear REQ\n"); - - SET_BUS_STATE(bus, bus->new_state); - bus->bus_out |= BUS_REQ; - } - } - - if (bus->change_state_delay) { - bus->change_state_delay--; - if (!bus->change_state_delay) { - uint8_t val; - - scsi_bus_log("Change state delay\n"); - - SET_BUS_STATE(bus, bus->new_state); - - switch (bus->bus_out & SCSI_PHASE_MESSAGE_IN) { - case SCSI_PHASE_DATA_IN: - lun = (bus->command[1] >> 5) & 7; - dev = &SCSIDevices[bus->dev_id][lun]; - - scsi_bus_log("Phase data in\n"); - bus->state = STATE_DATAIN; - val = dev->CmdBuffer[bus->data_pos++]; - bus->bus_out = (bus->bus_out & ~BUS_DATAMASK) | BUS_SETDATA(val) | BUS_DBP; - break; - - case SCSI_PHASE_DATA_OUT: - scsi_bus_log("Phase data out\n"); - if (bus->new_state & BUS_IDLE) { - bus->state = STATE_IDLE; - bus->bus_out &= ~BUS_BSY; - } else { - bus->state = STATE_DATAOUT; - } - break; - - case SCSI_PHASE_STATUS: - lun = (bus->command[1] >> 5) & 7; - dev = &SCSIDevices[bus->dev_id][lun]; - - scsi_bus_log("Phase status\n"); - bus->state = STATE_STATUS; - bus->bus_out |= BUS_REQ; - bus->bus_out = (bus->bus_out & ~BUS_DATAMASK) | BUS_SETDATA(dev->Status) | BUS_DBP; - /* scsi_bus_log("SCSI Status (command %02X): %02X (%08X)\n", bus->command[0], dev->Status, bus->bus_out); */ - break; - - case SCSI_PHASE_MESSAGE_IN: - scsi_bus_log("Phase message in\n"); - /* scsi_bus_log("Message in\n"); */ - bus->state = STATE_MESSAGEIN; - bus->bus_out = (bus->bus_out & ~BUS_DATAMASK) | BUS_SETDATA(0) | BUS_DBP; - break; - - default: - fatal("change_state_delay bad state %x\n", bus->bus_out); - } - } - } - - if (bus->new_req_delay) { - bus->new_req_delay--; - if (!bus->new_req_delay) { - bus->bus_out |= BUS_REQ; - } - } - - return(bus->bus_out); -} - - -int -scsi_bus_match(scsi_bus_t *bus, int bus_assert) -{ - return((bus_assert & (BUS_CD | BUS_IO | BUS_MSG)) == - (bus->bus_out & (BUS_CD | BUS_IO | BUS_MSG))); -} diff --git a/src/devices/scsi/scsi_buslogic.c b/src/devices/scsi/scsi_buslogic.c index fa0325f..d4e3d95 100644 --- a/src/devices/scsi/scsi_buslogic.c +++ b/src/devices/scsi/scsi_buslogic.c @@ -13,7 +13,7 @@ * 1 - BT-545S ISA; * 2 - BT-958D PCI * - * Version: @(#)scsi_buslogic.c 1.0.10 2018/05/06 + * Version: @(#)scsi_buslogic.c 1.0.11 2018/09/22 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -45,6 +45,7 @@ #include #include #include +#define dbglog scsi_dev_log #include "../../emu.h" #include "../../io.h" #include "../../mem.h" @@ -63,8 +64,6 @@ #include "scsi_x54x.h" -#define buslogic_log scsi_dev_log - #define BT542_BIOS_PATH L"scsi/buslogic/bt-542bh_bios.rom" #define BT545_BIOS_PATH L"scsi/buslogic/bt-545s_bios.rom" #define BT545_AUTO_BIOS_PATH L"scsi/buslogic/bt-545s_autoscsi.rom" @@ -76,9 +75,19 @@ #define BT958D_SCAM_BIOS_PATH L"scsi/buslogic/bt-958d_scam.rom" +enum { + CHIP_BUSLOGIC_ISA_542, + CHIP_BUSLOGIC_ISA, + CHIP_BUSLOGIC_MCA, + CHIP_BUSLOGIC_EISA, + CHIP_BUSLOGIC_VLB, + CHIP_BUSLOGIC_PCI +}; + + /* - * Auto SCSI structure which is located - * in host adapter RAM and contains several + * Auto SCSI structure which is located in + * host adapter RAM and contains several * configuration parameters. */ #pragma pack(push,1) @@ -229,7 +238,6 @@ typedef struct { } MailboxInitExtended_t; #pragma pack(pop) -#pragma pack(push,1) typedef struct { rom_t bios; int ExtendedLUNCCBFormat; @@ -245,17 +253,6 @@ typedef struct { uint8_t AutoSCSIROM[32768]; uint8_t SCAMData[65536]; } buslogic_data_t; -#pragma pack(pop) - - -enum { - CHIP_BUSLOGIC_ISA_542, - CHIP_BUSLOGIC_ISA, - CHIP_BUSLOGIC_MCA, - CHIP_BUSLOGIC_EISA, - CHIP_BUSLOGIC_VLB, - CHIP_BUSLOGIC_PCI -}; static wchar_t * @@ -279,8 +276,10 @@ GetNVRFileName(buslogic_data_t *bl) default: fatal("Unrecognized BusLogic chip: %i\n", bl->chip); - return NULL; + break; } + + return NULL; } @@ -494,7 +493,7 @@ get_irq(void *priv) uint8_t bl_irq[7] = { 0, 9, 10, 11, 12, 14, 15 }; HALocalRAM *halr = &bl->LocalRAM; - if (bl->chip == CHIP_BUSLOGIC_PCI) + if ((bl->chip == CHIP_BUSLOGIC_ISA_542) || (bl->chip == CHIP_BUSLOGIC_PCI)) return dev->Irq; else return bl_irq[halr->structured.autoSCSIData.uIrqChannel]; @@ -511,6 +510,8 @@ get_dma(void *priv) if (bl->chip == CHIP_BUSLOGIC_PCI) return (dev->Base ? 7 : 0); + else if (bl->chip == CHIP_BUSLOGIC_ISA_542) + return dev->DmaChannel; else return bl_dma[halr->structured.autoSCSIData.uDMAChannel]; } @@ -546,6 +547,7 @@ param_len(void *priv) return 2; case 0x94: + case 0xFB: return 3; case 0x93: /* Valid only for VLB */ @@ -573,29 +575,29 @@ static void SCSIBIOSDMATransfer(ESCMD *ESCSICmd, uint8_t TargetID, uint8_t LUN, int dir) { uint32_t DataPointer = ESCSICmd->DataPointer; - uint32_t DataLength = ESCSICmd->DataLength; + int DataLength = ESCSICmd->DataLength; uint32_t Address; uint32_t TransferLength; if (ESCSICmd->DataDirection == 0x03) { /* Non-data command. */ - buslogic_log("SCSIBIOSDMATransfer(): Non-data control byte\n"); + DEBUG("SCSIBIOSDMATransfer(): Non-data control byte\n"); return; } - buslogic_log("SCSIBIOSDMATransfer(): BIOS Data Buffer read: length %d, pointer 0x%04X\n", DataLength, DataPointer); + DEBUG("SCSIBIOSDMATransfer(): BIOS Data Buffer read: length %d, pointer 0x%04X\n", DataLength, DataPointer); /* If the control byte is 0x00, it means that the transfer direction is set up by the SCSI command without checking its length, so do this procedure for both read/write commands. */ if ((DataLength > 0) && (SCSIDevices[TargetID][LUN].BufferLength > 0)) { Address = DataPointer; - TransferLength = MIN(DataLength, (uint32_t)SCSIDevices[TargetID][LUN].BufferLength); + TransferLength = MIN(DataLength, SCSIDevices[TargetID][LUN].BufferLength); if (dir && ((ESCSICmd->DataDirection == CCB_DATA_XFER_OUT) || (ESCSICmd->DataDirection == 0x00))) { - buslogic_log("BusLogic BIOS DMA: Reading %i bytes from %08X\n", TransferLength, Address); + DEBUG("BusLogic BIOS DMA: Reading %i bytes from %08X\n", TransferLength, Address); DMAPageRead(Address, (uint8_t *)SCSIDevices[TargetID][LUN].CmdBuffer, TransferLength); } else if (!dir && ((ESCSICmd->DataDirection == CCB_DATA_XFER_IN) || (ESCSICmd->DataDirection == 0x00))) { - buslogic_log("BusLogic BIOS DMA: Writing %i bytes at %08X\n", TransferLength, Address); + DEBUG("BusLogic BIOS DMA: Writing %i bytes at %08X\n", TransferLength, Address); DMAPageWrite(Address, (uint8_t *)SCSIDevices[TargetID][LUN].CmdBuffer, TransferLength); } } @@ -609,7 +611,6 @@ SCSIBIOSRequestSetup(x54x_t *dev, uint8_t *CmdBuf, uint8_t *DataInBuf, uint8_t D uint32_t i; uint8_t temp_cdb[12]; int target_cdb_len = 12; - uint8_t target_id = 0; int phase; DataInBuf[0] = DataInBuf[1] = 0; @@ -619,48 +620,46 @@ SCSIBIOSRequestSetup(x54x_t *dev, uint8_t *CmdBuf, uint8_t *DataInBuf, uint8_t D DataInBuf[3] = SCSI_STATUS_OK; return; } - - buslogic_log("Scanning SCSI Target ID %i\n", ESCSICmd->TargetId); + + DEBUG("Scanning SCSI Target ID %i\n", ESCSICmd->TargetId); SCSIDevices[ESCSICmd->TargetId][ESCSICmd->LogicalUnit].Status = SCSI_STATUS_OK; if (!scsi_device_present(ESCSICmd->TargetId, 0)) { - buslogic_log("SCSI Target ID %i has no device attached\n",ESCSICmd->TargetId,ESCSICmd->LogicalUnit); + DEBUG("SCSI Target ID %i has no device attached\n", ESCSICmd->TargetId,ESCSICmd->LogicalUnit); DataInBuf[2] = CCB_SELECTION_TIMEOUT; DataInBuf[3] = SCSI_STATUS_OK; } else { - buslogic_log("SCSI Target ID %i detected and working\n", ESCSICmd->TargetId, ESCSICmd->LogicalUnit); + DEBUG("SCSI Target ID %i detected and working\n", ESCSICmd->TargetId, ESCSICmd->LogicalUnit); - buslogic_log("Transfer Control %02X\n", ESCSICmd->DataDirection); - buslogic_log("CDB Length %i\n", ESCSICmd->CDBLength); + DEBUG("Transfer Control %02X\n", ESCSICmd->DataDirection); + DEBUG("CDB Length %i\n", ESCSICmd->CDBLength); if (ESCSICmd->DataDirection > 0x03) { - buslogic_log("Invalid control byte: %02X\n", - ESCSICmd->DataDirection); + DEBUG("Invalid control byte: %02X\n", ESCSICmd->DataDirection); } } x54x_buf_alloc(ESCSICmd->TargetId, ESCSICmd->LogicalUnit, ESCSICmd->DataLength); - target_cdb_len = scsi_device_cdb_length(ESCSICmd->TargetId, ESCSICmd->LogicalUnit); + target_cdb_len = 12; - if (!scsi_device_valid(ESCSICmd->TargetId, ESCSICmd->LogicalUnit)) fatal("SCSI target on %02i:%02i has disappeared\n", ESCSICmd->TargetId, ESCSICmd->LogicalUnit); + if (!scsi_device_valid(ESCSICmd->TargetId, ESCSICmd->LogicalUnit)) fatal("SCSI target on ID %02i:%02i has disappeared\n", ESCSICmd->TargetId, ESCSICmd->LogicalUnit); - buslogic_log("SCSI target command being executed on: SCSI ID %i, SCSI LUN %i, Target %i\n", ESCSICmd->TargetId, ESCSICmd->LogicalUnit, target_id); + DEBUG("SCSI target command being executed on: SCSI ID %i, SCSI LUN %i\n", ESCSICmd->TargetId, ESCSICmd->LogicalUnit); - buslogic_log("SCSI Cdb[0]=0x%02X\n", ESCSICmd->CDB[0]); + DEBUG("SCSI Cdb[0]=0x%02X\n", ESCSICmd->CDB[0]); for (i = 1; i < ESCSICmd->CDBLength; i++) { - buslogic_log("SCSI Cdb[%i]=%i\n", i, ESCSICmd->CDB[i]); + DEBUG("SCSI Cdb[%i]=%i\n", i, ESCSICmd->CDB[i]); } memset(temp_cdb, 0, target_cdb_len); - if (ESCSICmd->CDBLength <= target_cdb_len) { + if (ESCSICmd->CDBLength <= target_cdb_len) memcpy(temp_cdb, ESCSICmd->CDB, ESCSICmd->CDBLength); - } else { + else memcpy(temp_cdb, ESCSICmd->CDB, target_cdb_len); - } SCSIDevices[ESCSICmd->TargetId][ESCSICmd->LogicalUnit].BufferLength = ESCSICmd->DataLength; - scsi_device_command_phase0(ESCSICmd->TargetId, ESCSICmd->LogicalUnit, ESCSICmd->CDBLength, temp_cdb); + scsi_device_command_phase0(ESCSICmd->TargetId, ESCSICmd->LogicalUnit, temp_cdb); phase = SCSIDevices[ESCSICmd->TargetId][ESCSICmd->LogicalUnit].Phase; if (phase != SCSI_PHASE_STATUS) { @@ -673,7 +672,7 @@ SCSIBIOSRequestSetup(x54x_t *dev, uint8_t *CmdBuf, uint8_t *DataInBuf, uint8_t D x54x_buf_free(ESCSICmd->TargetId, ESCSICmd->LogicalUnit); - buslogic_log("BIOS Request complete\n"); + DEBUG("BIOS Request complete\n"); if (SCSIDevices[ESCSICmd->TargetId][ESCSICmd->LogicalUnit].Status == SCSI_STATUS_OK) { DataInBuf[2] = CCB_COMPLETE; @@ -696,8 +695,7 @@ buslogic_cmds(void *priv) FILE *f; uint16_t TargetsPresentMask = 0; uint32_t Offset; - int i = 0; - int j = 0; + int i, j; MailboxInitExtended_t *MailboxInitE; ReplyInquireExtendedSetupInformation *ReplyIESI; BuslogicPCIInformation_t *ReplyPI; @@ -719,7 +717,7 @@ buslogic_cmds(void *priv) memset(dev->DataBuf, 0, 8); for (i = 8; i < 15; i++) { dev->DataBuf[i-8] = 0; - for (j=0; j<8; j++) { + for (j = 0; j < 8; j++) { if (scsi_device_present(i, j) && (i != get_host_id(dev))) dev->DataBuf[i-8] |= (1<DataBuf[0] = TargetsPresentMask & 0xFF; + dev->DataBuf[0] = TargetsPresentMask & 0xff; dev->DataBuf[1] = TargetsPresentMask >> 8; dev->DataReplyLeft = 2; break; @@ -754,10 +752,11 @@ buslogic_cmds(void *priv) dev->MailboxOutAddr = MailboxInitE->Address; dev->MailboxInAddr = MailboxInitE->Address + (dev->MailboxCount * sizeof(Mailbox32_t)); - buslogic_log("Buslogic Extended Initialize Mailbox Command\n"); - buslogic_log("Mailbox Out Address=0x%08X\n", dev->MailboxOutAddr); - buslogic_log("Mailbox In Address=0x%08X\n", dev->MailboxInAddr); - buslogic_log("Initialized Extended Mailbox, %d entries at 0x%08X\n", MailboxInitE->Count, MailboxInitE->Address); + DEBUG("Buslogic Extended Initialize Mailbox Command\n"); + DEBUG("Mailbox Out Address=0x%08X\n", dev->MailboxOutAddr); + DEBUG("Mailbox In Address=0x%08X\n", dev->MailboxInAddr); + DEBUG("Initialized Extended Mailbox, %d entries at 0x%08X\n", + MailboxInitE->Count, MailboxInitE->Address); dev->Status &= ~STAT_INIT; dev->DataReplyLeft = 0; @@ -766,9 +765,9 @@ buslogic_cmds(void *priv) case 0x83: if (dev->CmdParam == 12) { dev->CmdParamLeft = dev->CmdBuf[11]; - buslogic_log("Execute SCSI BIOS Command: %u more bytes follow\n", dev->CmdParamLeft); + DEBUG("Execute SCSI BIOS Command: %u more bytes follow\n", dev->CmdParamLeft); } else { - buslogic_log("Execute SCSI BIOS Command: received %u bytes\n", dev->CmdBuf[0]); + DEBUG("Execute SCSI BIOS Command: received %u bytes\n", dev->CmdBuf[0]); SCSIBIOSRequestSetup(dev, dev->CmdBuf, dev->DataBuf, 4); } break; @@ -876,7 +875,7 @@ buslogic_cmds(void *priv) if (bl->chip == CHIP_BUSLOGIC_PCI) ReplyIESI->fHostUltraSCSI = 1; memcpy(ReplyIESI->aFirmwareRevision, &(dev->fw_rev[strlen(dev->fw_rev) - 3]), sizeof(ReplyIESI->aFirmwareRevision)); - buslogic_log("Return Extended Setup Information: %d\n", dev->CmdBuf[0]); + DEBUG("Return Extended Setup Information: %d\n", dev->CmdBuf[0]); break; case 0x8F: @@ -886,7 +885,7 @@ buslogic_cmds(void *priv) break; case 0x90: - buslogic_log("Store Local RAM\n"); + DEBUG("Store Local RAM\n"); Offset = dev->CmdBuf[0]; dev->DataReplyLeft = 0; memcpy(&(bl->LocalRAM.u8View[Offset]), &(dev->CmdBuf[2]), dev->CmdBuf[1]); @@ -895,7 +894,7 @@ buslogic_cmds(void *priv) break; case 0x91: - buslogic_log("Fetch Local RAM\n"); + DEBUG("Fetch Local RAM\n"); Offset = dev->CmdBuf[0]; dev->DataReplyLeft = dev->CmdBuf[1]; memcpy(dev->DataBuf, &(bl->LocalRAM.u8View[Offset]), dev->CmdBuf[1]); @@ -970,7 +969,7 @@ buslogic_cmds(void *priv) } if (dev->CmdBuf[0]) { - buslogic_log("Invalid AutoSCSI command mode %x\n", dev->CmdBuf[0]); + DEBUG("Invalid AutoSCSI command mode %x\n", dev->CmdBuf[0]); dev->DataReplyLeft = 0; dev->Status |= STAT_INVCMD; } else { @@ -978,7 +977,7 @@ buslogic_cmds(void *priv) dev->DataReplyLeft <<= 8; dev->DataReplyLeft |= dev->CmdBuf[1]; memcpy(dev->DataBuf, bl->AutoSCSIROM, dev->DataReplyLeft); - buslogic_log("Returning AutoSCSI ROM (%04X %04X %04X %04X)\n", dev->DataBuf[0], dev->DataBuf[1], dev->DataBuf[2], dev->DataBuf[3]); + DEBUG("Returning AutoSCSI ROM (%04X %04X %04X %04X)\n", dev->DataBuf[0], dev->DataBuf[1], dev->DataBuf[2], dev->DataBuf[3]); } break; @@ -1055,6 +1054,10 @@ buslogic_cmds(void *priv) dev->DataReply = 0; break; + case 0xFB: + dev->DataReplyLeft = dev->CmdBuf[2]; + break; + default: dev->DataReplyLeft = 0; dev->Status |= STAT_INVCMD; @@ -1081,6 +1084,7 @@ setup_data(void *priv) ReplyISI->fParityCheckingEnabled = (halr->structured.autoSCSIData.uSCSIConfiguration & 2) ? 1 : 0; bl_setup->uSignature = 'B'; + /* The 'D' signature prevents Buslogic's OS/2 drivers from getting too * friendly with Adaptec hardware and upsetting the HBA state. */ @@ -1154,13 +1158,12 @@ BIOSUpdate(buslogic_data_t *bl) /* PCI BIOS stuff, just enable_disable. */ if ((bl->bios_addr > 0) && bios_enabled) { - mem_mapping_enable(&bl->bios.mapping); - mem_mapping_set_addr(&bl->bios.mapping, - bl->bios_addr, bl->bios_size); - buslogic_log("BT-958D: BIOS now at: %06X\n", bl->bios_addr); + mem_map_enable(&bl->bios.mapping); + mem_map_set_addr(&bl->bios.mapping, bl->bios_addr, bl->bios_size); + DEBUG("BT-958D: BIOS now at: %06X\n", bl->bios_addr); } else { - buslogic_log("BT-958D: BIOS disabled\n"); - mem_mapping_disable(&bl->bios.mapping); + DEBUG("BT-958D: BIOS disabled\n"); + mem_map_disable(&bl->bios.mapping); } } @@ -1169,108 +1172,141 @@ static uint8_t PCIRead(int func, int addr, void *priv) { x54x_t *dev = (x54x_t *)priv; +#ifdef _LOGGING buslogic_data_t *bl = (buslogic_data_t *)dev->ven_data; - - buslogic_log("BT-958D: Reading register %02X\n", addr & 0xff); +#endif + uint8_t ret = 0xff; switch (addr) { case 0x00: - return 0x4b; + ret = 0x4b; + break; case 0x01: - return 0x10; + ret = 0x10; + break; case 0x02: - return 0x40; + ret = 0x40; + break; case 0x03: - return 0x10; + ret = 0x10; + break; case 0x04: - return buslogic_pci_regs[0x04] & 0x03; /*Respond to IO and memory accesses*/ + ret = buslogic_pci_regs[0x04] & 0x03; /*Respond to IO and memory accesses*/ + break; case 0x05: - return 0; + ret = 0; + break; case 0x07: - return 2; + ret = 2; + break; case 0x08: - return 1; /*Revision ID*/ + ret = 1; /*Revision ID*/ + break; case 0x09: - return 0; /*Programming interface*/ + ret = 0; /*Programming interface*/ + break; case 0x0A: - return 0; /*Subclass*/ + ret = 0; /*Subclass*/ + break; case 0x0B: - return 1; /*Class code*/ + ret = 1; /*Class code*/ + break; case 0x0E: - return 0; /*Header type */ + ret = 0; /*Header type */ + break; case 0x10: - return (buslogic_pci_bar[0].addr_regs[0] & 0xe0) | 1; /*I/O space*/ + ret = (buslogic_pci_bar[0].addr_regs[0] & 0xe0) | 1; /*I/O space*/ + break; case 0x11: - return buslogic_pci_bar[0].addr_regs[1]; + ret = buslogic_pci_bar[0].addr_regs[1]; + break; case 0x12: - return buslogic_pci_bar[0].addr_regs[2]; + ret = buslogic_pci_bar[0].addr_regs[2]; + break; case 0x13: - return buslogic_pci_bar[0].addr_regs[3]; + ret = buslogic_pci_bar[0].addr_regs[3]; + break; case 0x14: - return (buslogic_pci_bar[1].addr_regs[0] & 0xe0); /*Memory space*/ + ret = (buslogic_pci_bar[1].addr_regs[0] & 0xe0); /*Memory space*/ + break; case 0x15: - return buslogic_pci_bar[1].addr_regs[1]; + ret = buslogic_pci_bar[1].addr_regs[1]; + break; case 0x16: - return buslogic_pci_bar[1].addr_regs[2]; + ret = buslogic_pci_bar[1].addr_regs[2]; + break; case 0x17: - return buslogic_pci_bar[1].addr_regs[3]; + ret = buslogic_pci_bar[1].addr_regs[3]; + break; case 0x2C: - return 0x4b; + ret = 0x4b; + break; case 0x2D: - return 0x10; + ret = 0x10; + break; case 0x2E: - return 0x40; + ret = 0x40; + break; case 0x2F: - return 0x10; + ret = 0x10; + break; case 0x30: /* PCI_ROMBAR */ - buslogic_log("BT-958D: BIOS BAR 00 = %02X\n", buslogic_pci_bar[2].addr_regs[0] & 0x01); - return buslogic_pci_bar[2].addr_regs[0] & 0x01; + ret = buslogic_pci_bar[2].addr_regs[0] & 0x01; + DEBUG("BT-958D: BIOS BAR 00 = %02X\n", ret); + break; case 0x31: /* PCI_ROMBAR 15:11 */ - buslogic_log("BT-958D: BIOS BAR 01 = %02X\n", (buslogic_pci_bar[2].addr_regs[1] & bl->bios_mask)); - return buslogic_pci_bar[2].addr_regs[1]; + ret = buslogic_pci_bar[2].addr_regs[1]; + DEBUG("BT-958D: BIOS BAR 01 = %02X\n", (ret & bl->bios_mask)); + break; case 0x32: /* PCI_ROMBAR 23:16 */ - buslogic_log("BT-958D: BIOS BAR 02 = %02X\n", buslogic_pci_bar[2].addr_regs[2]); - return buslogic_pci_bar[2].addr_regs[2]; + ret = buslogic_pci_bar[2].addr_regs[2]; + DEBUG("BT-958D: BIOS BAR 02 = %02X\n", ret); + break; case 0x33: /* PCI_ROMBAR 31:24 */ - buslogic_log("BT-958D: BIOS BAR 03 = %02X\n", buslogic_pci_bar[2].addr_regs[3]); - return buslogic_pci_bar[2].addr_regs[3]; + ret = buslogic_pci_bar[2].addr_regs[3]; + DEBUG("BT-958D: BIOS BAR 03 = %02X\n", ret); + break; case 0x3C: - return dev->Irq; + ret = dev->Irq; + break; case 0x3D: - return PCI_INTA; + ret = PCI_INTA; + break; } - return(0); + DBGLOG(2, "BT-958D: reading register %02X: %02X\n", addr & 0xff, ret); + + return(ret); } @@ -1281,22 +1317,20 @@ PCIWrite(int func, int addr, uint8_t val, void *priv) buslogic_data_t *bl = (buslogic_data_t *)dev->ven_data; uint8_t valxor; - buslogic_log("BT-958D: Write value %02X to register %02X\n", val, addr & 0xff); + DBGLOG(2, "BT-958D: Write value %02X to register %02X\n", val, addr & 0xff); switch (addr) { case 0x04: valxor = (val & 0x27) ^ buslogic_pci_regs[addr]; if (valxor & PCI_COMMAND_IO) { x54x_io_remove(dev, bl->PCIBase, 32); - if ((bl->PCIBase != 0) && (val & PCI_COMMAND_IO)) { + if ((bl->PCIBase != 0) && (val & PCI_COMMAND_IO)) x54x_io_set(dev, bl->PCIBase, 32); - } } if (valxor & PCI_COMMAND_MEM) { x54x_mem_disable(dev); - if ((bl->MMIOBase != 0) && (val & PCI_COMMAND_MEM)) { + if ((bl->MMIOBase != 0) && (val & PCI_COMMAND_MEM)) x54x_mem_set_addr(dev, bl->MMIOBase); - } } buslogic_pci_regs[addr] = val & 0x27; break; @@ -1314,12 +1348,11 @@ PCIWrite(int func, int addr, uint8_t val, void *priv) /* Then let's calculate the new I/O base. */ bl->PCIBase = buslogic_pci_bar[0].addr & 0xffe0; /* Log the new base. */ - buslogic_log("BusLogic PCI: New I/O base is %04X\n" , bl->PCIBase); + DEBUG("BusLogic PCI: New I/O base is %04X\n" , bl->PCIBase); /* We're done, so get out of the here. */ if (buslogic_pci_regs[4] & PCI_COMMAND_IO) { - if (bl->PCIBase != 0) { + if (bl->PCIBase != 0) x54x_io_set(dev, bl->PCIBase, 32); - } } return; @@ -1335,12 +1368,11 @@ PCIWrite(int func, int addr, uint8_t val, void *priv) /* Then let's calculate the new I/O base. */ bl->MMIOBase = buslogic_pci_bar[1].addr & 0xffffffe0; /* Log the new base. */ - buslogic_log("BusLogic PCI: New MMIO base is %04X\n" , bl->MMIOBase); + DEBUG("BusLogic PCI: New MMIO base is %04X\n" , bl->MMIOBase); /* We're done, so get out of the here. */ if (buslogic_pci_regs[4] & PCI_COMMAND_MEM) { - if (bl->MMIOBase != 0) { + if (bl->MMIOBase != 0) x54x_mem_set_addr(dev, bl->MMIOBase); - } } return; @@ -1351,14 +1383,14 @@ PCIWrite(int func, int addr, uint8_t val, void *priv) buslogic_pci_bar[2].addr_regs[addr & 3] = val; buslogic_pci_bar[2].addr &= 0xffffc001; bl->bios_addr = buslogic_pci_bar[2].addr & 0xffffc000; - buslogic_log("BT-958D: BIOS BAR %02X = NOW %02X (%02X)\n", addr & 3, buslogic_pci_bar[2].addr_regs[addr & 3], val); + DEBUG("BT-958D: BIOS BAR %02X = NOW %02X (%02X)\n", addr & 3, buslogic_pci_bar[2].addr_regs[addr & 3], val); BIOSUpdate(bl); return; case 0x3C: buslogic_pci_regs[addr] = val; if (val != 0xFF) { - buslogic_log("BusLogic IRQ now: %i\n", val); + DEBUG("BusLogic IRQ now: %i\n", val); dev->Irq = val; } else dev->Irq = 0; @@ -1470,6 +1502,7 @@ buslogic_mca_write(int port, uint8_t val, void *priv) * pos[2]=000xxxxx = 0 */ dev->HostID = (dev->pos_regs[4] >> 5) & 0x07; + halr->structured.autoSCSIData.uSCSIId = dev->HostID; /* * SYNC mode is pos[2]=xxxxxx1x. @@ -1489,6 +1522,45 @@ buslogic_mca_write(int port, uint8_t val, void *priv) halr->structured.autoSCSIData.uBIOSConfiguration &= ~4; halr->structured.autoSCSIData.uBIOSConfiguration |= (dev->pos_regs[4] & 8) ? 4 : 0; + switch(dev->DmaChannel) { + case 5: + halr->structured.autoSCSIData.uDMAChannel = 1; + break; + case 6: + halr->structured.autoSCSIData.uDMAChannel = 2; + break; + case 7: + halr->structured.autoSCSIData.uDMAChannel = 3; + break; + default: + halr->structured.autoSCSIData.uDMAChannel = 0; + break; + } + + switch(dev->Irq) { + case 9: + halr->structured.autoSCSIData.uIrqChannel = 1; + break; + case 10: + halr->structured.autoSCSIData.uIrqChannel = 2; + break; + case 11: + halr->structured.autoSCSIData.uIrqChannel = 3; + break; + case 12: + halr->structured.autoSCSIData.uIrqChannel = 4; + break; + case 14: + halr->structured.autoSCSIData.uIrqChannel = 5; + break; + case 15: + halr->structured.autoSCSIData.uIrqChannel = 6; + break; + default: + halr->structured.autoSCSIData.uIrqChannel = 0; + break; + } + /* * The PS/2 Model 80 BIOS always enables a card if it finds one, * even if no resources were assigned yet (because we only added @@ -1496,7 +1568,7 @@ buslogic_mca_write(int port, uint8_t val, void *priv) * * So, remove current address, if any. */ - mem_mapping_disable(&dev->bios.mapping); + mem_map_disable(&dev->bios.mapping); /* Initialize the device if fully configured. */ if (dev->pos_regs[2] & 0x01) { @@ -1508,13 +1580,13 @@ buslogic_mca_write(int port, uint8_t val, void *priv) /* Enable or disable the BIOS ROM. */ if (bl->has_bios && (bl->bios_addr != 0x000000)) { - mem_mapping_enable(&bl->bios.mapping); - mem_mapping_set_addr(&bl->bios.mapping, bl->bios_addr, ROM_SIZE); + mem_map_enable(&bl->bios.mapping); + mem_map_set_addr(&bl->bios.mapping, bl->bios_addr, ROM_SIZE); } /* Say hello. */ - pclog("BT-640A: I/O=%04x, IRQ=%d, DMA=%d, BIOS @%05X, HOST ID %i\n", - dev->Base, dev->Irq, dev->DmaChannel, bl->bios_addr, dev->HostID); + INFO("BT-640A: I/O=%04x, IRQ=%d, DMA=%d, BIOS @%05X, HOST ID %i\n", + dev->Base, dev->Irq, dev->DmaChannel, bl->bios_addr, dev->HostID); } } @@ -1550,9 +1622,9 @@ buslogic_init(const device_t *info) uint32_t bios_rom_addr; /* Call common initializer. */ - dev = x54x_init(info); + dev = (x54x_t *)x54x_init(info); - dev->ven_data = malloc(sizeof(buslogic_data_t)); + dev->ven_data = mem_alloc(sizeof(buslogic_data_t)); memset(dev->ven_data, 0x00, sizeof(buslogic_data_t)); bl = (buslogic_data_t *)dev->ven_data; @@ -1673,6 +1745,7 @@ buslogic_init(const device_t *info) dev->cdrom_boot = 1; dev->bit32 = 1; dev->ha_bps = 20000000.0; /* ultra SCSI */ + dev->max_id = 15; /* wide SCSI */ break; } @@ -1684,8 +1757,7 @@ buslogic_init(const device_t *info) memset(bl->SCAMData, 0x00, 65536); - if (bl->has_bios) - { + if (bl->has_bios) { bl->bios_size = bios_rom_size; bl->bios_mask = 0xffffc000; @@ -1697,7 +1769,6 @@ buslogic_init(const device_t *info) if (f != NULL) { (void)fread(bl->AutoSCSIROM, 1, autoscsi_rom_size, f); fclose(f); - f = NULL; } } @@ -1706,11 +1777,9 @@ buslogic_init(const device_t *info) if (f != NULL) { (void)fread(bl->SCAMData, 1, scam_rom_size, f); fclose(f); - f = NULL; } } - } - else { + } else { bl->bios_size = 0; bl->bios_mask = 0; } @@ -1723,21 +1792,20 @@ buslogic_init(const device_t *info) buslogic_pci_regs[0x04] = 3; /* Enable our BIOS space in PCI, if needed. */ - if (bl->has_bios) { + if (bl->has_bios) buslogic_pci_bar[2].addr = 0xFFFFC000; - } else { + else buslogic_pci_bar[2].addr = 0; - } x54x_mem_init(dev, 0xfffd0000); x54x_mem_disable(dev); } if ((bl->chip == CHIP_BUSLOGIC_MCA) || (bl->chip == CHIP_BUSLOGIC_PCI)) - mem_mapping_disable(&bl->bios.mapping); - - buslogic_log("Buslogic on port 0x%04X\n", dev->Base); - + mem_map_disable(&bl->bios.mapping); + + DEBUG("Buslogic on port 0x%04X\n", dev->Base); + x54x_device_reset(dev); if ((bl->chip != CHIP_BUSLOGIC_ISA_542) && (bl->chip != CHIP_BUSLOGIC_MCA)) { @@ -1750,152 +1818,152 @@ buslogic_init(const device_t *info) static const device_config_t BT_ISA_Config[] = { + { + "base", "Address", CONFIG_HEX16, "", 0x334, { - "base", "Address", CONFIG_HEX16, "", 0x334, { - { - "0x330", 0x330 - }, - { - "0x334", 0x334 - }, - { - "0x230", 0x230 - }, - { - "0x234", 0x234 - }, - { - "0x130", 0x130 - }, - { - "0x134", 0x134 - }, - { - "" - } + "0x330", 0x330 }, - }, + { + "0x334", 0x334 + }, + { + "0x230", 0x230 + }, + { + "0x234", 0x234 + }, + { + "0x130", 0x130 + }, + { + "0x134", 0x134 + }, + { + "", 0 + } + } + }, + { + "irq", "IRQ", CONFIG_SELECTION, "", 9, { - "irq", "IRQ", CONFIG_SELECTION, "", 9, { - { - "IRQ 9", 9 - }, - { - "IRQ 10", 10 - }, - { - "IRQ 11", 11 - }, - { - "IRQ 12", 12 - }, - { - "IRQ 14", 14 - }, - { - "IRQ 15", 15 - }, - { - "" - } + "IRQ 9", 9 }, - }, + { + "IRQ 10", 10 + }, + { + "IRQ 11", 11 + }, + { + "IRQ 12", 12 + }, + { + "IRQ 14", 14 + }, + { + "IRQ 15", 15 + }, + { + "", 0 + } + } + }, + { + "dma", "DMA channel", CONFIG_SELECTION, "", 6, { - "dma", "DMA channel", CONFIG_SELECTION, "", 6, { - { - "DMA 5", 5 - }, - { - "DMA 6", 6 - }, - { - "DMA 7", 7 - }, - { - "" - } + "DMA 5", 5 }, - }, + { + "DMA 6", 6 + }, + { + "DMA 7", 7 + }, + { + "", 0 + } + } + }, + { + "bios_addr", "BIOS Address", CONFIG_HEX20, "", 0, { - "bios_addr", "BIOS Address", CONFIG_HEX20, "", 0, { - { - "Disabled", 0 - }, - { - "C800H", 0xc8000 - }, - { - "D000H", 0xd0000 - }, - { - "D800H", 0xd8000 - }, - { - "" - } + "Disabled", 0 }, - }, - { - "", "", -1 - } + { + "C800H", 0xc8000 + }, + { + "D000H", 0xd0000 + }, + { + "D800H", 0xd8000 + }, + { + "", 0 + } + } + }, + { + "", "", -1 + } }; static const device_config_t BT958D_Config[] = { - { - "bios", "Enable BIOS", CONFIG_BINARY, "", 0 - }, - { - "", "", -1 - } + { + "bios", "Enable BIOS", CONFIG_BINARY, "", 0 + }, + { + "", "", -1 + } }; const device_t buslogic_device = { - "Buslogic BT-542BH ISA", - DEVICE_ISA | DEVICE_AT, - CHIP_BUSLOGIC_ISA_542, - buslogic_init, x54x_close, NULL, - NULL, NULL, NULL, NULL, - BT_ISA_Config + "Buslogic BT-542BH ISA", + DEVICE_ISA | DEVICE_AT, + CHIP_BUSLOGIC_ISA_542, + buslogic_init, x54x_close, NULL, + NULL, NULL, NULL, NULL, + BT_ISA_Config }; const device_t buslogic_545s_device = { - "Buslogic BT-545S ISA", - DEVICE_ISA | DEVICE_AT, - CHIP_BUSLOGIC_ISA, - buslogic_init, x54x_close, NULL, - NULL, NULL, NULL, NULL, - BT_ISA_Config + "Buslogic BT-545S ISA", + DEVICE_ISA | DEVICE_AT, + CHIP_BUSLOGIC_ISA, + buslogic_init, x54x_close, NULL, + NULL, NULL, NULL, NULL, + BT_ISA_Config }; const device_t buslogic_640a_device = { - "Buslogic BT-640A MCA", - DEVICE_MCA, - CHIP_BUSLOGIC_MCA, - buslogic_init, x54x_close, NULL, - NULL, NULL, NULL, NULL, - NULL + "Buslogic BT-640A MCA", + DEVICE_MCA, + CHIP_BUSLOGIC_MCA, + buslogic_init, x54x_close, NULL, + NULL, NULL, NULL, NULL, + NULL }; const device_t buslogic_445s_device = { - "Buslogic BT-445S ISA", - DEVICE_VLB, - CHIP_BUSLOGIC_VLB, - buslogic_init, x54x_close, NULL, - NULL, NULL, NULL, NULL, - BT_ISA_Config + "Buslogic BT-445S ISA", + DEVICE_VLB, + CHIP_BUSLOGIC_VLB, + buslogic_init, x54x_close, NULL, + NULL, NULL, NULL, NULL, + BT_ISA_Config }; const device_t buslogic_pci_device = { - "Buslogic BT-958D PCI", - DEVICE_PCI, - CHIP_BUSLOGIC_PCI, - buslogic_init, x54x_close, NULL, - NULL, NULL, NULL, NULL, - BT958D_Config + "Buslogic BT-958D PCI", + DEVICE_PCI, + CHIP_BUSLOGIC_PCI, + buslogic_init, x54x_close, NULL, + NULL, NULL, NULL, NULL, + BT958D_Config }; diff --git a/src/devices/scsi/scsi_device.c b/src/devices/scsi/scsi_device.c index 27a2843..00246c3 100644 --- a/src/devices/scsi/scsi_device.c +++ b/src/devices/scsi/scsi_device.c @@ -8,7 +8,7 @@ * * The generic SCSI device command handler. * - * Version: @(#)scsi_device.c 1.0.6 2018/05/06 + * Version: @(#)scsi_device.c 1.0.7 2018/09/15 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -38,51 +38,69 @@ #include #include #include +#define dbglog scsi_log #include "../../emu.h" #include "../../device.h" -#include "../cdrom/cdrom.h" #include "../disk/hdd.h" -#include "../disk/zip.h" #include "scsi.h" +#include "scsi_device.h" #include "scsi_disk.h" +#include "../cdrom/cdrom.h" +#include "../disk/zip.h" -static uint8_t scsi_null_device_sense[14] = { - 0x70,0,SENSE_ILLEGAL_REQUEST,0,0,0,0,0,0,0,0,0,ASC_INV_LUN,0 +static const uint8_t scsi_null_device_sense[18] = { + 0x70,0,SENSE_ILLEGAL_REQUEST,0,0,0,0,0,0,0,0,0,ASC_INV_LUN,0,0,0,0,0 }; static uint8_t scsi_device_target_command(int lun_type, uint8_t id, uint8_t *cdb) { - if (lun_type == SCSI_DISK) { - scsi_hd_command(id, cdb); - return scsi_hd_err_stat_to_scsi(id); - } - else if (lun_type == SCSI_CDROM) { - cdrom_command(id, cdb); - return cdrom_CDROM_PHASE_to_scsi(id); - } - else if (lun_type == SCSI_ZIP) { - zip_command(id, cdb); - return zip_ZIP_PHASE_to_scsi(id); + uint8_t ret = SCSI_STATUS_CHECK_CONDITION; + + switch (lun_type) { + case SCSI_DISK: + scsi_disk_command(scsi_disk[id], cdb); + ret = scsi_disk_err_stat_to_scsi(scsi_disk[id]); + break; + + case SCSI_CDROM: + cdrom_command(cdrom[id], cdb); + ret = cdrom_CDROM_PHASE_to_scsi(cdrom[id]); + break; + + case SCSI_ZIP: + zip_command(zip[id], cdb); + ret = zip_ZIP_PHASE_to_scsi(zip[id]); + break; + + default: + break; } - return SCSI_STATUS_CHECK_CONDITION; + return ret; } static void scsi_device_target_phase_callback(int lun_type, uint8_t id) { - if (lun_type == SCSI_DISK) { - scsi_hd_callback(id); - } - else if (lun_type == SCSI_CDROM) { - cdrom_phase_callback(id); - } - else if (lun_type == SCSI_ZIP) { - zip_phase_callback(id); + switch (lun_type) { + case SCSI_DISK: + scsi_disk_callback(scsi_disk[id]); + break; + + case SCSI_CDROM: + cdrom_phase_callback(cdrom[id]); + break; + + case SCSI_ZIP: + zip_phase_callback(zip[id]); + break; + + default: + break; } } @@ -90,32 +108,26 @@ scsi_device_target_phase_callback(int lun_type, uint8_t id) static int scsi_device_target_err_stat_to_scsi(int lun_type, uint8_t id) { - if (lun_type == SCSI_DISK) { - return scsi_hd_err_stat_to_scsi(id); - } - else if (lun_type == SCSI_CDROM) { - return cdrom_CDROM_PHASE_to_scsi(id); - } - else if (lun_type == SCSI_ZIP) { - return zip_ZIP_PHASE_to_scsi(id); + uint8_t ret = SCSI_STATUS_CHECK_CONDITION; + + switch (lun_type) { + case SCSI_DISK: + ret = scsi_disk_err_stat_to_scsi(scsi_disk[id]); + break; + + case SCSI_CDROM: + ret = cdrom_CDROM_PHASE_to_scsi(cdrom[id]); + break; + + case SCSI_ZIP: + ret = zip_ZIP_PHASE_to_scsi(zip[id]); + break; + + default: + break; } - return SCSI_STATUS_CHECK_CONDITION; -} - - -static void -scsi_device_target_save_cdb_byte(int lun_type, uint8_t id, uint8_t cdb_byte) -{ - if (lun_type == SCSI_DISK) { - shdc[id].request_length = cdb_byte; - } - else if (lun_type == SCSI_CDROM) { - cdrom[id]->request_length = cdb_byte; - } - else if (lun_type == SCSI_ZIP) { - zip[id].request_length = cdb_byte; - } + return ret; } @@ -123,23 +135,30 @@ int64_t scsi_device_get_callback(uint8_t scsi_id, uint8_t scsi_lun) { uint8_t lun_type = SCSIDevices[scsi_id][scsi_lun].LunType; - uint8_t id = 0; + int64_t ret = -1LL; + uint8_t id; switch (lun_type) { case SCSI_DISK: id = scsi_disks[scsi_id][scsi_lun]; - return shdc[id].callback; + ret = scsi_disk[id]->callback; + break; + case SCSI_CDROM: id = scsi_cdrom_drives[scsi_id][scsi_lun]; - return cdrom[id]->callback; + ret = cdrom[id]->callback; + break; + case SCSI_ZIP: id = scsi_zip_drives[scsi_id][scsi_lun]; - return zip[id].callback; + ret = zip[id]->callback; + break; + default: break; } - return -1LL; + return ret; } @@ -147,23 +166,30 @@ uint8_t * scsi_device_sense(uint8_t scsi_id, uint8_t scsi_lun) { uint8_t lun_type = SCSIDevices[scsi_id][scsi_lun].LunType; - uint8_t id = 0; + uint8_t *ret = (uint8_t *)scsi_null_device_sense; + uint8_t id; switch (lun_type) { case SCSI_DISK: id = scsi_disks[scsi_id][scsi_lun]; - return shdc[id].sense; + ret = scsi_disk[id]->sense; + break; + case SCSI_CDROM: id = scsi_cdrom_drives[scsi_id][scsi_lun]; - return cdrom[id]->sense; + ret = cdrom[id]->sense; + break; + case SCSI_ZIP: id = scsi_zip_drives[scsi_id][scsi_lun]; - return zip[id].sense; + ret = zip[id]->sense; + break; + default: break; } - return scsi_null_device_sense; + return ret; } @@ -171,21 +197,24 @@ void scsi_device_request_sense(uint8_t scsi_id, uint8_t scsi_lun, uint8_t *buffer, uint8_t alloc_length) { uint8_t lun_type = SCSIDevices[scsi_id][scsi_lun].LunType; - uint8_t id = 0; + uint8_t id; switch (lun_type) { case SCSI_DISK: id = scsi_disks[scsi_id][scsi_lun]; - scsi_hd_request_sense_for_scsi(id, buffer, alloc_length); + scsi_disk_request_sense_for_scsi(scsi_disk[id], buffer, alloc_length); break; + case SCSI_CDROM: id = scsi_cdrom_drives[scsi_id][scsi_lun]; - cdrom_request_sense_for_scsi(id, buffer, alloc_length); + cdrom_request_sense_for_scsi(cdrom[id], buffer, alloc_length); break; + case SCSI_ZIP: id = scsi_zip_drives[scsi_id][scsi_lun]; - zip_request_sense_for_scsi(id, buffer, alloc_length); + zip_request_sense_for_scsi(zip[id], buffer, alloc_length); break; + default: memcpy(buffer, scsi_null_device_sense, alloc_length); break; @@ -193,28 +222,56 @@ scsi_device_request_sense(uint8_t scsi_id, uint8_t scsi_lun, uint8_t *buffer, ui } +void +scsi_device_reset(uint8_t scsi_id, uint8_t scsi_lun) +{ + uint8_t lun_type = SCSIDevices[scsi_id][scsi_lun].LunType; + uint8_t id; + + switch (lun_type) { + case SCSI_DISK: + id = scsi_disks[scsi_id][scsi_lun]; + scsi_disk_reset(scsi_disk[id]); + break; + + case SCSI_CDROM: + id = scsi_cdrom_drives[scsi_id][scsi_lun]; + cdrom_reset(cdrom[id]); + break; + + case SCSI_ZIP: + id = scsi_zip_drives[scsi_id][scsi_lun]; + zip_reset(zip[id]); + break; + + default: + break; + } +} + + void scsi_device_type_data(uint8_t scsi_id, uint8_t scsi_lun, uint8_t *type, uint8_t *rmb) { uint8_t lun_type = SCSIDevices[scsi_id][scsi_lun].LunType; - uint8_t id = 0; switch (lun_type) { case SCSI_DISK: - id = scsi_disks[scsi_id][scsi_lun]; - *type = 0x00; - *rmb = (hdd[id].bus == HDD_BUS_SCSI_REMOVABLE) ? 0x80 : 0x00; + *type = *rmb = 0x00; break; + case SCSI_CDROM: *type = 0x05; *rmb = 0x80; break; + case SCSI_ZIP: *type = 0x00; *rmb = 0x80; break; + default: - *type = *rmb = 0xFF; + *type = *rmb = 0xff; break; } } @@ -224,23 +281,30 @@ int scsi_device_read_capacity(uint8_t scsi_id, uint8_t scsi_lun, uint8_t *cdb, uint8_t *buffer, uint32_t *len) { uint8_t lun_type = SCSIDevices[scsi_id][scsi_lun].LunType; - uint8_t id = 0; + int ret = 0; + uint8_t id; switch (lun_type) { case SCSI_DISK: id = scsi_disks[scsi_id][scsi_lun]; - return scsi_hd_read_capacity(id, cdb, buffer, len); + ret = scsi_disk_read_capacity(scsi_disk[id], cdb, buffer, len); + break; + case SCSI_CDROM: id = scsi_cdrom_drives[scsi_id][scsi_lun]; - return cdrom_read_capacity(id, cdb, buffer, len); + ret = cdrom_read_capacity(cdrom[id], cdb, buffer, len); + break; + case SCSI_ZIP: id = scsi_zip_drives[scsi_id][scsi_lun]; - return zip_read_capacity(id, cdb, buffer, len); + ret = zip_read_capacity(zip[id], cdb, buffer, len); + break; + default: break; } - return 0; + return ret; } @@ -248,15 +312,19 @@ int scsi_device_present(uint8_t scsi_id, uint8_t scsi_lun) { uint8_t lun_type = SCSIDevices[scsi_id][scsi_lun].LunType; + int ret = 0; switch (lun_type) { case SCSI_NONE: - return 0; + ret = 0; + break; + default: + ret = 1; break; } - return 1; + return ret; } @@ -270,44 +338,36 @@ scsi_device_valid(uint8_t scsi_id, uint8_t scsi_lun) case SCSI_DISK: id = scsi_disks[scsi_id][scsi_lun]; break; + case SCSI_CDROM: id = scsi_cdrom_drives[scsi_id][scsi_lun]; break; + case SCSI_ZIP: id = scsi_zip_drives[scsi_id][scsi_lun]; break; + default: - id = 0; break; } - return (id == 0xFF) ? 0 : 1; + return (id == 0xff) ? 0 : 1; } int scsi_device_cdb_length(uint8_t scsi_id, uint8_t scsi_lun) { - uint8_t lun_type = SCSIDevices[scsi_id][scsi_lun].LunType; - uint8_t id = 0; - - switch (lun_type) { - case SCSI_CDROM: - id = scsi_cdrom_drives[scsi_id][scsi_lun]; - return cdrom[id]->cdb_len; - case SCSI_ZIP: - id = scsi_zip_drives[scsi_id][scsi_lun]; - return zip[id].cdb_len; - default: - break; - } + (void)scsi_id; + (void)scsi_lun; + /* Right now, it's 12 for all devices. */ return 12; } void -scsi_device_command_phase0(uint8_t scsi_id, uint8_t scsi_lun, int cdb_len, uint8_t *cdb) +scsi_device_command_phase0(uint8_t scsi_id, uint8_t scsi_lun, uint8_t *cdb) { uint8_t lun_type = SCSIDevices[scsi_id][scsi_lun].LunType; uint8_t id = 0; @@ -316,34 +376,21 @@ scsi_device_command_phase0(uint8_t scsi_id, uint8_t scsi_lun, int cdb_len, uint8 case SCSI_DISK: id = scsi_disks[scsi_id][scsi_lun]; break; + case SCSI_CDROM: id = scsi_cdrom_drives[scsi_id][scsi_lun]; break; + case SCSI_ZIP: id = scsi_zip_drives[scsi_id][scsi_lun]; break; + default: - id = 0; SCSIDevices[scsi_id][scsi_lun].Phase = SCSI_PHASE_STATUS; SCSIDevices[scsi_id][scsi_lun].Status = SCSI_STATUS_CHECK_CONDITION; return; } - /* - * Since that field in the target struct is never used when - * the bus type is SCSI, let's use it for this scope. - */ - scsi_device_target_save_cdb_byte(lun_type, id, cdb[1]); - - if (cdb_len != 12) { - /* - * Make sure the LUN field of the temporary CDB is always 0, - * otherwise Daemon Tools drives will misbehave when a command - * is passed through to them. - */ - cdb[1] &= 0x1f; - } - /* Finally, execute the SCSI command immediately and get the transfer length. */ SCSIDevices[scsi_id][scsi_lun].Phase = SCSI_PHASE_COMMAND; SCSIDevices[scsi_id][scsi_lun].Status = scsi_device_target_command(lun_type, id, cdb); @@ -352,11 +399,13 @@ scsi_device_command_phase0(uint8_t scsi_id, uint8_t scsi_lun, int cdb_len, uint8 /* Command completed (either OK or error) - call the phase callback to complete the command. */ scsi_device_target_phase_callback(lun_type, id); } + /* If the phase is DATA IN or DATA OUT, finish this here. */ } -void scsi_device_command_phase1(uint8_t scsi_id, uint8_t scsi_lun) +void +scsi_device_command_phase1(uint8_t scsi_id, uint8_t scsi_lun) { uint8_t lun_type = SCSIDevices[scsi_id][scsi_lun].LunType; uint8_t id = 0; @@ -365,19 +414,22 @@ void scsi_device_command_phase1(uint8_t scsi_id, uint8_t scsi_lun) case SCSI_DISK: id = scsi_disks[scsi_id][scsi_lun]; break; + case SCSI_CDROM: id = scsi_cdrom_drives[scsi_id][scsi_lun]; break; + case SCSI_ZIP: id = scsi_zip_drives[scsi_id][scsi_lun]; break; + default: - id = 0; return; } /* Call the second phase. */ scsi_device_target_phase_callback(lun_type, id); + SCSIDevices[scsi_id][scsi_lun].Status = scsi_device_target_err_stat_to_scsi(lun_type, id); /* Command second phase complete - call the callback to complete the command. */ diff --git a/src/devices/scsi/scsi_device.h b/src/devices/scsi/scsi_device.h index 15733d0..3c826b5 100644 --- a/src/devices/scsi/scsi_device.h +++ b/src/devices/scsi/scsi_device.h @@ -8,7 +8,7 @@ * * Definitions for the generic SCSI device command handler. * - * Version: @(#)scsi_device.h 1.0.2 2018/03/08 + * Version: @(#)scsi_device.h 1.0.3 2018/10/05 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -38,6 +38,234 @@ # define SCSI_DEVICE_H +/* Configuration. */ +#define SCSI_ID_MAX 16 /* 16 on wide buses */ +#define SCSI_LUN_MAX 8 /* always 8 */ + +#define SCSI_TIME (5 * 100 * (1 << TIMER_SHIFT)) + + +/* SCSI commands. */ +#define GPCMD_TEST_UNIT_READY 0x00 +#define GPCMD_REZERO_UNIT 0x01 +#define GPCMD_REQUEST_SENSE 0x03 +#define GPCMD_FORMAT_UNIT 0x04 +#define GPCMD_IOMEGA_SENSE 0x06 +#define GPCMD_READ_6 0x08 +#define GPCMD_WRITE_6 0x0a +#define GPCMD_SEEK_6 0x0b +#define GPCMD_IOMEGA_SET_PROTECTION_MODE 0x0c +#define GPCMD_IOMEGA_EJECT 0x0d /* ATAPI only? */ +#define GPCMD_INQUIRY 0x12 +#define GPCMD_VERIFY_6 0x13 +#define GPCMD_MODE_SELECT_6 0x15 +#define GPCMD_SCSI_RESERVE 0x16 +#define GPCMD_SCSI_RELEASE 0x17 +#define GPCMD_MODE_SENSE_6 0x1a +#define GPCMD_START_STOP_UNIT 0x1b +#define GPCMD_SEND_DIAGNOSTIC 0x1d +#define GPCMD_PREVENT_REMOVAL 0x1e +#define GPCMD_READ_FORMAT_CAPACITIES 0x23 +#define GPCMD_READ_CDROM_CAPACITY 0x25 +#define GPCMD_READ_10 0x28 +#define GPCMD_WRITE_10 0x2a +#define GPCMD_SEEK_10 0x2b +#define GPCMD_WRITE_AND_VERIFY_10 0x2e +#define GPCMD_VERIFY_10 0x2f +#define GPCMD_READ_BUFFER 0x3c +#define GPCMD_WRITE_SAME_10 0x41 +#define GPCMD_READ_SUBCHANNEL 0x42 +#define GPCMD_READ_TOC_PMA_ATIP 0x43 +#define GPCMD_READ_HEADER 0x44 +#define GPCMD_PLAY_AUDIO_10 0x45 +#define GPCMD_GET_CONFIGURATION 0x46 +#define GPCMD_PLAY_AUDIO_MSF 0x47 +#define GPCMD_PLAY_AUDIO_TRACK_INDEX 0x48 +#define GPCMD_GET_EVENT_STATUS_NOTIFICATION 0x4a +#define GPCMD_PAUSE_RESUME 0x4b +#define GPCMD_STOP_PLAY_SCAN 0x4e +#define GPCMD_READ_DISC_INFORMATION 0x51 +#define GPCMD_READ_TRACK_INFORMATION 0x52 +#define GPCMD_MODE_SELECT_10 0x55 +#define GPCMD_MODE_SENSE_10 0x5a +#define GPCMD_PLAY_AUDIO_12 0xa5 +#define GPCMD_READ_12 0xa8 +#define GPCMD_WRITE_12 0xaa +#define GPCMD_READ_DVD_STRUCTURE 0xad /* For reading. */ +#define GPCMD_WRITE_AND_VERIFY_12 0xae +#define GPCMD_VERIFY_12 0xaf +#define GPCMD_PLAY_CD_OLD 0xb4 +#define GPCMD_READ_CD_OLD 0xb8 +#define GPCMD_READ_CD_MSF 0xb9 +#define GPCMD_SCAN 0xba +#define GPCMD_SET_SPEED 0xbb +#define GPCMD_PLAY_CD 0xbc +#define GPCMD_MECHANISM_STATUS 0xbd +#define GPCMD_READ_CD 0xbe +#define GPCMD_SEND_DVD_STRUCTURE 0xbf /* this is for writing only */ +#define GPCMD_PAUSE_RESUME_ALT 0xc2 +#define GPCMD_SCAN_ALT 0xcd /* should be equiv to 0xba */ +#define GPCMD_SET_SPEED_ALT 0xda /* should be equiv to 0xbb */ + +/* Mode page codes for mode sense/set */ +#define GPMODE_R_W_ERROR_PAGE 0x01 +#define GPMODE_CDROM_PAGE 0x0d +#define GPMODE_CDROM_AUDIO_PAGE 0x0e +#define GPMODE_CAPABILITIES_PAGE 0x2a +#define GPMODE_ALL_PAGES 0x3f + +/* Mode page codes for presence */ +#define GPMODEP_R_W_ERROR_PAGE 0x0000000000000002LL +#define GPMODEP_UNK_PAGE_02 0x0000000000000004LL +#define GPMODEP_UNK_PAGE_03 0x0000000000000008LL +#define GPMODEP_UNK_PAGE_04 0x0000000000000010LL +#define GPMODEP_UNK_PAGE_05 0x0000000000000020LL +#define GPMODEP_UNK_PAGE_08 0x0000000000000100LL +#define GPMODEP_CDROM_PAGE 0x0000000000002000LL +#define GPMODEP_CDROM_AUDIO_PAGE 0x0000000000004000LL +#define GPMODEP_CAPABILITIES_PAGE 0x0000040000000000LL +#define GPMODEP_UNK_PAGE_2F 0x0000800000000000LL +#define GPMODEP_UNK_PAGE_30 0x0001000000000000LL +#define GPMODEP_ALL_PAGES 0x8000000000000000LL + +/* SCSI Status Codes */ +#define SCSI_STATUS_OK 0 +#define SCSI_STATUS_CHECK_CONDITION 2 + +/* SCSI Sense Keys */ +#define SENSE_NONE 0 +#define SENSE_NOT_READY 2 +#define SENSE_ILLEGAL_REQUEST 5 +#define SENSE_UNIT_ATTENTION 6 + +/* SCSI Additional Sense Codes */ +#define ASC_AUDIO_PLAY_OPERATION 0x00 +#define ASC_NOT_READY 0x04 +#define ASC_ILLEGAL_OPCODE 0x20 +#define ASC_LBA_OUT_OF_RANGE 0x21 +#define ASC_INV_FIELD_IN_CMD_PACKET 0x24 +#define ASC_INV_LUN 0x25 +#define ASC_INV_FIELD_IN_PARAMETER_LIST 0x26 +#define ASC_WRITE_PROTECTED 0x27 +#define ASC_MEDIUM_MAY_HAVE_CHANGED 0x28 +#define ASC_CAPACITY_DATA_CHANGED 0x2A +#define ASC_INCOMPATIBLE_FORMAT 0x30 +#define ASC_MEDIUM_NOT_PRESENT 0x3a +#define ASC_DATA_PHASE_ERROR 0x4b +#define ASC_ILLEGAL_MODE_FOR_THIS_TRACK 0x64 +#define ASCQ_UNIT_IN_PROCESS_OF_BECOMING_READY 0x01 +#define ASCQ_INITIALIZING_COMMAND_REQUIRED 0x02 +#define ASCQ_CAPACITY_DATA_CHANGED 0x09 +#define ASCQ_AUDIO_PLAY_OPERATION_IN_PROGRESS 0x11 +#define ASCQ_AUDIO_PLAY_OPERATION_PAUSED 0x12 +#define ASCQ_AUDIO_PLAY_OPERATION_COMPLETED 0x13 + +/* Tell RISC OS that we have a 4x CD-ROM drive (600kb/sec data, 706kb/sec raw). + Not that it means anything */ +#define CDROM_SPEED 706 /* 0x2C2 */ +#define BUFFER_SIZE (256*1024) +#define RW_DELAY (TIMER_USEC * 500) + +/* Some generally useful CD-ROM information */ +#define CD_MINS 75 /* max. minutes per CD */ +#define CD_SECS 60 /* seconds per minute */ +#define CD_FRAMES 75 /* frames per second */ +#define CD_FRAMESIZE 2048 /* bytes per frame, "cooked" mode */ +#define CD_MAX_BYTES (CD_MINS * CD_SECS * CD_FRAMES * CD_FRAMESIZE) +#define CD_MAX_SECTORS (CD_MAX_BYTES / 512) + +/* Event notification classes for GET EVENT STATUS NOTIFICATION */ +#define GESN_NO_EVENTS 0 +#define GESN_OPERATIONAL_CHANGE 1 +#define GESN_POWER_MANAGEMENT 2 +#define GESN_EXTERNAL_REQUEST 3 +#define GESN_MEDIA 4 +#define GESN_MULTIPLE_HOSTS 5 +#define GESN_DEVICE_BUSY 6 + +/* Event codes for MEDIA event status notification */ +#define MEC_NO_CHANGE 0 +#define MEC_EJECT_REQUESTED 1 +#define MEC_NEW_MEDIA 2 +#define MEC_MEDIA_REMOVAL 3 /* only for media changers */ +#define MEC_MEDIA_CHANGED 4 /* only for media changers */ +#define MEC_BG_FORMAT_COMPLETED 5 /* MRW or DVD+RW b/g format completed */ +#define MEC_BG_FORMAT_RESTARTED 6 /* MRW or DVD+RW b/g format restarted */ +#define MS_TRAY_OPEN 1 +#define MS_MEDIA_PRESENT 2 + +/* Profile list from MMC-6 revision 1 table 91 */ +#define MMC_PROFILE_NONE 0x0000 +#define MMC_PROFILE_CD_ROM 0x0008 +#define MMC_PROFILE_CD_R 0x0009 +#define MMC_PROFILE_CD_RW 0x000A +#define MMC_PROFILE_DVD_ROM 0x0010 +#define MMC_PROFILE_DVD_R_SR 0x0011 +#define MMC_PROFILE_DVD_RAM 0x0012 +#define MMC_PROFILE_DVD_RW_RO 0x0013 +#define MMC_PROFILE_DVD_RW_SR 0x0014 +#define MMC_PROFILE_DVD_R_DL_SR 0x0015 +#define MMC_PROFILE_DVD_R_DL_JR 0x0016 +#define MMC_PROFILE_DVD_RW_DL 0x0017 +#define MMC_PROFILE_DVD_DDR 0x0018 +#define MMC_PROFILE_DVD_PLUS_RW 0x001A +#define MMC_PROFILE_DVD_PLUS_R 0x001B +#define MMC_PROFILE_DVD_PLUS_RW_DL 0x002A +#define MMC_PROFILE_DVD_PLUS_R_DL 0x002B +#define MMC_PROFILE_BD_ROM 0x0040 +#define MMC_PROFILE_BD_R_SRM 0x0041 +#define MMC_PROFILE_BD_R_RRM 0x0042 +#define MMC_PROFILE_BD_RE 0x0043 +#define MMC_PROFILE_HDDVD_ROM 0x0050 +#define MMC_PROFILE_HDDVD_R 0x0051 +#define MMC_PROFILE_HDDVD_RAM 0x0052 +#define MMC_PROFILE_HDDVD_RW 0x0053 +#define MMC_PROFILE_HDDVD_R_DL 0x0058 +#define MMC_PROFILE_HDDVD_RW_DL 0x005A +#define MMC_PROFILE_INVALID 0xFFFF + +#define SCSI_ONLY 32 +#define ATAPI_ONLY 16 +#define IMPLEMENTED 8 +#define NONDATA 4 +#define CHECK_READY 2 +#define ALLOW_UA 1 + +#define MSFtoLBA(m,s,f) ((((m*60)+s)*75)+f) + +#define MSG_COMMAND_COMPLETE 0x00 + +#define BUS_DBP 0x01 +#define BUS_SEL 0x02 +#define BUS_IO 0x04 +#define BUS_CD 0x08 +#define BUS_MSG 0x10 +#define BUS_REQ 0x20 +#define BUS_BSY 0x40 +#define BUS_RST 0x80 +#define BUS_ACK 0x200 +#define BUS_ATN 0x200 +#define BUS_ARB 0x8000 +#define BUS_SETDATA(val) ((uint32_t)val << 16) +#define BUS_GETDATA(val) ((val >> 16) & 0xff) +#define BUS_DATAMASK 0xff0000 + +#define BUS_IDLE (1 << 31) + +#define SCSI_PHASE_DATA_OUT 0 +#define SCSI_PHASE_DATA_IN BUS_IO +#define SCSI_PHASE_COMMAND BUS_CD +#define SCSI_PHASE_STATUS (BUS_CD | BUS_IO) +#define SCSI_PHASE_MESSAGE_OUT (BUS_MSG | BUS_CD) +#define SCSI_PHASE_MESSAGE_IN (BUS_MSG | BUS_CD | BUS_IO) + +#define MODE_SELECT_PHASE_IDLE 0 +#define MODE_SELECT_PHASE_HEADER 1 +#define MODE_SELECT_PHASE_BLOCK_DESC 2 +#define MODE_SELECT_PHASE_PAGE_HEADER 3 +#define MODE_SELECT_PHASE_PAGE 4 + + typedef struct { int state; int new_state; @@ -53,6 +281,38 @@ typedef struct { int new_req_delay; } scsi_bus_t; +typedef struct { + uint8_t *CmdBuffer; + int LunType; + int32_t BufferLength; + uint8_t Status; + uint8_t Phase; +} scsi_device_t; + +#pragma pack(push,1) +typedef struct { + uint8_t pages[0x40][0x40]; +} mode_sense_pages_t; +#pragma pack(pop) + +enum { + SCSI_NONE = 0, + SCSI_DISK, + SCSI_CDROM, + SCSI_ZIP +}; + + +extern scsi_device_t SCSIDevices[SCSI_ID_MAX][SCSI_LUN_MAX]; + + +extern void scsi_dev_log(int level, const char *fmt, ...); + +extern int cdrom_add_error_and_subchannel(uint8_t *b, int real_sector_type); +extern int cdrom_LBAtoMSF_accurate(void); +extern int mode_select_init(uint8_t command, uint16_t pl_length, uint8_t do_save); +extern int mode_select_terminate(int force); +extern int mode_select_write(uint8_t val); extern uint8_t *scsi_device_sense(uint8_t id, uint8_t lun); extern void scsi_device_type_data(uint8_t id, uint8_t lun, @@ -61,6 +321,7 @@ extern int64_t scsi_device_get_callback(uint8_t scsi_id, uint8_t scsi_lun); extern void scsi_device_request_sense(uint8_t scsi_id, uint8_t scsi_lun, uint8_t *buffer, uint8_t alloc_length); +extern void scsi_device_reset(uint8_t scsi_id, uint8_t scsi_lun); extern int scsi_device_read_capacity(uint8_t id, uint8_t lun, uint8_t *cdb, uint8_t *buffer, uint32_t *len); @@ -70,13 +331,9 @@ extern int scsi_device_cdb_length(uint8_t id, uint8_t lun); extern void scsi_device_command(uint8_t id, uint8_t lun, int cdb_len, uint8_t *cdb); extern void scsi_device_command_phase0(uint8_t scsi_id, uint8_t scsi_lun, - int cdb_len, uint8_t *cdb); + uint8_t *cdb); extern void scsi_device_command_phase1(uint8_t scsi_id, uint8_t scsi_lun); extern int32_t *scsi_device_get_buf_len(uint8_t scsi_id, uint8_t scsi_lun); -extern int scsi_bus_update(scsi_bus_t *bus, int bus_assert); -extern int scsi_bus_read(scsi_bus_t *bus); -extern int scsi_bus_match(scsi_bus_t *bus, int bus_assert); - #endif /*SCSI_DEVICE_H*/ diff --git a/src/devices/scsi/scsi_disk.c b/src/devices/scsi/scsi_disk.c index 407b7a8..9de9afc 100644 --- a/src/devices/scsi/scsi_disk.c +++ b/src/devices/scsi/scsi_disk.c @@ -6,9 +6,9 @@ * * This file is part of the VARCem Project. * - * Emulation of SCSI fixed and removable disks. + * Emulation of SCSI fixed disks. * - * Version: @(#)scsi_disk.c 1.0.11 2018/10/04 + * Version: @(#)scsi_disk.c 1.0.12 2018/10/05 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -41,6 +41,7 @@ #include #include #define HAVE_STDARG_H +#define dbglog scsi_disk_log #include "../../emu.h" #include "../../version.h" #include "../../timer.h" @@ -48,12 +49,12 @@ #include "../../nvr.h" #include "../../ui/ui.h" #include "../../plat.h" -#include "../cdrom/cdrom.h" #include "../disk/hdd.h" #include "../disk/hdc.h" #include "../disk/hdc_ide.h" -#include "scsi.h" +#include "scsi_device.h" #include "scsi_disk.h" +#include "../cdrom/cdrom.h" /* Bits of 'status' */ @@ -70,36 +71,42 @@ #define MAX_BLOCKS_AT_ONCE 340 -#define scsi_hd_sense_error shdc[id].sense[0] -#define scsi_hd_sense_key shdc[id].sense[2] -#define scsi_hd_asc shdc[id].sense[12] -#define scsi_hd_ascq shdc[id].sense[13] + +/*FIXME: PLEASE, get rid of these, they make the code unclear. --FvK */ +#define scsi_disk_sense_error dev->sense[0] +#define scsi_disk_sense_key dev->sense[2] +#define scsi_disk_asc dev->sense[12] +#define scsi_disk_ascq dev->sense[13] -scsi_disk_t shdc[HDD_NUM]; -FILE *shdf[HDD_NUM]; +#ifdef ENABLE_SCSI_DISK_LOG +int scsi_disk_do_log = ENABLE_SCSI_DISK_LOG; +#endif + + +scsi_disk_t *scsi_disk[HDD_NUM]; uint8_t scsi_disks[16][8] = { - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } + { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, + { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, + { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, + { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, + { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, + { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, + { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, + { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, + { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, + { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, + { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, + { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, + { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, + { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, + { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, + { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff } }; /* Table of all SCSI commands and their flags, needed for the new disc change / not ready handler. */ -static const uint8_t scsi_hd_command_flags[0x100] = { +static const uint8_t scsi_disk_command_flags[0x100] = { IMPLEMENTED | CHECK_READY | NONDATA, /* 0x00 */ IMPLEMENTED | ALLOW_UA | NONDATA | SCSI_ONLY, /* 0x01 */ 0, @@ -109,7 +116,8 @@ static const uint8_t scsi_hd_command_flags[0x100] = { IMPLEMENTED | CHECK_READY, /* 0x08 */ 0, IMPLEMENTED | CHECK_READY, /* 0x0A */ - 0, 0, 0, 0, 0, 0, 0, + IMPLEMENTED | CHECK_READY | NONDATA, /* 0x0B */ + 0, 0, 0, 0, 0, 0, IMPLEMENTED | ALLOW_UA, /* 0x12 */ IMPLEMENTED | CHECK_READY | NONDATA | SCSI_ONLY, /* 0x13 */ 0, @@ -118,8 +126,7 @@ static const uint8_t scsi_hd_command_flags[0x100] = { IMPLEMENTED | SCSI_ONLY, /* 0x17 */ 0, 0, IMPLEMENTED, /* 0x1A */ - IMPLEMENTED | CHECK_READY, /* 0x1B */ - 0, + 0, 0, IMPLEMENTED, /* 0x1D */ IMPLEMENTED | CHECK_READY, /* 0x1E */ 0, 0, 0, 0, 0, 0, @@ -128,7 +135,8 @@ static const uint8_t scsi_hd_command_flags[0x100] = { IMPLEMENTED | CHECK_READY, /* 0x28 */ 0, IMPLEMENTED | CHECK_READY, /* 0x2A */ - 0, 0, 0, + IMPLEMENTED | CHECK_READY | NONDATA, /* 0x2B */ + 0, 0, IMPLEMENTED | CHECK_READY, /* 0x2E */ IMPLEMENTED | CHECK_READY | NONDATA | SCSI_ONLY, /* 0x2F */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -161,45 +169,46 @@ static const uint8_t scsi_hd_command_flags[0x100] = { }; -static const uint64_t scsi_hd_mode_sense_page_flags = (1LL << 0x03) | (1LL << 0x04) | (1LL << 0x30) | (1LL << 0x3F); +uint64_t scsi_disk_mode_sense_page_flags = (GPMODEP_UNK_PAGE_03 | + GPMODEP_UNK_PAGE_04 | + GPMODEP_UNK_PAGE_30 | + GPMODEP_ALL_PAGES); /* This should be done in a better way but for time being, it's been done this way so it's not as huge and more readable. */ -static const mode_sense_pages_t scsi_hd_mode_sense_pages_default = { - { [0x03] = { 0x03, 0x16, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 - }, - [0x04] = { 0x04, 0x16, 0, 0x10, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10, 0, 0, 0 - }, - [0x30] = { 0xB0, 0x16, '8', '6', 'B', 'o', 'x', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' - } - } -}; - -static const mode_sense_pages_t scsi_hd_mode_sense_pages_changeable = { - { [0x03] = { 0x03, 0x16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 - }, - [0x04] = { 0x04, 0x16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 - }, - [0x30] = { 0xB0, 0x16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 - } - } -}; - - -static mode_sense_pages_t scsi_hd_mode_sense_pages_saved[HDD_NUM]; - - -#ifdef ENABLE_SCSI_DISK_LOG -int scsi_hd_do_log = ENABLE_SCSI_DISK_LOG; +static const mode_sense_pages_t scsi_disk_mode_sense_pages_default = { +#ifdef __cplusplus + 0 +#else + { [0x03] = { 0x03, 0x16, + 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + [0x04] = { 0x04, 0x16, + 0, 0x10, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10, 0, 0, 0 }, + [0x30] = { 0xB0, 0x16, + 'V', 'A', 'R', 'C', 'e', 'm', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } + } #endif +}; + +static const mode_sense_pages_t scsi_disk_mode_sense_pages_changeable = +{ +#ifdef __cplusplus + 0 +#else + { [0x03] = { 0x03, 0x16, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, + [0x04] = { 0x04, 0x16, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, + [0x30] = { 0xB0, 0x16, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } + } +#endif +}; -static void -scsi_hd_log(const char *fmt, ...) +void +scsi_disk_log(int level, const char *fmt, ...) { #ifdef ENABLE_SCSI_DISK_LOG va_list ap; - if (scsi_hd_do_log) { + if (scsi_disk_do_log >= level) { va_start(ap, fmt); pclog_ex(fmt, ap); va_end(ap); @@ -210,100 +219,57 @@ scsi_hd_log(const char *fmt, ...) /* Translates ATAPI status (ERR_STAT flag) to SCSI status. */ int -scsi_hd_err_stat_to_scsi(uint8_t id) +scsi_disk_err_stat_to_scsi(scsi_disk_t *dev) { - if (shdc[id].status & ERR_STAT) { + if (dev->status & ERR_STAT) return SCSI_STATUS_CHECK_CONDITION; - } return SCSI_STATUS_OK; } int -find_hdd_for_scsi_id(uint8_t scsi_id, uint8_t scsi_lun) +find_hdd_for_scsi_id(uint8_t id, uint8_t lun) { - uint8_t i = 0; + uint8_t i; - for (i=0; i 0) { + if (wcslen(hdd[scsi_disks[i][j]].fn) > 0) scsi_loadhd(i, j, scsi_disks[i][j]); - } } } } @@ -311,49 +277,53 @@ build_scsi_hd_map(void) void -scsi_hd_mode_sense_load(uint8_t id) +scsi_disk_mode_sense_load(scsi_disk_t *dev) { wchar_t file_name[512]; FILE *f; int i; - memset(&scsi_hd_mode_sense_pages_saved[id], 0, sizeof(mode_sense_pages_t)); - for (i=0; i<0x3f; i++) { - if (scsi_hd_mode_sense_pages_default.pages[i][1] != 0) - memcpy(scsi_hd_mode_sense_pages_saved[id].pages[i], scsi_hd_mode_sense_pages_default.pages[i], scsi_hd_mode_sense_pages_default.pages[i][1] + 2); + memset(&dev->ms_pages_saved, 0, sizeof(mode_sense_pages_t)); + + for (i = 0; i < 0x3f; i++) { + if (scsi_disk_mode_sense_pages_default.pages[i][1] != 0) + memcpy(dev->ms_pages_saved.pages[i], + scsi_disk_mode_sense_pages_default.pages[i], + scsi_disk_mode_sense_pages_default.pages[i][1] + 2); } - swprintf(file_name, 512, L"scsi_hd_%02i_mode_sense.bin", id); + + swprintf(file_name, 512, L"scsi_hd_%02i_mode_sense.bin", dev->id); memset(file_name, 0, 512 * sizeof(wchar_t)); f = plat_fopen(nvr_path(file_name), L"rb"); if (f) { - fread(scsi_hd_mode_sense_pages_saved[id].pages[0x30], 1, 0x18, f); + fread(dev->ms_pages_saved.pages[0x30], 1, 0x18, f); fclose(f); } } void -scsi_hd_mode_sense_save(uint8_t id) +scsi_disk_mode_sense_save(scsi_disk_t *dev) { wchar_t file_name[512]; FILE *f; memset(file_name, 0, 512 * sizeof(wchar_t)); - swprintf(file_name, 512, L"scsi_hd_%02i_mode_sense.bin", id); + swprintf(file_name, 512, L"scsi_hd_%02i_mode_sense.bin", dev->id); f = plat_fopen(nvr_path(file_name), L"wb"); if (f) { - fwrite(scsi_hd_mode_sense_pages_saved[id].pages[0x30], 1, 0x18, f); + fwrite(dev->ms_pages_saved.pages[0x30], 1, 0x18, f); fclose(f); } } int -scsi_hd_read_capacity(uint8_t id, uint8_t *cdb, uint8_t *buffer, uint32_t *len) +scsi_disk_read_capacity(scsi_disk_t *dev, uint8_t *cdb, uint8_t *buffer, uint32_t *len) { int size = 0; - size = hdd_image_get_last_sector(id); + size = hdd_image_get_last_sector(dev->id); memset(buffer, 0, 8); buffer[0] = (size >> 24) & 0xff; buffer[1] = (size >> 16) & 0xff; @@ -368,18 +338,18 @@ scsi_hd_read_capacity(uint8_t id, uint8_t *cdb, uint8_t *buffer, uint32_t *len) /*SCSI Mode Sense 6/10*/ uint8_t -scsi_hd_mode_sense_read(uint8_t id, uint8_t page_control, uint8_t page, uint8_t pos) +scsi_disk_mode_sense_read(scsi_disk_t *dev, uint8_t page_control, uint8_t page, uint8_t pos) { switch (page_control) { case 0: case 3: - return scsi_hd_mode_sense_pages_saved[id].pages[page][pos]; + return dev->ms_pages_saved.pages[page][pos]; break; case 1: - return scsi_hd_mode_sense_pages_changeable.pages[page][pos]; + return scsi_disk_mode_sense_pages_changeable.pages[page][pos]; break; case 2: - return scsi_hd_mode_sense_pages_default.pages[page][pos]; + return scsi_disk_mode_sense_pages_default.pages[page][pos]; break; } @@ -388,17 +358,15 @@ scsi_hd_mode_sense_read(uint8_t id, uint8_t page_control, uint8_t page, uint8_t uint32_t -scsi_hd_mode_sense(uint8_t id, uint8_t *buf, uint32_t pos, uint8_t type, uint8_t block_descriptor_len) +scsi_disk_mode_sense(scsi_disk_t *dev, uint8_t *buf, uint32_t pos, uint8_t type, uint8_t block_descriptor_len) { - uint8_t page_control = (type >> 6) & 3; - int i = 0; - int j = 0; - uint8_t msplen; + uint8_t msplen, page_control = (type >> 6) & 3; + int i = 0, j = 0; int size = 0; type &= 0x3f; - size = hdd_image_get_last_sector(id); + size = hdd_image_get_last_sector(dev->id); if (block_descriptor_len) { buf[pos++] = 1; /* Density code. */ @@ -412,15 +380,14 @@ scsi_hd_mode_sense(uint8_t id, uint8_t *buf, uint32_t pos, uint8_t type, uint8_t } for (i = 0; i < 0x40; i++) { - if ((type == GPMODE_ALL_PAGES) || (type == i)) { - if (scsi_hd_mode_sense_page_flags & (1LL << shdc[id].current_page_code)) { - buf[pos++] = scsi_hd_mode_sense_read(id, page_control, i, 0); - msplen = scsi_hd_mode_sense_read(id, page_control, i, 1); + if ((type == GPMODE_ALL_PAGES) || (type == i)) { + if (scsi_disk_mode_sense_page_flags & (1LL << dev->current_page_code)) { + buf[pos++] = scsi_disk_mode_sense_read(dev, page_control, i, 0); + msplen = scsi_disk_mode_sense_read(dev, page_control, i, 1); buf[pos++] = msplen; - scsi_hd_log("SCSI HDD %i: MODE SENSE: Page [%02X] length %i\n", id, i, msplen); - for (j=0; jid, i, msplen); + for (j = 0; j < msplen; j++) + buf[pos++] = scsi_disk_mode_sense_read(dev, page_control, i, 2 + j); } } } @@ -429,539 +396,365 @@ scsi_hd_mode_sense(uint8_t id, uint8_t *buf, uint32_t pos, uint8_t type, uint8_t } -void -scsi_hd_update_request_length(uint8_t id, int len, int block_len) -{ - /* For media access commands, make sure the requested - DRQ length matches the block length. */ - switch (shdc[id].current_cdb[0]) { - case 0x08: - case 0x0a: - case 0x28: - case 0x2a: - case 0xa8: - case 0xaa: - if (shdc[id].request_length < block_len) - { - shdc[id].request_length = block_len; - } - /* Make sure we respect the limit of how many blocks we can transfer at once. */ - if (shdc[id].requested_blocks > shdc[id].max_blocks_at_once) { - shdc[id].requested_blocks = shdc[id].max_blocks_at_once; - } - shdc[id].block_total = (shdc[id].requested_blocks * block_len); - if (len > shdc[id].block_total) { - len = shdc[id].block_total; - } - break; - default: - shdc[id].packet_len = len; - break; - } - - /* If the DRQ length is odd, and the total remaining length - is bigger, make sure it's even. */ - if ((shdc[id].request_length & 1) && (shdc[id].request_length < len)) { - shdc[id].request_length &= 0xfffe; - } - - /* If the DRQ length is smaller or equal in size to the - total remaining length, set it to that. */ - if (len <= shdc[id].request_length) { - shdc[id].request_length = len; - } -} - - static void -scsi_hd_command_common(uint8_t id) +scsi_disk_command_common(scsi_disk_t *dev) { - shdc[id].status = BUSY_STAT; - shdc[id].phase = 1; - shdc[id].pos = 0; - - if (shdc[id].packet_status == CDROM_PHASE_COMPLETE) { - scsi_hd_callback(id); - shdc[id].callback = 0LL; + dev->status = BUSY_STAT; + dev->phase = 1; + if (dev->packet_status == CDROM_PHASE_COMPLETE) { + scsi_disk_callback(dev); + dev->callback = 0LL; } else - shdc[id].callback = -1LL; /* Speed depends on SCSI controller */ -} - - -void -scsi_hd_command_complete(uint8_t id) -{ - shdc[id].packet_status = CDROM_PHASE_COMPLETE; - scsi_hd_command_common(id); + dev->callback = -1LL; /* Speed depends on SCSI controller */ } static void -scsi_hd_command_read_dma(uint8_t id) +scsi_disk_command_complete(scsi_disk_t *dev) { - shdc[id].packet_status = CDROM_PHASE_DATA_IN_DMA; - scsi_hd_command_common(id); - shdc[id].total_read = 0; + dev->packet_status = CDROM_PHASE_COMPLETE; + + scsi_disk_command_common(dev); } static void -scsi_hd_command_write_dma(uint8_t id) +scsi_disk_command_read_dma(scsi_disk_t *dev) { - shdc[id].packet_status = CDROM_PHASE_DATA_OUT_DMA; - scsi_hd_command_common(id); + dev->packet_status = CDROM_PHASE_DATA_IN_DMA; + + scsi_disk_command_common(dev); } -void -scsi_hd_data_command_finish(uint8_t id, int len, int block_len, int alloc_len, int direction) +static void +scsi_disk_command_write_dma(scsi_disk_t *dev) { - scsi_hd_log("SCSI HD %i: Finishing command (%02X): %i, %i, %i, %i, %i\n", id, shdc[id].current_cdb[0], len, block_len, alloc_len, direction, shdc[id].request_length); - shdc[id].pos=0; + dev->packet_status = CDROM_PHASE_DATA_OUT_DMA; + + scsi_disk_command_common(dev); +} + + +static void +scsi_disk_data_command_finish(scsi_disk_t *dev, int len, int block_len, int alloc_len, int direction) +{ + DEBUG("SCSI HD %i: Finishing command (%02X): %i, %i, %i, %i, %i\n", + dev->id, dev->current_cdb[0], len, block_len, alloc_len, + direction, dev->request_length); + if (alloc_len >= 0) { - if (alloc_len < len) { + if (alloc_len < len) len = alloc_len; - } } - if (len == 0) { - scsi_hd_command_complete(id); - } else { - if (direction == 0) { - scsi_hd_command_read_dma(id); - } else { - scsi_hd_command_write_dma(id); - } + if (len == 0) + scsi_disk_command_complete(dev); + else { + if (direction == 0) + scsi_disk_command_read_dma(dev); + else + scsi_disk_command_write_dma(dev); } - - scsi_hd_log("SCSI HD %i: Status: %i, cylinder %i, packet length: %i, position: %i, phase: %i\n", id, shdc[id].packet_status, shdc[id].request_length, shdc[id].packet_len, shdc[id].pos, shdc[id].phase); } static void -scsi_hd_sense_clear(int id, int command) +scsi_disk_sense_clear(scsi_disk_t *dev, int command) { - shdc[id].previous_command = command; - scsi_hd_sense_key = scsi_hd_asc = scsi_hd_ascq = 0; + scsi_disk_sense_key = scsi_disk_asc = scsi_disk_ascq = 0; } static void -scsi_hd_set_phase(uint8_t id, uint8_t phase) +scsi_disk_set_phase(scsi_disk_t *dev, uint8_t phase) { - uint8_t scsi_id = hdd[id].id.scsi.id; - uint8_t scsi_lun = hdd[id].id.scsi.lun; + uint8_t scsi_id = hdd[dev->id].id.scsi.id; + uint8_t scsi_lun = hdd[dev->id].id.scsi.lun; - if ((hdd[id].bus != HDD_BUS_SCSI) && - (hdd[id].bus != HDD_BUS_SCSI_REMOVABLE)) return; + if (hdd[dev->id].bus != HDD_BUS_SCSI) + return; SCSIDevices[scsi_id][scsi_lun].Phase = phase; } static void -scsi_hd_cmd_error(uint8_t id) +scsi_disk_cmd_error(scsi_disk_t *dev) { - scsi_hd_set_phase(id, SCSI_PHASE_STATUS); - shdc[id].error = ((scsi_hd_sense_key & 0xf) << 4) | ABRT_ERR; - if (shdc[id].unit_attention & 3) { - shdc[id].error |= MCR_ERR; - } - shdc[id].status = READY_STAT | ERR_STAT; - shdc[id].phase = 3; - shdc[id].packet_status = 0x80; - shdc[id].callback = 50 * SCSI_TIME; - - scsi_hd_log("SCSI HD %i: ERROR: %02X/%02X/%02X\n", id, scsi_hd_sense_key, scsi_hd_asc, scsi_hd_ascq); + scsi_disk_set_phase(dev, SCSI_PHASE_STATUS); + dev->error = ((scsi_disk_sense_key & 0xf) << 4) | ABRT_ERR; + dev->status = READY_STAT | ERR_STAT; + dev->phase = 3; + dev->packet_status = 0x80; + dev->callback = 50 * SCSI_TIME; + DEBUG("SCSI HD %i: ERROR: %02X/%02X/%02X\n", + dev->id, scsi_disk_sense_key, scsi_disk_asc, scsi_disk_ascq); } static void -scsi_hd_unit_attention(uint8_t id) +scsi_disk_invalid_lun(scsi_disk_t *dev) { - scsi_hd_set_phase(id, SCSI_PHASE_STATUS); - shdc[id].error = (SENSE_NOT_READY << 4) | ABRT_ERR; - if (shdc[id].unit_attention & 3) { - shdc[id].error |= MCR_ERR; - } - shdc[id].status = READY_STAT | ERR_STAT; - shdc[id].phase = 3; - shdc[id].packet_status = 0x80; - shdc[id].callback = 50 * CDROM_TIME; - - scsi_hd_log("SCSI HD %i: UNIT ATTENTION\n", id); + scsi_disk_sense_key = SENSE_ILLEGAL_REQUEST; + scsi_disk_asc = ASC_INV_LUN; + scsi_disk_ascq = 0; + scsi_disk_set_phase(dev, SCSI_PHASE_STATUS); + scsi_disk_cmd_error(dev); } static void -scsi_hd_not_ready(uint8_t id) +scsi_disk_illegal_opcode(scsi_disk_t *dev) { - scsi_hd_sense_key = SENSE_NOT_READY; - scsi_hd_asc = ASC_MEDIUM_NOT_PRESENT; - scsi_hd_ascq = 0; - scsi_hd_cmd_error(id); + scsi_disk_sense_key = SENSE_ILLEGAL_REQUEST; + scsi_disk_asc = ASC_ILLEGAL_OPCODE; + scsi_disk_ascq = 0; + scsi_disk_cmd_error(dev); } static void -scsi_hd_write_protected(uint8_t id) +scsi_disk_lba_out_of_range(scsi_disk_t *dev) { - scsi_hd_sense_key = SENSE_UNIT_ATTENTION; - scsi_hd_asc = ASC_WRITE_PROTECTED; - scsi_hd_ascq = 0; - scsi_hd_cmd_error(id); + scsi_disk_sense_key = SENSE_ILLEGAL_REQUEST; + scsi_disk_asc = ASC_LBA_OUT_OF_RANGE; + scsi_disk_ascq = 0; + scsi_disk_cmd_error(dev); } static void -scsi_hd_invalid_lun(uint8_t id) +scsi_disk_invalid_field(scsi_disk_t *dev) { - scsi_hd_sense_key = SENSE_ILLEGAL_REQUEST; - scsi_hd_asc = ASC_INV_LUN; - scsi_hd_ascq = 0; - scsi_hd_set_phase(id, SCSI_PHASE_STATUS); - scsi_hd_cmd_error(id); + scsi_disk_sense_key = SENSE_ILLEGAL_REQUEST; + scsi_disk_asc = ASC_INV_FIELD_IN_CMD_PACKET; + scsi_disk_ascq = 0; + scsi_disk_cmd_error(dev); + dev->status = 0x53; } static void -scsi_hd_illegal_opcode(uint8_t id) +scsi_disk_invalid_field_pl(scsi_disk_t *dev) { - scsi_hd_sense_key = SENSE_ILLEGAL_REQUEST; - scsi_hd_asc = ASC_ILLEGAL_OPCODE; - scsi_hd_ascq = 0; - scsi_hd_cmd_error(id); -} - - -void -scsi_hd_lba_out_of_range(uint8_t id) -{ - scsi_hd_sense_key = SENSE_ILLEGAL_REQUEST; - scsi_hd_asc = ASC_LBA_OUT_OF_RANGE; - scsi_hd_ascq = 0; - scsi_hd_cmd_error(id); + scsi_disk_sense_key = SENSE_ILLEGAL_REQUEST; + scsi_disk_asc = ASC_INV_FIELD_IN_PARAMETER_LIST; + scsi_disk_ascq = 0; + scsi_disk_cmd_error(dev); + dev->status = 0x53; } static void -scsi_hd_invalid_field(uint8_t id) +scsi_disk_data_phase_error(scsi_disk_t *dev) { - scsi_hd_sense_key = SENSE_ILLEGAL_REQUEST; - scsi_hd_asc = ASC_INV_FIELD_IN_CMD_PACKET; - scsi_hd_ascq = 0; - scsi_hd_cmd_error(id); - shdc[id].status = 0x53; + scsi_disk_sense_key = SENSE_ILLEGAL_REQUEST; + scsi_disk_asc = ASC_DATA_PHASE_ERROR; + scsi_disk_ascq = 0; + scsi_disk_cmd_error(dev); } -static void -scsi_hd_invalid_field_pl(uint8_t id) +static int +scsi_disk_pre_execution_check(scsi_disk_t *dev, uint8_t *cdb) { - scsi_hd_sense_key = SENSE_ILLEGAL_REQUEST; - scsi_hd_asc = ASC_INV_FIELD_IN_PARAMETER_LIST; - scsi_hd_ascq = 0; - scsi_hd_cmd_error(id); - shdc[id].status = 0x53; -} + if (((dev->request_length >> 5) & 7) != hdd[dev->id].id.scsi.lun) { + DEBUG("SCSI HD %i: Attempting to execute a unknown command targeted at SCSI LUN %i\n", + dev->id, ((dev->request_length >> 5) & 7)); - -static void -scsi_hd_data_phase_error(uint8_t id) -{ - scsi_hd_sense_key = SENSE_ILLEGAL_REQUEST; - scsi_hd_asc = ASC_DATA_PHASE_ERROR; - scsi_hd_ascq = 0; - scsi_hd_cmd_error(id); -} - - -/*SCSI Sense Initialization*/ -void -scsi_hd_sense_code_ok(uint8_t id) -{ - scsi_hd_sense_key = SENSE_NONE; - scsi_hd_asc = 0; - scsi_hd_ascq = 0; -} - - -int -scsi_hd_pre_execution_check(uint8_t id, uint8_t *cdb) -{ - int ready = 1; - - if (((shdc[id].request_length >> 5) & 7) != hdd[id].id.scsi.lun) { - scsi_hd_log("SCSI HD %i: Attempting to execute a unknown command targeted at SCSI LUN %i\n", id, ((shdc[id].request_length >> 5) & 7)); - scsi_hd_invalid_lun(id); + scsi_disk_invalid_lun(dev); return 0; } - if (!(scsi_hd_command_flags[cdb[0]] & IMPLEMENTED)) { - scsi_hd_log("SCSI HD %i: Attempting to execute unknown command %02X\n", id, cdb[0]); - scsi_hd_illegal_opcode(id); + if (!(scsi_disk_command_flags[cdb[0]] & IMPLEMENTED)) { + DEBUG("SCSI HD %i: Attempting to execute unknown command %02X\n", + dev->id, cdb[0]); + + scsi_disk_illegal_opcode(dev); return 0; } - if (hdd[id].bus == HDD_BUS_SCSI_REMOVABLE) { - /* Removable disk, set ready state. */ - if (wcslen(hdd[id].fn) > 0) { - ready = 1; - } else { - ready = 0; - } - } else { - /* Fixed disk, clear UNIT ATTENTION, just in case it might have been set when the disk was removable). */ - shdc[id].unit_attention = 0; - } - - if (!ready && shdc[id].unit_attention) { - /* If the drive is not ready, there is no reason to keep the - UNIT ATTENTION condition present, as we only use it to mark - disc changes. */ - shdc[id].unit_attention = 0; - } - - /* If the UNIT ATTENTION condition is set and the command does not allow - execution under it, error out and report the condition. */ - if (shdc[id].unit_attention == 1) { - /* Only increment the unit attention phase if the command can not pass through it. */ - if (!(scsi_hd_command_flags[cdb[0]] & ALLOW_UA)) { - /* scsi_hd_log("SCSI HD %i: Unit attention now 2\n", id); */ - shdc[id].unit_attention = 2; - scsi_hd_log("SCSI HD %i: UNIT ATTENTION: Command %02X not allowed to pass through\n", id, cdb[0]); - scsi_hd_unit_attention(id); - return 0; - } - } else if (shdc[id].unit_attention == 2) { - if (cdb[0] != GPCMD_REQUEST_SENSE) { - /* scsi_hd_log("SCSI HD %i: Unit attention now 0\n", id); */ - shdc[id].unit_attention = 0; - } - } - /* Unless the command is REQUEST SENSE, clear the sense. This will *NOT* - the UNIT ATTENTION condition if it's set. */ - if (cdb[0] != GPCMD_REQUEST_SENSE) { - scsi_hd_sense_clear(id, cdb[0]); - } + the UNIT ATTENTION condition if it's set. */ + if (cdb[0] != GPCMD_REQUEST_SENSE) + scsi_disk_sense_clear(dev, cdb[0]); - /* Next it's time for NOT READY. */ - if ((scsi_hd_command_flags[cdb[0]] & CHECK_READY) && !ready) { - scsi_hd_log("SCSI HD %i: Not ready (%02X)\n", id, cdb[0]); - scsi_hd_not_ready(id); - return 0; - } - - scsi_hd_log("SCSI HD %i: Continuing with command\n", id); + DEBUG("SCSI HD %i: Continuing with command\n", dev->id); return 1; } static void -scsi_hd_seek(uint8_t id, uint32_t pos) +scsi_disk_seek(scsi_disk_t *dev, uint32_t pos) { - /* scsi_hd_log("SCSI HD %i: Seek %08X\n", id, pos); */ - hdd_image_seek(id, pos); + DBGLOG(1, "SCSI HD %i: Seek %08X\n", dev->id, pos); + + hdd_image_seek(dev->id, pos); } static void -scsi_hd_rezero(uint8_t id) +scsi_disk_rezero(scsi_disk_t *dev) { - if (id == 255) return; + if (dev->id == 0xff) + return; - shdc[id].sector_pos = shdc[id].sector_len = 0; - scsi_hd_seek(id, 0); + dev->sector_pos = dev->sector_len = 0; + scsi_disk_seek(dev, 0); } void -scsi_hd_reset(uint8_t id) +scsi_disk_reset(scsi_disk_t *dev) { - scsi_hd_rezero(id); - shdc[id].status = 0; - shdc[id].callback = 0; - shdc[id].packet_status = 0xff; + scsi_disk_rezero(dev); + + dev->status = 0; + dev->callback = 0; + dev->packet_status = 0xff; } void -scsi_hd_request_sense(uint8_t id, uint8_t *buffer, uint8_t alloc_length, int desc) -{ +scsi_disk_request_sense(scsi_disk_t *dev, uint8_t *buffer, uint8_t alloc_length, int desc) +{ /*Will return 18 bytes of 0*/ if (alloc_length != 0) { - memset(buffer, 0x00, alloc_length); - if (! desc) - memcpy(buffer, shdc[id].sense, alloc_length); + memset(buffer, 0, alloc_length); + if (!desc) + memcpy(buffer, dev->sense, alloc_length); else { - buffer[1] = scsi_hd_sense_key; - buffer[2] = scsi_hd_asc; - buffer[3] = scsi_hd_ascq; + buffer[1] = scsi_disk_sense_key; + buffer[2] = scsi_disk_asc; + buffer[3] = scsi_disk_ascq; } - } else { + } else return; - } buffer[0] = 0x70; - if (shdc[id].unit_attention && (scsi_hd_sense_key == 0)) { - buffer[desc ? 1 : 2]=SENSE_UNIT_ATTENTION; - buffer[desc ? 2 : 12]=ASC_MEDIUM_MAY_HAVE_CHANGED; - buffer[desc ? 3 : 13]=0x00; - } - - scsi_hd_log("SCSI HD %i: Reporting sense: %02X %02X %02X\n", id, buffer[2], buffer[12], buffer[13]); - - if (buffer[desc ? 1: 2] == SENSE_UNIT_ATTENTION) { - /* If the last remaining sense is unit attention, clear - that condition. */ - shdc[id].unit_attention = 0; - } + DEBUG("SCSI HD %i: Reporting sense: %02X %02X %02X\n", + dev->id, buffer[2], buffer[12], buffer[13]); /* Clear the sense stuff as per the spec. */ - scsi_hd_sense_clear(id, GPCMD_REQUEST_SENSE); + scsi_disk_sense_clear(dev, GPCMD_REQUEST_SENSE); } void -scsi_hd_request_sense_for_scsi(uint8_t id, uint8_t *buffer, uint8_t alloc_length) +scsi_disk_request_sense_for_scsi(scsi_disk_t *dev, uint8_t *buffer, uint8_t alloc_length) { - int ready = 1; + scsi_disk_request_sense(dev, buffer, alloc_length, 0); +} - if (hdd[id].bus == HDD_BUS_SCSI_REMOVABLE) { - /* Removable disk, set ready state. */ - if (wcslen(hdd[id].fn) > 0) { - ready = 1; - } else { - ready = 0; - } - } else { - /* Fixed disk, clear UNIT ATTENTION, just in case it might have been set when the disk was removable). */ - shdc[id].unit_attention = 0; + +static void +scsi_disk_set_buf_len(scsi_disk_t *dev, int32_t *BufLen, int32_t *src_len) +{ + if (*BufLen == -1) + *BufLen = *src_len; + else { + *BufLen = MIN(*src_len, *BufLen); + *src_len = *BufLen; } - if (!ready && shdc[id].unit_attention) { - /* If the drive is not ready, there is no reason to keep the - UNIT ATTENTION condition present, as we only use it to mark - disc changes. */ - shdc[id].unit_attention = 0; - } - - /* Do *NOT* advance the unit attention phase. */ - scsi_hd_request_sense(id, buffer, alloc_length, 0); + DEBUG("SCSI HD %i: Actual transfer length: %i\n", dev->id, *BufLen); } void -scsi_hd_command(uint8_t id, uint8_t *cdb) +scsi_disk_command(scsi_disk_t *dev, uint8_t *cdb) { - /* uint8_t *hdbufferb = (uint8_t *) shdc[id].buffer; */ - uint8_t *hdbufferb = SCSIDevices[hdd[id].id.scsi.id][hdd[id].id.scsi.lun].CmdBuffer; - int32_t len; - int pos=0; - int max_len; - int idx = 0; - unsigned size_idx; - unsigned preamble_len; - int32_t alloc_length; - char device_identify[9] = { - 'E','M','U','_','H','D','0','0',0 }; - char device_identify_ex[15] = { - 'E','M','U','_','H','D','0','0',' ','v','1','.','0','0',0 }; - uint32_t last_sector = 0; - int block_desc = 0; - int32_t *BufLen = &SCSIDevices[hdd[id].id.scsi.id][hdd[id].id.scsi.lun].BufferLength; -#if 0 - int CdbLength; +#ifdef _LOGGING + uint8_t *hdbufferb = SCSIDevices[hdd[dev->id].id.scsi.id][hdd[dev->id].id.scsi.lun].CmdBuffer; #endif + int32_t len, max_len, alloc_length; + int pos = 0; + int idx = 0; + unsigned size_idx, preamble_len; + uint32_t last_sector = 0; + char device_identify[9] = { 'E', 'M', 'U', '_', 'H', 'D', '0', '0', 0 }; + char device_identify_ex[15] = { 'E', 'M', 'U', '_', 'H', 'D', '0', '0', ' ', 'v', '1', '.', '0', '0', 0 }; + int block_desc = 0; + int32_t *BufLen = &SCSIDevices[hdd[dev->id].id.scsi.id][hdd[dev->id].id.scsi.lun].BufferLength; - last_sector = hdd_image_get_last_sector(id); + last_sector = hdd_image_get_last_sector(dev->id); - shdc[id].status &= ~ERR_STAT; + dev->status &= ~ERR_STAT; + dev->packet_len = 0; - shdc[id].packet_len = 0; - shdc[id].request_pos = 0; + device_identify[6] = (dev->id / 10) + 0x30; + device_identify[7] = (dev->id % 10) + 0x30; - device_identify[6] = (id / 10) + 0x30; - device_identify[7] = (id % 10) + 0x30; - - device_identify_ex[6] = (id / 10) + 0x30; - device_identify_ex[7] = (id % 10) + 0x30; + device_identify_ex[6] = (dev->id / 10) + 0x30; + device_identify_ex[7] = (dev->id % 10) + 0x30; device_identify_ex[10] = EMU_VERSION[0]; device_identify_ex[12] = EMU_VERSION[2]; device_identify_ex[13] = EMU_VERSION[3]; - if (hdd[id].bus == HDD_BUS_SCSI_REMOVABLE) { - device_identify[4] = 'R'; - device_identify_ex[4] = 'R'; - } - - shdc[id].data_pos = 0; - - memcpy(shdc[id].current_cdb, cdb, 12); + memcpy(dev->current_cdb, cdb, 12); if (cdb[0] != 0) { - scsi_hd_log("SCSI HD %i: Command 0x%02X, Sense Key %02X, Asc %02X, Ascq %02X\n", id, cdb[0], scsi_hd_sense_key, scsi_hd_asc, scsi_hd_ascq); - scsi_hd_log("SCSI HD %i: Request length: %04X\n", id, shdc[id].request_length); - -#if 0 - for (CdbLength = 1; CdbLength < 12; CdbLength++) { - scsi_hd_log("SCSI HD %i: CDB[%d] = %d\n", id, CdbLength, cdb[CdbLength]); - } -#endif + DEBUG("SCSI HD %i: Command 0x%02X, Sense Key %02X, Asc %02X, Ascq %02X\n", + dev->id, cdb[0], scsi_disk_sense_key, scsi_disk_asc, + scsi_disk_ascq); + DEBUG("SCSI HD %i: Request length: %04X\n", + dev->id, dev->request_length); + DEBUG("SCSI HD %i: CDB: %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n", + dev->id, cdb[0], cdb[1], cdb[2], cdb[3], cdb[4], cdb[5], + cdb[6], cdb[7], cdb[8], cdb[9], cdb[10], cdb[11]); } - - shdc[id].sector_len = 0; - scsi_hd_set_phase(id, SCSI_PHASE_STATUS); + dev->sector_len = 0; + + scsi_disk_set_phase(dev, SCSI_PHASE_STATUS); /* This handles the Not Ready/Unit Attention check if it has to be handled at this point. */ - if (scsi_hd_pre_execution_check(id, cdb) == 0) return; + if (scsi_disk_pre_execution_check(dev, cdb) == 0) + return; switch (cdb[0]) { case GPCMD_SEND_DIAGNOSTIC: if (!(cdb[1] & (1 << 2))) { - scsi_hd_invalid_field(id); + scsi_disk_invalid_field(dev); return; } case GPCMD_SCSI_RESERVE: case GPCMD_SCSI_RELEASE: case GPCMD_TEST_UNIT_READY: case GPCMD_FORMAT_UNIT: - scsi_hd_set_phase(id, SCSI_PHASE_STATUS); - scsi_hd_command_complete(id); + scsi_disk_set_phase(dev, SCSI_PHASE_STATUS); + scsi_disk_command_complete(dev); break; case GPCMD_REZERO_UNIT: - shdc[id].sector_pos = shdc[id].sector_len = 0; - scsi_hd_seek(id, 0); - scsi_hd_set_phase(id, SCSI_PHASE_STATUS); + dev->sector_pos = dev->sector_len = 0; + scsi_disk_seek(dev, 0); + scsi_disk_set_phase(dev, SCSI_PHASE_STATUS); break; case GPCMD_REQUEST_SENSE: /* If there's a unit attention condition and there's a buffered not ready, a standalone REQUEST SENSE should forget about the not ready, and report unit attention straight away. */ - if ((*BufLen == -1) || (cdb[4] < *BufLen)) - *BufLen = cdb[4]; + len = cdb[4]; + scsi_disk_set_buf_len(dev, BufLen, &len); if (*BufLen < cdb[4]) cdb[4] = *BufLen; len = (cdb[1] & 1) ? 8 : 18; - scsi_hd_set_phase(id, SCSI_PHASE_DATA_IN); - scsi_hd_data_command_finish(id, len, len, cdb[4], 0); + scsi_disk_set_phase(dev, SCSI_PHASE_DATA_IN); + scsi_disk_data_command_finish(dev, len, len, cdb[4], 0); break; case GPCMD_MECHANISM_STATUS: len = (cdb[7] << 16) | (cdb[8] << 8) | cdb[9]; - if ((*BufLen == -1) || (len < *BufLen)) - *BufLen = len; - - scsi_hd_set_phase(id, SCSI_PHASE_DATA_IN); - scsi_hd_data_command_finish(id, 8, 8, len, 0); + scsi_disk_set_buf_len(dev, BufLen, &len); + scsi_disk_set_phase(dev, SCSI_PHASE_DATA_IN); + scsi_disk_data_command_finish(dev, 8, 8, len, 0); break; case GPCMD_READ_6: @@ -969,58 +762,55 @@ scsi_hd_command(uint8_t id, uint8_t *cdb) case GPCMD_READ_12: switch(cdb[0]) { case GPCMD_READ_6: - shdc[id].sector_len = cdb[4]; - shdc[id].sector_pos = ((((uint32_t) cdb[1]) & 0x1f) << 16) | (((uint32_t) cdb[2]) << 8) | ((uint32_t) cdb[3]); + dev->sector_len = cdb[4]; + dev->sector_pos = ((((uint32_t) cdb[1]) & 0x1f) << 16) | (((uint32_t) cdb[2]) << 8) | ((uint32_t) cdb[3]); break; case GPCMD_READ_10: - shdc[id].sector_len = (cdb[7] << 8) | cdb[8]; - shdc[id].sector_pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; + dev->sector_len = (cdb[7] << 8) | cdb[8]; + dev->sector_pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; break; case GPCMD_READ_12: - shdc[id].sector_len = (((uint32_t) cdb[6]) << 24) | (((uint32_t) cdb[7]) << 16) | (((uint32_t) cdb[8]) << 8) | ((uint32_t) cdb[9]); - shdc[id].sector_pos = (((uint32_t) cdb[2]) << 24) | (((uint32_t) cdb[3]) << 16) | (((uint32_t) cdb[4]) << 8) | ((uint32_t) cdb[5]); + dev->sector_len = (((uint32_t) cdb[6]) << 24) | (((uint32_t) cdb[7]) << 16) | (((uint32_t) cdb[8]) << 8) | ((uint32_t) cdb[9]); + dev->sector_pos = (((uint32_t) cdb[2]) << 24) | (((uint32_t) cdb[3]) << 16) | (((uint32_t) cdb[4]) << 8) | ((uint32_t) cdb[5]); break; } - if ((shdc[id].sector_pos > last_sector) || ((shdc[id].sector_pos + shdc[id].sector_len - 1) > last_sector)) { - scsi_hd_lba_out_of_range(id); + if ((dev->sector_pos > last_sector) || + ((dev->sector_pos + dev->sector_len - 1) > last_sector)) { + scsi_disk_lba_out_of_range(dev); return; } - if ((!shdc[id].sector_len) || (*BufLen == 0)) { - scsi_hd_set_phase(id, SCSI_PHASE_STATUS); - ui_sb_icon_update((hdd[id].bus == HDD_BUS_SCSI_REMOVABLE) ? (SB_RDISK | id) : (SB_HDD | HDD_BUS_SCSI), 0); - scsi_hd_log("SCSI HD %i: All done - callback set\n", id); - shdc[id].packet_status = CDROM_PHASE_COMPLETE; - shdc[id].callback = 20 * SCSI_TIME; + if ((!dev->sector_len) || (*BufLen == 0)) { + scsi_disk_set_phase(dev, SCSI_PHASE_STATUS); + DEBUG("SCSI HD %i: All done - callback set\n", dev->id); + dev->packet_status = CDROM_PHASE_COMPLETE; + dev->callback = 20 * SCSI_TIME; break; } - max_len = shdc[id].sector_len; - shdc[id].requested_blocks = max_len; + hdd_active(dev->id, 1); - alloc_length = shdc[id].packet_len = max_len << 9; + max_len = dev->sector_len; + dev->requested_blocks = max_len; - if ((*BufLen == -1) || (alloc_length < *BufLen)) - *BufLen = alloc_length; + alloc_length = dev->packet_len = max_len << 9; - scsi_hd_set_phase(id, SCSI_PHASE_DATA_IN); + scsi_disk_set_buf_len(dev, BufLen, &alloc_length); + scsi_disk_set_phase(dev, SCSI_PHASE_DATA_IN); - if (shdc[id].requested_blocks > 1) { - scsi_hd_data_command_finish(id, alloc_length, alloc_length / shdc[id].requested_blocks, alloc_length, 0); - } else { - scsi_hd_data_command_finish(id, alloc_length, alloc_length, alloc_length, 0); - } - shdc[id].all_blocks_total = shdc[id].block_total; - ui_sb_icon_update((hdd[id].bus == HDD_BUS_SCSI_REMOVABLE) ? (SB_RDISK | id) : (SB_HDD | HDD_BUS_SCSI), 1); + if (dev->requested_blocks > 1) + scsi_disk_data_command_finish(dev, alloc_length, alloc_length / dev->requested_blocks, alloc_length, 0); + else + scsi_disk_data_command_finish(dev, alloc_length, alloc_length, alloc_length, 0); return; case GPCMD_VERIFY_6: case GPCMD_VERIFY_10: case GPCMD_VERIFY_12: if (!(cdb[1] & 2)) { - scsi_hd_set_phase(id, SCSI_PHASE_STATUS); - scsi_hd_command_complete(id); + scsi_disk_set_phase(dev, SCSI_PHASE_STATUS); + scsi_disk_command_complete(dev); break; } case GPCMD_WRITE_6: @@ -1028,117 +818,102 @@ scsi_hd_command(uint8_t id, uint8_t *cdb) case GPCMD_WRITE_AND_VERIFY_10: case GPCMD_WRITE_12: case GPCMD_WRITE_AND_VERIFY_12: - if ((hdd[id].bus == HDD_BUS_SCSI_REMOVABLE) && hdd[id].wp) { - scsi_hd_write_protected(id); - return; - } - switch(cdb[0]) { case GPCMD_VERIFY_6: case GPCMD_WRITE_6: - shdc[id].sector_len = cdb[4]; - shdc[id].sector_pos = ((((uint32_t) cdb[1]) & 0x1f) << 16) | (((uint32_t) cdb[2]) << 8) | ((uint32_t) cdb[3]); - scsi_hd_log("SCSI HD %i: Length: %i, LBA: %i\n", id, shdc[id].sector_len, shdc[id].sector_pos); + dev->sector_len = cdb[4]; + dev->sector_pos = ((((uint32_t) cdb[1]) & 0x1f) << 16) | (((uint32_t) cdb[2]) << 8) | ((uint32_t) cdb[3]); + DEBUG("SCSI HD %i: Length: %i, LBA: %i\n", dev->id, dev->sector_len, dev->sector_pos); break; case GPCMD_VERIFY_10: case GPCMD_WRITE_10: case GPCMD_WRITE_AND_VERIFY_10: - shdc[id].sector_len = (cdb[7] << 8) | cdb[8]; - shdc[id].sector_pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; - scsi_hd_log("SCSI HD %i: Length: %i, LBA: %i\n", id, shdc[id].sector_len, shdc[id].sector_pos); + dev->sector_len = (cdb[7] << 8) | cdb[8]; + dev->sector_pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; + DEBUG("SCSI HD %i: Length: %i, LBA: %i\n", dev->id, dev->sector_len, dev->sector_pos); break; case GPCMD_VERIFY_12: case GPCMD_WRITE_12: case GPCMD_WRITE_AND_VERIFY_12: - shdc[id].sector_len = (((uint32_t) cdb[6]) << 24) | (((uint32_t) cdb[7]) << 16) | (((uint32_t) cdb[8]) << 8) | ((uint32_t) cdb[9]); - shdc[id].sector_pos = (((uint32_t) cdb[2]) << 24) | (((uint32_t) cdb[3]) << 16) | (((uint32_t) cdb[4]) << 8) | ((uint32_t) cdb[5]); + dev->sector_len = (((uint32_t) cdb[6]) << 24) | (((uint32_t) cdb[7]) << 16) | (((uint32_t) cdb[8]) << 8) | ((uint32_t) cdb[9]); + dev->sector_pos = (((uint32_t) cdb[2]) << 24) | (((uint32_t) cdb[3]) << 16) | (((uint32_t) cdb[4]) << 8) | ((uint32_t) cdb[5]); break; } - if ((shdc[id].sector_pos > last_sector) || ((shdc[id].sector_pos + shdc[id].sector_len - 1) > last_sector)) { - scsi_hd_lba_out_of_range(id); + if ((dev->sector_pos > last_sector) || + ((dev->sector_pos + dev->sector_len - 1) > last_sector)) { + scsi_disk_lba_out_of_range(dev); return; } - if ((!shdc[id].sector_len) || (*BufLen == 0)) { - scsi_hd_set_phase(id, SCSI_PHASE_STATUS); - ui_sb_icon_update((hdd[id].bus == HDD_BUS_SCSI_REMOVABLE) ? (SB_RDISK | id) : (SB_HDD | HDD_BUS_SCSI), 0); - scsi_hd_log("SCSI HD %i: All done - callback set\n", id); - shdc[id].packet_status = CDROM_PHASE_COMPLETE; - shdc[id].callback = 20 * SCSI_TIME; + if ((!dev->sector_len) || (*BufLen == 0)) { + scsi_disk_set_phase(dev, SCSI_PHASE_STATUS); + DEBUG("SCSI HD %i: All done - callback set\n", dev->id); + dev->packet_status = CDROM_PHASE_COMPLETE; + dev->callback = 20 * SCSI_TIME; break; } - max_len = shdc[id].sector_len; - shdc[id].requested_blocks = max_len; + hdd_active(dev->id, 1); - alloc_length = shdc[id].packet_len = max_len << 9; + max_len = dev->sector_len; + dev->requested_blocks = max_len; - if ((*BufLen == -1) || (alloc_length < *BufLen)) - *BufLen = alloc_length; + alloc_length = dev->packet_len = max_len << 9; - scsi_hd_set_phase(id, SCSI_PHASE_DATA_OUT); + scsi_disk_set_buf_len(dev, BufLen, &alloc_length); + scsi_disk_set_phase(dev, SCSI_PHASE_DATA_OUT); - if (shdc[id].requested_blocks > 1) { - scsi_hd_data_command_finish(id, alloc_length, alloc_length / shdc[id].requested_blocks, alloc_length, 1); - } else { - scsi_hd_data_command_finish(id, alloc_length, alloc_length, alloc_length, 1); - } - shdc[id].all_blocks_total = shdc[id].block_total; - ui_sb_icon_update((hdd[id].bus == HDD_BUS_SCSI_REMOVABLE) ? (SB_RDISK | id) : (SB_HDD | HDD_BUS_SCSI), 1); + if (dev->requested_blocks > 1) + scsi_disk_data_command_finish(dev, alloc_length, alloc_length / dev->requested_blocks, alloc_length, 1); + else + scsi_disk_data_command_finish(dev, alloc_length, alloc_length, alloc_length, 1); return; case GPCMD_WRITE_SAME_10: if ((cdb[1] & 6) == 6) { - scsi_hd_invalid_field(id); + scsi_disk_invalid_field(dev); return; } - if ((hdd[id].bus == HDD_BUS_SCSI_REMOVABLE) && hdd[id].wp) { - scsi_hd_write_protected(id); + dev->sector_len = (cdb[7] << 8) | cdb[8]; + dev->sector_pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; + DEBUG("SCSI HD %i: Length: %i, LBA: %i\n", + dev->id, dev->sector_len, dev->sector_pos); + + if ((dev->sector_pos > last_sector) || + ((dev->sector_pos + dev->sector_len - 1) > last_sector)) { + scsi_disk_lba_out_of_range(dev); return; } - shdc[id].sector_len = (cdb[7] << 8) | cdb[8]; - shdc[id].sector_pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; - scsi_hd_log("SCSI HD %i: Length: %i, LBA: %i\n", id, shdc[id].sector_len, shdc[id].sector_pos); - - if ((shdc[id].sector_pos > last_sector) || ((shdc[id].sector_pos + shdc[id].sector_len - 1) > last_sector)) { - scsi_hd_lba_out_of_range(id); - return; - } - - if ((!shdc[id].sector_len) || (*BufLen == 0)) { - scsi_hd_set_phase(id, SCSI_PHASE_STATUS); - ui_sb_icon_update((hdd[id].bus == HDD_BUS_SCSI_REMOVABLE) ? (SB_RDISK | id) : (SB_HDD | HDD_BUS_SCSI), 0); - scsi_hd_log("SCSI HD %i: All done - callback set\n", id); - shdc[id].packet_status = CDROM_PHASE_COMPLETE; - shdc[id].callback = 20 * SCSI_TIME; + if ((!dev->sector_len) || (*BufLen == 0)) { + scsi_disk_set_phase(dev, SCSI_PHASE_STATUS); + DEBUG("SCSI HD %i: All done - callback set\n", dev->id); + dev->packet_status = CDROM_PHASE_COMPLETE; + dev->callback = 20 * SCSI_TIME; break; } + hdd_active(dev->id, 1); + max_len = 1; - shdc[id].requested_blocks = max_len; + dev->requested_blocks = max_len; - alloc_length = shdc[id].packet_len = max_len << 9; + alloc_length = dev->packet_len = max_len << 9; - if ((*BufLen == -1) || (alloc_length < *BufLen)) - *BufLen = alloc_length; + scsi_disk_set_buf_len(dev, BufLen, &alloc_length); + scsi_disk_set_phase(dev, SCSI_PHASE_DATA_OUT); - scsi_hd_set_phase(id, SCSI_PHASE_DATA_OUT); - - if (shdc[id].requested_blocks > 1) { - scsi_hd_data_command_finish(id, alloc_length, alloc_length / shdc[id].requested_blocks, alloc_length, 1); - } else { - scsi_hd_data_command_finish(id, alloc_length, alloc_length, alloc_length, 1); - } - shdc[id].all_blocks_total = shdc[id].block_total; - ui_sb_icon_update((hdd[id].bus == HDD_BUS_SCSI_REMOVABLE) ? (SB_RDISK | id) : (SB_HDD | HDD_BUS_SCSI), 1); + if (dev->requested_blocks > 1) + scsi_disk_data_command_finish(dev, alloc_length, alloc_length / dev->requested_blocks, alloc_length, 1); + else + scsi_disk_data_command_finish(dev, alloc_length, alloc_length, alloc_length, 1); return; case GPCMD_MODE_SENSE_6: case GPCMD_MODE_SENSE_10: - scsi_hd_set_phase(id, SCSI_PHASE_DATA_IN); + scsi_disk_set_phase(dev, SCSI_PHASE_DATA_IN); block_desc = ((cdb[1] >> 3) & 1) ? 0 : 1; @@ -1147,31 +922,31 @@ scsi_hd_command(uint8_t id, uint8_t *cdb) else len = (cdb[8] | (cdb[7] << 8)); - shdc[id].current_page_code = cdb[2] & 0x3F; + dev->current_page_code = cdb[2] & 0x3F; alloc_length = len; - shdc[id].temp_buffer = (uint8_t *) malloc(65536); - memset(shdc[id].temp_buffer, 0, 65536); + dev->temp_buffer = (uint8_t *)mem_alloc(65536); + memset(dev->temp_buffer, 0, 65536); if (cdb[0] == GPCMD_MODE_SENSE_6) { - len = scsi_hd_mode_sense(id, shdc[id].temp_buffer, 4, cdb[2], block_desc); + len = scsi_disk_mode_sense(dev, dev->temp_buffer, 4, cdb[2], block_desc); if (len > alloc_length) len = alloc_length; - shdc[id].temp_buffer[0] = len - 1; - shdc[id].temp_buffer[1] = 0; + dev->temp_buffer[0] = len - 1; + dev->temp_buffer[1] = 0; if (block_desc) - shdc[id].temp_buffer[3] = 8; + dev->temp_buffer[3] = 8; } else { - len = scsi_hd_mode_sense(id, shdc[id].temp_buffer, 8, cdb[2], block_desc); + len = scsi_disk_mode_sense(dev, dev->temp_buffer, 8, cdb[2], block_desc); if (len > alloc_length) len = alloc_length; - shdc[id].temp_buffer[0]=(len - 2) >> 8; - shdc[id].temp_buffer[1]=(len - 2) & 255; - shdc[id].temp_buffer[2] = 0; + dev->temp_buffer[0]=(len - 2) >> 8; + dev->temp_buffer[1]=(len - 2) & 255; + dev->temp_buffer[2] = 0; if (block_desc) { - shdc[id].temp_buffer[6] = 0; - shdc[id].temp_buffer[7] = 8; + dev->temp_buffer[6] = 0; + dev->temp_buffer[7] = 8; } } @@ -1180,172 +955,142 @@ scsi_hd_command(uint8_t id, uint8_t *cdb) else if (len < alloc_length) alloc_length = len; - if ((*BufLen == -1) || (alloc_length < *BufLen)) - *BufLen = alloc_length; + scsi_disk_set_buf_len(dev, BufLen, &alloc_length); - scsi_hd_log("SCSI HDD %i: Reading mode page: %02X...\n", id, cdb[2]); + DEBUG("SCSI HDD %i: Reading mode page: %02X...\n", + dev->id, cdb[2]); - scsi_hd_data_command_finish(id, len, len, alloc_length, 0); + scsi_disk_data_command_finish(dev, len, len, alloc_length, 0); return; case GPCMD_MODE_SELECT_6: case GPCMD_MODE_SELECT_10: - scsi_hd_set_phase(id, SCSI_PHASE_DATA_OUT); + scsi_disk_set_phase(dev, SCSI_PHASE_DATA_OUT); if (cdb[0] == GPCMD_MODE_SELECT_6) len = cdb[4]; else len = (cdb[7] << 8) | cdb[8]; - if ((*BufLen == -1) || (len < *BufLen)) - *BufLen = len; + scsi_disk_set_buf_len(dev, BufLen, &len); + dev->total_length = len; + dev->do_page_save = cdb[1] & 1; - shdc[id].total_length = len; - shdc[id].do_page_save = cdb[1] & 1; - - shdc[id].current_page_pos = 0; - - scsi_hd_data_command_finish(id, len, len, len, 1); + scsi_disk_data_command_finish(dev, len, len, len, 1); return; - case GPCMD_START_STOP_UNIT: - if (hdd[id].bus != HDD_BUS_SCSI_REMOVABLE) { - scsi_hd_illegal_opcode(id); - break; - } - - switch(cdb[4] & 3) { - case 0: /* Stop the disc. */ - case 1: /* Start the disc and read the TOC. */ - break; - case 2: /* Eject the disc if possible. */ - removable_disk_eject(id); - break; - case 3: /* Load the disc (close tray). */ - removable_disk_reload(id); - break; - } - - scsi_hd_set_phase(id, SCSI_PHASE_STATUS); - scsi_hd_command_complete(id); - break; - case GPCMD_INQUIRY: max_len = cdb[3]; max_len <<= 8; max_len |= cdb[4]; if ((!max_len) || (*BufLen == 0)) { - scsi_hd_set_phase(id, SCSI_PHASE_STATUS); - /* scsi_hd_log("SCSI HD %i: All done - callback set\n", id); */ - shdc[id].packet_status = CDROM_PHASE_COMPLETE; - shdc[id].callback = 20 * SCSI_TIME; + scsi_disk_set_phase(dev, SCSI_PHASE_STATUS); + + DEBUG("SCSI HD %i: All done - callback set\n", dev->id); + + dev->packet_status = CDROM_PHASE_COMPLETE; + dev->callback = 20 * SCSI_TIME; break; } - - shdc[id].temp_buffer = malloc(1024); + + dev->temp_buffer = (uint8_t *)mem_alloc(1024); if (cdb[1] & 1) { preamble_len = 4; size_idx = 3; - shdc[id].temp_buffer[idx++] = 05; - shdc[id].temp_buffer[idx++] = cdb[2]; - shdc[id].temp_buffer[idx++] = 0; + dev->temp_buffer[idx++] = 05; + dev->temp_buffer[idx++] = cdb[2]; + dev->temp_buffer[idx++] = 0; idx++; switch (cdb[2]) { case 0x00: - shdc[id].temp_buffer[idx++] = 0x00; - shdc[id].temp_buffer[idx++] = 0x83; + dev->temp_buffer[idx++] = 0x00; + dev->temp_buffer[idx++] = 0x83; break; case 0x83: if (idx + 24 > max_len) { - free(shdc[id].temp_buffer); - shdc[id].temp_buffer = NULL; - scsi_hd_data_phase_error(id); + free(dev->temp_buffer); + dev->temp_buffer = NULL; + scsi_disk_data_phase_error(dev); return; } - shdc[id].temp_buffer[idx++] = 0x02; - shdc[id].temp_buffer[idx++] = 0x00; - shdc[id].temp_buffer[idx++] = 0x00; - shdc[id].temp_buffer[idx++] = 20; - ide_padstr8(shdc[id].temp_buffer + idx, 20, "53R141"); /* Serial */ + dev->temp_buffer[idx++] = 0x02; + dev->temp_buffer[idx++] = 0x00; + dev->temp_buffer[idx++] = 0x00; + dev->temp_buffer[idx++] = 20; + ide_padstr8(dev->temp_buffer + idx, 20, "53R141"); /* Serial */ idx += 20; - if (idx + 72 > cdb[4]) { + if (idx + 72 > cdb[4]) goto atapi_out; - } - shdc[id].temp_buffer[idx++] = 0x02; - shdc[id].temp_buffer[idx++] = 0x01; - shdc[id].temp_buffer[idx++] = 0x00; - shdc[id].temp_buffer[idx++] = 68; - ide_padstr8(shdc[id].temp_buffer + idx, 8, EMU_NAME); /* Vendor */ + dev->temp_buffer[idx++] = 0x02; + dev->temp_buffer[idx++] = 0x01; + dev->temp_buffer[idx++] = 0x00; + dev->temp_buffer[idx++] = 68; + ide_padstr8(dev->temp_buffer + idx, 8, EMU_NAME); /* Vendor */ idx += 8; - ide_padstr8(shdc[id].temp_buffer + idx, 40, device_identify_ex); /* Product */ + ide_padstr8(dev->temp_buffer + idx, 40, device_identify_ex); /* Product */ idx += 40; - ide_padstr8(shdc[id].temp_buffer + idx, 20, "53R141"); /* Product */ + ide_padstr8(dev->temp_buffer + idx, 20, "53R141"); /* Product */ idx += 20; break; default: - scsi_hd_log("INQUIRY: Invalid page: %02X\n", cdb[2]); - free(shdc[id].temp_buffer); - shdc[id].temp_buffer = NULL; - scsi_hd_invalid_field(id); + DEBUG("INQUIRY: Invalid page: %02X\n", cdb[2]); + free(dev->temp_buffer); + dev->temp_buffer = NULL; + scsi_disk_invalid_field(dev); return; } } else { preamble_len = 5; size_idx = 4; - memset(shdc[id].temp_buffer, 0, 8); - shdc[id].temp_buffer[0] = 0; /*SCSI HD*/ - if (hdd[id].bus == HDD_BUS_SCSI_REMOVABLE) { - shdc[id].temp_buffer[1] = 0x80; /*Removable*/ - } else { - shdc[id].temp_buffer[1] = 0; /*Fixed*/ - } - shdc[id].temp_buffer[2] = 0x02; /*SCSI-2 compliant*/ - shdc[id].temp_buffer[3] = 0x02; - shdc[id].temp_buffer[4] = 31; - shdc[id].temp_buffer[6] = 1; /* 16-bit transfers supported */ - shdc[id].temp_buffer[7] = 0x20; /* Wide bus supported */ + memset(dev->temp_buffer, 0, 8); + dev->temp_buffer[0] = 0; /*SCSI HD*/ + dev->temp_buffer[1] = 0; /*Fixed*/ + dev->temp_buffer[2] = 0x02; /*SCSI-2 compliant*/ + dev->temp_buffer[3] = 0x02; + dev->temp_buffer[4] = 31; + dev->temp_buffer[6] = 1; /* 16-bit transfers supported */ + dev->temp_buffer[7] = 0x20; /* Wide bus supported */ - ide_padstr8(shdc[id].temp_buffer + 8, 8, EMU_NAME); /* Vendor */ - ide_padstr8(shdc[id].temp_buffer + 16, 16, device_identify); /* Product */ - ide_padstr8(shdc[id].temp_buffer + 32, 4, EMU_VERSION); /* Revision */ + ide_padstr8(dev->temp_buffer + 8, 8, EMU_NAME); /* Vendor */ + ide_padstr8(dev->temp_buffer + 16, 16, device_identify); /* Product */ + ide_padstr8(dev->temp_buffer + 32, 4, EMU_VERSION); /* Revision */ idx = 36; if (max_len == 96) { - shdc[id].temp_buffer[4] = 91; + dev->temp_buffer[4] = 91; idx = 96; } } atapi_out: - shdc[id].temp_buffer[size_idx] = idx - preamble_len; + dev->temp_buffer[size_idx] = idx - preamble_len; len=idx; - scsi_hd_log("scsi_hd_command(): Inquiry (%08X, %08X)\n", hdbufferb, shdc[id].temp_buffer); - + DEBUG("scsi_disk_command(): Inquiry (%08X, %08X)\n", hdbufferb, dev->temp_buffer); + if (len > max_len) len = max_len; - if ((*BufLen == -1) || (len < *BufLen)) - *BufLen = len; + scsi_disk_set_buf_len(dev, BufLen, &len); if (len > *BufLen) len = *BufLen; - scsi_hd_set_phase(id, SCSI_PHASE_DATA_IN); - scsi_hd_data_command_finish(id, len, len, max_len, 0); + scsi_disk_set_phase(dev, SCSI_PHASE_DATA_IN); + scsi_disk_data_command_finish(dev, len, len, max_len, 0); break; case GPCMD_PREVENT_REMOVAL: - scsi_hd_set_phase(id, SCSI_PHASE_STATUS); - scsi_hd_command_complete(id); + scsi_disk_set_phase(dev, SCSI_PHASE_STATUS); + scsi_disk_command_complete(dev); break; case GPCMD_SEEK_6: @@ -1358,115 +1103,108 @@ atapi_out: pos = (cdb[2] << 24) | (cdb[3]<<16) | (cdb[4]<<8) | cdb[5]; break; } - scsi_hd_seek(id, pos); + scsi_disk_seek(dev, pos); - scsi_hd_set_phase(id, SCSI_PHASE_STATUS); - scsi_hd_command_complete(id); + scsi_disk_set_phase(dev, SCSI_PHASE_STATUS); + scsi_disk_command_complete(dev); break; case GPCMD_READ_CDROM_CAPACITY: - shdc[id].temp_buffer = (uint8_t *) malloc(8); + dev->temp_buffer = (uint8_t *)mem_alloc(8); - if (scsi_hd_read_capacity(id, shdc[id].current_cdb, shdc[id].temp_buffer, (uint32_t *)&len) == 0) { - scsi_hd_set_phase(id, SCSI_PHASE_STATUS); + if (scsi_disk_read_capacity(dev, dev->current_cdb, dev->temp_buffer, (uint32_t *) &len) == 0) { + scsi_disk_set_phase(dev, SCSI_PHASE_STATUS); return; } - if ((*BufLen == -1) || (len < *BufLen)) - *BufLen = len; + scsi_disk_set_buf_len(dev, BufLen, &len); - scsi_hd_set_phase(id, SCSI_PHASE_DATA_IN); - scsi_hd_data_command_finish(id, len, len, len, 0); + scsi_disk_set_phase(dev, SCSI_PHASE_DATA_IN); + scsi_disk_data_command_finish(dev, len, len, len, 0); break; default: - scsi_hd_illegal_opcode(id); + scsi_disk_illegal_opcode(dev); break; } - /* scsi_hd_log("SCSI HD %i: Phase: %02X, request length: %i\n", shdc[id].phase, shdc[id].request_length); */ + DBGLOG(1, "SCSI HD %i: Phase: %02X, request length: %i\n", + dev->id, dev->phase, dev->request_length); } -void -scsi_hd_phase_data_in(uint8_t id) +static void +scsi_disk_phase_data_in(scsi_disk_t *dev) { - uint8_t *hdbufferb = SCSIDevices[hdd[id].id.scsi.id][hdd[id].id.scsi.lun].CmdBuffer; - int32_t *BufLen = &SCSIDevices[hdd[id].id.scsi.id][hdd[id].id.scsi.lun].BufferLength; + uint8_t *hdbufferb = SCSIDevices[hdd[dev->id].id.scsi.id][hdd[dev->id].id.scsi.lun].CmdBuffer; + int32_t *BufLen = &SCSIDevices[hdd[dev->id].id.scsi.id][hdd[dev->id].id.scsi.lun].BufferLength; if (!*BufLen) { - scsi_hd_log("scsi_hd_phase_data_in(): Buffer length is 0\n"); - scsi_hd_set_phase(id, SCSI_PHASE_STATUS); - ui_sb_icon_update((hdd[id].bus == HDD_BUS_SCSI_REMOVABLE) ? (SB_RDISK | id) : (SB_HDD | HDD_BUS_SCSI), 0); + DEBUG("scsi_disk_phase_data_in(): Buffer length is 0\n"); + scsi_disk_set_phase(dev, SCSI_PHASE_STATUS); return; } - switch (shdc[id].current_cdb[0]) { + switch (dev->current_cdb[0]) { case GPCMD_REQUEST_SENSE: - scsi_hd_log("SCSI HDD %i: %08X, %08X\n", id, hdbufferb, *BufLen); - scsi_hd_request_sense(id, hdbufferb, *BufLen, shdc[id].current_cdb[1] & 1); + DEBUG("SCSI HD %i: %08X, %08X\n", dev->id, hdbufferb, *BufLen); + scsi_disk_request_sense(dev, hdbufferb, *BufLen, dev->current_cdb[1] & 1); break; case GPCMD_MECHANISM_STATUS: - memset(hdbufferb, 0, *BufLen); + memset(hdbufferb, 0, *BufLen); hdbufferb[5] = 1; break; case GPCMD_READ_6: case GPCMD_READ_10: case GPCMD_READ_12: - if ((shdc[id].requested_blocks > 0) && (*BufLen > 0)) { - if (shdc[id].packet_len > (uint32_t)*BufLen) { - hdd_image_read(id, shdc[id].sector_pos, *BufLen >> 9, hdbufferb); - } else { - hdd_image_read(id, shdc[id].sector_pos, shdc[id].requested_blocks, hdbufferb); - } + if ((dev->requested_blocks > 0) && (*BufLen > 0)) { + if (dev->packet_len > (uint32_t) *BufLen) + hdd_image_read(dev->id, dev->sector_pos, *BufLen >> 9, hdbufferb); + else + hdd_image_read(dev->id, dev->sector_pos, dev->requested_blocks, hdbufferb); } break; case GPCMD_MODE_SENSE_6: case GPCMD_MODE_SENSE_10: case GPCMD_INQUIRY: case GPCMD_READ_CDROM_CAPACITY: - scsi_hd_log("scsi_hd_phase_data_in(): Filling buffer (%08X, %08X)\n", hdbufferb, shdc[id].temp_buffer); - memcpy(hdbufferb, shdc[id].temp_buffer, *BufLen); - free(shdc[id].temp_buffer); - shdc[id].temp_buffer = NULL; - scsi_hd_log("%02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n", - hdbufferb[0], hdbufferb[1], hdbufferb[2], hdbufferb[3], hdbufferb[4], hdbufferb[5], hdbufferb[6], hdbufferb[7], - hdbufferb[8], hdbufferb[9], hdbufferb[10], hdbufferb[11], hdbufferb[12], hdbufferb[13], hdbufferb[14], hdbufferb[15]); + DEBUG("scsi_disk_phase_data_in(): Filling buffer (%08X, %08X)\n", hdbufferb, dev->temp_buffer); + memcpy(hdbufferb, dev->temp_buffer, *BufLen); + free(dev->temp_buffer); + dev->temp_buffer = NULL; + DEBUG("%02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n", + hdbufferb[0], hdbufferb[1], hdbufferb[2], hdbufferb[3], hdbufferb[4], hdbufferb[5], hdbufferb[6], hdbufferb[7], + hdbufferb[8], hdbufferb[9], hdbufferb[10], hdbufferb[11], hdbufferb[12], hdbufferb[13], hdbufferb[14], hdbufferb[15]); break; default: - fatal("SCSI HDD %i: Bad Command for phase 2 (%02X)\n", shdc[id].current_cdb[0]); + fatal("SCSI HDD %i: Bad Command for phase 2 (%02X)\n", dev->current_cdb[0]); break; } - scsi_hd_set_phase(id, SCSI_PHASE_STATUS); - ui_sb_icon_update((hdd[id].bus == HDD_BUS_SCSI_REMOVABLE) ? (SB_RDISK | id) : (SB_HDD | HDD_BUS_SCSI), 0); + scsi_disk_set_phase(dev, SCSI_PHASE_STATUS); } -void -scsi_hd_phase_data_out(uint8_t id) +static void +scsi_disk_phase_data_out(scsi_disk_t *dev) { - uint8_t *hdbufferb = SCSIDevices[hdd[id].id.scsi.id][hdd[id].id.scsi.lun].CmdBuffer; - uint32_t i; - int32_t *BufLen = &SCSIDevices[hdd[id].id.scsi.id][hdd[id].id.scsi.lun].BufferLength; - uint32_t last_sector = hdd_image_get_last_sector(id); - uint32_t last_to_write = 0; - uint32_t c, h, s; - uint16_t block_desc_len; - uint16_t pos; - uint8_t error = 0; + uint8_t *hdbufferb = SCSIDevices[hdd[dev->id].id.scsi.id][hdd[dev->id].id.scsi.lun].CmdBuffer; + int i; + int32_t *BufLen = &SCSIDevices[hdd[dev->id].id.scsi.id][hdd[dev->id].id.scsi.lun].BufferLength; + uint32_t last_sector = hdd_image_get_last_sector(dev->id); + uint32_t c, h, s, last_to_write = 0; + uint16_t block_desc_len, pos; + uint8_t hdr_len, val, old_val, ch, error = 0; uint8_t page, page_len; - uint8_t hdr_len, val, old_val, ch; if (!*BufLen) { - scsi_hd_set_phase(id, SCSI_PHASE_STATUS); - ui_sb_icon_update((hdd[id].bus == HDD_BUS_SCSI_REMOVABLE) ? (SB_RDISK | id) : (SB_HDD | HDD_BUS_SCSI), 0); + scsi_disk_set_phase(dev, SCSI_PHASE_STATUS); return; } - switch (shdc[id].current_cdb[0]) { + switch (dev->current_cdb[0]) { case GPCMD_VERIFY_6: case GPCMD_VERIFY_10: case GPCMD_VERIFY_12: @@ -1476,30 +1214,29 @@ scsi_hd_phase_data_out(uint8_t id) case GPCMD_WRITE_AND_VERIFY_10: case GPCMD_WRITE_12: case GPCMD_WRITE_AND_VERIFY_12: - if ((shdc[id].requested_blocks > 0) && (*BufLen > 0)) { - if (shdc[id].packet_len > (uint32_t)*BufLen) { - hdd_image_write(id, shdc[id].sector_pos, *BufLen >> 9, hdbufferb); - } else { - hdd_image_write(id, shdc[id].sector_pos, shdc[id].requested_blocks, hdbufferb); - } + if ((dev->requested_blocks > 0) && (*BufLen > 0)) { + if (dev->packet_len > (uint32_t) *BufLen) + hdd_image_write(dev->id, dev->sector_pos, *BufLen >> 9, hdbufferb); + else + hdd_image_write(dev->id, dev->sector_pos, dev->requested_blocks, hdbufferb); } break; case GPCMD_WRITE_SAME_10: - if (!shdc[id].current_cdb[7] && !shdc[id].current_cdb[8]) + if (!dev->current_cdb[7] && !dev->current_cdb[8]) last_to_write = last_sector; else - last_to_write = shdc[id].sector_pos + shdc[id].sector_len - 1; + last_to_write = dev->sector_pos + dev->sector_len - 1; - for (i = shdc[id].sector_pos; i <= last_to_write; i++) { - if (shdc[id].current_cdb[1] & 2) { + for (i = dev->sector_pos; i <= (int) last_to_write; i++) { + if (dev->current_cdb[1] & 2) { hdbufferb[0] = (i >> 24) & 0xff; hdbufferb[1] = (i >> 16) & 0xff; hdbufferb[2] = (i >> 8) & 0xff; hdbufferb[3] = i & 0xff; - } else if (shdc[id].current_cdb[1] & 4) { - s = (i % hdd[id].spt); - h = (uint32_t)(((i - s) / hdd[id].spt) % hdd[id].hpc); - c = (uint32_t)(((i - s) / hdd[id].spt) / hdd[id].hpc); + } else if (dev->current_cdb[1] & 4) { + s = (i % hdd[dev->id].spt); + h = ((i - s) / hdd[dev->id].spt) % hdd[dev->id].hpc; + c = ((i - s) / hdd[dev->id].spt) / hdd[dev->id].hpc; hdbufferb[0] = (c >> 16) & 0xff; hdbufferb[1] = (c >> 8) & 0xff; hdbufferb[2] = c & 0xff; @@ -1509,17 +1246,17 @@ scsi_hd_phase_data_out(uint8_t id) hdbufferb[6] = (s >> 8) & 0xff; hdbufferb[7] = s & 0xff; } - hdd_image_write(id, i, 1, hdbufferb); + hdd_image_write(dev->id, i, 1, hdbufferb); } break; case GPCMD_MODE_SELECT_6: case GPCMD_MODE_SELECT_10: - if (shdc[id].current_cdb[0] == GPCMD_MODE_SELECT_10) + if (dev->current_cdb[0] == GPCMD_MODE_SELECT_10) hdr_len = 8; else hdr_len = 4; - if (shdc[id].current_cdb[0] == GPCMD_MODE_SELECT_6) { + if (dev->current_cdb[0] == GPCMD_MODE_SELECT_6) { block_desc_len = hdbufferb[2]; block_desc_len <<= 8; block_desc_len |= hdbufferb[3]; @@ -1537,16 +1274,16 @@ scsi_hd_phase_data_out(uint8_t id) pos += 2; - if (!(scsi_hd_mode_sense_page_flags & (1LL << ((uint64_t) page)))) + if (!(scsi_disk_mode_sense_page_flags & (1LL << ((uint64_t) page)))) error |= 1; else { for (i = 0; i < page_len; i++) { - ch = scsi_hd_mode_sense_pages_changeable.pages[page][i + 2]; + ch = scsi_disk_mode_sense_pages_changeable.pages[page][i + 2]; val = hdbufferb[pos + i]; - old_val = scsi_hd_mode_sense_pages_saved[id].pages[page][i + 2]; + old_val = dev->ms_pages_saved.pages[page][i + 2]; if (val != old_val) { if (ch) - scsi_hd_mode_sense_pages_saved[id].pages[page][i + 2] = val; + dev->ms_pages_saved.pages[page][i + 2] = val; else error |= 1; } @@ -1555,75 +1292,113 @@ scsi_hd_phase_data_out(uint8_t id) pos += page_len; - val = scsi_hd_mode_sense_pages_default.pages[page][0] & 0x80; - if (shdc[id].do_page_save && val) - scsi_hd_mode_sense_save(id); + val = scsi_disk_mode_sense_pages_default.pages[page][0] & 0x80; + if (dev->do_page_save && val) + scsi_disk_mode_sense_save(dev); - if (pos >= shdc[id].total_length) + if (pos >= dev->total_length) break; } if (error) - scsi_hd_invalid_field_pl(id); + scsi_disk_invalid_field_pl(dev); break; default: - fatal("SCSI HDD %i: Bad Command for phase 2 (%02X)\n", shdc[id].current_cdb[0]); + fatal("SCSI HD %i: Bad Command for phase 2 (%02X)\n", dev->id, dev->current_cdb[0]); break; } - scsi_hd_set_phase(id, SCSI_PHASE_STATUS); - ui_sb_icon_update((hdd[id].bus == HDD_BUS_SCSI_REMOVABLE) ? (SB_RDISK | id) : (SB_HDD | HDD_BUS_SCSI), 0); + scsi_disk_set_phase(dev, SCSI_PHASE_STATUS); } /* If the result is 1, issue an IRQ, otherwise not. */ void -scsi_hd_callback(uint8_t id) +scsi_disk_callback(scsi_disk_t *dev) { - switch(shdc[id].packet_status) { + switch(dev->packet_status) { case CDROM_PHASE_IDLE: - scsi_hd_log("SCSI HD %i: PHASE_IDLE\n", id); - shdc[id].pos=0; - shdc[id].phase = 1; - shdc[id].status = READY_STAT | DRQ_STAT | (shdc[id].status & ERR_STAT); + DEBUG("SCSI HD %i: PHASE_IDLE\n", dev->id); + dev->phase = 1; + dev->status = READY_STAT | DRQ_STAT | (dev->status & ERR_STAT); + hdd_active(dev->id, 0); return; case CDROM_PHASE_COMPLETE: - scsi_hd_log("SCSI HD %i: PHASE_COMPLETE\n", id); - shdc[id].status = READY_STAT; - shdc[id].phase = 3; - shdc[id].packet_status = 0xFF; - ui_sb_icon_update((hdd[id].bus == HDD_BUS_SCSI_REMOVABLE) ? (SB_RDISK | id) : (SB_HDD | HDD_BUS_SCSI), 0); - return; - case CDROM_PHASE_DATA_OUT: - scsi_hd_log("SCSI HD %i: PHASE_DATA_OUT\n", id); - shdc[id].status = READY_STAT | DRQ_STAT | (shdc[id].status & ERR_STAT); - shdc[id].phase = 0; + DEBUG("SCSI HD %i: PHASE_COMPLETE\n", dev->id); + dev->status = READY_STAT; + dev->phase = 3; + dev->packet_status = 0xFF; + hdd_active(dev->id, 0); return; case CDROM_PHASE_DATA_OUT_DMA: - scsi_hd_log("SCSI HD %i: PHASE_DATA_OUT_DMA\n", id); - scsi_hd_phase_data_out(id); - shdc[id].packet_status = CDROM_PHASE_COMPLETE; - shdc[id].status = READY_STAT; - shdc[id].phase = 3; - ui_sb_icon_update((hdd[id].bus == HDD_BUS_SCSI_REMOVABLE) ? (SB_RDISK | id) : (SB_HDD | HDD_BUS_SCSI), 0); - return; - case CDROM_PHASE_DATA_IN: - scsi_hd_log("SCSI HD %i: PHASE_DATA_IN\n", id); - shdc[id].status = READY_STAT | DRQ_STAT | (shdc[id].status & ERR_STAT); - shdc[id].phase = 2; + DEBUG("SCSI HD %i: PHASE_DATA_OUT_DMA\n", dev->id); + scsi_disk_phase_data_out(dev); + dev->packet_status = CDROM_PHASE_COMPLETE; + dev->status = READY_STAT; + dev->phase = 3; return; case CDROM_PHASE_DATA_IN_DMA: - scsi_hd_log("SCSI HD %i: PHASE_DATA_IN_DMA\n", id); - scsi_hd_phase_data_in(id); - shdc[id].packet_status = CDROM_PHASE_COMPLETE; - shdc[id].status = READY_STAT; - shdc[id].phase = 3; - ui_sb_icon_update((hdd[id].bus == HDD_BUS_SCSI_REMOVABLE) ? (SB_RDISK | id) : (SB_HDD | HDD_BUS_SCSI), 0); + DEBUG("SCSI HD %i: PHASE_DATA_IN_DMA\n", dev->id); + scsi_disk_phase_data_in(dev); + dev->packet_status = CDROM_PHASE_COMPLETE; + dev->status = READY_STAT; + dev->phase = 3; return; case CDROM_PHASE_ERROR: - scsi_hd_log("SCSI HD %i: PHASE_ERROR\n", id); - shdc[id].status = READY_STAT | ERR_STAT; - shdc[id].phase = 3; + DEBUG("SCSI HD %i: PHASE_ERROR\n", dev->id); + dev->status = READY_STAT | ERR_STAT; + dev->phase = 3; return; } } + + +/* Peform a master init on the entire module. */ +void +scsi_disk_global_init(void) +{ + /* Clear the global data. */ + memset(scsi_disk, 0x00, sizeof(scsi_disk)); +} + + +void +scsi_disk_hard_reset(void) +{ + int c; + + for (c = 0; c < HDD_NUM; c++) { + if (hdd[c].bus == HDD_BUS_SCSI) { + DEBUG("SCSI disk hard_reset drive=%d\n", c); + + if (scsi_disk[c] == NULL) { + scsi_disk[c] = (scsi_disk_t *)mem_alloc(sizeof(scsi_disk_t)); + memset(scsi_disk[c], 0, sizeof(scsi_disk_t)); + } + + scsi_disk[c]->id = c; + scsi_disk[c]->drv = &hdd[c]; + scsi_disk_mode_sense_load(scsi_disk[c]); + } + } +} + + +void +scsi_disk_close(void) +{ + scsi_disk_t *dev; + int c; + + for (c = 0; c < HDD_NUM; c++) { + dev = scsi_disk[c]; + + if (dev != NULL) { + hdd_image_close(c); + + free(scsi_disk[c]); + + scsi_disk[c] = NULL; + } + } +} diff --git a/src/devices/scsi/scsi_disk.h b/src/devices/scsi/scsi_disk.h index 8917b3d..5fee188 100644 --- a/src/devices/scsi/scsi_disk.h +++ b/src/devices/scsi/scsi_disk.h @@ -8,7 +8,7 @@ * * Emulation of SCSI fixed and removable disks. * - * Version: @(#)scsi_disk.h 1.0.2 2018/03/19 + * Version: @(#)scsi_disk.h 1.0.3 2018/09/19 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -39,62 +39,60 @@ typedef struct { - /* Stuff for SCSI hard disks. */ - uint8_t cdb[16]; - uint8_t current_cdb[16]; - uint8_t max_cdb_len; - int requested_blocks; - int max_blocks_at_once; - uint16_t request_length; - int block_total; - int all_blocks_total; - uint32_t packet_len; - int packet_status; - uint8_t status; - uint8_t phase; - uint32_t pos; - int callback; - int total_read; - int unit_attention; - uint8_t sense[256]; - uint8_t previous_command; - uint8_t error; - uint32_t sector_pos; - uint32_t sector_len; - uint32_t seek_pos; - int data_pos; - int old_len; - int request_pos; - uint8_t hd_cdb[16]; + mode_sense_pages_t ms_pages_saved; - uint64_t current_page_code; - int current_page_len; + hard_disk_t *drv; - int current_page_pos; + /* Stuff for SCSI hard disks. */ + uint8_t status, phase, + error, id, + current_cdb[16], + sense[256]; - int mode_select_phase; + uint16_t request_length; - int total_length; - int written_length; + int requested_blocks, block_total, + packet_status, callback, + block_descriptor_len, + total_length, do_page_save; - int do_page_save; - int block_descriptor_len; + uint32_t sector_pos, sector_len, + packet_len; - uint8_t *temp_buffer; + uint64_t current_page_code; + + uint8_t *temp_buffer; } scsi_disk_t; -extern scsi_disk_t shdc[HDD_NUM]; -extern FILE *shdf[HDD_NUM]; +extern scsi_disk_t *scsi_disk[HDD_NUM]; +extern uint8_t scsi_disks[16][8]; -extern void scsi_disk_insert(uint8_t id); -extern void scsi_loadhd(int scsi_id, int scsi_lun, int id); +#ifdef USE_REMOVABLE_DISK +extern void scsi_disk_insert(int id); extern void scsi_reloadhd(int id); extern void scsi_unloadhd(int scsi_id, int scsi_lun, int id); +#endif -extern int scsi_hd_read_capacity(uint8_t id, uint8_t *cdb, - uint8_t *buffer, uint32_t *len); +extern void scsi_disk_log(int level, const char *fmt, ...); +extern void scsi_disk_global_init(void); +extern void scsi_disk_hard_reset(void); +extern void scsi_disk_close(void); +extern void scsi_loadhd(int scsi_id, int scsi_lun, int id); + +extern int scsi_disk_read_capacity(scsi_disk_t *dev, uint8_t *cdb, + uint8_t *buffer, uint32_t *len); +extern int scsi_disk_err_stat_to_scsi(scsi_disk_t *dev); +extern int scsi_disk_phase_to_scsi(scsi_disk_t *dev); +extern int find_hdd_for_scsi_id(uint8_t scsi_id, uint8_t scsi_lun); +extern void build_scsi_disk_map(void); +extern void scsi_disk_reset(scsi_disk_t *dev); +extern void scsi_disk_request_sense_for_scsi(scsi_disk_t *dev, + uint8_t *buffer, + uint8_t alloc_length); +extern void scsi_disk_command(scsi_disk_t *dev, uint8_t *cdb); +extern void scsi_disk_callback(scsi_disk_t *dev); #endif /*SCSI_DISK_H*/ diff --git a/src/devices/scsi/scsi_ncr5380.c b/src/devices/scsi/scsi_ncr5380.c index 6203ce3..3a93ce9 100644 --- a/src/devices/scsi/scsi_ncr5380.c +++ b/src/devices/scsi/scsi_ncr5380.c @@ -9,7 +9,9 @@ * Implementation of the NCR 5380 series of SCSI Host Adapters * made by NCR. These controllers were designed for the ISA bus. * - * Version: @(#)scsi_ncr5380.c 1.0.7 2018/05/06 + * NOTE: This code now only supports targets at LUN=0 !! + * + * Version: @(#)scsi_ncr5380.c 1.0.8 2018/10/05 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -38,18 +40,19 @@ * Boston, MA 02111-1307 * USA. */ +#include #include #include #include #include #include +#define dbglog scsi_dev_log #include "../../emu.h" -#include "../../cpu/cpu.h" #include "../../io.h" #include "../../mem.h" #include "../../rom.h" -#include "../../nvr.h" #include "../../device.h" +#include "../../nvr.h" #include "../../timer.h" #include "../../plat.h" #include "../system/dma.h" @@ -60,12 +63,10 @@ #include "scsi_ncr5380.h" -#define ncr_log scsi_dev_log - -#define LCS6821N_ROM L"scsi/ncr5380/longshine lcs-6821n - bios version 1.04.bin" -#define RT1000B_ROM L"scsi/ncr5380/rancho_rt1000_rtbios_version_8.10r.bin" -#define T130B_ROM L"scsi/ncr5380/trantor_t130b_bios_v2.14.bin" -#define SCSIAT_ROM L"scsi/ncr5380/sumo_scsiat_bios_v6.3.bin" +#define LCS6821N_ROM L"scsi/ncr/ncr5380/longshine lcs-6821n - bios version 1.04.bin" +#define RT1000B_ROM L"scsi/ncr/ncr5380/rancho_rt1000_rtbios_version_8.10r.bin" +#define T130B_ROM L"scsi/ncr/ncr5380/trantor_t130b_bios_v2.14.bin" +#define SCSIAT_ROM L"scsi/ncr/ncr5380/sumo_scsiat_bios_v6.3.bin" #define NCR_CURDATA 0 /* current SCSI data (read only) */ @@ -82,11 +83,6 @@ #define NCR_DMAINIRECV 7 /* DMA initiator receive (write only) */ #define NCR_RESETPARITY 7 /* reset parity/interrupt (read only) */ -#define POLL_TIME_US 10LL -#define MAX_BYTES_TRANSFERRED_PER_POLL 50 -/*10us poll period with 50 bytes transferred per poll = 5MB/sec*/ - - #define ICR_DBP 0x01 #define ICR_ATN 0x02 #define ICR_SEL 0x04 @@ -102,6 +98,7 @@ #define STATUS_ACK 0x01 #define STATUS_BUSY_ERROR 0x04 +#define STATUS_PHASE_MATCH 0x08 #define STATUS_INT 0x10 #define STATUS_DRQ 0x40 #define STATUS_END_OF_DMA 0x80 @@ -112,9 +109,9 @@ #define TCR_REQ 0x08 #define TCR_LAST_BYTE_SENT 0x80 -#define CTRL_DATA_DIR (1<<6) -#define STATUS_BUFFER_NOT_READY (1<<2) -#define STATUS_53C80_ACCESSIBLE (1<<7) +#define CTRL_DATA_DIR 0x40 +#define STATUS_BUFFER_NOT_READY 0x04 +#define STATUS_53C80_ACCESSIBLE 0x80 typedef struct { @@ -125,16 +122,24 @@ typedef struct { uint8_t isr; uint8_t output_data; - int target_bsy; - int target_req; - uint8_t target_id; + uint8_t target_id, + target_lun; - uint8_t bus_status; - int dma_mode; - scsi_bus_t bus; -} ncr5380_t; + int bus_host, cur_bus, bus_in; + int new_phase; + int state; + + int clear_req, wait_data, wait_complete; + + int command_pos; + uint8_t command[20]; + int data_pos; + uint8_t tx_data; + + uint8_t unk_08, unk_08_ret; +} ncr_t; typedef struct { const char *name; @@ -144,125 +149,238 @@ typedef struct { int8_t type; rom_t bios_rom; - mem_mapping_t mapping; + mem_map_t mapping; uint8_t block_count; int block_count_loaded; uint8_t status_ctrl; - uint8_t buffer[0x80]; + uint8_t buffer[128]; int buffer_pos; int buffer_host_pos; uint8_t int_ram[0x40]; uint8_t ext_ram[0x600]; - ncr5380_t ncr; - int ncr5380_dma_enabled; - - int64_t dma_timer; - int64_t dma_enabled; - + ncr_t ncr; int ncr_busy; -} ncr_t; + + int is_non_data_mode; + + int dma_enabled; + + int64_t timer_period; + int64_t timer_enabled; + + int64_t media_period, + temp_period; + double period; +} ncr5380_t; -enum { - DMA_IDLE = 0, - DMA_SEND, - DMA_TARGET_RECEIVE, - DMA_INITIATOR_RECEIVE -}; +#define STATE_IDLE 0 +#define STATE_COMMAND 1 +#define STATE_DATAIN 2 +#define STATE_DATAOUT 3 +#define STATE_STATUS 4 +#define STATE_MESSAGEIN 5 +#define STATE_SELECT 6 + +#define DMA_IDLE 0 +#define DMA_SEND 1 +#define DMA_INITIATOR_RECEIVE 2 + +#define SET_BUS_STATE(ncr, state) \ + ncr->cur_bus = (ncr->cur_bus & ~(SCSI_PHASE_MESSAGE_IN)) | \ + (state & (SCSI_PHASE_MESSAGE_IN)) -static void -dma_changed(void *priv, int mode, int enable) +static void ncr_callback(void *priv); + + +static int +get_dev_id(uint8_t data) { - ncr_t *scsi = (ncr_t *)priv; + int c; - scsi->ncr5380_dma_enabled = (mode && enable); + for (c = 0; c < SCSI_ID_MAX; c++) { + if (data & (1 << c)) return(c); + } - scsi->dma_enabled = (scsi->ncr5380_dma_enabled && scsi->block_count_loaded); + return(-1); } -void -ncr5380_reset(ncr5380_t *ncr) +/* get the length of a SCSI command based on its command byte type */ +static int +get_cmd_len(int cbyte) { - memset(ncr, 0x00, sizeof(ncr5380_t)); + int len; + int group; + + group = (cbyte>>5) & 7; + + if (group == 0) len = 6; + if (group == 1 || group == 2) len = 10; + + return(len); +} + + +static void +ncr_reset(ncr_t *ncr) +{ + memset(ncr, 0x00, sizeof(ncr_t)); + DEBUG("NCR reset\n"); } static uint32_t -get_bus_host(ncr5380_t *ncr) +get_bus_host(ncr_t *ncr) { uint32_t bus_host = 0; - if (ncr->icr & ICR_DBP) + if (ncr->icr & ICR_DBP) { + DEBUG("Data bus phase\n"); bus_host |= BUS_DBP; - if (ncr->icr & ICR_SEL) + } + if (ncr->icr & ICR_SEL) { + DEBUG("Selection phase\n"); bus_host |= BUS_SEL; - if (ncr->icr & ICR_ATN) - bus_host |= BUS_ATN; - if (ncr->tcr & TCR_IO) + } + if (ncr->tcr & TCR_IO) { + DEBUG("Data phase\n"); bus_host |= BUS_IO; - if (ncr->tcr & TCR_CD) + } + if (ncr->tcr & TCR_CD) { + DEBUG("Command phase\n"); bus_host |= BUS_CD; - if (ncr->tcr & TCR_MSG) + } + if (ncr->tcr & TCR_MSG) { + DEBUG("Message phase\n"); bus_host |= BUS_MSG; - if (ncr->tcr & TCR_REQ) + } + if (ncr->tcr & TCR_REQ) { + DEBUG("Request phase\n"); bus_host |= BUS_REQ; - if (ncr->icr & ICR_BSY) + } + if (ncr->icr & ICR_BSY) { + DEBUG("Busy phase\n"); bus_host |= BUS_BSY; - if (ncr->icr & ICR_ACK) + } + if (ncr->icr & ICR_ATN) { + bus_host |= BUS_ATN; + } + if (ncr->icr & ICR_ACK) { + DEBUG("ACK phase\n"); bus_host |= BUS_ACK; - if (ncr->mode & MODE_ARBITRATE) + } + if (ncr->mode & MODE_ARBITRATE) { bus_host |= BUS_ARB; + } return(bus_host | BUS_SETDATA(ncr->output_data)); } +static void +ncr_wait_process(ncr5380_t *ncr_dev) +{ + ncr_t *ncr = &ncr_dev->ncr; + scsi_device_t *dev; + + /*Wait processes to handle bus requests*/ + DEBUG("Clear REQ=%d\n", ncr->clear_req); + if (ncr->clear_req) { + ncr->clear_req--; + if (!ncr->clear_req) { + DEBUG("Prelude to command data\n"); + SET_BUS_STATE(ncr, ncr->new_phase); + ncr->cur_bus |= BUS_REQ; + } + } + + if (ncr->wait_data) { + ncr->wait_data--; + + if (!ncr->wait_data) { + dev = &SCSIDevices[ncr->target_id][ncr->target_lun]; + SET_BUS_STATE(ncr, ncr->new_phase); + + if (ncr->new_phase == SCSI_PHASE_DATA_IN) { + DEBUG("Data In bus phase\n"); + ncr->tx_data = dev->CmdBuffer[ncr->data_pos++]; + ncr->state = STATE_DATAIN; + ncr->cur_bus = (ncr->cur_bus & ~BUS_DATAMASK) | BUS_SETDATA(ncr->tx_data) | BUS_DBP; + } else if (ncr->new_phase == SCSI_PHASE_STATUS) { + DEBUG("Status bus phase\n"); + ncr->cur_bus |= BUS_REQ; + ncr->state = STATE_STATUS; + ncr->cur_bus = (ncr->cur_bus & ~BUS_DATAMASK) | BUS_SETDATA(dev->Status) | BUS_DBP; + } else if (ncr->new_phase == SCSI_PHASE_MESSAGE_IN) { + DEBUG("Message In bus phase\n"); + ncr->state = STATE_MESSAGEIN; + ncr->cur_bus = (ncr->cur_bus & ~BUS_DATAMASK) | BUS_SETDATA(0) | BUS_DBP; + } else { + if (ncr->new_phase & BUS_IDLE) { + DEBUG("Bus Idle phase\n"); + ncr->state = STATE_IDLE; + ncr->cur_bus &= ~BUS_BSY; + ncr_dev->media_period = 0LL; + ncr_dev->temp_period = 0LL; + } else { + ncr->state = STATE_DATAOUT; + DEBUG("Data Out bus phase\n"); + } + } + } + } + + if (ncr->wait_complete) { + ncr->wait_complete--; + if (!ncr->wait_complete) { + ncr->cur_bus |= BUS_REQ; + } + } + + ncr->bus_host = ncr->cur_bus; +} + + static void ncr_write(uint16_t port, uint8_t val, void *priv) { - ncr_t *scsi = (ncr_t *)priv; - ncr5380_t *ncr = &scsi->ncr; - int bus_host = 0; + ncr5380_t *ncr_dev = (ncr5380_t *)priv; + ncr_t *ncr = &ncr_dev->ncr; + + DBGLOG(2, "NCR5380 write(%04x,%02x)\n", port & 7, val); -#ifdef ENABLE_SCSI_DEV_LOG - ncr_log("NCR5380 write(%04x,%02x) @%04X:%04X\n",port,val,CS,cpu_state.pc); -#endif switch (port & 7) { case 0: /* Output data register */ + DEBUG("Write: Output data register\n"); ncr->output_data = val; break; case 1: /* Initiator Command Register */ - if ((val & (ICR_BSY | ICR_SEL)) == (ICR_BSY | ICR_SEL) && - (ncr->icr & (ICR_BSY | ICR_SEL)) == ICR_SEL) { - uint8_t temp = ncr->output_data & 0x7f; - - ncr->target_id = -1; - while (temp) { - temp >>= 1; - ncr->target_id++; - } - - ncr_log("Select - target ID = %i, temp data %x\n", ncr->target_id, temp); - } + DEBUG("Write: Initiator command register\n"); ncr->icr = val; + + ncr_dev->timer_enabled = 1; break; case 2: /* Mode register */ + DEBUG("Write: Mode register, val=%02x\n", val & MODE_DMA); if ((val & MODE_ARBITRATE) && !(ncr->mode & MODE_ARBITRATE)) { ncr->icr &= ~ICR_ARB_LOST; ncr->icr |= ICR_ARB_IN_PROGRESS; } + ncr->mode = val; - dma_changed(scsi, ncr->dma_mode, ncr->mode & MODE_DMA); - if (! (ncr->mode & MODE_DMA)) { + + /*If it's not DMA mode, don't do anything*/ + if (!(ncr->mode & MODE_DMA)) { + DEBUG("No DMA mode\n"); ncr->tcr &= ~TCR_LAST_BYTE_SENT; ncr->isr &= ~STATUS_END_OF_DMA; ncr->dma_mode = DMA_IDLE; @@ -270,302 +388,201 @@ ncr_write(uint16_t port, uint8_t val, void *priv) break; case 3: /* Target Command Register */ + DEBUG("Write: Target Command register\n"); ncr->tcr = val; break; case 4: /* Select Enable Register */ - ncr->ser = val; + DEBUG("Write: Select Enable register\n"); break; - + case 5: /* start DMA Send */ + DEBUG("Write: start DMA send register\n"); + DEBUG("Write 6 or 10, block count loaded=%d\n", ncr_dev->block_count_loaded); + /*a Write 6/10 has occurred, start the timer when the block count is loaded*/ ncr->dma_mode = DMA_SEND; - dma_changed(scsi, ncr->dma_mode, ncr->mode & MODE_DMA); break; case 7: /* start DMA Initiator Receive */ + DEBUG("Write: start DMA initiator receive register\n"); + DEBUG("Read 6 or 10, block count loaded=%d\n", ncr_dev->block_count_loaded); + /*a Read 6/10 has occurred, start the timer when the block count is loaded*/ ncr->dma_mode = DMA_INITIATOR_RECEIVE; - dma_changed(scsi, ncr->dma_mode, ncr->mode & MODE_DMA); break; default: -#if 1 - pclog("NCR5380: bad write %04x %02x\n", port, val); -#endif + DEBUG("NCR5380: bad write %04x %02x\n", port, val); break; } - - bus_host = get_bus_host(ncr); - - scsi_bus_update(&ncr->bus, bus_host); } static uint8_t ncr_read(uint16_t port, void *priv) { - ncr_t *scsi = (ncr_t *)priv; - ncr5380_t *ncr = &scsi->ncr; - uint32_t bus = 0; + ncr5380_t *ncr_dev = (ncr5380_t *)priv; + ncr_t *ncr = &ncr_dev->ncr; uint8_t ret = 0xff; switch (port & 7) { - case 0: /* current SCSI data */ + case 0: /* Current SCSI data */ + DEBUG("Read: Current SCSI data register\n"); if (ncr->icr & ICR_DBP) { + /*Return the data from the output register if on data bus phase from ICR*/ + DEBUG("Data Bus Phase\n"); ret = ncr->output_data; - } else { - bus = scsi_bus_read(&ncr->bus); - ret = BUS_GETDATA(bus); + } else { + /*Return the data from the SCSI bus*/ + ncr_wait_process(ncr_dev); + DEBUG("NCR GetData=%02x\n", BUS_GETDATA(ncr->bus_host)); + ret = BUS_GETDATA(ncr->bus_host); } break; case 1: /* Initiator Command Register */ + DEBUG("Read: Initiator Command register\n"); + DEBUG("NCR ICR Read=%02x\n", ncr->icr); + ret = ncr->icr; break; case 2: /* Mode register */ + DEBUG("Read: Mode register\n"); ret = ncr->mode; break; case 3: /* Target Command Register */ + DEBUG("Read: Target Command register\n"); + DEBUG("NCR target stat=%02x\n", ncr->tcr); ret = ncr->tcr; break; case 4: /* Current SCSI Bus status */ + DEBUG("Read: SCSI bus status register\n"); ret = 0; - bus = scsi_bus_read(&ncr->bus); - ret |= (bus & 0xff); + ncr_wait_process(ncr_dev); + DEBUG("NCR cur bus stat=%02x\n", ncr->bus_host & 0xff); + ret |= (ncr->bus_host & 0xff); break; case 5: /* Bus and Status register */ - ret = 0; + DEBUG("Read: Bus and Status register\n"); + ret = 0; - bus = get_bus_host(ncr); - if (scsi_bus_match(&ncr->bus, bus)) - ret |= 0x08; - bus = scsi_bus_read(&ncr->bus); + ncr->bus_host = get_bus_host(ncr); + DEBUG("Get host from Interrupt\n"); + + /*Check if the phase in process matches with TCR's*/ + if ((ncr->bus_host & SCSI_PHASE_MESSAGE_IN) == + (ncr->cur_bus & SCSI_PHASE_MESSAGE_IN)) { + DEBUG("Phase match\n"); + ret |= STATUS_PHASE_MATCH; + } else + picint(1 << ncr_dev->irq); - if (bus & BUS_ACK) + ncr_wait_process(ncr_dev); + + if (ncr->bus_host & BUS_ACK) ret |= STATUS_ACK; - if ((bus & BUS_REQ) && (ncr->mode & MODE_DMA)) + + if ((ncr->bus_host & BUS_REQ) && (ncr->mode & MODE_DMA)) { + DEBUG("Entering DMA mode\n"); ret |= STATUS_DRQ; - if ((bus & BUS_REQ) && (ncr->mode & MODE_DMA)) { - int bus_state = 0; - - if (bus & BUS_IO) - bus_state |= TCR_IO; - if (bus & BUS_CD) - bus_state |= TCR_CD; - if (bus & BUS_MSG) - bus_state |= TCR_MSG; - if ((ncr->tcr & 7) != bus_state) + + int bus = 0; + + if (ncr->bus_host & BUS_IO) + bus |= TCR_IO; + if (ncr->bus_host & BUS_CD) + bus |= TCR_CD; + if (ncr->bus_host & BUS_MSG) + bus |= TCR_MSG; + if ((ncr->tcr & 7) != bus) { ncr->isr |= STATUS_INT; + } + } + if (!(ncr->bus_host & BUS_BSY) && (ncr->mode & MODE_MONITOR_BUSY)) { + DEBUG("Busy error\n"); + ret |= STATUS_BUSY_ERROR; } - if (!(bus & BUS_BSY) && (ncr->mode & MODE_MONITOR_BUSY)) - ret |= STATUS_BUSY_ERROR; ret |= (ncr->isr & (STATUS_INT | STATUS_END_OF_DMA)); break; case 7: /* reset Parity/Interrupt */ ncr->isr &= ~STATUS_INT; + picintc(1 << ncr_dev->irq); + DEBUG("Reset IRQ\n"); break; default: - ncr_log("NCR5380: bad read %04x\n", port); + DEBUG("NCR5380: bad read %04x\n", port); break; } -#ifdef ENABLE_SCSI_DEV_LOG - ncr_log("NCR5380 read(%04x)=%02x @%04X:%04X\n", port, ret, CS,cpu_state.pc); -#endif + DEBUG("NCR5380 read(%04x)=%02x\n", port & 7, ret); + return(ret); } -static void -dma_callback(void *priv) -{ - ncr_t *scsi = (ncr_t *)priv; - ncr5380_t *ncr = &scsi->ncr; - int bytes_transferred = 0; - int c; - - scsi->dma_timer += POLL_TIME_US * TIMER_USEC; - - switch (scsi->ncr.dma_mode) { - case DMA_SEND: - if (scsi->status_ctrl & CTRL_DATA_DIR) { - ncr_log("DMA_SEND with DMA direction set wrong\n"); - break; - } - - if (!(scsi->status_ctrl & STATUS_BUFFER_NOT_READY)) { - break; - } - - if (! scsi->block_count_loaded) break; - - while (bytes_transferred < MAX_BYTES_TRANSFERRED_PER_POLL) { - int bus; - uint8_t data; - - for (c = 0; c < 10; c++) { - uint8_t status = scsi_bus_read(&ncr->bus); - - if (status & BUS_REQ) break; - } - if (c == 10) break; - - /* Data ready. */ - data = scsi->buffer[scsi->buffer_pos]; - bus = get_bus_host(ncr) & ~BUS_DATAMASK; - bus |= BUS_SETDATA(data); - - scsi_bus_update(&ncr->bus, bus | BUS_ACK); - scsi_bus_update(&ncr->bus, bus & ~BUS_ACK); - - bytes_transferred++; - if (++scsi->buffer_pos == 128) { - scsi->buffer_pos = 0; - scsi->buffer_host_pos = 0; - scsi->status_ctrl &= ~STATUS_BUFFER_NOT_READY; - scsi->block_count = (scsi->block_count - 1) & 255; - scsi->ncr_busy = 0; - if (! scsi->block_count) { - scsi->block_count_loaded = 0; - scsi->dma_enabled = 0; - - ncr->tcr |= TCR_LAST_BYTE_SENT; - ncr->isr |= STATUS_END_OF_DMA; - if (ncr->mode & MODE_ENA_EOP_INT) - ncr->isr |= STATUS_INT; - } - break; - } - } - break; - - case DMA_INITIATOR_RECEIVE: - if (!(scsi->status_ctrl & CTRL_DATA_DIR)) { - ncr_log("DMA_INITIATOR_RECEIVE with DMA direction set wrong\n"); - break; - } - - if (!(scsi->status_ctrl & STATUS_BUFFER_NOT_READY)) break; - - if (!scsi->block_count_loaded) break; - - while (bytes_transferred < MAX_BYTES_TRANSFERRED_PER_POLL) { - int bus; - uint8_t temp; - - for (c = 0; c < 10; c++) { - uint8_t status = scsi_bus_read(&ncr->bus); - - if (status & BUS_REQ) break; - } - if (c == 10) break; - - /* Data ready. */ - bus = scsi_bus_read(&ncr->bus); - temp = BUS_GETDATA(bus); - bus = get_bus_host(ncr); - - scsi_bus_update(&ncr->bus, bus | BUS_ACK); - scsi_bus_update(&ncr->bus, bus & ~BUS_ACK); - - bytes_transferred++; - scsi->buffer[scsi->buffer_pos++] = temp; - if (scsi->buffer_pos == 128) { - scsi->buffer_pos = 0; - scsi->buffer_host_pos = 0; - scsi->status_ctrl &= ~STATUS_BUFFER_NOT_READY; - scsi->block_count = (scsi->block_count - 1) & 255; - if (!scsi->block_count) { - scsi->block_count_loaded = 0; - scsi->dma_enabled = 0; - - ncr->isr |= STATUS_END_OF_DMA; - if (ncr->mode & MODE_ENA_EOP_INT) - ncr->isr |= STATUS_INT; - } - break; - } - } - break; - - default: -#if 1 - pclog("DMA callback bad mode %i\n", scsi->ncr.dma_mode); -#endif - break; - } - - c = scsi_bus_read(&ncr->bus); - if (!(c & BUS_BSY) && (ncr->mode & MODE_MONITOR_BUSY)) { - ncr->mode &= ~MODE_DMA; - ncr->dma_mode = DMA_IDLE; - dma_changed(scsi, ncr->dma_mode, ncr->mode & MODE_DMA); - } -} - - /* Memory-mapped I/O READ handler. */ static uint8_t memio_read(uint32_t addr, void *priv) { - ncr_t *scsi = (ncr_t *)priv; + ncr5380_t *ncr_dev = (ncr5380_t *)priv; uint8_t ret = 0xff; - + addr &= 0x3fff; -#ifdef ENABLE_SCSI_DEV_LOG - ncr_log("memio_read %08x\n", addr); -#endif + DBGLOG(2, "memio_read %08x\n", addr); if (addr < 0x2000) - ret = scsi->bios_rom.rom[addr & 0x1fff]; + ret = ncr_dev->bios_rom.rom[addr & 0x1fff]; else if (addr < 0x3800) ret = 0xff; else if (addr >= 0x3a00) - ret = scsi->ext_ram[addr - 0x3a00]; + ret = ncr_dev->ext_ram[addr - 0x3a00]; else switch (addr & 0x3f80) { case 0x3800: -#ifdef ENABLE_SCSI_DEV_LOG - ncr_log("Read intRAM %02x %02x\n", addr & 0x3f, scsi->int_ram[addr & 0x3f]); -#endif - ret = scsi->int_ram[addr & 0x3f]; + DBGLOG(1, "Read intRAM %02x %02x\n", addr & 0x3f, ncr_dev->int_ram[addr & 0x3f]); + ret = ncr_dev->int_ram[addr & 0x3f]; break; case 0x3880: -#ifdef ENABLE_SCSI_DEV_LOG - ncr_log("Read 53c80 %04x\n", addr); -#endif - ret = ncr_read(addr, scsi); + DBGLOG(1, "Read 53c80 %04x\n", addr); + ret = ncr_read(addr, ncr_dev); break; - + case 0x3900: -#ifdef ENABLE_SCSI_DEV_LOG - ncr_log(" Read 3900 %i %02x\n", scsi->buffer_host_pos, scsi->status_ctrl); -#endif - if (scsi->buffer_host_pos >= 128 || !(scsi->status_ctrl & CTRL_DATA_DIR)) + DBGLOG(1, "Read 3900 host pos %i status ctrl %02x\n", ncr_dev->buffer_host_pos, ncr_dev->status_ctrl); + DEBUG("Read port 0x3900-0x397f\n"); + + if (ncr_dev->buffer_host_pos >= 128 || !(ncr_dev->status_ctrl & CTRL_DATA_DIR)) ret = 0xff; else { - ret = scsi->buffer[scsi->buffer_host_pos++]; + ret = ncr_dev->buffer[ncr_dev->buffer_host_pos++]; + + DEBUG("Read host buffer=%d\n", ncr_dev->buffer_host_pos); - if (scsi->buffer_host_pos == 128) - scsi->status_ctrl |= STATUS_BUFFER_NOT_READY; + if (ncr_dev->buffer_host_pos == 128) + { + DEBUG("Not ready\n"); + ncr_dev->status_ctrl |= STATUS_BUFFER_NOT_READY; + } } break; case 0x3980: switch (addr) { case 0x3980: /* status */ - ret = scsi->status_ctrl;// | 0x80; - if (! scsi->ncr_busy) + ret = ncr_dev->status_ctrl;// | 0x80; + DEBUG("NCR status ctrl read=%02x\n", ncr_dev->status_ctrl & STATUS_BUFFER_NOT_READY); + if (!ncr_dev->ncr_busy) { ret |= STATUS_53C80_ACCESSIBLE; + } break; case 0x3981: /* block counter register*/ - ret = scsi->block_count; + ret = ncr_dev->block_count; break; case 0x3982: /* switch register read */ @@ -576,13 +593,12 @@ memio_read(uint32_t addr, void *priv) ret = 0xff; break; } - break; + break; } -#ifdef ENABLE_SCSI_DEV_LOG - if (addr >= 0x3880) - ncr_log("memio_read(%08x)=%02x\n", addr, ret); -#endif + if (addr >= 0x3880) { + DBGLOG(2, "memio_read(%08x)=%02x\n", addr, ret); + } return(ret); } @@ -592,37 +608,33 @@ memio_read(uint32_t addr, void *priv) static void memio_write(uint32_t addr, uint8_t val, void *priv) { - ncr_t *scsi = (ncr_t *)priv; - + ncr5380_t *ncr_dev = (ncr5380_t *)priv; + addr &= 0x3fff; -#ifdef ENABLE_SCSI_DEV_LOG - ncr_log("memio_write(%08x,%02x) @%04X:%04X %i %02x\n", addr, val, CS,cpu_state.pc, scsi->buffer_host_pos, scsi->status_ctrl); -#endif + DBGLOG(2, "memio_write(%08x,%02x) %i %02x\n", addr, val, ncr_dev->buffer_host_pos, ncr_dev->status_ctrl); + if (addr >= 0x3a00) - scsi->ext_ram[addr - 0x3a00] = val; + ncr_dev->ext_ram[addr - 0x3a00] = val; else switch (addr & 0x3f80) { case 0x3800: -#if 0 - ncr_log("Write intram %02x %02x\n", addr & 0x3f, val); -#endif - scsi->int_ram[addr & 0x3f] = val; + DBGLOG(1, "Write intram %02x %02x\n", addr & 0x3f, val); + ncr_dev->int_ram[addr & 0x3f] = val; break; case 0x3880: -#ifdef ENABLE_SCSI_DEV_LOG - ncr_log("Write 53c80 %04x %02x\n", addr, val); -#endif - ncr_write(addr, val, scsi); + DBGLOG(1, "Write 53c80 %04x %02x\n", addr, val); + ncr_write(addr, val, ncr_dev); break; - + case 0x3900: - if (!(scsi->status_ctrl & CTRL_DATA_DIR) && scsi->buffer_host_pos < 128) { - scsi->buffer[scsi->buffer_host_pos++] = val; - if (scsi->buffer_host_pos == 128) { - scsi->status_ctrl |= STATUS_BUFFER_NOT_READY; - scsi->ncr_busy = 1; + if (!(ncr_dev->status_ctrl & CTRL_DATA_DIR) && ncr_dev->buffer_host_pos < 128) { + ncr_dev->buffer[ncr_dev->buffer_host_pos++] = val; + + if (ncr_dev->buffer_host_pos == 128) { + ncr_dev->status_ctrl |= STATUS_BUFFER_NOT_READY; + ncr_dev->ncr_busy = 1; } } break; @@ -630,31 +642,44 @@ memio_write(uint32_t addr, uint8_t val, void *priv) case 0x3980: switch (addr) { case 0x3980: /* Control */ - if ((val & CTRL_DATA_DIR) && !(scsi->status_ctrl & CTRL_DATA_DIR)) { - scsi->buffer_host_pos = 128; - scsi->status_ctrl |= STATUS_BUFFER_NOT_READY; + DEBUG("Write 0x3980: val=%02x\n", val); + if (val & 0x80) { + DEBUG("Resetting the 53c400\n"); + picint(1 << ncr_dev->irq); } - else if (!(val & CTRL_DATA_DIR) && (scsi->status_ctrl & CTRL_DATA_DIR)) { - scsi->buffer_host_pos = 0; - scsi->status_ctrl &= ~STATUS_BUFFER_NOT_READY; + + if ((val & CTRL_DATA_DIR) && !(ncr_dev->status_ctrl & CTRL_DATA_DIR)) { + DEBUG("Pos 128\n"); + ncr_dev->buffer_host_pos = 128; + ncr_dev->status_ctrl |= STATUS_BUFFER_NOT_READY; } - scsi->status_ctrl = (scsi->status_ctrl & 0x87) | (val & 0x78); + else if (!(val & CTRL_DATA_DIR) && (ncr_dev->status_ctrl & CTRL_DATA_DIR)) { + DEBUG("Pos 0\n"); + ncr_dev->buffer_host_pos = 0; + ncr_dev->status_ctrl &= ~STATUS_BUFFER_NOT_READY; + } + ncr_dev->status_ctrl = (ncr_dev->status_ctrl & 0x87) | (val & 0x78); break; case 0x3981: /* block counter register */ - scsi->block_count = val; - scsi->block_count_loaded = 1; - scsi->dma_enabled = (scsi->ncr5380_dma_enabled && scsi->block_count_loaded); - if (scsi->status_ctrl & CTRL_DATA_DIR) { - scsi->buffer_host_pos = 128; - scsi->status_ctrl |= STATUS_BUFFER_NOT_READY; + DEBUG("Write 0x3981: val=%d\n", val); + ncr_dev->block_count = val; + ncr_dev->block_count_loaded = 1; + + DEBUG("Timer for transfers=%02x\n", ncr_dev->timer_enabled); + + if (ncr_dev->status_ctrl & CTRL_DATA_DIR) { + DEBUG("Data Read\n"); + ncr_dev->buffer_host_pos = 128; + ncr_dev->status_ctrl |= STATUS_BUFFER_NOT_READY; } else { - scsi->buffer_host_pos = 0; - scsi->status_ctrl &= ~STATUS_BUFFER_NOT_READY; + DEBUG("Data Write\n"); + ncr_dev->buffer_host_pos = 0; + ncr_dev->status_ctrl &= ~STATUS_BUFFER_NOT_READY; } break; } - break; + break; } } @@ -663,15 +688,15 @@ memio_write(uint32_t addr, uint8_t val, void *priv) static uint8_t t130b_read(uint32_t addr, void *priv) { - ncr_t *scsi = (ncr_t *)priv; + ncr5380_t *ncr_dev = (ncr5380_t *)priv; uint8_t ret = 0xff; addr &= 0x3fff; if (addr < 0x1800) - ret = scsi->bios_rom.rom[addr & 0x1fff]; + ret = ncr_dev->bios_rom.rom[addr & 0x1fff]; else if (addr < 0x1880) - ret = scsi->ext_ram[addr & 0x7f]; + ret = ncr_dev->ext_ram[addr & 0x7f]; return(ret); } @@ -681,18 +706,18 @@ t130b_read(uint32_t addr, void *priv) static void t130b_write(uint32_t addr, uint8_t val, void *priv) { - ncr_t *scsi = (ncr_t *)priv; + ncr5380_t *ncr_dev = (ncr5380_t *)priv; addr &= 0x3fff; if (addr >= 0x1800 && addr < 0x1880) - scsi->ext_ram[addr & 0x7f] = val; + ncr_dev->ext_ram[addr & 0x7f] = val; } static uint8_t t130b_in(uint16_t port, void *priv) { - ncr_t *scsi = (ncr_t *)priv; + ncr5380_t *ncr_dev = (ncr5380_t *)priv; uint8_t ret = 0xff; switch (port & 0x0f) { @@ -700,14 +725,14 @@ t130b_in(uint16_t port, void *priv) case 0x01: case 0x02: case 0x03: - ret = memio_read((port & 7) | 0x3980, scsi); + ret = memio_read((port & 7) | 0x3980, ncr_dev); break; case 0x04: case 0x05: - ret = memio_read(0x3900, scsi); - break; - + ret = memio_read(0x3900, ncr_dev); + break; + case 0x08: case 0x09: case 0x0a: @@ -716,7 +741,7 @@ t130b_in(uint16_t port, void *priv) case 0x0d: case 0x0e: case 0x0f: - ret = ncr_read(port, scsi); + ret = ncr_read(port, ncr_dev); break; } @@ -727,21 +752,21 @@ t130b_in(uint16_t port, void *priv) static void t130b_out(uint16_t port, uint8_t val, void *priv) { - ncr_t *scsi = (ncr_t *)priv; + ncr5380_t *ncr_dev = (ncr5380_t *)priv; switch (port & 0x0f) { case 0x00: case 0x01: case 0x02: case 0x03: - memio_write((port & 7) | 0x3980, val, scsi); + memio_write((port & 7) | 0x3980, val, ncr_dev); break; case 0x04: case 0x05: - memio_write(0x3900, val, scsi); - break; - + memio_write(0x3900, val, ncr_dev); + break; + case 0x08: case 0x09: case 0x0a: @@ -750,7 +775,7 @@ t130b_out(uint16_t port, uint8_t val, void *priv) case 0x0d: case 0x0e: case 0x0f: - ncr_write(port, val, scsi); + ncr_write(port, val, ncr_dev); break; } } @@ -759,7 +784,7 @@ t130b_out(uint16_t port, uint8_t val, void *priv) static uint8_t scsiat_in(uint16_t port, void *priv) { - ncr_t *scsi = (ncr_t *)priv; + ncr5380_t *ncr_dev = (ncr5380_t *)priv; uint8_t ret = 0xff; switch (port & 0x0f) { @@ -767,26 +792,16 @@ scsiat_in(uint16_t port, void *priv) case 0x01: case 0x02: case 0x03: - ret = memio_read((port & 7) | 0x3980, scsi); - break; - case 0x04: case 0x05: - ret = memio_read(0x3900, scsi); - break; - - case 0x08: - case 0x09: - case 0x0a: - case 0x0b: - case 0x0c: - case 0x0d: - case 0x0e: - case 0x0f: - ret = ncr_read(port, scsi); + case 0x06: + case 0x07: + ret = ncr_read(port, ncr_dev); break; } + DBGLOG(2, "SCSI-AT read=0x%03x, ret=%02x\n", port, ret); + return(ret); } @@ -794,31 +809,514 @@ scsiat_in(uint16_t port, void *priv) static void scsiat_out(uint16_t port, uint8_t val, void *priv) { - ncr_t *scsi = (ncr_t *)priv; + ncr5380_t *ncr_dev = (ncr5380_t *)priv; + ncr_t *ncr = &ncr_dev->ncr; + scsi_device_t *dev = &SCSIDevices[ncr->target_id][ncr->target_lun]; + + DBGLOG(2, "SCSI-AT write=0x%03x, val=%02x\n", port, val); switch (port & 0x0f) { + case 0x08: + ncr->unk_08 = val; + + if (ncr->unk_08 & 0x08) { + if (ncr->dma_mode == DMA_INITIATOR_RECEIVE) { + while (ncr_dev->buffer_host_pos < 128) { + uint8_t temp; + + temp = ncr_dev->buffer[ncr_dev->buffer_host_pos++]; + + DBGLOG(1, "Read Buffer host=%d\n", ncr_dev->buffer_host_pos); + + ncr->bus_host = get_bus_host(ncr) & ~BUS_DATAMASK; + ncr->bus_host |= BUS_SETDATA(temp); + + if (ncr_dev->buffer_host_pos == 128) + break; + } + } else if (ncr->dma_mode == DMA_SEND) { + while (ncr_dev->buffer_host_pos < 128) { + /* Data ready. */ + uint8_t temp; + + ncr_wait_process(ncr_dev); + temp = BUS_GETDATA(ncr->bus_host); + ncr->bus_host = get_bus_host(ncr); + + ncr_dev->buffer[ncr_dev->buffer_host_pos++] = temp; + + DBGLOG(1, "Write Buffer host=%d\n", ncr_dev->buffer_host_pos); + + if (ncr_dev->buffer_host_pos == 128) { + + break; + } + } + } + } + + if (ncr->unk_08 & 0x01) { + ncr_dev->block_count_loaded = 1; + ncr_dev->block_count = dev->BufferLength / 128; + } + break; + case 0x00: case 0x01: case 0x02: case 0x03: - memio_write((port & 7) | 0x3980, val, scsi); - break; - case 0x04: case 0x05: - memio_write(0x3900, val, scsi); + case 0x06: + case 0x07: + ncr_write(port, val, ncr_dev); break; + } +} - case 0x08: - case 0x09: - case 0x0a: - case 0x0b: - case 0x0c: - case 0x0d: - case 0x0e: - case 0x0f: - ncr_write(port, val, scsi); - break; + +static void +ncr_callback(void *priv) +{ + ncr5380_t *ncr_dev = (ncr5380_t *)priv; + ncr_t *ncr = &ncr_dev->ncr; + scsi_device_t *dev = &SCSIDevices[ncr->target_id][ncr->target_lun]; + int c = 0; + + DEBUG("DMA mode=%d\n", ncr->dma_mode); + + ncr_dev->timer_enabled = 0; + if (((ncr->state == STATE_DATAIN) || (ncr->state == STATE_DATAOUT)) && (ncr->dma_mode != DMA_IDLE)) + ncr_dev->timer_period = (int64_t)ncr_dev->period; + else + ncr_dev->timer_period += 10LL * TIMER_USEC; + + if (ncr->dma_mode == DMA_IDLE) { + ncr->bus_host = get_bus_host(ncr); + + /*Start the SCSI command layer, which will also make the timings*/ + if (ncr->bus_host & BUS_ARB) { + DEBUG("Arbitration\n"); + ncr->state = STATE_IDLE; + } + + if (ncr->state == STATE_IDLE) { + ncr->clear_req = ncr->wait_data = ncr->wait_complete = 0; + if ((ncr->bus_host & BUS_SEL) && !(ncr->bus_host & BUS_BSY)) { + DEBUG("Selection phase\n"); + uint8_t sel_data = BUS_GETDATA(ncr->bus_host); + + ncr->target_id = get_dev_id(sel_data); + + DEBUG("Select - target ID = %i\n", ncr->target_id); + + /*Once the device has been found and selected, mark it as busy*/ + if ((ncr->target_id != -1) && + scsi_device_present(ncr->target_id, ncr->target_lun)) { + ncr->cur_bus |= BUS_BSY; + DEBUG("Device found at ID %i\n", ncr->target_id); + DEBUG("Current Bus BSY=%02x\n", ncr->cur_bus); + ncr->state = STATE_COMMAND; + ncr->cur_bus = BUS_BSY | BUS_REQ; + DEBUG("CurBus BSY|REQ=%02x\n", ncr->cur_bus); + ncr->command_pos = 0; + SET_BUS_STATE(ncr, SCSI_PHASE_COMMAND); + picint(1 << ncr_dev->irq); + } else { + ncr->state = STATE_IDLE; + ncr->cur_bus = 0; + } + } + } else if (ncr->state == STATE_COMMAND) { + int64_t p; + + /*Command phase, make sure the ICR ACK bit is set to keep on, + because the device must be acknowledged by ICR*/ + DEBUG("NCR ICR for Command=%02x\n", ncr->bus_host & BUS_ACK); + if (ncr->bus_host & BUS_ACK) { + /*Write command byte to the output data register*/ + ncr->command[ncr->command_pos++] = BUS_GETDATA(ncr->bus_host); + + ncr->new_phase = ncr->cur_bus & SCSI_PHASE_MESSAGE_IN; + ncr->clear_req = 3; + DEBUG("Current bus for command request=%02x\n", ncr->cur_bus & BUS_REQ); + ncr->cur_bus &= ~BUS_REQ; + + DEBUG("Command pos=%i, output data=%02x\n", ncr->command_pos, BUS_GETDATA(ncr->bus_host)); + if (get_cmd_len(ncr->command[0]) == ncr->command_pos) { + /*Reset data position to default*/ + ncr->data_pos = 0; + + dev = &SCSIDevices[ncr->target_id][ncr->target_lun]; + + DEBUG("SCSI Command 0x%02X for ID %d, status code=%02x\n", ncr->command[0], ncr->target_id, dev->Status); + + dev->BufferLength = -1; + + /*Now, execute the given SCSI command*/ + scsi_device_command_phase0(ncr->target_id, ncr->target_lun, ncr->command); + + DEBUG("SCSI ID %i: Command %02X: Buffer Length %i, SCSI Phase %02X\n", ncr->target_id, ncr->command[0], dev->BufferLength, dev->Phase); + + if (dev->Status != SCSI_STATUS_OK) + ncr_dev->is_non_data_mode = 1; + + if (ncr_dev->is_non_data_mode) { + ncr_dev->is_non_data_mode = 0; + ncr->new_phase = SCSI_PHASE_STATUS; + ncr->wait_data = 4; + return; + } + + /*If the SCSI phase is Data In or Data Out, allocate the SCSI buffer based on the transfer length of the command*/ + if (dev->BufferLength && (dev->Phase == SCSI_PHASE_DATA_IN || dev->Phase == SCSI_PHASE_DATA_OUT)) { + dev->CmdBuffer = (uint8_t *)mem_alloc(dev->BufferLength); + + p = scsi_device_get_callback(ncr->target_id, ncr->target_lun); + if (p <= 0LL) { + ncr_dev->temp_period = (int64_t)(dev->BufferLength); + ncr_dev->media_period = 0; + ncr_dev->period = 0.2 * ((double) TIMER_USEC) * ((double) MIN(64, ncr_dev->temp_period)); + } else { + ncr_dev->media_period += p; + ncr_dev->temp_period = dev->BufferLength; + ncr_dev->period = (p / ((double) ncr_dev->temp_period)) * ((double) MIN(64, ncr_dev->temp_period)); + } + } + + if (dev->Phase == SCSI_PHASE_DATA_OUT) { + /* Write direction commands have delayed execution - only execute them after the bus has gotten all the data from the host. */ + DEBUG("Next state is data out\n"); + ncr->new_phase = SCSI_PHASE_DATA_OUT; + ncr->wait_data = 4; + ncr->clear_req = 4; + } else { + /* Other command - execute immediately. */ + ncr->new_phase = dev->Phase; + + if (ncr->new_phase == SCSI_PHASE_DATA_IN) { + scsi_device_command_phase1(ncr->target_id, ncr->target_lun); + } + + ncr->wait_data = 4; + } + } + } + } else if (ncr->state == STATE_DATAIN) { + dev = &SCSIDevices[ncr->target_id][ncr->target_lun]; + DEBUG("Data In ACK=%02x\n", ncr->bus_host & BUS_ACK); + if (ncr->bus_host & BUS_ACK) { + if (ncr->data_pos >= dev->BufferLength) { + if (dev->CmdBuffer != NULL) { + free(dev->CmdBuffer); + dev->CmdBuffer = NULL; + } + + ncr->cur_bus &= ~BUS_REQ; + ncr->new_phase = SCSI_PHASE_STATUS; + ncr->wait_data = 4; + ncr->wait_complete = 8; + } else { + ncr->tx_data = dev->CmdBuffer[ncr->data_pos++]; + ncr->cur_bus = (ncr->cur_bus & ~BUS_DATAMASK) | BUS_SETDATA(ncr->tx_data) | BUS_DBP | BUS_REQ; + ncr->clear_req = 3; + ncr->cur_bus &= ~BUS_REQ; + ncr->new_phase = SCSI_PHASE_DATA_IN; + } + } + } else if (ncr->state == STATE_DATAOUT) { + dev = &SCSIDevices[ncr->target_id][ncr->target_lun]; + + DEBUG("Data Out ACK=%02x\n", ncr->bus_host & BUS_ACK); + if (ncr->bus_host & BUS_ACK) { + dev->CmdBuffer[ncr->data_pos++] = BUS_GETDATA(ncr->bus_host); + + if (ncr->data_pos >= dev->BufferLength) { + scsi_device_command_phase1(ncr->target_id, ncr->target_lun); + + if (dev->CmdBuffer != NULL) { + free(dev->CmdBuffer); + dev->CmdBuffer = NULL; + } + + ncr->cur_bus &= ~BUS_REQ; + DEBUG("CurBus ~REQ_DataOutDone=%02x\n", ncr->cur_bus); + ncr->new_phase = SCSI_PHASE_STATUS; + ncr->wait_data = 4; + ncr->wait_complete = 8; + } else { + /*More data is to be transferred, place a request*/ + ncr->cur_bus |= BUS_REQ; + DEBUG("CurBus ~REQ_DataOut=%02x\n", ncr->cur_bus); + } + } + } else if (ncr->state == STATE_STATUS) { + if (ncr->bus_host & BUS_ACK) { + /*All transfers done, wait until next transfer*/ + ncr->cur_bus &= ~BUS_REQ; + ncr->new_phase = SCSI_PHASE_MESSAGE_IN; + ncr->wait_data = 4; + ncr->wait_complete = 8; + } + } else if (ncr->state == STATE_MESSAGEIN) { + if (ncr->bus_host & BUS_ACK) { + ncr->cur_bus &= ~BUS_REQ; + ncr->new_phase = BUS_IDLE; + ncr->wait_data = 4; + } + } + } + + if (ncr_dev->type < 3) { + if (ncr->dma_mode == DMA_INITIATOR_RECEIVE) { + if (!(ncr_dev->status_ctrl & CTRL_DATA_DIR)) { + DEBUG("DMA_INITIATOR_RECEIVE with DMA direction set wrong\n"); + return; + } + + DEBUG("Status for reading=%02x\n", ncr_dev->status_ctrl); + + if (!(ncr_dev->status_ctrl & STATUS_BUFFER_NOT_READY)) return; + + if (!ncr_dev->block_count_loaded) return; + + while (c < 64) { + /* Data ready. */ + uint8_t temp; + + ncr_wait_process(ncr_dev); + temp = BUS_GETDATA(ncr->bus_host); + ncr->bus_host = get_bus_host(ncr); + + if (ncr->data_pos >= dev->BufferLength) { + if (dev->CmdBuffer != NULL) { + free(dev->CmdBuffer); + dev->CmdBuffer = NULL; + } + + ncr->cur_bus &= ~BUS_REQ; + ncr->new_phase = SCSI_PHASE_STATUS; + ncr->wait_data = 4; + ncr->wait_complete = 8; + } else { + ncr->tx_data = dev->CmdBuffer[ncr->data_pos++]; + ncr->cur_bus = (ncr->cur_bus & ~BUS_DATAMASK) | BUS_SETDATA(ncr->tx_data) | BUS_DBP | BUS_REQ; + ncr->clear_req = 3; + ncr->cur_bus &= ~BUS_REQ; + ncr->new_phase = SCSI_PHASE_DATA_IN; + } + + ncr_dev->buffer[ncr_dev->buffer_pos++] = temp; + DEBUG("Buffer pos for reading=%d\n", ncr_dev->buffer_pos); + + c++; + + if (ncr_dev->buffer_pos == 128) { + ncr_dev->buffer_pos = 0; + ncr_dev->buffer_host_pos = 0; + ncr_dev->status_ctrl &= ~STATUS_BUFFER_NOT_READY; + ncr_dev->block_count = (ncr_dev->block_count - 1) & 255; + DEBUG("Remaining blocks to be read=%d\n", ncr_dev->block_count); + if (!ncr_dev->block_count) { + ncr_dev->block_count_loaded = 0; + DEBUG("IO End of read transfer\n"); + + ncr->isr |= STATUS_END_OF_DMA; + if (ncr->mode & MODE_ENA_EOP_INT) { + DEBUG("NCR read irq\n"); + ncr->isr |= STATUS_INT; + picint(1 << ncr_dev->irq); + } + } + break; + } + } + } else if (ncr->dma_mode == DMA_SEND) { + if (ncr_dev->status_ctrl & CTRL_DATA_DIR) { + DEBUG("DMA_SEND with DMA direction set wrong\n"); + return; + } + + DEBUG("Status for writing=%02x\n", ncr_dev->status_ctrl); + + if (!(ncr_dev->status_ctrl & STATUS_BUFFER_NOT_READY)) { + DEBUG("Buffer ready\n"); + return; + } + + if (!ncr_dev->block_count_loaded) return; + + while (c < 64) { + /* Data ready. */ + uint8_t data; + + data = ncr_dev->buffer[ncr_dev->buffer_pos]; + ncr->bus_host = get_bus_host(ncr) & ~BUS_DATAMASK; + ncr->bus_host |= BUS_SETDATA(data); + + dev->CmdBuffer[ncr->data_pos++] = BUS_GETDATA(ncr->bus_host); + + if (ncr->data_pos >= dev->BufferLength) { + scsi_device_command_phase1(ncr->target_id, ncr->target_lun); + + if (dev->CmdBuffer != NULL) { + free(dev->CmdBuffer); + dev->CmdBuffer = NULL; + } + + ncr->cur_bus &= ~BUS_REQ; + DEBUG("CurBus ~REQ_DataOutDone=%02x\n", ncr->cur_bus); + ncr->new_phase = SCSI_PHASE_STATUS; + ncr->wait_data = 4; + ncr->wait_complete = 8; + } else { + /*More data is to be transferred, place a request*/ + ncr->cur_bus |= BUS_REQ; + DEBUG("CurBus ~REQ_DataOut=%02x\n", ncr->cur_bus); + } + + c++; + + if (++ncr_dev->buffer_pos == 128) { + ncr_dev->buffer_pos = 0; + ncr_dev->buffer_host_pos = 0; + ncr_dev->status_ctrl &= ~STATUS_BUFFER_NOT_READY; + ncr_dev->ncr_busy = 0; + ncr_dev->block_count = (ncr_dev->block_count - 1) & 255; + DEBUG("Remaining blocks to be written=%d\n", ncr_dev->block_count); + if (!ncr_dev->block_count) { + ncr_dev->block_count_loaded = 0; + DEBUG("IO End of write transfer\n"); + + ncr->tcr |= TCR_LAST_BYTE_SENT; + ncr->isr |= STATUS_END_OF_DMA; + if (ncr->mode & MODE_ENA_EOP_INT) { + DEBUG("NCR write irq\n"); + ncr->isr |= STATUS_INT; + picint(1 << ncr_dev->irq); + } + } + break; + } + } + } + } else { + if (ncr->dma_mode == DMA_INITIATOR_RECEIVE) { + if (!(ncr_dev->block_count_loaded)) + return; + + while (c < 64) { + /* Data ready. */ + uint8_t temp; + + ncr_wait_process(ncr_dev); + temp = BUS_GETDATA(ncr->bus_host); + ncr->bus_host = get_bus_host(ncr); + + if (ncr->data_pos >= dev->BufferLength) { + if (dev->CmdBuffer != NULL) { + free(dev->CmdBuffer); + dev->CmdBuffer = NULL; + } + + ncr->cur_bus &= ~BUS_REQ; + ncr->new_phase = SCSI_PHASE_STATUS; + ncr->wait_data = 4; + ncr->wait_complete = 8; + } else { + ncr->tx_data = dev->CmdBuffer[ncr->data_pos++]; + ncr->cur_bus = (ncr->cur_bus & ~BUS_DATAMASK) | BUS_SETDATA(ncr->tx_data) | BUS_DBP | BUS_REQ; + ncr->clear_req = 3; + ncr->cur_bus &= ~BUS_REQ; + ncr->new_phase = SCSI_PHASE_DATA_IN; + } + + ncr_dev->buffer[ncr_dev->buffer_pos++] = temp; + DEBUG("Buffer pos for reading=%d\n", ncr_dev->buffer_pos); + + c++; + + if (ncr_dev->buffer_pos == 128) { + ncr_dev->buffer_pos = 0; + ncr_dev->buffer_host_pos = 0; + ncr_dev->block_count = (ncr_dev->block_count - 1) & 255; + DEBUG("Remaining blocks to be read=%d\n", ncr_dev->block_count); + if (!ncr_dev->block_count) { + ncr_dev->block_count_loaded = 0; + DEBUG("IO End of read transfer\n"); + + ncr->isr |= STATUS_END_OF_DMA; + if (ncr->mode & MODE_ENA_EOP_INT) { + DEBUG("NCR read irq\n"); + ncr->isr |= STATUS_INT; + picint(1 << ncr_dev->irq); + } + } + break; + } + } + } else if (ncr->dma_mode == DMA_SEND) { + if (!ncr_dev->block_count_loaded) return; + while (c < 64) { + /* Data ready. */ + uint8_t data; + + data = ncr_dev->buffer[ncr_dev->buffer_pos]; + ncr->bus_host = get_bus_host(ncr) & ~BUS_DATAMASK; + ncr->bus_host |= BUS_SETDATA(data); + + dev->CmdBuffer[ncr->data_pos++] = BUS_GETDATA(ncr->bus_host); + + if (ncr->data_pos >= dev->BufferLength) { + scsi_device_command_phase1(ncr->target_id, ncr->target_lun); + + if (dev->CmdBuffer != NULL) { + free(dev->CmdBuffer); + dev->CmdBuffer = NULL; + } + + ncr->cur_bus &= ~BUS_REQ; + DEBUG("CurBus ~REQ_DataOutDone=%02x\n", ncr->cur_bus); + ncr->new_phase = SCSI_PHASE_STATUS; + ncr->wait_data = 4; + ncr->wait_complete = 8; + } else { + /*More data is to be transferred, place a request*/ + ncr->cur_bus |= BUS_REQ; + DEBUG("CurBus ~REQ_DataOut=%02x\n", ncr->cur_bus); + } + + c++; + + if (++ncr_dev->buffer_pos == 128) { + ncr_dev->buffer_pos = 0; + ncr_dev->buffer_host_pos = 0; + ncr_dev->block_count = (ncr_dev->block_count - 1) & 255; + DEBUG("Remaining blocks to be written=%d\n", ncr_dev->block_count); + if (!ncr_dev->block_count) { + ncr_dev->block_count_loaded = 0; + DEBUG("IO End of write transfer\n"); + + ncr->tcr |= TCR_LAST_BYTE_SENT; + ncr->isr |= STATUS_END_OF_DMA; + if (ncr->mode & MODE_ENA_EOP_INT) { + DEBUG("NCR write irq\n"); + ncr->isr |= STATUS_INT; + picint(1 << ncr_dev->irq); + } + } + break; + } + } + } + } + + ncr_wait_process(ncr_dev); + + if (!(ncr->bus_host & BUS_BSY) && (ncr->mode & MODE_MONITOR_BUSY)) { + DEBUG("Updating DMA\n"); + ncr->mode &= ~MODE_DMA; + ncr->dma_mode = DMA_IDLE; } } @@ -827,95 +1325,111 @@ static void * ncr_init(const device_t *info) { char temp[128]; - ncr_t *scsi; + ncr5380_t *ncr_dev; - scsi = malloc(sizeof(ncr_t)); - memset(scsi, 0x00, sizeof(ncr_t)); - scsi->name = info->name; - scsi->type = info->local; + ncr_dev = (ncr5380_t *)mem_alloc(sizeof(ncr5380_t)); + memset(ncr_dev, 0x00, sizeof(ncr5380_t)); + ncr_dev->name = info->name; + ncr_dev->type = info->local; - switch(scsi->type) { + switch(ncr_dev->type) { case 0: /* Longshine LCS6821N */ - scsi->rom_addr = 0xDC000; - rom_init(&scsi->bios_rom, LCS6821N_ROM, - scsi->rom_addr, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL); - mem_mapping_disable(&scsi->bios_rom.mapping); + ncr_dev->rom_addr = 0xDC000; + rom_init(&ncr_dev->bios_rom, LCS6821N_ROM, + ncr_dev->rom_addr, 0x4000, 0x3fff, + 0, MEM_MAPPING_EXTERNAL); - mem_mapping_add(&scsi->mapping, scsi->rom_addr, 0x4000, - memio_read, NULL, NULL, - memio_write, NULL, NULL, - scsi->bios_rom.rom, 0, scsi); + mem_map_disable(&ncr_dev->bios_rom.mapping); + + mem_map_add(&ncr_dev->mapping, ncr_dev->rom_addr, 0x4000, + memio_read, NULL, NULL, + memio_write, NULL, NULL, + ncr_dev->bios_rom.rom, 0, ncr_dev); break; - case 1: /* Ranco RT1000B */ - scsi->rom_addr = 0xDC000; - rom_init(&scsi->bios_rom, RT1000B_ROM, - scsi->rom_addr, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL); + case 1: /* Rancho RT1000B */ + ncr_dev->rom_addr = 0xDC000; + rom_init(&ncr_dev->bios_rom, RT1000B_ROM, + ncr_dev->rom_addr, 0x4000, 0x3fff, + 0, MEM_MAPPING_EXTERNAL); - mem_mapping_disable(&scsi->bios_rom.mapping); + mem_map_disable(&ncr_dev->bios_rom.mapping); - mem_mapping_add(&scsi->mapping, scsi->rom_addr, 0x4000, - memio_read, NULL, NULL, - memio_write, NULL, NULL, - scsi->bios_rom.rom, 0, scsi); + mem_map_add(&ncr_dev->mapping, ncr_dev->rom_addr, 0x4000, + memio_read, NULL, NULL, + memio_write, NULL, NULL, + ncr_dev->bios_rom.rom, 0, ncr_dev); break; case 2: /* Trantor T130B */ - scsi->rom_addr = 0xDC000; - scsi->base = 0x0350; - rom_init(&scsi->bios_rom, T130B_ROM, - scsi->rom_addr, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL); + ncr_dev->rom_addr = 0xDC000; + ncr_dev->base = device_get_config_hex16("base"); + ncr_dev->irq = device_get_config_int("irq"); + rom_init(&ncr_dev->bios_rom, T130B_ROM, + ncr_dev->rom_addr, 0x4000, 0x3fff, + 0, MEM_MAPPING_EXTERNAL); - mem_mapping_add(&scsi->mapping, scsi->rom_addr, 0x4000, - t130b_read, NULL, NULL, - t130b_write, NULL, NULL, - scsi->bios_rom.rom, 0, scsi); + mem_map_add(&ncr_dev->mapping, ncr_dev->rom_addr, 0x4000, + t130b_read, NULL, NULL, + t130b_write, NULL, NULL, + ncr_dev->bios_rom.rom, 0, ncr_dev); - io_sethandler(scsi->base, 16, - t130b_in,NULL,NULL, t130b_out,NULL,NULL, scsi); + io_sethandler(ncr_dev->base, 16, + t130b_in,NULL,NULL, t130b_out,NULL,NULL, ncr_dev); break; case 3: /* Sumo SCSI-AT */ - scsi->base = device_get_config_hex16("base"); - scsi->irq = device_get_config_int("irq"); - scsi->rom_addr = device_get_config_hex20("bios_addr"); - rom_init(&scsi->bios_rom, SCSIAT_ROM, - scsi->rom_addr, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL); + ncr_dev->base = device_get_config_hex16("base"); + ncr_dev->irq = device_get_config_int("irq"); + ncr_dev->rom_addr = device_get_config_hex20("bios_addr"); + rom_init(&ncr_dev->bios_rom, SCSIAT_ROM, + ncr_dev->rom_addr, 0x4000, 0x3fff, + 0, MEM_MAPPING_EXTERNAL); - mem_mapping_add(&scsi->mapping, scsi->rom_addr, 0x4000, - t130b_read, NULL, NULL, - t130b_write, NULL, NULL, - scsi->bios_rom.rom, 0, scsi); + mem_map_disable(&ncr_dev->bios_rom.mapping); + + mem_map_add(&ncr_dev->mapping, ncr_dev->rom_addr, 0x4000, + t130b_read, NULL, NULL, + t130b_write, NULL, NULL, + ncr_dev->bios_rom.rom, 0, ncr_dev); - io_sethandler(scsi->base, 16, - scsiat_in,NULL,NULL, scsiat_out,NULL,NULL, scsi); + io_sethandler(ncr_dev->base, 16, + scsiat_in,NULL,NULL, scsiat_out,NULL,NULL, ncr_dev); break; } - sprintf(temp, "%s: BIOS=%05X", scsi->name, scsi->rom_addr); - if (scsi->base != 0) - sprintf(&temp[strlen(temp)], " I/O=%04x", scsi->base); - if (scsi->irq != 0) - sprintf(&temp[strlen(temp)], " IRQ=%d", scsi->irq); - pclog("%s\n", temp); + sprintf(temp, "%s: BIOS=%05X", ncr_dev->name, ncr_dev->rom_addr); + if (ncr_dev->base != 0) + sprintf(&temp[strlen(temp)], " I/O=%04x", ncr_dev->base); + if (ncr_dev->irq != 0) + sprintf(&temp[strlen(temp)], " IRQ=%d", ncr_dev->irq); + INFO("%s\n", temp); - ncr5380_reset(&scsi->ncr); + ncr_reset(&ncr_dev->ncr); - scsi->status_ctrl = STATUS_BUFFER_NOT_READY; - scsi->buffer_host_pos = 128; + ncr_dev->status_ctrl = STATUS_BUFFER_NOT_READY; + ncr_dev->buffer_host_pos = 128; + + ncr_dev->timer_period = 10LL * TIMER_USEC; + timer_add(ncr_callback, &ncr_dev->timer_period, + TIMER_ALWAYS_ENABLED, ncr_dev); - timer_add(dma_callback, &scsi->dma_timer, &scsi->dma_enabled, scsi); - - return(scsi); + return(ncr_dev); } static void ncr_close(void *priv) { - ncr_t *scsi = (ncr_t *)priv; + ncr5380_t *ncr_dev = (ncr5380_t *)priv; - free(scsi); + if (ncr_dev) { + /* Tell the timer to terminate. */ + ncr_dev->timer_period = 0LL; + ncr_dev->timer_enabled = 0LL; + + free(ncr_dev); + } } @@ -925,21 +1439,18 @@ lcs6821n_available(void) return(rom_present(LCS6821N_ROM)); } - static int rt1000b_available(void) { return(rom_present(RT1000B_ROM)); } - static int t130b_available(void) { return(rom_present(T130B_ROM)); } - static int scsiat_available(void) { @@ -947,105 +1458,147 @@ scsiat_available(void) } +static const device_config_t t130b_config[] = { + { + "base", "Address", CONFIG_HEX16, "", 0x0350, + { + { + "240H", 0x0240 + }, + { + "250H", 0x0250 + }, + { + "340H", 0x0340 + }, + { + "350H", 0x0350 + }, + { + "" + } + } + }, + { + "irq", "IRQ", CONFIG_SELECTION, "", 5, + { + { + "IRQ 3", 3 + }, + { + "IRQ 5", 5 + }, + { + "IRQ 7", 7 + }, + { + "" + } + } + }, + { + "", "", -1 + } +}; + static const device_config_t scsiat_config[] = { + { + "base", "Address", CONFIG_HEX16, "", 0x0310, { - "base", "Address", CONFIG_HEX16, "", 0x0310, { - { - "None", 0 - }, - { - "300H", 0x0300 - }, - { - "310H", 0x0310 - }, - { - "320H", 0x0320 - }, - { - "330H", 0x0330 - }, - { - "340H", 0x0340 - }, - { - "350H", 0x0350 - }, - { - "360H", 0x0360 - }, - { - "370H", 0x0370 - }, - { - "" - } + "None", 0 }, - }, + { + "300H", 0x0300 + }, + { + "310H", 0x0310 + }, + { + "320H", 0x0320 + }, + { + "330H", 0x0330 + }, + { + "340H", 0x0340 + }, + { + "350H", 0x0350 + }, + { + "360H", 0x0360 + }, + { + "370H", 0x0370 + }, + { + "" + } + } + }, + { + "irq", "IRQ", CONFIG_SELECTION, "", 5, { - "irq", "IRQ", CONFIG_SELECTION, "", 5, { - { - "IRQ 3", 3 - }, - { - "IRQ 4", 4 - }, - { - "IRQ 5", 5 - }, - { - "IRQ 10", 10 - }, - { - "IRQ 11", 11 - }, - { - "IRQ 12", 12 - }, - { - "IRQ 14", 14 - }, - { - "IRQ 15", 15 - }, - { - "" - } + "IRQ 3", 3 }, - }, + { + "IRQ 4", 4 + }, + { + "IRQ 5", 5 + }, + { + "IRQ 10", 10 + }, + { + "IRQ 11", 11 + }, + { + "IRQ 12", 12 + }, + { + "IRQ 14", 14 + }, + { + "IRQ 15", 15 + }, + { + "" + } + } + }, + { + "bios_addr", "BIOS Address", CONFIG_HEX20, "", 0xD8000, { - "bios_addr", "BIOS Address", CONFIG_HEX20, "", 0xD8000, { - { - "Disabled", 0 - }, - { - "C800H", 0xc8000 - }, - { - "CC00H", 0xcc000 - }, - { - "D800H", 0xd8000 - }, - { - "DC00H", 0xdc000 - }, - { - "" - } + "Disabled", 0 }, - }, - { - "", "", -1 - } + { + "C800H", 0xc8000 + }, + { + "CC00H", 0xcc000 + }, + { + "D800H", 0xd8000 + }, + { + "DC00H", 0xdc000 + }, + { + "" + } + } + }, + { + "", "", -1 + } }; -const device_t scsi_lcs6821n_device = -{ +const device_t scsi_lcs6821n_device = { "Longshine LCS-6821N", DEVICE_ISA, 0, @@ -1055,8 +1608,7 @@ const device_t scsi_lcs6821n_device = NULL }; -const device_t scsi_rt1000b_device = -{ +const device_t scsi_rt1000b_device = { "Ranco RT1000B", DEVICE_ISA, 1, @@ -1066,19 +1618,17 @@ const device_t scsi_rt1000b_device = NULL }; -const device_t scsi_t130b_device = -{ +const device_t scsi_t130b_device = { "Trantor T130B", DEVICE_ISA, 2, ncr_init, ncr_close, NULL, t130b_available, NULL, NULL, NULL, - NULL + t130b_config }; -const device_t scsi_scsiat_device = -{ +const device_t scsi_scsiat_device = { "Sumo SCSI-AT", DEVICE_ISA, 3, diff --git a/src/devices/scsi/scsi_ncr53c810.c b/src/devices/scsi/scsi_ncr53c810.c index e7709ec..15485de 100644 --- a/src/devices/scsi/scsi_ncr53c810.c +++ b/src/devices/scsi/scsi_ncr53c810.c @@ -10,7 +10,7 @@ * NCR and later Symbios and LSI. This controller was designed * for the PCI bus. * - * Version: @(#)scsi_ncr53c810.c 1.0.9 2018/05/06 + * Version: @(#)scsi_ncr53c810.c 1.0.10 2018/09/22 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -46,6 +46,7 @@ #include #include #include +#define dbglog scsi_dev_log #include "../../emu.h" #include "../../io.h" #include "../../mem.h" @@ -62,7 +63,8 @@ #include "scsi_ncr53c810.h" -#define ncr53c810_log scsi_dev_log +#define NCR53C810_ROM L"scsi/ncr/ncr53c810/ncr307.bin" +#define USE_PCI_BAR 0 #define NCR_SCNTL0_TRG 0x01 #define NCR_SCNTL0_AAP 0x02 @@ -188,6 +190,7 @@ #define NCR_BUF_SIZE 4096 + typedef struct ncr53c810_request { uint32_t tag; uint32_t dma_len; @@ -196,23 +199,28 @@ typedef struct ncr53c810_request { int out; } ncr53c810_request; -typedef enum -{ - SCSI_STATE_SEND_COMMAND, - SCSI_STATE_READ_DATA, - SCSI_STATE_WRITE_DATA, - SCSI_STATE_READ_STATUS, - SCSI_STATE_READ_MESSAGE, - SCSI_STATE_WRITE_MESSAGE +typedef enum { + SCSI_STATE_SEND_COMMAND, + SCSI_STATE_READ_DATA, + SCSI_STATE_WRITE_DATA, + SCSI_STATE_READ_STATUS, + SCSI_STATE_READ_MESSAGE, + SCSI_STATE_WRITE_MESSAGE } scsi_state_t; typedef struct { uint8_t pci_slot; + int has_bios; + rom_t bios; +#if USE_PCI_BAR + uint32_t bios_addr, + bios_mask; +#endif int PCIBase; int MMIOBase; - mem_mapping_t mmio_mapping; + mem_map_t mmio_mapping; int RAMBase; - mem_mapping_t ram_mapping; + mem_map_t ram_mapping; int carry; /* ??? Should this be an a visible register somewhere? */ int status; @@ -332,7 +340,9 @@ ncr53c810_irq_on_rsl(ncr53c810_t *dev) static void ncr53c810_soft_reset(ncr53c810_t *dev) { - ncr53c810_log("LSI Reset\n"); + int i, j; + + DEBUG("LSI Reset\n"); dev->timer_period = dev->timer_enabled = 0; dev->carry = 0; @@ -386,42 +396,49 @@ ncr53c810_soft_reset(ncr53c810_t *dev) dev->last_level = 0; dev->gpreg0 = 0; dev->sstop = 1; + + for (i = 0; i < 16; i++) { + for (j = 0; j < 8; j++) + scsi_device_reset(i, j); + } } static void ncr53c810_read(ncr53c810_t *dev, uint32_t addr, uint8_t *buf, uint32_t len) { - uint32_t i = 0; + uint32_t i = 0; - ncr53c810_log("ncr53c810_read(): %08X-%08X, length %i\n", addr, (addr + len - 1), len); + DEBUG("ncr53c810_read(): %08X-%08X, length %i\n", + addr, (addr + len - 1), len); - if (dev->dmode & NCR_DMODE_SIOM) { - ncr53c810_log("NCR 810: Reading from I/O address %04X\n", (uint16_t) addr); - for (i = 0; i < len; i++) - buf[i] = inb((uint16_t) (addr + i)); - } else { - ncr53c810_log("NCR 810: Reading from memory address %08X\n", addr); - DMAPageRead(addr, buf, len); - } + if (dev->dmode & NCR_DMODE_SIOM) { + DEBUG("NCR 810: Reading from I/O address %04X\n", (uint16_t) addr); + for (i = 0; i < len; i++) + buf[i] = inb((uint16_t) (addr + i)); + } else { + DEBUG("NCR 810: Reading from memory address %08X\n", addr); + DMAPageRead(addr, buf, len); + } } static void ncr53c810_write(ncr53c810_t *dev, uint32_t addr, uint8_t *buf, uint32_t len) { - uint32_t i = 0; + uint32_t i = 0; - ncr53c810_log("ncr53c810_write(): %08X-%08X, length %i\n", addr, (addr + len - 1), len); + DEBUG("ncr53c810_write(): %08X-%08X, length %i\n", + addr, (addr + len - 1), len); - if (dev->dmode & NCR_DMODE_DIOM) { - ncr53c810_log("NCR 810: Writing to I/O address %04X\n", (uint16_t) addr); - for (i = 0; i < len; i++) - outb((uint16_t) (addr + i), buf[i]); - } else { - ncr53c810_log("NCR 810: Writing to memory address %08X\n", addr); - DMAPageWrite(addr, buf, len); - } + if (dev->dmode & NCR_DMODE_DIOM) { + DEBUG("NCR 810: Writing to I/O address %04X\n", (uint16_t) addr); + for (i = 0; i < len; i++) + outb((uint16_t) (addr + i), buf[i]); + } else { + DEBUG("NCR 810: Writing to memory address %08X\n", addr); + DMAPageWrite(addr, buf, len); + } } @@ -429,8 +446,11 @@ static __inline uint32_t read_dword(ncr53c810_t *dev, uint32_t addr) { uint32_t buf; - ncr53c810_log("Reading the next DWORD from memory (%08X)...\n", addr); + + DEBUG("Reading the next DWORD from memory (%08X)...\n", addr); + DMAPageRead(addr, (uint8_t *)&buf, 4); + return buf; } @@ -440,10 +460,10 @@ void do_irq(ncr53c810_t *dev, int level) { if (level) { pci_set_irq(dev->pci_slot, PCI_INTA); - ncr53c810_log("Raising IRQ...\n"); + DEBUG("Raising IRQ...\n"); } else { pci_clear_irq(dev->pci_slot, PCI_INTA); - ncr53c810_log("Lowering IRQ...\n"); + DEBUG("Lowering IRQ...\n"); } } @@ -477,8 +497,8 @@ ncr53c810_update_irq(ncr53c810_t *dev) } if (level != dev->last_level) { - ncr53c810_log("Update IRQ level %d dstat %02x sist %02x%02x\n", - level, dev->dstat, dev->sist1, dev->sist0); + DEBUG("Update IRQ level %d dstat %02x sist %02x%02x\n", + level, dev->dstat, dev->sist1, dev->sist0); dev->last_level = level; do_irq(dev, level); /* Only do something with the IRQ if the new level differs from the previous one. */ } @@ -492,8 +512,9 @@ ncr53c810_script_scsi_interrupt(ncr53c810_t *dev, int stat0, int stat1) uint32_t mask0; uint32_t mask1; - ncr53c810_log("SCSI Interrupt 0x%02x%02x prev 0x%02x%02x\n", - stat1, stat0, dev->sist1, dev->sist0); + DEBUG("SCSI Interrupt 0x%02x%02x prev 0x%02x%02x\n", + stat1, stat0, dev->sist1, dev->sist0); + dev->sist0 |= stat0; dev->sist1 |= stat1; /* Stop processor on fatal or unmasked interrupt. As a special hack @@ -503,7 +524,7 @@ ncr53c810_script_scsi_interrupt(ncr53c810_t *dev, int stat0, int stat1) mask1 = dev->sien1 | ~(NCR_SIST1_GEN | NCR_SIST1_HTH); mask1 &= ~NCR_SIST1_STO; if ((dev->sist0 & mask0) || (dev->sist1 & mask1)) { - ncr53c810_log("NCR 810: IRQ-mandated stop\n"); + DEBUG("NCR 810: IRQ-mandated stop\n"); dev->sstop = 1; dev->timer_period = dev->timer_enabled = 0; } @@ -515,7 +536,7 @@ ncr53c810_script_scsi_interrupt(ncr53c810_t *dev, int stat0, int stat1) static void ncr53c810_script_dma_interrupt(ncr53c810_t *dev, int stat) { - ncr53c810_log("DMA Interrupt 0x%x prev 0x%x\n", stat, dev->dstat); + DEBUG("DMA Interrupt 0x%x prev 0x%x\n", stat, dev->dstat); dev->dstat |= stat; ncr53c810_update_irq(dev); dev->sstop = 1; @@ -534,7 +555,7 @@ static void ncr53c810_bad_phase(ncr53c810_t *dev, int out, int new_phase) { /* Trigger a phase mismatch. */ - ncr53c810_log("Phase mismatch interrupt\n"); + DEBUG("Phase mismatch interrupt\n"); ncr53c810_script_scsi_interrupt(dev, NCR_SIST0_MA, 0); dev->sstop = 1; dev->timer_period = dev->timer_enabled = 0; @@ -555,7 +576,7 @@ ncr53c810_disconnect(ncr53c810_t *dev) static void ncr53c810_bad_selection(ncr53c810_t *dev, uint32_t id) { - ncr53c810_log("Selected absent target %d\n", id); + DEBUG("Selected absent target %d\n", id); ncr53c810_script_scsi_interrupt(dev, 0, NCR_SIST1_STO); ncr53c810_disconnect(dev); } @@ -567,9 +588,10 @@ ncr53c810_command_complete(void *priv, uint32_t status) { ncr53c810_t *dev = (ncr53c810_t *)priv; int out; - + + DEBUG("(ID=%02i LUN=%02i) SCSI Command 0x%02x: Command complete status=%d\n", dev->current->tag, dev->current_lun, dev->last_command, (int)status); + out = (dev->sstat1 & PHASE_MASK) == PHASE_DO; - ncr53c810_log("(ID=%02i LUN=%02i) SCSI Command 0x%02x: Command complete status=%d\n", dev->current->tag, dev->current_lun, dev->last_command, (int)status); dev->status = status; dev->command_complete = 2; if (dev->waiting && dev->dbc != 0) { @@ -592,14 +614,14 @@ ncr53c810_do_dma(ncr53c810_t *dev, int out, uint8_t id) sd = &SCSIDevices[id][dev->current_lun]; - if (((id == 0xff) && !scsi_device_present(id, dev->current_lun))) { - ncr53c810_log("(ID=%02i LUN=%02i) SCSI Command 0x%02x: Device not present when attempting to do DMA\n", id, dev->current_lun, dev->last_command); + if ((!scsi_device_present(id, dev->current_lun))) { + DEBUG("(ID=%02i LUN=%02i) SCSI Command 0x%02x: Device not present when attempting to do DMA\n", id, dev->current_lun, dev->last_command); return; } if (!dev->current->dma_len) { /* Wait until data is available. */ - ncr53c810_log("(ID=%02i LUN=%02i) SCSI Command 0x%02x: DMA no data available\n", id, dev->current_lun, dev->last_command); + DEBUG("(ID=%02i LUN=%02i) SCSI Command 0x%02x: DMA no data available\n", id, dev->current_lun, dev->last_command); return; } @@ -610,7 +632,7 @@ ncr53c810_do_dma(ncr53c810_t *dev, int out, uint8_t id) addr = dev->dnad; - ncr53c810_log("(ID=%02i LUN=%02i) SCSI Command 0x%02x: DMA addr=0x%08x len=%d cur_len=%d dev->dbc=%d\n", id, dev->current_lun, dev->last_command, dev->dnad, dev->temp_buf_len, count, tdbc); + DEBUG("(ID=%02i LUN=%02i) SCSI Command 0x%02x: DMA addr=0x%08x len=%d cur_len=%d dev->dbc=%d\n", id, dev->current_lun, dev->last_command, dev->dnad, dev->temp_buf_len, count, tdbc); dev->dnad += count; dev->dbc -= count; @@ -618,7 +640,7 @@ ncr53c810_do_dma(ncr53c810_t *dev, int out, uint8_t id) ncr53c810_read(dev, addr, sd->CmdBuffer+dev->buffer_pos, count); else { if (!dev->buffer_pos) { - ncr53c810_log("(ID=%02i LUN=%02i) SCSI Command 0x%02x: SCSI Command Phase 1 on PHASE_DI\n", id, dev->current_lun, dev->last_command); + DEBUG("(ID=%02i LUN=%02i) SCSI Command 0x%02x: SCSI Command Phase 1 on PHASE_DI\n", id, dev->current_lun, dev->last_command); scsi_device_command_phase1(dev->current->tag, dev->current_lun); } ncr53c810_write(dev, addr, sd->CmdBuffer+dev->buffer_pos, count); @@ -629,7 +651,7 @@ ncr53c810_do_dma(ncr53c810_t *dev, int out, uint8_t id) if (dev->temp_buf_len <= 0) { if (out) { - ncr53c810_log("(ID=%02i LUN=%02i) SCSI Command 0x%02x: SCSI Command Phase 1 on PHASE_DO\n", id, dev->current_lun, dev->last_command); + DEBUG("(ID=%02i LUN=%02i) SCSI Command 0x%02x: SCSI Command Phase 1 on PHASE_DO\n", id, dev->current_lun, dev->last_command); scsi_device_command_phase1(id, dev->current_lun); } if (sd->CmdBuffer != NULL) { @@ -638,7 +660,7 @@ ncr53c810_do_dma(ncr53c810_t *dev, int out, uint8_t id) } ncr53c810_command_complete(dev, sd->Status); } else { - ncr53c810_log("(ID=%02i LUN=%02i) SCSI Command 0x%02x: Resume SCRIPTS\n", id, dev->current_lun, dev->last_command); + DEBUG("(ID=%02i LUN=%02i) SCSI Command 0x%02x: Resume SCRIPTS\n", id, dev->current_lun, dev->last_command); dev->sstop = 0; } } @@ -649,9 +671,9 @@ static void ncr53c810_add_msg_byte(ncr53c810_t *dev, uint8_t data) { if (dev->msg_len >= NCR_MAX_MSGIN_LEN) - ncr53c810_log("MSG IN data too long\n"); + DEBUG("MSG IN data too long\n"); else { - ncr53c810_log("MSG IN 0x%02x\n", data); + DEBUG("MSG IN 0x%02x\n", data); dev->msg[dev->msg_len++] = data; } } @@ -668,28 +690,28 @@ ncr53c810_do_command(ncr53c810_t *dev, uint8_t id) memset(buf, 0, 12); DMAPageRead(dev->dnad, buf, MIN(12, dev->dbc)); if (dev->dbc > 12) { - ncr53c810_log("(ID=%02i LUN=%02i) SCSI Command 0x%02x: CDB length %i too big\n", id, dev->current_lun, buf[0], dev->dbc); + DEBUG("(ID=%02i LUN=%02i) SCSI Command 0x%02x: CDB length %i too big\n", id, dev->current_lun, buf[0], dev->dbc); dev->dbc = 12; } dev->sfbr = buf[0]; dev->command_complete = 0; sd = &SCSIDevices[id][dev->current_lun]; - if (((id == 0xff) || !scsi_device_present(id, dev->current_lun))) { - ncr53c810_log("(ID=%02i LUN=%02i) SCSI Command 0x%02x: Bad Selection\n", id, dev->current_lun, buf[0]); + if (!scsi_device_present(id, dev->current_lun)) { + DEBUG("(ID=%02i LUN=%02i) SCSI Command 0x%02x: Bad Selection\n", id, dev->current_lun, buf[0]); ncr53c810_bad_selection(dev, id); return(0); } - dev->current = (ncr53c810_request*)malloc(sizeof(ncr53c810_request)); + dev->current = (ncr53c810_request*)mem_alloc(sizeof(ncr53c810_request)); dev->current->tag = id; sd->BufferLength = -1; - ncr53c810_log("(ID=%02i LUN=%02i) SCSI Command 0x%02x: DBC=%i\n", id, dev->current_lun, buf[0], dev->dbc); + DEBUG("(ID=%02i LUN=%02i) SCSI Command 0x%02x: DBC=%i\n", id, dev->current_lun, buf[0], dev->dbc); dev->last_command = buf[0]; - scsi_device_command_phase0(dev->current->tag, dev->current_lun, dev->dbc, buf); + scsi_device_command_phase0(dev->current->tag, dev->current_lun, buf); dev->hba_private = (void *)dev->current; dev->waiting = 0; @@ -698,12 +720,12 @@ ncr53c810_do_command(ncr53c810_t *dev, uint8_t id) dev->temp_buf_len = sd->BufferLength; if (sd->BufferLength > 0) { - sd->CmdBuffer = (uint8_t *)malloc(sd->BufferLength); + sd->CmdBuffer = (uint8_t *)mem_alloc(sd->BufferLength); dev->current->dma_len = sd->BufferLength; } if ((sd->Phase == SCSI_PHASE_DATA_IN) && (sd->BufferLength > 0)) { - ncr53c810_log("(ID=%02i LUN=%02i) SCSI Command 0x%02x: PHASE_DI\n", id, dev->current_lun, buf[0]); + DEBUG("(ID=%02i LUN=%02i) SCSI Command 0x%02x: PHASE_DI\n", id, dev->current_lun, buf[0]); ncr53c810_set_phase(dev, PHASE_DI); p = scsi_device_get_callback(dev->current->tag, dev->current_lun); if (p <= 0LL) { @@ -713,7 +735,7 @@ ncr53c810_do_command(ncr53c810_t *dev, uint8_t id) dev->timer_period += p; return(1); } else if ((sd->Phase == SCSI_PHASE_DATA_OUT) && (sd->BufferLength > 0)) { - ncr53c810_log("(ID=%02i LUN=%02i) SCSI Command 0x%02x: PHASE_DO\n", id, dev->current_lun, buf[0]); + DEBUG("(ID=%02i LUN=%02i) SCSI Command 0x%02x: PHASE_DO\n", id, dev->current_lun, buf[0]); ncr53c810_set_phase(dev, PHASE_DO); p = scsi_device_get_callback(dev->current->tag, dev->current_lun); if (p <= 0LL) { @@ -733,9 +755,10 @@ static void ncr53c810_do_status(ncr53c810_t *dev) { uint8_t status; - ncr53c810_log("Get status len=%d status=%d\n", dev->dbc, dev->status); - if (dev->dbc != 1) - ncr53c810_log("Bad Status move\n"); + DEBUG("Get status len=%d status=%d\n", dev->dbc, dev->status); + if (dev->dbc != 1) { + DEBUG("Bad Status move\n"); + } dev->dbc = 1; status = dev->status; dev->sfbr = status; @@ -750,7 +773,9 @@ static void ncr53c810_do_msgin(ncr53c810_t *dev) { uint32_t len; - ncr53c810_log("Message in len=%d/%d\n", dev->dbc, dev->msg_len); + + DEBUG("Message in len=%d/%d\n", dev->dbc, dev->msg_len); + dev->sfbr = dev->msg[0]; len = dev->msg_len; if (len > dev->dbc) @@ -808,7 +833,8 @@ ncr53c810_skip_msgbytes(ncr53c810_t *dev, unsigned int n) static void ncr53c810_bad_message(ncr53c810_t *dev, uint8_t msg) { - ncr53c810_log("Unimplemented message 0x%02x\n", msg); + DEBUG("Unimplemented message 0x%02x\n", msg); + ncr53c810_set_phase(dev, PHASE_MI); ncr53c810_add_msg_byte(dev, 7); /* MESSAGE REJECT */ dev->msg_action = 0; @@ -820,39 +846,44 @@ ncr53c810_do_msgout(ncr53c810_t *dev, uint8_t id) { uint8_t msg; int len; +#ifdef _LOGGING uint32_t current_tag; +#endif scsi_device_t *sd; + DEBUG("MSG out len=%d\n", dev->dbc); + sd = &SCSIDevices[id][dev->current_lun]; +#ifdef _LOGGING current_tag = id; +#endif - ncr53c810_log("MSG out len=%d\n", dev->dbc); while (dev->dbc) { msg = ncr53c810_get_msgbyte(dev); dev->sfbr = msg; switch (msg) { case 0x04: - ncr53c810_log("MSG: Disconnect\n"); + DEBUG("MSG: Disconnect\n"); ncr53c810_disconnect(dev); break; case 0x08: - ncr53c810_log("MSG: No Operation\n"); + DEBUG("MSG: No Operation\n"); ncr53c810_set_phase(dev, PHASE_CMD); break; case 0x01: len = ncr53c810_get_msgbyte(dev); msg = ncr53c810_get_msgbyte(dev); (void) len; /* avoid a warning about unused variable*/ - ncr53c810_log("Extended message 0x%x (len %d)\n", msg, len); + DEBUG("Extended message 0x%x (len %d)\n", msg, len); switch (msg) { case 1: - ncr53c810_log("SDTR (ignored)\n"); + DEBUG("SDTR (ignored)\n"); ncr53c810_skip_msgbytes(dev, 2); break; case 3: - ncr53c810_log("WDTR (ignored)\n"); + DEBUG("WDTR (ignored)\n"); ncr53c810_skip_msgbytes(dev, 1); break; default: @@ -862,19 +893,19 @@ ncr53c810_do_msgout(ncr53c810_t *dev, uint8_t id) break; case 0x20: /* SIMPLE queue */ id |= ncr53c810_get_msgbyte(dev) | NCR_TAG_VALID; - ncr53c810_log("SIMPLE queue tag=0x%x\n", id & 0xff); + DEBUG("SIMPLE queue tag=0x%x\n", id & 0xff); break; case 0x21: /* HEAD of queue */ - ncr53c810_log("HEAD queue not implemented\n"); + DEBUG("HEAD queue not implemented\n"); id |= ncr53c810_get_msgbyte(dev) | NCR_TAG_VALID; break; case 0x22: /* ORDERED queue */ - ncr53c810_log("ORDERED queue not implemented\n"); + DEBUG("ORDERED queue not implemented\n"); id |= ncr53c810_get_msgbyte(dev) | NCR_TAG_VALID; break; case 0x0d: /* The ABORT TAG message clears the current I/O process only. */ - ncr53c810_log("MSG: ABORT TAG tag=0x%x\n", current_tag); + DEBUG("MSG: ABORT TAG tag=0x%x\n", current_tag); if (sd->CmdBuffer) { free(sd->CmdBuffer); sd->CmdBuffer = NULL; @@ -887,15 +918,15 @@ ncr53c810_do_msgout(ncr53c810_t *dev, uint8_t id) /* The ABORT message clears all I/O processes for the selecting initiator on the specified logical unit of the target. */ if (msg == 0x06) - ncr53c810_log("MSG: ABORT tag=0x%x\n", current_tag); + DEBUG("MSG: ABORT tag=0x%x\n", current_tag); /* The CLEAR QUEUE message clears all I/O processes for all initiators on the specified logical unit of the target. */ if (msg == 0x0e) - ncr53c810_log("MSG: CLEAR QUEUE tag=0x%x\n", current_tag); + DEBUG("MSG: CLEAR QUEUE tag=0x%x\n", current_tag); /* The BUS DEVICE RESET message clears all I/O processes for all initiators on all logical units of the target. */ if (msg == 0x0c) - ncr53c810_log("MSG: BUS DEVICE RESET tag=0x%x\n", current_tag); + DEBUG("MSG: BUS DEVICE RESET tag=0x%x\n", current_tag); /* clear the current I/O process */ if (sd->CmdBuffer) { @@ -910,7 +941,7 @@ ncr53c810_do_msgout(ncr53c810_t *dev, uint8_t id) return; } else { dev->current_lun = msg & 7; - ncr53c810_log("Select LUN %d\n", dev->current_lun); + DEBUG("Select LUN %d\n", dev->current_lun); ncr53c810_set_phase(dev, PHASE_CMD); } break; @@ -925,7 +956,7 @@ ncr53c810_memcpy(ncr53c810_t *dev, uint32_t dest, uint32_t src, int count) int n; uint8_t buf[NCR_BUF_SIZE]; - ncr53c810_log("memcpy dest 0x%08x src 0x%08x count %d\n", dest, src, count); + DEBUG("memcpy dest 0x%08x src 0x%08x count %d\n", dest, src, count); while (count) { n = (count > NCR_BUF_SIZE) ? NCR_BUF_SIZE : count; ncr53c810_read(dev, src, buf, n); @@ -941,9 +972,12 @@ static void ncr53c810_process_script(ncr53c810_t *dev) { uint32_t insn, addr, id, buf[2], dest; - int opcode, insn_processed = 0, reg, operator, cond, jmp, n, i, c; + int opcode, insn_processed = 0, reg, oper, cond, jmp, n, i, c; int32_t offset; - uint8_t op0, op1, data8, mask, data[7], *pp; + uint8_t op0, op1, data8, mask, data[7]; +#ifdef _LOGGING + uint8_t *pp; +#endif dev->sstop = 0; again: @@ -960,28 +994,28 @@ again: return; } addr = read_dword(dev, dev->dsp + 4); - ncr53c810_log("SCRIPTS dsp=%08x opcode %08x arg %08x\n", dev->dsp, insn, addr); + DEBUG("SCRIPTS dsp=%08x opcode %08x arg %08x\n", dev->dsp, insn, addr); dev->dsps = addr; dev->dcmd = insn >> 24; dev->dsp += 8; switch (insn >> 30) { case 0: /* Block move. */ - ncr53c810_log("00: Block move\n"); + DEBUG("00: Block move\n"); if (dev->sist1 & NCR_SIST1_STO) { - ncr53c810_log("Delayed select timeout\n"); + DEBUG("Delayed select timeout\n"); dev->sstop = 1; break; } - ncr53c810_log("Block Move DBC=%d\n", dev->dbc); + DEBUG("Block Move DBC=%d\n", dev->dbc); dev->dbc = insn & 0xffffff; - ncr53c810_log("Block Move DBC=%d now\n", dev->dbc); + DEBUG("Block Move DBC=%d now\n", dev->dbc); /* ??? Set ESA. */ if (insn & (1 << 29)) { /* Indirect addressing. */ /* Should this respect SIOM? */ addr = read_dword(dev, addr); - ncr53c810_log("Indirect Block Move address: %08X\n", addr); + DEBUG("Indirect Block Move address: %08X\n", addr); } else if (insn & (1 << 28)) { /* Table indirect addressing. */ @@ -996,7 +1030,7 @@ again: * table, bits [31:24] */ } if ((dev->sstat1 & PHASE_MASK) != ((insn >> 24) & 7)) { - ncr53c810_log("Wrong phase got %d expected %d\n", + DEBUG("Wrong phase got %d expected %d\n", dev->sstat1 & PHASE_MASK, (insn >> 24) & 7); ncr53c810_script_scsi_interrupt(dev, NCR_SIST0_MA, 0); break; @@ -1004,17 +1038,17 @@ again: dev->dnad = addr; switch (dev->sstat1 & 0x7) { case PHASE_DO: - ncr53c810_log("Data Out Phase\n"); + DEBUG("Data Out Phase\n"); dev->waiting = 0; ncr53c810_do_dma(dev, 1, dev->sdid); break; case PHASE_DI: - ncr53c810_log("Data In Phase\n"); + DEBUG("Data In Phase\n"); dev->waiting = 0; ncr53c810_do_dma(dev, 0, dev->sdid); break; case PHASE_CMD: - ncr53c810_log("Command Phase\n"); + DEBUG("Command Phase\n"); c = ncr53c810_do_command(dev, dev->sdid); if (!c || dev->sstop || dev->waiting || ((dev->sstat1 & 0x7) == PHASE_ST)) @@ -1029,26 +1063,26 @@ again: ncr53c810_script_dma_interrupt(dev, NCR_DSTAT_SSI); return; case PHASE_ST: - ncr53c810_log("Status Phase\n"); + DEBUG("Status Phase\n"); ncr53c810_do_status(dev); break; case PHASE_MO: - ncr53c810_log("MSG Out Phase\n"); + DEBUG("MSG Out Phase\n"); ncr53c810_do_msgout(dev, dev->sdid); break; case PHASE_MI: - ncr53c810_log("MSG In Phase\n"); + DEBUG("MSG In Phase\n"); ncr53c810_do_msgin(dev); break; default: - ncr53c810_log("Unimplemented phase %d\n", dev->sstat1 & PHASE_MASK); + DEBUG("Unimplemented phase %d\n", dev->sstat1 & PHASE_MASK); } dev->dfifo = dev->dbc & 0xff; dev->ctest5 = (dev->ctest5 & 0xfc) | ((dev->dbc >> 8) & 3); break; case 1: /* IO or Read/Write instruction. */ - ncr53c810_log("01: I/O or Read/Write instruction\n"); + DEBUG("01: I/O or Read/Write instruction\n"); opcode = (insn >> 27) & 7; if (opcode < 5) { if (insn & (1 << 25)) @@ -1063,18 +1097,18 @@ again: case 0: /* Select */ dev->sdid = id; if (dev->scntl1 & NCR_SCNTL1_CON) { - ncr53c810_log("Already reselected, jumping to alternative address\n"); + DEBUG("Already reselected, jumping to alternative address\n"); dev->dsp = dev->dnad; break; } dev->sstat0 |= NCR_SSTAT0_WOA; dev->scntl1 &= ~NCR_SCNTL1_IARB; - if (((id == -1) || !scsi_device_present(id, 0))) { + if (!scsi_device_present(id, 0)) { ncr53c810_bad_selection(dev, id); break; } - ncr53c810_log("Selected target %d%s\n", - id, insn & (1 << 24) ? " ATN" : ""); + DEBUG("Selected target %d%s\n", + id, insn & (1 << 24) ? " ATN" : ""); dev->select_id = id << 8; dev->scntl1 |= NCR_SCNTL1_CON; if (insn & (1 << 24)) @@ -1083,33 +1117,37 @@ again: dev->waiting = 0; break; case 1: /* Disconnect */ - ncr53c810_log("Wait Disconnect\n"); + DEBUG("Wait Disconnect\n"); dev->scntl1 &= ~NCR_SCNTL1_CON; break; case 2: /* Wait Reselect */ - ncr53c810_log("Wait Reselect\n"); - if (!ncr53c810_irq_on_rsl(dev)) - dev->waiting = 1; + DEBUG("Wait Reselect\n"); + if (dev->istat & NCR_ISTAT_SIGP) + dev->dsp = dev->dnad; /* If SIGP is set, this command causes an immediate jump to DNAD. */ + else { + if (!ncr53c810_irq_on_rsl(dev)) + dev->waiting = 1; + } break; case 3: /* Set */ - ncr53c810_log("Set%s%s%s%s\n", insn & (1 << 3) ? " ATN" : "", - insn & (1 << 6) ? " ACK" : "", - insn & (1 << 9) ? " TM" : "", - insn & (1 << 10) ? " CC" : ""); + DEBUG("Set%s%s%s%s\n", insn & (1 << 3) ? " ATN" : "", + insn & (1 << 6) ? " ACK" : "", + insn & (1 << 9) ? " TM" : "", + insn & (1 << 10) ? " CC" : ""); if (insn & (1 << 3)) { dev->socl |= NCR_SOCL_ATN; ncr53c810_set_phase(dev, PHASE_MO); } if (insn & (1 << 9)) - ncr53c810_log("Target mode not implemented\n"); + DEBUG("Target mode not implemented\n"); if (insn & (1 << 10)) dev->carry = 1; break; case 4: /* Clear */ - ncr53c810_log("Clear%s%s%s%s\n", insn & (1 << 3) ? " ATN" : "", - insn & (1 << 6) ? " ACK" : "", - insn & (1 << 9) ? " TM" : "", - insn & (1 << 10) ? " CC" : ""); + DEBUG("Clear%s%s%s%s\n", insn & (1 << 3) ? " ATN" : "", + insn & (1 << 6) ? " ACK" : "", + insn & (1 << 9) ? " TM" : "", + insn & (1 << 10) ? " CC" : ""); if (insn & (1 << 3)) dev->socl &= ~NCR_SOCL_ATN; if (insn & (1 << 10)) @@ -1120,7 +1158,7 @@ again: reg = ((insn >> 16) & 0x7f) | (insn & 0x80); data8 = (insn >> 8) & 0xff; opcode = (insn >> 27) & 7; - operator = (insn >> 24) & 7; + oper = (insn >> 24) & 7; op0 = op1 = 0; switch (opcode) { case 5: /* From SFBR */ @@ -1128,12 +1166,12 @@ again: op1 = data8; break; case 6: /* To SFBR */ - if (operator) + if (oper) op0 = ncr53c810_reg_readb(dev, reg); op1 = data8; break; case 7: /* Read-modify-write */ - if (operator) + if (oper) op0 = ncr53c810_reg_readb(dev, reg); if (insn & (1 << 23)) op1 = dev->sfbr; @@ -1142,7 +1180,7 @@ again: break; } - switch (operator) { + switch (oper) { case 0: /* move */ op0 = op1; break; @@ -1191,29 +1229,30 @@ again: break; case 2: /* Transfer Control. */ - ncr53c810_log("02: Transfer Control\n"); + DEBUG("02: Transfer Control\n"); if ((insn & 0x002e0000) == 0) { - ncr53c810_log("NOP\n"); + DEBUG("NOP\n"); break; } if (dev->sist1 & NCR_SIST1_STO) { - ncr53c810_log("Delayed select timeout\n"); + DEBUG("Delayed select timeout\n"); dev->sstop = 1; break; } cond = jmp = (insn & (1 << 19)) != 0; if (cond == jmp && (insn & (1 << 21))) { - ncr53c810_log("Compare carry %d\n", dev->carry == jmp); + DEBUG("Compare carry %d\n", dev->carry == jmp); cond = dev->carry != 0; } if (cond == jmp && (insn & (1 << 17))) { - ncr53c810_log("Compare phase %d %c= %d\n", (dev->sstat1 & PHASE_MASK), - jmp ? '=' : '!', ((insn >> 24) & 7)); + DEBUG("Compare phase %d %c= %d\n", + (dev->sstat1 & PHASE_MASK), + jmp ? '=' : '!', ((insn >> 24) & 7)); cond = (dev->sstat1 & PHASE_MASK) == ((insn >> 24) & 7); } if (cond == jmp && (insn & (1 << 18))) { mask = (~insn >> 8) & 0xff; - ncr53c810_log("Compare data 0x%x & 0x%x %c= 0x%x\n", dev->sfbr, mask, + DEBUG("Compare data 0x%x & 0x%x %c= 0x%x\n", dev->sfbr, mask, jmp ? '=' : '!', insn & mask); cond = (dev->sfbr & mask) == (insn & mask); } @@ -1224,21 +1263,21 @@ again: } switch ((insn >> 27) & 7) { case 0: /* Jump */ - ncr53c810_log("Jump to 0x%08x\n", addr); + DEBUG("Jump to 0x%08x\n", addr); dev->adder = addr; dev->dsp = addr; break; case 1: /* Call */ - ncr53c810_log("Call 0x%08x\n", addr); + DEBUG("Call 0x%08x\n", addr); dev->temp = dev->dsp; dev->dsp = addr; break; case 2: /* Return */ - ncr53c810_log("Return to 0x%08x\n", dev->temp); + DEBUG("Return to 0x%08x\n", dev->temp); dev->dsp = dev->temp; break; case 3: /* Interrupt */ - ncr53c810_log("Interrupt 0x%08x\n", dev->dsps); + DEBUG("Interrupt 0x%08x\n", dev->dsps); if ((insn & (1 << 20)) != 0) { dev->istat |= NCR_ISTAT_INTF; ncr53c810_update_irq(dev); @@ -1246,16 +1285,16 @@ again: ncr53c810_script_dma_interrupt(dev, NCR_DSTAT_SIR); break; default: - ncr53c810_log("Illegal transfer control\n"); + DEBUG("Illegal transfer control\n"); ncr53c810_script_dma_interrupt(dev, NCR_DSTAT_IID); break; } } else - ncr53c810_log("Control condition failed\n"); + DEBUG("Control condition failed\n"); break; case 3: - ncr53c810_log("00: Memory move\n"); + DEBUG("00: Memory move\n"); if ((insn & (1 << 29)) == 0) { /* Memory move. */ /* ??? The docs imply the destination address is loaded into @@ -1265,7 +1304,9 @@ again: dev->dsp += 4; ncr53c810_memcpy(dev, dest, addr, insn & 0xffffff); } else { +#ifdef _LOGGING pp = data; +#endif if (insn & (1 << 28)) addr = dev->dsa + sextract32(addr, 0, 24); @@ -1273,12 +1314,12 @@ again: reg = (insn >> 16) & 0xff; if (insn & (1 << 24)) { DMAPageRead(addr, data, n); - ncr53c810_log("Load reg 0x%x size %d addr 0x%08x = %08x\n", reg, n, addr, + DEBUG("Load reg 0x%x size %d addr 0x%08x = %08x\n", reg, n, addr, *(unsigned *)pp); for (i = 0; i < n; i++) ncr53c810_reg_writeb(dev, reg + i, data[i]); } else { - ncr53c810_log("Store reg 0x%x size %d addr 0x%08x\n", reg, n, addr); + DEBUG("Store reg 0x%x size %d addr 0x%08x\n", reg, n, addr); for (i = 0; i < n; i++) data[i] = ncr53c810_reg_readb(dev, reg + i); DMAPageWrite(addr, data, n); @@ -1287,40 +1328,40 @@ again: break; default: - ncr53c810_log("%02X: Unknown command\n", (uint8_t) (insn >> 30)); + DEBUG("%02X: Unknown command\n", (uint8_t) (insn >> 30)); } dev->timer_period += (40LL * TIMER_USEC); - ncr53c810_log("instructions processed %i\n", insn_processed); + DEBUG("instructions processed %i\n", insn_processed); if (insn_processed > 10000 && !dev->waiting) { /* Some windows drivers make the device spin waiting for a memory location to change. If we have been executed a lot of code then assume this is the case and force an unexpected device disconnect. This is apparently sufficient to beat the drivers into submission. */ - ncr53c810_log("Some windows drivers make the device spin...\n"); + DEBUG("Some windows drivers make the device spin...\n"); if (!(dev->sien0 & NCR_SIST0_UDC)) - ncr53c810_log("inf. loop with UDC masked\n"); + DEBUG("inf. loop with UDC masked\n"); ncr53c810_script_scsi_interrupt(dev, NCR_SIST0_UDC, 0); ncr53c810_disconnect(dev); } else if (!dev->sstop && !dev->waiting) { if (dev->dcntl & NCR_DCNTL_SSM) { - ncr53c810_log("NCR 810: SCRIPTS: Single-step mode\n"); + DEBUG("NCR 810: SCRIPTS: Single-step mode\n"); ncr53c810_script_dma_interrupt(dev, NCR_DSTAT_SSI); } else { - ncr53c810_log("NCR 810: SCRIPTS: Normal mode\n"); + DEBUG("NCR 810: SCRIPTS: Normal mode\n"); if (insn_processed < 100) goto again; } } else { if (dev->sstop) - ncr53c810_log("NCR 810: SCRIPTS: Stopped\n"); + DEBUG("NCR 810: SCRIPTS: Stopped\n"); if (dev->waiting) - ncr53c810_log("NCR 810: SCRIPTS: Waiting\n"); + DEBUG("NCR 810: SCRIPTS: Waiting\n"); } - ncr53c810_log("SCRIPTS execution stopped\n"); + DEBUG("SCRIPTS execution stopped\n"); } @@ -1370,9 +1411,7 @@ ncr53c810_reg_writeb(ncr53c810_t *dev, uint32_t offset, uint8_t val) case addr + 2: dev->name &= 0xff00ffff; dev->name |= val << 16; break; \ case addr + 3: dev->name &= 0x00ffffff; dev->name |= val << 24; break; -#ifdef DEBUG_NCR_REG - ncr53c810_log("Write reg %02x = %02x\n", offset, val); -#endif + DBGLOG(1, "Write reg %02x = %02x\n", offset, val); dev->regop = 1; @@ -1382,7 +1421,7 @@ ncr53c810_reg_writeb(ncr53c810_t *dev, uint32_t offset, uint8_t val) if (val & NCR_SCNTL0_START) { /* Looks like this (turn on bit 4 of SSTAT0 to mark arbitration in progress) is enough to make BIOS v4.x happy. */ - ncr53c810_log("NCR 810: Selecting SCSI ID %i\n", dev->sdid); + DEBUG("NCR 810: Selecting SCSI ID %i\n", dev->sdid); dev->select_id = dev->sdid; dev->sstat0 |= 0x10; } @@ -1391,7 +1430,7 @@ ncr53c810_reg_writeb(ncr53c810_t *dev, uint32_t offset, uint8_t val) dev->scntl1 = val & ~NCR_SCNTL1_SST; if (val & NCR_SCNTL1_IARB) { dev->select_id = dev->sdid; - ncr53c810_log("Arbitration lost\n"); + DEBUG("Arbitration lost\n"); dev->sstat0 |= 0x08; dev->waiting = 0; } @@ -1418,11 +1457,11 @@ ncr53c810_reg_writeb(ncr53c810_t *dev, uint32_t offset, uint8_t val) break; case 0x06: /* SDID */ if ((dev->ssid & 0x80) && (val & 0xf) != (dev->ssid & 0xf)) - ncr53c810_log("Destination ID does not match SSID\n"); + DEBUG("Destination ID does not match SSID\n"); dev->sdid = val & 0xf; break; case 0x07: /* GPREG0 */ - ncr53c810_log("NCR 810: GPREG0 write %02X\n", val); + DEBUG("NCR 810: GPREG0 write %02X\n", val); dev->gpreg0 = val & 0x03; break; case 0x08: /* SFBR */ @@ -1431,7 +1470,7 @@ ncr53c810_reg_writeb(ncr53c810_t *dev, uint32_t offset, uint8_t val) dev->sfbr = val; break; case 0x09: /* SOCL */ - ncr53c810_log("NCR 810: SOCL write %02X\n", val); + DEBUG("NCR 810: SOCL write %02X\n", val); dev->socl = val; break; case 0x0a: case 0x0b: @@ -1442,7 +1481,7 @@ ncr53c810_reg_writeb(ncr53c810_t *dev, uint32_t offset, uint8_t val) return; CASE_SET_REG32(dsa, 0x10) case 0x14: /* ISTAT */ - ncr53c810_log("ISTAT write: %02X\n", val); + DEBUG("ISTAT write: %02X\n", val); tmp = dev->istat; dev->istat = (dev->istat & 0x0f) | (val & 0xf0); if ((val & NCR_ISTAT_ABRT) && !(val & NCR_ISTAT_SRST)) @@ -1452,8 +1491,8 @@ ncr53c810_reg_writeb(ncr53c810_t *dev, uint32_t offset, uint8_t val) ncr53c810_update_irq(dev); } - if (dev->waiting == 1 && val & NCR_ISTAT_SIGP) { - ncr53c810_log("Woken by SIGP\n"); + if ((dev->waiting == 1) && (val & NCR_ISTAT_SIGP)) { + DEBUG("Woken by SIGP\n"); dev->waiting = 0; dev->dsp = dev->dnad; #if 0 @@ -1487,12 +1526,12 @@ ncr53c810_reg_writeb(ncr53c810_t *dev, uint32_t offset, uint8_t val) CASE_SET_REG32(temp, 0x1c) case 0x21: /* CTEST4 */ if (val & 7) - ncr53c810_log("Unimplemented CTEST4-FBL 0x%x\n", val); + DEBUG("Unimplemented CTEST4-FBL 0x%x\n", val); dev->ctest4 = val; break; case 0x22: /* CTEST5 */ if (val & (NCR_CTEST5_ADCK | NCR_CTEST5_BBCK)) - ncr53c810_log("CTEST5 DMA increment not implemented\n"); + DEBUG("CTEST5 DMA increment not implemented\n"); dev->ctest5 = val; break; CASE_SET_REG24(dbc, 0x24) @@ -1521,7 +1560,7 @@ ncr53c810_reg_writeb(ncr53c810_t *dev, uint32_t offset, uint8_t val) dev->dmode = val; break; case 0x39: /* DIEN */ - ncr53c810_log("DIEN write: %02X\n", val); + DEBUG("DIEN write: %02X\n", val); dev->dien = val; ncr53c810_update_irq(dev); break; @@ -1548,7 +1587,7 @@ ncr53c810_reg_writeb(ncr53c810_t *dev, uint32_t offset, uint8_t val) break; case 0x49: /* STIME1 */ if (val & 0xf) { - ncr53c810_log("General purpose timer not implemented\n"); + DEBUG("General purpose timer not implemented\n"); /* ??? Raising the interrupt immediately seems to be sufficient to keep the FreeBSD driver happy. */ ncr53c810_script_scsi_interrupt(dev, 0, NCR_SIST1_GEN); @@ -1562,19 +1601,19 @@ ncr53c810_reg_writeb(ncr53c810_t *dev, uint32_t offset, uint8_t val) break; case 0x4e: /* STEST2 */ if (val & 1) - ncr53c810_log("Low level mode not implemented\n"); + DEBUG("Low level mode not implemented\n"); dev->stest2 = val; break; case 0x4f: /* STEST3 */ if (val & 0x41) - ncr53c810_log("SCSI FIFO test mode not implemented\n"); + DEBUG("SCSI FIFO test mode not implemented\n"); dev->stest3 = val; break; case 0x54: break; CASE_SET_REG32(scratchb, 0x5c) default: - ncr53c810_log("Unhandled writeb 0x%x = 0x%x\n", offset, val); + DEBUG("Unhandled writeb 0x%x = 0x%x\n", offset, val); } #undef CASE_SET_REG24 #undef CASE_SET_REG32 @@ -1600,34 +1639,34 @@ ncr53c810_reg_readb(ncr53c810_t *dev, uint32_t offset) switch (offset) { case 0x00: /* SCNTL0 */ - ncr53c810_log("NCR 810: Read SCNTL0 %02X\n", dev->scntl0); + DEBUG("NCR 810: Read SCNTL0 %02X\n", dev->scntl0); return dev->scntl0; case 0x01: /* SCNTL1 */ - ncr53c810_log("NCR 810: Read SCNTL1 %02X\n", dev->scntl1); + DEBUG("NCR 810: Read SCNTL1 %02X\n", dev->scntl1); return dev->scntl1; case 0x02: /* SCNTL2 */ - ncr53c810_log("NCR 810: Read SCNTL2 %02X\n", dev->scntl2); + DEBUG("NCR 810: Read SCNTL2 %02X\n", dev->scntl2); return dev->scntl2; case 0x03: /* SCNTL3 */ - ncr53c810_log("NCR 810: Read SCNTL3 %02X\n", dev->scntl3); + DEBUG("NCR 810: Read SCNTL3 %02X\n", dev->scntl3); return dev->scntl3; case 0x04: /* SCID */ - ncr53c810_log("NCR 810: Read SCID %02X\n", dev->scid); + DEBUG("NCR 810: Read SCID %02X\n", dev->scid); return dev->scid; case 0x05: /* SXFER */ - ncr53c810_log("NCR 810: Read SXFER %02X\n", dev->sxfer); + DEBUG("NCR 810: Read SXFER %02X\n", dev->sxfer); return dev->sxfer; case 0x06: /* SDID */ - ncr53c810_log("NCR 810: Read SDID %02X\n", dev->sdid); + DEBUG("NCR 810: Read SDID %02X\n", dev->sdid); return dev->sdid; case 0x07: /* GPREG0 */ - ncr53c810_log("NCR 810: Read GPREG0 %02X\n", dev->gpreg0 & 3); + DEBUG("NCR 810: Read GPREG0 %02X\n", dev->gpreg0 & 3); return dev->gpreg0 & 3; case 0x08: /* Revision ID */ - ncr53c810_log("NCR 810: Read REVID 00\n"); + DEBUG("NCR 810: Read REVID 00\n"); return 0x00; case 0xa: /* SSID */ - ncr53c810_log("NCR 810: Read SSID %02X\n", dev->ssid); + DEBUG("NCR 810: Read SSID %02X\n", dev->ssid); return dev->ssid; case 0xb: /* SBCL */ /* Bit 7 = REQ (SREQ/ status) @@ -1639,39 +1678,39 @@ ncr53c810_reg_readb(ncr53c810_t *dev, uint32_t offset) Bit 1 = C/D (SC_D/ status) Bit 0 = I/O (SI_O/ status) */ tmp = (dev->sstat1 & 7); - ncr53c810_log("NCR 810: Read SBCL %02X\n", tmp); + DEBUG("NCR 810: Read SBCL %02X\n", tmp); return tmp; /* For now, return the MSG, C/D, and I/O bits from SSTAT1. */ case 0xc: /* DSTAT */ tmp = dev->dstat | NCR_DSTAT_DFE; if ((dev->istat & NCR_ISTAT_INTF) == 0) dev->dstat = 0; ncr53c810_update_irq(dev); - ncr53c810_log("NCR 810: Read DSTAT %02X\n", tmp); + DEBUG("NCR 810: Read DSTAT %02X\n", tmp); return tmp; case 0x0d: /* SSTAT0 */ - ncr53c810_log("NCR 810: Read SSTAT0 %02X\n", dev->sstat0); + DEBUG("NCR 810: Read SSTAT0 %02X\n", dev->sstat0); return dev->sstat0; case 0x0e: /* SSTAT1 */ - ncr53c810_log("NCR 810: Read SSTAT1 %02X\n", dev->sstat1); + DEBUG("NCR 810: Read SSTAT1 %02X\n", dev->sstat1); return dev->sstat1; case 0x0f: /* SSTAT2 */ - ncr53c810_log("NCR 810: Read SSTAT2 %02X\n", dev->scntl1 & NCR_SCNTL1_CON ? 0 : 2); + DEBUG("NCR 810: Read SSTAT2 %02X\n", dev->scntl1 & NCR_SCNTL1_CON ? 0 : 2); return dev->scntl1 & NCR_SCNTL1_CON ? 0 : 2; CASE_GET_REG32(dsa, 0x10) case 0x14: /* ISTAT */ - ncr53c810_log("NCR 810: Read ISTAT %02X\n", dev->istat); + DEBUG("NCR 810: Read ISTAT %02X\n", dev->istat); return dev->istat; case 0x16: /* MBOX0 */ - ncr53c810_log("NCR 810: Read MBOX0 %02X\n", dev->mbox0); + DEBUG("NCR 810: Read MBOX0 %02X\n", dev->mbox0); return dev->mbox0; case 0x17: /* MBOX1 */ - ncr53c810_log("NCR 810: Read MBOX1 %02X\n", dev->mbox1); + DEBUG("NCR 810: Read MBOX1 %02X\n", dev->mbox1); return dev->mbox1; case 0x18: /* CTEST0 */ - ncr53c810_log("NCR 810: Read CTEST0 FF\n"); + DEBUG("NCR 810: Read CTEST0 FF\n"); return 0xff; case 0x19: /* CTEST1 */ - ncr53c810_log("NCR 810: Read CTEST1 F0\n"); + DEBUG("NCR 810: Read CTEST1 F0\n"); return 0xf0; /* dma fifo empty */ case 0x1a: /* CTEST2 */ tmp = dev->ctest2 | NCR_CTEST2_DACK | NCR_CTEST2_CM; @@ -1679,110 +1718,110 @@ ncr53c810_reg_readb(ncr53c810_t *dev, uint32_t offset) dev->istat &= ~NCR_ISTAT_SIGP; tmp |= NCR_CTEST2_SIGP; } - ncr53c810_log("NCR 810: Read CTEST2 %02X\n", tmp); + DEBUG("NCR 810: Read CTEST2 %02X\n", tmp); return tmp; case 0x1b: /* CTEST3 */ - ncr53c810_log("NCR 810: Read CTEST3 %02X\n", + DEBUG("NCR 810: Read CTEST3 %02X\n", (dev->ctest3 & (0x08 | 0x02 | 0x01)) | dev->chip_rev); return (dev->ctest3 & (0x08 | 0x02 | 0x01)) | dev->chip_rev; CASE_GET_REG32(temp, 0x1c) case 0x20: /* DFIFO */ - ncr53c810_log("NCR 810: Read DFIFO 00\n"); + DEBUG("NCR 810: Read DFIFO 00\n"); return 0; case 0x21: /* CTEST4 */ - ncr53c810_log("NCR 810: Read CTEST4 %02X\n", dev->ctest4); + DEBUG("NCR 810: Read CTEST4 %02X\n", dev->ctest4); return dev->ctest4; case 0x22: /* CTEST5 */ - ncr53c810_log("NCR 810: Read CTEST5 %02X\n", dev->ctest5); + DEBUG("NCR 810: Read CTEST5 %02X\n", dev->ctest5); return dev->ctest5; case 0x23: /* CTEST6 */ - ncr53c810_log("NCR 810: Read CTEST6 00\n"); + DEBUG("NCR 810: Read CTEST6 00\n"); return 0; CASE_GET_REG24(dbc, 0x24) case 0x27: /* DCMD */ - ncr53c810_log("NCR 810: Read DCMD %02X\n", dev->dcmd); + DEBUG("NCR 810: Read DCMD %02X\n", dev->dcmd); return dev->dcmd; CASE_GET_REG32(dnad, 0x28) CASE_GET_REG32(dsp, 0x2c) CASE_GET_REG32(dsps, 0x30) CASE_GET_REG32(scratcha, 0x34) case 0x38: /* DMODE */ - ncr53c810_log("NCR 810: Read DMODE %02X\n", dev->dmode); + DEBUG("NCR 810: Read DMODE %02X\n", dev->dmode); return dev->dmode; case 0x39: /* DIEN */ - ncr53c810_log("NCR 810: Read DIEN %02X\n", dev->dien); + DEBUG("NCR 810: Read DIEN %02X\n", dev->dien); return dev->dien; case 0x3a: /* SBR */ - ncr53c810_log("NCR 810: Read SBR %02X\n", dev->sbr); + DEBUG("NCR 810: Read SBR %02X\n", dev->sbr); return dev->sbr; case 0x3b: /* DCNTL */ - ncr53c810_log("NCR 810: Read DCNTL %02X\n", dev->dcntl); + DEBUG("NCR 810: Read DCNTL %02X\n", dev->dcntl); return dev->dcntl; CASE_GET_REG32(adder, 0x3c) /* ADDER Output (Debug of relative jump address) */ case 0x40: /* SIEN0 */ - ncr53c810_log("NCR 810: Read SIEN0 %02X\n", dev->sien0); + DEBUG("NCR 810: Read SIEN0 %02X\n", dev->sien0); return dev->sien0; case 0x41: /* SIEN1 */ - ncr53c810_log("NCR 810: Read SIEN1 %02X\n", dev->sien1); + DEBUG("NCR 810: Read SIEN1 %02X\n", dev->sien1); return dev->sien1; case 0x42: /* SIST0 */ tmp = dev->sist0; dev->sist0 = 0; ncr53c810_update_irq(dev); - ncr53c810_log("NCR 810: Read SIST0 %02X\n", tmp); + DEBUG("NCR 810: Read SIST0 %02X\n", tmp); return tmp; case 0x43: /* SIST1 */ tmp = dev->sist1; dev->sist1 = 0; ncr53c810_update_irq(dev); - ncr53c810_log("NCR 810: Read SIST1 %02X\n", tmp); + DEBUG("NCR 810: Read SIST1 %02X\n", tmp); return tmp; case 0x46: /* MACNTL */ - ncr53c810_log("NCR 810: Read MACNTL 4F\n"); + DEBUG("NCR 810: Read MACNTL 4F\n"); return 0x4f; case 0x47: /* GPCNTL0 */ - ncr53c810_log("NCR 810: Read GPCNTL0 0F\n"); + DEBUG("NCR 810: Read GPCNTL0 0F\n"); return 0x0f; case 0x48: /* STIME0 */ - ncr53c810_log("NCR 810: Read STIME0 %02X\n", dev->stime0); + DEBUG("NCR 810: Read STIME0 %02X\n", dev->stime0); return dev->stime0; case 0x4a: /* RESPID */ - ncr53c810_log("NCR 810: Read RESPID %02X\n", dev->respid); + DEBUG("NCR 810: Read RESPID %02X\n", dev->respid); return dev->respid; case 0x4c: /* STEST0 */ - ncr53c810_log("NCR 810: Read STEST0 %02X\n", dev->stest1); + DEBUG("NCR 810: Read STEST0 %02X\n", dev->stest1); return 0x00; case 0x4d: /* STEST1 */ - ncr53c810_log("NCR 810: Read STEST1 %02X\n", dev->stest1); + DEBUG("NCR 810: Read STEST1 %02X\n", dev->stest1); return dev->stest1; case 0x4e: /* STEST2 */ - ncr53c810_log("NCR 810: Read STEST2 %02X\n", dev->stest2); + DEBUG("NCR 810: Read STEST2 %02X\n", dev->stest2); return dev->stest2; case 0x4f: /* STEST3 */ - ncr53c810_log("NCR 810: Read STEST3 %02X\n", dev->stest3); + DEBUG("NCR 810: Read STEST3 %02X\n", dev->stest3); return dev->stest3; case 0x50: /* SIDL */ /* This is needed by the linux drivers. We currently only update it during the MSG IN phase. */ - ncr53c810_log("NCR 810: Read SIDL %02X\n", dev->sidl); + DEBUG("NCR 810: Read SIDL %02X\n", dev->sidl); return dev->sidl; case 0x52: /* STEST4 */ - ncr53c810_log("NCR 810: Read STEST4 E0\n"); + DEBUG("NCR 810: Read STEST4 E0\n"); return 0xe0; case 0x58: /* SBDL */ /* Some drivers peek at the data bus during the MSG IN phase. */ if ((dev->sstat1 & PHASE_MASK) == PHASE_MI) { - ncr53c810_log("NCR 810: Read SBDL %02X\n", dev->msg[0]); + DEBUG("NCR 810: Read SBDL %02X\n", dev->msg[0]); return dev->msg[0]; } - ncr53c810_log("NCR 810: Read SBDL 00\n"); + DEBUG("NCR 810: Read SBDL 00\n"); return 0; case 0x59: /* SBDL high */ - ncr53c810_log("NCR 810: Read SBDLH 00\n"); + DEBUG("NCR 810: Read SBDLH 00\n"); return 0; CASE_GET_REG32(scratchb, 0x5c) } - ncr53c810_log("readb 0x%x\n", offset); + DEBUG("readb 0x%x\n", offset); return 0; #undef CASE_GET_REG24 @@ -1830,7 +1869,8 @@ static void ncr53c810_io_writeb(uint16_t addr, uint8_t val, void *p) { ncr53c810_t *dev = (ncr53c810_t *)p; - ncr53c810_reg_writeb(dev, addr & 0xff, val); + + ncr53c810_reg_writeb(dev, addr & 0xff, val); } @@ -1838,9 +1878,10 @@ static void ncr53c810_io_writew(uint16_t addr, uint16_t val, void *p) { ncr53c810_t *dev = (ncr53c810_t *)p; - addr &= 0xff; - ncr53c810_reg_writeb(dev, addr, val & 0xff); - ncr53c810_reg_writeb(dev, addr + 1, (val >> 8) & 0xff); + + addr &= 0xff; + ncr53c810_reg_writeb(dev, addr, val & 0xff); + ncr53c810_reg_writeb(dev, addr + 1, (val >> 8) & 0xff); } @@ -1848,6 +1889,7 @@ static void ncr53c810_io_writel(uint16_t addr, uint32_t val, void *p) { ncr53c810_t *dev = (ncr53c810_t *)p; + addr &= 0xff; ncr53c810_reg_writeb(dev, addr, val & 0xff); ncr53c810_reg_writeb(dev, addr + 1, (val >> 8) & 0xff); @@ -1868,110 +1910,139 @@ ncr53c810_mmio_writeb(uint32_t addr, uint8_t val, void *p) static void ncr53c810_mmio_writew(uint32_t addr, uint16_t val, void *p) { - ncr53c810_t *dev = (ncr53c810_t *)p; - - addr &= 0xff; - ncr53c810_reg_writeb(dev, addr, val & 0xff); - ncr53c810_reg_writeb(dev, addr + 1, (val >> 8) & 0xff); + ncr53c810_t *dev = (ncr53c810_t *)p; + + addr &= 0xff; + ncr53c810_reg_writeb(dev, addr, val & 0xff); + ncr53c810_reg_writeb(dev, addr + 1, (val >> 8) & 0xff); } static void ncr53c810_mmio_writel(uint32_t addr, uint32_t val, void *p) { - ncr53c810_t *dev = (ncr53c810_t *)p; + ncr53c810_t *dev = (ncr53c810_t *)p; - addr &= 0xff; - ncr53c810_reg_writeb(dev, addr, val & 0xff); - ncr53c810_reg_writeb(dev, addr + 1, (val >> 8) & 0xff); - ncr53c810_reg_writeb(dev, addr + 2, (val >> 16) & 0xff); - ncr53c810_reg_writeb(dev, addr + 3, (val >> 24) & 0xff); + addr &= 0xff; + ncr53c810_reg_writeb(dev, addr, val & 0xff); + ncr53c810_reg_writeb(dev, addr + 1, (val >> 8) & 0xff); + ncr53c810_reg_writeb(dev, addr + 2, (val >> 16) & 0xff); + ncr53c810_reg_writeb(dev, addr + 3, (val >> 24) & 0xff); } static uint8_t ncr53c810_mmio_readb(uint32_t addr, void *p) { - ncr53c810_t *dev = (ncr53c810_t *)p; - - return ncr53c810_reg_readb(dev, addr & 0xff); + ncr53c810_t *dev = (ncr53c810_t *)p; + + return ncr53c810_reg_readb(dev, addr & 0xff); } static uint16_t ncr53c810_mmio_readw(uint32_t addr, void *p) { - ncr53c810_t *dev = (ncr53c810_t *)p; - uint16_t val; - - addr &= 0xff; - val = ncr53c810_reg_readb(dev, addr); - val |= ncr53c810_reg_readb(dev, addr + 1) << 8; - return val; + ncr53c810_t *dev = (ncr53c810_t *)p; + uint16_t val; + + addr &= 0xff; + val = ncr53c810_reg_readb(dev, addr); + val |= ncr53c810_reg_readb(dev, addr + 1) << 8; + + return val; } static uint32_t ncr53c810_mmio_readl(uint32_t addr, void *p) { - ncr53c810_t *dev = (ncr53c810_t *)p; - uint32_t val; - - addr &= 0xff; - val = ncr53c810_reg_readb(dev, addr); - val |= ncr53c810_reg_readb(dev, addr + 1) << 8; - val |= ncr53c810_reg_readb(dev, addr + 2) << 16; - val |= ncr53c810_reg_readb(dev, addr + 3) << 24; - return val; + ncr53c810_t *dev = (ncr53c810_t *)p; + uint32_t val; + + addr &= 0xff; + val = ncr53c810_reg_readb(dev, addr); + val |= ncr53c810_reg_readb(dev, addr + 1) << 8; + val |= ncr53c810_reg_readb(dev, addr + 2) << 16; + val |= ncr53c810_reg_readb(dev, addr + 3) << 24; + + return val; } static void ncr53c810_io_set(ncr53c810_t *dev, uint32_t base, uint16_t len) { - ncr53c810_log("NCR53c810: [PCI] Setting I/O handler at %04X\n", base); - io_sethandler(base, len, - ncr53c810_io_readb, ncr53c810_io_readw, ncr53c810_io_readl, - ncr53c810_io_writeb, ncr53c810_io_writew, ncr53c810_io_writel, dev); + DEBUG("NCR53c810: [PCI] Setting I/O handler at %04X\n", base); + + io_sethandler(base, len, + ncr53c810_io_readb,ncr53c810_io_readw,ncr53c810_io_readl, + ncr53c810_io_writeb,ncr53c810_io_writew,ncr53c810_io_writel, dev); } static void ncr53c810_io_remove(ncr53c810_t *dev, uint32_t base, uint16_t len) { - ncr53c810_log("NCR53c810: Removing I/O handler at %04X\n", base); - io_removehandler(base, len, - ncr53c810_io_readb, ncr53c810_io_readw, ncr53c810_io_readl, - ncr53c810_io_writeb, ncr53c810_io_writew, ncr53c810_io_writel, dev); + DEBUG("NCR53c810: Removing I/O handler at %04X\n", base); + + io_removehandler(base, len, + ncr53c810_io_readb,ncr53c810_io_readw,ncr53c810_io_readl, + ncr53c810_io_writeb,ncr53c810_io_writew,ncr53c810_io_writel, dev); } static void ncr53c810_mem_init(ncr53c810_t *dev, uint32_t addr) { - mem_mapping_add(&dev->mmio_mapping, addr, 0x100, - ncr53c810_mmio_readb, ncr53c810_mmio_readw, ncr53c810_mmio_readl, - ncr53c810_mmio_writeb, ncr53c810_mmio_writew, ncr53c810_mmio_writel, - NULL, MEM_MAPPING_EXTERNAL, dev); + mem_map_add(&dev->mmio_mapping, addr, 0x100, + ncr53c810_mmio_readb, ncr53c810_mmio_readw, ncr53c810_mmio_readl, + ncr53c810_mmio_writeb, ncr53c810_mmio_writew, ncr53c810_mmio_writel, + NULL, MEM_MAPPING_EXTERNAL, dev); } static void ncr53c810_mem_set_addr(ncr53c810_t *dev, uint32_t base) { - mem_mapping_set_addr(&dev->mmio_mapping, base, 0x100); + mem_map_set_addr(&dev->mmio_mapping, base, 0x100); } static void ncr53c810_mem_disable(ncr53c810_t *dev) { - mem_mapping_disable(&dev->mmio_mapping); + mem_map_disable(&dev->mmio_mapping); } uint8_t ncr53c810_pci_regs[256]; +#if USE_PCI_BAR +bar_t ncr53c810_pci_bar[3]; + + +static void +ncr53c810_bios_update(ncr53c810_t *dev) +{ + int bios_enabled = ncr53c810_pci_bar[2].addr_regs[0] & 0x01; + + if (!dev->has_bios) + return; + + /* PCI BIOS stuff, just enable_disable. */ + if ((dev->bios_addr > 0) && bios_enabled) { + mem_map_enable(&dev->bios.mapping); + mem_map_set_addr(&dev->bios.mapping, + dev->bios_addr, 0x4000); + DEBUG("NCR53c810: BIOS now at: %06X\n", dev->bios_addr); + } else { + DEBUG("NCR53c810: BIOS disabled\n"); + mem_map_disable(&dev->bios.mapping); + } +} +#else bar_t ncr53c810_pci_bar[2]; +#endif static uint8_t @@ -1979,11 +2050,15 @@ ncr53c810_pci_read(int func, int addr, void *p) { ncr53c810_t *dev = (ncr53c810_t *)p; - ncr53c810_log("NCR53c810: Reading register %02X\n", addr & 0xff); + DEBUG("NCR53c810: Reading register %02X\n", addr & 0xff); - if ((addr >= 0x80) && (addr <= 0xDF)) { +#if USE_PCI_BAR + if ((addr >= 0x30) && (addr <= 0x33) && !dev->has_bios) + return 0x00; +#endif + + if ((addr >= 0x80) && (addr <= 0xDF)) return ncr53c810_reg_readb(dev, addr & 0x7F); - } switch (addr) { case 0x00: @@ -2037,6 +2112,19 @@ ncr53c810_pci_read(int func, int addr, void *p) return 0x01; case 0x2F: return 0x00; +#if USE_PCI_BAR + case 0x30: /* PCI_ROMBAR */ + return ncr53c810_pci_bar[2].addr_regs[0] & 0x01; + case 0x31: /* PCI_ROMBAR 15:11 */ + return ncr53c810_pci_bar[2].addr_regs[1]; + break; + case 0x32: /* PCI_ROMBAR 23:16 */ + return ncr53c810_pci_bar[2].addr_regs[2]; + break; + case 0x33: /* PCI_ROMBAR 31:24 */ + return ncr53c810_pci_bar[2].addr_regs[3]; + break; +#endif case 0x3C: return dev->irq; case 0x3D: @@ -2057,7 +2145,12 @@ ncr53c810_pci_write(int func, int addr, uint8_t val, void *p) ncr53c810_t *dev = (ncr53c810_t *)p; uint8_t valxor; - ncr53c810_log("NCR53c810: Write value %02X to register %02X\n", val, addr & 0xff); + DEBUG("NCR53c810: Write value %02X to register %02X\n", val, addr & 0xff); + +#if USE_PCI_BAR + if ((addr >= 0x30) && (addr <= 0x33) && !dev->has_bios) + return; +#endif if ((addr >= 0x80) && (addr <= 0xDF)) { ncr53c810_reg_writeb(dev, addr & 0x7F, val); @@ -2101,13 +2194,14 @@ ncr53c810_pci_write(int func, int addr, uint8_t val, void *p) /* Then let's calculate the new I/O base. */ ncr53c810_pci_bar[0].addr &= 0xff00; dev->PCIBase = ncr53c810_pci_bar[0].addr; + /* Log the new base. */ - ncr53c810_log("NCR53c810: New I/O base is %04X\n" , dev->PCIBase); + DEBUG("NCR53c810: New I/O base is %04X\n" , dev->PCIBase); + /* We're done, so get out of the here. */ if (ncr53c810_pci_regs[4] & PCI_COMMAND_IO) { - if (dev->PCIBase != 0) { + if (dev->PCIBase != 0) ncr53c810_io_set(dev, dev->PCIBase, 0x0100); - } } return; @@ -2119,16 +2213,33 @@ ncr53c810_pci_write(int func, int addr, uint8_t val, void *p) ncr53c810_pci_bar[1].addr_regs[addr & 3] = val; /* Then let's calculate the new I/O base. */ dev->MMIOBase = ncr53c810_pci_bar[1].addr & 0xffffff00; + /* Log the new base. */ - ncr53c810_log("NCR53c810: New MMIO base is %08X\n" , dev->MMIOBase); + DEBUG("NCR53c810: New MMIO base is %08X\n" , dev->MMIOBase); + /* We're done, so get out of the here. */ if (ncr53c810_pci_regs[4] & PCI_COMMAND_MEM) { - if (dev->MMIOBase != 0) { + if (dev->MMIOBase != 0) ncr53c810_mem_set_addr(dev, dev->MMIOBase); - } } return; +#if USE_PCI_BAR + case 0x30: /* PCI_ROMBAR */ + case 0x31: /* PCI_ROMBAR */ + case 0x32: /* PCI_ROMBAR */ + case 0x33: /* PCI_ROMBAR */ + ncr53c810_pci_bar[2].addr_regs[addr & 3] = val; + ncr53c810_pci_bar[2].addr &= 0xffffc001; + dev->bios_addr = ncr53c810_pci_bar[2].addr & 0xffffc000; + + DEBUG("NCR53c810: BIOS BAR %02X = NOW %02X (%02X)\n", + addr&3, ncr53c810_pci_bar[2].addr_regs[addr & 3], val); + + ncr53c810_bios_update(dev); + return; +#endif + case 0x3C: ncr53c810_pci_regs[addr] = val; dev->irq = val; @@ -2142,7 +2253,7 @@ ncr53c810_init(const device_t *info) { ncr53c810_t *dev; - dev = malloc(sizeof(ncr53c810_t)); + dev = (ncr53c810_t *)mem_alloc(sizeof(ncr53c810_t)); memset(dev, 0x00, sizeof(ncr53c810_t)); dev->chip_rev = 0; @@ -2160,6 +2271,23 @@ ncr53c810_init(const device_t *info) timer_add(ncr53c810_callback, &dev->timer_period, &dev->timer_enabled, dev); + dev->has_bios = device_get_config_int("bios"); + + /* Enable our BIOS space in PCI, if needed. */ +#if USE_PCI_BAR + if (dev->has_bios) { + dev->bios_mask = 0xffffc000; + rom_init(&dev->bios, NCR53C810_ROM, 0xc8000, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL); + ncr53c810_pci_bar[2].addr = 0xFFFFC000; + mem_map_disable(&dev->bios.mapping); + } else + ncr53c810_pci_bar[2].addr = 0; +#else + if (dev->has_bios) + rom_init(&dev->bios, NCR53C810_ROM, + 0xc8000, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL); +#endif + return(dev); } @@ -2176,13 +2304,20 @@ ncr53c810_close(void *priv) } -const device_t ncr53c810_pci_device = -{ +static const device_config_t ncr53c810_pci_config[] = { + { + "bios", "Enable BIOS", CONFIG_BINARY, "", 0 + }, + { + "", "", -1 + } +}; + +const device_t ncr53c810_pci_device = { "NCR 53c810 (SCSI)", DEVICE_PCI, 0, ncr53c810_init, ncr53c810_close, NULL, - NULL, - NULL, NULL, NULL, - NULL + NULL, NULL, NULL, NULL, + ncr53c810_pci_config }; diff --git a/src/devices/scsi/scsi_x54x.c b/src/devices/scsi/scsi_x54x.c index 175bf81..35a8f1d 100644 --- a/src/devices/scsi/scsi_x54x.c +++ b/src/devices/scsi/scsi_x54x.c @@ -8,11 +8,11 @@ * * Implementation of the code common to the AHA-154x series of * SCSI Host Adapters made by Adaptec, Inc. and the BusLogic - * series of SCSI Host Adapters made by Mylex. + * series of SCSI Host Adapters made by Buslogic (now Mylex.) * * These controllers were designed for various buses. * - * Version: @(#)scsi_x54x.c 1.0.11 2018/05/06 + * Version: @(#)scsi_x54x.c 1.0.12 2018/10/05 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -44,8 +44,8 @@ #include #include #include -#include #include +#define dbglog scsi_dev_log #include "../../emu.h" #include "../../io.h" #include "../../mem.h" @@ -83,25 +83,22 @@ x54x_irq(x54x_t *dev, int set) irq = dev->Irq; if (dev->bus & DEVICE_PCI) { - scsi_dev_log("PCI IRQ: %02X, PCI_INTA\n", dev->pci_slot); - if (set) { + DEBUG("PCI IRQ: %02X, PCI_INTA\n", dev->pci_slot); + if (set) pci_set_irq(dev->pci_slot, PCI_INTA); - } else { + else pci_clear_irq(dev->pci_slot, PCI_INTA); - } } else { if (set) { if (dev->interrupt_type) int_type = dev->interrupt_type(dev); - if (int_type) { + if (int_type) picintlevel(1 << irq); - } else { + else picint(1 << irq); - } - } else { + } else picintc(1 << irq); - } } } @@ -110,20 +107,18 @@ static void raise_irq(x54x_t *dev, int suppress, uint8_t Interrupt) { if (Interrupt & (INTR_MBIF | INTR_MBOA)) { - if (! (dev->Interrupt & INTR_HACC)) { + if (! (dev->Interrupt & INTR_HACC)) dev->Interrupt |= Interrupt; /* Report now. */ - } else { + else dev->PendingInterrupt |= Interrupt; /* Report later. */ - } } else if (Interrupt & INTR_HACC) { if (dev->Interrupt == 0 || dev->Interrupt == (INTR_ANY | INTR_HACC)) { - scsi_dev_log("%s: RaiseInterrupt(): Interrupt=%02X\n", - dev->name, dev->Interrupt); + DEBUG("%s: RaiseInterrupt(): Interrupt=%02X\n", + dev->name, dev->Interrupt); } dev->Interrupt |= Interrupt; - } else { - scsi_dev_log("%s: RaiseInterrupt(): Invalid interrupt state!\n", dev->name); - } + } else + DEBUG("%s: RaiseInterrupt(): Invalid interrupt state!\n", dev->name); dev->Interrupt |= INTR_ANY; @@ -135,16 +130,17 @@ raise_irq(x54x_t *dev, int suppress, uint8_t Interrupt) static void clear_irq(x54x_t *dev) { - dev->Interrupt = 0; - scsi_dev_log("%s: lowering IRQ %i (stat 0x%02x)\n", + DEBUG("%s: lowering IRQ %i (stat 0x%02x)\n", dev->name, dev->Irq, dev->Interrupt); + + dev->Interrupt = 0; + x54x_irq(dev, 0); if (dev->PendingInterrupt) { - scsi_dev_log("%s: Raising Interrupt 0x%02X (Pending)\n", - dev->name, dev->Interrupt); - if (dev->MailboxOutInterrupts || !(dev->Interrupt & INTR_MBOA)) { + DEBUG("%s: Raising Interrupt 0x%02X (Pending)\n", + dev->name, dev->Interrupt); + if (dev->MailboxOutInterrupts || !(dev->Interrupt & INTR_MBOA)) raise_irq(dev, 0, dev->PendingInterrupt); - } dev->PendingInterrupt = 0; } } @@ -153,9 +149,8 @@ clear_irq(x54x_t *dev) static void target_check(uint8_t id, uint8_t lun) { - if (! scsi_device_valid(id, lun)) { - fatal("BIOS INT13 device on %02i:%02i has disappeared\n", id, lun); - } + if (! scsi_device_valid(id, lun)) + fatal("BIOS INT13 device on ID %02i:%02i has disappeared\n", id, lun); } @@ -245,8 +240,8 @@ x54x_bios_command_08(uint8_t id, uint8_t lun, uint8_t *buffer) buffer[i] = rcbuf[i]; for (i=4; i<6; i++) buffer[i] = rcbuf[(i + 2) ^ 1]; - scsi_dev_log("BIOS Command 0x08: %02X %02X %02X %02X %02X %02X\n", - buffer[0], buffer[1], buffer[2], buffer[3], buffer[4], buffer[5]); + DEBUG("BIOS Command 0x08: %02X %02X %02X %02X %02X %02X\n", + buffer[0], buffer[1], buffer[2], buffer[3], buffer[4], buffer[5]); return(0); } @@ -269,8 +264,8 @@ x54x_bios_command_15(uint8_t id, uint8_t lun, uint8_t *buffer) scsi_device_type_data(id, lun, &(buffer[4]), &(buffer[5])); - scsi_dev_log("BIOS Command 0x15: %02X %02X %02X %02X %02X %02X\n", - buffer[0], buffer[1], buffer[2], buffer[3], buffer[4], buffer[5]); + DEBUG("BIOS Command 0x15: %02X %02X %02X %02X %02X %02X\n", + buffer[0], buffer[1], buffer[2], buffer[3], buffer[4], buffer[5]); return(sc); } @@ -292,11 +287,16 @@ x54x_bios_command(x54x_t *x54x, uint8_t max_id, BIOSCMD *cmd, int8_t islba) else lba = (cmd->u.chs.cyl << 9) + (cmd->u.chs.head << 5) + cmd->u.chs.sec; - scsi_dev_log("BIOS Command = 0x%02X\n", cmd->command); + DEBUG("BIOS Command = 0x%02X\n", cmd->command); if ((cmd->id > max_id) || (cmd->lun > 7)) { - scsi_dev_log("BIOS Target ID %i or LUN %i are above maximum\n", - cmd->id, cmd->lun); + DEBUG("BIOS Target ID %i or LUN %i are above maximum\n", + cmd->id, cmd->lun); + return(0x80); + } + + if (cmd->lun) { + DEBUG("BIOS Target LUN is not 0\n"); return(0x80); } @@ -305,21 +305,21 @@ x54x_bios_command(x54x_t *x54x, uint8_t max_id, BIOSCMD *cmd, int8_t islba) dev->BufferLength = 0; if (! scsi_device_present(cmd->id, cmd->lun)) { - scsi_dev_log("BIOS Target ID %i and LUN %i have no device attached\n", - cmd->id, cmd->lun); + DEBUG("BIOS Target ID %i and LUN %i have no device attached\n", + cmd->id, cmd->lun); return(0x80); } if ((dev->LunType == SCSI_CDROM) && !x54x->cdrom_boot) { - scsi_dev_log("BIOS Target ID %i and LUN %i is CD-ROM on unsupported BIOS\n", - cmd->id, cmd->lun); + DEBUG("BIOS Target ID %i and LUN %i is CD-ROM on unsupported BIOS\n", + cmd->id, cmd->lun); return(0x80); } dma_address = ADDR_TO_U32(cmd->dma_address); - scsi_dev_log("BIOS Data Buffer write: length %d, pointer 0x%04X\n", - sector_len, dma_address); + DEBUG("BIOS Data Buffer write: length %d, pointer 0x%04X\n", + sector_len, dma_address); if (dev->CmdBuffer != NULL) { free(dev->CmdBuffer); @@ -339,11 +339,11 @@ x54x_bios_command(x54x_t *x54x, uint8_t max_id, BIOSCMD *cmd, int8_t islba) * indication is given. */ dev->BufferLength = 14; - dev->CmdBuffer = (uint8_t *)malloc(14); + dev->CmdBuffer = (uint8_t *)mem_alloc(14); memset(dev->CmdBuffer, 0x00, 14); if (sector_len > 0) { - scsi_dev_log("BIOS DMA: Reading 14 bytes at %08X\n", + DEBUG("BIOS DMA: Reading 14 bytes at %08X\n", dma_address); DMAPageWrite(dma_address, scsi_device_sense(cmd->id, cmd->lun), 14); @@ -369,21 +369,19 @@ x54x_bios_command(x54x_t *x54x, uint8_t max_id, BIOSCMD *cmd, int8_t islba) cdb[5] = lba & 0xff; cdb[7] = 0; cdb[8] = sector_len; -#if 0 - scsi_dev_log("BIOS CMD(READ, %08lx, %d)\n", lba, cmd->secount); -#endif + DBGLOG(1, "BIOS CMD(READ, %08lx, %d)\n", lba, cmd->secount); - scsi_device_command_phase0(cmd->id, cmd->lun, 12, cdb); + scsi_device_command_phase0(cmd->id, cmd->lun, cdb); if (dev->Phase == SCSI_PHASE_STATUS) goto skip_read_phase1; - dev->CmdBuffer = (uint8_t *)malloc(dev->BufferLength); + dev->CmdBuffer = (uint8_t *)mem_alloc(dev->BufferLength); scsi_device_command_phase1(cmd->id, cmd->lun); if (sector_len > 0) { - scsi_dev_log("BIOS DMA: Reading %i bytes at %08X\n", - dev->BufferLength, dma_address); + DEBUG("BIOS DMA: Reading %i bytes at %08X\n", + dev->BufferLength, dma_address); DMAPageWrite(dma_address, dev->CmdBuffer, dev->BufferLength); } @@ -409,20 +407,18 @@ skip_read_phase1: cdb[5] = lba & 0xff; cdb[7] = 0; cdb[8] = sector_len; -#if 0 - scsi_dev_log("BIOS CMD(WRITE, %08lx, %d)\n", lba, cmd->secount); -#endif + DBGLOG(1, "BIOS CMD(WRITE, %08lx, %d)\n", lba, cmd->secount); - scsi_device_command_phase0(cmd->id, cmd->lun, 12, cdb); + scsi_device_command_phase0(cmd->id, cmd->lun, cdb); if (dev->Phase == SCSI_PHASE_STATUS) goto skip_write_phase1; - dev->CmdBuffer = (uint8_t *)malloc(dev->BufferLength); + dev->CmdBuffer = (uint8_t *)mem_alloc(dev->BufferLength); if (sector_len > 0) { - scsi_dev_log("BIOS DMA: Reading %i bytes at %08X\n", - dev->BufferLength, dma_address); + DEBUG("BIOS DMA: Reading %i bytes at %08X\n", + dev->BufferLength, dma_address); DMAPageRead(dma_address, dev->CmdBuffer, dev->BufferLength); } @@ -449,7 +445,7 @@ skip_write_phase1: cdb[7] = 0; cdb[8] = sector_len; - scsi_device_command_phase0(cmd->id, cmd->lun, 12, cdb); + scsi_device_command_phase0(cmd->id, cmd->lun, cdb); return(completion_code(scsi_device_sense(cmd->id, cmd->lun))); @@ -467,7 +463,7 @@ skip_write_phase1: cdb[0] = GPCMD_FORMAT_UNIT; cdb[1] = (cmd->lun & 7) << 5; - scsi_device_command_phase0(cmd->id, cmd->lun, 12, cdb); + scsi_device_command_phase0(cmd->id, cmd->lun, cdb); return(completion_code(scsi_device_sense(cmd->id, cmd->lun))); @@ -475,12 +471,12 @@ skip_write_phase1: target_check(cmd->id, cmd->lun); dev->BufferLength = 6; - dev->CmdBuffer = (uint8_t *)malloc(dev->BufferLength); + dev->CmdBuffer = (uint8_t *)mem_alloc(dev->BufferLength); memset(dev->CmdBuffer, 0x00, dev->BufferLength); ret = x54x_bios_command_08(cmd->id, cmd->lun, dev->CmdBuffer); - scsi_dev_log("BIOS DMA: Reading 6 bytes at %08X\n", dma_address); + DEBUG("BIOS DMA: Reading 6 bytes at %08X\n", dma_address); DMAPageWrite(dma_address, dev->CmdBuffer, 4 /* dev->BufferLength */); @@ -505,7 +501,7 @@ skip_write_phase1: cdb[4] = (lba >> 8) & 0xff; cdb[5] = lba & 0xff; - scsi_device_command_phase0(cmd->id, cmd->lun, 12, cdb); + scsi_device_command_phase0(cmd->id, cmd->lun, cdb); return((dev->Status == SCSI_STATUS_OK) ? 1 : 0); @@ -519,7 +515,7 @@ skip_write_phase1: cdb[0] = GPCMD_TEST_UNIT_READY; cdb[1] = (cmd->lun & 7) << 5; - scsi_device_command_phase0(cmd->id, cmd->lun, 12, cdb); + scsi_device_command_phase0(cmd->id, cmd->lun, cdb); return(completion_code(scsi_device_sense(cmd->id, cmd->lun))); @@ -529,7 +525,7 @@ skip_write_phase1: cdb[0] = GPCMD_REZERO_UNIT; cdb[1] = (cmd->lun & 7) << 5; - scsi_device_command_phase0(cmd->id, cmd->lun, 12, cdb); + scsi_device_command_phase0(cmd->id, cmd->lun, cdb); return(completion_code(scsi_device_sense(cmd->id, cmd->lun))); @@ -541,12 +537,12 @@ skip_write_phase1: target_check(cmd->id, cmd->lun); dev->BufferLength = 6; - dev->CmdBuffer = (uint8_t *)malloc(dev->BufferLength); + dev->CmdBuffer = (uint8_t *)mem_alloc(dev->BufferLength); memset(dev->CmdBuffer, 0x00, dev->BufferLength); ret = x54x_bios_command_15(cmd->id, cmd->lun, dev->CmdBuffer); - scsi_dev_log("BIOS DMA: Reading 6 bytes at %08X\n", dma_address); + DEBUG("BIOS DMA: Reading 6 bytes at %08X\n", dma_address); DMAPageWrite(dma_address, dev->CmdBuffer, 4 /* dev->BufferLength */); @@ -558,11 +554,11 @@ skip_write_phase1: return(ret); default: - scsi_dev_log("BIOS: Unimplemented command: %02X\n", cmd->command); + DEBUG("BIOS: Unimplemented command: %02X\n", cmd->command); return(1); } - scsi_dev_log("BIOS Request complete\n"); + DEBUG("BIOS Request complete\n"); } @@ -574,13 +570,12 @@ x54x_cmd_done(x54x_t *dev, int suppress) dev->DataReply = 0; dev->Status |= STAT_IDLE; - if (dev->ven_cmd_is_fast) { + if (dev->ven_cmd_is_fast) fast = dev->ven_cmd_is_fast(dev); - } if ((dev->Command != CMD_START_SCSI) || fast) { dev->Status &= ~STAT_DFULL; - scsi_dev_log("%s: Raising IRQ %i\n", dev->name, dev->Irq); + DEBUG("%s: Raising IRQ %i\n", dev->name, dev->Irq); raise_irq(dev, suppress, INTR_HACC); } @@ -609,7 +604,7 @@ x54x_mbi_setup(x54x_t *dev, uint32_t CCBPointer, CCBU *CmdBlock, req->TargetStatus = TargetStatus; req->MailboxCompletionCode = mbcc; - scsi_dev_log("Mailbox in setup\n"); + DEBUG("Mailbox in setup\n"); } @@ -619,7 +614,9 @@ x54x_ccb(x54x_t *dev) Req_t *req = &dev->Req; /* Rewrite the CCB up to the CDB. */ - scsi_dev_log("CCB completion code and statuses rewritten (pointer %08X)\n", req->CCBPointer); + DEBUG("CCB completion code and statuses rewritten (pointer %08X)\n", + req->CCBPointer); + DMAPageWrite(req->CCBPointer + 0x000D, &(req->MailboxCompletionCode), 1); DMAPageWrite(req->CCBPointer + 0x000E, &(req->HostStatus), 1); DMAPageWrite(req->CCBPointer + 0x000F, &(req->TargetStatus), 1); @@ -650,32 +647,32 @@ x54x_mbi(x54x_t *dev) CmdBlock->common.TargetStatus = TargetStatus; /* Rewrite the CCB up to the CDB. */ - scsi_dev_log("CCB statuses rewritten (pointer %08X)\n", req->CCBPointer); + DEBUG("CCB statuses rewritten (pointer %08X)\n", req->CCBPointer); DMAPageWrite(req->CCBPointer + 0x000E, &(req->HostStatus), 1); DMAPageWrite(req->CCBPointer + 0x000F, &(req->TargetStatus), 1); x54x_add_to_period(2); } else { - scsi_dev_log("Mailbox not found!\n"); + DEBUG("Mailbox not found!\n"); } - scsi_dev_log("Host Status 0x%02X, Target Status 0x%02X\n",HostStatus,TargetStatus); + DEBUG("Host Status 0x%02X, Target Status 0x%02X\n",HostStatus,TargetStatus); if (dev->Mbx24bit) { U32_TO_ADDR(CCBPointer, req->CCBPointer); - scsi_dev_log("Mailbox 24-bit: Status=0x%02X, CCB at 0x%04X\n", req->MailboxCompletionCode, CCBPointer); + DEBUG("Mailbox 24-bit: Status=0x%02X, CCB at 0x%04X\n", req->MailboxCompletionCode, CCBPointer); DMAPageWrite(Incoming, &(req->MailboxCompletionCode), 1); DMAPageWrite(Incoming + 1, (uint8_t *)&CCBPointer, 3); x54x_add_to_period(4); - scsi_dev_log("%i bytes of 24-bit mailbox written to: %08X\n", sizeof(Mailbox_t), Incoming); + DEBUG("%i bytes of 24-bit mailbox written to: %08X\n", sizeof(Mailbox_t), Incoming); } else { U32_TO_ADDR(CCBPointer, req->CCBPointer); - scsi_dev_log("Mailbox 32-bit: Status=0x%02X, CCB at 0x%04X\n", req->MailboxCompletionCode, CCBPointer); + DEBUG("Mailbox 32-bit: Status=0x%02X, CCB at 0x%04X\n", req->MailboxCompletionCode, CCBPointer); DMAPageWrite(Incoming, (uint8_t *)&(req->CCBPointer), 4); DMAPageWrite(Incoming + 4, &(req->HostStatus), 1); DMAPageWrite(Incoming + 5, &(req->TargetStatus), 1); DMAPageWrite(Incoming + 7, &(req->MailboxCompletionCode), 1); x54x_add_to_period(7); - scsi_dev_log("%i bytes of 32-bit mailbox written to: %08X\n", sizeof(Mailbox32_t), Incoming); + DEBUG("%i bytes of 32-bit mailbox written to: %08X\n", sizeof(Mailbox32_t), Incoming); } dev->MailboxInPosCur++; @@ -698,7 +695,7 @@ x54x_rd_sge(int Is24bit, uint32_t Address, SGE32 *SG) x54x_add_to_period(sizeof(SGE)); /* Convert the 24-bit entries into 32-bit entries. */ - scsi_dev_log("Read S/G block: %06X, %06X\n", SGE24.Segment, SGE24.SegmentPointer); + DEBUG("Read S/G block: %06X, %06X\n", SGE24.Segment, SGE24.SegmentPointer); SG->Segment = ADDR_TO_U32(SGE24.Segment); SG->SegmentPointer = ADDR_TO_U32(SGE24.SegmentPointer); } else { @@ -714,19 +711,18 @@ x54x_get_length(Req_t *req, int Is24bit) uint32_t DataPointer, DataLength; uint32_t SGEntryLength = (Is24bit ? sizeof(SGE) : sizeof(SGE32)); SGE32 SGBuffer; - uint32_t DataToTransfer = 0; - uint32_t i = 0; + uint32_t DataToTransfer = 0, i = 0; if (Is24bit) { - DataPointer = ADDR_TO_U32(req->CmdBlock.old.DataPointer); - DataLength = ADDR_TO_U32(req->CmdBlock.old.DataLength); - scsi_dev_log("Data length: %08X\n", req->CmdBlock.old.DataLength); + DataPointer = ADDR_TO_U32(req->CmdBlock.old_fmt.DataPointer); + DataLength = ADDR_TO_U32(req->CmdBlock.old_fmt.DataLength); + DEBUG("Data length: %08X\n", req->CmdBlock.old_fmt.DataLength); } else { - DataPointer = req->CmdBlock.new.DataPointer; - DataLength = req->CmdBlock.new.DataLength; + DataPointer = req->CmdBlock.new_fmt.DataPointer; + DataLength = req->CmdBlock.new_fmt.DataLength; } - scsi_dev_log("Data Buffer write: length %d, pointer 0x%04X\n", - DataLength, DataPointer); + DEBUG("Data Buffer write: length %d, pointer 0x%04X\n", + DataLength, DataPointer); if (!DataLength) return(0); @@ -772,11 +768,11 @@ x54x_set_residue(Req_t *req, int32_t TransferLength) U32_TO_ADDR(Residue24, Residue); DMAPageWrite(req->CCBPointer + 0x0004, (uint8_t *)&Residue24, 3); x54x_add_to_period(3); - scsi_dev_log("24-bit Residual data length for reading: %d\n", Residue); + DEBUG("24-bit Residual data length for reading: %d\n", Residue); } else { DMAPageWrite(req->CCBPointer + 0x0004, (uint8_t *)&Residue, 4); x54x_add_to_period(4); - scsi_dev_log("32-bit Residual data length for reading: %d\n", Residue); + DEBUG("32-bit Residual data length for reading: %d\n", Residue); } } } @@ -787,8 +783,7 @@ x54x_buf_dma_transfer(Req_t *req, int Is24bit, int TransferLength, int dir) { uint32_t DataPointer, DataLength; uint32_t SGEntryLength = (Is24bit ? sizeof(SGE) : sizeof(SGE32)); - uint32_t Address; - uint32_t i = 0; + uint32_t Address, i = 0; uint32_t BufLen = SCSIDevices[req->TargetID][req->LUN].BufferLength; uint8_t read_from_host = (dir && ((req->CmdBlock.common.ControlByte == CCB_DATA_XFER_OUT) || (req->CmdBlock.common.ControlByte == 0x00))); uint8_t write_to_host = (!dir && ((req->CmdBlock.common.ControlByte == CCB_DATA_XFER_IN) || (req->CmdBlock.common.ControlByte == 0x00))); @@ -797,14 +792,14 @@ x54x_buf_dma_transfer(Req_t *req, int Is24bit, int TransferLength, int dir) uint32_t DataToTransfer = 0; if (Is24bit) { - DataPointer = ADDR_TO_U32(req->CmdBlock.old.DataPointer); - DataLength = ADDR_TO_U32(req->CmdBlock.old.DataLength); + DataPointer = ADDR_TO_U32(req->CmdBlock.old_fmt.DataPointer); + DataLength = ADDR_TO_U32(req->CmdBlock.old_fmt.DataLength); } else { - DataPointer = req->CmdBlock.new.DataPointer; - DataLength = req->CmdBlock.new.DataLength; + DataPointer = req->CmdBlock.new_fmt.DataPointer; + DataLength = req->CmdBlock.new_fmt.DataLength; } - scsi_dev_log("Data Buffer %s: length %d, pointer 0x%04X\n", - dir ? "write" : "read", BufLen, DataPointer); + DEBUG("Data Buffer %s: length %d (%u), pointer 0x%04X\n", + dir ? "write" : "read", BufLen, DataLength, DataPointer); if ((req->CmdBlock.common.ControlByte != 0x03) && TransferLength && BufLen) { if ((req->CmdBlock.common.Opcode == SCATTER_GATHER_COMMAND) || @@ -817,18 +812,18 @@ x54x_buf_dma_transfer(Req_t *req, int Is24bit, int TransferLength, int dir) x54x_rd_sge(Is24bit, DataPointer + i, &SGBuffer); Address = SGBuffer.SegmentPointer; - DataToTransfer = MIN(SGBuffer.Segment, BufLen); + DataToTransfer = MIN((int)SGBuffer.Segment, BufLen); if (read_from_host && DataToTransfer) { - scsi_dev_log("Reading S/G segment %i: length %i, pointer %08X\n", i, DataToTransfer, Address); + DEBUG("Reading S/G segment %i: length %i, pointer %08X\n", i, DataToTransfer, Address); DMAPageRead(Address, &(SCSIDevices[req->TargetID][req->LUN].CmdBuffer[sg_pos]), DataToTransfer); } else if (write_to_host && DataToTransfer) { - scsi_dev_log("Writing S/G segment %i: length %i, pointer %08X\n", i, DataToTransfer, Address); + DEBUG("Writing S/G segment %i: length %i, pointer %08X\n", i, DataToTransfer, Address); DMAPageWrite(Address, &(SCSIDevices[req->TargetID][req->LUN].CmdBuffer[sg_pos]), DataToTransfer); } else - scsi_dev_log("No action on S/G segment %i: length %i, pointer %08X\n", i, DataToTransfer, Address); + DEBUG("No action on S/G segment %i: length %i, pointer %08X\n", i, DataToTransfer, Address); sg_pos += SGBuffer.Segment; @@ -838,7 +833,7 @@ x54x_buf_dma_transfer(Req_t *req, int Is24bit, int TransferLength, int dir) BufLen = 0; #endif - scsi_dev_log("After S/G segment done: %i, %i\n", sg_pos, BufLen); + DEBUG("After S/G segment done: %i, %i\n", sg_pos, BufLen); } } } else if ((req->CmdBlock.common.Opcode == SCSI_INITIATOR_COMMAND) || @@ -847,9 +842,9 @@ x54x_buf_dma_transfer(Req_t *req, int Is24bit, int TransferLength, int dir) if ((DataLength > 0) && (BufLen > 0) && (req->CmdBlock.common.ControlByte < 0x03)) { if (read_from_host) - DMAPageRead(Address, SCSIDevices[req->TargetID][req->LUN].CmdBuffer, MIN(BufLen, DataLength)); + DMAPageRead(Address, SCSIDevices[req->TargetID][req->LUN].CmdBuffer, MIN(BufLen, (int)DataLength)); else if (write_to_host) - DMAPageWrite(Address, SCSIDevices[req->TargetID][req->LUN].CmdBuffer, MIN(BufLen, DataLength)); + DMAPageWrite(Address, SCSIDevices[req->TargetID][req->LUN].CmdBuffer, MIN(BufLen, (int)DataLength)); } } } @@ -864,8 +859,8 @@ x54x_buf_alloc(uint8_t id, uint8_t lun, int length) SCSIDevices[id][lun].CmdBuffer = NULL; } - scsi_dev_log("Allocating data buffer (%i bytes)\n", length); - SCSIDevices[id][lun].CmdBuffer = (uint8_t *) malloc(length); + DEBUG("Allocating data buffer (%i bytes)\n", length); + SCSIDevices[id][lun].CmdBuffer = (uint8_t *)mem_alloc(length); memset(SCSIDevices[id][lun].CmdBuffer, 0, length); } @@ -883,14 +878,14 @@ x54x_buf_free(uint8_t id, uint8_t lun) static uint8_t ConvertSenseLength(uint8_t RequestSenseLength) { - scsi_dev_log("Unconverted Request Sense length %i\n", RequestSenseLength); + DEBUG("Unconverted Request Sense length %i\n", RequestSenseLength); if (RequestSenseLength == 0) RequestSenseLength = 14; else if (RequestSenseLength == 1) RequestSenseLength = 0; - scsi_dev_log("Request Sense length %i\n", RequestSenseLength); + DEBUG("Request Sense length %i\n", RequestSenseLength); return(RequestSenseLength); } @@ -904,7 +899,7 @@ SenseBufferPointer(Req_t *req) SenseBufferAddress = req->CCBPointer; SenseBufferAddress += req->CmdBlock.common.CdbLength + 18; } else { - SenseBufferAddress = req->CmdBlock.new.SensePointer; + SenseBufferAddress = req->CmdBlock.new_fmt.SensePointer; } return(SenseBufferAddress); @@ -928,13 +923,13 @@ SenseBufferFree(Req_t *req, int Copy) */ SenseBufferAddress = SenseBufferPointer(req); - scsi_dev_log("Request Sense address: %02X\n", SenseBufferAddress); + DEBUG("Request Sense address: %02X\n", SenseBufferAddress); - scsi_dev_log("SenseBufferFree(): Writing %i bytes at %08X\n", + DEBUG("SenseBufferFree(): Writing %i bytes at %08X\n", SenseLength, SenseBufferAddress); DMAPageWrite(SenseBufferAddress, temp_sense, SenseLength); x54x_add_to_period(SenseLength); - scsi_dev_log("Sense data written to buffer: %02X %02X %02X\n", + DEBUG("Sense data written to buffer: %02X %02X %02X\n", temp_sense[2], temp_sense[12], temp_sense[13]); } } @@ -958,19 +953,17 @@ x54x_scsi_cmd(x54x_t *dev) id = req->TargetID; lun = req->LUN; - target_cdb_len = scsi_device_cdb_length(id, lun); + target_cdb_len = 12; target_data_len = x54x_get_length(req, bit24); if (!scsi_device_valid(id, lun)) fatal("SCSI target on %02i:%02i has disappeared\n", id, lun); - scsi_dev_log("target_data_len = %i\n", target_data_len); - - scsi_dev_log("SCSI command being executed on ID %i, LUN %i\n", id, lun); - - scsi_dev_log("SCSI CDB[0]=0x%02X\n", req->CmdBlock.common.Cdb[0]); + DEBUG("target_data_len = %i\n", target_data_len); + DEBUG("SCSI command being executed on ID %i, LUN %i\n", id, lun); + DEBUG("SCSI CDB[0]=0x%02X\n", req->CmdBlock.common.Cdb[0]); for (i=1; iCmdBlock.common.CdbLength; i++) - scsi_dev_log("SCSI CDB[%i]=%i\n", i, req->CmdBlock.common.Cdb[i]); + DEBUG("SCSI CDB[%i]=%i\n", i, req->CmdBlock.common.Cdb[i]); memset(temp_cdb, 0x00, target_cdb_len); if (req->CmdBlock.common.CdbLength <= target_cdb_len) { @@ -987,13 +980,13 @@ x54x_scsi_cmd(x54x_t *dev) BufLen = scsi_device_get_buf_len(id, lun); *BufLen = target_data_len; - scsi_dev_log("Command buffer: %08X\n", SCSIDevices[id][lun].CmdBuffer); + DEBUG("Command buffer: %08X\n", SCSIDevices[id][lun].CmdBuffer); - scsi_device_command_phase0(id, lun, req->CmdBlock.common.CdbLength, temp_cdb); + scsi_device_command_phase0(id, lun, temp_cdb); phase = SCSIDevices[id][lun].Phase; - scsi_dev_log("Control byte: %02X\n", (req->CmdBlock.common.ControlByte == 0x03)); + DEBUG("Control byte: %02X\n", (req->CmdBlock.common.ControlByte == 0x03)); if (phase != SCSI_PHASE_STATUS) { if ((temp_cdb[0] == 0x03) && (req->CmdBlock.common.ControlByte == 0x03)) { @@ -1028,7 +1021,7 @@ x54x_scsi_cmd(x54x_t *dev) x54x_buf_free(id, lun); - scsi_dev_log("Request complete\n"); + DEBUG("Request complete\n"); if (SCSIDevices[id][lun].Status == SCSI_STATUS_OK) { x54x_mbi_setup(dev, req->CCBPointer, &req->CmdBlock, @@ -1038,7 +1031,8 @@ x54x_scsi_cmd(x54x_t *dev) CCB_COMPLETE, SCSI_STATUS_CHECK_CONDITION, MBI_ERROR); } - scsi_dev_log("SCSIDevices[%02i][%02i].Status = %02X\n", id, lun, SCSIDevices[id][lun].Status); + DEBUG("SCSIDevices[%02i][%02i].Status = %02X\n", + id, lun, SCSIDevices[id][lun].Status); } @@ -1057,7 +1051,6 @@ x54x_req_setup(x54x_t *dev, uint32_t CCBPointer, Mailbox32_t *Mailbox32) { Req_t *req = &dev->Req; uint8_t id, lun; - uint8_t max_id = SCSI_ID_MAX-1; /* Fetch data from the Command Control Block. */ DMAPageRead(CCBPointer, (uint8_t *)&req->CmdBlock, sizeof(CCB32)); @@ -1065,66 +1058,71 @@ x54x_req_setup(x54x_t *dev, uint32_t CCBPointer, Mailbox32_t *Mailbox32) req->Is24bit = dev->Mbx24bit; req->CCBPointer = CCBPointer; - req->TargetID = dev->Mbx24bit ? req->CmdBlock.old.Id : req->CmdBlock.new.Id; - req->LUN = dev->Mbx24bit ? req->CmdBlock.old.Lun : req->CmdBlock.new.Lun; + req->TargetID = dev->Mbx24bit ? req->CmdBlock.old_fmt.Id : req->CmdBlock.new_fmt.Id; + req->LUN = dev->Mbx24bit ? req->CmdBlock.old_fmt.Lun : req->CmdBlock.new_fmt.Lun; id = req->TargetID; lun = req->LUN; - if ((id > max_id) || (lun > 7)) { - scsi_dev_log("SCSI Target ID %i or LUN %i is not valid\n",id,lun); + if ((id > dev->max_id) || (lun > 7)) { + DEBUG("SCSI Target ID %i or LUN %i is not valid\n",id,lun); x54x_mbi_setup(dev, CCBPointer, &req->CmdBlock, CCB_SELECTION_TIMEOUT, SCSI_STATUS_OK, MBI_ERROR); - scsi_dev_log("%s: Callback: Send incoming mailbox\n", dev->name); + DEBUG("%s: Callback: Send incoming mailbox\n", dev->name); x54x_notify(dev); return; } - scsi_dev_log("Scanning SCSI Target ID %i\n", id); + DEBUG("Scanning SCSI Target ID %i\n", id); SCSIDevices[id][lun].Status = SCSI_STATUS_OK; /* If there is no device at ID:0, timeout the selection - the LUN is then checked later. */ if (! scsi_device_present(id, 0)) { - scsi_dev_log("SCSI Target ID %i and LUN %i have no device attached\n",id,lun); + DEBUG("SCSI Target ID %i and LUN %i have no device attached\n",id,lun); x54x_mbi_setup(dev, CCBPointer, &req->CmdBlock, CCB_SELECTION_TIMEOUT, SCSI_STATUS_OK, MBI_ERROR); - scsi_dev_log("%s: Callback: Send incoming mailbox\n", dev->name); + DEBUG("%s: Callback: Send incoming mailbox\n", dev->name); x54x_notify(dev); } else { - scsi_dev_log("SCSI Target ID %i detected and working\n", id); + DEBUG("SCSI Target ID %i detected and working\n", id); + DEBUG("Transfer Control %02X\n", req->CmdBlock.common.ControlByte); + DEBUG("CDB Length %i\n", req->CmdBlock.common.CdbLength); + DEBUG("CCB Opcode %x\n", req->CmdBlock.common.Opcode); - scsi_dev_log("Transfer Control %02X\n", req->CmdBlock.common.ControlByte); - scsi_dev_log("CDB Length %i\n", req->CmdBlock.common.CdbLength); - scsi_dev_log("CCB Opcode %x\n", req->CmdBlock.common.Opcode); if ((req->CmdBlock.common.Opcode > 0x04) && (req->CmdBlock.common.Opcode != 0x81)) { - scsi_dev_log("Invalid opcode: %02X\n", - req->CmdBlock.common.ControlByte); + DEBUG("Invalid opcode: %02X\n", + req->CmdBlock.common.ControlByte); + x54x_mbi_setup(dev, CCBPointer, &req->CmdBlock, CCB_INVALID_OP_CODE, SCSI_STATUS_OK, MBI_ERROR); - scsi_dev_log("%s: Callback: Send incoming mailbox\n", dev->name); + DEBUG("%s: Callback: Send incoming mailbox\n", dev->name); x54x_notify(dev); return; } if (req->CmdBlock.common.Opcode == 0x81) { - scsi_dev_log("Bus reset opcode\n"); + DEBUG("Bus reset opcode\n"); + + scsi_device_reset(id, lun); x54x_mbi_setup(dev, req->CCBPointer, &req->CmdBlock, CCB_COMPLETE, SCSI_STATUS_OK, MBI_SUCCESS); - scsi_dev_log("%s: Callback: Send incoming mailbox\n", dev->name); + + DEBUG("%s: Callback: Send incoming mailbox\n", dev->name); x54x_notify(dev); return; } + if (req->CmdBlock.common.ControlByte > 0x03) { - scsi_dev_log("Invalid control byte: %02X\n", + DEBUG("Invalid control byte: %02X\n", req->CmdBlock.common.ControlByte); x54x_mbi_setup(dev, CCBPointer, &req->CmdBlock, CCB_INVALID_DIRECTION, SCSI_STATUS_OK, MBI_ERROR); - scsi_dev_log("%s: Callback: Send incoming mailbox\n", dev->name); + DEBUG("%s: Callback: Send incoming mailbox\n", dev->name); x54x_notify(dev); return; } - scsi_dev_log("%s: Callback: Process SCSI request\n", dev->name); + DEBUG("%s: Callback: Process SCSI request\n", dev->name); x54x_scsi_cmd(dev); - scsi_dev_log("%s: Callback: Send incoming mailbox\n", dev->name); + DEBUG("%s: Callback: Send incoming mailbox\n", dev->name); x54x_notify(dev); } } @@ -1141,7 +1139,7 @@ x54x_req_abort(x54x_t *dev, uint32_t CCBPointer) x54x_mbi_setup(dev, CCBPointer, &CmdBlock, 0x26, SCSI_STATUS_OK, MBI_NOT_FOUND); - scsi_dev_log("%s: Callback: Send incoming mailbox\n", dev->name); + DEBUG("%s: Callback: Send incoming mailbox\n", dev->name); x54x_notify(dev); } @@ -1195,18 +1193,18 @@ x54x_mbo_process(x54x_t *dev) Outgoing = x54x_mbo(dev, &mb32); if (mb32.u.out.ActionCode == MBO_START) { - scsi_dev_log("Start Mailbox Command\n"); + DEBUG("Start Mailbox Command\n"); x54x_req_setup(dev, mb32.CCBPointer, &mb32); } else if (!dev->MailboxIsBIOS && (mb32.u.out.ActionCode == MBO_ABORT)) { - scsi_dev_log("Abort Mailbox Command\n"); + DEBUG("Abort Mailbox Command\n"); x54x_req_abort(dev, mb32.CCBPointer); } /* else { - scsi_dev_log("Invalid action code: %02X\n", mb32.u.out.ActionCode); + DEBUG("Invalid action code: %02X\n", mb32.u.out.ActionCode); } */ if ((mb32.u.out.ActionCode == MBO_START) || (!dev->MailboxIsBIOS && (mb32.u.out.ActionCode == MBO_ABORT))) { /* We got the mailbox, mark it as free in the guest. */ - scsi_dev_log("x54x_do_mail(): Writing %i bytes at %08X\n", sizeof(CmdStatus), Outgoing + CodeOffset); + DEBUG("x54x_do_mail(): Writing %i bytes at %08X\n", sizeof(CmdStatus), Outgoing + CodeOffset); DMAPageWrite(Outgoing + CodeOffset, &CmdStatus, 1); x54x_add_to_period(1); @@ -1234,13 +1232,13 @@ x54x_do_mail(x54x_t *dev) if (dev->is_aggressive_mode) { aggressive = dev->is_aggressive_mode(dev); - scsi_dev_log("Processing mailboxes in %s mode...\n", aggressive ? "aggressive" : "strict"); + DEBUG("Processing mailboxes in %s mode...\n", aggressive ? "aggressive" : "strict"); }/* else { - scsi_dev_log("Defaulting to process mailboxes in %s mode...\n", aggressive ? "aggressive" : "strict"); + DEBUG("Defaulting to process mailboxes in %s mode...\n", aggressive ? "aggressive" : "strict"); }*/ if (!dev->MailboxCount) { - scsi_dev_log("x54x_do_mail(): No Mailboxes\n"); + DEBUG("x54x_do_mail(): No Mailboxes\n"); return; } @@ -1262,8 +1260,7 @@ x54x_do_mail_again: } -static void -x54x_cmd_done(x54x_t *dev, int suppress); +static void x54x_cmd_done(x54x_t *dev, int suppress); static void @@ -1271,8 +1268,11 @@ x54x_cmd_callback(void *priv) { x54x_t *dev = (x54x_t *) x54x_dev; double period; + int mailboxes_present, bios_mailboxes_present; - if ((dev->Status & STAT_INIT) || (!dev->MailboxInit && !dev->BIOSMailboxInit) || (!dev->MailboxReq && !dev->BIOSMailboxReq)) { + mailboxes_present = (!(dev->Status & STAT_INIT) && dev->MailboxInit && dev->MailboxReq); + bios_mailboxes_present = (dev->ven_callback && dev->BIOSMailboxInit && dev->BIOSMailboxReq); + if (!mailboxes_present && !bios_mailboxes_present) { /* If we did not get anything, do nothing and wait 10 us. */ dev->timer_period = 10LL * TIMER_USEC; return; @@ -1280,15 +1280,27 @@ x54x_cmd_callback(void *priv) dev->temp_period = dev->media_period = 0LL; - if (!(x54x_dev->Status & STAT_INIT) && x54x_dev->MailboxInit && dev->MailboxReq) - x54x_do_mail(dev); - - if (dev->ven_callback) + if (!mailboxes_present) { + /* Do only BIOS mailboxes. */ dev->ven_callback(dev); + } else if (!bios_mailboxes_present) { + /* Do only normal mailboxes. */ + x54x_do_mail(dev); + } else { + /* Do both kinds of mailboxes. */ + if (dev->callback_phase) + dev->ven_callback(dev); + else + x54x_do_mail(dev); + + dev->callback_phase = (dev->callback_phase + 1) & 0x01; + } period = (1000000.0 / x54x_dev->ha_bps) * ((double) TIMER_USEC) * ((double) dev->temp_period); dev->timer_period = dev->media_period + ((int64_t) period) + (40LL * TIMER_USEC); - scsi_dev_log("Temporary period: %" PRId64 " us (%" PRIi64 " periods)\n", dev->timer_period, dev->temp_period); + + DEBUG("Temporary period: %" PRId64 " us (%" PRIi64 " periods)\n", + dev->timer_period, dev->temp_period); } @@ -1315,7 +1327,10 @@ x54x_in(uint16_t port, void *priv) break; case 2: - ret = dev->Interrupt; + if (dev->int_geom_writable) + ret = dev->Interrupt; + else + ret = dev->Interrupt & ~0x70; break; case 3: @@ -1346,9 +1361,8 @@ x54x_in(uint16_t port, void *priv) break; } -#if 0 - scsi_dev_log("%s: Read Port 0x%02X, Value %02X\n", dev->name, port, ret); -#endif + DBGLOG(2, "%s: Read Port 0x%02X, Value %02X\n", dev->name, port, ret); + return(ret); } @@ -1402,11 +1416,14 @@ x54x_reset_poll(void *priv) static void x54x_reset(x54x_t *dev) { + int i, j; + clear_irq(dev); if (dev->int_geom_writable) dev->Geometry = 0x80; else dev->Geometry = 0x00; + dev->callback_phase = 0; dev->Command = 0xFF; dev->CmdParam = 0; dev->CmdParamLeft = 0; @@ -1418,9 +1435,14 @@ x54x_reset(x54x_t *dev) dev->MailboxCount = 0; dev->MailboxOutPosCur = 0; - if (dev->ven_reset) { - dev->ven_reset(dev); + /* Reset all devices on controller reset. */ + for (i = 0; i < 16; i++) { + for (j = 0; j < 8; j++) + scsi_device_reset(i, j); } + + if (dev->ven_reset) + dev->ven_reset(dev); } @@ -1428,18 +1450,17 @@ void x54x_reset_ctrl(x54x_t *dev, uint8_t Reset) { /* Say hello! */ - scsi_dev_log("%s %s (IO=0x%04X, IRQ=%d, DMA=%d, BIOS @%05lX) ID=%d\n", - dev->vendor, dev->name, dev->Base, dev->Irq, dev->DmaChannel, - dev->rom_addr, dev->HostID); + INFO("%s %s (IO=0x%04X, IRQ=%d, DMA=%d, BIOS @%05lX) ID=%d\n", + dev->vendor, dev->name, dev->Base, dev->Irq, dev->DmaChannel, + dev->rom_addr, dev->HostID); x54x_reset(dev); if (Reset) { dev->Status = STAT_STST; dev->ResetCB = X54X_RESET_DURATION_US * TIMER_USEC; - } else { + } else dev->Status = STAT_INIT | STAT_IDLE; - } } @@ -1460,21 +1481,29 @@ x54x_out(uint16_t port, uint8_t val, void *priv) uint8_t host_id = dev->HostID; uint8_t irq = 0; - scsi_dev_log("%s: Write Port 0x%02X, Value %02X\n", dev->name, port, val); + DEBUG("%s: Write Port 0x%02X, Value %02X\n", dev->name, port, val); switch (port & 3) { case 0: if ((val & CTRL_HRST) || (val & CTRL_SRST)) { reset = (val & CTRL_HRST); - scsi_dev_log("Reset completed = %x\n", reset); + DEBUG("Reset completed = %x\n", reset); x54x_reset_ctrl(dev, reset); - scsi_dev_log("Controller reset: "); + DEBUG("Controller reset: "); break; } + if (val & CTRL_SCRST) { + /* Reset all devices on SCSI bus reset. */ + for (i = 0; i < 16; i++) { + for (j = 0; j < 8; j++) + scsi_device_reset(i, j); + } + } + if (val & CTRL_IRST) { clear_irq(dev); - scsi_dev_log("Interrupt reset: "); + DEBUG("Interrupt reset: "); } break; @@ -1482,7 +1511,7 @@ x54x_out(uint16_t port, uint8_t val, void *priv) /* Fast path for the mailbox execution command. */ if ((val == CMD_START_SCSI) && (dev->Command == 0xff)) { dev->MailboxReq++; - scsi_dev_log("Start SCSI command: "); + DEBUG("Start SCSI command: "); return; } if (dev->ven_fast_cmds) { @@ -1498,7 +1527,7 @@ x54x_out(uint16_t port, uint8_t val, void *priv) dev->CmdParamLeft = 0; dev->Status &= ~(STAT_INVCMD | STAT_IDLE); - scsi_dev_log("%s: Operation Code 0x%02X\n", dev->name, val); + DEBUG("%s: Operation Code 0x%02X\n", dev->name, val); switch (dev->Command) { case CMD_MBINIT: dev->CmdParamLeft = sizeof(MailboxInit_t); @@ -1542,7 +1571,7 @@ x54x_out(uint16_t port, uint8_t val, void *priv) } if (! dev->CmdParamLeft) { - scsi_dev_log("Running Operation Code 0x%02X\n", dev->Command); + DEBUG("Running Operation Code 0x%02X\n", dev->Command); switch (dev->Command) { case CMD_NOP: /* No Operation */ dev->DataReplyLeft = 0; @@ -1558,7 +1587,7 @@ x54x_out(uint16_t port, uint8_t val, void *priv) dev->MailboxOutAddr = ADDR_TO_U32(mbi->Address); dev->MailboxInAddr = dev->MailboxOutAddr + (dev->MailboxCount * sizeof(Mailbox_t)); - scsi_dev_log("Initialize Mailbox: MBO=0x%08lx, MBI=0x%08lx, %d entries at 0x%08lx\n", + DEBUG("Initialize Mailbox: MBO=0x%08lx, MBI=0x%08lx, %d entries at 0x%08lx\n", dev->MailboxOutAddr, dev->MailboxInAddr, mbi->Count, @@ -1566,7 +1595,7 @@ x54x_out(uint16_t port, uint8_t val, void *priv) dev->Status &= ~STAT_INIT; dev->DataReplyLeft = 0; - scsi_dev_log("Mailbox init: "); + DEBUG("Mailbox init: "); break; case CMD_BIOSCMD: /* execute BIOS */ @@ -1578,32 +1607,32 @@ x54x_out(uint16_t port, uint8_t val, void *priv) } if (dev->lba_bios) { /* 1640 uses LBA. */ - scsi_dev_log("BIOS LBA=%06lx (%lu)\n", + DEBUG("BIOS LBA=%06lx (%lu)\n", lba32_blk(cmd), lba32_blk(cmd)); } else { cmd->u.chs.head &= 0xf; cmd->u.chs.sec &= 0x1f; - scsi_dev_log("BIOS CHS=%04X/%02X%02X\n", + DEBUG("BIOS CHS=%04X/%02X%02X\n", cmd->u.chs.cyl, cmd->u.chs.head, cmd->u.chs.sec); } dev->DataBuf[0] = x54x_bios_command(dev, dev->max_id, cmd, (dev->lba_bios)?1:0); - scsi_dev_log("BIOS Completion/Status Code %x\n", dev->DataBuf[0]); + DEBUG("BIOS Completion/Status Code %x\n", dev->DataBuf[0]); dev->DataReplyLeft = 1; break; case CMD_INQUIRY: /* Inquiry */ memcpy(dev->DataBuf, dev->fw_rev, 4); - scsi_dev_log("Adapter inquiry: %c %c %c %c\n", dev->fw_rev[0], dev->fw_rev[1], dev->fw_rev[2], dev->fw_rev[3]); + DEBUG("Adapter inquiry: %c %c %c %c\n", dev->fw_rev[0], dev->fw_rev[1], dev->fw_rev[2], dev->fw_rev[3]); dev->DataReplyLeft = 4; break; case CMD_EMBOI: /* enable MBO Interrupt */ if (dev->CmdBuf[0] <= 1) { dev->MailboxOutInterrupts = dev->CmdBuf[0]; - scsi_dev_log("Mailbox out interrupts: %s\n", dev->MailboxOutInterrupts ? "ON" : "OFF"); + DEBUG("Mailbox out interrupts: %s\n", dev->MailboxOutInterrupts ? "ON" : "OFF"); suppress = 1; } else { dev->Status |= STAT_INVCMD; @@ -1618,19 +1647,19 @@ x54x_out(uint16_t port, uint8_t val, void *priv) case CMD_BUSON_TIME: /* bus-on time */ dev->BusOnTime = dev->CmdBuf[0]; dev->DataReplyLeft = 0; - scsi_dev_log("Bus-on time: %d\n", dev->CmdBuf[0]); + DEBUG("Bus-on time: %d\n", dev->CmdBuf[0]); break; case CMD_BUSOFF_TIME: /* bus-off time */ dev->BusOffTime = dev->CmdBuf[0]; dev->DataReplyLeft = 0; - scsi_dev_log("Bus-off time: %d\n", dev->CmdBuf[0]); + DEBUG("Bus-off time: %d\n", dev->CmdBuf[0]); break; case CMD_DMASPEED: /* DMA Transfer Rate */ dev->ATBusSpeed = dev->CmdBuf[0]; dev->DataReplyLeft = 0; - scsi_dev_log("DMA transfer rate: %02X\n", dev->CmdBuf[0]); + DEBUG("DMA transfer rate: %02X\n", dev->CmdBuf[0]); break; case CMD_RETDEVS: /* return Installed Devices */ @@ -1639,7 +1668,7 @@ x54x_out(uint16_t port, uint8_t val, void *priv) if (dev->ven_get_host_id) host_id = dev->ven_get_host_id(dev); - for (i=0; iDataBuf[i] = 0x00; /* Skip the HA .. */ @@ -1672,7 +1701,7 @@ x54x_out(uint16_t port, uint8_t val, void *priv) dev->DataBuf[2] = dev->ven_get_host_id(dev); else dev->DataBuf[2] = dev->HostID; - scsi_dev_log("Configuration data: %02X %02X %02X\n", dev->DataBuf[0], dev->DataBuf[1], dev->DataBuf[2]); + DEBUG("Configuration data: %02X %02X %02X\n", dev->DataBuf[0], dev->DataBuf[1], dev->DataBuf[2]); dev->DataReplyLeft = 3; break; @@ -1692,7 +1721,7 @@ x54x_out(uint16_t port, uint8_t val, void *priv) } dev->DataReplyLeft = dev->CmdBuf[0]; - scsi_dev_log("Return Setup Information: %d (length: %i)\n", dev->CmdBuf[0], sizeof(ReplyInquireSetupInformation)); + DEBUG("Return Setup Information: %d (length: %i)\n", dev->CmdBuf[0], sizeof(ReplyInquireSetupInformation)); } break; @@ -1707,7 +1736,7 @@ x54x_out(uint16_t port, uint8_t val, void *priv) Address.mid = dev->CmdBuf[1]; Address.lo = dev->CmdBuf[2]; FIFOBuf = ADDR_TO_U32(Address); - scsi_dev_log("Adaptec LocalRAM: Reading 64 bytes at %08X\n", FIFOBuf); + DEBUG("Adaptec LocalRAM: Reading 64 bytes at %08X\n", FIFOBuf); DMAPageRead(FIFOBuf, dev->dma_buffer, 64); break; @@ -1717,7 +1746,7 @@ x54x_out(uint16_t port, uint8_t val, void *priv) Address.mid = dev->CmdBuf[1]; Address.lo = dev->CmdBuf[2]; FIFOBuf = ADDR_TO_U32(Address); - scsi_dev_log("Adaptec LocalRAM: Writing 64 bytes at %08X\n", FIFOBuf); + DEBUG("Adaptec LocalRAM: Writing 64 bytes at %08X\n", FIFOBuf); DMAPageWrite(FIFOBuf, dev->dma_buffer, 64); break; @@ -1803,12 +1832,12 @@ x54x_io_set(x54x_t *dev, uint32_t base, uint8_t len) bit32 = 1; if (bit32) { - scsi_dev_log("x54x: [PCI] Setting I/O handler at %04X\n", base); + DEBUG("x54x: [PCI] Setting I/O handler at %04X\n", base); io_sethandler(base, len, x54x_in, x54x_inw, x54x_inl, x54x_out, x54x_outw, x54x_outl, dev); } else { - scsi_dev_log("x54x: [ISA] Setting I/O handler at %04X\n", base); + DEBUG("x54x: [ISA] Setting I/O handler at %04X\n", base); io_sethandler(base, len, x54x_in, x54x_inw, NULL, x54x_out, x54x_outw, NULL, dev); @@ -1826,7 +1855,7 @@ x54x_io_remove(x54x_t *dev, uint32_t base, uint8_t len) else if ((dev->bus & DEVICE_MCA) && dev->bit32) bit32 = 1; - scsi_dev_log("x54x: Removing I/O handler at %04X\n", base); + DEBUG("x54x: Removing I/O handler at %04X\n", base); if (bit32) { io_removehandler(base, len, @@ -1851,15 +1880,15 @@ x54x_mem_init(x54x_t *dev, uint32_t addr) bit32 = 1; if (bit32) { - mem_mapping_add(&dev->mmio_mapping, addr, 0x20, - x54x_read, x54x_readw, x54x_readl, - x54x_write, x54x_writew, x54x_writel, - NULL, MEM_MAPPING_EXTERNAL, dev); + mem_map_add(&dev->mmio_mapping, addr, 0x20, + x54x_read, x54x_readw, x54x_readl, + x54x_write, x54x_writew, x54x_writel, + NULL, MEM_MAPPING_EXTERNAL, dev); } else { - mem_mapping_add(&dev->mmio_mapping, addr, 0x20, - x54x_read, x54x_readw, NULL, - x54x_write, x54x_writew, NULL, - NULL, MEM_MAPPING_EXTERNAL, dev); + mem_map_add(&dev->mmio_mapping, addr, 0x20, + x54x_read, x54x_readw, NULL, + x54x_write, x54x_writew, NULL, + NULL, MEM_MAPPING_EXTERNAL, dev); } } @@ -1867,21 +1896,21 @@ x54x_mem_init(x54x_t *dev, uint32_t addr) void x54x_mem_enable(x54x_t *dev) { - mem_mapping_enable(&dev->mmio_mapping); + mem_map_enable(&dev->mmio_mapping); } void x54x_mem_set_addr(x54x_t *dev, uint32_t base) { - mem_mapping_set_addr(&dev->mmio_mapping, base, 0x20); + mem_map_set_addr(&dev->mmio_mapping, base, 0x20); } void x54x_mem_disable(x54x_t *dev) { - mem_mapping_disable(&dev->mmio_mapping); + mem_map_disable(&dev->mmio_mapping); } @@ -1892,12 +1921,13 @@ x54x_init(const device_t *info) x54x_t *dev; /* Allocate control block and set up basic stuff. */ - dev = malloc(sizeof(x54x_t)); + dev = (x54x_t *)mem_alloc(sizeof(x54x_t)); if (dev == NULL) return(dev); memset(dev, 0x00, sizeof(x54x_t)); dev->type = info->local; dev->bus = info->flags; + dev->callback_phase = 0; timer_add(x54x_reset_poll, &dev->ResetCB, &dev->ResetCB, dev); dev->timer_period = 10LL * TIMER_USEC; diff --git a/src/devices/scsi/scsi_x54x.h b/src/devices/scsi/scsi_x54x.h index aeb3154..e3f7141 100644 --- a/src/devices/scsi/scsi_x54x.h +++ b/src/devices/scsi/scsi_x54x.h @@ -8,7 +8,7 @@ * * Definitions for the common AHA/BL code. * - * Version: @(#)scsi_x54x.h 1.0.3 2018/03/15 + * Version: @(#)scsi_x54x.h 1.0.4 2018/10/05 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -133,6 +133,18 @@ #define INTR_MBIF 0x01 /* MBI full */ +#pragma pack(push,1) +typedef struct { + uint8_t hi; + uint8_t mid; + uint8_t lo; +} addr24; +#pragma pack(pop) + +#define ADDR_TO_U32(x) (((x).hi<<16)|((x).mid<<8)|((x).lo&0xFF)) +#define U32_TO_ADDR(a,x) do {(a).hi=(x)>>16;(a).mid=(x)>>8;(a).lo=(x)&0xFF;}while(0) + + /* Structure for the INQUIRE_SETUP_INFORMATION reply. */ #pragma pack(push,1) typedef struct { @@ -321,8 +333,8 @@ typedef struct { #pragma pack(push,1) typedef union { - CCB32 new; - CCB old; + CCB32 new_fmt; + CCB old_fmt; CCBC common; } CCBU; #pragma pack(pop) @@ -348,6 +360,7 @@ typedef struct { char name[16]; /* name of device */ int64_t timer_period, temp_period; + uint8_t callback_phase; int64_t media_period; double ha_bps; /* bytes per second */ @@ -440,7 +453,7 @@ typedef struct { uint8_t bit32; uint8_t lba_bios; - mem_mapping_t mmio_mapping; + mem_map_t mmio_mapping; uint8_t int_geom_writable; uint8_t cdrom_boot; @@ -480,30 +493,52 @@ typedef struct { #pragma pack(push,1) typedef struct { - uint8_t command; - uint8_t lun:3, + uint8_t command; + uint8_t lun:3, reserved:2, id:3; - union { - struct { + union { + struct { uint16_t cyl; uint8_t head; uint8_t sec; - } chs; - struct { + } chs; + struct { uint8_t lba0; /* MSB */ uint8_t lba1; uint8_t lba2; uint8_t lba3; /* LSB */ - } lba; - } u; - uint8_t secount; - addr24 dma_address; + } lba; + } u; + uint8_t secount; + addr24 dma_address; } BIOSCMD; #pragma pack(pop) #define lba32_blk(p) ((uint32_t)(p->u.lba.lba0<<24) | (p->u.lba.lba1<<16) | \ (p->u.lba.lba2<<8) | p->u.lba.lba3) +/* + * + * Scatter/Gather Segment List Definitions + * + * Adapter limits + */ +#define MAX_SG_DESCRIPTORS 32 /* Always make the array 32 elements long, if less are used, that's not an issue. */ + +#pragma pack(push,1) +typedef struct { + uint32_t Segment; + uint32_t SegmentPointer; +} SGE32; +#pragma pack(pop) + +#pragma pack(push,1) +typedef struct { + addr24 Segment; + addr24 SegmentPointer; +} SGE; +#pragma pack(pop) + extern void x54x_reset_ctrl(x54x_t *dev, uint8_t Reset); extern void x54x_buf_alloc(uint8_t id, uint8_t lun, int length); diff --git a/src/devices/sio/sio.h b/src/devices/sio/sio.h index a4945a1..fcfe48f 100644 --- a/src/devices/sio/sio.h +++ b/src/devices/sio/sio.h @@ -49,14 +49,22 @@ extern void superio_detect_init(void); + extern void fdc37c663_init(void); + extern void fdc37c665_init(void); + extern void fdc37c669_init(void); + extern void fdc37c932fr_init(void); + extern void fdc37c935_init(void); + extern void pc87306_init(void); + extern void um8669f_init(void); -extern void w83877f_init(void); + +extern void w83877f_init(int flag); #endif /*EMU_SIO_H*/ diff --git a/src/devices/sio/sio_fdc37c669.c b/src/devices/sio/sio_fdc37c669.c index d352fa5..9754061 100644 --- a/src/devices/sio/sio_fdc37c669.c +++ b/src/devices/sio/sio_fdc37c669.c @@ -8,7 +8,7 @@ * * Implementation of the SMC FDC37C669 Super I/O Chip. * - * Version: @(#)sio_fdc37c669.c 1.0.7 2018/05/06 + * Version: @(#)sio_fdc37c669.c 1.0.8 2018/09/19 * * Author: Miran Grca, * @@ -56,6 +56,7 @@ static uint8_t fdc37c669_regs[42]; static uint8_t tries; static fdc_t *fdc37c669_fdc; + static uint16_t make_port(uint8_t reg) { uint16_t p = 0; @@ -92,7 +93,6 @@ void fdc37c669_write(uint16_t port, uint8_t val, void *priv) uint8_t index = (port & 1) ? 0 : 1; uint8_t valxor = 0; uint8_t max = 42; - /* pclog("fdc37c669_write : port=%04x reg %02X = %02X locked=%i\n", port, fdc37c669_curreg, val, fdc37c669_locked); */ if (index) { @@ -144,7 +144,7 @@ process_value: if (valxor & 3) { ide_pri_disable(); - if ((fdc37c669_regs[0] & 3) == 2) ide_pri_enable_ex(); + if ((fdc37c669_regs[0] & 3) == 2) ide_pri_enable(); break; } #endif @@ -172,24 +172,20 @@ process_value: if (valxor & 8) { #if 0 - /* pclog("Removing UART1\n"); */ serial_remove(1); #endif if ((fdc37c669_regs[2] & 8) && (fdc37c669_regs[0x24] >= 0x40)) { - /* pclog("UART1 init (%02X, %i)\n", make_port(0x24), (fdc37c669_regs[0x28] & 0xF0) >> 4); */ serial_setup(1, make_port(0x24), (fdc37c669_regs[0x28] & 0xF0) >> 4); } } if (valxor & 0x80) { #if 0 - /* pclog("Removing UART2\n"); */ serial_remove(2); #endif if ((fdc37c669_regs[2] & 0x80) && (fdc37c669_regs[0x25] >= 0x40)) { - /* pclog("UART2 init (%02X, %i)\n", make_port(0x25), fdc37c669_regs[0x28] & 0x0F); */ serial_setup(2, make_port(0x25), fdc37c669_regs[0x28] & 0x0F); } } @@ -227,7 +223,7 @@ process_value: ide_set_side(0, make_port(0x22)); break; } - if ((fdc37c669_regs[0] & 3) == 2) ide_pri_enable_ex(); + if ((fdc37c669_regs[0] & 3) == 2) ide_pri_enable(); } #endif break; @@ -245,12 +241,10 @@ process_value: if (valxor & 0xfe) { #if 0 - /* pclog("Removing UART1\n"); */ serial_remove(1); #endif if ((fdc37c669_regs[2] & 8) && (fdc37c669_regs[0x24] >= 0x40)) { - /* pclog("UART1 init (%02X, %i)\n", make_port(0x24), (fdc37c669_regs[0x28] & 0xF0) >> 4); */ serial_setup(1, make_port(0x24), (fdc37c669_regs[0x28] & 0xF0) >> 4); } } @@ -259,12 +253,10 @@ process_value: if (valxor & 0xfe) { #if 0 - /* pclog("Removing UART2\n"); */ serial_remove(2); #endif if ((fdc37c669_regs[2] & 0x80) && (fdc37c669_regs[0x25] >= 0x40)) { - /* pclog("UART2 init (%02X, %i)\n", make_port(0x25), fdc37c669_regs[0x28] & 0x0F); */ serial_setup(2, make_port(0x25), fdc37c669_regs[0x28] & 0x0F); } } @@ -273,24 +265,20 @@ process_value: if (valxor & 0xf) { #if 0 - /* pclog("Removing UART2\n"); */ serial_remove(2); #endif if ((fdc37c669_regs[2] & 0x80) && (fdc37c669_regs[0x25] >= 0x40)) { - /* pclog("UART2 init (%02X, %i)\n", make_port(0x25), fdc37c669_regs[0x28] & 0x0F); */ serial_setup(2, make_port(0x25), fdc37c669_regs[0x28] & 0x0F); } } if (valxor & 0xf0) { #if 0 - /* pclog("Removing UART1\n"); */ serial_remove(1); #endif if ((fdc37c669_regs[2] & 8) && (fdc37c669_regs[0x24] >= 0x40)) { - /* pclog("UART1 init (%02X, %i)\n", make_port(0x24), (fdc37c669_regs[0x28] & 0xF0) >> 4); */ serial_setup(1, make_port(0x24), (fdc37c669_regs[0x28] & 0xF0) >> 4); } } @@ -302,8 +290,6 @@ uint8_t fdc37c669_read(uint16_t port, void *priv) { uint8_t index = (port & 1) ? 0 : 1; - /* pclog("fdc37c669_read : port=%04x reg %02X locked=%i\n", port, fdc37c669_curreg, fdc37c669_locked); */ - if (!fdc37c669_locked) { return 0xFF; @@ -313,7 +299,6 @@ uint8_t fdc37c669_read(uint16_t port, void *priv) return fdc37c669_curreg; else { - /* pclog("0x03F1: %02X\n", fdc37c669_regs[fdc37c669_curreg]); */ if ((fdc37c669_curreg < 0x18) && (fdc37c669_rw_locked)) return 0xff; return fdc37c669_regs[fdc37c669_curreg]; } @@ -370,11 +355,9 @@ void fdc37c669_reset(void) void fdc37c669_init() { - fdc37c669_fdc = device_add(&fdc_at_smc_device); + fdc37c669_fdc = (fdc_t *)device_add(&fdc_at_smc_device); io_sethandler(0x3f0, 0x0002, fdc37c669_read, NULL, NULL, fdc37c669_write, NULL, NULL, NULL); fdc37c669_reset(); - - pci_reset_handler.super_io_reset = fdc37c669_reset; } diff --git a/src/devices/sio/sio_fdc37c66x.c b/src/devices/sio/sio_fdc37c66x.c index a9f0722..147cd5c 100644 --- a/src/devices/sio/sio_fdc37c66x.c +++ b/src/devices/sio/sio_fdc37c66x.c @@ -9,7 +9,7 @@ * Implementation of the SMC FDC37C663 and FDC37C665 Super * I/O Chips. * - * Version: @(#)sio_fdc37c66x.c 1.0.7 2018/05/06 + * Version: @(#)sio_fdc37c66x.c 1.0.8 2018/09/19 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -61,304 +61,309 @@ static int com3_addr, com4_addr; static fdc_t *fdc37c66x_fdc; -static void write_lock(uint8_t val) +static void +write_lock(uint8_t val) { - if (val == 0x55 && fdc37c66x_lock[1] == 0x55) - fdc_3f1_enable(fdc37c66x_fdc, 0); - if (fdc37c66x_lock[0] == 0x55 && fdc37c66x_lock[1] == 0x55 && val != 0x55) - fdc_3f1_enable(fdc37c66x_fdc, 1); + if (val == 0x55 && fdc37c66x_lock[1] == 0x55) + fdc_3f1_enable(fdc37c66x_fdc, 0); + if (fdc37c66x_lock[0] == 0x55 && fdc37c66x_lock[1] == 0x55 && val != 0x55) + fdc_3f1_enable(fdc37c66x_fdc, 1); - fdc37c66x_lock[0] = fdc37c66x_lock[1]; - fdc37c66x_lock[1] = val; + fdc37c66x_lock[0] = fdc37c66x_lock[1]; + fdc37c66x_lock[1] = val; } -static void ide_handler() + +static void +ide_handler(void) { #if 0 - uint16_t or_value = 0; - if ((romset == ROM_440FX) || (romset == ROM_R418) || (romset == ROM_MB500N)) - { - return; - } - ide_pri_disable(); - if (fdc37c66x_regs[0] & 1) - { - if (fdc37c66x_regs[5] & 2) - { - or_value = 0; - } - else - { - or_value = 0x800; - } - ide_set_base(0, 0x170 | or_value); - ide_set_side(0, 0x376 | or_value); - ide_pri_enable_ex(); - } + uint16_t or_value = 0; + + if ((romset == ROM_440FX) || + (romset == ROM_R418) || + (romset == ROM_MB500N)) return; + + ide_pri_disable(); + + if (fdc37c66x_regs[0] & 1) { + if (fdc37c66x_regs[5] & 2) + or_value = 0; + else + or_value = 0x800; + ide_set_base(0, 0x170 | or_value); + ide_set_side(0, 0x376 | or_value); + ide_pri_enable(); + } #endif } -static void set_com34_addr() + +static void +set_com34_addr(void) { - switch (fdc37c66x_regs[1] & 0x60) - { - case 0x00: - com3_addr = 0x338; - com4_addr = 0x238; - break; - case 0x20: - com3_addr = 0x3e8; - com4_addr = 0x2e8; - break; - case 0x40: - com3_addr = 0x3e8; - com4_addr = 0x2e0; - break; - case 0x60: - com3_addr = 0x220; - com4_addr = 0x228; - break; - } + switch (fdc37c66x_regs[1] & 0x60) { + case 0x00: + com3_addr = 0x338; + com4_addr = 0x238; + break; + + case 0x20: + com3_addr = 0x3e8; + com4_addr = 0x2e8; + break; + + case 0x40: + com3_addr = 0x3e8; + com4_addr = 0x2e0; + break; + + case 0x60: + com3_addr = 0x220; + com4_addr = 0x228; + break; + } } -static void set_serial1_addr() + +static void +set_serial1_addr(void) { - if (fdc37c66x_regs[2] & 4) - { - switch (fdc37c66x_regs[2] & 3) - { - case 0: - serial_setup(1, SERIAL1_ADDR, SERIAL1_IRQ); - break; + if (fdc37c66x_regs[2] & 4) { + switch (fdc37c66x_regs[2] & 3) { + case 0: + serial_setup(1, SERIAL1_ADDR, SERIAL1_IRQ); + break; - case 1: - serial_setup(1, SERIAL2_ADDR, SERIAL2_IRQ); - break; + case 1: + serial_setup(1, SERIAL2_ADDR, SERIAL2_IRQ); + break; - case 2: - serial_setup(1, com3_addr, 4); - break; + case 2: + serial_setup(1, com3_addr, 4); + break; - case 3: - serial_setup(1, com4_addr, 3); - break; - } + case 3: + serial_setup(1, com4_addr, 3); + break; } + } } -static void set_serial2_addr() + +static void +set_serial2_addr(void) { - if (fdc37c66x_regs[2] & 0x40) - { - switch (fdc37c66x_regs[2] & 0x30) - { - case 0: - serial_setup(2, SERIAL1_ADDR, SERIAL1_IRQ); - break; + if (fdc37c66x_regs[2] & 0x40) { + switch (fdc37c66x_regs[2] & 0x30) { + case 0: + serial_setup(2, SERIAL1_ADDR, SERIAL1_IRQ); + break; - case 1: - serial_setup(2, SERIAL2_ADDR, SERIAL2_IRQ); - break; + case 1: + serial_setup(2, SERIAL2_ADDR, SERIAL2_IRQ); + break; - case 2: - serial_setup(2, com3_addr, 4); - break; + case 2: + serial_setup(2, com3_addr, 4); + break; - case 3: - serial_setup(2, com4_addr, 3); - break; - } + case 3: + serial_setup(2, com4_addr, 3); + break; } + } } -static void lpt1_handler() + +static void +lpt1_handler(void) { //FIXME: parallel_remove(1); - switch (fdc37c66x_regs[1] & 3) - { - case 1: - parallel_setup(1, 0x3bc); - break; - case 2: - parallel_setup(1, 0x378); - break; - case 3: - parallel_setup(1, 0x278); - break; + + switch (fdc37c66x_regs[1] & 3) { + case 1: + parallel_setup(1, 0x3bc); + break; + + case 2: + parallel_setup(1, 0x378); + break; + + case 3: + parallel_setup(1, 0x278); + break; + } +} + + +static void +fdc37c66x_write(uint16_t port, uint8_t val, void *priv) +{ + uint8_t valxor = 0; + + if (fdc37c66x_lock[0] == 0x55 && fdc37c66x_lock[1] == 0x55) { + if (port == 0x3f0) { + if (val == 0xaa) + write_lock(val); + else + fdc37c66x_curreg = val; +#if 0 + if (fdc37c66x_curreg != 0) + fdc37c66x_curreg = val & 0xf; + else { + /* Hardcode the IDE to AT type. */ + fdc37c66x_curreg = (val & 0xf) | 2; + } +#endif + } else { + if (fdc37c66x_curreg > 15) + return; + + valxor = val ^ fdc37c66x_regs[fdc37c66x_curreg]; + fdc37c66x_regs[fdc37c66x_curreg] = val; + + switch(fdc37c66x_curreg) { + case 0: + if (valxor & 1) + ide_handler(); + break; + + case 1: + if (valxor & 3) + lpt1_handler(); + + if (valxor & 0x60) { +#if 0 + serial_remove(1); +#endif + set_com34_addr(); + set_serial1_addr(); + set_serial2_addr(); + } + break; + + case 2: + if (valxor & 7) { +#if 0 + serial_remove(1); +#endif + set_serial1_addr(); + } + if (valxor & 0x70) { +#if 0 + serial_remove(2); +#endif + set_serial2_addr(); + } + break; + + case 3: + if (valxor & 2) + fdc_update_enh_mode(fdc37c66x_fdc, (fdc37c66x_regs[3] & 2) ? 1 : 0); + break; + + case 5: + if (valxor & 2) + ide_handler(); + + if (valxor & 0x18) + fdc_update_densel_force(fdc37c66x_fdc, (fdc37c66x_regs[5] & 0x18) >> 3); + + if (valxor & 0x20) + fdc_set_swap(fdc37c66x_fdc, (fdc37c66x_regs[5] & 0x20) >> 5); + break; + } } + } else { + if (port == 0x3f0) + write_lock(val); + } } -static void fdc37c66x_write(uint16_t port, uint8_t val, void *priv) -{ - uint8_t valxor = 0; - if (fdc37c66x_lock[0] == 0x55 && fdc37c66x_lock[1] == 0x55) - { - if (port == 0x3f0) - { - if (val == 0xaa) - write_lock(val); - else - fdc37c66x_curreg = val; -#if 0 - if (fdc37c66x_curreg != 0) - { - fdc37c66x_curreg = val & 0xf; - } - else - { - /* Hardcode the IDE to AT type. */ - fdc37c66x_curreg = (val & 0xf) | 2; - } -#endif - } - else - { - if (fdc37c66x_curreg > 15) - return; - valxor = val ^ fdc37c66x_regs[fdc37c66x_curreg]; - fdc37c66x_regs[fdc37c66x_curreg] = val; - - switch(fdc37c66x_curreg) - { - case 0: - if (valxor & 1) - { - ide_handler(); - } - break; - case 1: - if (valxor & 3) - { - lpt1_handler(); - } - if (valxor & 0x60) - { -#if 0 - serial_remove(1); -#endif - set_com34_addr(); - set_serial1_addr(); - set_serial2_addr(); - } - break; - case 2: - if (valxor & 7) - { -#if 0 - serial_remove(1); -#endif - set_serial1_addr(); - } - if (valxor & 0x70) - { -#if 0 - serial_remove(2); -#endif - set_serial2_addr(); - } - break; - case 3: - if (valxor & 2) - { - fdc_update_enh_mode(fdc37c66x_fdc, (fdc37c66x_regs[3] & 2) ? 1 : 0); - } - break; - case 5: - if (valxor & 2) - { - ide_handler(); - } - if (valxor & 0x18) - { - fdc_update_densel_force(fdc37c66x_fdc, (fdc37c66x_regs[5] & 0x18) >> 3); - } - if (valxor & 0x20) - { - fdc_set_swap(fdc37c66x_fdc, (fdc37c66x_regs[5] & 0x20) >> 5); - } - break; - } - } - } - else - { - if (port == 0x3f0) - write_lock(val); - } +static uint8_t +fdc37c66x_read(uint16_t port, void *priv) +{ + if (fdc37c66x_lock[0] == 0x55 && fdc37c66x_lock[1] == 0x55) { + if (port == 0x3f1) + return fdc37c66x_regs[fdc37c66x_curreg]; + } + + return 0xff; } -static uint8_t fdc37c66x_read(uint16_t port, void *priv) -{ - if (fdc37c66x_lock[0] == 0x55 && fdc37c66x_lock[1] == 0x55) - { - if (port == 0x3f1) - return fdc37c66x_regs[fdc37c66x_curreg]; - } - return 0xff; -} -static void fdc37c66x_reset(void) +static void +fdc37c66x_reset(void) { - com3_addr = 0x338; - com4_addr = 0x238; + com3_addr = 0x338; + com4_addr = 0x238; #if 0 - serial_remove(1); + serial_remove(1); #endif - serial_setup(1, SERIAL1_ADDR, SERIAL1_IRQ); + serial_setup(1, SERIAL1_ADDR, SERIAL1_IRQ); #if 0 - serial_remove(2); + serial_remove(2); #endif - serial_setup(2, SERIAL2_ADDR, SERIAL2_IRQ); + serial_setup(2, SERIAL2_ADDR, SERIAL2_IRQ); //FIXME: parallel_remove(1); //FIXME: parallel_remove(2); - parallel_setup(1, 0x378); + parallel_setup(1, 0x378); - fdc_reset(fdc37c66x_fdc); + fdc_reset(fdc37c66x_fdc); - memset(fdc37c66x_lock, 0, 2); - memset(fdc37c66x_regs, 0, 16); - fdc37c66x_regs[0x0] = 0x3a; - fdc37c66x_regs[0x1] = 0x9f; - fdc37c66x_regs[0x2] = 0xdc; - fdc37c66x_regs[0x3] = 0x78; - fdc37c66x_regs[0x6] = 0xff; - fdc37c66x_regs[0xe] = 0x01; + memset(fdc37c66x_lock, 0, 2); + memset(fdc37c66x_regs, 0, 16); + fdc37c66x_regs[0x0] = 0x3a; + fdc37c66x_regs[0x1] = 0x9f; + fdc37c66x_regs[0x2] = 0xdc; + fdc37c66x_regs[0x3] = 0x78; + fdc37c66x_regs[0x6] = 0xff; + fdc37c66x_regs[0xe] = 0x01; } -static void fdc37c663_reset(void) + +static void +fdc37c663_reset(void) { - fdc37c66x_reset(); - fdc37c66x_regs[0xd] = 0x63; + fdc37c66x_reset(); + + fdc37c66x_regs[0xd] = 0x63; } -static void fdc37c665_reset(void) + +static void +fdc37c665_reset(void) { - fdc37c66x_reset(); - fdc37c66x_regs[0xd] = 0x65; + fdc37c66x_reset(); + + fdc37c66x_regs[0xd] = 0x65; } -void fdc37c663_init() + +void +fdc37c663_init(void) { - fdc37c66x_fdc = device_add(&fdc_at_smc_device); + fdc37c66x_fdc = (fdc_t *)device_add(&fdc_at_smc_device); - io_sethandler(0x03f0, 0x0002, fdc37c66x_read, NULL, NULL, fdc37c66x_write, NULL, NULL, NULL); + io_sethandler(0x03f0, 2, + fdc37c66x_read,NULL,NULL, fdc37c66x_write,NULL,NULL, NULL); - fdc37c663_reset(); - - pci_reset_handler.super_io_reset = fdc37c663_reset; + fdc37c663_reset(); } -void fdc37c665_init() + +void +fdc37c665_init(void) { - fdc37c66x_fdc = device_add(&fdc_at_smc_device); + fdc37c66x_fdc = (fdc_t *)device_add(&fdc_at_smc_device); - io_sethandler(0x03f0, 0x0002, fdc37c66x_read, NULL, NULL, fdc37c66x_write, NULL, NULL, NULL); + io_sethandler(0x03f0, 2, + fdc37c66x_read,NULL,NULL, fdc37c66x_write,NULL,NULL, NULL); - fdc37c665_reset(); - - pci_reset_handler.super_io_reset = fdc37c665_reset; + fdc37c665_reset(); } diff --git a/src/devices/sio/sio_fdc37c93x.c b/src/devices/sio/sio_fdc37c93x.c index 717815d..ab4f7f0 100644 --- a/src/devices/sio/sio_fdc37c93x.c +++ b/src/devices/sio/sio_fdc37c93x.c @@ -9,7 +9,7 @@ * Implementation of the SMC FDC37C932FR and FDC37C935 Super * I/O Chips. * - * Version: @(#)sio_fdc37c93x.c 1.0.9 2018/05/06 + * Version: @(#)sio_fdc37c93x.c 1.0.10 2018/09/19 * * Author: Miran Grca, * @@ -60,6 +60,7 @@ static fdc_t *fdc37c93x_fdc; static uint8_t tries; + static uint16_t make_port(uint8_t ld) { uint16_t r0 = fdc37c93x_ld_regs[ld][0x60]; @@ -72,13 +73,11 @@ static uint16_t make_port(uint8_t ld) static uint8_t fdc37c93x_gpio_read(uint16_t port, void *priv) { - /* pclog("fdc37c93x: GPIO read: %02X\n", fdc37c93x_gpio_reg); */ return fdc37c93x_gpio_reg; } static void fdc37c93x_gpio_write(uint16_t port, uint8_t val, void *priv) { - /* pclog("fdc37c93x: GPIO write: %02X\n", val); */ fdc37c93x_gpio_reg = val; } @@ -90,11 +89,9 @@ static void fdc37c93x_fdc_handler(void) uint8_t local_enable = !!fdc37c93x_ld_regs[0][0x30]; fdc_remove(fdc37c93x_fdc); - /* pclog("fdc37c93x: Removing FDC (%i, %i)\n", global_enable, local_enable); */ if (global_enable && local_enable) { ld_port = make_port(0); - /* pclog("fdc37c93x: Setting FDC port to %04X\n", ld_port); */ if ((ld_port >= 0x0100) && (ld_port <= 0x0FF8)) { fdc_set_base(fdc37c93x_fdc, ld_port); } @@ -112,7 +109,6 @@ static void fdc37c93x_lpt_handler(void) if (global_enable && local_enable) { ld_port = make_port(3); - /* pclog("fdc37c93x: Setting LPT1 port to %04X\n", ld_port); */ if ((ld_port >= 0x0100) && (ld_port <= 0x0FFC)) parallel_setup(1, ld_port); } @@ -133,7 +129,6 @@ static void fdc37c93x_serial_handler(int uart) if (global_enable && local_enable) { ld_port = make_port(uart_no); - /* pclog("fdc37c93x: Setting COM%i port to %04X\n", uart, ld_port); */ if ((ld_port >= 0x0100) && (ld_port <= 0x0FF8)) serial_setup(uart, ld_port, fdc37c93x_ld_regs[uart_no][0x70]); } @@ -149,7 +144,6 @@ static void fdc37c93x_auxio_handler(void) if (local_enable) { fdc37c93x_gpio_base = ld_port = make_port(8); - /* pclog("fdc37c93x: Setting Auxiliary I/O port to %04X\n", ld_port); */ if ((ld_port >= 0x0100) && (ld_port <= 0x0FFF)) io_sethandler(fdc37c93x_gpio_base, 0x0001, fdc37c93x_gpio_read, NULL, NULL, fdc37c93x_gpio_write, NULL, NULL, NULL); } @@ -219,7 +213,6 @@ static void fdc37c932fr_access_bus_handler(void) if (global_enable && local_enable) { access_bus.base = ld_port = make_port(9); - /* pclog("fdc37c93x: Setting Auxiliary I/O port to %04X\n", ld_port); */ if ((ld_port >= 0x0100) && (ld_port <= 0x0FFC)) io_sethandler(access_bus.base, 0x0004, fdc37c932fr_access_bus_read, NULL, NULL, fdc37c932fr_access_bus_write, NULL, NULL, NULL); } @@ -576,7 +569,7 @@ static void fdc37c93x_init(void) { //FIXME: parallel_remove(2); - fdc37c93x_fdc = device_add(&fdc_at_smc_device); + fdc37c93x_fdc = (fdc_t *)device_add(&fdc_at_smc_device); fdc37c93x_gpio_reg = 0xFD; @@ -587,14 +580,10 @@ void fdc37c932fr_init(void) { fdc37c93x_init(); fdc37c932fr_reset(); - - pci_reset_handler.super_io_reset = fdc37c932fr_reset; } void fdc37c935_init(void) { fdc37c93x_init(); fdc37c935_reset(); - - pci_reset_handler.super_io_reset = fdc37c935_reset; } diff --git a/src/devices/sio/sio_pc87306.c b/src/devices/sio/sio_pc87306.c index 829d890..3240e3e 100644 --- a/src/devices/sio/sio_pc87306.c +++ b/src/devices/sio/sio_pc87306.c @@ -8,7 +8,7 @@ * * Emulation of the NatSemi PC87306 Super I/O chip. * - * Version: @(#)sio_pc87306.c 1.0.7 2018/05/06 + * Version: @(#)sio_pc87306.c 1.0.8 2018/10/05 * * Author: Miran Grca, * @@ -173,11 +173,7 @@ void serial2_handler() void pc87306_write(uint16_t port, uint8_t val, void *priv) { - uint8_t index; - uint8_t valxor; -#if 0 - uint16_t or_value; -#endif + uint8_t index, valxor; index = (port & 1) ? 0 : 1; @@ -264,27 +260,6 @@ process_value: fdc_set_base(pc87306_fdc, (val & 0x20) ? 0x370 : 0x3f0); } } - if (valxor & 0xc0) - { -#if 0 - ide_pri_disable(); - if (val & 0x80) - { - or_value = 0; - } - else - { - or_value = 0x80; - } - ide_set_base(0, 0x170 | or_value); - ide_set_side(0, 0x376 | or_value); - if (val & 0x40) - { - ide_pri_enable_ex(); - } -#endif - } - break; case 1: if (valxor & 3) @@ -471,7 +446,6 @@ void pc87306_reset(void) { memset(pc87306_regs, 0, 29); - /* pc87306_regs[0] = 0x4B; */ pc87306_regs[0] = 0x0B; pc87306_regs[1] = 0x01; pc87306_regs[3] = 0x01; @@ -501,13 +475,11 @@ void pc87306_reset(void) void pc87306_init() { - pc87306_fdc = device_add(&fdc_at_nsc_device); + pc87306_fdc = (fdc_t *)device_add(&fdc_at_nsc_device); //FIXME: parallel_remove(2); pc87306_reset(); io_sethandler(0x02e, 0x0002, pc87306_read, NULL, NULL, pc87306_write, NULL, NULL, NULL); - - pci_reset_handler.super_io_reset = pc87306_reset; } diff --git a/src/devices/sio/sio_um8669f.c b/src/devices/sio/sio_um8669f.c index 50e1fc9..7908c9f 100644 --- a/src/devices/sio/sio_um8669f.c +++ b/src/devices/sio/sio_um8669f.c @@ -29,7 +29,7 @@ * 70 - IRQ * 74 - DMA * - * Version: @(#)sio_um8669f.c 1.0.7 2018/05/06 + * Version: @(#)sio_um8669f.c 1.0.8 2018/09/19 * * Author: Miran Grca, * Sarah Walker, @@ -122,7 +122,6 @@ void um8669f_pnp_write(uint16_t port, uint8_t val, void *p) um8669f->cur_device = val & 7; else { -/* pclog("Write UM8669F %02x [%02x] %02x\n", um8669f->cur_reg, um8669f->cur_device, val); */ switch (um8669f->cur_reg) { case REG_ENABLE: @@ -150,8 +149,6 @@ void um8669f_pnp_write(uint16_t port, uint8_t val, void *p) break; } - /* pclog("UM8669F: Write %02X to [%02X][%02X]...\n", val, um8669f->cur_device, um8669f->cur_reg); */ - switch (um8669f->cur_device) { case DEV_FDC: @@ -200,8 +197,6 @@ uint8_t um8669f_pnp_read(uint16_t port, void *p) { um8669f_t *um8669f = (um8669f_t *)p; -/* pclog("Read UM8669F %02x\n", um8669f->cur_reg); */ - switch (um8669f->cur_reg) { case REG_DEVICE: @@ -243,7 +238,6 @@ void um8669f_write(uint16_t port, uint8_t val, void *p) } else { -/* pclog("Write UM8669f register %02x %02x %04x:%04x %i\n", um8669f_curreg, val, CS,cpu_state.pc, ins); */ um8669f->regs_108[um8669f->cur_reg_108] = val; if (um8669f->cur_reg_108 == 0xc1) { @@ -270,7 +264,6 @@ uint8_t um8669f_read(uint16_t port, void *p) { um8669f_t *um8669f = (um8669f_t *)p; -/* pclog("um8669f_read : port=%04x reg %02X locked=%i %02x\n", port, um8669f_curreg, um8669f_locked, um8669f_regs[um8669f_curreg]); */ if (um8669f->locked) return 0xff; @@ -335,11 +328,9 @@ void um8669f_reset(void) void um8669f_init(void) { - um8669f_global.fdc = device_add(&fdc_at_device); + um8669f_global.fdc = (fdc_t *)device_add(&fdc_at_device); io_sethandler(0x0108, 0x0002, um8669f_read, NULL, NULL, um8669f_write, NULL, NULL, &um8669f_global); um8669f_reset(); - - pci_reset_handler.super_io_reset = um8669f_reset; } diff --git a/src/devices/sio/sio_w83877f.c b/src/devices/sio/sio_w83877f.c index 6e610c7..f3263d1 100644 --- a/src/devices/sio/sio_w83877f.c +++ b/src/devices/sio/sio_w83877f.c @@ -11,7 +11,7 @@ * Winbond W83877F Super I/O Chip * Used by the Award 430HX * - * Version: @(#)sio_w83877f.c 1.0.7 2018/05/06 + * Version: @(#)sio_w83877f.c 1.0.8 2018/10/05 * * Author: Miran Grca, * @@ -40,7 +40,6 @@ #include #include #include "../../emu.h" -#include "../../machines/machine.h" #include "../../io.h" #include "../../mem.h" #include "../../rom.h" @@ -65,8 +64,9 @@ static int winbond_key = 0x89; static int winbond_key_times = 1; -void w83877f_write(uint16_t port, uint8_t val, void *priv); -uint8_t w83877f_read(uint16_t port, void *priv); +static void w83877f_write(uint16_t port, uint8_t val, void *priv); +static uint8_t w83877f_read(uint16_t port, void *priv); + #define OCSS0 (w83877f_regs[0] & 1) #define OCSS1 ((w83877f_regs[0] >> 1) & 1) @@ -235,330 +235,334 @@ static uint16_t com1_valid_ports[9] = {0x3F8, 0x2F8, 0x3E8, 0x2E8}; static uint16_t com2_valid_ports[9] = {0x3F8, 0x2F8, 0x3E8, 0x2E8}; -static void w83877f_remap(void) +static void +w83877f_remap(void) { - io_removehandler(0x250, 0x0002, w83877f_read, NULL, NULL, w83877f_write, NULL, NULL, NULL); - io_removehandler(0x3f0, 0x0002, w83877f_read, NULL, NULL, w83877f_write, NULL, NULL, NULL); - io_sethandler(HEFRAS ? 0x3f0 : 0x250, 0x0002, w83877f_read, NULL, NULL, w83877f_write, NULL, NULL, NULL); - winbond_port = (HEFRAS ? 0x3f0 : 0x250); - winbond_key_times = HEFRAS + 1; - winbond_key = (HEFRAS ? 0x86 : 0x88) | HEFERE; - /* pclog("W83877F: Remapped to port %04X, key %02X\n", winbond_port, winbond_key); */ + io_removehandler(0x250, 2, + w83877f_read,NULL,NULL, w83877f_write,NULL,NULL, NULL); + io_removehandler(0x3f0, 2, + w83877f_read,NULL,NULL, w83877f_write,NULL,NULL, NULL); + + io_sethandler(HEFRAS ? 0x3f0 : 0x250, 2, + w83877f_read,NULL,NULL, w83877f_write,NULL,NULL, NULL); + + winbond_port = (HEFRAS ? 0x3f0 : 0x250); + winbond_key_times = HEFRAS + 1; + winbond_key = (HEFRAS ? 0x86 : 0x88) | HEFERE; } -static uint8_t is_in_array(uint16_t *port_array, uint8_t max, uint16_t port) +static uint8_t +is_in_array(uint16_t *port_array, uint8_t max, uint16_t port) { - uint8_t i = 0; + uint8_t i = 0; - for (i = 0; i < max; i++) - { - if (port_array[i] == port) return 1; - } - return 0; + for (i = 0; i < max; i++) + if (port_array[i] == port) return 1; + + return 0; } -static uint16_t make_port(uint8_t reg) +static uint16_t +make_port(uint8_t reg) { - uint16_t p = 0; + uint16_t p = 0; - switch(reg) - { - case 0x20: - p = ((uint16_t) (w83877f_regs[reg] & 0xfc)) << 2; - p &= 0xFF0; - if ((p < 0x100) || (p > 0x3F0)) p = 0x3F0; - if (!(is_in_array(fdc_valid_ports, 2, p))) p = 0x3F0; - w83877f_regs[reg] = ((p >> 2) & 0xfc) | (w83877f_regs[reg] & 3); - break; - case 0x21: - p = ((uint16_t) (w83877f_regs[reg] & 0xfc)) << 2; - p &= 0xFF0; - if ((p < 0x100) || (p > 0x3F0)) p = 0x1F0; - if (!(is_in_array(ide_valid_ports, 2, p))) p = 0x1F0; - w83877f_regs[reg] = ((p >> 2) & 0xfc) | (w83877f_regs[reg] & 3); - break; - case 0x22: - p = ((uint16_t) (w83877f_regs[reg] & 0xfc)) << 2; - p &= 0xFF0; - if ((p < 0x106) || (p > 0x3F6)) p = 0x3F6; - if (!(is_in_array(ide_as_valid_ports, 2, p))) p = 0x3F6; - w83877f_regs[reg] = ((p >> 2) & 0xfc) | (w83877f_regs[reg] & 3); - break; - case 0x23: - p = ((uint16_t) (w83877f_regs[reg] & 0xff)) << 2; - p &= 0xFFC; - if ((p < 0x100) || (p > 0x3F8)) p = 0x378; - if (!(is_in_array(lpt1_valid_ports, 3, p))) p = 0x378; - w83877f_regs[reg] = (p >> 2); - break; - case 0x24: - p = ((uint16_t) (w83877f_regs[reg] & 0xfe)) << 2; - p &= 0xFF8; - if ((p < 0x100) || (p > 0x3F8)) p = 0x3F8; - if (!(is_in_array(com1_valid_ports, 9, p))) p = 0x3F8; - w83877f_regs[reg] = ((p >> 2) & 0xfe) | (w83877f_regs[reg] & 1); - break; - case 0x25: - p = ((uint16_t) (w83877f_regs[reg] & 0xfe)) << 2; - p &= 0xFF8; - if ((p < 0x100) || (p > 0x3F8)) p = 0x2F8; - if (!(is_in_array(com2_valid_ports, 9, p))) p = 0x2F8; - w83877f_regs[reg] = ((p >> 2) & 0xfe) | (w83877f_regs[reg] & 1); - break; - } + switch(reg) { + case 0x20: + p = ((uint16_t) (w83877f_regs[reg] & 0xfc)) << 2; + p &= 0xFF0; + if ((p < 0x100) || (p > 0x3F0)) p = 0x3F0; + if (!(is_in_array(fdc_valid_ports, 2, p))) p = 0x3F0; + w83877f_regs[reg] = ((p >> 2) & 0xfc) | (w83877f_regs[reg] & 3); + break; - return p; + case 0x21: + p = ((uint16_t) (w83877f_regs[reg] & 0xfc)) << 2; + p &= 0xFF0; + if ((p < 0x100) || (p > 0x3F0)) p = 0x1F0; + if (!(is_in_array(ide_valid_ports, 2, p))) p = 0x1F0; + w83877f_regs[reg] = ((p >> 2) & 0xfc) | (w83877f_regs[reg] & 3); + break; + + case 0x22: + p = ((uint16_t) (w83877f_regs[reg] & 0xfc)) << 2; + p &= 0xFF0; + if ((p < 0x106) || (p > 0x3F6)) p = 0x3F6; + if (!(is_in_array(ide_as_valid_ports, 2, p))) p = 0x3F6; + w83877f_regs[reg] = ((p >> 2) & 0xfc) | (w83877f_regs[reg] & 3); + break; + + case 0x23: + p = ((uint16_t) (w83877f_regs[reg] & 0xff)) << 2; + p &= 0xFFC; + if ((p < 0x100) || (p > 0x3F8)) p = 0x378; + if (!(is_in_array(lpt1_valid_ports, 3, p))) p = 0x378; + w83877f_regs[reg] = (p >> 2); + break; + + case 0x24: + p = ((uint16_t) (w83877f_regs[reg] & 0xfe)) << 2; + p &= 0xFF8; + if ((p < 0x100) || (p > 0x3F8)) p = 0x3F8; + if (!(is_in_array(com1_valid_ports, 9, p))) p = 0x3F8; + w83877f_regs[reg] = ((p >> 2) & 0xfe) | (w83877f_regs[reg] & 1); + break; + + case 0x25: + p = ((uint16_t) (w83877f_regs[reg] & 0xfe)) << 2; + p &= 0xFF8; + if ((p < 0x100) || (p > 0x3F8)) p = 0x2F8; + if (!(is_in_array(com2_valid_ports, 9, p))) p = 0x2F8; + w83877f_regs[reg] = ((p >> 2) & 0xfe) | (w83877f_regs[reg] & 1); + break; + } + + return p; } -void w83877f_serial_handler(int id) +static void +serial_handler(int id) { - int reg_mask = (id - 1) ? 0x10 : 0x20; - int reg_id = (id - 1) ? 0x24 : 0x25; - int irq_mask = (id - 1) ? 0xF : 0xF0; + int reg_mask = (id - 1) ? 0x10 : 0x20; + int reg_id = (id - 1) ? 0x24 : 0x25; + int irq_mask = (id - 1) ? 0xF : 0xF0; - /* pclog("Registers (%i): %02X %02X %02X\n", id, w83877f_regs[4], w83877f_regs[reg_id], w83877f_regs[0x28]); */ - - if ((w83877f_regs[4] & reg_mask) || !(w83877f_regs[reg_id] & 0xc0)) - { + if ((w83877f_regs[4] & reg_mask) || !(w83877f_regs[reg_id] & 0xc0)) { #if 0 - serial_remove(id); + serial_remove(id); #endif - } - else - { - serial_setup(id, make_port(reg_id), w83877f_regs[0x28] & irq_mask); - } + } else { + serial_setup(id, make_port(reg_id), w83877f_regs[0x28] & irq_mask); + } } -void w83877f_write(uint16_t port, uint8_t val, void *priv) +static void +w83877f_write(uint16_t port, uint8_t val, void *priv) { - uint8_t index = (port & 1) ? 0 : 1; - uint8_t valxor = 0; - uint8_t max = 0x2A; + uint8_t index = (port & 1) ? 0 : 1; + uint8_t valxor = 0; + uint8_t max = 0x2A; - if (index) - { - if ((val == winbond_key) && !w83877f_locked) - { - if (winbond_key_times == 2) - { - if (tries) - { - w83877f_locked = 1; - tries = 0; - } - else - { - tries++; - } - } - else - { + if (index) { + if ((val == winbond_key) && !w83877f_locked) { + if (winbond_key_times == 2) { + if (tries) { w83877f_locked = 1; tries = 0; + } else { + tries++; } + } else { + w83877f_locked = 1; + tries = 0; } - else - { - if (w83877f_locked) - { - if (val < max) w83877f_curreg = val; - if (val == 0xaa) - { - w83877f_locked = 0; - } - } - else - { - if (tries) - tries = 0; + } else { + if (w83877f_locked) { + if (val < max) w83877f_curreg = val; + if (val == 0xaa) { + w83877f_locked = 0; } + } else { + if (tries) + tries = 0; } } - else - { - if (w83877f_locked) - { - if (w83877f_rw_locked) return; - if ((w83877f_curreg >= 0x26) && (w83877f_curreg <= 0x27)) return; - if (w83877f_curreg == 0x29) return; - if (w83877f_curreg == 6) val &= 0xF3; - valxor = val ^ w83877f_regs[w83877f_curreg]; - w83877f_regs[w83877f_curreg] = val; - goto process_value; - } + } else { + if (w83877f_locked) { + if (w83877f_rw_locked) return; + + if ((w83877f_curreg >= 0x26) && (w83877f_curreg <= 0x27)) + return; + + if (w83877f_curreg == 0x29) + return; + + if (w83877f_curreg == 6) val &= 0xF3; + valxor = val ^ w83877f_regs[w83877f_curreg]; + w83877f_regs[w83877f_curreg] = val; + goto process_value; } - return; + } + return; process_value: - switch(w83877f_curreg) - { - case 1: - if (valxor & 0x80) - { - fdc_set_swap(w83877f_fdc, (w83877f_regs[1] & 0x80) ? 1 : 0); - } - break; - case 4: - if (valxor & 0x10) - { - w83877f_serial_handler(2); - } - if (valxor & 0x20) - { - w83877f_serial_handler(1); - } - if (valxor & 0x80) - { -//FIXME: parallel_remove(1); - if (!(w83877f_regs[4] & 0x80)) parallel_setup(1, make_port(0x23)); - } - break; - case 6: - if (valxor & 0x08) - { - fdc_remove(w83877f_fdc); - if (!(w83877f_regs[6] & 0x08)) fdc_set_base(w83877f_fdc, 0x03f0); - } - break; - case 7: - if (valxor & 3) fdc_update_rwc(w83877f_fdc, 0, FDDA_TYPE); - if (valxor & 0xC) fdc_update_rwc(w83877f_fdc, 1, FDDB_TYPE); - if (valxor & 0x30) fdc_update_rwc(w83877f_fdc, 2, FDDC_TYPE); - if (valxor & 0xC0) fdc_update_rwc(w83877f_fdc, 3, FDDD_TYPE); - break; - case 8: - if (valxor & 3) fdc_update_boot_drive(w83877f_fdc, FD_BOOT); - if (valxor & 0x10) fdc_set_swwp(w83877f_fdc, SWWP ? 1 : 0); - if (valxor & 0x20) fdc_set_diswr(w83877f_fdc, DISFDDWR ? 1 : 0); - break; - case 9: - if (valxor & 0x20) - { - fdc_update_enh_mode(w83877f_fdc, EN3MODE ? 1 : 0); - } - if (valxor & 0x40) - { - w83877f_rw_locked = (val & 0x40) ? 1 : 0; - } - break; - case 0xB: - if (valxor & 1) fdc_update_drv2en(w83877f_fdc, DRV2EN_NEG ? 0 : 1); - if (valxor & 2) fdc_update_densel_polarity(w83877f_fdc, INVERTZ ? 1 : 0); - break; - case 0xC: - if (valxor & 0x20) w83877f_remap(); - break; - case 0x16: - if (valxor & 1) w83877f_remap(); - break; - case 0x23: - if (valxor) - { -//FIXME: parallel_remove(1); - if (!(w83877f_regs[4] & 0x80)) parallel_setup(1, make_port(0x23)); - } - break; - case 0x24: - if (valxor & 0xfe) - { - w83877f_serial_handler(1); - } - break; - case 0x25: - if (valxor & 0xfe) - { - w83877f_serial_handler(2); - } - break; - case 0x28: - if (valxor & 0xf) - { - if ((w83877f_regs[0x28] & 0xf) == 0) w83877f_regs[0x28] |= 0x3; - if (!(w83877f_regs[2] & 0x10)) serial_setup(2, make_port(0x25), w83877f_regs[0x28] & 0xF); - } - if (valxor & 0xf0) - { - if ((w83877f_regs[0x28] & 0xf0) == 0) w83877f_regs[0x28] |= 0x40; - if (!(w83877f_regs[4] & 0x20)) - { - serial_setup(1, make_port(0x24), (w83877f_regs[0x28] & 0xF0) >> 8); - } - } - break; - } + switch(w83877f_curreg) { + case 1: + if (valxor & 0x80) + fdc_set_swap(w83877f_fdc, (w83877f_regs[1] & 0x80) ? 1 : 0); + break; + + case 4: + if (valxor & 0x10) + serial_handler(2); + + if (valxor & 0x20) + serial_handler(1); + + if (valxor & 0x80) { +//FIXME: parallel_remove(1); + if (! (w83877f_regs[4] & 0x80)) + parallel_setup(1, make_port(0x23)); + } + break; + + case 6: + if (valxor & 0x08) { + fdc_remove(w83877f_fdc); + if (! (w83877f_regs[6] & 0x08)) + fdc_set_base(w83877f_fdc, 0x03f0); + } + break; + + case 7: + if (valxor & 3) + fdc_update_rwc(w83877f_fdc, 0, FDDA_TYPE); + if (valxor & 0xC) + fdc_update_rwc(w83877f_fdc, 1, FDDB_TYPE); + if (valxor & 0x30) + fdc_update_rwc(w83877f_fdc, 2, FDDC_TYPE); + if (valxor & 0xC0) + fdc_update_rwc(w83877f_fdc, 3, FDDD_TYPE); + break; + + case 8: + if (valxor & 3) + fdc_update_boot_drive(w83877f_fdc, FD_BOOT); + if (valxor & 0x10) + fdc_set_swwp(w83877f_fdc, SWWP ? 1 : 0); + if (valxor & 0x20) + fdc_set_diswr(w83877f_fdc, DISFDDWR ? 1 : 0); + break; + + case 9: + if (valxor & 0x20) + fdc_update_enh_mode(w83877f_fdc, EN3MODE ? 1 : 0); + + if (valxor & 0x40) + w83877f_rw_locked = (val & 0x40) ? 1 : 0; + break; + + case 0xB: + if (valxor & 1) + fdc_update_drv2en(w83877f_fdc, DRV2EN_NEG ? 0 : 1); + if (valxor & 2) + fdc_update_densel_polarity(w83877f_fdc, INVERTZ ? 1 : 0); + break; + + case 0xC: + if (valxor & 0x20) + w83877f_remap(); + break; + + case 0x16: + if (valxor & 1) + w83877f_remap(); + break; + + case 0x23: + if (valxor) { +//FIXME: parallel_remove(1); + if (! (w83877f_regs[4] & 0x80)) + parallel_setup(1, make_port(0x23)); + } + break; + + case 0x24: + if (valxor & 0xfe) + serial_handler(1); + break; + + case 0x25: + if (valxor & 0xfe) + serial_handler(2); + break; + + case 0x28: + if (valxor & 0xf) { + if ((w83877f_regs[0x28] & 0xf) == 0) + w83877f_regs[0x28] |= 0x3; + if (! (w83877f_regs[2] & 0x10)) + serial_setup(2, make_port(0x25), w83877f_regs[0x28] & 0xF); + } + + if (valxor & 0xf0) { + if ((w83877f_regs[0x28] & 0xf0) == 0) w83877f_regs[0x28] |= 0x40; + if (!(w83877f_regs[4] & 0x20)) + serial_setup(1, make_port(0x24), (w83877f_regs[0x28] & 0xF0) >> 8); + } + break; + } } -uint8_t w83877f_read(uint16_t port, void *priv) +static uint8_t +w83877f_read(uint16_t port, void *priv) { - uint8_t index = (port & 1) ? 0 : 1; + uint8_t index = (port & 1) ? 0 : 1; - if (!w83877f_locked) - { - return 0xff; - } + if (! w83877f_locked) + return 0xff; - if (index) - { - return w83877f_curreg; - } - else - { - if ((w83877f_curreg < 0x18) && w83877f_rw_locked) return 0xff; - if (w83877f_curreg == 7) - return (fdc_get_rwc(w83877f_fdc, 0) | (fdc_get_rwc(w83877f_fdc, 1) << 2)); - return w83877f_regs[w83877f_curreg]; - } + if (index) + return w83877f_curreg; + + if ((w83877f_curreg < 0x18) && w83877f_rw_locked) return 0xff; + + if (w83877f_curreg == 7) + return (fdc_get_rwc(w83877f_fdc, 0) | (fdc_get_rwc(w83877f_fdc, 1) << 2)); + + return w83877f_regs[w83877f_curreg]; } -void w83877f_reset(void) +static void +w83877f_reset(int flag) { //FIXME: parallel_remove(1); - parallel_setup(1, 0x378); + parallel_setup(1, 0x378); - fdc_reset(w83877f_fdc); + fdc_reset(w83877f_fdc); - memset(w83877f_regs, 0, 0x2A); - w83877f_regs[3] = 0x30; - w83877f_regs[7] = 0xF5; - w83877f_regs[9] = 0x0A; - w83877f_regs[0xA] = 0x1F; - w83877f_regs[0xC] = 0x28; - w83877f_regs[0xD] = 0xA3; - w83877f_regs[0x16] = (romset == ROM_PRESIDENT) ? 4 : 5; - w83877f_regs[0x1E] = 0x81; - w83877f_regs[0x20] = (0x3f0 >> 2) & 0xfc; - w83877f_regs[0x21] = (0x1f0 >> 2) & 0xfc; - w83877f_regs[0x22] = ((0x3f6 >> 2) & 0xfc) | 1; - w83877f_regs[0x23] = (0x378 >> 2); - w83877f_regs[0x24] = (0x3f8 >> 2) & 0xfe; - w83877f_regs[0x25] = (0x2f8 >> 2) & 0xfe; - w83877f_regs[0x26] = (2 << 4) | 4; - w83877f_regs[0x27] = (6 << 4) | 7; - w83877f_regs[0x28] = (4 << 4) | 3; - w83877f_regs[0x29] = 0x62; + memset(w83877f_regs, 0, 0x2A); + w83877f_regs[3] = 0x30; + w83877f_regs[7] = 0xF5; + w83877f_regs[9] = 0x0A; + w83877f_regs[0xA] = 0x1F; + w83877f_regs[0xC] = 0x28; + w83877f_regs[0xD] = 0xA3; + w83877f_regs[0x16] = (flag) ? 4 : 5; + w83877f_regs[0x1E] = 0x81; + w83877f_regs[0x20] = (0x3f0 >> 2) & 0xfc; + w83877f_regs[0x21] = (0x1f0 >> 2) & 0xfc; + w83877f_regs[0x22] = ((0x3f6 >> 2) & 0xfc) | 1; + w83877f_regs[0x23] = (0x378 >> 2); + w83877f_regs[0x24] = (0x3f8 >> 2) & 0xfe; + w83877f_regs[0x25] = (0x2f8 >> 2) & 0xfe; + w83877f_regs[0x26] = (2 << 4) | 4; + w83877f_regs[0x27] = (6 << 4) | 7; + w83877f_regs[0x28] = (4 << 4) | 3; + w83877f_regs[0x29] = 0x62; - serial_setup(1, SERIAL1_ADDR, SERIAL1_IRQ); - serial_setup(2, SERIAL2_ADDR, SERIAL2_IRQ); - w83877f_remap(); - w83877f_locked = 0; - w83877f_rw_locked = 0; + serial_setup(1, SERIAL1_ADDR, SERIAL1_IRQ); + serial_setup(2, SERIAL2_ADDR, SERIAL2_IRQ); + + w83877f_remap(); + + w83877f_locked = 0; + w83877f_rw_locked = 0; } -void w83877f_init(void) +void +w83877f_init(int flag) { - w83877f_fdc = device_add(&fdc_at_winbond_device); + w83877f_fdc = (fdc_t *)device_add(&fdc_at_winbond_device); //FIXME: parallel_remove(2); - w83877f_reset(); - - pci_reset_handler.super_io_reset = w83877f_reset; + w83877f_reset(flag); } diff --git a/src/devices/sound/dbopl.cpp b/src/devices/sound/dbopl.cpp index 3fa9152..219a2cb 100644 --- a/src/devices/sound/dbopl.cpp +++ b/src/devices/sound/dbopl.cpp @@ -28,7 +28,7 @@ * multipliers sounds better or not * DUNNO Keyon in 4op, switch to 2op without keyoff. * - * Version: @(#)dbopl.cpp 1.0.1 2018/02/14 + * Version: @(#)dbopl.cpp 1.0.2 2018/09/15 * * Based on (dbopl.cpp,v 1.10 2009-06-10 19:54:51 harekiet) * diff --git a/src/devices/sound/midi.c b/src/devices/sound/midi.c index 81fe683..346be53 100644 --- a/src/devices/sound/midi.c +++ b/src/devices/sound/midi.c @@ -8,7 +8,7 @@ * * MIDI support module, main file. * - * Version: @(#)midi.c 1.0.6 2018/05/06 + * Version: @(#)midi.c 1.0.7 2018/09/22 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -40,10 +40,14 @@ #include #include #include +#include #include +#define HAVE_STDARG_H +#define dbglog sound_midi_log #include "../../emu.h" #include "../../device.h" #include "../../plat.h" +#include "sound.h" #include "midi.h" #include "midi_system.h" #ifdef USE_FLUIDSYNTH @@ -58,41 +62,30 @@ #define RAWBUF 1024 -int midi_device_current = 0; - - typedef struct { - const char *name; - const char *internal_name; - const device_t *device; + uint8_t rt_buf[1024], + cmd_buf[1024], + status, + sysex_data[1026]; + + int cmd_pos, + cmd_len; + + unsigned int sysex_start, + sysex_delay, + pos; + + const midi_device_t *device; } midi_t; -static const midi_t devices[] = { - {"Disabled", "none", NULL }, -#ifdef USE_FLUIDSYNTH - {"FluidSynth", "fluidsynth", &fluidsynth_device}, +#ifdef ENABLE_SOUND_MIDI_LOG +int sound_midi_do_log = ENABLE_SOUND_MIDI_LOG; #endif -#ifdef USE_MUNT - {"Roland MT-32 Emulation", "mt32", &mt32_device }, - {"Roland CM-32L Emulation", "cm32l", &cm32l_device }, -#endif - {SYSTEM_MIDI_NAME, SYSTEM_MIDI_INT, &system_midi_device}, - {NULL, NULL, NULL } -}; -static const midi_device_t *m_device = NULL; -static int midi_device_last = 0; -static uint8_t midi_rt_buf[1024]; -static uint8_t midi_cmd_buf[1024]; -static int midi_cmd_pos = 0; -static int midi_cmd_len = 0; -static uint8_t midi_status = 0; -static unsigned int midi_pos; -static unsigned int midi_sysex_start = 0; -static unsigned int midi_sysex_delay = 0; -static uint8_t midi_sysex_data[1024+2]; +static midi_t *midi = NULL; + static const uint8_t MIDI_evt_len[256] = { 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // 0x00 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // 0x10 @@ -115,6 +108,21 @@ static const uint8_t MIDI_evt_len[256] = { 0,2,3,2, 0,0,1,0, 1,0,1,1, 1,0,1,0 // 0xf0 }; +static struct { + const char *internal_name; + const device_t *device; +} devices[] = { + {"none", NULL }, +#ifdef USE_FLUIDSYNTH + {"fluidsynth", &fluidsynth_device }, +#endif +#ifdef USE_MUNT + {"mt32", &mt32_device }, + {"cm32l", &cm32l_device }, +#endif + {SYSTEM_MIDI_INT, &system_midi_device }, + {NULL, NULL } +}; int @@ -130,7 +138,10 @@ midi_device_available(int card) const char * midi_device_getname(int card) { - return(devices[card].name); + if (devices[card].device != NULL) + return(devices[card].device->name); + + return(NULL); } @@ -144,9 +155,10 @@ midi_device_getdevice(int card) int midi_device_has_config(int card) { - if (devices[card].device == NULL) return(0); + if (devices[card].device != NULL) + return(devices[card].device->config ? 1 : 0); - return(devices[card].device->config ? 1 : 0); + return(0); } @@ -174,58 +186,69 @@ midi_device_get_from_internal_name(const char *s) void -midi_device_init(void) +sound_midi_log(int level, const char *fmt, ...) { - if (devices[midi_device_current].device != NULL) - device_add(devices[midi_device_current].device); +#ifdef ENABLE_SOUND_MIDI_LOG + va_list ap; - midi_device_last = midi_device_current; + if (sound_midi_do_log >= level) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +#endif } void -midi_init(const midi_device_t *device) +midi_device_init(void) { - memset(midi_rt_buf, 0, sizeof(midi_rt_buf)); - memset(midi_cmd_buf, 0, sizeof(midi_cmd_buf)); + if (devices[midi_device].device != NULL) + device_add(devices[midi_device].device); +} - midi_cmd_pos = midi_cmd_len = 0; - midi_status = 0; - midi_sysex_start = midi_sysex_delay = 0; +void +midi_init(const midi_device_t *dev) +{ + midi = (midi_t *)mem_alloc(sizeof(midi_t)); + memset(midi, 0, sizeof(midi_t)); - m_device = device; + midi->device = dev; } void midi_close(void) { - m_device = NULL; + if (midi != NULL) { + free(midi); + midi = NULL; + } } void midi_poll(void) { - if (m_device && m_device->poll) - m_device->poll(); + if (midi && midi->device && midi->device->poll) + midi->device->poll(); } void play_msg(uint8_t *msg) { - if (m_device->play_msg) - m_device->play_msg(msg); + if (midi && midi->device && midi->device->play_msg) + midi->device->play_msg(msg); } void play_sysex(uint8_t *sysex, unsigned int len) { - if (m_device->play_sysex) - m_device->play_sysex(sysex, len); + if (midi && midi->device && midi->device->play_sysex) + midi->device->play_sysex(sysex, len); } @@ -234,67 +257,72 @@ midi_write(uint8_t val) { uint32_t passed_ticks; - if (m_device == NULL) return; + if (!midi || !midi->device) return; - if (m_device->write && m_device->write(val)) return; + if (midi->device->write && midi->device->write(val)) return; - if (midi_sysex_start) { - passed_ticks = plat_get_ticks() - midi_sysex_start; - if (passed_ticks < midi_sysex_delay) - plat_delay_ms(midi_sysex_delay - passed_ticks); + if (midi->sysex_start) { + passed_ticks = plat_get_ticks() - midi->sysex_start; + if (passed_ticks < midi->sysex_delay) + plat_delay_ms(midi->sysex_delay - passed_ticks); } /* Test for a realtime MIDI message */ if (val >= 0xf8) { - midi_rt_buf[0] = val; - play_msg(midi_rt_buf); + midi->rt_buf[0] = val; + play_msg(midi->rt_buf); return; } /* Test for a active sysex transfer */ - if (midi_status == 0xf0) { - if (! (val & 0x80)) { - if (midi_pos < (SYSEX_SIZE-1)) midi_sysex_data[midi_pos++] = val; + if (midi->status == 0xf0) { + if (!(val & 0x80)) { + if (midi->pos < (SYSEX_SIZE-1)) + midi->sysex_data[midi->pos++] = val; return; } else { - midi_sysex_data[midi_pos++] = 0xf7; - - if ((midi_sysex_start) && (midi_pos >= 4) && (midi_pos <= 9) && (midi_sysex_data[1] == 0x41) && (midi_sysex_data[3] == 0x16)) { - /* pclog("MIDI: Skipping invalid MT-32 SysEx MIDI message\n"); */ + midi->sysex_data[midi->pos++] = 0xf7; + if ((midi->sysex_start) && (midi->pos >= 4) && + (midi->pos <= 9) && (midi->sysex_data[1] == 0x41) && + (midi->sysex_data[3] == 0x16)) { + DEBUG("MIDI: Skipping invalid MT-32 SysEx MIDI message\n"); } else { - play_sysex(midi_sysex_data, midi_pos); - if (midi_sysex_start) { - if (midi_sysex_data[5] == 0x7f) { - midi_sysex_delay = 290; /* All parameters reset */ - } else if ((midi_sysex_data[5] == 0x10) && (midi_sysex_data[6] == 0x00) && (midi_sysex_data[7] == 0x04)) { - midi_sysex_delay = 145; /* Viking Child */ - } else if ((midi_sysex_data[5] == 0x10) && (midi_sysex_data[6] == 0x00) && (midi_sysex_data[7] == 0x01)) { - midi_sysex_delay = 30; /* Dark Sun 1 */ - } else - midi_sysex_delay = (unsigned int) (((float) (midi_pos) * 1.25f) * 1000.0f / 3125.0f) + 2; - - midi_sysex_start = plat_get_ticks(); + play_sysex(midi->sysex_data, midi->pos); + if (midi->sysex_start) { + if (midi->sysex_data[5] == 0x7f) + /* All parameters reset */ + midi->sysex_delay = 290; + else if ((midi->sysex_data[5] == 0x10) && + (midi->sysex_data[6] == 0x00) && + (midi->sysex_data[7] == 0x04)) + midi->sysex_delay = 145; /* Viking Child */ + else if ((midi->sysex_data[5] == 0x10) && + (midi->sysex_data[6] == 0x00) && + (midi->sysex_data[7] == 0x01)) + midi->sysex_delay = 30; /* Dark Sun 1 */ + else + midi->sysex_delay = (unsigned int) (((float) (midi->pos) * 1.25f) * 1000.0f / 3125.0f) + 2; + midi->sysex_start = plat_get_ticks(); } } } } if (val & 0x80) { - midi_status = val; - midi_cmd_pos = 0; - midi_cmd_len = MIDI_evt_len[val]; - - if (midi_status == 0xf0) { - midi_sysex_data[0] = 0xf0; - midi_pos = 1; + midi->status = val; + midi->cmd_pos = 0; + midi->cmd_len = MIDI_evt_len[val]; + if (midi->status == 0xf0) { + midi->sysex_data[0] = 0xf0; + midi->pos = 1; } } - if (midi_cmd_len) { - midi_cmd_buf[midi_cmd_pos++] = val; - if (midi_cmd_pos >= midi_cmd_len) { - play_msg(midi_cmd_buf); - midi_cmd_pos = 1; + if (midi->cmd_len) { + midi->cmd_buf[midi->cmd_pos++] = val; + if (midi->cmd_pos >= midi->cmd_len) { + play_msg(midi->cmd_buf); + midi->cmd_pos = 1; } } } diff --git a/src/devices/sound/midi.h b/src/devices/sound/midi.h index a926ace..1f5811b 100644 --- a/src/devices/sound/midi.h +++ b/src/devices/sound/midi.h @@ -8,7 +8,7 @@ * * Definitions for the MIDI module. * - * Version: @(#)midi.h 1.0.5 2018/04/14 + * Version: @(#)midi.h 1.0.6 2018/09/15 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -50,10 +50,10 @@ typedef struct { - void (*play_sysex)(uint8_t *sysex, unsigned int len); - void (*play_msg)(uint8_t *msg); - void (*poll)(void); - int (*write)(uint8_t val); + void (*play_sysex)(uint8_t *sysex, unsigned int len); + void (*play_msg)(uint8_t *msg); + void (*poll)(void); + int (*write)(uint8_t val); } midi_device_t; @@ -67,6 +67,7 @@ extern const char *midi_device_get_internal_name(int card); extern int midi_device_get_from_internal_name(const char *s); extern void midi_device_init(void); +extern void sound_midi_log(int level, const char *fmt, ...); extern void midi_init(const midi_device_t *device); extern void midi_close(void); extern void midi_write(uint8_t val); diff --git a/src/devices/sound/midi_fluidsynth.c b/src/devices/sound/midi_fluidsynth.c index a9ba901..981d106 100644 --- a/src/devices/sound/midi_fluidsynth.c +++ b/src/devices/sound/midi_fluidsynth.c @@ -17,7 +17,7 @@ * website (for 32bit and 64bit Windows) are working, and * need no additional support files other than sound fonts. * - * Version: @(#)midi_fluidsynth.c 1.0.11 2018/05/24 + * Version: @(#)midi_fluidsynth.c 1.0.12 2018/10/05 * * Code borrowed from scummvm. * @@ -53,6 +53,7 @@ #include #include #include +#define dbglog sound_midi_log #include "../../emu.h" #include "../../config.h" #include "../../device.h" @@ -73,11 +74,6 @@ #endif -extern void givealbuffer_midi(void *buf, uint32_t size); -extern void al_set_midi(int freq, int buf_size); -extern int soundon; - - static void *fluidsynth_handle = NULL; /* handle to FluidSynth DLL */ /* Pointers to the real functions. */ @@ -186,7 +182,7 @@ fluidsynth_thread(void *param) buf_pos += buf_size; if (buf_pos >= data->buf_size) { if (soundon) - givealbuffer_midi(data->buffer, data->buf_size / sizeof(float)); + openal_buffer_midi(data->buffer, data->buf_size / sizeof(float)); buf_pos = 0; } } else { @@ -197,7 +193,7 @@ fluidsynth_thread(void *param) buf_pos += buf_size; if (buf_pos >= data->buf_size) { if (soundon) - givealbuffer_midi(data->buffer_int16, data->buf_size / sizeof(int16_t)); + openal_buffer_midi(data->buffer_int16, data->buf_size / sizeof(int16_t)); buf_pos = 0; } } @@ -208,13 +204,13 @@ fluidsynth_thread(void *param) if (data->synth) f_fluid_synth_write_float(data->synth, data->buf_size/2, data->buffer, 0, 2, data->buffer, 1, 2); if (soundon) - givealbuffer_midi(data->buffer, data->buf_size); + openal_buffer_midi(data->buffer, data->buf_size); } else { memset(data->buffer, 0, data->buf_size * sizeof(int16_t)); if (data->synth) f_fluid_synth_write_s16(data->synth, data->buf_size/2, data->buffer_int16, 0, 2, data->buffer_int16, 1, 2); if (soundon) - givealbuffer_midi(data->buffer_int16, data->buf_size); + openal_buffer_midi(data->buffer_int16, data->buf_size); } #endif } @@ -262,9 +258,7 @@ fluidsynth_msg(uint8_t *msg) break; default: -#if 0 - pclog("fluidsynth: unknown send() command 0x%02X", cmd); -#endif + DEBUG("fluidsynth: unknown send() command 0x%02X", cmd); break; } } @@ -345,23 +339,22 @@ fluidsynth_init(const device_t *info) data->samplerate = (int)samplerate; if (sound_is_float) { data->buf_size = (data->samplerate/RENDER_RATE)*2*sizeof(float)*BUFFER_SEGMENTS; - data->buffer = malloc(data->buf_size); + data->buffer = (float *)mem_alloc(data->buf_size); data->buffer_int16 = NULL; } else { data->buf_size = (data->samplerate/RENDER_RATE)*2*sizeof(int16_t)*BUFFER_SEGMENTS; data->buffer = NULL; - data->buffer_int16 = malloc(data->buf_size); + data->buffer_int16 = (int16_t *)mem_alloc(data->buf_size); } data->event = thread_create_event(); data->thread_h = thread_create(fluidsynth_thread, data); - al_set_midi(data->samplerate, data->buf_size); + openal_set_midi(data->samplerate, data->buf_size); -#if 1 - pclog("fluidsynth (%s) initialized, samplerate %d, buf_size %d\n", f_fluid_version_str(), data->samplerate, data->buf_size); -#endif + DEBUG("fluidsynth (%s) initialized, samplerate %d, buf_size %d\n", + f_fluid_version_str(), data->samplerate, data->buf_size); - midi_device_t* dev = malloc(sizeof(midi_device_t)); + midi_device_t *dev = (midi_device_t *)mem_alloc(sizeof(midi_device_t)); memset(dev, 0, sizeof(midi_device_t)); dev->play_msg = fluidsynth_msg; @@ -378,11 +371,7 @@ static void fluidsynth_close(void* priv) { if (priv == NULL) return; - - if (fluidsynth_handle == NULL) { - ui_msgbox(MBX_ERROR, (wchar_t *)IDS_ERR_FSYNTH); - return; - } + if (fluidsynth_handle == NULL) return; fluidsynth_t* data = &fsdev; @@ -424,188 +413,150 @@ fluidsynth_close(void* priv) void fluidsynth_global_init(void) { + wchar_t temp[512]; + const char *fn = PATH_FS_DLL; + /* Try loading the DLL. */ - fluidsynth_handle = dynld_module(PATH_FS_DLL, fluidsynth_imports); + fluidsynth_handle = dynld_module(fn, fluidsynth_imports); if (fluidsynth_handle == NULL) { - pclog("SOUND: unable to load '%s', FluidSynth not available!\n", - PATH_FS_DLL); + swprintf(temp, sizeof_w(temp), + get_string(IDS_ERR_NOLIB), "FluidSynth", fn); + ui_msgbox(MBX_ERROR, temp); + ERRLOG("SOUND: unable to load '%s', FluidSynth not available!\n", fn); + } else { + INFO("SOUND: module '%s' loaded.\n", fn); } } static const device_config_t fluidsynth_config[] = { +#if 0 + { + "sound_font","Sound Font",CONFIG_FNAME,"",0, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { - .name = "sound_font", - .description = "Sound Font", - .type = CONFIG_FNAME, - .default_string = "", - .file_filter = { - { - .description = "SF2 Sound Fonts", - .extensions = - { - "sf2" - } - } + "SF2 Sound Fonts","sf2" } - }, - { - .name = "output_gain", - .description = "Output Gain", - .type = CONFIG_SPINNER, - .spinner = - { - .min = 0, - .max = 100 - }, - .default_int = 100 - }, - { - .name = "chorus", - .description = "Chorus", - .type = CONFIG_BINARY, - .default_int = 0 - }, - { - .name = "chorus_voices", - .description = "Chorus Voices", - .type = CONFIG_SPINNER, - .spinner = - { - .min = 0, - .max = 99 - }, - .default_int = 3 - }, - { - .name = "chorus_level", - .description = "Chorus Level", - .type = CONFIG_SPINNER, - .spinner = - { - .min = 0, - .max = 100 - }, - .default_int = 100 - }, - { - .name = "chorus_speed", - .description = "Chorus Speed", - .type = CONFIG_SPINNER, - .spinner = - { - .min = 30, - .max = 500 - }, - .default_int = 30 - }, - { - .name = "chorus_depth", - .description = "Chorus Depth", - .type = CONFIG_SPINNER, - .spinner = - { - .min = 0, - .max = 210 - }, - .default_int = 80 - }, - { - .name = "chorus_waveform", - .description = "Chorus Waveform", - .type = CONFIG_SELECTION, - .selection = - { - { - .description = "Sine", - .value = 0 - }, - { - .description = "Triangle", - .value = 1 - } - }, - .default_int = 0 - }, - { - .name = "reverb", - .description = "Reverb", - .type = CONFIG_BINARY, - .default_int = 0 - }, - { - .name = "reverb_room_size", - .description = "Reverb Room Size", - .type = CONFIG_SPINNER, - .spinner = - { - .min = 0, - .max = 120 - }, - .default_int = 20 - }, - { - .name = "reverb_damping", - .description = "Reverb Damping", - .type = CONFIG_SPINNER, - .spinner = - { - .min = 0, - .max = 100 - }, - .default_int = 0 - }, - { - .name = "reverb_width", - .description = "Reverb Width", - .type = CONFIG_SPINNER, - .spinner = - { - .min = 0, - .max = 100 - }, - .default_int = 1 - }, - { - .name = "reverb_level", - .description = "Reverb Level", - .type = CONFIG_SPINNER, - .spinner = - { - .min = 0, - .max = 100 - }, - .default_int = 90 - }, - { - .name = "interpolation", - .description = "Interpolation Method", - .type = CONFIG_SELECTION, - .selection = - { - { - .description = "None", - .value = 0 - }, - { - .description = "Linear", - .value = 1 - }, - { - .description = "4th Order", - .value = 2 - }, - { - .description = "7th Order", - .value = 3 - } - }, - .default_int = 2 - }, - { - .type = -1 } + }, + { + "output_gain","Output Gain",CONFIG_SPINNER,"",100, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { + 0, 100, 1 + } + }, +#endif + { + "chorus","Chorus",CONFIG_BINARY,"",0 + }, +#if 0 + { + "chorus_voices","Chorus Voices",CONFIG_SPINNER,"",3, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { + 0, 99, 1 + } + }, + { + "chorus_level","Chorus Level",CONFIG_SPINNER,"",100, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { + 0, 100, 1 + } + }, + { + "chorus_speed","Chorus Speed",CONFIG_SPINNER,"",30, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { + 30, 500, 10 + } + }, + { + "chorus_depth","Chorus Depth",CONFIG_SPINNER,"",80, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { + 0, 210, 10 + } + }, +#endif + { + "chorus_waveform","Chorus Waveform",CONFIG_SELECTION,"",0, + { + { + "Sine",0 + }, + { + "Triangle",1 + } + } + }, + { + "reverb","Reverb",CONFIG_BINARY,"",0 + }, +#if 0 + { + "reverb_room_size","Reverb Room Size",CONFIG_SPINNER,"",20, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { + 0, 120, 1 + } + }, + { + "reverb_damping","Reverb Damping",CONFIG_SPINNER, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { + 0, 100, 1 + } + }, + { + "reverb_width","Reverb Width",CONFIG_SPINNER,"",1, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { + 0, 100, 1 + } + }, + { + "reverb_level","Reverb Level",CONFIG_SPINNER,"",90, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { + 0, 100, 1 + } + }, +#endif + { + "interpolation","Interpolation Method",CONFIG_SELECTION,"",2, + { + { + "None",0 + }, + { + "Linear",1 + }, + { + "4th Order",2 + }, + { + "7th Order",3 + }, + { + "" + } + } + }, + { + "","",-1 + } }; diff --git a/src/devices/sound/midi_mt32.c b/src/devices/sound/midi_mt32.c index 731401e..a23ef40 100644 --- a/src/devices/sound/midi_mt32.c +++ b/src/devices/sound/midi_mt32.c @@ -8,7 +8,7 @@ * * Interface to the MuNT32 MIDI synthesizer. * - * Version: @(#)midi_mt32.c 1.0.4 2018/05/08 + * Version: @(#)midi_mt32.c 1.0.5 2018/10/05 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -42,6 +42,7 @@ #include #include #include "munt/c_interface/c_interface.h" +#define dbglog sound_midi_log #include "../../emu.h" #include "../../mem.h" #include "../../rom.h" @@ -58,13 +59,6 @@ #define CM32_PCM_ROM_PATH L"sound/cm32l/cm32l_pcm.rom" -extern void givealbuffer_midi(void *buf, uint32_t size); -extern void pclog(const char *format, ...); -extern void al_set_midi(int freq, int buf_size); - -extern int soundon; - - static const mt32emu_report_handler_i_v0 handler_v0 = { /** Returns the actual interface version ID */ NULL, //mt32emu_report_handler_version (*getVersionID)(mt32emu_report_handler_i i); @@ -118,14 +112,16 @@ static mt32emu_context context = NULL; static int mtroms_present[2] = {-1, -1}; +#if 1 +int +#else mt32emu_return_code +#endif mt32_check(const char *func, mt32emu_return_code ret, mt32emu_return_code expected) { if (ret != expected) { -#if 0 - pclog("%s() failed, expected %d but returned %d\n", func, expected, ret); -#endif - return 0; + ERRLOG("%s() failed, expected %d but returned %d\n", func, expected, ret); + return 0; } return 1; @@ -194,7 +190,7 @@ mt32_thread(void *param) buf_pos += bsize; if (buf_pos >= buf_size) { if (soundon) - givealbuffer_midi(buffer, buf_size / sizeof(float)); + openal_buffer_midi(buffer, buf_size / sizeof(float)); buf_pos = 0; } } else { @@ -205,7 +201,7 @@ mt32_thread(void *param) buf_pos += bsize; if (buf_pos >= buf_size) { if (soundon) - givealbuffer_midi(buffer_int16, buf_size / sizeof(int16_t)); + openal_buffer_midi(buffer_int16, buf_size / sizeof(int16_t)); buf_pos = 0; } } @@ -231,6 +227,7 @@ static void * mt32emu_init(wchar_t *control_rom, wchar_t *pcm_rom) { wchar_t path[1024]; + midi_device_t *dev; char fn[1024]; context = mt32emu_create_context(handler, NULL); @@ -252,30 +249,30 @@ mt32emu_init(wchar_t *control_rom, wchar_t *pcm_rom) /* buf_size = samplerate/RENDER_RATE*2; */ if (sound_is_float) { buf_size = (samplerate/RENDER_RATE)*2*BUFFER_SEGMENTS*sizeof(float); - buffer = malloc(buf_size); + buffer = (float *)mem_alloc(buf_size); buffer_int16 = NULL; } else { buf_size = (samplerate/RENDER_RATE)*2*BUFFER_SEGMENTS*sizeof(int16_t); buffer = NULL; - buffer_int16 = malloc(buf_size); + buffer_int16 = (int16_t *)mem_alloc(buf_size); } mt32emu_set_output_gain(context, device_get_config_int("output_gain")/100.0f); - mt32emu_set_reverb_enabled(context, device_get_config_int("reverb")); + mt32emu_set_reverb_enabled(context, (mt32emu_boolean) !!device_get_config_int("reverb")); mt32emu_set_reverb_output_gain(context, device_get_config_int("reverb_output_gain")/100.0f); - mt32emu_set_reversed_stereo_enabled(context, device_get_config_int("reversed_stereo")); - mt32emu_set_nice_amp_ramp_enabled(context, device_get_config_int("nice_ramp")); + mt32emu_set_reversed_stereo_enabled(context, (mt32emu_boolean) !!device_get_config_int("reversed_stereo")); + mt32emu_set_nice_amp_ramp_enabled(context, (mt32emu_boolean) !!device_get_config_int("nice_ramp")); - /* pclog("mt32 output gain: %f\n", mt32emu_get_output_gain(context)); - pclog("mt32 reverb output gain: %f\n", mt32emu_get_reverb_output_gain(context)); - pclog("mt32 reverb: %d\n", mt32emu_is_reverb_enabled(context)); - pclog("mt32 reversed stereo: %d\n", mt32emu_is_reversed_stereo_enabled(context)); */ + /* DEBUG("mt32 output gain: %f\n", mt32emu_get_output_gain(context)); + DEBUG("mt32 reverb output gain: %f\n", mt32emu_get_reverb_output_gain(context)); + DEBUG("mt32 reverb: %d\n", mt32emu_is_reverb_enabled(context)); + DEBUG("mt32 reversed stereo: %d\n", mt32emu_is_reversed_stereo_enabled(context)); */ - al_set_midi(samplerate, buf_size); + openal_set_midi(samplerate, buf_size); - /* pclog("mt32 (Munt %s) initialized, samplerate %d, buf_size %d\n", mt32emu_get_library_version_string(), samplerate, buf_size); */ + /* DEBUG("mt32 (Munt %s) initialized, samplerate %d, buf_size %d\n", mt32emu_get_library_version_string(), samplerate, buf_size); */ - midi_device_t* dev = malloc(sizeof(midi_device_t)); + dev = (midi_device_t *)mem_alloc(sizeof(midi_device_t)); memset(dev, 0, sizeof(midi_device_t)); dev->play_msg = mt32_msg; @@ -336,48 +333,35 @@ mt32_close(void *priv) static const device_config_t mt32_config[] = { +#if 0 { - .name = "output_gain", - .description = "Output Gain", - .type = CONFIG_SPINNER, + "output_gain","Output Gain",CONFIG_SPINNER,"",100, .spinner = { - .min = 0, - .max = 100 - }, - .default_int = 100 + 0, 100 + } }, +#endif { - .name = "reverb", - .description = "Reverb", - .type = CONFIG_BINARY, - .default_int = 1 + "reverb","Reverb",CONFIG_BINARY,"",1 }, +#if 0 { - .name = "reverb_output_gain", - .description = "Reverb Output Gain", - .type = CONFIG_SPINNER, + "reverb_output_gain","Reverb Output Gain",CONFIG_SPINNER,"",100, .spinner = { - .min = 0, - .max = 100 - }, - .default_int = 100 + 0, 100 + } + }, +#endif + { + "reversed_stereo","Reversed stereo",CONFIG_BINARY,"",0 }, { - .name = "reversed_stereo", - .description = "Reversed stereo", - .type = CONFIG_BINARY, - .default_int = 0 + "nice_ramp","Nice ramp",CONFIG_BINARY,"",1 }, { - .name = "nice_ramp", - .description = "Nice ramp", - .type = CONFIG_BINARY, - .default_int = 1 - }, - { - .type = -1 + "","",-1 } }; diff --git a/src/devices/sound/midi_system.c b/src/devices/sound/midi_system.c index 23d179f..31efc22 100644 --- a/src/devices/sound/midi_system.c +++ b/src/devices/sound/midi_system.c @@ -8,7 +8,7 @@ * * Interface to system MIDI driver. * - * Version: @(#)midi_system.c 1.0.4 2018/05/06 + * Version: @(#)midi_system.c 1.0.5 2018/09/22 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -41,6 +41,7 @@ #include #include #include +#define dbglog sound_midi_log #include "../../emu.h" #include "../../device.h" #include "../../plat.h" @@ -48,57 +49,58 @@ #include "midi_system.h" -void* system_midi_init(const device_t *info) +void * +system_midi_init(const device_t *info) { - midi_device_t* dev = malloc(sizeof(midi_device_t)); - memset(dev, 0, sizeof(midi_device_t)); + midi_device_t *dev; - dev->play_msg = plat_midi_play_msg; - dev->play_sysex = plat_midi_play_sysex; - dev->write = plat_midi_write; + dev = (midi_device_t *)mem_alloc(sizeof(midi_device_t)); + memset(dev, 0, sizeof(midi_device_t)); - plat_midi_init(); + dev->play_msg = plat_midi_play_msg; + dev->play_sysex = plat_midi_play_sysex; + dev->write = plat_midi_write; - midi_init(dev); + plat_midi_init(); - return dev; + midi_init(dev); + + return dev; } -void system_midi_close(void* p) -{ - plat_midi_close(); - midi_close(); +void +system_midi_close(void *priv) +{ + plat_midi_close(); + + midi_close(); + + free(priv); } -int system_midi_available(void) + +int +system_midi_available(void) { - return plat_midi_get_num_devs(); + return plat_midi_get_num_devs(); } -static const device_config_t system_midi_config[] = -{ - { - .name = "midi", - .description = "MIDI out device", - .type = CONFIG_MIDI, - .default_int = 0 - }, - { - .type = -1 - } + +static const device_config_t system_midi_config[] = { + { + "midi","MIDI out device",CONFIG_MIDI,"",0 + }, + { + "","",-1 + } }; -const device_t system_midi_device = -{ - SYSTEM_MIDI_NAME, - 0, 0, - system_midi_init, - system_midi_close, - NULL, - system_midi_available, - NULL, - NULL, - NULL, - system_midi_config +const device_t system_midi_device = { + SYSTEM_MIDI_NAME, + 0, 0, + system_midi_init, system_midi_close, NULL, + system_midi_available, + NULL, NULL, NULL, + system_midi_config }; diff --git a/src/devices/sound/nukedopl.cpp b/src/devices/sound/nukedopl.cpp index 7014bd1..0dbdfd7 100644 --- a/src/devices/sound/nukedopl.cpp +++ b/src/devices/sound/nukedopl.cpp @@ -15,10 +15,12 @@ * Tremolo and phase generator calculation information. * OPLx decapsulated(Matthew Gambrell, Olli Niemitalo): * OPL2 ROMs. + * siliconpr0n.org(John McMaster, digshadow): + * YMF262 and VRC VII decaps and die shots. * - * Version: 1.7.4 + * Version: 1.8.0 * - * Version: @(#)nukedopl.cpp 1.0.1 2018/02/14 + * Version: @(#)nukedopl.c 1.0.3 2018/09/15 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -28,7 +30,7 @@ * Copyright 2017,2018 Fred N. van Kempen. * Copyright 2016-2018 Miran Grca. * Copyright 2008-2018 Sarah Walker. - * Copyright 2015-2018 Alexey Khokholov. + * Copyright 2013-2018 Alexey Khokholov (Nuke.YKT) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -57,7 +59,6 @@ #define RSM_FRAC 10 // Channel types - enum { ch_2op = 0, ch_4op = 1, @@ -66,7 +67,6 @@ enum { }; // Envelope key types - enum { egk_norm = 0x01, egk_drum = 0x02 @@ -117,38 +117,38 @@ static const Bit16u logsinrom[256] = { // static const Bit16u exprom[256] = { - 0x000, 0x003, 0x006, 0x008, 0x00b, 0x00e, 0x011, 0x014, - 0x016, 0x019, 0x01c, 0x01f, 0x022, 0x025, 0x028, 0x02a, - 0x02d, 0x030, 0x033, 0x036, 0x039, 0x03c, 0x03f, 0x042, - 0x045, 0x048, 0x04b, 0x04e, 0x051, 0x054, 0x057, 0x05a, - 0x05d, 0x060, 0x063, 0x066, 0x069, 0x06c, 0x06f, 0x072, - 0x075, 0x078, 0x07b, 0x07e, 0x082, 0x085, 0x088, 0x08b, - 0x08e, 0x091, 0x094, 0x098, 0x09b, 0x09e, 0x0a1, 0x0a4, - 0x0a8, 0x0ab, 0x0ae, 0x0b1, 0x0b5, 0x0b8, 0x0bb, 0x0be, - 0x0c2, 0x0c5, 0x0c8, 0x0cc, 0x0cf, 0x0d2, 0x0d6, 0x0d9, - 0x0dc, 0x0e0, 0x0e3, 0x0e7, 0x0ea, 0x0ed, 0x0f1, 0x0f4, - 0x0f8, 0x0fb, 0x0ff, 0x102, 0x106, 0x109, 0x10c, 0x110, - 0x114, 0x117, 0x11b, 0x11e, 0x122, 0x125, 0x129, 0x12c, - 0x130, 0x134, 0x137, 0x13b, 0x13e, 0x142, 0x146, 0x149, - 0x14d, 0x151, 0x154, 0x158, 0x15c, 0x160, 0x163, 0x167, - 0x16b, 0x16f, 0x172, 0x176, 0x17a, 0x17e, 0x181, 0x185, - 0x189, 0x18d, 0x191, 0x195, 0x199, 0x19c, 0x1a0, 0x1a4, - 0x1a8, 0x1ac, 0x1b0, 0x1b4, 0x1b8, 0x1bc, 0x1c0, 0x1c4, - 0x1c8, 0x1cc, 0x1d0, 0x1d4, 0x1d8, 0x1dc, 0x1e0, 0x1e4, - 0x1e8, 0x1ec, 0x1f0, 0x1f5, 0x1f9, 0x1fd, 0x201, 0x205, - 0x209, 0x20e, 0x212, 0x216, 0x21a, 0x21e, 0x223, 0x227, - 0x22b, 0x230, 0x234, 0x238, 0x23c, 0x241, 0x245, 0x249, - 0x24e, 0x252, 0x257, 0x25b, 0x25f, 0x264, 0x268, 0x26d, - 0x271, 0x276, 0x27a, 0x27f, 0x283, 0x288, 0x28c, 0x291, - 0x295, 0x29a, 0x29e, 0x2a3, 0x2a8, 0x2ac, 0x2b1, 0x2b5, - 0x2ba, 0x2bf, 0x2c4, 0x2c8, 0x2cd, 0x2d2, 0x2d6, 0x2db, - 0x2e0, 0x2e5, 0x2e9, 0x2ee, 0x2f3, 0x2f8, 0x2fd, 0x302, - 0x306, 0x30b, 0x310, 0x315, 0x31a, 0x31f, 0x324, 0x329, - 0x32e, 0x333, 0x338, 0x33d, 0x342, 0x347, 0x34c, 0x351, - 0x356, 0x35b, 0x360, 0x365, 0x36a, 0x370, 0x375, 0x37a, - 0x37f, 0x384, 0x38a, 0x38f, 0x394, 0x399, 0x39f, 0x3a4, - 0x3a9, 0x3ae, 0x3b4, 0x3b9, 0x3bf, 0x3c4, 0x3c9, 0x3cf, - 0x3d4, 0x3da, 0x3df, 0x3e4, 0x3ea, 0x3ef, 0x3f5, 0x3fa + 0x7fa, 0x7f5, 0x7ef, 0x7ea, 0x7e4, 0x7df, 0x7da, 0x7d4, + 0x7cf, 0x7c9, 0x7c4, 0x7bf, 0x7b9, 0x7b4, 0x7ae, 0x7a9, + 0x7a4, 0x79f, 0x799, 0x794, 0x78f, 0x78a, 0x784, 0x77f, + 0x77a, 0x775, 0x770, 0x76a, 0x765, 0x760, 0x75b, 0x756, + 0x751, 0x74c, 0x747, 0x742, 0x73d, 0x738, 0x733, 0x72e, + 0x729, 0x724, 0x71f, 0x71a, 0x715, 0x710, 0x70b, 0x706, + 0x702, 0x6fd, 0x6f8, 0x6f3, 0x6ee, 0x6e9, 0x6e5, 0x6e0, + 0x6db, 0x6d6, 0x6d2, 0x6cd, 0x6c8, 0x6c4, 0x6bf, 0x6ba, + 0x6b5, 0x6b1, 0x6ac, 0x6a8, 0x6a3, 0x69e, 0x69a, 0x695, + 0x691, 0x68c, 0x688, 0x683, 0x67f, 0x67a, 0x676, 0x671, + 0x66d, 0x668, 0x664, 0x65f, 0x65b, 0x657, 0x652, 0x64e, + 0x649, 0x645, 0x641, 0x63c, 0x638, 0x634, 0x630, 0x62b, + 0x627, 0x623, 0x61e, 0x61a, 0x616, 0x612, 0x60e, 0x609, + 0x605, 0x601, 0x5fd, 0x5f9, 0x5f5, 0x5f0, 0x5ec, 0x5e8, + 0x5e4, 0x5e0, 0x5dc, 0x5d8, 0x5d4, 0x5d0, 0x5cc, 0x5c8, + 0x5c4, 0x5c0, 0x5bc, 0x5b8, 0x5b4, 0x5b0, 0x5ac, 0x5a8, + 0x5a4, 0x5a0, 0x59c, 0x599, 0x595, 0x591, 0x58d, 0x589, + 0x585, 0x581, 0x57e, 0x57a, 0x576, 0x572, 0x56f, 0x56b, + 0x567, 0x563, 0x560, 0x55c, 0x558, 0x554, 0x551, 0x54d, + 0x549, 0x546, 0x542, 0x53e, 0x53b, 0x537, 0x534, 0x530, + 0x52c, 0x529, 0x525, 0x522, 0x51e, 0x51b, 0x517, 0x514, + 0x510, 0x50c, 0x509, 0x506, 0x502, 0x4ff, 0x4fb, 0x4f8, + 0x4f4, 0x4f1, 0x4ed, 0x4ea, 0x4e7, 0x4e3, 0x4e0, 0x4dc, + 0x4d9, 0x4d6, 0x4d2, 0x4cf, 0x4cc, 0x4c8, 0x4c5, 0x4c2, + 0x4be, 0x4bb, 0x4b8, 0x4b5, 0x4b1, 0x4ae, 0x4ab, 0x4a8, + 0x4a4, 0x4a1, 0x49e, 0x49b, 0x498, 0x494, 0x491, 0x48e, + 0x48b, 0x488, 0x485, 0x482, 0x47e, 0x47b, 0x478, 0x475, + 0x472, 0x46f, 0x46c, 0x469, 0x466, 0x463, 0x460, 0x45d, + 0x45a, 0x457, 0x454, 0x451, 0x44e, 0x44b, 0x448, 0x445, + 0x442, 0x43f, 0x43c, 0x439, 0x436, 0x433, 0x430, 0x42d, + 0x42a, 0x428, 0x425, 0x422, 0x41f, 0x41c, 0x419, 0x416, + 0x414, 0x411, 0x40e, 0x40b, 0x408, 0x406, 0x403, 0x400 }; // @@ -177,33 +177,11 @@ static const Bit8u kslshift[4] = { // envelope generator constants // -static const Bit8u eg_incstep[3][4][8] = { - { - { 0, 0, 0, 0, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 0, 0, 0, 0 } - }, - { - { 0, 1, 0, 1, 0, 1, 0, 1 }, - { 0, 1, 0, 1, 1, 1, 0, 1 }, - { 0, 1, 1, 1, 0, 1, 1, 1 }, - { 0, 1, 1, 1, 1, 1, 1, 1 } - }, - { - { 1, 1, 1, 1, 1, 1, 1, 1 }, - { 2, 2, 1, 1, 1, 1, 1, 1 }, - { 2, 2, 1, 1, 2, 2, 1, 1 }, - { 2, 2, 2, 2, 2, 2, 1, 1 } - } -}; - -static const Bit8u eg_incdesc[16] = { - 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2 -}; - -static const Bit8s eg_incsh[16] = { - 0, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0, -1, -2 +static const Bit8u eg_incstep[4][4] = { + { 0, 0, 0, 0 }, + { 1, 0, 0, 0 }, + { 1, 0, 1, 0 }, + { 1, 1, 1, 0 } }; // @@ -232,7 +210,7 @@ static Bit16s OPL3_EnvelopeCalcExp(Bit32u level) { level = 0x1fff; } - return ((exprom[(level & 0xff) ^ 0xff] | 0x400) << 1) >> (level >> 8); + return (exprom[level & 0xff] << 1) >> (level >> 8); } static Bit16s OPL3_EnvelopeCalcSin0(Bit16u phase, Bit16u envelope) @@ -242,7 +220,7 @@ static Bit16s OPL3_EnvelopeCalcSin0(Bit16u phase, Bit16u envelope) phase &= 0x3ff; if (phase & 0x200) { - neg = ~0; + neg = 0xffff; } if (phase & 0x100) { @@ -311,7 +289,7 @@ static Bit16s OPL3_EnvelopeCalcSin4(Bit16u phase, Bit16u envelope) phase &= 0x3ff; if ((phase & 0x300) == 0x100) { - neg = ~0; + neg = 0xffff; } if (phase & 0x200) { @@ -353,7 +331,7 @@ static Bit16s OPL3_EnvelopeCalcSin6(Bit16u phase, Bit16u envelope) phase &= 0x3ff; if (phase & 0x200) { - neg = ~0; + neg = 0xffff; } return OPL3_EnvelopeCalcExp(envelope << 3) ^ neg; } @@ -365,7 +343,7 @@ static Bit16s OPL3_EnvelopeCalcSin7(Bit16u phase, Bit16u envelope) phase &= 0x3ff; if (phase & 0x200) { - neg = ~0; + neg = 0xffff; phase = (phase & 0x1ff) ^ 0x1ff; } out = phase << 3; @@ -383,45 +361,14 @@ static const envelope_sinfunc envelope_sin[8] = { OPL3_EnvelopeCalcSin7 }; -static void OPL3_EnvelopeGenOff(opl3_slot *slot); -static void OPL3_EnvelopeGenAttack(opl3_slot *slot); -static void OPL3_EnvelopeGenDecay(opl3_slot *slot); -static void OPL3_EnvelopeGenSustain(opl3_slot *slot); -static void OPL3_EnvelopeGenRelease(opl3_slot *slot); - -envelope_genfunc envelope_gen[5] = { - OPL3_EnvelopeGenOff, - OPL3_EnvelopeGenAttack, - OPL3_EnvelopeGenDecay, - OPL3_EnvelopeGenSustain, - OPL3_EnvelopeGenRelease -}; - enum envelope_gen_num { - envelope_gen_num_off = 0, - envelope_gen_num_attack = 1, - envelope_gen_num_decay = 2, - envelope_gen_num_sustain = 3, - envelope_gen_num_release = 4 + envelope_gen_num_attack = 0, + envelope_gen_num_decay = 1, + envelope_gen_num_sustain = 2, + envelope_gen_num_release = 3 }; -static Bit8u OPL3_EnvelopeCalcRate(opl3_slot *slot, Bit8u reg_rate) -{ - Bit8u rate; - if (reg_rate == 0x00) - { - return 0x00; - } - rate = (reg_rate << 2) - + (slot->reg_ksr ? slot->channel->ksv : (slot->channel->ksv >> 2)); - if (rate > 0x3c) - { - rate = 0x3c; - } - return rate; -} - static void OPL3_EnvelopeUpdateKSL(opl3_slot *slot) { Bit16s ksl = (kslrom[slot->channel->f_num >> 6] << 2) @@ -433,128 +380,161 @@ static void OPL3_EnvelopeUpdateKSL(opl3_slot *slot) slot->eg_ksl = (Bit8u)ksl; } -static void OPL3_EnvelopeUpdateRate(opl3_slot *slot) -{ - switch (slot->eg_gen) - { - case envelope_gen_num_off: - case envelope_gen_num_attack: - slot->eg_rate = OPL3_EnvelopeCalcRate(slot, slot->reg_ar); - break; - case envelope_gen_num_decay: - slot->eg_rate = OPL3_EnvelopeCalcRate(slot, slot->reg_dr); - break; - case envelope_gen_num_sustain: - case envelope_gen_num_release: - slot->eg_rate = OPL3_EnvelopeCalcRate(slot, slot->reg_rr); - break; - } -} - -static void OPL3_EnvelopeGenOff(opl3_slot *slot) -{ - slot->eg_rout = 0x1ff; -} - -static void OPL3_EnvelopeGenAttack(opl3_slot *slot) -{ - if (slot->eg_rout == 0x00) - { - slot->eg_gen = envelope_gen_num_decay; - OPL3_EnvelopeUpdateRate(slot); - return; - } - slot->eg_rout += ((~slot->eg_rout) * slot->eg_inc) >> 3; - if (slot->eg_rout < 0x00) - { - slot->eg_rout = 0x00; - } -} - -static void OPL3_EnvelopeGenDecay(opl3_slot *slot) -{ - if (slot->eg_rout >= slot->reg_sl << 4) - { - slot->eg_gen = envelope_gen_num_sustain; - OPL3_EnvelopeUpdateRate(slot); - return; - } - slot->eg_rout += slot->eg_inc; -} - -static void OPL3_EnvelopeGenSustain(opl3_slot *slot) -{ - if (!slot->reg_type) - { - OPL3_EnvelopeGenRelease(slot); - } -} - -static void OPL3_EnvelopeGenRelease(opl3_slot *slot) -{ - if (slot->eg_rout >= 0x1ff) - { - slot->eg_gen = envelope_gen_num_off; - slot->eg_rout = 0x1ff; - OPL3_EnvelopeUpdateRate(slot); - return; - } - slot->eg_rout += slot->eg_inc; -} - static void OPL3_EnvelopeCalc(opl3_slot *slot) { - Bit8u rate_h, rate_l; - Bit8u inc = 0; - rate_h = slot->eg_rate >> 2; - rate_l = slot->eg_rate & 3; - if (eg_incsh[rate_h] > 0) + Bit8u nonzero; + Bit8u rate; + Bit8u rate_hi; + Bit8u rate_lo; + Bit8u reg_rate = 0; + Bit8u ks; + Bit8u eg_shift, shift; + Bit16u eg_rout; + Bit16s eg_inc; + Bit8u eg_off; + Bit8u reset = 0; + slot->eg_out = slot->eg_rout + (slot->reg_tl << 2) + + (slot->eg_ksl >> kslshift[slot->reg_ksl]) + *slot->trem; + if (slot->key && slot->eg_gen == envelope_gen_num_release) { - if ((slot->chip->timer & ((1 << eg_incsh[rate_h]) - 1)) == 0) - { - inc = eg_incstep[eg_incdesc[rate_h]][rate_l] - [((slot->chip->timer)>> eg_incsh[rate_h]) & 0x07]; - } + reset = 1; + reg_rate = slot->reg_ar; } else { - inc = eg_incstep[eg_incdesc[rate_h]][rate_l] - [slot->chip->timer & 0x07] << (-eg_incsh[rate_h]); + switch (slot->eg_gen) + { + case envelope_gen_num_attack: + reg_rate = slot->reg_ar; + break; + case envelope_gen_num_decay: + reg_rate = slot->reg_dr; + break; + case envelope_gen_num_sustain: + if (!slot->reg_type) + { + reg_rate = slot->reg_rr; + } + break; + case envelope_gen_num_release: + reg_rate = slot->reg_rr; + break; + } + } + slot->pg_reset = reset; + ks = slot->channel->ksv >> ((slot->reg_ksr ^ 1) << 1); + nonzero = (reg_rate != 0); + rate = ks + (reg_rate << 2); + rate_hi = rate >> 2; + rate_lo = rate & 0x03; + if (rate_hi & 0x10) + { + rate_hi = 0x0f; + } + eg_shift = rate_hi + slot->chip->eg_add; + shift = 0; + if (nonzero) + { + if (rate_hi < 12) + { + if (slot->chip->eg_state) + { + switch (eg_shift) + { + case 12: + shift = 1; + break; + case 13: + shift = (rate_lo >> 1) & 0x01; + break; + case 14: + shift = rate_lo & 0x01; + break; + default: + break; + } + } + } + else + { + shift = (rate_hi & 0x03) + eg_incstep[rate_lo][slot->chip->timer & 0x03]; + if (shift & 0x04) + { + shift = 0x03; + } + if (!shift) + { + shift = slot->chip->eg_state; + } + } + } + eg_rout = slot->eg_rout; + eg_inc = 0; + eg_off = 0; + // Instant attack + if (reset && rate_hi == 0x0f) + { + eg_rout = 0x00; + } + // Envelope off + if ((slot->eg_rout & 0x1f8) == 0x1f8) + { + eg_off = 1; + } + if (slot->eg_gen != envelope_gen_num_attack && !reset && eg_off) + { + eg_rout = 0x1ff; + } + switch (slot->eg_gen) + { + case envelope_gen_num_attack: + if (!slot->eg_rout) + { + slot->eg_gen = envelope_gen_num_decay; + } + else if (slot->key && shift > 0 && rate_hi != 0x0f) + { + eg_inc = ((~slot->eg_rout) << shift) >> 4; + } + break; + case envelope_gen_num_decay: + if ((slot->eg_rout >> 4) == slot->reg_sl) + { + slot->eg_gen = envelope_gen_num_sustain; + } + else if (!eg_off && !reset && shift > 0) + { + eg_inc = 1 << (shift - 1); + } + break; + case envelope_gen_num_sustain: + case envelope_gen_num_release: + if (!eg_off && !reset && shift > 0) + { + eg_inc = 1 << (shift - 1); + } + break; + } + slot->eg_rout = (eg_rout + eg_inc) & 0x1ff; + // Key off + if (reset) + { + slot->eg_gen = envelope_gen_num_attack; + } + if (!slot->key) + { + slot->eg_gen = envelope_gen_num_release; } - slot->eg_inc = inc; - slot->eg_out = slot->eg_rout + (slot->reg_tl << 2) - + (slot->eg_ksl >> kslshift[slot->reg_ksl]) + *slot->trem; - envelope_gen[slot->eg_gen](slot); } static void OPL3_EnvelopeKeyOn(opl3_slot *slot, Bit8u type) { - if (!slot->key) - { - slot->eg_gen = envelope_gen_num_attack; - OPL3_EnvelopeUpdateRate(slot); - if ((slot->eg_rate >> 2) == 0x0f) - { - slot->eg_gen = envelope_gen_num_decay; - OPL3_EnvelopeUpdateRate(slot); - slot->eg_rout = 0x00; - } - slot->pg_phase = 0x00; - } slot->key |= type; } static void OPL3_EnvelopeKeyOff(opl3_slot *slot, Bit8u type) { - if (slot->key) - { - slot->key &= (~type); - if (!slot->key) - { - slot->eg_gen = envelope_gen_num_release; - OPL3_EnvelopeUpdateRate(slot); - } - } + slot->key &= ~type; } // @@ -563,9 +543,14 @@ static void OPL3_EnvelopeKeyOff(opl3_slot *slot, Bit8u type) static void OPL3_PhaseGenerate(opl3_slot *slot) { + opl3_chip *chip; Bit16u f_num; Bit32u basefreq; + Bit8u rm_xor, n_bit; + Bit32u noise; + Bit16u phase; + chip = slot->chip; f_num = slot->channel->f_num; if (slot->reg_vib) { @@ -592,20 +577,58 @@ static void OPL3_PhaseGenerate(opl3_slot *slot) f_num += range; } basefreq = (f_num << slot->channel->block) >> 1; - slot->pg_phase += (basefreq * mt[slot->reg_mult]) >> 1; -} - -// -// Noise Generator -// - -static void OPL3_NoiseGenerate(opl3_chip *chip) -{ - if (chip->noise & 0x01) + phase = (Bit16u)(slot->pg_phase >> 9); + if (slot->pg_reset) { - chip->noise ^= 0x800302; + slot->pg_phase = 0; } - chip->noise >>= 1; + slot->pg_phase += (basefreq * mt[slot->reg_mult]) >> 1; + // Rhythm mode + noise = chip->noise; + slot->pg_phase_out = phase; + if (slot->slot_num == 13) // hh + { + chip->rm_hh_bit2 = (phase >> 2) & 1; + chip->rm_hh_bit3 = (phase >> 3) & 1; + chip->rm_hh_bit7 = (phase >> 7) & 1; + chip->rm_hh_bit8 = (phase >> 8) & 1; + } + if (slot->slot_num == 17 && (chip->rhy & 0x20)) // tc + { + chip->rm_tc_bit3 = (phase >> 3) & 1; + chip->rm_tc_bit5 = (phase >> 5) & 1; + } + if (chip->rhy & 0x20) + { + rm_xor = (chip->rm_hh_bit2 ^ chip->rm_hh_bit7) + | (chip->rm_hh_bit3 ^ chip->rm_tc_bit5) + | (chip->rm_tc_bit3 ^ chip->rm_tc_bit5); + switch (slot->slot_num) + { + case 13: // hh + slot->pg_phase_out = rm_xor << 9; + if (rm_xor ^ (noise & 1)) + { + slot->pg_phase_out |= 0xd0; + } + else + { + slot->pg_phase_out |= 0x34; + } + break; + case 16: // sd + slot->pg_phase_out = (chip->rm_hh_bit8 << 9) + | ((chip->rm_hh_bit8 ^ (noise & 1)) << 8); + break; + case 17: // tc + slot->pg_phase_out = (rm_xor << 9) | 0x80; + break; + default: + break; + } + } + n_bit = ((noise >> 14) ^ noise) & 0x01; + chip->noise = (noise >> 1) | (n_bit << 22); } // @@ -626,7 +649,6 @@ static void OPL3_SlotWrite20(opl3_slot *slot, Bit8u data) slot->reg_type = (data >> 5) & 0x01; slot->reg_ksr = (data >> 4) & 0x01; slot->reg_mult = data & 0x0f; - OPL3_EnvelopeUpdateRate(slot); } static void OPL3_SlotWrite40(opl3_slot *slot, Bit8u data) @@ -640,7 +662,6 @@ static void OPL3_SlotWrite60(opl3_slot *slot, Bit8u data) { slot->reg_ar = (data >> 4) & 0x0f; slot->reg_dr = data & 0x0f; - OPL3_EnvelopeUpdateRate(slot); } static void OPL3_SlotWrite80(opl3_slot *slot, Bit8u data) @@ -651,7 +672,6 @@ static void OPL3_SlotWrite80(opl3_slot *slot, Bit8u data) slot->reg_sl = 0x1f; } slot->reg_rr = data & 0x0f; - OPL3_EnvelopeUpdateRate(slot); } static void OPL3_SlotWriteE0(opl3_slot *slot, Bit8u data) @@ -663,19 +683,9 @@ static void OPL3_SlotWriteE0(opl3_slot *slot, Bit8u data) } } -static void OPL3_SlotGeneratePhase(opl3_slot *slot, Bit16u phase) -{ - slot->out = envelope_sin[slot->reg_wf](phase, slot->eg_out); -} - static void OPL3_SlotGenerate(opl3_slot *slot) { - OPL3_SlotGeneratePhase(slot, (Bit16u)(slot->pg_phase >> 9) + *slot->mod); -} - -static void OPL3_SlotGenerateZM(opl3_slot *slot) -{ - OPL3_SlotGeneratePhase(slot, (Bit16u)(slot->pg_phase >> 9)); + slot->out = envelope_sin[slot->reg_wf](slot->pg_phase_out + *slot->mod, slot->eg_out); } static void OPL3_SlotCalcFB(opl3_slot *slot) @@ -727,6 +737,8 @@ static void OPL3_ChannelUpdateRhythm(opl3_chip *chip, Bit8u data) chip->channel[chnum].chtype = ch_drum; } OPL3_ChannelSetupAlg(channel6); + OPL3_ChannelSetupAlg(channel7); + OPL3_ChannelSetupAlg(channel8); //hh if (chip->rhy & 0x01) { @@ -798,16 +810,12 @@ static void OPL3_ChannelWriteA0(opl3_channel *channel, Bit8u data) | ((channel->f_num >> (0x09 - channel->chip->nts)) & 0x01); OPL3_EnvelopeUpdateKSL(channel->slots[0]); OPL3_EnvelopeUpdateKSL(channel->slots[1]); - OPL3_EnvelopeUpdateRate(channel->slots[0]); - OPL3_EnvelopeUpdateRate(channel->slots[1]); if (channel->chip->newm && channel->chtype == ch_4op) { channel->pair->f_num = channel->f_num; channel->pair->ksv = channel->ksv; OPL3_EnvelopeUpdateKSL(channel->pair->slots[0]); OPL3_EnvelopeUpdateKSL(channel->pair->slots[1]); - OPL3_EnvelopeUpdateRate(channel->pair->slots[0]); - OPL3_EnvelopeUpdateRate(channel->pair->slots[1]); } } @@ -823,8 +831,6 @@ static void OPL3_ChannelWriteB0(opl3_channel *channel, Bit8u data) | ((channel->f_num >> (0x09 - channel->chip->nts)) & 0x01); OPL3_EnvelopeUpdateKSL(channel->slots[0]); OPL3_EnvelopeUpdateKSL(channel->slots[1]); - OPL3_EnvelopeUpdateRate(channel->slots[0]); - OPL3_EnvelopeUpdateRate(channel->slots[1]); if (channel->chip->newm && channel->chtype == ch_4op) { channel->pair->f_num = channel->f_num; @@ -832,8 +838,6 @@ static void OPL3_ChannelWriteB0(opl3_channel *channel, Bit8u data) channel->pair->ksv = channel->ksv; OPL3_EnvelopeUpdateKSL(channel->pair->slots[0]); OPL3_EnvelopeUpdateKSL(channel->pair->slots[1]); - OPL3_EnvelopeUpdateRate(channel->pair->slots[0]); - OPL3_EnvelopeUpdateRate(channel->pair->slots[1]); } } @@ -841,6 +845,12 @@ static void OPL3_ChannelSetupAlg(opl3_channel *channel) { if (channel->chtype == ch_drum) { + if (channel->ch_num == 7 || channel->ch_num == 8) + { + channel->slots[0]->mod = &channel->chip->zeromod; + channel->slots[1]->mod = &channel->chip->zeromod; + return; + } switch (channel->alg & 0x01) { case 0x00: @@ -967,7 +977,7 @@ static void OPL3_ChannelWriteC0(opl3_channel *channel, Bit8u data) } else { - channel->cha = channel->chb = ~0; + channel->cha = channel->chb = (Bit16u)~0; } } @@ -1056,96 +1066,23 @@ static Bit16s OPL3_ClipSample(Bit32s sample) return (Bit16s)sample; } -static void OPL3_GenerateRhythm1(opl3_chip *chip) -{ - opl3_channel *channel6; - opl3_channel *channel7; - opl3_channel *channel8; - Bit16u phase14; - Bit16u phase17; - Bit16u phase; - Bit16u phasebit; - - channel6 = &chip->channel[6]; - channel7 = &chip->channel[7]; - channel8 = &chip->channel[8]; - OPL3_SlotGenerate(channel6->slots[0]); - phase14 = (channel7->slots[0]->pg_phase >> 9) & 0x3ff; - phase17 = (channel8->slots[1]->pg_phase >> 9) & 0x3ff; - phase = 0x00; - //hh tc phase bit - phasebit = ((phase14 & 0x08) | (((phase14 >> 5) ^ phase14) & 0x04) - | (((phase17 >> 2) ^ phase17) & 0x08)) ? 0x01 : 0x00; - //hh - phase = (phasebit << 9) - | (0x34 << ((phasebit ^ (chip->noise & 0x01)) << 1)); - OPL3_SlotGeneratePhase(channel7->slots[0], phase); - //tt - OPL3_SlotGenerateZM(channel8->slots[0]); -} - -static void OPL3_GenerateRhythm2(opl3_chip *chip) -{ - opl3_channel *channel6; - opl3_channel *channel7; - opl3_channel *channel8; - Bit16u phase14; - Bit16u phase17; - Bit16u phase; - Bit16u phasebit; - - channel6 = &chip->channel[6]; - channel7 = &chip->channel[7]; - channel8 = &chip->channel[8]; - OPL3_SlotGenerate(channel6->slots[1]); - phase14 = (channel7->slots[0]->pg_phase >> 9) & 0x3ff; - phase17 = (channel8->slots[1]->pg_phase >> 9) & 0x3ff; - phase = 0x00; - //hh tc phase bit - phasebit = ((phase14 & 0x08) | (((phase14 >> 5) ^ phase14) & 0x04) - | (((phase17 >> 2) ^ phase17) & 0x08)) ? 0x01 : 0x00; - //sd - phase = (0x100 << ((phase14 >> 8) & 0x01)) ^ ((chip->noise & 0x01) << 8); - OPL3_SlotGeneratePhase(channel7->slots[1], phase); - //tc - phase = 0x100 | (phasebit << 9); - OPL3_SlotGeneratePhase(channel8->slots[1], phase); -} - void OPL3_Generate(opl3_chip *chip, Bit16s *buf) { Bit8u ii; Bit8u jj; Bit16s accm; + Bit8u shift = 0; buf[1] = OPL3_ClipSample(chip->mixbuff[1]); - for (ii = 0; ii < 12; ii++) + for (ii = 0; ii < 15; ii++) { OPL3_SlotCalcFB(&chip->slot[ii]); - OPL3_PhaseGenerate(&chip->slot[ii]); OPL3_EnvelopeCalc(&chip->slot[ii]); + OPL3_PhaseGenerate(&chip->slot[ii]); OPL3_SlotGenerate(&chip->slot[ii]); } - for (ii = 12; ii < 15; ii++) - { - OPL3_SlotCalcFB(&chip->slot[ii]); - OPL3_PhaseGenerate(&chip->slot[ii]); - OPL3_EnvelopeCalc(&chip->slot[ii]); - } - - if (chip->rhy & 0x20) - { - OPL3_GenerateRhythm1(chip); - } - else - { - OPL3_SlotGenerate(&chip->slot[12]); - OPL3_SlotGenerate(&chip->slot[13]); - OPL3_SlotGenerate(&chip->slot[14]); - } - chip->mixbuff[0] = 0; for (ii = 0; ii < 18; ii++) { @@ -1160,19 +1097,9 @@ void OPL3_Generate(opl3_chip *chip, Bit16s *buf) for (ii = 15; ii < 18; ii++) { OPL3_SlotCalcFB(&chip->slot[ii]); - OPL3_PhaseGenerate(&chip->slot[ii]); OPL3_EnvelopeCalc(&chip->slot[ii]); - } - - if (chip->rhy & 0x20) - { - OPL3_GenerateRhythm2(chip); - } - else - { - OPL3_SlotGenerate(&chip->slot[15]); - OPL3_SlotGenerate(&chip->slot[16]); - OPL3_SlotGenerate(&chip->slot[17]); + OPL3_PhaseGenerate(&chip->slot[ii]); + OPL3_SlotGenerate(&chip->slot[ii]); } buf[0] = OPL3_ClipSample(chip->mixbuff[0]); @@ -1180,8 +1107,8 @@ void OPL3_Generate(opl3_chip *chip, Bit16s *buf) for (ii = 18; ii < 33; ii++) { OPL3_SlotCalcFB(&chip->slot[ii]); - OPL3_PhaseGenerate(&chip->slot[ii]); OPL3_EnvelopeCalc(&chip->slot[ii]); + OPL3_PhaseGenerate(&chip->slot[ii]); OPL3_SlotGenerate(&chip->slot[ii]); } @@ -1199,13 +1126,11 @@ void OPL3_Generate(opl3_chip *chip, Bit16s *buf) for (ii = 33; ii < 36; ii++) { OPL3_SlotCalcFB(&chip->slot[ii]); - OPL3_PhaseGenerate(&chip->slot[ii]); OPL3_EnvelopeCalc(&chip->slot[ii]); + OPL3_PhaseGenerate(&chip->slot[ii]); OPL3_SlotGenerate(&chip->slot[ii]); } - OPL3_NoiseGenerate(chip); - if ((chip->timer & 0x3f) == 0x3f) { chip->tremolopos = (chip->tremolopos + 1) % 210; @@ -1225,6 +1150,52 @@ void OPL3_Generate(opl3_chip *chip, Bit16s *buf) } chip->timer++; + + chip->eg_add = 0; + if (chip->eg_timer) + { + while (shift < 36 && ((chip->eg_timer >> shift) & 1) == 0) + { + shift++; + } + if (shift > 12) + { + chip->eg_add = 0; + } + else + { + chip->eg_add = shift + 1; + } + } + + if (chip->eg_timerrem || chip->eg_state) + { + if (chip->eg_timer == 0xfffffffff) + { + chip->eg_timer = 0; + chip->eg_timerrem = 1; + } + else + { + chip->eg_timer++; + chip->eg_timerrem = 0; + } + } + + chip->eg_state ^= 1; + + while (chip->writebuf[chip->writebuf_cur].time <= chip->writebuf_samplecnt) + { + if (!(chip->writebuf[chip->writebuf_cur].reg & 0x200)) + { + break; + } + chip->writebuf[chip->writebuf_cur].reg &= 0x1ff; + OPL3_WriteReg(chip, chip->writebuf[chip->writebuf_cur].reg, + chip->writebuf[chip->writebuf_cur].data); + chip->writebuf_cur = (chip->writebuf_cur + 1) % OPL_WRITEBUF_SIZE; + } + chip->writebuf_samplecnt++; } void OPL3_GenerateResampled(opl3_chip *chip, Bit16s *buf) @@ -1255,8 +1226,9 @@ void OPL3_Reset(opl3_chip *chip, Bit32u samplerate) chip->slot[slotnum].mod = &chip->zeromod; chip->slot[slotnum].eg_rout = 0x1ff; chip->slot[slotnum].eg_out = 0x1ff; - chip->slot[slotnum].eg_gen = envelope_gen_num_off; + chip->slot[slotnum].eg_gen = envelope_gen_num_release; chip->slot[slotnum].trem = (Bit8u*)&chip->zeromod; + chip->slot[slotnum].slot_num = slotnum; } for (channum = 0; channum < 18; channum++) { @@ -1278,11 +1250,12 @@ void OPL3_Reset(opl3_chip *chip, Bit32u samplerate) chip->channel[channum].out[2] = &chip->zeromod; chip->channel[channum].out[3] = &chip->zeromod; chip->channel[channum].chtype = ch_2op; - chip->channel[channum].cha = ~0; - chip->channel[channum].chb = ~0; + chip->channel[channum].cha = 0xffff; + chip->channel[channum].chb = 0xffff; + chip->channel[channum].ch_num = channum; OPL3_ChannelSetupAlg(&chip->channel[channum]); } - chip->noise = 0x306600; + chip->noise = 1; chip->rateratio = (samplerate << RSM_FRAC) / 49716; chip->tremoloshift = 4; chip->vibshift = 1; @@ -1397,6 +1370,34 @@ void OPL3_WriteReg(opl3_chip *chip, Bit16u reg, Bit8u v) } } +void OPL3_WriteRegBuffered(opl3_chip *chip, Bit16u reg, Bit8u v) +{ + Bit64u time1, time2; + + if (chip->writebuf[chip->writebuf_last].reg & 0x200) + { + OPL3_WriteReg(chip, chip->writebuf[chip->writebuf_last].reg & 0x1ff, + chip->writebuf[chip->writebuf_last].data); + + chip->writebuf_cur = (chip->writebuf_last + 1) % OPL_WRITEBUF_SIZE; + chip->writebuf_samplecnt = chip->writebuf[chip->writebuf_last].time; + } + + chip->writebuf[chip->writebuf_last].reg = reg | 0x200; + chip->writebuf[chip->writebuf_last].data = v; + time1 = chip->writebuf_lasttime + OPL_WRITEBUF_DELAY; + time2 = chip->writebuf_samplecnt; + + if (time1 < time2) + { + time1 = time2; + } + + chip->writebuf[chip->writebuf_last].time = time1; + chip->writebuf_lasttime = time1; + chip->writebuf_last = (chip->writebuf_last + 1) % OPL_WRITEBUF_SIZE; +} + void OPL3_GenerateStream(opl3_chip *chip, Bit16s *sndptr, Bit32u numsamples) { Bit32u i; diff --git a/src/devices/sound/nukedopl.h b/src/devices/sound/nukedopl.h index 812d4c2..1400ca0 100644 --- a/src/devices/sound/nukedopl.h +++ b/src/devices/sound/nukedopl.h @@ -8,7 +8,7 @@ * * Definitions for the NukedOPL3 driver. * - * Version: @(#)nukedopl.h 1.0.1 2018/02/14 + * Version: @(#)nukedopl.h 1.0.2 2018/09/04 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -18,7 +18,7 @@ * Copyright 2017,2018 Fred N. van Kempen. * Copyright 2016-2018 Miran Grca. * Copyright 2008-2018 Sarah Walker. - * Copyright 2015-2018 Alexey Khokholov. + * Copyright 2013-2018 Alexey Khokholov. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -42,6 +42,10 @@ # define SOUND_NUKEDOPL_H +#define OPL_WRITEBUF_SIZE 1024 +#define OPL_WRITEBUF_DELAY 1 + + #include typedef signed int Bits; typedef unsigned int Bitu; @@ -51,10 +55,12 @@ typedef int16_t Bit16s; typedef uint16_t Bit16u; typedef int32_t Bit32s; typedef uint32_t Bit32u; +typedef int64_t Bit64s; +typedef uint64_t Bit64u; -struct opl3_chip; struct opl3_slot; struct opl3_channel; +struct opl3_chip; struct opl3_slot { opl3_channel *channel; @@ -82,8 +88,10 @@ struct opl3_slot { Bit8u reg_rr; Bit8u reg_wf; Bit8u key; + Bit32u pg_reset; Bit32u pg_phase; - Bit32u timer; + Bit16u pg_phase_out; + Bit8u slot_num; }; struct opl3_channel { @@ -99,12 +107,23 @@ struct opl3_channel { Bit8u alg; Bit8u ksv; Bit16u cha, chb; + Bit8u ch_num; +}; + +struct opl3_writebuf { + Bit64u time; + Bit16u reg; + Bit8u data; }; struct opl3_chip { opl3_channel channel[18]; opl3_slot slot[36]; Bit16u timer; + Bit64u eg_timer; + Bit8u eg_timerrem; + Bit8u eg_state; + Bit8u eg_add; Bit8u newm; Bit8u nts; Bit8u rhy; @@ -116,11 +135,23 @@ struct opl3_chip { Bit32u noise; Bit16s zeromod; Bit32s mixbuff[2]; - + Bit8u rm_hh_bit2; + Bit8u rm_hh_bit3; + Bit8u rm_hh_bit7; + Bit8u rm_hh_bit8; + Bit8u rm_tc_bit3; + Bit8u rm_tc_bit5; + //OPL3L Bit32s rateratio; Bit32s samplecnt; Bit16s oldsamples[2]; Bit16s samples[2]; + + Bit64u writebuf_samplecnt; + Bit32u writebuf_cur; + Bit32u writebuf_last; + Bit64u writebuf_lasttime; + opl3_writebuf writebuf[OPL_WRITEBUF_SIZE]; }; @@ -129,6 +160,7 @@ extern void OPL3_GenerateResampled(opl3_chip *chip, Bit16s *buf); extern void OPL3_Reset(opl3_chip *chip, Bit32u samplerate); extern Bit32u OPL3_WriteAddr(opl3_chip *chip, Bit32u port, Bit8u val); extern void OPL3_WriteReg(opl3_chip *chip, Bit16u reg, Bit8u v); +extern void OPL3_WriteRegBuffered(opl3_chip *chip, Bit16u reg, Bit8u v); extern void OPL3_GenerateStream(opl3_chip *chip, Bit16s *sndptr, Bit32u numsamples); diff --git a/src/devices/sound/openal.c b/src/devices/sound/openal.c index 95f703d..84dd1af 100644 --- a/src/devices/sound/openal.c +++ b/src/devices/sound/openal.c @@ -8,7 +8,7 @@ * * Interface to the OpenAL sound processing library. * - * Version: @(#)openal.c 1.0.15 2018/08/27 + * Version: @(#)openal.c 1.0.17 2018/10/05 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -51,6 +51,7 @@ # include # include #endif +#define dbglog sound_log #include "../../emu.h" #include "../../ui/ui.h" #include "../../plat.h" @@ -73,12 +74,13 @@ #ifdef USE_OPENAL -ALuint buffers[4]; /* front and back buffers */ -ALuint buffers_cd[4]; /* front and back buffers */ -ALuint buffers_midi[4]; /* front and back buffers */ - -static ALuint source[3]; /* audio source */ -static void *openal_handle = NULL; /* handle to (open) DLL */ +static ALuint buffers[4], /* front and back buffers */ + buffers_cd[4], /* front and back buffers */ + buffers_midi[4], /* front and back buffers */ + source[3]; /* audio source */ +static int nbuffers, + nsources; +static void *openal_handle = NULL; /* handle to (open) DLL */ /* Pointers to the real functions. */ static ALC_API ALCdevice* (ALC_APIENTRY *f_alcOpenDevice)(const ALCchar *devicename); @@ -99,6 +101,8 @@ static AL_API void (AL_APIENTRY *f_alGetSourcei)(ALuint source, ALenum param, A static AL_API void (AL_APIENTRY *f_alListenerf)(ALenum param, ALfloat value); static AL_API void (AL_APIENTRY *f_alGenBuffers)(ALsizei n, ALuint *buffers); static AL_API void (AL_APIENTRY *f_alGenSources)(ALsizei n, ALuint *sources); +static AL_API void (AL_APIENTRY *f_alDeleteSources)(ALsizei n, const ALuint *sources); +static AL_API void (AL_APIENTRY *f_alDeleteBuffers)(ALsizei n, const ALuint *buffers); static dllimp_t openal_imports[] = { { "alcOpenDevice", &f_alcOpenDevice }, @@ -119,6 +123,8 @@ static dllimp_t openal_imports[] = { { "alListenerf", &f_alListenerf }, { "alGenBuffers", &f_alGenBuffers }, { "alGenSources", &f_alGenSources }, + { "alDeleteBuffers", &f_alDeleteBuffers }, + { "alDeleteSources", &f_alDeleteSources }, { NULL, NULL } }; #endif @@ -128,14 +134,6 @@ static int midi_freq = 44100; static int midi_buf_size = 4410; -void -al_set_midi(int freq, int buf_size) -{ - midi_freq = freq; - midi_buf_size = buf_size; -} - - #ifdef USE_OPENAL ALvoid alutInit(ALint *argc, ALbyte **argv) @@ -147,7 +145,7 @@ alutInit(ALint *argc, ALbyte **argv) if (openal_handle == NULL) return; /* Open device */ - Device = f_alcOpenDevice((ALCchar *)""); + Device = f_alcOpenDevice(NULL); if (Device != NULL) { /* Create context(s) */ Context = f_alcCreateContext(Device, NULL); @@ -173,16 +171,22 @@ alutExit(ALvoid) if (Context != NULL) { /* Get device for active context */ Device = f_alcGetContextsDevice(Context); - if (Device != NULL) { - /* Disable context */ - f_alcMakeContextCurrent(NULL); - /* Close device */ - f_alcCloseDevice(Device); - } + /* Disable context */ + f_alcMakeContextCurrent(NULL); + + f_alDeleteSources(nsources, source); + + f_alDeleteBuffers(4, buffers); + f_alDeleteBuffers(4, buffers_cd); + if (nbuffers > 0) + f_alDeleteBuffers(nbuffers, buffers_midi); /* Release context(s) */ f_alcDestroyContext(Context); + + /* Close device */ + f_alcCloseDevice(Device); } #if 0 @@ -197,7 +201,7 @@ alutExit(ALvoid) void -closeal(void) +openal_close(void) { #ifdef USE_OPENAL alutExit(); @@ -206,32 +210,39 @@ closeal(void) void -initalmain(int argc, char *argv[]) +openal_init(void) { #ifdef USE_OPENAL + wchar_t temp[512]; + const char *fn = PATH_AL_DLL; + /* Try loading the DLL if needed. */ if (openal_handle == NULL) { - openal_handle = dynld_module(PATH_AL_DLL, openal_imports); + openal_handle = dynld_module(fn, openal_imports); if (openal_handle == NULL) { - pclog("SOUND: unable to load '%s' - sound disabled!\n", - PATH_AL_DLL); - ui_msgbox(MBX_ERROR, (wchar_t *)IDS_ERR_OPENAL); + ERRLOG("SOUND: unable to load '%s' - sound disabled!\n", fn); + swprintf(temp, sizeof_w(temp), + get_string(IDS_ERR_NOLIB), "OpenAL", fn); + ui_msgbox(MBX_ERROR, temp); return; } else { -#ifdef _DEBUG - pclog("SOUND: module '%s' loaded.\n", PATH_AL_DLL); -#endif + INFO("SOUND: module '%s' loaded.\n", fn); } } + /* Perform a module initialization. */ alutInit(NULL, NULL); - atexit(closeal); + + /* Close up shop on application exit. */ + atexit(openal_close); #endif } +/* Reset the OpenAL interface and its buffers. */ +//FIXME: isnt this a major memory leak, we never free buffers! --FvK void -inital(void) +openal_reset(void) { #ifdef USE_OPENAL float *buf = NULL, *cd_buf = NULL, *midi_buf = NULL; @@ -251,15 +262,15 @@ inital(void) #ifdef USE_OPENAL if (sound_is_float) { - buf = (float *) malloc((BUFLEN << 1) * sizeof(float)); - cd_buf = (float *) malloc((CD_BUFLEN << 1) * sizeof(float)); + buf = (float *)mem_alloc((BUFLEN << 1) * sizeof(float)); + cd_buf = (float *)mem_alloc((CD_BUFLEN << 1) * sizeof(float)); if (init_midi) - midi_buf = (float *) malloc(midi_buf_size * sizeof(float)); + midi_buf = (float *)mem_alloc(midi_buf_size * sizeof(float)); } else { - buf_int16 = (int16_t *) malloc((BUFLEN << 1) * sizeof(int16_t)); - cd_buf_int16 = (int16_t *) malloc((CD_BUFLEN << 1) * sizeof(int16_t)); + buf_int16 = (int16_t *)mem_alloc((BUFLEN << 1) * sizeof(int16_t)); + cd_buf_int16 = (int16_t *)mem_alloc((CD_BUFLEN << 1) * sizeof(int16_t)); if (init_midi) - midi_buf_int16 = (int16_t *) malloc(midi_buf_size * sizeof(int16_t)); + midi_buf_int16 = (int16_t *)mem_alloc(midi_buf_size * sizeof(int16_t)); } f_alGenBuffers(4, buffers); @@ -267,8 +278,13 @@ inital(void) if (init_midi) { f_alGenBuffers(4, buffers_midi); f_alGenSources(3, source); - } else + nbuffers = 4; + nsources = 3; + } else { f_alGenSources(2, source); + nbuffers = 0; + nsources = 2; + } f_alSource3f(source[0], AL_POSITION, 0.0, 0.0, 0.0); f_alSource3f(source[0], AL_VELOCITY, 0.0, 0.0, 0.0); @@ -338,8 +354,8 @@ inital(void) } -void -givealbuffer_common(void *buf, uint8_t src, int size, int freq) +static void +openal_buffer_common(void *buf, uint8_t src, int size, int freq) { #ifdef USE_OPENAL int processed; @@ -375,21 +391,29 @@ givealbuffer_common(void *buf, uint8_t src, int size, int freq) void -givealbuffer(void *buf) +openal_buffer(void *buf) { - givealbuffer_common(buf, 0, BUFLEN << 1, FREQ); + openal_buffer_common(buf, 0, BUFLEN << 1, FREQ); } void -givealbuffer_cd(void *buf) +openal_buffer_cd(void *buf) { - givealbuffer_common(buf, 1, CD_BUFLEN << 1, CD_FREQ); + openal_buffer_common(buf, 1, CD_BUFLEN << 1, CD_FREQ); } void -givealbuffer_midi(void *buf, uint32_t size) +openal_buffer_midi(void *buf, uint32_t size) { - givealbuffer_common(buf, 2, size, midi_freq); + openal_buffer_common(buf, 2, size, midi_freq); +} + + +void +openal_set_midi(int freq, int buf_size) +{ + midi_freq = freq; + midi_buf_size = buf_size; } diff --git a/src/devices/sound/snd_ad1848.c b/src/devices/sound/snd_ad1848.c index 11923f4..266ad92 100644 --- a/src/devices/sound/snd_ad1848.c +++ b/src/devices/sound/snd_ad1848.c @@ -8,7 +8,7 @@ * * Emulation of the AD1848 (Windows Sound System) CODEC. * - * Version: @(#)snd_ad1848.c 1.0.4 2018/05/06 + * Version: @(#)snd_ad1848.c 1.0.5 2018/09/15 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -41,6 +41,7 @@ #include #include #include +#define dbglog sound_dev_log #include "../../emu.h" #include "../../timer.h" #include "../system/dma.h" diff --git a/src/devices/sound/snd_adlib.c b/src/devices/sound/snd_adlib.c index 7c1449e..ecce028 100644 --- a/src/devices/sound/snd_adlib.c +++ b/src/devices/sound/snd_adlib.c @@ -8,7 +8,7 @@ * * Implementation of the ADLIB sound device. * - * Version: @(#)snd_adlib.c 1.0.4 2018/05/06 + * Version: @(#)snd_adlib.c 1.0.5 2018/09/22 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -41,6 +41,7 @@ #include #include #include +#define dbglog sound_dev_log #include "../../emu.h" #include "../../io.h" #include "../../device.h" @@ -74,7 +75,7 @@ uint8_t adlib_mca_read(int port, void *p) { adlib_t *adlib = (adlib_t *)p; - pclog("adlib_mca_read: port=%04x\n", port); + DBGLOG(1, "adlib_mca_read: port=%04x\n", port); return adlib->pos_regs[port & 7]; } @@ -86,7 +87,7 @@ void adlib_mca_write(int port, uint8_t val, void *p) if (port < 0x102) return; - pclog("adlib_mca_write: port=%04x val=%02x\n", port, val); + DBGLOG(1, "adlib_mca_write: port=%04x val=%02x\n", port, val); switch (port) { @@ -100,21 +101,25 @@ void adlib_mca_write(int port, uint8_t val, void *p) adlib->pos_regs[port & 7] = val; } -void *adlib_init(const device_t *info) + +void * +adlib_init(const device_t *info) { - adlib_t *adlib = malloc(sizeof(adlib_t)); + adlib_t *adlib = (adlib_t *)mem_alloc(sizeof(adlib_t)); memset(adlib, 0, sizeof(adlib_t)); - pclog("adlib_init\n"); + DEBUG("adlib_init\n"); opl2_init(&adlib->opl); io_sethandler(0x0388, 0x0002, opl2_read, NULL, NULL, opl2_write, NULL, NULL, &adlib->opl); sound_add_handler(adlib_get_buffer, adlib); return adlib; } -void *adlib_mca_init(const device_t *info) + +void * +adlib_mca_init(const device_t *info) { - adlib_t *adlib = adlib_init(info); + adlib_t *adlib = (adlib_t *)adlib_init(info); io_removehandler(0x0388, 0x0002, opl2_read, NULL, NULL, opl2_write, NULL, NULL, &adlib->opl); mca_add(adlib_mca_read, adlib_mca_write, adlib); @@ -131,22 +136,20 @@ void adlib_close(void *p) free(adlib); } -const device_t adlib_device = -{ - "AdLib", - DEVICE_ISA, - 0, - adlib_init, adlib_close, NULL, - NULL, NULL, NULL, NULL, - NULL +const device_t adlib_device = { + "AdLib", + DEVICE_ISA, + 0, + adlib_init, adlib_close, NULL, + NULL, NULL, NULL, NULL, + NULL }; -const device_t adlib_mca_device = -{ - "AdLib (MCA)", - DEVICE_MCA, - 0, - adlib_init, adlib_close, NULL, - NULL, NULL, NULL, NULL, - NULL +const device_t adlib_mca_device = { + "AdLib", + DEVICE_MCA, + 0, + adlib_init, adlib_close, NULL, + NULL, NULL, NULL, NULL, + NULL }; diff --git a/src/devices/sound/snd_adlibgold.c b/src/devices/sound/snd_adlibgold.c index 7a36ff9..3d6554a 100644 --- a/src/devices/sound/snd_adlibgold.c +++ b/src/devices/sound/snd_adlibgold.c @@ -10,7 +10,7 @@ * * TODO: Stack allocation of big buffers (line 688 et al.) * - * Version: @(#)snd_adlibgold.c 1.0.8 2018/05/06 + * Version: @(#)snd_adlibgold.c 1.0.9 2018/10/05 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -43,17 +43,15 @@ #include #include #include +#define dbglog sound_dev_log #include "../../emu.h" #include "../../io.h" -#include "../../mem.h" -#include "../../rom.h" #include "../../timer.h" #include "../../device.h" #include "../../nvr.h" #include "../../plat.h" #include "../system/dma.h" #include "../system/pic.h" -#include "../system/pit.h" #include "sound.h" #include "filters.h" #include "snd_opl.h" @@ -690,10 +688,14 @@ static void adgold_get_buffer(int32_t *buffer, int len, void *p) /* TODO: Fix this to use a static buffer */ if (len > 512 * 1024) { - pclog("adgold_get_buffer: possible stack overflow detected. Buffer size was %d bytes", 2 * len); + DEBUG("adgold_get_buffer: possible stack overflow detected. Buffer size was %d bytes", 2 * len); return; } +# ifdef __cplusplus + int16_t *adgold_buffer = (int16_t *)mem_alloc(sizeof(int16_t) * len * 2); +# else int16_t *adgold_buffer = (int16_t *)_alloca(sizeof(int16_t) * len * 2); +# endif #else int16_t adgold_buffer[len*2]; #endif @@ -802,6 +804,11 @@ static void adgold_get_buffer(int32_t *buffer, int len, void *p) adgold->opl.pos = 0; adgold->pos = 0; +#ifdef _MSC_VER +# ifdef __cplusplus + free(adgold_buffer); +# endif +#endif } @@ -810,7 +817,7 @@ void *adgold_init(const device_t *info) FILE *f; int c; double out; - adgold_t *adgold = malloc(sizeof(adgold_t)); + adgold_t *adgold = (adgold_t *)mem_alloc(sizeof(adgold_t)); memset(adgold, 0, sizeof(adgold_t)); adgold->surround_enabled = device_get_config_int("surround"); @@ -878,26 +885,21 @@ void adgold_close(void *p) free(adgold); } -static const device_config_t adgold_config[] = -{ - { - "surround", "Surround module", CONFIG_BINARY, "", 1 - }, - { - "", "", -1 - } + +static const device_config_t adgold_config[] = { + { + "surround", "Surround module", CONFIG_BINARY, "", 1 + }, + { + "", "", -1 + } }; -const device_t adgold_device = -{ - "AdLib Gold", - DEVICE_ISA, 0, - adgold_init, - adgold_close, - NULL, - NULL, - NULL, - NULL, - NULL, - adgold_config +const device_t adgold_device = { + "AdLib Gold", + DEVICE_ISA, + 0, + adgold_init, adgold_close, NULL, + NULL, NULL, NULL, NULL, + adgold_config }; diff --git a/src/devices/sound/snd_audiopci.c b/src/devices/sound/snd_audiopci.c index 4c280fe..e8963fb 100644 --- a/src/devices/sound/snd_audiopci.c +++ b/src/devices/sound/snd_audiopci.c @@ -8,7 +8,7 @@ * * Implementation of the AudioPCI sound device. * - * Version: @(#)snd_audiopci.c 1.0.12 2018/05/06 + * Version: @(#)snd_audiopci.c 1.0.13 2018/09/22 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -41,7 +41,9 @@ #include #include #include +#define dbglog sound_dev_log #include "../../emu.h" +#include "../../cpu/cpu.h" /* for the debugging stuff */ #include "../../io.h" #include "../../mem.h" #include "../../timer.h" @@ -162,1171 +164,1229 @@ typedef struct { #define FORMAT_MONO_16 2 #define FORMAT_STEREO_16 3 -const int32_t codec_attn[]= { - 25,32,41,51,65,82,103,130,164,206,260,327,412,519,653, - 822,1036,1304,1641,2067,2602,3276,4125,5192,6537,8230,10362,13044, - 16422,20674,26027,32767 +static const int32_t codec_attn[]= { + 25, 32, 41, 51, 65, 82, 103, 130, + 164, 206, 260, 327, 412, 519, 653, 822, + 1036, 1304, 1641, 2067, 2602, 3276, 4125, 5192, + 6537, 8230, 10362, 13044, 16422, 20674, 26027, 32767 }; -static void es1371_fetch(es1371_t *es1371, int dac_nr); -static void update_legacy(es1371_t *es1371); + +static void es1371_fetch(es1371_t *dev, int dac_nr); +static void update_legacy(es1371_t *dev); -static void es1371_update_irqs(es1371_t *es1371) +static void +es1371_update_irqs(es1371_t *dev) { - int irq = 0; + int irq = 0; - if ((es1371->int_status & INT_STATUS_DAC1) && (es1371->si_cr & SI_P1_INTR_EN)) - irq = 1; - if ((es1371->int_status & INT_STATUS_DAC2) && (es1371->si_cr & SI_P2_INTR_EN)) - irq = 1; + if ((dev->int_status & INT_STATUS_DAC1) && (dev->si_cr & SI_P1_INTR_EN)) + irq = 1; + if ((dev->int_status & INT_STATUS_DAC2) && (dev->si_cr & SI_P2_INTR_EN)) + irq = 1; - if (irq) - es1371->int_status |= INT_STATUS_INTR; - else - es1371->int_status &= ~INT_STATUS_INTR; + if (irq) + dev->int_status |= INT_STATUS_INTR; + else + dev->int_status &= ~INT_STATUS_INTR; - if (es1371->legacy_ctrl & LEGACY_FORCE_IRQ) - irq = 1; + if (dev->legacy_ctrl & LEGACY_FORCE_IRQ) + irq = 1; - if (irq) - { - pci_set_irq(es1371->card, PCI_INTA); -// snddev_log("Raise IRQ\n"); - } - else - { - pci_clear_irq(es1371->card, PCI_INTA); -// snddev_log("Drop IRQ\n"); - } + if (irq) { + pci_set_irq(dev->card, PCI_INTA); + DBGLOG(1, "Raise IRQ\n"); + } else { + pci_clear_irq(dev->card, PCI_INTA); + DBGLOG(1, "Drop IRQ\n"); + } } -static uint8_t es1371_inb(uint16_t port, void *p) + +static uint8_t +es1371_inb(uint16_t port, void *priv) { - es1371_t *es1371 = (es1371_t *)p; - uint8_t ret = 0; + es1371_t *dev = (es1371_t *)priv; + uint8_t ret = 0; - switch (port & 0x3f) - { - case 0x00: - ret = es1371->int_ctrl & 0xff; - break; - case 0x01: - ret = (es1371->int_ctrl >> 8) & 0xff; - break; - case 0x02: - ret = (es1371->int_ctrl >> 16) & 0xff; - break; - case 0x03: - ret = (es1371->int_ctrl >> 24) & 0xff; + switch (port & 0x3f) { + case 0x00: + ret = dev->int_ctrl & 0xff; break; - case 0x04: - ret = es1371->int_status & 0xff; - break; - case 0x05: - ret = (es1371->int_status >> 8) & 0xff; - break; - case 0x06: - ret = (es1371->int_status >> 16) & 0xff; - break; - case 0x07: - ret = (es1371->int_status >> 24) & 0xff; + case 0x01: + ret = (dev->int_ctrl >> 8) & 0xff; break; + case 0x02: + ret = (dev->int_ctrl >> 16) & 0xff; + break; - case 0x09: - ret = es1371->uart_status; + case 0x03: + ret = (dev->int_ctrl >> 24) & 0xff; + break; + + case 0x04: + ret = dev->int_status & 0xff; + break; + + case 0x05: + ret = (dev->int_status >> 8) & 0xff; + break; + + case 0x06: + ret = (dev->int_status >> 16) & 0xff; + break; + + case 0x07: + ret = (dev->int_status >> 24) & 0xff; + break; + + case 0x09: + ret = dev->uart_status; break; - case 0x0c: - ret = es1371->mem_page; + case 0x0c: + ret = dev->mem_page; break; - case 0x1a: - ret = es1371->legacy_ctrl >> 16; + case 0x1a: + ret = dev->legacy_ctrl >> 16; break; - case 0x1b: - ret = es1371->legacy_ctrl >> 24; + + case 0x1b: + ret = dev->legacy_ctrl >> 24; break; - case 0x20: - ret = es1371->si_cr & 0xff; + case 0x20: + ret = dev->si_cr & 0xff; break; - case 0x21: - ret = es1371->si_cr >> 8; + + case 0x21: + ret = dev->si_cr >> 8; break; - case 0x22: - ret = (es1371->si_cr >> 16) | 0x80; + + case 0x22: + ret = (dev->si_cr >> 16) | 0x80; break; - case 0x23: + + case 0x23: ret = 0xff; break; - default: - snddev_log("Bad es1371_inb: port=%04x\n", port); - } + default: + DEBUG("Bad es1371_inb: port=%04x\n", port); + } -// snddev_log("es1371_inb: port=%04x ret=%02x\n", port, ret); -// output = 3; - return ret; + DBGLOG(2, "es1371_inb: port=%04x ret=%02x\n", port, ret); + + return ret; } -static uint16_t es1371_inw(uint16_t port, void *p) + + +static uint16_t +es1371_inw(uint16_t port, void *priv) { - es1371_t *es1371 = (es1371_t *)p; - uint16_t ret = 0; + es1371_t *dev = (es1371_t *)priv; + uint16_t ret = 0; - switch (port & 0x3e) - { - case 0x00: - ret = es1371->int_ctrl & 0xffff; - break; - case 0x02: - ret = (es1371->int_ctrl >> 16) & 0xffff; + switch (port & 0x3e) { + case 0x00: + ret = dev->int_ctrl & 0xffff; break; - case 0x18: - ret = es1371->legacy_ctrl & 0xffff; -// snddev_log("Read legacy ctrl %04x\n", ret); + case 0x02: + ret = (dev->int_ctrl >> 16) & 0xffff; break; - case 0x26: - ret = es1371->dac[0].curr_samp_ct; + case 0x18: + ret = dev->legacy_ctrl & 0xffff; + DEBUG("Read legacy ctrl %04x\n", ret); break; - case 0x2a: - ret = es1371->dac[1].curr_samp_ct; + case 0x26: + ret = dev->dac[0].curr_samp_ct; + break; + + case 0x2a: + ret = dev->dac[1].curr_samp_ct; break; - case 0x36: - switch (es1371->mem_page) - { + case 0x36: + switch (dev->mem_page) { case 0xc: - ret = es1371->dac[0].count; - break; + ret = dev->dac[0].count; + break; default: - snddev_log("Bad es1371_inw: mem_page=%x port=%04x\n", es1371->mem_page, port); + DEBUG("Bad es1371_inw: mem_page=%x port=%04x\n", dev->mem_page, port); } break; - case 0x3e: - switch (es1371->mem_page) - { + case 0x3e: + switch (dev->mem_page) { case 0xc: - ret = es1371->dac[1].count; - break; + ret = dev->dac[1].count; + break; default: - snddev_log("Bad es1371_inw: mem_page=%x port=%04x\n", es1371->mem_page, port); + DEBUG("Bad es1371_inw: mem_page=%x port=%04x\n", dev->mem_page, port); } break; - default: - snddev_log("Bad es1371_inw: port=%04x\n", port); - } + default: + DEBUG("Bad es1371_inw: port=%04x\n", port); + } -// snddev_log("es1371_inw: port=%04x ret=%04x %04x:%08x\n", port, ret, CS,cpu_state.pc); - return ret; + DBGLOG(2, "es1371_inw: port=%04x ret=%04x %04x:%08x\n", port, ret, CS,cpu_state.pc); + return ret; } -static uint32_t es1371_inl(uint16_t port, void *p) + + +static uint32_t +es1371_inl(uint16_t port, void *priv) { - es1371_t *es1371 = (es1371_t *)p; - uint32_t ret = 0; - - switch (port & 0x3c) - { - case 0x00: - ret = es1371->int_ctrl; + es1371_t *dev = (es1371_t *)priv; + uint32_t ret = 0; + + switch (port & 0x3c) { + case 0x00: + ret = dev->int_ctrl; break; - case 0x04: - ret = es1371->int_status; + + case 0x04: + ret = dev->int_status; break; - case 0x10: - ret = es1371->sr_cir & ~0xffff; - ret |= es1371->sr_ram[es1371->sr_cir >> 25]; + case 0x10: + ret = dev->sr_cir & ~0xffff; + ret |= dev->sr_ram[dev->sr_cir >> 25]; break; - case 0x14: - ret = es1371->codec_ctrl & 0x00ff0000; - ret |= es1371->codec_regs[(es1371->codec_ctrl >> 16) & 0x3f]; + case 0x14: + ret = dev->codec_ctrl & 0x00ff0000; + ret |= dev->codec_regs[(dev->codec_ctrl >> 16) & 0x3f]; ret |= CODEC_READY; break; - case 0x34: - switch (es1371->mem_page) - { - + case 0x34: + switch (dev->mem_page) { case 0xc: - ret = es1371->dac[0].size | (es1371->dac[0].count << 16); - break; + ret = dev->dac[0].size | (dev->dac[0].count << 16); + break; case 0xd: - - ret = es1371->adc.size | (es1371->adc.count << 16); - break; + ret = dev->adc.size | (dev->adc.count << 16); + break; default: - snddev_log("Bad es1371_inl: mem_page=%x port=%04x\n", es1371->mem_page, port); + DEBUG("Bad es1371_inl: mem_page=%x port=%04x\n", dev->mem_page, port); } break; - case 0x3c: - switch (es1371->mem_page) - { + case 0x3c: + switch (dev->mem_page) { case 0xc: - ret = es1371->dac[1].size | (es1371->dac[1].count << 16); - break; + ret = dev->dac[1].size | (dev->dac[1].count << 16); + break; default: - snddev_log("Bad es1371_inl: mem_page=%x port=%04x\n", es1371->mem_page, port); + DEBUG("Bad es1371_inl: mem_page=%x port=%04x\n", dev->mem_page, port); } break; - - default: - snddev_log("Bad es1371_inl: port=%04x\n", port); - } -// snddev_log("es1371_inl: port=%04x ret=%08x %08x\n", port, ret, cpu_state.pc); - return ret; + default: + DEBUG("Bad es1371_inl: port=%04x\n", port); + } + + DBGLOG(2, "es1371_inl: port=%04x ret=%08x %08x\n", port, ret, cpu_state.pc); + + return ret; } -static void es1371_outb(uint16_t port, uint8_t val, void *p) + +static void +es1371_outb(uint16_t port, uint8_t val, void *priv) { - es1371_t *es1371 = (es1371_t *)p; + es1371_t *dev = (es1371_t *)priv; -// snddev_log("es1371_outb: port=%04x val=%02x %04x:%08x\n", port, val, cs, cpu_state.pc); - switch (port & 0x3f) - { - case 0x00: - if (!(es1371->int_ctrl & INT_DAC1_EN) && (val & INT_DAC1_EN)) - { - es1371->dac[0].addr = es1371->dac[0].addr_latch; - es1371->dac[0].buffer_pos = 0; - es1371->dac[0].buffer_pos_end = 0; - es1371_fetch(es1371, 0); + DBGLOG(2, "es1371_outb: port=%04x val=%02x %04x:%08x\n", port, val, cs, cpu_state.pc); + + switch (port & 0x3f) { + case 0x00: + if (!(dev->int_ctrl & INT_DAC1_EN) && (val & INT_DAC1_EN)) { + dev->dac[0].addr = dev->dac[0].addr_latch; + dev->dac[0].buffer_pos = 0; + dev->dac[0].buffer_pos_end = 0; + es1371_fetch(dev, 0); } - if (!(es1371->int_ctrl & INT_DAC2_EN) && (val & INT_DAC2_EN)) - { - es1371->dac[1].addr = es1371->dac[1].addr_latch; - es1371->dac[1].buffer_pos = 0; - es1371->dac[1].buffer_pos_end = 0; - es1371_fetch(es1371, 1); + if (!(dev->int_ctrl & INT_DAC2_EN) && (val & INT_DAC2_EN)) { + dev->dac[1].addr = dev->dac[1].addr_latch; + dev->dac[1].buffer_pos = 0; + dev->dac[1].buffer_pos_end = 0; + es1371_fetch(dev, 1); } - es1371->int_ctrl = (es1371->int_ctrl & 0xffffff00) | val; - break; - case 0x01: - es1371->int_ctrl = (es1371->int_ctrl & 0xffff00ff) | (val << 8); - break; - case 0x02: - es1371->int_ctrl = (es1371->int_ctrl & 0xff00ffff) | (val << 16); - break; - case 0x03: - es1371->int_ctrl = (es1371->int_ctrl & 0x00ffffff) | (val << 24); - break; - - case 0x09: - es1371->uart_ctrl = val; - break; - - case 0x0c: - es1371->mem_page = val & 0xf; + dev->int_ctrl = (dev->int_ctrl & 0xffffff00) | val; break; - case 0x18: - es1371->legacy_ctrl |= LEGACY_INT; + case 0x01: + dev->int_ctrl = (dev->int_ctrl & 0xffff00ff) | (val << 8); + break; + + case 0x02: + dev->int_ctrl = (dev->int_ctrl & 0xff00ffff) | (val << 16); + break; + + case 0x03: + dev->int_ctrl = (dev->int_ctrl & 0x00ffffff) | (val << 24); + break; + + case 0x09: + dev->uart_ctrl = val; + break; + + case 0x0c: + dev->mem_page = val & 0xf; + break; + + case 0x18: + dev->legacy_ctrl |= LEGACY_INT; nmi = 0; break; - case 0x1a: - es1371->legacy_ctrl = (es1371->legacy_ctrl & 0xff00ffff) | (val << 16); - update_legacy(es1371); + + case 0x1a: + dev->legacy_ctrl = (dev->legacy_ctrl & 0xff00ffff) | (val << 16); + update_legacy(dev); break; - case 0x1b: - es1371->legacy_ctrl = (es1371->legacy_ctrl & 0x00ffffff) | (val << 24); - es1371_update_irqs(es1371); -// output = 3; - update_legacy(es1371); + + case 0x1b: + dev->legacy_ctrl = (dev->legacy_ctrl & 0x00ffffff) | (val << 24); + es1371_update_irqs(dev); + update_legacy(dev); break; - case 0x20: - es1371->si_cr = (es1371->si_cr & 0xffff00) | val; + case 0x20: + dev->si_cr = (dev->si_cr & 0xffff00) | val; break; - case 0x21: - es1371->si_cr = (es1371->si_cr & 0xff00ff) | (val << 8); - if (!(es1371->si_cr & SI_P1_INTR_EN)) - es1371->int_status &= ~INT_STATUS_DAC1; - if (!(es1371->si_cr & SI_P2_INTR_EN)) - es1371->int_status &= ~INT_STATUS_DAC2; - es1371_update_irqs(es1371); + + case 0x21: + dev->si_cr = (dev->si_cr & 0xff00ff) | (val << 8); + if (!(dev->si_cr & SI_P1_INTR_EN)) + dev->int_status &= ~INT_STATUS_DAC1; + if (!(dev->si_cr & SI_P2_INTR_EN)) + dev->int_status &= ~INT_STATUS_DAC2; + es1371_update_irqs(dev); break; - case 0x22: - es1371->si_cr = (es1371->si_cr & 0x00ffff) | (val << 16); + + case 0x22: + dev->si_cr = (dev->si_cr & 0x00ffff) | (val << 16); break; - default: - snddev_log("Bad es1371_outb: port=%04x val=%02x\n", port, val); - } + default: + DEBUG("Bad es1371_outb: port=%04x val=%02x\n", port, val); + } } -static void es1371_outw(uint16_t port, uint16_t val, void *p) + + +static void +es1371_outw(uint16_t port, uint16_t val, void *priv) { - es1371_t *es1371 = (es1371_t *)p; + es1371_t *dev = (es1371_t *)priv; -// snddev_log("es1371_outw: port=%04x val=%04x\n", port, val); - switch (port & 0x3f) - { - case 0x0c: - es1371->mem_page = val & 0xf; + DBGLOG(2, "es1371_outw: port=%04x val=%04x\n", port, val); + + switch (port & 0x3f) { + case 0x0c: + dev->mem_page = val & 0xf; break; - case 0x24: - es1371->dac[0].samp_ct = val; + case 0x24: + dev->dac[0].samp_ct = val; break; - case 0x28: - es1371->dac[1].samp_ct = val; + case 0x28: + dev->dac[1].samp_ct = val; break; - default: - snddev_log("Bad es1371_outw: port=%04x val=%04x\n", port, val); - } + default: + DEBUG("Bad es1371_outw: port=%04x val=%04x\n", port, val); + } } -static void es1371_outl(uint16_t port, uint32_t val, void *p) -{ - es1371_t *es1371 = (es1371_t *)p; -// snddev_log("es1371_outl: port=%04x val=%08x %04x:%08x\n", port, val, CS, cpu_state.pc); - switch (port & 0x3f) - { - case 0x04: + +static void +es1371_outl(uint16_t port, uint32_t val, void *priv) +{ + es1371_t *dev = (es1371_t *)priv; + + DBGLOG(2, "es1371_outl: port=%04x val=%08x %04x:%08x\n", port, val, CS, cpu_state.pc); + + switch (port & 0x3f) { + case 0x04: break; - case 0x0c: - es1371->mem_page = val & 0xf; + case 0x0c: + dev->mem_page = val & 0xf; break; - case 0x10: - es1371->sr_cir = val; - if (es1371->sr_cir & SRC_RAM_WE) - { -// snddev_log("Write SR RAM %02x %04x\n", es1371->sr_cir >> 25, val & 0xffff); - es1371->sr_ram[es1371->sr_cir >> 25] = val & 0xffff; - switch (es1371->sr_cir >> 25) - { + case 0x10: + dev->sr_cir = val; + if (dev->sr_cir & SRC_RAM_WE) { + DBGLOG(1, "Write SR RAM %02x %04x\n", dev->sr_cir >> 25, val & 0xffff); + dev->sr_ram[dev->sr_cir >> 25] = val & 0xffff; + switch (dev->sr_cir >> 25) { case 0x71: - es1371->dac[0].vf = (es1371->dac[0].vf & ~0x1f8000) | ((val & 0xfc00) << 5); - es1371->dac[0].ac = (es1371->dac[0].ac & ~0x7f8000) | ((val & 0x00ff) << 15); - es1371->dac[0].f_pos = 0; - break; + dev->dac[0].vf = (dev->dac[0].vf & ~0x1f8000) | ((val & 0xfc00) << 5); + dev->dac[0].ac = (dev->dac[0].ac & ~0x7f8000) | ((val & 0x00ff) << 15); + dev->dac[0].f_pos = 0; + break; + case 0x72: - es1371->dac[0].ac = (es1371->dac[0].ac & ~0x7fff) | (val & 0x7fff); - break; + dev->dac[0].ac = (dev->dac[0].ac & ~0x7fff) | (val & 0x7fff); + break; + case 0x73: - es1371->dac[0].vf = (es1371->dac[0].vf & ~0x7fff) | (val & 0x7fff); - break; + dev->dac[0].vf = (dev->dac[0].vf & ~0x7fff) | (val & 0x7fff); + break; case 0x75: - es1371->dac[1].vf = (es1371->dac[1].vf & ~0x1f8000) | ((val & 0xfc00) << 5); - es1371->dac[1].ac = (es1371->dac[1].ac & ~0x7f8000) | ((val & 0x00ff) << 15); - es1371->dac[1].f_pos = 0; - break; + dev->dac[1].vf = (dev->dac[1].vf & ~0x1f8000) | ((val & 0xfc00) << 5); + dev->dac[1].ac = (dev->dac[1].ac & ~0x7f8000) | ((val & 0x00ff) << 15); + dev->dac[1].f_pos = 0; + break; + case 0x76: - es1371->dac[1].ac = (es1371->dac[1].ac & ~0x7fff) | (val & 0x7fff); - break; + dev->dac[1].ac = (dev->dac[1].ac & ~0x7fff) | (val & 0x7fff); + break; + case 0x77: - es1371->dac[1].vf = (es1371->dac[1].vf & ~0x7fff) | (val & 0x7fff); - break; + dev->dac[1].vf = (dev->dac[1].vf & ~0x7fff) | (val & 0x7fff); + break; case 0x7c: - es1371->dac[0].vol_l = (int32_t)(int16_t)(val & 0xffff); - break; + dev->dac[0].vol_l = (int32_t)(int16_t)(val & 0xffff); + break; + case 0x7d: - es1371->dac[0].vol_r = (int32_t)(int16_t)(val & 0xffff); - break; + dev->dac[0].vol_r = (int32_t)(int16_t)(val & 0xffff); + break; + case 0x7e: - es1371->dac[1].vol_l = (int32_t)(int16_t)(val & 0xffff); - break; + dev->dac[1].vol_l = (int32_t)(int16_t)(val & 0xffff); + break; + case 0x7f: - es1371->dac[1].vol_r = (int32_t)(int16_t)(val & 0xffff); - break; + dev->dac[1].vol_r = (int32_t)(int16_t)(val & 0xffff); + break; } } break; - case 0x14: - es1371->codec_ctrl = val; - if (!(val & CODEC_READ)) - { -// snddev_log("Write codec %02x %04x\n", (val >> 16) & 0x3f, val & 0xffff); - es1371->codec_regs[(val >> 16) & 0x3f] = val & 0xffff; - switch ((val >> 16) & 0x3f) - { + case 0x14: + dev->codec_ctrl = val; + if (!(val & CODEC_READ)) { + DBGLOG(1, "Write codec %02x %04x\n", (val >> 16) & 0x3f, val & 0xffff); + dev->codec_regs[(val >> 16) & 0x3f] = val & 0xffff; + switch ((val >> 16) & 0x3f) { case 0x02: /*Master volume*/ - if (val & 0x8000) - es1371->master_vol_l = es1371->master_vol_r = 0; - else - { - if (val & 0x2000) - es1371->master_vol_l = codec_attn[0]; - else - es1371->master_vol_l = codec_attn[0x1f - ((val >> 8) & 0x1f)]; - if (val & 0x20) - es1371->master_vol_r = codec_attn[0]; - else - es1371->master_vol_r = codec_attn[0x1f - (val & 0x1f)]; - } - break; + if (val & 0x8000) + dev->master_vol_l = dev->master_vol_r = 0; + else { + if (val & 0x2000) + dev->master_vol_l = codec_attn[0]; + else + dev->master_vol_l = codec_attn[0x1f - ((val >> 8) & 0x1f)]; + if (val & 0x20) + dev->master_vol_r = codec_attn[0]; + else + dev->master_vol_r = codec_attn[0x1f - (val & 0x1f)]; + } + break; + case 0x12: /*CD volume*/ - if (val & 0x8000) - sound_cd_set_volume(0, 0); - else - sound_cd_set_volume(codec_attn[0x1f - ((val >> 8) & 0x1f)] * 2, codec_attn[0x1f - (val & 0x1f)] * 2); - break; + if (val & 0x8000) + sound_cd_set_volume(0, 0); + else + sound_cd_set_volume(codec_attn[0x1f - ((val >> 8) & 0x1f)] * 2, codec_attn[0x1f - (val & 0x1f)] * 2); + break; } } break; - case 0x24: - es1371->dac[0].samp_ct = val & 0xffff; + case 0x24: + dev->dac[0].samp_ct = val & 0xffff; break; - case 0x28: - es1371->dac[1].samp_ct = val & 0xffff; + case 0x28: + dev->dac[1].samp_ct = val & 0xffff; break; - case 0x30: - switch (es1371->mem_page) - { + case 0x30: + switch (dev->mem_page) { case 0x0: case 0x1: case 0x2: case 0x3: case 0x4: case 0x5: case 0x6: case 0x7: case 0x8: case 0x9: case 0xa: case 0xb: - break; + break; case 0xc: - es1371->dac[0].addr_latch = val; -// snddev_log("DAC1 addr %08x\n", val); - break; + dev->dac[0].addr_latch = val; + DBGLOG(1, "DAC1 addr %08x\n", val); + break; default: - snddev_log("Bad es1371_outl: mem_page=%x port=%04x val=%08x\n", es1371->mem_page, port, val); + DEBUG("Bad es1371_outl: mem_page=%x port=%04x val=%08x\n", dev->mem_page, port, val); } break; - case 0x34: - switch (es1371->mem_page) - { + + case 0x34: + switch (dev->mem_page) { case 0x0: case 0x1: case 0x2: case 0x3: case 0x4: case 0x5: case 0x6: case 0x7: case 0x8: case 0x9: case 0xa: case 0xb: - break; + break; case 0xc: - es1371->dac[0].size = val & 0xffff; - es1371->dac[0].count = val >> 16; - if (es1371->dac[0].count) - es1371->dac[0].count -= 4; - break; + dev->dac[0].size = val & 0xffff; + dev->dac[0].count = val >> 16; + if (dev->dac[0].count) + dev->dac[0].count -= 4; + break; case 0xd: - es1371->adc.size = val & 0xffff; - es1371->adc.count = val >> 16; - break; + dev->adc.size = val & 0xffff; + dev->adc.count = val >> 16; + break; default: - snddev_log("Bad es1371_outl: mem_page=%x port=%04x val=%08x\n", es1371->mem_page, port, val); + DEBUG("Bad es1371_outl: mem_page=%x port=%04x val=%08x\n", dev->mem_page, port, val); } break; - case 0x38: - switch (es1371->mem_page) - { + + case 0x38: + switch (dev->mem_page) { case 0x0: case 0x1: case 0x2: case 0x3: case 0x4: case 0x5: case 0x6: case 0x7: case 0x8: case 0x9: case 0xa: case 0xb: - break; + break; case 0xc: - es1371->dac[1].addr_latch = val; - break; + dev->dac[1].addr_latch = val; + break; case 0xd: - break; + break; default: - snddev_log("Bad es1371_outl: mem_page=%x port=%04x val=%08x\n", es1371->mem_page, port, val); + DEBUG("Bad es1371_outl: mem_page=%x port=%04x val=%08x\n", dev->mem_page, port, val); } break; - case 0x3c: - switch (es1371->mem_page) - { + + case 0x3c: + switch (dev->mem_page) { case 0x0: case 0x1: case 0x2: case 0x3: case 0x4: case 0x5: case 0x6: case 0x7: case 0x8: case 0x9: case 0xa: case 0xb: - break; + break; case 0xc: - es1371->dac[1].size = val & 0xffff; - es1371->dac[1].count = val >> 16; - break; + dev->dac[1].size = val & 0xffff; + dev->dac[1].count = val >> 16; + break; default: - snddev_log("Bad es1371_outl: mem_page=%x port=%04x val=%08x\n", es1371->mem_page, port, val); + DEBUG("Bad es1371_outl: mem_page=%x port=%04x val=%08x\n", dev->mem_page, port, val); } break; - default: - snddev_log("Bad es1371_outl: port=%04x val=%08x\n", port, val); - } + default: + DEBUG("Bad es1371_outl: port=%04x val=%08x\n", port, val); + } } -static void capture_event(es1371_t *es1371, int type, int rw, uint16_t port) + +static void +capture_event(void *priv, int type, int rw, uint16_t port) { - es1371->legacy_ctrl &= ~(LEGACY_EVENT_MASK | LEGACY_EVENT_ADDR_MASK); - es1371->legacy_ctrl |= type; - if (rw) - es1371->legacy_ctrl |= LEGACY_EVENT_TYPE_RW; + es1371_t *dev = (es1371_t *)priv; + + dev->legacy_ctrl &= ~(LEGACY_EVENT_MASK | LEGACY_EVENT_ADDR_MASK); + dev->legacy_ctrl |= type; + + if (rw) + dev->legacy_ctrl |= LEGACY_EVENT_TYPE_RW; + else + dev->legacy_ctrl &= ~LEGACY_EVENT_TYPE_RW; + dev->legacy_ctrl |= ((port << LEGACY_EVENT_ADDR_SHIFT) & LEGACY_EVENT_ADDR_MASK); + dev->legacy_ctrl &= ~LEGACY_INT; + + nmi = 1; + + DBGLOG(1, "Event! %s %04x\n", rw ? "write" : "read", port); +} + + +static void +cap_write_sscape(uint16_t port, uint8_t val, void *p) +{ + capture_event(p, LEGACY_EVENT_SSCAPE, 1, port); +} +static void +cap_write_codec(uint16_t port, uint8_t val, void *p) +{ + capture_event(p, LEGACY_EVENT_CODEC, 1, port); +} +static void +cap_write_sb(uint16_t port, uint8_t val, void *p) +{ + capture_event(p, LEGACY_EVENT_SB, 1, port); +} +static void +cap_write_adlib(uint16_t port, uint8_t val, void *p) +{ + capture_event(p, LEGACY_EVENT_ADLIB, 1, port); +} +static void +cap_write_master_pic(uint16_t port, uint8_t val, void *p) +{ + capture_event(p, LEGACY_EVENT_MASTER_PIC, 1, port); +} +static void +cap_write_master_dma(uint16_t port, uint8_t val, void *p) +{ + capture_event(p, LEGACY_EVENT_MASTER_DMA, 1, port); +} +static void +cap_write_slave_pic(uint16_t port, uint8_t val, void *p) +{ + capture_event(p, LEGACY_EVENT_SLAVE_PIC, 1, port); +} +static void +cap_write_slave_dma(uint16_t port, uint8_t val, void *p) +{ + capture_event(p, LEGACY_EVENT_SLAVE_DMA, 1, port); +} + +static uint8_t +cap_read_sscape(uint16_t port, void *p) +{ + capture_event(p, LEGACY_EVENT_SSCAPE, 0, port); + return 0xff; +} +static uint8_t +cap_read_codec(uint16_t port, void *p) +{ + capture_event(p, LEGACY_EVENT_CODEC, 0, port); + return 0xff; +} +static uint8_t +cap_read_sb(uint16_t port, void *p) +{ + capture_event(p, LEGACY_EVENT_SB, 0, port); + return 0xff; +} +static uint8_t +cap_read_adlib(uint16_t port, void *p) +{ + capture_event(p, LEGACY_EVENT_ADLIB, 0, port); + return 0xff; +} +static uint8_t +cap_read_master_pic(uint16_t port, void *p) +{ + capture_event(p, LEGACY_EVENT_MASTER_PIC, 0, port); + return 0xff; +} +static uint8_t +cap_read_master_dma(uint16_t port, void *p) +{ + capture_event(p, LEGACY_EVENT_MASTER_DMA, 0, port); + return 0xff; +} +static uint8_t +cap_read_slave_pic(uint16_t port, void *p) +{ + capture_event(p, LEGACY_EVENT_SLAVE_PIC, 0, port); + return 0xff; +} +static uint8_t +cap_read_slave_dma(uint16_t port, void *p) +{ + capture_event(p, LEGACY_EVENT_SLAVE_DMA, 0, port); + return 0xff; +} + + +static void +update_legacy(es1371_t *dev) +{ + io_removehandler(0x0320, 8, + cap_read_sscape,NULL,NULL, cap_write_sscape,NULL,NULL, dev); + io_removehandler(0x0330, 8, + cap_read_sscape,NULL,NULL, cap_write_sscape,NULL,NULL, dev); + io_removehandler(0x0340, 8, + cap_read_sscape,NULL,NULL, cap_write_sscape,NULL,NULL, dev); + io_removehandler(0x0350, 8, + cap_read_sscape,NULL,NULL, cap_write_sscape,NULL,NULL, dev); + + io_removehandler(0x5300, 0x0080, + cap_read_codec,NULL,NULL, cap_write_codec,NULL,NULL, dev); + io_removehandler(0xe800, 0x0080, + cap_read_codec,NULL,NULL, cap_write_codec,NULL,NULL, dev); + io_removehandler(0xf400, 0x0080, + cap_read_codec,NULL,NULL, cap_write_codec,NULL,NULL, dev); + + io_removehandler(0x0220, 0x0010, + cap_read_sb,NULL,NULL, cap_write_sb,NULL,NULL, dev); + io_removehandler(0x0240, 0x0010, + cap_read_sb,NULL,NULL, cap_write_sb,NULL,NULL, dev); + + io_removehandler(0x0388, 0x0004, + cap_read_adlib,NULL,NULL, cap_write_adlib,NULL,NULL, dev); + + io_removehandler(0x0020, 0x0002, + cap_read_master_pic,NULL,NULL, cap_write_master_pic,NULL,NULL, dev); + io_removehandler(0x0000, 0x0010, + cap_read_master_dma,NULL,NULL, cap_write_master_dma,NULL,NULL, dev); + io_removehandler(0x00a0, 0x0002, + cap_read_slave_pic,NULL,NULL, cap_write_slave_pic,NULL,NULL, dev); + io_removehandler(0x00c0, 0x0020, + cap_read_slave_dma,NULL,NULL, cap_write_slave_dma,NULL,NULL, dev); + + if (dev->legacy_ctrl & LEGACY_CAPTURE_SSCAPE) { + switch ((dev->legacy_ctrl >> LEGACY_SSCAPE_ADDR_SHIFT) & 3) { + case 0: io_sethandler(0x0320, 0x0008, cap_read_sscape,NULL,NULL, cap_write_sscape,NULL,NULL, dev); break; + case 1: io_sethandler(0x0330, 0x0008, cap_read_sscape,NULL,NULL, cap_write_sscape,NULL,NULL, dev); break; + case 2: io_sethandler(0x0340, 0x0008, cap_read_sscape,NULL,NULL, cap_write_sscape,NULL,NULL, dev); break; + case 3: io_sethandler(0x0350, 0x0008, cap_read_sscape,NULL,NULL, cap_write_sscape,NULL,NULL, dev); break; + } + } if (dev->legacy_ctrl & LEGACY_CAPTURE_CODEC) { + switch ((dev->legacy_ctrl >> LEGACY_CODEC_ADDR_SHIFT) & 3) { + case 0: io_sethandler(0x5300, 0x0080, cap_read_codec,NULL,NULL, cap_write_codec,NULL,NULL, dev); break; + case 2: io_sethandler(0xe800, 0x0080, cap_read_codec,NULL,NULL, cap_write_codec,NULL,NULL, dev); break; + case 3: io_sethandler(0xf400, 0x0080, cap_read_codec,NULL,NULL, cap_write_codec,NULL,NULL, dev); break; + } + } + + if (dev->legacy_ctrl & LEGACY_CAPTURE_SB) { + if (!(dev->legacy_ctrl & LEGACY_SB_ADDR)) + io_sethandler(0x0220, 0x0010, cap_read_sb,NULL,NULL, cap_write_sb,NULL,NULL, dev); else - es1371->legacy_ctrl &= ~LEGACY_EVENT_TYPE_RW; - es1371->legacy_ctrl |= ((port << LEGACY_EVENT_ADDR_SHIFT) & LEGACY_EVENT_ADDR_MASK); - es1371->legacy_ctrl &= ~LEGACY_INT; - nmi = 1; -// snddev_log("Event! %s %04x\n", rw ? "write" : "read", port); -} + io_sethandler(0x0240, 0x0010, cap_read_sb,NULL,NULL, cap_write_sb,NULL,NULL, dev); + } -static void capture_write_sscape(uint16_t port, uint8_t val, void *p) -{ - capture_event(p, LEGACY_EVENT_SSCAPE, 1, port); -} -static void capture_write_codec(uint16_t port, uint8_t val, void *p) -{ - capture_event(p, LEGACY_EVENT_CODEC, 1, port); -} -static void capture_write_sb(uint16_t port, uint8_t val, void *p) -{ - capture_event(p, LEGACY_EVENT_SB, 1, port); -} -static void capture_write_adlib(uint16_t port, uint8_t val, void *p) -{ - capture_event(p, LEGACY_EVENT_ADLIB, 1, port); -} -static void capture_write_master_pic(uint16_t port, uint8_t val, void *p) -{ - capture_event(p, LEGACY_EVENT_MASTER_PIC, 1, port); -} -static void capture_write_master_dma(uint16_t port, uint8_t val, void *p) -{ - capture_event(p, LEGACY_EVENT_MASTER_DMA, 1, port); -} -static void capture_write_slave_pic(uint16_t port, uint8_t val, void *p) -{ - capture_event(p, LEGACY_EVENT_SLAVE_PIC, 1, port); -} -static void capture_write_slave_dma(uint16_t port, uint8_t val, void *p) -{ - capture_event(p, LEGACY_EVENT_SLAVE_DMA, 1, port); -} - -static uint8_t capture_read_sscape(uint16_t port, void *p) -{ - capture_event(p, LEGACY_EVENT_SSCAPE, 0, port); - return 0xff; -} -static uint8_t capture_read_codec(uint16_t port, void *p) -{ - capture_event(p, LEGACY_EVENT_CODEC, 0, port); - return 0xff; -} -static uint8_t capture_read_sb(uint16_t port, void *p) -{ - capture_event(p, LEGACY_EVENT_SB, 0, port); - return 0xff; -} -static uint8_t capture_read_adlib(uint16_t port, void *p) -{ - capture_event(p, LEGACY_EVENT_ADLIB, 0, port); - return 0xff; -} -static uint8_t capture_read_master_pic(uint16_t port, void *p) -{ - capture_event(p, LEGACY_EVENT_MASTER_PIC, 0, port); - return 0xff; -} -static uint8_t capture_read_master_dma(uint16_t port, void *p) -{ - capture_event(p, LEGACY_EVENT_MASTER_DMA, 0, port); - return 0xff; -} -static uint8_t capture_read_slave_pic(uint16_t port, void *p) -{ - capture_event(p, LEGACY_EVENT_SLAVE_PIC, 0, port); - return 0xff; -} -static uint8_t capture_read_slave_dma(uint16_t port, void *p) -{ - capture_event(p, LEGACY_EVENT_SLAVE_DMA, 0, port); - return 0xff; -} - -static void update_legacy(es1371_t *es1371) -{ - io_removehandler(0x0320, 0x0008, capture_read_sscape,NULL,NULL, capture_write_sscape,NULL,NULL, es1371); - io_removehandler(0x0330, 0x0008, capture_read_sscape,NULL,NULL, capture_write_sscape,NULL,NULL, es1371); - io_removehandler(0x0340, 0x0008, capture_read_sscape,NULL,NULL, capture_write_sscape,NULL,NULL, es1371); - io_removehandler(0x0350, 0x0008, capture_read_sscape,NULL,NULL, capture_write_sscape,NULL,NULL, es1371); - - io_removehandler(0x5300, 0x0080, capture_read_codec,NULL,NULL, capture_write_codec,NULL,NULL, es1371); - io_removehandler(0xe800, 0x0080, capture_read_codec,NULL,NULL, capture_write_codec,NULL,NULL, es1371); - io_removehandler(0xf400, 0x0080, capture_read_codec,NULL,NULL, capture_write_codec,NULL,NULL, es1371); - - io_removehandler(0x0220, 0x0010, capture_read_sb,NULL,NULL, capture_write_sb,NULL,NULL, es1371); - io_removehandler(0x0240, 0x0010, capture_read_sb,NULL,NULL, capture_write_sb,NULL,NULL, es1371); - - io_removehandler(0x0388, 0x0004, capture_read_adlib,NULL,NULL, capture_write_adlib,NULL,NULL, es1371); - - io_removehandler(0x0020, 0x0002, capture_read_master_pic,NULL,NULL, capture_write_master_pic,NULL,NULL, es1371); - io_removehandler(0x0000, 0x0010, capture_read_master_dma,NULL,NULL, capture_write_master_dma,NULL,NULL, es1371); - io_removehandler(0x00a0, 0x0002, capture_read_slave_pic,NULL,NULL, capture_write_slave_pic,NULL,NULL, es1371); - io_removehandler(0x00c0, 0x0020, capture_read_slave_dma,NULL,NULL, capture_write_slave_dma,NULL,NULL, es1371); - - if (es1371->legacy_ctrl & LEGACY_CAPTURE_SSCAPE) - { - switch ((es1371->legacy_ctrl >> LEGACY_SSCAPE_ADDR_SHIFT) & 3) - { - case 0: io_sethandler(0x0320, 0x0008, capture_read_sscape,NULL,NULL, capture_write_sscape,NULL,NULL, es1371); break; - case 1: io_sethandler(0x0330, 0x0008, capture_read_sscape,NULL,NULL, capture_write_sscape,NULL,NULL, es1371); break; - case 2: io_sethandler(0x0340, 0x0008, capture_read_sscape,NULL,NULL, capture_write_sscape,NULL,NULL, es1371); break; - case 3: io_sethandler(0x0350, 0x0008, capture_read_sscape,NULL,NULL, capture_write_sscape,NULL,NULL, es1371); break; - } - } - if (es1371->legacy_ctrl & LEGACY_CAPTURE_CODEC) - { - switch ((es1371->legacy_ctrl >> LEGACY_CODEC_ADDR_SHIFT) & 3) - { - case 0: io_sethandler(0x5300, 0x0080, capture_read_codec,NULL,NULL, capture_write_codec,NULL,NULL, es1371); break; - case 2: io_sethandler(0xe800, 0x0080, capture_read_codec,NULL,NULL, capture_write_codec,NULL,NULL, es1371); break; - case 3: io_sethandler(0xf400, 0x0080, capture_read_codec,NULL,NULL, capture_write_codec,NULL,NULL, es1371); break; - } - } - if (es1371->legacy_ctrl & LEGACY_CAPTURE_SB) - { - if (!(es1371->legacy_ctrl & LEGACY_SB_ADDR)) - io_sethandler(0x0220, 0x0010, capture_read_sb,NULL,NULL, capture_write_sb,NULL,NULL, es1371); - else - io_sethandler(0x0240, 0x0010, capture_read_sb,NULL,NULL, capture_write_sb,NULL,NULL, es1371); - } - if (es1371->legacy_ctrl & LEGACY_CAPTURE_ADLIB) - io_sethandler(0x0388, 0x0004, capture_read_adlib,NULL,NULL, capture_write_adlib,NULL,NULL, es1371); - if (es1371->legacy_ctrl & LEGACY_CAPTURE_MASTER_PIC) - io_sethandler(0x0020, 0x0002, capture_read_master_pic,NULL,NULL, capture_write_master_pic,NULL,NULL, es1371); - if (es1371->legacy_ctrl & LEGACY_CAPTURE_MASTER_DMA) - io_sethandler(0x0000, 0x0010, capture_read_master_dma,NULL,NULL, capture_write_master_dma,NULL,NULL, es1371); - if (es1371->legacy_ctrl & LEGACY_CAPTURE_SLAVE_PIC) - io_sethandler(0x00a0, 0x0002, capture_read_slave_pic,NULL,NULL, capture_write_slave_pic,NULL,NULL, es1371); - if (es1371->legacy_ctrl & LEGACY_CAPTURE_SLAVE_DMA) - io_sethandler(0x00c0, 0x0020, capture_read_slave_dma,NULL,NULL, capture_write_slave_dma,NULL,NULL, es1371); + if (dev->legacy_ctrl & LEGACY_CAPTURE_ADLIB) + io_sethandler(0x0388, 0x0004, cap_read_adlib,NULL,NULL, cap_write_adlib,NULL,NULL, dev); + if (dev->legacy_ctrl & LEGACY_CAPTURE_MASTER_PIC) + io_sethandler(0x0020, 0x0002, cap_read_master_pic,NULL,NULL, cap_write_master_pic,NULL,NULL, dev); + if (dev->legacy_ctrl & LEGACY_CAPTURE_MASTER_DMA) + io_sethandler(0x0000, 0x0010, cap_read_master_dma,NULL,NULL, cap_write_master_dma,NULL,NULL, dev); + if (dev->legacy_ctrl & LEGACY_CAPTURE_SLAVE_PIC) + io_sethandler(0x00a0, 0x0002, cap_read_slave_pic,NULL,NULL, cap_write_slave_pic,NULL,NULL, dev); + if (dev->legacy_ctrl & LEGACY_CAPTURE_SLAVE_DMA) + io_sethandler(0x00c0, 0x0020, cap_read_slave_dma,NULL,NULL, cap_write_slave_dma,NULL,NULL, dev); } -static uint8_t es1371_pci_read(int func, int addr, void *p) +static void +es1371_fetch(es1371_t *dev, int dac_nr) { - es1371_t *es1371 = (es1371_t *)p; + int format = dac_nr ? ((dev->si_cr >> 2) & 3) : (dev->si_cr & 3); + int pos = dev->dac[dac_nr].buffer_pos & 63; + int c; - if (func) - return 0; + DBGLOG(2, "Fetch format=%i %08x %08x %08x %08x %08x\n", format, dev->dac[dac_nr].count, dev->dac[dac_nr].size, dev->dac[dac_nr].curr_samp_ct,dev->dac[dac_nr].samp_ct, dev->dac[dac_nr].addr); - //snddev_log("ES1371 PCI read %08X PC=%08x\n", addr, cpu_state.pc); - - switch (addr) - { - case 0x00: return 0x74; /*Ensoniq*/ - case 0x01: return 0x12; - - case 0x02: return 0x71; /*ES1371*/ - case 0x03: return 0x13; - - case 0x04: return es1371->pci_command; - case 0x05: return es1371->pci_serr; - - case 0x06: return 0x10; /*Supports ACPI*/ - case 0x07: return 0; - - case 0x08: return 2; /*Revision ID*/ - case 0x09: return 0x00; /*Multimedia audio device*/ - case 0x0a: return 0x01; - case 0x0b: return 0x04; - - case 0x10: return 0x01 | (es1371->base_addr & 0xc0); /*memBaseAddr*/ - case 0x11: return es1371->base_addr >> 8; - case 0x12: return es1371->base_addr >> 16; - case 0x13: return es1371->base_addr >> 24; - - case 0x2c: return 0x74; /*Subsystem vendor ID*/ - case 0x2d: return 0x12; - case 0x2e: return 0x71; - case 0x2f: return 0x13; - - case 0x34: return 0xdc; /*Capabilites pointer*/ - - case 0x3c: return es1371->int_line; - case 0x3d: return 0x01; /*INTA*/ - - case 0x3e: return 0xc; /*Minimum grant*/ - case 0x3f: return 0x80; /*Maximum latency*/ - - case 0xdc: return 0x01; /*Capabilities identifier*/ - case 0xdd: return 0x00; /*Next item pointer*/ - case 0xde: return 0x31; /*Power management capabilities*/ - case 0xdf: return 0x6c; - - case 0xe0: return es1371->pmcsr & 0xff; - case 0xe1: return es1371->pmcsr >> 8; - } - return 0; -} - -static void es1371_pci_write(int func, int addr, uint8_t val, void *p) -{ - es1371_t *es1371 = (es1371_t *)p; + switch (format) { + case FORMAT_MONO_8: + for (c = 0; c < 32; c += 4) { + dev->dac[dac_nr].buffer_l[(pos+c) & 63] = dev->dac[dac_nr].buffer_r[(pos+c) & 63] = (mem_readb_phys(dev->dac[dac_nr].addr) ^ 0x80) << 8; + dev->dac[dac_nr].buffer_l[(pos+c+1) & 63] = dev->dac[dac_nr].buffer_r[(pos+c+1) & 63] = (mem_readb_phys(dev->dac[dac_nr].addr+1) ^ 0x80) << 8; + dev->dac[dac_nr].buffer_l[(pos+c+2) & 63] = dev->dac[dac_nr].buffer_r[(pos+c+2) & 63] = (mem_readb_phys(dev->dac[dac_nr].addr+2) ^ 0x80) << 8; + dev->dac[dac_nr].buffer_l[(pos+c+3) & 63] = dev->dac[dac_nr].buffer_r[(pos+c+3) & 63] = (mem_readb_phys(dev->dac[dac_nr].addr+3) ^ 0x80) << 8; + dev->dac[dac_nr].addr += 4; - if (func) - return; - -// snddev_log("ES1371 PCI write %04X %02X PC=%08x\n", addr, val, cpu_state.pc); - - switch (addr) - { - case 0x04: - if (es1371->pci_command & PCI_COMMAND_IO) - io_removehandler(es1371->base_addr, 0x0040, es1371_inb, es1371_inw, es1371_inl, es1371_outb, es1371_outw, es1371_outl, es1371); - es1371->pci_command = val & 0x05; - if (es1371->pci_command & PCI_COMMAND_IO) - io_sethandler(es1371->base_addr, 0x0040, es1371_inb, es1371_inw, es1371_inl, es1371_outb, es1371_outw, es1371_outl, es1371); - break; - case 0x05: - es1371->pci_serr = val & 1; - break; - - case 0x10: - if (es1371->pci_command & PCI_COMMAND_IO) - io_removehandler(es1371->base_addr, 0x0040, es1371_inb, es1371_inw, es1371_inl, es1371_outb, es1371_outw, es1371_outl, es1371); - es1371->base_addr = (es1371->base_addr & 0xffffff00) | (val & 0xc0); - if (es1371->pci_command & PCI_COMMAND_IO) - io_sethandler(es1371->base_addr, 0x0040, es1371_inb, es1371_inw, es1371_inl, es1371_outb, es1371_outw, es1371_outl, es1371); - break; - case 0x11: - if (es1371->pci_command & PCI_COMMAND_IO) - io_removehandler(es1371->base_addr, 0x0040, es1371_inb, es1371_inw, es1371_inl, es1371_outb, es1371_outw, es1371_outl, es1371); - es1371->base_addr = (es1371->base_addr & 0xffff00c0) | (val << 8); - if (es1371->pci_command & PCI_COMMAND_IO) - io_sethandler(es1371->base_addr, 0x0040, es1371_inb, es1371_inw, es1371_inl, es1371_outb, es1371_outw, es1371_outl, es1371); - break; - case 0x12: - es1371->base_addr = (es1371->base_addr & 0xff00ffc0) | (val << 16); - break; - case 0x13: - es1371->base_addr = (es1371->base_addr & 0x00ffffc0) | (val << 24); - break; - - case 0x3c: - es1371->int_line = val; - break; - - case 0xe0: - es1371->pmcsr = (es1371->pmcsr & 0xff00) | (val & 0x03); - break; - case 0xe1: - es1371->pmcsr = (es1371->pmcsr & 0x00ff) | ((val & 0x01) << 8); - break; - } -// snddev_log("es1371->base_addr %08x\n", es1371->base_addr); -} - -static void es1371_fetch(es1371_t *es1371, int dac_nr) -{ - int format = dac_nr ? ((es1371->si_cr >> 2) & 3) : (es1371->si_cr & 3); - int pos = es1371->dac[dac_nr].buffer_pos & 63; - int c; - -//snddev_log("Fetch format=%i %08x %08x %08x %08x %08x\n", format, es1371->dac[dac_nr].count, es1371->dac[dac_nr].size, es1371->dac[dac_nr].curr_samp_ct,es1371->dac[dac_nr].samp_ct, es1371->dac[dac_nr].addr); - switch (format) - { - case FORMAT_MONO_8: - for (c = 0; c < 32; c += 4) - { - es1371->dac[dac_nr].buffer_l[(pos+c) & 63] = es1371->dac[dac_nr].buffer_r[(pos+c) & 63] = (mem_readb_phys(es1371->dac[dac_nr].addr) ^ 0x80) << 8; - es1371->dac[dac_nr].buffer_l[(pos+c+1) & 63] = es1371->dac[dac_nr].buffer_r[(pos+c+1) & 63] = (mem_readb_phys(es1371->dac[dac_nr].addr+1) ^ 0x80) << 8; - es1371->dac[dac_nr].buffer_l[(pos+c+2) & 63] = es1371->dac[dac_nr].buffer_r[(pos+c+2) & 63] = (mem_readb_phys(es1371->dac[dac_nr].addr+2) ^ 0x80) << 8; - es1371->dac[dac_nr].buffer_l[(pos+c+3) & 63] = es1371->dac[dac_nr].buffer_r[(pos+c+3) & 63] = (mem_readb_phys(es1371->dac[dac_nr].addr+3) ^ 0x80) << 8; - es1371->dac[dac_nr].addr += 4; - - es1371->dac[dac_nr].buffer_pos_end += 4; - es1371->dac[dac_nr].count++; - if (es1371->dac[dac_nr].count > es1371->dac[dac_nr].size) - { - es1371->dac[dac_nr].count = 0; - es1371->dac[dac_nr].addr = es1371->dac[dac_nr].addr_latch; + dev->dac[dac_nr].buffer_pos_end += 4; + dev->dac[dac_nr].count++; + if (dev->dac[dac_nr].count > dev->dac[dac_nr].size) { + dev->dac[dac_nr].count = 0; + dev->dac[dac_nr].addr = dev->dac[dac_nr].addr_latch; break; } } break; - case FORMAT_STEREO_8: - for (c = 0; c < 16; c += 2) - { - es1371->dac[dac_nr].buffer_l[(pos+c) & 63] = (mem_readb_phys(es1371->dac[dac_nr].addr) ^ 0x80) << 8; - es1371->dac[dac_nr].buffer_r[(pos+c) & 63] = (mem_readb_phys(es1371->dac[dac_nr].addr + 1) ^ 0x80) << 8; - es1371->dac[dac_nr].buffer_l[(pos+c+1) & 63] = (mem_readb_phys(es1371->dac[dac_nr].addr + 2) ^ 0x80) << 8; - es1371->dac[dac_nr].buffer_r[(pos+c+1) & 63] = (mem_readb_phys(es1371->dac[dac_nr].addr + 3) ^ 0x80) << 8; - es1371->dac[dac_nr].addr += 4; + + case FORMAT_STEREO_8: + for (c = 0; c < 16; c += 2) { + dev->dac[dac_nr].buffer_l[(pos+c) & 63] = (mem_readb_phys(dev->dac[dac_nr].addr) ^ 0x80) << 8; + dev->dac[dac_nr].buffer_r[(pos+c) & 63] = (mem_readb_phys(dev->dac[dac_nr].addr + 1) ^ 0x80) << 8; + dev->dac[dac_nr].buffer_l[(pos+c+1) & 63] = (mem_readb_phys(dev->dac[dac_nr].addr + 2) ^ 0x80) << 8; + dev->dac[dac_nr].buffer_r[(pos+c+1) & 63] = (mem_readb_phys(dev->dac[dac_nr].addr + 3) ^ 0x80) << 8; + dev->dac[dac_nr].addr += 4; - es1371->dac[dac_nr].buffer_pos_end += 2; - es1371->dac[dac_nr].count++; - if (es1371->dac[dac_nr].count > es1371->dac[dac_nr].size) - { - es1371->dac[dac_nr].count = 0; - es1371->dac[dac_nr].addr = es1371->dac[dac_nr].addr_latch; + dev->dac[dac_nr].buffer_pos_end += 2; + dev->dac[dac_nr].count++; + if (dev->dac[dac_nr].count > dev->dac[dac_nr].size) { + dev->dac[dac_nr].count = 0; + dev->dac[dac_nr].addr = dev->dac[dac_nr].addr_latch; break; } } break; - case FORMAT_MONO_16: - for (c = 0; c < 16; c += 2) - { - es1371->dac[dac_nr].buffer_l[(pos+c) & 63] = es1371->dac[dac_nr].buffer_r[(pos+c) & 63] = mem_readw_phys(es1371->dac[dac_nr].addr); - es1371->dac[dac_nr].buffer_l[(pos+c+1) & 63] = es1371->dac[dac_nr].buffer_r[(pos+c+1) & 63] = mem_readw_phys(es1371->dac[dac_nr].addr + 2); - es1371->dac[dac_nr].addr += 4; - es1371->dac[dac_nr].buffer_pos_end += 2; - es1371->dac[dac_nr].count++; - if (es1371->dac[dac_nr].count > es1371->dac[dac_nr].size) - { - es1371->dac[dac_nr].count = 0; - es1371->dac[dac_nr].addr = es1371->dac[dac_nr].addr_latch; + case FORMAT_MONO_16: + for (c = 0; c < 16; c += 2) { + dev->dac[dac_nr].buffer_l[(pos+c) & 63] = dev->dac[dac_nr].buffer_r[(pos+c) & 63] = mem_readw_phys(dev->dac[dac_nr].addr); + dev->dac[dac_nr].buffer_l[(pos+c+1) & 63] = dev->dac[dac_nr].buffer_r[(pos+c+1) & 63] = mem_readw_phys(dev->dac[dac_nr].addr + 2); + dev->dac[dac_nr].addr += 4; + + dev->dac[dac_nr].buffer_pos_end += 2; + dev->dac[dac_nr].count++; + if (dev->dac[dac_nr].count > dev->dac[dac_nr].size) { + dev->dac[dac_nr].count = 0; + dev->dac[dac_nr].addr = dev->dac[dac_nr].addr_latch; break; } } break; - case FORMAT_STEREO_16: - for (c = 0; c < 4; c++) - { - es1371->dac[dac_nr].buffer_l[(pos+c) & 63] = mem_readw_phys(es1371->dac[dac_nr].addr); - es1371->dac[dac_nr].buffer_r[(pos+c) & 63] = mem_readw_phys(es1371->dac[dac_nr].addr + 2); -// snddev_log("Fetch %02x %08x %04x %04x\n", (pos+c) & 63, es1371->dac[dac_nr].addr, es1371->dac[dac_nr].buffer_l[(pos+c) & 63], es1371->dac[dac_nr].buffer_r[(pos+c) & 63]); - es1371->dac[dac_nr].addr += 4; + + case FORMAT_STEREO_16: + for (c = 0; c < 4; c++) { + dev->dac[dac_nr].buffer_l[(pos+c) & 63] = mem_readw_phys(dev->dac[dac_nr].addr); + dev->dac[dac_nr].buffer_r[(pos+c) & 63] = mem_readw_phys(dev->dac[dac_nr].addr + 2); +// DBGLOG(1, "Fetch %02x %08x %04x %04x\n", (pos+c) & 63, dev->dac[dac_nr].addr, dev->dac[dac_nr].buffer_l[(pos+c) & 63], dev->dac[dac_nr].buffer_r[(pos+c) & 63]); + dev->dac[dac_nr].addr += 4; - es1371->dac[dac_nr].buffer_pos_end++; - es1371->dac[dac_nr].count++; - if (es1371->dac[dac_nr].count > es1371->dac[dac_nr].size) - { - es1371->dac[dac_nr].count = 0; - es1371->dac[dac_nr].addr = es1371->dac[dac_nr].addr_latch; + dev->dac[dac_nr].buffer_pos_end++; + dev->dac[dac_nr].count++; + if (dev->dac[dac_nr].count > dev->dac[dac_nr].size) { + dev->dac[dac_nr].count = 0; + dev->dac[dac_nr].addr = dev->dac[dac_nr].addr_latch; break; } } break; - } + } } -static inline float low_fir_es1371(int dac_nr, int i, float NewSample) + +static __inline float +low_fir_es1371(int dac_nr, int i, float NewSample) { - static float x[2][2][128]; //input samples - static int x_pos[2] = {0, 0}; - float out = 0.0; - int read_pos; - int n_coef; - int pos = x_pos[dac_nr]; + static float x[2][2][128]; //input samples + static int x_pos[2] = {0, 0}; + float out = 0.0; + int read_pos; + int n_coef; + int pos = x_pos[dac_nr]; - x[dac_nr][i][pos] = NewSample; + x[dac_nr][i][pos] = NewSample; - /*Since only 1/16th of input samples are non-zero, only filter those that - are valid.*/ - read_pos = (pos + 15) & (127 & ~15); - n_coef = (16 - pos) & 15; + /*Since only 1/16th of input samples are non-zero, only filter those that + are valid.*/ + read_pos = (pos + 15) & (127 & ~15); + n_coef = (16 - pos) & 15; - while (n_coef < ES1371_NCoef) - { - out += low_fir_es1371_coef[n_coef] * x[dac_nr][i][read_pos]; - read_pos = (read_pos + 16) & (127 & ~15); - n_coef += 16; - } + while (n_coef < ES1371_NCoef) { + out += low_fir_es1371_coef[n_coef] * x[dac_nr][i][read_pos]; + read_pos = (read_pos + 16) & (127 & ~15); + n_coef += 16; + } - if (i == 1) - { - x_pos[dac_nr] = (x_pos[dac_nr] + 1) & 127; - if (x_pos[dac_nr] > 127) - x_pos[dac_nr] = 0; - } + if (i == 1) { + x_pos[dac_nr] = (x_pos[dac_nr] + 1) & 127; + if (x_pos[dac_nr] > 127) + x_pos[dac_nr] = 0; + } - return out; + return out; } -static void es1371_next_sample_filtered(es1371_t *es1371, int dac_nr, int out_idx) -{ - int out_l, out_r; - int c; - - if ((es1371->dac[dac_nr].buffer_pos - es1371->dac[dac_nr].buffer_pos_end) >= 0) - { - es1371_fetch(es1371, dac_nr); - } - out_l = es1371->dac[dac_nr].buffer_l[es1371->dac[dac_nr].buffer_pos & 63]; - out_r = es1371->dac[dac_nr].buffer_r[es1371->dac[dac_nr].buffer_pos & 63]; +static void +es1371_next_sample_filtered(es1371_t *dev, int dac_nr, int out_idx) +{ + int out_l, out_r; + int c; - es1371->dac[dac_nr].filtered_l[out_idx] = (int)low_fir_es1371(dac_nr, 0, (float)out_l); - es1371->dac[dac_nr].filtered_r[out_idx] = (int)low_fir_es1371(dac_nr, 1, (float)out_r); - for (c = 1; c < 16; c++) - { - es1371->dac[dac_nr].filtered_l[out_idx+c] = (int)low_fir_es1371(dac_nr, 0, 0); - es1371->dac[dac_nr].filtered_r[out_idx+c] = (int)low_fir_es1371(dac_nr, 1, 0); - } + if ((dev->dac[dac_nr].buffer_pos - dev->dac[dac_nr].buffer_pos_end) >= 0) { + es1371_fetch(dev, dac_nr); + } + + out_l = dev->dac[dac_nr].buffer_l[dev->dac[dac_nr].buffer_pos & 63]; + out_r = dev->dac[dac_nr].buffer_r[dev->dac[dac_nr].buffer_pos & 63]; -// snddev_log("Use %02x %04x %04x\n", es1371->dac[dac_nr].buffer_pos & 63, es1371->dac[dac_nr].out_l, es1371->dac[dac_nr].out_r); + dev->dac[dac_nr].filtered_l[out_idx] = (int)low_fir_es1371(dac_nr, 0, (float)out_l); + dev->dac[dac_nr].filtered_r[out_idx] = (int)low_fir_es1371(dac_nr, 1, (float)out_r); + for (c = 1; c < 16; c++) { + dev->dac[dac_nr].filtered_l[out_idx+c] = (int)low_fir_es1371(dac_nr, 0, 0); + dev->dac[dac_nr].filtered_r[out_idx+c] = (int)low_fir_es1371(dac_nr, 1, 0); + } + +// DBGLOG(1, "Use %02x %04x %04x\n", dev->dac[dac_nr].buffer_pos & 63, dev->dac[dac_nr].out_l, dev->dac[dac_nr].out_r); - es1371->dac[dac_nr].buffer_pos++; -// snddev_log("Next sample %08x %08x %08x\n", es1371->dac[dac_nr].buffer_pos, es1371->dac[dac_nr].buffer_pos_end, es1371->dac[dac_nr].curr_samp_ct); + dev->dac[dac_nr].buffer_pos++; +// DBGLOG(1, "Next sample %08x %08x %08x\n", dev->dac[dac_nr].buffer_pos, dev->dac[dac_nr].buffer_pos_end, dev->dac[dac_nr].curr_samp_ct); } -//static FILE *es1371_f;//,*es1371_f2; -static void es1371_update(es1371_t *es1371) +static void +es1371_update(es1371_t *dev) { - int32_t l, r; - - l = (es1371->dac[0].out_l * es1371->dac[0].vol_l) >> 12; - l += ((es1371->dac[1].out_l * es1371->dac[1].vol_l) >> 12); - r = (es1371->dac[0].out_r * es1371->dac[0].vol_r) >> 12; - r += ((es1371->dac[1].out_r * es1371->dac[1].vol_r) >> 12); - - l >>= 1; - r >>= 1; - - l = (l * es1371->master_vol_l) >> 15; - r = (r * es1371->master_vol_r) >> 15; - - if (l < -32768) - l = -32768; - else if (l > 32767) - l = 32767; - if (r < -32768) - r = -32768; - else if (r > 32767) - r = 32767; + int32_t l, r; - for (; es1371->pos < sound_pos_global; es1371->pos++) - { - es1371->buffer[es1371->pos*2] = l; - es1371->buffer[es1371->pos*2 + 1] = r; - } + l = (dev->dac[0].out_l * dev->dac[0].vol_l) >> 12; + l += ((dev->dac[1].out_l * dev->dac[1].vol_l) >> 12); + r = (dev->dac[0].out_r * dev->dac[0].vol_r) >> 12; + r += ((dev->dac[1].out_r * dev->dac[1].vol_r) >> 12); + + l >>= 1; + r >>= 1; + + l = (l * dev->master_vol_l) >> 15; + r = (r * dev->master_vol_r) >> 15; + + if (l < -32768) + l = -32768; + else if (l > 32767) + l = 32767; + if (r < -32768) + r = -32768; + else if (r > 32767) + r = 32767; + + for (; dev->pos < sound_pos_global; dev->pos++) { + dev->buffer[dev->pos*2] = l; + dev->buffer[dev->pos*2 + 1] = r; + } } -static void es1371_poll(void *p) -{ - es1371_t *es1371 = (es1371_t *)p; - - es1371->dac[1].time += es1371->dac[1].latch; - - es1371_update(es1371); - - if (es1371->int_ctrl & INT_DAC1_EN) - { - int frac = es1371->dac[0].ac & 0x7fff; - int idx = es1371->dac[0].ac >> 15; - int samp1_l = es1371->dac[0].filtered_l[idx]; - int samp1_r = es1371->dac[0].filtered_r[idx]; - int samp2_l = es1371->dac[0].filtered_l[(idx + 1) & 31]; - int samp2_r = es1371->dac[0].filtered_r[(idx + 1) & 31]; - - es1371->dac[0].out_l = ((samp1_l * (0x8000 - frac)) + (samp2_l * frac)) >> 15; - es1371->dac[0].out_r = ((samp1_r * (0x8000 - frac)) + (samp2_r * frac)) >> 15; -// snddev_log("1Samp %i %i %08x\n", es1371->dac[0].curr_samp_ct, es1371->dac[0].samp_ct, es1371->dac[0].ac); - es1371->dac[0].ac += es1371->dac[0].vf; - es1371->dac[0].ac &= ((32 << 15) - 1); - if ((es1371->dac[0].ac >> (15+4)) != es1371->dac[0].f_pos) - { - es1371_next_sample_filtered(es1371, 0, es1371->dac[0].f_pos ? 16 : 0); - es1371->dac[0].f_pos = (es1371->dac[0].f_pos + 1) & 1; - es1371->dac[0].curr_samp_ct++; - if (es1371->dac[0].curr_samp_ct == es1371->dac[0].samp_ct) - { -// snddev_log("DAC1 IRQ\n"); - es1371->int_status |= INT_STATUS_DAC1; - es1371_update_irqs(es1371); - } - if (es1371->dac[0].curr_samp_ct > es1371->dac[0].samp_ct) - { - es1371->dac[0].curr_samp_ct = 0; - } +static void +es1371_poll(void *priv) +{ + es1371_t *dev = (es1371_t *)priv; + + dev->dac[1].time += dev->dac[1].latch; + + es1371_update(dev); + + if (dev->int_ctrl & INT_DAC1_EN) { + int frac = dev->dac[0].ac & 0x7fff; + int idx = dev->dac[0].ac >> 15; + int samp1_l = dev->dac[0].filtered_l[idx]; + int samp1_r = dev->dac[0].filtered_r[idx]; + int samp2_l = dev->dac[0].filtered_l[(idx + 1) & 31]; + int samp2_r = dev->dac[0].filtered_r[(idx + 1) & 31]; + + dev->dac[0].out_l = ((samp1_l * (0x8000 - frac)) + (samp2_l * frac)) >> 15; + dev->dac[0].out_r = ((samp1_r * (0x8000 - frac)) + (samp2_r * frac)) >> 15; +// DBGLOG(1, "1Samp %i %i %08x\n", dev->dac[0].curr_samp_ct, dev->dac[0].samp_ct, dev->dac[0].ac); + dev->dac[0].ac += dev->dac[0].vf; + dev->dac[0].ac &= ((32 << 15) - 1); + + if ((dev->dac[0].ac >> (15+4)) != dev->dac[0].f_pos) { + es1371_next_sample_filtered(dev, 0, dev->dac[0].f_pos ? 16 : 0); + dev->dac[0].f_pos = (dev->dac[0].f_pos + 1) & 1; + + dev->dac[0].curr_samp_ct++; + if (dev->dac[0].curr_samp_ct == dev->dac[0].samp_ct) { +// DBGLOG(1, "DAC1 IRQ\n"); + dev->int_status |= INT_STATUS_DAC1; + es1371_update_irqs(dev); } + + if (dev->dac[0].curr_samp_ct > dev->dac[0].samp_ct) + dev->dac[0].curr_samp_ct = 0; } + } - if (es1371->int_ctrl & INT_DAC2_EN) - { - int frac = es1371->dac[1].ac & 0x7fff; - int idx = es1371->dac[1].ac >> 15; - int samp1_l = es1371->dac[1].filtered_l[idx]; - int samp1_r = es1371->dac[1].filtered_r[idx]; - int samp2_l = es1371->dac[1].filtered_l[(idx + 1) & 31]; - int samp2_r = es1371->dac[1].filtered_r[(idx + 1) & 31]; - - es1371->dac[1].out_l = ((samp1_l * (0x8000 - frac)) + (samp2_l * frac)) >> 15; - es1371->dac[1].out_r = ((samp1_r * (0x8000 - frac)) + (samp2_r * frac)) >> 15; -// snddev_log("2Samp %i %i %08x\n", es1371->dac[1].curr_samp_ct, es1371->dac[1].samp_ct, es1371->dac[1].ac); - es1371->dac[1].ac += es1371->dac[1].vf; - es1371->dac[1].ac &= ((32 << 15) - 1); - if ((es1371->dac[1].ac >> (15+4)) != es1371->dac[1].f_pos) - { - es1371_next_sample_filtered(es1371, 1, es1371->dac[1].f_pos ? 16 : 0); - es1371->dac[1].f_pos = (es1371->dac[1].f_pos + 1) & 1; + if (dev->int_ctrl & INT_DAC2_EN) { + int frac = dev->dac[1].ac & 0x7fff; + int idx = dev->dac[1].ac >> 15; + int samp1_l = dev->dac[1].filtered_l[idx]; + int samp1_r = dev->dac[1].filtered_r[idx]; + int samp2_l = dev->dac[1].filtered_l[(idx + 1) & 31]; + int samp2_r = dev->dac[1].filtered_r[(idx + 1) & 31]; - es1371->dac[1].curr_samp_ct++; - if (es1371->dac[1].curr_samp_ct > es1371->dac[1].samp_ct) - { -// es1371->dac[1].curr_samp_ct = 0; -// snddev_log("DAC2 IRQ\n"); - es1371->int_status |= INT_STATUS_DAC2; - es1371_update_irqs(es1371); - } - if (es1371->dac[1].curr_samp_ct > es1371->dac[1].samp_ct) - es1371->dac[1].curr_samp_ct = 0; + dev->dac[1].out_l = ((samp1_l * (0x8000 - frac)) + (samp2_l * frac)) >> 15; + dev->dac[1].out_r = ((samp1_r * (0x8000 - frac)) + (samp2_r * frac)) >> 15; +// DBGLOG(1,"2Samp %i %i %08x\n", dev->dac[1].curr_samp_ct, dev->dac[1].samp_ct, dev->dac[1].ac); + dev->dac[1].ac += dev->dac[1].vf; + dev->dac[1].ac &= ((32 << 15) - 1); + if ((dev->dac[1].ac >> (15+4)) != dev->dac[1].f_pos) { + es1371_next_sample_filtered(dev, 1, dev->dac[1].f_pos ? 16 : 0); + dev->dac[1].f_pos = (dev->dac[1].f_pos + 1) & 1; + + dev->dac[1].curr_samp_ct++; + if (dev->dac[1].curr_samp_ct > dev->dac[1].samp_ct) { +// dev->dac[1].curr_samp_ct = 0; +// DBGLOG(1, "DAC2 IRQ\n"); + dev->int_status |= INT_STATUS_DAC2; + es1371_update_irqs(dev); } + + if (dev->dac[1].curr_samp_ct > dev->dac[1].samp_ct) + dev->dac[1].curr_samp_ct = 0; } + } } -static void es1371_get_buffer(int32_t *buffer, int len, void *p) + +static void +es1371_get_buffer(int32_t *buffer, int len, void *priv) { - es1371_t *es1371 = (es1371_t *)p; - int c; + es1371_t *dev = (es1371_t *)priv; + int c; - es1371_update(es1371); + es1371_update(dev); - for (c = 0; c < len * 2; c++) - buffer[c] += (es1371->buffer[c] / 2); + for (c = 0; c < len * 2; c++) + buffer[c] += (dev->buffer[c] / 2); - es1371->pos = 0; + dev->pos = 0; } -static inline double sinc(double x) + +static __inline +double sinc(double x) { - return sin(M_PI * x) / (M_PI * x); + return sin(M_PI * x) / (M_PI * x); } -static void generate_es1371_filter() + +static void +generate_es1371_filter(void) { - /*Cutoff frequency = 1 / 32*/ - float fC = 1.0 / 32.0; - float gain; - int n; - - for (n = 0; n < ES1371_NCoef; n++) - { - /*Blackman window*/ - double w = 0.42 - (0.5 * cos((2.0*n*M_PI)/(double)(ES1371_NCoef-1))) + (0.08 * cos((4.0*n*M_PI)/(double)(ES1371_NCoef-1))); - /*Sinc filter*/ - double h = sinc(2.0 * fC * ((double)n - ((double)(ES1371_NCoef-1) / 2.0))); - - /*Create windowed-sinc filter*/ - low_fir_es1371_coef[n] = (float)(w * h); - } - - low_fir_es1371_coef[(ES1371_NCoef - 1) / 2] = 1.0; + /*Cutoff frequency = 1 / 32*/ + float fC = 1.0 / 32.0; + float gain; + int n; - gain = 0.0; - for (n = 0; n < ES1371_NCoef; n++) - gain += low_fir_es1371_coef[n] / (float)N; + for (n = 0; n < ES1371_NCoef; n++) { + /*Blackman window*/ + double w = 0.42 - (0.5 * cos((2.0*n*M_PI)/(double)(ES1371_NCoef-1))) + (0.08 * cos((4.0*n*M_PI)/(double)(ES1371_NCoef-1))); - /*Normalise filter, to produce unity gain*/ - for (n = 0; n < ES1371_NCoef; n++) - low_fir_es1371_coef[n] /= gain; + /*Sinc filter*/ + double h = sinc(2.0 * fC * ((double)n - ((double)(ES1371_NCoef-1) / 2.0))); + + /*Create windowed-sinc filter*/ + low_fir_es1371_coef[n] = (float)(w * h); + } + + low_fir_es1371_coef[(ES1371_NCoef - 1) / 2] = 1.0; + + gain = 0.0; + for (n = 0; n < ES1371_NCoef; n++) + gain += low_fir_es1371_coef[n] / (float)N; + + gain /= (float)0.95; + + /*Normalise filter, to produce unity gain*/ + for (n = 0; n < ES1371_NCoef; n++) + low_fir_es1371_coef[n] /= gain; } -static void *es1371_init(const device_t *info) + +static uint8_t +es1371_pci_read(int func, int addr, void *priv) { - es1371_t *es1371 = malloc(sizeof(es1371_t)); - memset(es1371, 0, sizeof(es1371_t)); - - sound_add_handler(es1371_get_buffer, es1371); + es1371_t *dev = (es1371_t *)priv; - es1371->card = pci_add_card(PCI_ADD_NORMAL, es1371_pci_read, es1371_pci_write, es1371); + if (func) + return 0; - timer_add(es1371_poll, &es1371->dac[1].time, TIMER_ALWAYS_ENABLED, es1371); - - generate_es1371_filter(); + DBGLOG(2, "ES1371 PCI read %08X PC=%08x\n", addr, cpu_state.pc); + + switch (addr) { + case 0x00: return 0x74; /*Ensoniq*/ + case 0x01: return 0x12; + + case 0x02: return 0x71; /*ES1371*/ + case 0x03: return 0x13; + + case 0x04: return dev->pci_command; + case 0x05: return dev->pci_serr; + + case 0x06: return 0x10; /*Supports ACPI*/ + case 0x07: return 0; + + case 0x08: return 2; /*Revision ID*/ + case 0x09: return 0x00; /*Multimedia audio device*/ + case 0x0a: return 0x01; + case 0x0b: return 0x04; - return es1371; + case 0x10: return 0x01 | (dev->base_addr & 0xc0); /*memBaseAddr*/ + case 0x11: return dev->base_addr >> 8; + case 0x12: return dev->base_addr >> 16; + case 0x13: return dev->base_addr >> 24; + + case 0x2c: return 0x74; /*Subsystem vendor ID*/ + case 0x2d: return 0x12; + case 0x2e: return 0x71; + case 0x2f: return 0x13; + + case 0x34: return 0xdc; /*Capabilites pointer*/ + + case 0x3c: return dev->int_line; + case 0x3d: return 0x01; /*INTA*/ + + case 0x3e: return 0xc; /*Minimum grant*/ + case 0x3f: return 0x80; /*Maximum latency*/ + + case 0xdc: return 0x01; /*Capabilities identifier*/ + case 0xdd: return 0x00; /*Next item pointer*/ + case 0xde: return 0x31; /*Power management capabilities*/ + case 0xdf: return 0x6c; + + case 0xe0: return dev->pmcsr & 0xff; + case 0xe1: return dev->pmcsr >> 8; + } + + return 0; } -static void es1371_close(void *p) + +static void +es1371_pci_write(int func, int addr, uint8_t val, void *p) { - es1371_t *es1371 = (es1371_t *)p; - - free(es1371); + es1371_t *dev = (es1371_t *)p; + + if (func) + return; + + DBGLOG(2, "ES1371 PCI write %04X %02X PC=%08x\n", addr, val, cpu_state.pc); + + switch (addr) { + case 0x04: + if (dev->pci_command & PCI_COMMAND_IO) + io_removehandler(dev->base_addr, 0x0040, + es1371_inb, es1371_inw, es1371_inl, + es1371_outb, es1371_outw, es1371_outl, + dev); + dev->pci_command = val & 0x05; + if (dev->pci_command & PCI_COMMAND_IO) + io_sethandler(dev->base_addr, 0x0040, + es1371_inb, es1371_inw, es1371_inl, + es1371_outb, es1371_outw, es1371_outl, + dev); + break; + + case 0x05: + dev->pci_serr = val & 1; + break; + + case 0x10: + if (dev->pci_command & PCI_COMMAND_IO) + io_removehandler(dev->base_addr, 0x0040, + es1371_inb, es1371_inw, es1371_inl, + es1371_outb, es1371_outw, es1371_outl, + dev); + dev->base_addr = (dev->base_addr & 0xffffff00) | (val & 0xc0); + if (dev->pci_command & PCI_COMMAND_IO) + io_sethandler(dev->base_addr, 0x0040, + es1371_inb, es1371_inw, es1371_inl, + es1371_outb, es1371_outw, es1371_outl, + dev); + break; + + case 0x11: + if (dev->pci_command & PCI_COMMAND_IO) + io_removehandler(dev->base_addr, 0x0040, + es1371_inb, es1371_inw, es1371_inl, + es1371_outb, es1371_outw, es1371_outl, + dev); + dev->base_addr = (dev->base_addr & 0xffff00c0) | (val << 8); + if (dev->pci_command & PCI_COMMAND_IO) + io_sethandler(dev->base_addr, 0x0040, + es1371_inb, es1371_inw, es1371_inl, + es1371_outb, es1371_outw, es1371_outl, + dev); + break; + + case 0x12: + dev->base_addr = (dev->base_addr & 0xff00ffc0) | (val << 16); + break; + + case 0x13: + dev->base_addr = (dev->base_addr & 0x00ffffc0) | (val << 24); + break; + + case 0x3c: + dev->int_line = val; + break; + + case 0xe0: + dev->pmcsr = (dev->pmcsr & 0xff00) | (val & 0x03); + break; + + case 0xe1: + dev->pmcsr = (dev->pmcsr & 0x00ff) | ((val & 0x01) << 8); + break; + } + + DBGLOG(2, "dev->base_addr %08x\n", dev->base_addr); } -static void es1371_speed_changed(void *p) + +static void * +es1371_init(const device_t *info) { - es1371_t *es1371 = (es1371_t *)p; + es1371_t *dev = (es1371_t *)mem_alloc(sizeof(es1371_t)); + memset(dev, 0, sizeof(es1371_t)); + + sound_add_handler(es1371_get_buffer, dev); + + dev->card = pci_add_card(PCI_ADD_NORMAL, + es1371_pci_read, es1371_pci_write, dev); + + timer_add(es1371_poll, &dev->dac[1].time, TIMER_ALWAYS_ENABLED, dev); + + generate_es1371_filter(); + + return dev; +} + + +static void +es1371_close(void *priv) +{ + es1371_t *dev = (es1371_t *)priv; - es1371->dac[1].latch = (int)((double)TIMER_USEC * (1000000.0 / 48000.0)); + free(dev); +} + + +static void +es1371_speed_changed(void *priv) +{ + es1371_t *dev = (es1371_t *)priv; + + dev->dac[1].latch = (int)((double)TIMER_USEC * (1000000.0 / 48000.0)); } -void es1371_add_status_info_dac(es1371_t *es1371, char *s, int max_len, int dac_nr) -{ - int ena = dac_nr ? INT_DAC2_EN : INT_DAC1_EN; - char *dac_name = dac_nr ? "DAC2 (Wave)" : "DAC1 (MIDI)"; - char temps[128]; - if (es1371->int_ctrl & ena) - { - int format = dac_nr ? ((es1371->si_cr >> 2) & 3) : (es1371->si_cr & 3); - double freq = 48000.0 * ((double)es1371->dac[dac_nr].vf / (32768.0 * 16.0)); - - switch (format) - { - case FORMAT_MONO_8: - snprintf(temps, 128, "%s format : 8-bit mono\n", dac_name); - break; - case FORMAT_STEREO_8: - snprintf(temps, 128, "%s format : 8-bit stereo\n", dac_name); - break; - case FORMAT_MONO_16: - snprintf(temps, 128, "%s format : 16-bit mono\n", dac_name); - break; - case FORMAT_STEREO_16: - snprintf(temps, 128, "%s format : 16-bit stereo\n", dac_name); - break; - } - - strncat(s, temps, max_len); - max_len -= strlen(temps); - - snprintf(temps, 128, "Playback frequency : %i Hz\n", (int)freq); - strncat(s, temps, max_len); - } - else - { - snprintf(temps, max_len, "%s stopped\n", dac_name); - strncat(s, temps, max_len); - } -} - -void es1371_add_status_info(char *s, int max_len, void *p) -{ - es1371_t *es1371 = (es1371_t *)p; - - es1371_add_status_info_dac(es1371, s, max_len, 0); - es1371_add_status_info_dac(es1371, s, max_len, 1); -} - -const device_t es1371_device = -{ - "Ensoniq AudioPCI (ES1371)", - DEVICE_PCI, - 0, - es1371_init, - es1371_close, - NULL, - NULL, - es1371_speed_changed, - NULL, - es1371_add_status_info, - NULL +const device_t es1371_device = { + "Ensoniq AudioPCI (ES1371)", + DEVICE_PCI, + 0, + es1371_init, es1371_close, NULL, + NULL, + es1371_speed_changed, + NULL, + NULL, + NULL +}; + + +const device_t sbpci128_device = { + "Sound Blaster 128", + DEVICE_PCI, + 1, + es1371_init, es1371_close, NULL, + NULL, + es1371_speed_changed, + NULL, + NULL, + NULL }; diff --git a/src/devices/sound/snd_cms.c b/src/devices/sound/snd_cms.c index f2a13cd..2dcca72 100644 --- a/src/devices/sound/snd_cms.c +++ b/src/devices/sound/snd_cms.c @@ -8,7 +8,7 @@ * * Implementation of the Creative CMS/GameBlaster sound device. * - * Version: @(#)snd_cms.c 1.0.5 2018/05/06 + * Version: @(#)snd_cms.c 1.0.6 2018/09/22 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -41,6 +41,7 @@ #include #include #include +#define dbglog sound_dev_log #include "../../emu.h" #include "../../io.h" #include "../../device.h" @@ -243,7 +244,7 @@ cms_init(const device_t *info) { cms_t *dev; - dev = (cms_t *)malloc(sizeof(cms_t)); + dev = (cms_t *)mem_alloc(sizeof(cms_t)); memset(dev, 0x00, sizeof(cms_t)); io_sethandler(0x0220, 16, @@ -265,7 +266,7 @@ cms_close(void *priv) const device_t cms_device = { - "Creative Music System / Game Blaster", + "Creative Music System (Game Blaster)", DEVICE_ISA, 0, cms_init, cms_close, NULL, diff --git a/src/devices/sound/snd_dbopl.cpp b/src/devices/sound/snd_dbopl.cpp index 8aeb4a7..367933c 100644 --- a/src/devices/sound/snd_dbopl.cpp +++ b/src/devices/sound/snd_dbopl.cpp @@ -10,7 +10,7 @@ * * NOTE: See MSC_ macros for allocation on stack. --FvK * - * Version: @(#)snd_dbopl.cpp 1.0.6 2018/04/25 + * Version: @(#)snd_dbopl.cpp 1.0.7 2018/09/22 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -44,24 +44,26 @@ # include # include # include +# define dbglog sound_log # include "../../emu.h" #endif #include "dbopl.h" #include "nukedopl.h" +#include "sound.h" #include "snd_dbopl.h" static struct { DBOPL::Chip chip; - struct opl3_chip opl3chip; + opl3_chip opl3chip; int addr; int timer[2]; uint8_t timer_ctrl; uint8_t status_mask; uint8_t status; int is_opl3; - + void (*timer_callback)(void *param, int timer, int64_t period); void *timer_param; } opl[2]; @@ -84,20 +86,18 @@ enum void opl_init(void (*timer_callback)(void *param, int timer, int64_t period), void *timer_param, int nr, int is_opl3) { - if (!is_opl3 || !opl3_type) + opl[nr].timer_callback = timer_callback; + opl[nr].timer_param = timer_param; + opl[nr].is_opl3 = is_opl3; + if (!opl_type) { - DBOPL::InitTables(); - opl[nr].chip.Setup(48000, is_opl3); - opl[nr].timer_callback = timer_callback; - opl[nr].timer_param = timer_param; - opl[nr].is_opl3 = is_opl3; + DBOPL::InitTables(); + opl[nr].chip.Setup(48000, is_opl3); } else { - OPL3_Reset(&opl[nr].opl3chip, 48000); - opl[nr].timer_callback = timer_callback; - opl[nr].timer_param = timer_param; - opl[nr].is_opl3 = is_opl3; + opl[nr].opl3chip.newm = 0; + OPL3_Reset(&opl[nr].opl3chip, 48000); } } @@ -129,17 +129,22 @@ void opl_write(int nr, uint16_t addr, uint8_t val) { if (!(addr & 1)) { - if (!opl[nr].is_opl3 || !opl3_type) - opl[nr].addr = (int)opl[nr].chip.WriteAddr(addr, val) & (opl[nr].is_opl3 ? 0x1ff : 0xff); + if (!opl_type) + opl[nr].addr = (int)opl[nr].chip.WriteAddr(addr, val) & 0x1ff; else opl[nr].addr = (int)OPL3_WriteAddr(&opl[nr].opl3chip, addr, val) & 0x1ff; + if (!opl[nr].is_opl3) + opl[nr].addr &= 0xff; } else { - if (!opl[nr].is_opl3 || !opl3_type) + if (!opl_type) opl[nr].chip.WriteReg(opl[nr].addr, val); - else - OPL3_WriteReg(&opl[nr].opl3chip, opl[nr].addr, val); + else { + OPL3_WriteRegBuffered(&opl[nr].opl3chip, (uint16_t) opl[nr].addr, val); + if (opl[nr].addr == 0x105) + opl[nr].opl3chip.newm = opl[nr].addr & 0x01; + } switch (opl[nr].addr) { @@ -192,29 +197,33 @@ void opl2_update(int nr, int16_t *buffer, int samples) #ifdef _MSC_VER static Bit32s *buffer_32 = NULL; static Bit32u buffer_sz = 0; -#endif - int c; -#ifdef _MSC_VER + /* TODO: Fix this to use a static buffer */ - if (samples > 512*1024) - { - pclog("opl2_update: possible stack overflow detected. sample count was %d", samples); - return; + if (samples > 512*1024) { + INFO("opl2_update: possible stack overflow detected. sample count was %d", samples); + return; } if ((sizeof(Bit32s) * samples) > buffer_sz) { if (buffer_32 != NULL) free(buffer_32); buffer_sz = sizeof(Bit32s) * samples; - buffer_32 = (Bit32s *)malloc(buffer_sz); + buffer_32 = (Bit32s *)mem_alloc(buffer_sz); } #else - Bit32s buffer_32[samples]; + Bit32s buffer_32[SOUNDBUFLEN]; #endif - - opl[nr].chip.GenerateBlock2(samples, buffer_32); - - for (c = 0; c < samples; c++) - buffer[c*2] = (int16_t)buffer_32[c]; + int c; + + if (opl_type) + { + OPL3_GenerateStream(&opl[nr].opl3chip, buffer, samples); + } + else + { + opl[nr].chip.GenerateBlock2(samples, buffer_32); + for (c = 0; c < samples; c++) + buffer[c*2] = (int16_t)buffer_32[c]; + } } void opl3_update(int nr, int16_t *buffer, int samples) @@ -222,26 +231,24 @@ void opl3_update(int nr, int16_t *buffer, int samples) #ifdef _MSC_VER static Bit32s *buffer_32 = NULL; static Bit32u buffer_sz = 0; -#endif - int c; -#ifdef _MSC_VER + /* TODO: Fix this to use a static buffer */ - if (samples > 512 * 1024) - { - pclog("opl2_update: possible stack overflow detected. sample count was %d", samples); - return; + if (samples > 512*1024) { + INFO("opl2_update: possible stack overflow detected. sample count was %d", samples); + return; } - if ((sizeof(Bit32s) * samples * 2) > buffer_sz) { + if ((sizeof(Bit32s) * samples) > buffer_sz) { if (buffer_32 != NULL) free(buffer_32); - buffer_sz = sizeof(Bit32s) * samples * 2; - buffer_32 = (Bit32s *)malloc(buffer_sz); + buffer_sz = sizeof(Bit32s) * samples; + buffer_32 = (Bit32s *)mem_alloc(buffer_sz); } #else - Bit32s buffer_32[samples*2]; + Bit32s buffer_32[SOUNDBUFLEN]; #endif + int c; - if (opl3_type) + if (opl_type) { OPL3_GenerateStream(&opl[nr].opl3chip, buffer, samples); } diff --git a/src/devices/sound/snd_dbopl.h b/src/devices/sound/snd_dbopl.h index dca57a6..098d585 100644 --- a/src/devices/sound/snd_dbopl.h +++ b/src/devices/sound/snd_dbopl.h @@ -8,7 +8,7 @@ * * Definitions for the DOSbox OPL emulator. * - * Version: @(#)snd_dbopl.h 1.0.2 2018/04/27 + * Version: @(#)snd_dbopl.h 1.0.3 2018/09/04 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -44,7 +44,7 @@ #ifdef __cplusplus extern "C" { #endif - extern int opl3_type; + extern int opl_type; void opl_init(void (*timer_callback)(void *param, int timer, int64_t period), void *timer_param, int nr, int is_opl3); void opl_write(int nr, uint16_t addr, uint8_t val); diff --git a/src/devices/sound/snd_emu8k.c b/src/devices/sound/snd_emu8k.c index 17d90f9..667f36b 100644 --- a/src/devices/sound/snd_emu8k.c +++ b/src/devices/sound/snd_emu8k.c @@ -8,7 +8,7 @@ * * Implementation of Emu8000 emulator. * - * Version: @(#)snd_emu8k.c 1.0.11 2018/05/06 + * Version: @(#)snd_emu8k.c 1.0.12 2018/09/22 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -44,7 +44,7 @@ #include #include #include -#define HAVE_STDARG_H +#define dbglog sound_dev_log #include "../../emu.h" #include "../../io.h" #include "../../mem.h" @@ -56,9 +56,6 @@ #include "snd_emu8k.h" -#define EMU8K_ROM_PATH L"sound/awe32.raw" - - #if !defined FILTER_INITIAL && !defined FILTER_MOOG && !defined FILTER_CONSTANT //#define FILTER_INITIAL #define FILTER_MOOG @@ -297,11 +294,11 @@ uint32_t rep_count_w = 0; } \ if (name == 0) \ { \ - /*emu8k_log("EMU8K READ %04X-%02X(%d): %04X\n",addr,(emu8k->cur_reg)<<5|emu8k->cur_voice, emu8k->cur_voice,ret);*/ \ + /*DEBUG("EMU8K READ %04X-%02X(%d): %04X\n",addr,(emu8k->cur_reg)<<5|emu8k->cur_voice, emu8k->cur_voice,ret);*/ \ } \ else \ { \ - emu8k_log("EMU8K READ %s(%d) (%d): %04X\n",name, (addr&0x2), emu8k->cur_voice, ret); \ + DEBUG("EMU8K READ %s(%d) (%d): %04X\n",name, (addr&0x2), emu8k->cur_voice, ret); \ }\ } # define WRITE16(addr, var, val) WRITE16_SWITCH(addr, var, val) \ @@ -321,11 +318,11 @@ uint32_t rep_count_w = 0; } \ if (name == 0) \ { \ - /*emu8k_log("EMU8K WRITE %04X-%02X(%d): %04X\n",addr,(emu8k->cur_reg)<<5|emu8k->cur_voice,emu8k->cur_voice, val);*/ \ + /*DEBUG("EMU8K WRITE %04X-%02X(%d): %04X\n",addr,(emu8k->cur_reg)<<5|emu8k->cur_voice,emu8k->cur_voice, val);*/ \ } \ else \ { \ - emu8k_log("EMU8K WRITE %s(%d) (%d): %04X\n",name, (addr&0x2), emu8k->cur_voice,val); \ + DEBUG("EMU8K WRITE %s(%d) (%d): %04X\n",name, (addr&0x2), emu8k->cur_voice,val); \ }\ } @@ -335,26 +332,6 @@ uint32_t rep_count_w = 0; #endif //EMU8K_DEBUG_REGISTERS -#ifdef ENABLE_SOUND_EMU8K_LOG -int sound_emu8k_do_log = ENABLE_SOUND_EMU8K_LOG; -#endif - - -static void -emu8k_log(const char *fmt, ...) -{ -#ifdef ENABLE_SOUND_EMU8K_LOG - va_list ap; - - if (sound_emu8k_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); - } -#endif -} - - static inline int16_t EMU8K_READ(emu8k_t *emu8k, uint32_t addr) { const register emu8k_mem_pointers_t addrmem = {{addr}}; @@ -427,7 +404,7 @@ uint16_t emu8k_inw(uint16_t addr, void *p) #ifdef EMU8K_DEBUG_REGISTERS if (addr == 0xE22) { - emu8k_log("EMU8K READ POINTER: %d\n", + DEBUG("EMU8K READ POINTER: %d\n", ((0x80 | ((random_helper + 1) & 0x1F)) << 8) | (emu8k->cur_reg << 5) | emu8k->cur_voice); } else if ((addr&0xF00) == 0x600) @@ -435,7 +412,7 @@ uint16_t emu8k_inw(uint16_t addr, void *p) /* These are automatically reported by READ16 */ if (rep_count_r>1) { - emu8k_log("EMU8K ...... for %d times\n", rep_count_r); + DEBUG("EMU8K ...... for %d times\n", rep_count_r); rep_count_r=0; } last_read=0; @@ -445,7 +422,7 @@ uint16_t emu8k_inw(uint16_t addr, void *p) /* These are automatically reported by READ16 */ if (rep_count_r>1) { - emu8k_log("EMU8K ...... for %d times\n", rep_count_r); + DEBUG("EMU8K ...... for %d times\n", rep_count_r); rep_count_r=0; } last_read=0; @@ -457,13 +434,13 @@ uint16_t emu8k_inw(uint16_t addr, void *p) { if (rep_count_r>1) { - emu8k_log("EMU8K ...... for %d times\n", rep_count_r); + DEBUG("EMU8K ...... for %d times\n", rep_count_r); rep_count_r=0; } last_read=tmpz; - emu8k_log("EMU8K READ RAM I/O or configuration or clock \n"); + DEBUG("EMU8K READ RAM I/O or configuration or clock \n"); } - //emu8k_log("EMU8K READ %04X-%02X(%d/%d)\n",addr,(emu8k->cur_reg)<<5|emu8k->cur_voice, emu8k->cur_reg, emu8k->cur_voice); + //DEBUG("EMU8K READ %04X-%02X(%d/%d)\n",addr,(emu8k->cur_reg)<<5|emu8k->cur_voice, emu8k->cur_reg, emu8k->cur_voice); } else if ((addr&0xF00) == 0xA00 && (emu8k->cur_reg == 2 || emu8k->cur_reg == 3)) { @@ -472,13 +449,13 @@ uint16_t emu8k_inw(uint16_t addr, void *p) { if (rep_count_r>1) { - emu8k_log("EMU8K ...... for %d times\n", rep_count_r); + DEBUG("EMU8K ...... for %d times\n", rep_count_r); rep_count_r=0; } last_read=tmpz; - emu8k_log("EMU8K READ INIT \n"); + DEBUG("EMU8K READ INIT \n"); } - //emu8k_log("EMU8K READ %04X-%02X(%d/%d)\n",addr,(emu8k->cur_reg)<<5|emu8k->cur_voice, emu8k->cur_reg, emu8k->cur_voice); + //DEBUG("EMU8K READ %04X-%02X(%d/%d)\n",addr,(emu8k->cur_reg)<<5|emu8k->cur_voice, emu8k->cur_reg, emu8k->cur_voice); } else { @@ -530,15 +507,15 @@ uint16_t emu8k_inw(uint16_t addr, void *p) } if (rep_count_r>1) { - emu8k_log("EMU8K ...... for %d times\n", rep_count_r); + DEBUG("EMU8K ...... for %d times\n", rep_count_r); } if (name == 0) { - emu8k_log("EMU8K READ %04X-%02X(%d/%d): %04X\n",addr,(emu8k->cur_reg)<<5|emu8k->cur_voice, emu8k->cur_reg, emu8k->cur_voice,val); + DEBUG("EMU8K READ %04X-%02X(%d/%d): %04X\n",addr,(emu8k->cur_reg)<<5|emu8k->cur_voice, emu8k->cur_reg, emu8k->cur_voice,val); } else { - emu8k_log("EMU8K READ %s (%d): %04X\n",name,emu8k->cur_voice, val); + DEBUG("EMU8K READ %s (%d): %04X\n",name,emu8k->cur_voice, val); } rep_count_r=0; @@ -783,7 +760,7 @@ uint16_t emu8k_inw(uint16_t addr, void *p) random_helper = (random_helper + 1) & 0x1F; return ((0x80 | random_helper) << 8) | (emu8k->cur_reg << 5) | emu8k->cur_voice; } - emu8k_log("EMU8K READ : Unknown register read: %04X-%02X(%d/%d) \n", addr, (emu8k->cur_reg << 5) | emu8k->cur_voice, emu8k->cur_reg, emu8k->cur_voice); + DEBUG("EMU8K READ : Unknown register read: %04X-%02X(%d/%d) \n", addr, (emu8k->cur_reg << 5) | emu8k->cur_voice, emu8k->cur_reg, emu8k->cur_voice); return 0xffff; } @@ -798,14 +775,14 @@ void emu8k_outw(uint16_t addr, uint16_t val, void *p) #ifdef EMU8K_DEBUG_REGISTERS if (addr == 0xE22) { - //emu8k_log("EMU8K WRITE POINTER: %d\n", val); + //DEBUG("EMU8K WRITE POINTER: %d\n", val); } else if ((addr&0xF00) == 0x600) { /* These are automatically reported by WRITE16 */ if (rep_count_w>1) { - emu8k_log("EMU8K ...... for %d times\n", rep_count_w); + DEBUG("EMU8K ...... for %d times\n", rep_count_w); rep_count_w=0; } last_write=0; @@ -815,7 +792,7 @@ void emu8k_outw(uint16_t addr, uint16_t val, void *p) /* These are automatically reported by WRITE16 */ if (rep_count_w>1) { - emu8k_log("EMU8K ...... for %d times\n", rep_count_w); + DEBUG("EMU8K ...... for %d times\n", rep_count_w); rep_count_w=0; } last_write=0; @@ -827,13 +804,13 @@ void emu8k_outw(uint16_t addr, uint16_t val, void *p) { if (rep_count_w>1) { - emu8k_log("EMU8K ...... for %d times\n", rep_count_w); + DEBUG("EMU8K ...... for %d times\n", rep_count_w); rep_count_w=0; } last_write=tmpz; - emu8k_log("EMU8K WRITE RAM I/O or configuration \n"); + DEBUG("EMU8K WRITE RAM I/O or configuration \n"); } - //emu8k_log("EMU8K WRITE %04X-%02X(%d/%d): %04X\n",addr,(emu8k->cur_reg)<<5|emu8k->cur_voice,emu8k->cur_reg,emu8k->cur_voice, val); + //DEBUG("EMU8K WRITE %04X-%02X(%d/%d): %04X\n",addr,(emu8k->cur_reg)<<5|emu8k->cur_voice,emu8k->cur_reg,emu8k->cur_voice, val); } else if ((addr&0xF00) == 0xA00 && (emu8k->cur_reg == 2 || emu8k->cur_reg == 3)) { @@ -842,13 +819,13 @@ void emu8k_outw(uint16_t addr, uint16_t val, void *p) { if (rep_count_w>1) { - emu8k_log("EMU8K ...... for %d times\n", rep_count_w); + DEBUG("EMU8K ...... for %d times\n", rep_count_w); rep_count_w=0; } last_write=tmpz; - emu8k_log("EMU8K WRITE INIT \n"); + DEBUG("EMU8K WRITE INIT \n"); } - //emu8k_log("EMU8K WRITE %04X-%02X(%d/%d): %04X\n",addr,(emu8k->cur_reg)<<5|emu8k->cur_voice,emu8k->cur_reg,emu8k->cur_voice, val); + //DEBUG("EMU8K WRITE %04X-%02X(%d/%d): %04X\n",addr,(emu8k->cur_reg)<<5|emu8k->cur_voice,emu8k->cur_reg,emu8k->cur_voice, val); } else if (addr != 0xE22) { @@ -872,15 +849,15 @@ void emu8k_outw(uint16_t addr, uint16_t val, void *p) if (rep_count_w>1) { - emu8k_log("EMU8K ...... for %d times\n", rep_count_w); + DEBUG("EMU8K ...... for %d times\n", rep_count_w); } if (name == 0) { - emu8k_log("EMU8K WRITE %04X-%02X(%d/%d): %04X\n",addr,(emu8k->cur_reg)<<5|emu8k->cur_voice,emu8k->cur_reg,emu8k->cur_voice, val); + DEBUG("EMU8K WRITE %04X-%02X(%d/%d): %04X\n",addr,(emu8k->cur_reg)<<5|emu8k->cur_voice,emu8k->cur_reg,emu8k->cur_voice, val); } else { - emu8k_log("EMU8K WRITE %s (%d): %04X\n",name,emu8k->cur_voice, val); + DEBUG("EMU8K WRITE %s (%d): %04X\n",name,emu8k->cur_voice, val); } rep_count_w=0; @@ -1548,7 +1525,7 @@ void emu8k_outw(uint16_t addr, uint16_t val, void *p) emu8k->cur_reg = ((val >> 5) & 7); return; } - emu8k_log("EMU8K WRITE: Unknown register write: %04X-%02X(%d/%d): %04X \n", addr, (emu8k->cur_reg)<<5|emu8k->cur_voice, + DEBUG("EMU8K WRITE: Unknown register write: %04X-%02X(%d/%d): %04X \n", addr, (emu8k->cur_reg)<<5|emu8k->cur_voice, emu8k->cur_reg,emu8k->cur_voice, val); } @@ -2139,10 +2116,10 @@ I've recopilated these sentences to get an idea of how to loop emu_voice->cpf_curr_frac_addr = emu_voice->addr.fract_address; //if ( emu_voice->cvcf_curr_volume != old_vol[c]) { - // emu8k_log("EMUVOL (%d):%d\n", c, emu_voice->cvcf_curr_volume); + // DEBUG("EMUVOL (%d):%d\n", c, emu_voice->cvcf_curr_volume); // old_vol[c]=emu_voice->cvcf_curr_volume; //} - //emu8k_log("EMUFILT :%d\n", emu_voice->cvcf_curr_filt_ctoff); + //DEBUG("EMUFILT :%d\n", emu_voice->cvcf_curr_filt_ctoff); } @@ -2173,18 +2150,18 @@ I've recopilated these sentences to get an idea of how to loop emu8k->pos = new_pos; } /* onboard_ram in kilobytes */ -void emu8k_init(emu8k_t *emu8k, uint16_t emu_addr, int onboard_ram) +void emu8k_init(emu8k_t *emu8k, const wchar_t *romfile, uint16_t emu_addr, int onboard_ram) { uint32_t const BLOCK_SIZE_WORDS = 0x10000; FILE *fp; int c; double out; - fp = plat_fopen(rom_path(EMU8K_ROM_PATH), L"rb"); + fp = plat_fopen(rom_path(romfile), L"rb"); if (fp == NULL) - fatal("AWE32.RAW not found\n"); + fatal("EMU8K: ROM file not found\n"); - emu8k->rom = malloc(1024 * 1024); + emu8k->rom = (int16_t *)mem_alloc(1024 * 1024); fread(emu8k->rom, 1024 * 1024, 1, fp); fclose(fp); /*AWE-DUMP creates ROM images offset by 2 bytes, so if we detect this @@ -2195,23 +2172,23 @@ void emu8k_init(emu8k_t *emu8k, uint16_t emu_addr, int onboard_ram) emu8k->rom[0x7ffff] = 0; } - emu8k->empty = malloc(2*BLOCK_SIZE_WORDS); + emu8k->empty = (int16_t *)mem_alloc(2*BLOCK_SIZE_WORDS); memset(emu8k->empty, 0, 2*BLOCK_SIZE_WORDS); /* * To save on .bss space, we allocate these on the * heap as needed, and free them on device close. */ - cubic_table = (float *)malloc(CUBIC_RESOLUTION*4*sizeof(float)); - freqtable = (int64_t *)malloc(65536*sizeof(int64_t)); - attentable = (int32_t *)malloc(256*sizeof(int32_t)); - env_vol_db_to_vol_target = (int32_t *)malloc(65537*sizeof(int32_t)); - env_vol_amplitude_to_db = (int32_t *)malloc(65537*sizeof(int32_t)); - env_mod_hertz_to_octave = (int32_t *)malloc(65537*sizeof(int32_t)); - env_attack_to_samples = (int32_t *)malloc(128*sizeof(int32_t)); - lfotable = (int32_t *)malloc(65536*sizeof(int32_t)); - lfofreqtospeed = (int64_t *)malloc(256*sizeof(int64_t)); - chortable = (double *)malloc(65536*sizeof(double)); + cubic_table = (float *)mem_alloc(CUBIC_RESOLUTION*4*sizeof(float)); + freqtable = (int64_t *)mem_alloc(65536*sizeof(int64_t)); + attentable = (int32_t *)mem_alloc(256*sizeof(int32_t)); + env_vol_db_to_vol_target = (int32_t *)mem_alloc(65537*sizeof(int32_t)); + env_vol_amplitude_to_db = (int32_t *)mem_alloc(65537*sizeof(int32_t)); + env_mod_hertz_to_octave = (int32_t *)mem_alloc(65537*sizeof(int32_t)); + env_attack_to_samples = (int32_t *)mem_alloc(128*sizeof(int32_t)); + lfotable = (int32_t *)mem_alloc(65536*sizeof(int32_t)); + lfofreqtospeed = (int64_t *)mem_alloc(256*sizeof(int64_t)); + chortable = (double *)mem_alloc(65536*sizeof(double)); int j=0; for (;j<0x8;j++) @@ -2227,7 +2204,7 @@ void emu8k_init(emu8k_t *emu8k, uint16_t emu_addr, int onboard_ram) { /*Clip to 28MB, since that's the max that we can address. */ if (onboard_ram > 0x7000) onboard_ram = 0x7000; - emu8k->ram = malloc(onboard_ram * 1024); + emu8k->ram = (int16_t *)mem_alloc(onboard_ram * 1024); memset(emu8k->ram, 0, onboard_ram * 1024); const int i_end=onboard_ram>>7; int i=0; diff --git a/src/devices/sound/snd_emu8k.h b/src/devices/sound/snd_emu8k.h index 6c71e6b..b2c7f6a 100644 --- a/src/devices/sound/snd_emu8k.h +++ b/src/devices/sound/snd_emu8k.h @@ -8,7 +8,7 @@ * * Definitions for the Emu8K emulator. * - * Version: @(#)snd_emu8k.h 1.0.1 2018/02/14 + * Version: @(#)snd_emu8k.h 1.0.2 2018/09/22 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -423,7 +423,7 @@ typedef struct emu8k_t -void emu8k_init(emu8k_t *emu8k, uint16_t emu_addr, int onboard_ram); +void emu8k_init(emu8k_t *emu8k, const wchar_t *romfile, uint16_t emu_addr, int onboard_ram); void emu8k_close(emu8k_t *emu8k); void emu8k_update(emu8k_t *emu8k); diff --git a/src/devices/sound/snd_gus.c b/src/devices/sound/snd_gus.c index 32bd7ba..a107334 100644 --- a/src/devices/sound/snd_gus.c +++ b/src/devices/sound/snd_gus.c @@ -8,7 +8,7 @@ * * Implementation of the Gravis UltraSound sound device. * - * Version: @(#)snd_gus.c 1.0.5 2018/05/06 + * Version: @(#)snd_gus.c 1.0.6 2018/09/22 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -41,6 +41,7 @@ #include #include #include +#define dbglog sound_dev_log #include "../../emu.h" #include "../../io.h" #include "../../timer.h" @@ -1101,11 +1102,11 @@ gus_init(const device_t *info) { int c; double out = 1.0; - gus_t *dev = malloc(sizeof(gus_t)); + gus_t *dev = (gus_t *)mem_alloc(sizeof(gus_t)); memset(dev, 0x00, sizeof(gus_t)); - dev->ram = malloc(1 << 20); + dev->ram = (uint8_t *)mem_alloc(1 << 20); memset(dev->ram, 0x00, 1 << 20); for (c = 0; c < 32; c++) { @@ -1119,7 +1120,7 @@ gus_init(const device_t *info) out /= 1.002709201; /* 0.0235 dB Steps */ } -// pclog("GUS: top volume %f %f %f %f\n",vol16bit[4095],vol16bit[3800],vol16bit[3000],vol16bit[2048]); +// DEBUG("GUS: top volume %f %f %f %f\n",vol16bit[4095],vol16bit[3800],vol16bit[3000],vol16bit[2048]); dev->voices=14; dev->samp_timer = dev->samp_latch = (int64_t)(TIMER_USEC * (1000000.0 / 44100.0)); diff --git a/src/devices/sound/snd_lpt_dac.c b/src/devices/sound/snd_lpt_dac.c index 922eb23..e403cf1 100644 --- a/src/devices/sound/snd_lpt_dac.c +++ b/src/devices/sound/snd_lpt_dac.c @@ -8,7 +8,7 @@ * * Implemantation of LPT-based sound devices. * - * Version: @(#)snd_lpt_dac.c 1.0.7 2018/05/06 + * Version: @(#)snd_lpt_dac.c 1.0.8 2018/09/22 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -41,6 +41,7 @@ #include #include #include +#define dbglog sound_dev_log #include "../../emu.h" #include "../../cpu/cpu.h" #include "../../machines/machine.h" @@ -132,11 +133,12 @@ dac_get_buffer(int32_t *buffer, int len, void *priv) static void * dac_init(const lpt_device_t *info) { - lpt_dac_t *dev = malloc(sizeof(lpt_dac_t)); + lpt_dac_t *dev; - pclog("SOUND: LPT device '%s' [%d] initializing!\n", + INFO("SOUND: LPT device '%s' [%d] initializing!\n", info->name, info->type); + dev = (lpt_dac_t *)mem_alloc(sizeof(lpt_dac_t)); memset(dev, 0x00, sizeof(lpt_dac_t)); dev->name = info->name; @@ -157,7 +159,7 @@ dac_close(void *priv) { lpt_dac_t *dev = (lpt_dac_t *)priv; - pclog("SOUND: LPT device '%s' closed!\n", dev->name); + INFO("SOUND: LPT device '%s' closed!\n", dev->name); free(dev); } diff --git a/src/devices/sound/snd_lpt_dss.c b/src/devices/sound/snd_lpt_dss.c index 614037e..bbe3e64 100644 --- a/src/devices/sound/snd_lpt_dss.c +++ b/src/devices/sound/snd_lpt_dss.c @@ -8,7 +8,7 @@ * * Implementation of the LPT-based DSS sound device. * - * Version: @(#)snd_lpt_dss.c 1.0.7 2018/05/06 + * Version: @(#)snd_lpt_dss.c 1.0.8 2018/09/22 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -41,6 +41,7 @@ #include #include #include +#define dbglog sound_dev_log #include "../../emu.h" #include "../../cpu/cpu.h" #include "../../machines/machine.h" @@ -145,9 +146,11 @@ dss_callback(void *priv) static void * dss_init(const lpt_device_t *info) { - dss_t *dev = malloc(sizeof(dss_t)); + dss_t *dev; -pclog("SOUND: LPT device '%s' initializing!\n", info->name); + INFO("SOUND: LPT device '%s' initializing!\n", info->name); + + dev = (dss_t *)mem_alloc(sizeof(dss_t)); memset(dev, 0x00, sizeof(dss_t)); dev->name = info->name; @@ -164,7 +167,7 @@ dss_close(void *priv) { dss_t *dev = (dss_t *)priv; - pclog("SOUND: LPT device '%s' closed!\n", dev->name); + INFO("SOUND: LPT device '%s' closed!\n", dev->name); free(dev); } diff --git a/src/devices/sound/snd_mpu401.c b/src/devices/sound/snd_mpu401.c index 340fe9a..a9414e2 100644 --- a/src/devices/sound/snd_mpu401.c +++ b/src/devices/sound/snd_mpu401.c @@ -8,7 +8,7 @@ * * Roland MPU-401 emulation. * - * Version: @(#)snd_mpu401.c 1.0.10 2018/09/04 + * Version: @(#)snd_mpu401.c 1.0.10 2018/09/22 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -45,9 +45,10 @@ #include #include #include -#define HAVE_STDARG_H +#define dbglog sound_midi_log #include "../../emu.h" #include "../../io.h" +#include "../../machines/machine.h" #include "../../timer.h" #include "../../device.h" #include "../system/pic.h" @@ -63,13 +64,6 @@ enum { }; -#ifdef ENABLE_SOUND_MPU401_LOG -int sound_mpu401_do_log = ENABLE_SOUND_MPU401_LOG; -#endif - - -int mca_version = 0; - static int64_t mpu401_event_callback = 0LL; static int64_t mpu401_eoi_callback = 0LL; static int64_t mpu401_reset_callback = 0LL; @@ -79,32 +73,16 @@ static void MPU401_WriteCommand(mpu_t *mpu, uint8_t val); static void MPU401_EOIHandlerDispatch(void *p); -static void -mpu_log(const char *fmt, ...) -{ -#ifdef ENABLE_SOUND_MPU401_LOG - va_list ap; - - if (sound_mpu401_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); - } -#endif -} -#define pclog mpu_log - - static void QueueByte(mpu_t *mpu, uint8_t data) { if (mpu->state.block_ack) { - mpu->state.block_ack=0; + mpu->state.block_ack = 0; return; } - if (mpu->queue_used == 0 && mpu->intelligent) { - mpu->state.irq_pending=1; + if ((mpu->queue_used == 0) && (mpu->mode == M_INTELLIGENT)) { + mpu->state.irq_pending = 1; picint(1 << mpu->irq); } if (mpu->queue_used < MPU401_QUEUE) { @@ -117,9 +95,9 @@ QueueByte(mpu_t *mpu, uint8_t data) pos-=MPU401_QUEUE; mpu->queue_used++; - mpu->queue[pos]=data; + mpu->queue[pos] = data; } else - pclog("MPU401:Data queue full\n"); + DEBUG("MPU401:Data queue full\n"); } @@ -136,9 +114,12 @@ MPU401_Reset(mpu_t *mpu) { uint8_t i; - picintc(1 << mpu->irq); + if (mpu->mode == M_INTELLIGENT) { + picintc(1 << mpu->irq); + mpu->state.irq_pending = 0; + } - mpu->mode = (mpu->intelligent ? M_INTELLIGENT : M_UART); + mpu->mode = M_INTELLIGENT; mpu->state.eoi_scheduled = 0; mpu->state.wsd = 0; mpu->state.wsm = 0; @@ -147,7 +128,6 @@ MPU401_Reset(mpu_t *mpu) mpu->state.cond_set = 0; mpu->state.playing = 0; mpu->state.run_irq = 0; - mpu->state.irq_pending = 0; mpu->state.cmask = 0xff; mpu->state.amask = mpu->state.tmask = 0; mpu->state.midi_mask = 0xffff; @@ -180,14 +160,14 @@ MPU401_ResetDone(void *priv) { mpu_t *mpu = (mpu_t *)priv; - pclog("MPU-401 reset callback\n"); + DEBUG("MPU-401 reset callback\n"); mpu401_reset_callback = 0LL; - mpu->state.reset=0; + mpu->state.reset = 0; if (mpu->state.cmd_pending) { - MPU401_WriteCommand(mpu, mpu->state.cmd_pending-1); - mpu->state.cmd_pending=0; + MPU401_WriteCommand(mpu, mpu->state.cmd_pending - 1); + mpu->state.cmd_pending = 0; } } @@ -195,14 +175,15 @@ MPU401_ResetDone(void *priv) static void MPU401_WriteCommand(mpu_t *mpu, uint8_t val) { - uint8_t i; + uint8_t i, was_uart; - if (mpu->state.reset) { - mpu->state.cmd_pending=val+1; - } + if (mpu->state.reset) + mpu->state.cmd_pending = val + 1; + if ((val != 0x3f) && (val != 0xff) && !mpu->intelligent) + return; if (val <= 0x2f) { - switch (val&3) { /* MIDI stop, start, continue */ + switch (val & 3) { /* MIDI stop, start, continue */ case 1: midi_write(0xfc); break; @@ -216,16 +197,15 @@ MPU401_WriteCommand(mpu_t *mpu, uint8_t val) break; } -#if 0 - if (val&0x20) - pclog("MPU-401:Unhandled Recording Command %x",(int)val); -#endif + if (val & 0x20) + DEBUG("MPU-401:Unhandled Recording Command %x",(int)val); + switch (val & 0xc) { case 0x4: /* Stop */ mpu->state.playing = 0; mpu401_event_callback = 0LL; - for (i=0xb0; i<0xbf; i++) { + for (i = 0xb0; i < 0xbf; i++) { /* All notes off */ midi_write(i); midi_write(0x7b); @@ -234,15 +214,16 @@ MPU401_WriteCommand(mpu_t *mpu, uint8_t val) break; case 0x8: /* Play */ -// pclog("MPU-401:Intelligent mode playback started"); + DEBUG("MPU-401:Intelligent mode playback started"); mpu->state.playing = 1; mpu401_event_callback = (int64_t) ((MPU401_TIMECONSTANT / (mpu->clock.tempo*mpu->clock.timebase)) * 1000LL * TIMER_USEC); ClrQueue(mpu); break; } - } else if (val>=0xa0 && val<=0xa7) { /* Request play counter */ - if (mpu->state.cmask&(1<<(val&7))) QueueByte(mpu, mpu->playbuf[val&7].counter); - } else if (val>=0xd0 && val<=0xd7) { /* Send data */ + } else if ((val >= 0xa0) && (val <= 0xa7)) {/* Request play counter */ + if (mpu->state.cmask & (1 << (val&7))) + QueueByte(mpu, mpu->playbuf[val&7].counter); + } else if ((val >= 0xd0) && (val <= 0xd7)) { /* Send data */ mpu->state.old_chan = mpu->state.channel; mpu->state.channel= val & 7; mpu->state.wsd = 1; @@ -264,44 +245,44 @@ MPU401_WriteCommand(mpu_t *mpu, uint8_t val) break; case 0x94: /* Clock to host */ - mpu->clock.clock_to_host=0; + mpu->clock.clock_to_host = 0; break; case 0x95: - mpu->clock.clock_to_host=1; + mpu->clock.clock_to_host = 1; break; case 0xc2: /* Internal timebase */ - mpu->clock.timebase=48; + mpu->clock.timebase = 48; break; case 0xc3: - mpu->clock.timebase=72; + mpu->clock.timebase = 72; break; case 0xc4: - mpu->clock.timebase=96; + mpu->clock.timebase = 96; break; case 0xc5: - mpu->clock.timebase=120; + mpu->clock.timebase = 120; break; case 0xc6: - mpu->clock.timebase=144; + mpu->clock.timebase = 144; break; case 0xc7: - mpu->clock.timebase=168; + mpu->clock.timebase = 168; break; case 0xc8: - mpu->clock.timebase=192; + mpu->clock.timebase = 192; break; /* Commands with data byte */ case 0xe0: case 0xe1: case 0xe2: case 0xe4: case 0xe6: case 0xe7: case 0xec: case 0xed: case 0xee: case 0xef: - mpu->state.command_byte=val; + mpu->state.command_byte = val; break; /* Commands 0xa# returning data */ @@ -352,22 +333,23 @@ MPU401_WriteCommand(mpu_t *mpu, uint8_t val) break; case 0xff: /* Reset MPU-401 */ - pclog("MPU-401:Reset %X\n",val); + DEBUG("MPU-401:Reset %X\n", val); mpu401_reset_callback = (int64_t) (MPU401_RESETBUSY * 33LL * TIMER_USEC); - mpu->state.reset=1; + mpu->state.reset = 1; + was_uart = (mpu->mode == M_UART); MPU401_Reset(mpu); -#if 0 - if (mpu->mode==M_UART) return;//do not send ack in UART mode -#endif + if (was_uart) + return; /* do not send ack in UART mode */ break; case 0x3f: /* UART mode */ - pclog("MPU-401:Set UART mode %X\n",val); - mpu->mode=M_UART; - break; + DEBUG("MPU-401:Set UART mode %X\n", val); + QueueByte(mpu, MSG_MPU_ACK); + mpu->mode = M_UART; + return; default:; - //pclog("MPU-401:Unhandled command %X",val); + DEBUG("MPU-401:Unhandled command %X", val); } QueueByte(mpu, MSG_MPU_ACK); @@ -377,80 +359,90 @@ MPU401_WriteCommand(mpu_t *mpu, uint8_t val) static void MPU401_WriteData(mpu_t *mpu, uint8_t val) { - if (mpu->mode==M_UART) {midi_write(val); return;} + static int length, cnt, posd; + + if (mpu->mode == M_UART) { + midi_write(val); + return; + } + + if (!mpu->intelligent) { + mpu->state.command_byte = 0; + return; + } switch (mpu->state.command_byte) { /* 0xe# command data */ case 0x00: break; case 0xe0: /* Set tempo */ - mpu->state.command_byte=0; - mpu->clock.tempo=val; + mpu->state.command_byte = 0; + mpu->clock.tempo = val; return; case 0xe1: /* Set relative tempo */ - mpu->state.command_byte=0; - mpu->clock.old_tempo_rel=mpu->clock.tempo_rel; - mpu->clock.tempo_rel=val; + mpu->state.command_byte = 0; + mpu->clock.old_tempo_rel = mpu->clock.tempo_rel; + mpu->clock.tempo_rel = val; return; case 0xe7: /* Set internal clock to host interval */ - mpu->state.command_byte=0; - mpu->clock.cth_rate=val>>2; + mpu->state.command_byte = 0; + mpu->clock.cth_rate = val >> 2; return; case 0xec: /* Set active track mask */ - mpu->state.command_byte=0; - mpu->state.tmask=val; + mpu->state.command_byte = 0; + mpu->state.tmask = val; return; case 0xed: /* Set play counter mask */ - mpu->state.command_byte=0; - mpu->state.cmask=val; + mpu->state.command_byte = 0; + mpu->state.cmask = val; return; case 0xee: /* Set 1-8 MIDI channel mask */ - mpu->state.command_byte=0; - mpu->state.midi_mask&=0xff00; - mpu->state.midi_mask|=val; + mpu->state.command_byte = 0; + mpu->state.midi_mask &= 0xff00; + mpu->state.midi_mask |= val; return; case 0xef: /* Set 9-16 MIDI channel mask */ - mpu->state.command_byte=0; - mpu->state.midi_mask&=0x00ff; - mpu->state.midi_mask|=((uint16_t)val)<<8; + mpu->state.command_byte = 0; + mpu->state.midi_mask &= 0x00ff; + mpu->state.midi_mask |= ((uint16_t)val) << 8; return; - //case 0xe2: /* Set graduation for relative tempo */ - //case 0xe4: /* Set metronome */ - //case 0xe6: /* Set metronome measure length */ default: - mpu->state.command_byte=0; + mpu->state.command_byte = 0; return; } - static int length,cnt,posd; - if (mpu->state.wsd) { /* Directly send MIDI message */ if (mpu->state.wsd_start) { - mpu->state.wsd_start=0; - cnt=0; - switch (val&0xf0) { - case 0xc0:case 0xd0: - mpu->playbuf[mpu->state.channel].value[0]=val; - length=2; + mpu->state.wsd_start = 0; + cnt = 0; + switch (val & 0xf0) { + case 0xc0: + case 0xd0: + mpu->playbuf[mpu->state.channel].value[0] = val; + length = 2; break; - case 0x80:case 0x90:case 0xa0:case 0xb0:case 0xe0: - mpu->playbuf[mpu->state.channel].value[0]=val; - length=3; + case 0x80: + case 0x90: + case 0xa0: + case 0xb0: + case 0xe0: + mpu->playbuf[mpu->state.channel].value[0] = val; + length = 3; break; case 0xf0: - //pclog("MPU-401:Illegal WSD byte\n"); - mpu->state.wsd=0; - mpu->state.channel=mpu->state.old_chan; + DEBUG("MPU-401:Illegal WSD byte\n"); + mpu->state.wsd = 0; + mpu->state.channel = mpu->state.old_chan; return; default: /* MIDI with running status */ @@ -459,49 +451,58 @@ MPU401_WriteData(mpu_t *mpu, uint8_t val) } } - if (cntstate.wsd=0; - mpu->state.channel=mpu->state.old_chan; + if (cnt == length) { + mpu->state.wsd = 0; + mpu->state.channel = mpu->state.old_chan; } return; } if (mpu->state.wsm) { /* Directly send system message */ - if (val==MSG_EOX) {midi_write(MSG_EOX);mpu->state.wsm=0;return;} + if (val == MSG_EOX) { + midi_write(MSG_EOX); + mpu->state.wsm = 0; + return; + } + if (mpu->state.wsd_start) { - mpu->state.wsd_start=0; - cnt=0; + mpu->state.wsd_start = 0; + cnt = 0; switch (val) { case 0xf2: - length=3; + length = 3; break; case 0xf3: - length=2; + length = 2; break; case 0xf6: - length=1; + length = 1; break; case 0xf0: - length=0; + length = 0; break; default: - length=0; + length = 0; } } - if (!length || cntstate.wsm=0; + if (cnt == length) + mpu->state.wsm = 0; return; } @@ -513,31 +514,32 @@ MPU401_WriteData(mpu_t *mpu, uint8_t val) return; case 0: /* Timing byte */ - mpu->condbuf.vlength=0; - if (val<0xf0) mpu->state.data_onoff++; + mpu->condbuf.vlength = 0; + if (val < 0xf0) + mpu->state.data_onoff++; else { - mpu->state.data_onoff=-1; + mpu->state.data_onoff = -1; MPU401_EOIHandlerDispatch(mpu); return; } - - if (val==0) mpu->state.send_now=1; - else mpu->state.send_now=0; - mpu->condbuf.counter=val; + mpu->state.send_now = val ? 0 : 1; + mpu->condbuf.counter = val; break; case 1: /* Command byte #1 */ - mpu->condbuf.type=T_COMMAND; - if (val==0xf8 || val==0xf9) - mpu->condbuf.type=T_OVERFLOW; - mpu->condbuf.value[mpu->condbuf.vlength]=val; + mpu->condbuf.type = T_COMMAND; + if (val == 0xf8 || val == 0xf9) + mpu->condbuf.type = T_OVERFLOW; + mpu->condbuf.value[mpu->condbuf.vlength] = val; mpu->condbuf.vlength++; - if ((val&0xf0)!=0xe0) MPU401_EOIHandlerDispatch(mpu); - else mpu->state.data_onoff++; + if ((val & 0xf0) != 0xe0) + MPU401_EOIHandlerDispatch(mpu); + else + mpu->state.data_onoff++; break; case 2:/* Command byte #2 */ - mpu->condbuf.value[mpu->condbuf.vlength]=val; + mpu->condbuf.value[mpu->condbuf.vlength] = val; mpu->condbuf.vlength++; MPU401_EOIHandlerDispatch(mpu); break; @@ -551,55 +553,57 @@ MPU401_WriteData(mpu_t *mpu, uint8_t val) return; case 0: /* Timing byte */ - if (val<0xf0) mpu->state.data_onoff=1; + if (val < 0xf0) + mpu->state.data_onoff = 1; else { - mpu->state.data_onoff=-1; + mpu->state.data_onoff = -1; MPU401_EOIHandlerDispatch(mpu); return; } - if (val==0) mpu->state.send_now=1; - else mpu->state.send_now=0; - mpu->playbuf[mpu->state.channel].counter=val; + mpu->state.send_now = val ? 0 : 1; + mpu->playbuf[mpu->state.channel].counter = val; break; case 1: /* MIDI */ mpu->playbuf[mpu->state.channel].vlength++; - posd=mpu->playbuf[mpu->state.channel].vlength; - if (posd==1) switch (val&0xf0) { + posd = mpu->playbuf[mpu->state.channel].vlength; + if (posd == 1) switch (val & 0xf0) { case 0xf0: /* System message or mark */ - if (val>0xf7) { - mpu->playbuf[mpu->state.channel].type=T_MARK; - mpu->playbuf[mpu->state.channel].sys_val=val; - length=1; - } else { - //LOG(LOG_MISC,LOG_ERROR)("MPU-401:Illegal message"); - mpu->playbuf[mpu->state.channel].type=T_MIDI_SYS; - mpu->playbuf[mpu->state.channel].sys_val=val; - length=1; - } + if (val > 0xf7) + mpu->playbuf[mpu->state.channel].type = T_MARK; + else + mpu->playbuf[mpu->state.channel].type = T_MIDI_SYS; + mpu->playbuf[mpu->state.channel].sys_val = val; + length = 1; break; - case 0xc0: case 0xd0: /* MIDI Message */ - mpu->playbuf[mpu->state.channel].type=T_MIDI_NORM; - length=mpu->playbuf[mpu->state.channel].length=2; + case 0xc0: /* MIDI Message */ + case 0xd0: + mpu->playbuf[mpu->state.channel].type = T_MIDI_NORM; + length = mpu->playbuf[mpu->state.channel].length = 2; break; - case 0x80: case 0x90: case 0xa0: case 0xb0: case 0xe0: - mpu->playbuf[mpu->state.channel].type=T_MIDI_NORM; - length=mpu->playbuf[mpu->state.channel].length=3; + case 0x80: + case 0x90: + case 0xa0: + case 0xb0: + case 0xe0: + mpu->playbuf[mpu->state.channel].type = T_MIDI_NORM; + length = mpu->playbuf[mpu->state.channel].length = 3; break; default: /* MIDI data with running status */ posd++; mpu->playbuf[mpu->state.channel].vlength++; - mpu->playbuf[mpu->state.channel].type=T_MIDI_NORM; - length=mpu->playbuf[mpu->state.channel].length; + mpu->playbuf[mpu->state.channel].type = T_MIDI_NORM; + length = mpu->playbuf[mpu->state.channel].length; break; } - if (!(posd==1 && val>=0xf0)) - mpu->playbuf[mpu->state.channel].value[posd-1]=val; - if (posd==length) MPU401_EOIHandlerDispatch(mpu); + if (! (posd == 1 && val >= 0xf0)) + mpu->playbuf[mpu->state.channel].value[posd - 1] = val; + if (posd == length) + MPU401_EOIHandlerDispatch(mpu); } } @@ -615,16 +619,16 @@ MPU401_IntelligentOut(mpu_t *mpu, uint8_t chan) break; case T_MARK: - val=mpu->playbuf[chan].sys_val; - if (val==0xfc) { + val = mpu->playbuf[chan].sys_val; + if (val == 0xfc) { midi_write(val); - mpu->state.amask&=~(1<state.req_mask&=~(1<state.amask &= ~(1 << chan); + mpu->state.req_mask &= ~(1 << chan); } break; case T_MIDI_NORM: - for (i=0;iplaybuf[chan].vlength;i++) + for (i = 0; i < mpu->playbuf[chan].vlength; i++) midi_write(mpu->playbuf[chan].value[i]); break; @@ -639,14 +643,14 @@ UpdateTrack(mpu_t *mpu, uint8_t chan) { MPU401_IntelligentOut(mpu, chan); - if (mpu->state.amask&(1<playbuf[chan].vlength=0; - mpu->playbuf[chan].type=T_OVERFLOW; - mpu->playbuf[chan].counter=0xf0; - mpu->state.req_mask|=(1<state.amask & (1 << chan)) { + mpu->playbuf[chan].vlength = 0; + mpu->playbuf[chan].type = T_OVERFLOW; + mpu->playbuf[chan].counter = 0xf0; + mpu->state.req_mask |= (1 << chan); } else { - if (mpu->state.amask==0 && !mpu->state.conductor) - mpu->state.req_mask|=(1<<12); + if (mpu->state.amask == 0 && !mpu->state.conductor) + mpu->state.req_mask |= (1 << 12); } } @@ -654,50 +658,52 @@ UpdateTrack(mpu_t *mpu, uint8_t chan) static void UpdateConductor(mpu_t *mpu) { - if (mpu->condbuf.value[0]==0xfc) { - mpu->condbuf.value[0]=0; - mpu->state.conductor=0; - mpu->state.req_mask&=~(1<<9); - if (mpu->state.amask==0) - mpu->state.req_mask|=(1<<12); + if (mpu->condbuf.value[0] == 0xfc) { + mpu->condbuf.value[0] = 0; + mpu->state.conductor = 0; + mpu->state.req_mask &= ~(1 << 9); + if (mpu->state.amask == 0) + mpu->state.req_mask |= (1 << 12); return; } - mpu->condbuf.vlength=0; - mpu->condbuf.counter=0xf0; - mpu->state.req_mask|=(1<<9); + mpu->condbuf.vlength = 0; + mpu->condbuf.counter = 0xf0; + mpu->state.req_mask |= (1 << 9); } -//Updates counters and requests new data on "End of Input" +/* Updates counters and requests new data on "End of Input". */ static void MPU401_EOIHandler(void *priv) { mpu_t *mpu = (mpu_t *)priv; uint8_t i; - pclog("MPU-401 end of input callback\n"); - + DEBUG("MPU-401 end of input callback\n"); + mpu401_eoi_callback = 0LL; - mpu->state.eoi_scheduled=0; + mpu->state.eoi_scheduled = 0; if (mpu->state.send_now) { - mpu->state.send_now=0; - if (mpu->state.cond_req) UpdateConductor(mpu); - else UpdateTrack(mpu, mpu->state.channel); + mpu->state.send_now = 0; + if (mpu->state.cond_req) + UpdateConductor(mpu); + else + UpdateTrack(mpu, mpu->state.channel); } - mpu->state.irq_pending=0; + mpu->state.irq_pending = 0; if (!mpu->state.playing || !mpu->state.req_mask) return; - i=0; + i = 0; do { - if (mpu->state.req_mask&(1<state.req_mask&=~(1<state.req_mask & (1 << i)) { + QueueByte(mpu, 0xf0 + i); + mpu->state.req_mask &= ~(1 << i); break; } - } while ((i++)<16); + } while ((i++) < 16); } @@ -707,9 +713,9 @@ MPU401_EOIHandlerDispatch(void *priv) mpu_t *mpu = (mpu_t *)priv; if (mpu->state.send_now) { - mpu->state.eoi_scheduled=1; + mpu->state.eoi_scheduled = 1; mpu401_eoi_callback = 60LL * TIMER_USEC; /* Possible a bit longer */ - } else if (!mpu->state.eoi_scheduled) + } else if (! mpu->state.eoi_scheduled) MPU401_EOIHandler(mpu); } @@ -717,7 +723,7 @@ MPU401_EOIHandlerDispatch(void *priv) static void imf_write(uint16_t addr, uint8_t val, void *priv) { - pclog("IMF:Wr %4X,%X\n", addr, val); + DBGLOG(1, "IMF:Wr %4X,%X\n", addr, val); } @@ -728,36 +734,48 @@ MPU401_ReadData(mpu_t *mpu) ret = MSG_MPU_ACK; if (mpu->queue_used) { - if (mpu->queue_pos>=MPU401_QUEUE) mpu->queue_pos-=MPU401_QUEUE; - ret=mpu->queue[mpu->queue_pos]; - mpu->queue_pos++;mpu->queue_used--; + if (mpu->queue_pos >= MPU401_QUEUE) + mpu->queue_pos -= MPU401_QUEUE; + ret = mpu->queue[mpu->queue_pos]; + mpu->queue_pos++; + mpu->queue_used--; } - if (!mpu->intelligent) return ret; + if (mpu->mode == M_UART) { + if (mpu->state.irq_pending) { + picintc(1 << mpu->irq); + mpu->state.irq_pending = 0; + } - if (mpu->queue_used == 0) picintc(1 << mpu->irq); + return ret; + } - if (ret>=0xf0 && ret<=0xf7) { + if (mpu->queue_used == 0) { + picintc(1 << mpu->irq); + mpu->state.irq_pending = 0; + } + + if (ret >= 0xf0 && ret <= 0xf7) { /* MIDI data request */ - mpu->state.channel=ret&7; - mpu->state.data_onoff=0; - mpu->state.cond_req=0; + mpu->state.channel = ret & 7; + mpu->state.data_onoff = 0; + mpu->state.cond_req = 0; } - if (ret==MSG_MPU_COMMAND_REQ) { - mpu->state.data_onoff=0; - mpu->state.cond_req=1; - if (mpu->condbuf.type!=T_OVERFLOW) { - mpu->state.block_ack=1; + if (ret == MSG_MPU_COMMAND_REQ) { + mpu->state.data_onoff = 0; + mpu->state.cond_req = 1; + if (mpu->condbuf.type != T_OVERFLOW) { + mpu->state.block_ack = 1; MPU401_WriteCommand(mpu, mpu->condbuf.value[0]); if (mpu->state.command_byte) MPU401_WriteData(mpu, mpu->condbuf.value[1]); } - mpu->condbuf.type=T_OVERFLOW; + mpu->condbuf.type = T_OVERFLOW; } - if (ret==MSG_MPU_END || ret==MSG_MPU_CLOCK || ret==MSG_MPU_ACK) { - mpu->state.data_onoff=-1; + if (ret == MSG_MPU_END || ret == MSG_MPU_CLOCK || ret == MSG_MPU_ACK) { + mpu->state.data_onoff = -1; MPU401_EOIHandlerDispatch(mpu); } @@ -769,17 +787,18 @@ static void mpu401_write(uint16_t addr, uint8_t val, void *priv) { mpu_t *mpu = (mpu_t *)priv; - - /* pclog("MPU401 Write Port %04X, val %x\n", addr, val); */ + + DBGLOG(2, "MPU401 Write Port %04X, val %x\n", addr, val); + switch (addr & 1) { case 0: /*Data*/ MPU401_WriteData(mpu, val); - pclog("Write Data (0x330) %X\n", val); + DBGLOG(1, "Write Data (0x330) %X\n", val); break; case 1: /*Command*/ MPU401_WriteCommand(mpu, val); - pclog("Write Command (0x331) %x\n", val); + DBGLOG(1, "Write Command (0x331) %x\n", val); break; } } @@ -792,21 +811,23 @@ mpu401_read(uint16_t addr, void *priv) uint8_t ret = 0; switch (addr & 1) { - case 0: //Read Data + case 0: /* Read Data */ ret = MPU401_ReadData(mpu); - pclog("Read Data (0x330) %X\n", ret); + DBGLOG(1, "Read Data (0x330) %X\n", ret); break; - case 1: //Read Status - if (mpu->state.cmd_pending) ret=STATUS_OUTPUT_NOT_READY; - if (!mpu->queue_used) ret=STATUS_INPUT_NOT_READY; + case 1: /* Read Status */ + if (mpu->state.cmd_pending) + ret = STATUS_OUTPUT_NOT_READY; + if (! mpu->queue_used) + ret = STATUS_INPUT_NOT_READY; ret |= 0x3f; - - pclog("Read Status (0x331) %x\n", ret); + DBGLOG(1, "Read Status (0x331) %x\n", ret); break; } - /* pclog("MPU401 Read Port %04X, ret %x\n", addr, ret); */ + DBGLOG(2, "MPU401 Read Port %04X, ret %x\n", addr, ret); + return(ret); } @@ -818,14 +839,15 @@ MPU401_Event(void *priv) int new_time; uint8_t i; - pclog("MPU-401 event callback\n"); + DBGLOG(1, "MPU-401 event callback\n"); if (mpu->mode == M_UART) { mpu401_event_callback = 0LL; return; } - if (mpu->state.irq_pending) goto next_event; + if (mpu->state.irq_pending) + goto next_event; for (i = 0; i < 8; i++) { /* Decrease counters */ if (mpu->state.amask & (1 << i)) { @@ -854,14 +876,11 @@ MPU401_Event(void *priv) next_event: /* mpu401_event_callback = 0LL; */ - new_time = ((mpu->clock.tempo * mpu->clock.timebase * mpu->clock.tempo_rel)/0x40); - if (new_time == 0) { + new_time = ((mpu->clock.tempo * mpu->clock.timebase * mpu->clock.tempo_rel) / 0x40); + if (new_time == 0) mpu401_event_callback = 0LL; - return; - } else { - mpu401_event_callback += (int64_t) ((MPU401_TIMECONSTANT/new_time) * 1000LL * TIMER_USEC); - pclog("Next event after %i us (time constant: %i)\n", (int) ((MPU401_TIMECONSTANT/new_time) * 1000 * TIMER_USEC), (int) MPU401_TIMECONSTANT); - } + else + mpu401_event_callback += (int64_t) ((MPU401_TIMECONSTANT / new_time) * 1000LL * TIMER_USEC); } @@ -874,15 +893,26 @@ mpu401_init(mpu_t *mpu, uint16_t addr, int irq, int mode) mpu->queue_pos = 0; mpu->mode = M_UART; + /* Explanation: + * + * MPU-401 starting in intelligent mode = Full MPU-401 intelligent + * mode capability; + * MPU-401 starting in UART mode = Reduced MPU-401 intelligent mode + * capability seen on the Sound Blaster 16/AWE32, only + * supporting commands 3F (set UART mode) and FF (reset). + */ mpu->intelligent = (mode == M_INTELLIGENT) ? 1 : 0; - pclog("Starting as %s (mode is %s)\n", mpu->intelligent ? "INTELLIGENT" : "UART", (mode == M_INTELLIGENT) ? "INTELLIGENT" : "UART"); + INFO("MPU-401: starting as %s (mode is %s)\n", + mpu->intelligent ? "INTELLIGENT" : "UART", + (mode == M_INTELLIGENT) ? "INTELLIGENT" : "UART"); mpu401_event_callback = 0LL; mpu401_eoi_callback = 0LL; mpu401_reset_callback = 0LL; - io_sethandler(addr, 2, - mpu401_read, NULL, NULL, mpu401_write, NULL, NULL, mpu); + if (addr) + io_sethandler(addr, 2, + mpu401_read, NULL, NULL, mpu401_write, NULL, NULL, mpu); io_sethandler(0x2A20, 16, NULL, NULL, NULL, imf_write, NULL, NULL, mpu); timer_add(MPU401_Event, &mpu401_event_callback, &mpu401_event_callback, mpu); @@ -896,23 +926,8 @@ mpu401_init(mpu_t *mpu, uint16_t addr, int irq, int mode) void mpu401_device_add(void) { - const char *n; - if (!mpu401_standalone_enable) return; - - n = sound_card_get_internal_name(sound_card); - if (n != NULL) { - if (! strcmp(n, "ncraudio")) - mca_version = 1; - else - mca_version = 0; - - if (!strcmp(n, "sb16") || - !strcmp(n, "sbawe32") || - !strcmp(n, "replysb16")) return; - } - - if (mca_version) + if (machines[machine].flags & MACHINE_MCA) device_add(&mpu401_mca_device); else device_add(&mpu401_device); @@ -937,20 +952,17 @@ mpu401_mca_write(int port, uint8_t val, void *priv) if (port < 0x102) return; addr = (dev->pos_regs[2] & 2) ? 0x0330 : 0x1330; + port &= 7; + dev->pos_regs[port] = val; - io_removehandler(addr, 2, - mpu401_read,NULL,NULL, mpu401_write,NULL,NULL, dev); - io_removehandler(0x2a20, 16, - NULL,NULL,NULL, imf_write,NULL,NULL, dev); + if (port == 2) { + io_removehandler(addr, 2, + mpu401_read,NULL,NULL, mpu401_write,NULL,NULL, dev); - dev->pos_regs[port & 7] = val; - - if (dev->pos_regs[2] & 1) { addr = (dev->pos_regs[2] & 2) ? 0x0330 : 0x1330; - mpu401_init(dev, addr, - device_get_config_int("irq"), - device_get_config_int("mode")); + io_removehandler(addr, 2, + mpu401_read,NULL,NULL, mpu401_write,NULL,NULL, dev); } } @@ -959,21 +971,26 @@ static void * mpu401_standalone_init(const device_t *info) { mpu_t *dev; + uint16_t base; + int irq; - dev = malloc(sizeof(mpu_t)); + dev = (mpu_t *)mem_alloc(sizeof(mpu_t)); memset(dev, 0x00, sizeof(mpu_t)); if (info->flags & DEVICE_MCA) { - mca_add(mpu401_mca_read, mpu401_mca_write, dev); dev->pos_regs[0] = 0x0F; - dev->pos_regs[1] = 0x6C; + dev->pos_regs[1] = 0x6C; + mca_add(mpu401_mca_read, mpu401_mca_write, dev); + + base = 0; /* Tell mpu401_init() that this is the MCA variant. */ + irq = 2; /* According to @6c0f.adf, the IRQ is fixed to 2. */ } else { - mpu401_init(dev, - device_get_config_hex16("base"), - device_get_config_int("irq"), - device_get_config_int("mode")); + base = device_get_config_hex16("base"); + irq = device_get_config_int("irq"); } + mpu401_init(dev, base, irq, M_INTELLIGENT); + return(dev); } @@ -987,69 +1004,54 @@ mpu401_standalone_close(void *priv) } -static const device_config_t mpu401_standalone_config[] = -{ +static const device_config_t mpu401_standalone_config[] = { + { + "base", "MPU-401 Address", CONFIG_HEX16, "", 0x330, { - "base", "MPU-401 Address", CONFIG_HEX16, "", 0x330, { - { - "0x300", 0x300 - }, - { - "0x330", 0x330 - }, - { - "" - } - } - }, - { - "irq", "MPU-401 IRQ", CONFIG_SELECTION, "", 9, + "0x300", 0x300 + }, { - { - "IRQ 9", 9 - }, - { - "IRQ 3", 3 - }, - { - "IRQ 4", 4 - }, - { - "IRQ 5", 5 - }, - { - "IRQ 7", 7 - }, - { - "IRQ 10", 10 - }, - { - "" - } - } - }, - { - "mode", "Mode", CONFIG_SELECTION, "", 1, + "0x330", 0x330 + }, { - { - "UART", M_UART - }, - { - "Intelligent", M_INTELLIGENT - }, - { - "" - } + "" } - }, - { - "", "", -1 } + }, + { + "irq", "MPU-401 IRQ", CONFIG_SELECTION, "", 9, + { + { + "IRQ 9", 9 + }, + { + "IRQ 3", 3 + }, + { + "IRQ 4", 4 + }, + { + "IRQ 5", 5 + }, + { + "IRQ 7", 7 + }, + { + "IRQ 10", 10 + }, + { + "" + } + } + }, + { + "", "", -1 + } }; const device_t mpu401_device = { - "MPU-401 (Standalone)", + "Roland MPU-IPC-T", DEVICE_ISA, 0, mpu401_standalone_init, mpu401_standalone_close, NULL, @@ -1060,54 +1062,6 @@ const device_t mpu401_device = { mpu401_standalone_config }; - -static const device_config_t mpu401_mca_standalone_config[] = -{ - { - "irq", "MPU-401 IRQ", CONFIG_SELECTION, "", 9, - { - { - "IRQ 9", 9 - }, - { - "IRQ 3", 3 - }, - { - "IRQ 4", 4 - }, - { - "IRQ 5", 5 - }, - { - "IRQ 7", 7 - }, - { - "IRQ 10", 10 - }, - { - "" - } - } - }, - { - "mode", "Mode", CONFIG_SELECTION, "", 1, - { - { - "UART", M_UART - }, - { - "Intelligent", M_INTELLIGENT - }, - { - "" - } - } - }, - { - "", "", -1 - } -}; - const device_t mpu401_mca_device = { "MPU-401 MCA (Standalone)", DEVICE_MCA, @@ -1117,5 +1071,5 @@ const device_t mpu401_mca_device = { NULL, NULL, NULL, - mpu401_mca_standalone_config + NULL }; diff --git a/src/devices/sound/snd_mpu401.h b/src/devices/sound/snd_mpu401.h index 39c802f..853665f 100644 --- a/src/devices/sound/snd_mpu401.h +++ b/src/devices/sound/snd_mpu401.h @@ -8,7 +8,7 @@ * * Roland MPU-401 emulation. * - * Version: @(#)snd_mpu401.h 1.0.4 2018/09/03 + * Version: @(#)snd_mpu401.h 1.0.5 2018/09/11 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -53,6 +53,7 @@ typedef enum { M_UART, M_INTELLIGENT } MpuMode; +#define M_MCA 0x10 typedef enum { T_OVERFLOW, @@ -64,68 +65,61 @@ typedef enum { /* Messages sent to MPU-401 from host */ -#define MSG_EOX 0xf7 -#define MSG_OVERFLOW 0xf8 -#define MSG_MARK 0xfc +#define MSG_EOX 0xf7 +#define MSG_OVERFLOW 0xf8 +#define MSG_MARK 0xfc /* Messages sent to host from MPU-401 */ -#define MSG_MPU_OVERFLOW 0xf8 -#define MSG_MPU_COMMAND_REQ 0xf9 -#define MSG_MPU_END 0xfc -#define MSG_MPU_CLOCK 0xfd -#define MSG_MPU_ACK 0xfe +#define MSG_MPU_OVERFLOW 0xf8 +#define MSG_MPU_COMMAND_REQ 0xf9 +#define MSG_MPU_END 0xfc +#define MSG_MPU_CLOCK 0xfd +#define MSG_MPU_ACK 0xfe typedef struct { - int uart_mode; - uint8_t rx_data; - int intelligent; - MpuMode mode; - int irq; - uint8_t status; - uint8_t queue[MPU401_QUEUE]; - int queue_pos, - queue_used; + int uart_mode, intelligent, + irq, + queue_pos, queue_used; + + uint8_t rx_data, is_mca, + status, + queue[MPU401_QUEUE], pos_regs[8]; + MpuMode mode; struct track { - int counter; - uint8_t value[8], - sys_val; - uint8_t vlength, - length; - MpuDataType type; - } playbuf[8], - condbuf; + int counter; + uint8_t value[8], sys_val, + vlength,length; + MpuDataType type; + } playbuf[8], condbuf; struct { - int conductor,cond_req,cond_set, block_ack; - int playing,reset; - int wsd,wsm,wsd_start; - int run_irq,irq_pending; - int send_now; - int eoi_scheduled; - int data_onoff; - uint32_t command_byte,cmd_pending; - uint8_t tmask,cmask,amask; - uint16_t midi_mask; - uint16_t req_mask; - uint8_t channel,old_chan; + int conductor, cond_req, + cond_set, block_ack, + playing, reset, + wsd, wsm, wsd_start, + run_irq, irq_pending, + send_now, eoi_scheduled, + data_onoff; + uint8_t tmask, cmask, + amask, + channel, old_chan; + uint16_t midi_mask, req_mask; + uint32_t command_byte, cmd_pending; } state; struct { - uint8_t timebase,old_timebase; - uint8_t tempo,old_tempo; - uint8_t tempo_rel,old_tempo_rel; - uint8_t tempo_grad; - uint8_t cth_rate,cth_counter; - int clock_to_host,cth_active; + uint8_t timebase, old_timebase, + tempo, old_tempo, + tempo_rel, old_tempo_rel, + tempo_grad, + cth_rate, cth_counter; + int clock_to_host,cth_active; } clock; - - uint8_t pos_regs[8]; } mpu_t; -extern int mca_version; extern const device_t mpu401_device; extern const device_t mpu401_mca_device; diff --git a/src/devices/sound/snd_opl.c b/src/devices/sound/snd_opl.c index 0dad542..dc5878d 100644 --- a/src/devices/sound/snd_opl.c +++ b/src/devices/sound/snd_opl.c @@ -8,7 +8,7 @@ * * Interface to the actual OPL emulator. * - * Version: @(#)snd_opl.c 1.0.2 2018/05/06 + * Version: @(#)snd_opl.c 1.0.3 2018/09/15 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -42,6 +42,7 @@ #include #include #include +#define dbglog sound_dev_log #include "../../emu.h" #include "../../cpu/cpu.h" #include "../../io.h" diff --git a/src/devices/sound/snd_pas16.c b/src/devices/sound/snd_pas16.c index a210838..c7d8d7c 100644 --- a/src/devices/sound/snd_pas16.c +++ b/src/devices/sound/snd_pas16.c @@ -79,7 +79,7 @@ * FF88 - board model * 3 = PAS16 * - * Version: @(#)snd_pas16.c 1.0.6 2018/05/06 + * Version: @(#)snd_pas16.c 1.0.7 2018/09/22 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -112,6 +112,7 @@ #include #include #include +#define dbglog sound_dev_log #include "../../emu.h" #include "../../cpu/cpu.h" #include "../../io.h" @@ -215,8 +216,10 @@ static uint8_t pas16_in(uint16_t port, void *p) { pas16_t *pas16 = (pas16_t *)p; uint8_t temp; + /* if (CS == 0xCA53 && pc == 0x3AFC) fatal("here");*/ + switch ((port - pas16->base) + 0x388) { case 0x388: case 0x389: case 0x38a: case 0x38b: @@ -307,22 +310,26 @@ static uint8_t pas16_in(uint16_t port, void *p) temp = 0xff; break; } -/* if (port != 0x388 && port != 0x389 && port != 0xb8b) */pclog("pas16_in : port %04X return %02X %04X:%04X\n", port, temp, CS,cpu_state.pc); + +/* if (port != 0x388 && port != 0x389 && port != 0xb8b) */DEBUG("pas16_in : port %04X return %02X %04X:%04X\n", port, temp, CS,cpu_state.pc); /* if (CS == 0x1FF4 && pc == 0x0585) { if (output) fatal("here"); output = 3; }*/ + return temp; } static void pas16_out(uint16_t port, uint8_t val, void *p) { pas16_t *pas16 = (pas16_t *)p; -/* if (port != 0x388 && port != 0x389) */pclog("pas16_out : port %04X val %02X %04X:%04X\n", port, val, CS,cpu_state.pc); + +/* if (port != 0x388 && port != 0x389) */DEBUG("pas16_out : port %04X val %02X %04X:%04X\n", port, val, CS,cpu_state.pc); /* if (CS == 0x369 && pc == 0x2AC5) fatal("here\n");*/ + switch ((port - pas16->base) + 0x388) { case 0x388: case 0x389: case 0x38a: case 0x38b: @@ -387,12 +394,12 @@ static void pas16_out(uint16_t port, uint8_t val, void *p) case 0xf389: pas16->io_conf_2 = val; pas16->dma = pas16_dmas[val & 0x7]; - pclog("pas16_out : set PAS DMA %i\n", pas16->dma); + DEBUG("pas16_out : set PAS DMA %i\n", pas16->dma); break; case 0xf38a: pas16->io_conf_3 = val; pas16->irq = pas16_irqs[val & 0xf]; - pclog("pas16_out : set PAS IRQ %i\n", pas16->irq); + DEBUG("pas16_out : set PAS IRQ %i\n", pas16->irq); break; case 0xf38b: pas16->io_conf_4 = val; @@ -415,11 +422,11 @@ static void pas16_out(uint16_t port, uint8_t val, void *p) pas16->sb_irqdma = val; sb_dsp_setirq(&pas16->dsp, pas16_sb_irqs[(val >> 3) & 7]); sb_dsp_setdma8(&pas16->dsp, pas16_sb_dmas[(val >> 6) & 3]); - pclog("pas16_out : set SB IRQ %i DMA %i\n", pas16_sb_irqs[(val >> 3) & 7], pas16_sb_dmas[(val >> 6) & 3]); + DEBUG("pas16_out : set SB IRQ %i DMA %i\n", pas16_sb_irqs[(val >> 3) & 7], pas16_sb_dmas[(val >> 6) & 3]); break; default: - pclog("pas16_out : unknown %04X\n", port); + DEBUG("pas16_out : unknown %04X\n", port); } if (cpu_state.pc == 0x80048CF3) { @@ -452,7 +459,7 @@ static void pas16_pit_out(uint16_t port, uint8_t val, void *p) pas16->pit.ctrls[t] = pas16->pit.ctrl = val; if (t == 3) { - pclog("PAS16: bad PIT reg select\n"); + DEBUG("PAS16: bad PIT reg select\n"); return; } if (!(pas16->pit.ctrl & 0x30)) @@ -662,7 +669,7 @@ static void pas16_pcm_poll(void *p) pas16->irq_stat |= PAS16_INT_PCM; if (pas16->irq_ena & PAS16_INT_PCM) { - pclog("pas16_pcm_poll : cause IRQ %i %02X\n", pas16->irq, 1 << pas16->irq); + DEBUG("pas16_pcm_poll : cause IRQ %i %02X\n", pas16->irq, 1 << pas16->irq); picint(1 << pas16->irq); } } @@ -693,7 +700,7 @@ static void pas16_out_base(uint16_t port, uint8_t val, void *p) io_removehandler((pas16->base - 0x388) + 0xff88, 0x0004, pas16_in, NULL, NULL, pas16_out, NULL, NULL, pas16); pas16->base = val << 2; - pclog("pas16_write_base : PAS16 base now at %04X\n", pas16->base); + DEBUG("pas16_write_base : PAS16 base now at %04X\n", pas16->base); io_sethandler((pas16->base - 0x388) + 0x0388, 0x0004, pas16_in, NULL, NULL, pas16_out, NULL, NULL, pas16); io_sethandler((pas16->base - 0x388) + 0x0788, 0x0004, pas16_in, NULL, NULL, pas16_out, NULL, NULL, pas16); @@ -759,7 +766,7 @@ void pas16_get_buffer(int32_t *buffer, int len, void *p) static void *pas16_init(const device_t *info) { - pas16_t *pas16 = malloc(sizeof(pas16_t)); + pas16_t *pas16 = (pas16_t *)mem_alloc(sizeof(pas16_t)); memset(pas16, 0, sizeof(pas16_t)); opl3_init(&pas16->opl); diff --git a/src/devices/sound/snd_resid.cpp b/src/devices/sound/snd_resid.cpp index 084b628..940ef3e 100644 --- a/src/devices/sound/snd_resid.cpp +++ b/src/devices/sound/snd_resid.cpp @@ -8,7 +8,7 @@ * * Interface to the ReSid library. * - * Version: @(#)snd_resid.cpp 1.0.4 2018/05/06 + * Version: @(#)snd_resid.cpp 1.0.5 2018/09/15 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -41,6 +41,8 @@ #include #include #include "resid-fp/sid.h" +#define dbglog sound_log +#include "../../emu.h" #include "../../plat.h" #include "sound.h" #include "snd_resid.h" @@ -93,7 +95,7 @@ sid_init(void) method, (float)48000, 0.9*48000.0/2.0)) { - snddev_log("ReSID set_sampling_parameters() failed!\n"); + DEBUG("ReSID set_sampling_parameters() failed!\n"); } dev->sid->set_chip_model(MOS6581FP); diff --git a/src/devices/sound/snd_sb.c b/src/devices/sound/snd_sb.c index fc6f23b..d9665e7 100644 --- a/src/devices/sound/snd_sb.c +++ b/src/devices/sound/snd_sb.c @@ -8,7 +8,7 @@ * * Sound Blaster emulation. * - * Version: @(#)sound_sb.c 1.0.6 2018/05/06 + * Version: @(#)snd_sb.c 1.0.7 2018/09/25 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -42,6 +42,7 @@ #include #include #include +#define dbglog sound_dev_log #include "../../emu.h" #include "../../io.h" #include "../../mem.h" @@ -57,6 +58,10 @@ #include "snd_sb.h" #include "snd_sb_dsp.h" + +#define ROM_PATH_AWE32 L"sound/creative/awe32.raw" + + //#define SB_DSP_RECORD_DEBUG #ifdef SB_DSP_RECORD_DEBUG @@ -65,7 +70,6 @@ FILE* soundfsbin = 0/*NULL*/; #endif - /* SB 2.0 CD version */ typedef struct sb_ct1335_mixer_t { @@ -152,8 +156,11 @@ typedef struct sb_t sb_ct1345_mixer_t mixer_sbpro; sb_ct1745_mixer_t mixer_sb16; }; - mpu_t mpu; + mpu_t *mpu; emu8k_t emu8k; +#if 0 + sb_ct1745_mixer_t temp_mixer_sb16; +#endif int pos; @@ -164,8 +171,8 @@ typedef struct sb_t /* 0 to 7 -> -14dB to 0dB i 2dB steps. 8 to 15 -> 0 to +14dB in 2dB steps. Note that for positive dB values, this is not amplitude, it is amplitude-1. */ const float sb_bass_treble_4bits[]= { - 0.199526231f, 0.25f, 0.316227766f, 0.398107170f, 0.5f, 0.63095734f, 0.794328234f, 1.0f, - 0, 0.25892541f, 0.584893192f, 1.0f, 1.511886431f, 2.16227766f, 3.0f, 4.011872336f + (float)0.199526231, (float)0.25, (float)0.316227766, (float)0.398107170, (float)0.5, (float)0.63095734, (float)0.794328234, (float)1, + (float)0, (float)0.25892541, (float)0.584893192, (float)1, (float)1.511886431, (float)2.16227766, (float)3, (float)4.011872336 }; /* Attenuation tables for the mixer. Max volume = 32767 in order to give 6dB of @@ -185,6 +192,7 @@ const int32_t sb_att_7dbstep_2bits[]= 164,6537,14637,32767 }; + /* sb 1, 1.5, 2, 2 mvc do not have a mixer, so signal is hardwired */ static void sb_get_buffer_sb2(int32_t *buffer, int len, void *p) { @@ -292,19 +300,21 @@ static void sb_get_buffer_sbpro(int32_t *buffer, int len, void *p) sb->dsp.pos = 0; } +// FIXME: See why this causes weird audio glitches in some situations. +#if 0 static void sb_process_buffer_sb16(int32_t *buffer, int len, void *p) { sb_t *sb = (sb_t *)p; - sb_ct1745_mixer_t *mixer = &sb->mixer_sb16; - + sb_ct1745_mixer_t *mixer = &sb->temp_mixer_sb16; + int c; for (c = 0; c < len * 2; c += 2) { int32_t out_l = 0, out_r = 0; - - out_l = ((int32_t)(buffer[c] * mixer->cd_l) / 3) >> 15; - out_r = ((int32_t)(buffer[c + 1] * mixer->cd_r) / 3) >> 15; + + out_l = ((int32_t)(low_fir_sb16(0, (float)buffer[c]) * mixer->cd_l) / 3) >> 15; + out_r = ((int32_t)(low_fir_sb16(1, (float)buffer[c + 1]) * mixer->cd_r) / 3) >> 15; out_l = (out_l * mixer->master_l) >> 15; out_r = (out_r * mixer->master_r) >> 15; @@ -326,6 +336,7 @@ static void sb_process_buffer_sb16(int32_t *buffer, int len, void *p) buffer[c + 1] = (out_r << mixer->output_gain_R); } } +#endif static void sb_get_buffer_sb16(int32_t *buffer, int len, void *p) { @@ -347,9 +358,10 @@ static void sb_get_buffer_sb16(int32_t *buffer, int len, void *p) out_r = ((((sb->opl.buffer[c + 1] * mixer->fm_r) >> 16) * (sb->opl_emu ? 47000 : 51000)) >> 15); } + /*TODO: multi-recording mic with agc/+20db, cd and line in with channel inversion */ in_l = (mixer->input_selector_left&INPUT_MIDI_L) ? out_l : 0 + (mixer->input_selector_left&INPUT_MIDI_R) ? out_r : 0; in_r = (mixer->input_selector_right&INPUT_MIDI_L) ? out_l : 0 + (mixer->input_selector_right&INPUT_MIDI_R) ? out_r : 0; - + out_l += ((int32_t)(low_fir_sb16(0, (float)sb->dsp.buffer[c]) * mixer->voice_l) / 3) >> 15; out_r += ((int32_t)(low_fir_sb16(1, (float)sb->dsp.buffer[c + 1]) * mixer->voice_r) / 3) >> 15; @@ -397,6 +409,9 @@ static void sb_get_buffer_sb16(int32_t *buffer, int len, void *p) sb->pos = 0; sb->opl.pos = 0; sb->dsp.pos = 0; +#if 0 + memcpy(&sb->temp_mixer_sb16, &sb->mixer_sb16, sizeof(sb_ct1745_mixer_t)); +#endif } #ifdef SB_DSP_RECORD_DEBUG int old_dsp_rec_pos=0; @@ -431,7 +446,7 @@ static void sb_get_buffer_emu8k(int32_t *buffer, int len, void *p) /*TODO: multi-recording mic with agc/+20db, cd and line in with channel inversion */ in_l = (mixer->input_selector_left&INPUT_MIDI_L) ? out_l : 0 + (mixer->input_selector_left&INPUT_MIDI_R) ? out_r : 0; in_r = (mixer->input_selector_right&INPUT_MIDI_L) ? out_l : 0 + (mixer->input_selector_right&INPUT_MIDI_R) ? out_r : 0; - + out_l += ((int32_t)(low_fir_sb16(0, (float)sb->dsp.buffer[c]) * mixer->voice_l) / 3) >> 15; out_r += ((int32_t)(low_fir_sb16(1, (float)sb->dsp.buffer[c + 1]) * mixer->voice_r) / 3) >> 15; @@ -507,6 +522,9 @@ static void sb_get_buffer_emu8k(int32_t *buffer, int len, void *p) sb->opl.pos = 0; sb->dsp.pos = 0; sb->emu8k.pos = 0; +#if 0 + memcpy(&sb->temp_mixer_sb16, &sb->mixer_sb16, sizeof(sb_ct1745_mixer_t)); +#endif } @@ -540,7 +558,7 @@ void sb_ct1335_mixer_write(uint16_t addr, uint8_t val, void *p) break; default: - /* pclog("sb_ct1335: Unknown register WRITE: %02X\t%02X\n", mixer->index, mixer->regs[mixer->index]); */ + DEBUG("sb_ct1335: Unknown register WRITE: %02X\t%02X\n", mixer->index, mixer->regs[mixer->index]); break; } } @@ -567,7 +585,7 @@ uint8_t sb_ct1335_mixer_read(uint16_t addr, void *p) case 0x00: case 0x02: case 0x06: case 0x08: case 0x0A: return mixer->regs[mixer->index]; default: - /* pclog("sb_ct1335: Unknown register READ: %02X\t%02X\n", mixer->index, mixer->regs[mixer->index]); */ + DEBUG("sb_ct1335: Unknown register READ: %02X\t%02X\n", mixer->index, mixer->regs[mixer->index]); break; } @@ -631,7 +649,7 @@ void sb_ct1345_mixer_write(uint16_t addr, uint8_t val, void *p) default: - /* pclog("sb_ct1345: Unknown register WRITE: %02X\t%02X\n", mixer->index, mixer->regs[mixer->index]); */ + DEBUG("sb_ct1345: Unknown register WRITE: %02X\t%02X\n", mixer->index, mixer->regs[mixer->index]); break; } } @@ -691,7 +709,7 @@ uint8_t sb_ct1345_mixer_read(uint16_t addr, void *p) return mixer->regs[mixer->index]; default: - /* pclog("sb_ct1345: Unknown register READ: %02X\t%02X\n", mixer->index, mixer->regs[mixer->index]); */ + DEBUG("sb_ct1345: Unknown register READ: %02X\t%02X\n", mixer->index, mixer->regs[mixer->index]); break; } @@ -838,7 +856,7 @@ void sb_ct1745_mixer_write(uint16_t addr, uint8_t val, void *p) /*TODO: pcspeaker volume, with "output_selector" check? or better not? */ sound_cd_set_volume(((uint32_t)mixer->master_l * (uint32_t)mixer->cd_l) / 65535, ((uint32_t)mixer->master_r * (uint32_t)mixer->cd_r) / 65535); -// pclog("sb_ct1745: Received register WRITE: %02X\t%02X\n", mixer->index, mixer->regs[mixer->index]); + DEBUG("sb_ct1745: Received register WRITE: %02X\t%02X\n", mixer->index, mixer->regs[mixer->index]); } } @@ -846,11 +864,12 @@ uint8_t sb_ct1745_mixer_read(uint16_t addr, void *p) { sb_t *sb = (sb_t *)p; sb_ct1745_mixer_t *mixer = &sb->mixer_sb16; + uint8_t temp; if (!(addr & 1)) return mixer->index; -// pclog("sb_ct1745: received register READ: %02X\t%02X\n", mixer->index, mixer->regs[mixer->index]); + DEBUG("sb_ct1745: received register READ: %02X\t%02X\n", mixer->index, mixer->regs[mixer->index]); if (mixer->index>=0x30 && mixer->index<=0x47) { @@ -926,13 +945,16 @@ uint8_t sb_ct1745_mixer_read(uint16_t addr, void *p) case 0x82: /* 0 = none, 1 = digital 8bit or SBMIDI, 2 = digital 16bit, 4 = MPU-401 */ /* 0x02000 DSP v4.04, 0x4000 DSP v4.05 0x8000 DSP v4.12. I haven't seen this making any difference, but I'm keeping it for now. */ - return ((sb->dsp.sb_irq8) ? 1 : 0) | ((sb->dsp.sb_irq16) ? 2 : 0) | 0x4000; + temp = ((sb->dsp.sb_irq8) ? 1 : 0) | ((sb->dsp.sb_irq16) ? 2 : 0) | 0x4000; + if (sb->mpu) + temp |= ((sb->mpu->state.irq_pending) ? 4 : 0); + return temp; /* TODO: creative drivers read and write on 0xFE and 0xFF. not sure what they are supposed to be. */ default: - /* pclog("sb_ct1745: Unknown register READ: %02X\t%02X\n", mixer->index, mixer->regs[mixer->index]); */ + DEBUG("sb_ct1745: Unknown register READ: %02X\t%02X\n", mixer->index, mixer->regs[mixer->index]); break; } @@ -952,8 +974,8 @@ uint8_t sb_mcv_read(int port, void *p) { sb_t *sb = (sb_t *)p; - /* pclog("sb_mcv_read: port=%04x\n", port); */ - + DEBUG("sb_mcv_read: port=%04x\n", port); + return sb->pos_regs[port & 7]; } @@ -965,7 +987,7 @@ void sb_mcv_write(int port, uint8_t val, void *p) if (port < 0x102) return; - /* pclog("sb_mcv_write: port=%04x val=%02x\n", port, val); */ + DEBUG("sb_mcv_write: port=%04x val=%02x\n", port, val); addr = sb_mcv_addr[sb->pos_regs[4] & 7]; if (sb->opl_enabled) { @@ -996,8 +1018,8 @@ uint8_t sb_pro_mcv_read(int port, void *p) { sb_t *sb = (sb_t *)p; - /* pclog("sb_pro_mcv_read: port=%04x\n", port); */ - + DEBUG("sb_pro_mcv_read: port=%04x\n", port); + return sb->pos_regs[port & 7]; } @@ -1009,7 +1031,7 @@ void sb_pro_mcv_write(int port, uint8_t val, void *p) if (port < 0x102) return; - /* pclog("sb_pro_mcv_write: port=%04x val=%02x\n", port, val); */ + DEBUG("sb_pro_mcv_write: port=%04x val=%02x\n", port, val); addr = (sb->pos_regs[2] & 0x20) ? 0x220 : 0x240; io_removehandler(addr+0, 0x0004, opl3_read, NULL, NULL, opl3_write, NULL, NULL, &sb->opl); @@ -1042,7 +1064,7 @@ void *sb_1_init(const device_t *info) 2x0 to 2x3 -> CMS chip 2x6, 2xA, 2xC, 2xE -> DSP chip 2x8, 2x9, 388 and 389 FM chip*/ - sb_t *sb = malloc(sizeof(sb_t)); + sb_t *sb = (sb_t *)mem_alloc(sizeof(sb_t)); uint16_t addr = device_get_config_hex16("base"); memset(sb, 0, sizeof(sb_t)); @@ -1053,7 +1075,6 @@ void *sb_1_init(const device_t *info) sb_dsp_setaddr(&sb->dsp, addr); sb_dsp_setirq(&sb->dsp, device_get_config_int("irq")); sb_dsp_setdma8(&sb->dsp, device_get_config_int("dma")); - sb_dsp_set_mpu(&sb->mpu); /* CMS I/O handler is activated on the dedicated sound_cms module DSP I/O handler is activated in sb_dsp_setaddr */ if (sb->opl_enabled) { @@ -1069,7 +1090,7 @@ void *sb_15_init(const device_t *info) 2x0 to 2x3 -> CMS chip 2x6, 2xA, 2xC, 2xE -> DSP chip 2x8, 2x9, 388 and 389 FM chip*/ - sb_t *sb = malloc(sizeof(sb_t)); + sb_t *sb = (sb_t *)mem_alloc(sizeof(sb_t)); uint16_t addr = device_get_config_hex16("base"); memset(sb, 0, sizeof(sb_t)); @@ -1095,7 +1116,7 @@ void *sb_mcv_init(const device_t *info) /*sb1/2 port mappings, 210h to 260h in 10h steps 2x6, 2xA, 2xC, 2xE -> DSP chip 2x8, 2x9, 388 and 389 FM chip*/ - sb_t *sb = malloc(sizeof(sb_t)); + sb_t *sb = (sb_t *)mem_alloc(sizeof(sb_t)); memset(sb, 0, sizeof(sb_t)); sb->opl_enabled = device_get_config_int("opl"); @@ -1105,7 +1126,6 @@ void *sb_mcv_init(const device_t *info) sb_dsp_setaddr(&sb->dsp, 0);//addr); sb_dsp_setirq(&sb->dsp, device_get_config_int("irq")); sb_dsp_setdma8(&sb->dsp, device_get_config_int("dma")); - sb_dsp_set_mpu(&sb->mpu); sound_add_handler(sb_get_buffer_sb2, sb); /* I/O handlers activated in sb_mcv_write */ mca_add(sb_mcv_read, sb_mcv_write, sb); @@ -1122,7 +1142,13 @@ void *sb_2_init(const device_t *info) "CD version" also uses 250h or 260h for 2x0 to 2x3 -> CDROM interface 2x4 to 2x5 -> Mixer interface*/ - sb_t *sb = malloc(sizeof(sb_t)); + /*My SB 2.0 mirrors the OPL2 at ports 2x0/2x1. Presumably this mirror is + disabled when the CMS chips are present. + This mirror may also exist on SB 1.5 & MCV, however I am unable to + test this. It shouldn't exist on SB 1.0 as the CMS chips are always + present there. + Syndicate requires this mirror for music to play.*/ + sb_t *sb = (sb_t *)mem_alloc(sizeof(sb_t)); uint16_t addr = device_get_config_hex16("base"); memset(sb, 0, sizeof(sb_t)); @@ -1133,11 +1159,14 @@ void *sb_2_init(const device_t *info) sb_dsp_setaddr(&sb->dsp, addr); sb_dsp_setirq(&sb->dsp, device_get_config_int("irq")); sb_dsp_setdma8(&sb->dsp, device_get_config_int("dma")); - sb_dsp_set_mpu(&sb->mpu); sb_ct1335_mixer_reset(sb); /* CMS I/O handler is activated on the dedicated sound_cms module DSP I/O handler is activated in sb_dsp_setaddr */ if (sb->opl_enabled) { +#if 0 + if (!GAMEBLASTER) +#endif + io_sethandler(addr, 0x0002, opl2_read, NULL, NULL, opl2_write, NULL, NULL, &sb->opl); io_sethandler(addr+8, 0x0002, opl2_read, NULL, NULL, opl2_write, NULL, NULL, &sb->opl); io_sethandler(0x0388, 0x0002, opl2_read, NULL, NULL, opl2_write, NULL, NULL, &sb->opl); } @@ -1162,7 +1191,7 @@ void *sb_pro_v1_init(const device_t *info) 2x6, 2xA, 2xC, 2xE -> DSP chip 2x8, 2x9, 388 and 389 FM chip (9 voices) 2x0+10 to 2x0+13 CDROM interface.*/ - sb_t *sb = malloc(sizeof(sb_t)); + sb_t *sb = (sb_t *)mem_alloc(sizeof(sb_t)); uint16_t addr = device_get_config_hex16("base"); memset(sb, 0, sizeof(sb_t)); @@ -1173,7 +1202,6 @@ void *sb_pro_v1_init(const device_t *info) sb_dsp_setaddr(&sb->dsp, addr); sb_dsp_setirq(&sb->dsp, device_get_config_int("irq")); sb_dsp_setdma8(&sb->dsp, device_get_config_int("dma")); - sb_dsp_set_mpu(&sb->mpu); sb_ct1345_mixer_reset(sb); /* DSP I/O handler is activated in sb_dsp_setaddr */ if (sb->opl_enabled) { @@ -1196,7 +1224,7 @@ void *sb_pro_v2_init(const device_t *info) 2x6, 2xA, 2xC, 2xE -> DSP chip 2x8, 2x9, 388 and 389 FM chip (9 voices) 2x0+10 to 2x0+13 CDROM interface.*/ - sb_t *sb = malloc(sizeof(sb_t)); + sb_t *sb = (sb_t *)mem_alloc(sizeof(sb_t)); uint16_t addr = device_get_config_hex16("base"); memset(sb, 0, sizeof(sb_t)); @@ -1207,7 +1235,6 @@ void *sb_pro_v2_init(const device_t *info) sb_dsp_setaddr(&sb->dsp, addr); sb_dsp_setirq(&sb->dsp, device_get_config_int("irq")); sb_dsp_setdma8(&sb->dsp, device_get_config_int("dma")); - sb_dsp_set_mpu(&sb->mpu); sb_ct1345_mixer_reset(sb); /* DSP I/O handler is activated in sb_dsp_setaddr */ if (sb->opl_enabled) { @@ -1228,7 +1255,7 @@ void *sb_pro_mcv_init(const device_t *info) 2x4 to 2x5 -> Mixer interface 2x6, 2xA, 2xC, 2xE -> DSP chip 2x8, 2x9, 388 and 389 FM chip (9 voices)*/ - sb_t *sb = malloc(sizeof(sb_t)); + sb_t *sb = (sb_t *)mem_alloc(sizeof(sb_t)); memset(sb, 0, sizeof(sb_t)); sb->opl_enabled = 1; @@ -1248,8 +1275,9 @@ void *sb_pro_mcv_init(const device_t *info) void *sb_16_init(const device_t *info) { - sb_t *sb = malloc(sizeof(sb_t)); + sb_t *sb = (sb_t *)mem_alloc(sizeof(sb_t)); uint16_t addr = device_get_config_hex16("base"); + uint16_t mpu_addr = device_get_config_hex16("base401"); memset(sb, 0, sizeof(sb_t)); sb->opl_enabled = device_get_config_int("opl"); @@ -1268,22 +1296,33 @@ void *sb_16_init(const device_t *info) } io_sethandler(addr+4, 0x0002, sb_ct1745_mixer_read, NULL, NULL, sb_ct1745_mixer_write, NULL, NULL, sb); sound_add_handler(sb_get_buffer_sb16, sb); +#if 0 sound_add_process_handler(sb_process_buffer_sb16, sb); - mpu401_init(&sb->mpu, device_get_config_hex16("base401"), device_get_config_int("irq401"), device_get_config_int("mode401")); - sb_dsp_set_mpu(&sb->mpu); +#endif + if (mpu_addr) { + sb->mpu = (mpu_t *)mem_alloc(sizeof(mpu_t)); + memset(sb->mpu, 0, sizeof(mpu_t)); + mpu401_init(sb->mpu, device_get_config_hex16("base401"), device_get_config_int("irq"), M_UART); + sb_dsp_set_mpu(sb->mpu); + } else + sb->mpu = NULL; +#if 0 + memcpy(&sb->temp_mixer_sb16, &sb->mixer_sb16, sizeof(sb_ct1745_mixer_t)); +#endif return sb; } int sb_awe32_available() { - return rom_present(L"sound/awe32.raw"); + return rom_present(ROM_PATH_AWE32); } void *sb_awe32_init(const device_t *info) { - sb_t *sb = malloc(sizeof(sb_t)); + sb_t *sb = (sb_t *)mem_alloc(sizeof(sb_t)); uint16_t addr = device_get_config_hex16("base"); + uint16_t mpu_addr = device_get_config_hex16("base401"); uint16_t emu_addr = device_get_config_hex16("emu_base"); int onboard_ram = device_get_config_int("onboard_ram"); memset(sb, 0, sizeof(sb_t)); @@ -1298,7 +1337,6 @@ void *sb_awe32_init(const device_t *info) sb_dsp_setirq(&sb->dsp, device_get_config_int("irq")); sb_dsp_setdma8(&sb->dsp, device_get_config_int("dma")); sb_dsp_setdma16(&sb->dsp, device_get_config_int("dma16")); - sb_dsp_set_mpu(&sb->mpu); sb_ct1745_mixer_reset(sb); if (sb->opl_enabled) { io_sethandler(addr, 0x0004, opl3_read, NULL, NULL, opl3_write, NULL, NULL, &sb->opl); @@ -1307,10 +1345,20 @@ void *sb_awe32_init(const device_t *info) } io_sethandler(addr+4, 0x0002, sb_ct1745_mixer_read, NULL, NULL, sb_ct1745_mixer_write, NULL, NULL, sb); sound_add_handler(sb_get_buffer_emu8k, sb); +#if 0 sound_add_process_handler(sb_process_buffer_sb16, sb); - mpu401_init(&sb->mpu, device_get_config_hex16("base401"), device_get_config_int("irq401"), device_get_config_int("mode401")); - sb_dsp_set_mpu(&sb->mpu); - emu8k_init(&sb->emu8k, emu_addr, onboard_ram); +#endif + if (mpu_addr) { + sb->mpu = (mpu_t *)mem_alloc(sizeof(mpu_t)); + memset(sb->mpu, 0, sizeof(mpu_t)); + mpu401_init(sb->mpu, device_get_config_hex16("base401"), device_get_config_int("irq"), M_UART); + sb_dsp_set_mpu(sb->mpu); + } else + sb->mpu = NULL; + emu8k_init(&sb->emu8k, ROM_PATH_AWE32, emu_addr, onboard_ram); +#if 0 + memcpy(&sb->temp_mixer_sb16, &sb->mixer_sb16, sizeof(sb_ct1745_mixer_t)); +#endif return sb; } @@ -1351,13 +1399,6 @@ void sb_speed_changed(void *p) sb_dsp_speed_changed(&sb->dsp); } -void sb_add_status_info(char *s, int max_len, void *p) -{ - sb_t *sb = (sb_t *)p; - - sb_dsp_add_status_info(s, max_len, &sb->dsp); -} - static const device_config_t sb_config[] = { { @@ -1540,6 +1581,9 @@ static const device_config_t sb_16_config[] = { "base401", "MPU-401 Address", CONFIG_HEX16, "", 0x330, { + { + "Disabled", 0 + }, { "0x300", 0x300 }, @@ -1571,32 +1615,6 @@ static const device_config_t sb_16_config[] = } } }, - { - "irq401", "MPU-401 IRQ", CONFIG_SELECTION, "", 9, - { - { - "IRQ 9", 9 - }, - { - "IRQ 3", 3 - }, - { - "IRQ 4", 4 - }, - { - "IRQ 5", 5 - }, - { - "IRQ 7", 7 - }, - { - "IRQ 10", 10 - }, - { - "" - } - } - }, { "dma", "Low DMA channel", CONFIG_SELECTION, "", 1, { @@ -1631,20 +1649,6 @@ static const device_config_t sb_16_config[] = } } }, - { - "mode401", "MPU-401 mode", CONFIG_SELECTION, "", 1, - { - { - "UART", M_UART - }, - { - "Intelligent", M_INTELLIGENT - }, - { - "" - } - } - }, { "opl", "Enable OPL", CONFIG_BINARY, "", 1 }, @@ -1698,6 +1702,9 @@ static const device_config_t sb_awe32_config[] = { "base401", "MPU-401 Address", CONFIG_HEX16, "", 0x330, { + { + "Disabled", 0 + }, { "0x300", 0x300 }, @@ -1729,32 +1736,6 @@ static const device_config_t sb_awe32_config[] = } } }, - { - "irq401", "MPU-401 IRQ", CONFIG_SELECTION, "", 9, - { - { - "IRQ 9", 9 - }, - { - "IRQ 3", 3 - }, - { - "IRQ 4", 4 - }, - { - "IRQ 5", 5 - }, - { - "IRQ 7", 7 - }, - { - "IRQ 10", 10 - }, - { - "" - } - } - }, { "dma", "Low DMA channel", CONFIG_SELECTION, "", 1, { @@ -1789,20 +1770,6 @@ static const device_config_t sb_awe32_config[] = } } }, - { - "mode401", "MPU-401 mode", CONFIG_SELECTION, "", 1, - { - { - "UART", M_UART - }, - { - "Intelligent", M_INTELLIGENT - }, - { - "" - } - } - }, { "onboard_ram", "Onboard RAM", CONFIG_SELECTION, "", 512, { @@ -1839,10 +1806,11 @@ const device_t sb_1_device = "Sound Blaster v1.0", DEVICE_ISA, 0, - sb_1_init, sb_close, NULL, NULL, + sb_1_init, sb_close, NULL, + NULL, sb_speed_changed, NULL, - sb_add_status_info, + NULL, sb_config }; const device_t sb_15_device = @@ -1850,10 +1818,11 @@ const device_t sb_15_device = "Sound Blaster v1.5", DEVICE_ISA, 0, - sb_15_init, sb_close, NULL, NULL, + sb_15_init, sb_close, NULL, + NULL, sb_speed_changed, NULL, - sb_add_status_info, + NULL, sb_config }; const device_t sb_mcv_device = @@ -1861,10 +1830,11 @@ const device_t sb_mcv_device = "Sound Blaster MCV", DEVICE_MCA, 0, - sb_mcv_init, sb_close, NULL, NULL, + sb_mcv_init, sb_close, NULL, + NULL, sb_speed_changed, NULL, - sb_add_status_info, + NULL, sb_mcv_config }; const device_t sb_2_device = @@ -1872,21 +1842,23 @@ const device_t sb_2_device = "Sound Blaster v2.0", DEVICE_ISA, 0, - sb_2_init, sb_close, NULL, NULL, + sb_2_init, sb_close, NULL, + NULL, sb_speed_changed, + NULL, NULL, - sb_add_status_info, sb_config }; const device_t sb_pro_v1_device = { - "Sound Blaster Pro v1", + "Sound Blaster Pro", DEVICE_ISA, 0, - sb_pro_v1_init, sb_close, NULL, NULL, + sb_pro_v1_init, sb_close, NULL, + NULL, sb_speed_changed, NULL, - sb_add_status_info, + NULL, sb_pro_config }; const device_t sb_pro_v2_device = @@ -1894,10 +1866,11 @@ const device_t sb_pro_v2_device = "Sound Blaster Pro v2", DEVICE_ISA, 0, - sb_pro_v2_init, sb_close, NULL, NULL, + sb_pro_v2_init, sb_close, NULL, + NULL, sb_speed_changed, NULL, - sb_add_status_info, + NULL, sb_pro_config }; const device_t sb_pro_mcv_device = @@ -1905,10 +1878,11 @@ const device_t sb_pro_mcv_device = "Sound Blaster Pro MCV", DEVICE_MCA, 0, - sb_pro_mcv_init, sb_close, NULL, NULL, + sb_pro_mcv_init, sb_close, NULL, + NULL, sb_speed_changed, NULL, - sb_add_status_info, + NULL, NULL }; const device_t sb_16_device = @@ -1916,10 +1890,11 @@ const device_t sb_16_device = "Sound Blaster 16", DEVICE_ISA, 0, - sb_16_init, sb_close, NULL, NULL, + sb_16_init, sb_close, NULL, + NULL, sb_speed_changed, NULL, - sb_add_status_info, + NULL, sb_16_config }; const device_t sb_awe32_device = @@ -1931,6 +1906,6 @@ const device_t sb_awe32_device = sb_awe32_available, sb_speed_changed, NULL, - sb_add_status_info, + NULL, sb_awe32_config }; diff --git a/src/devices/sound/snd_sb_dsp.c b/src/devices/sound/snd_sb_dsp.c index 6f52946..1108fc7 100644 --- a/src/devices/sound/snd_sb_dsp.c +++ b/src/devices/sound/snd_sb_dsp.c @@ -14,7 +14,7 @@ * 486-50 - 32kHz * Pentium - 45kHz * - * Version: @(#)snd_sb_dsp.c 1.0.6 2018/05/06 + * Version: @(#)snd_sb_dsp.c 1.0.7 2018/09/25 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -48,6 +48,7 @@ #include #include #include +#define dbglog sound_dev_log #include "../../emu.h" #include "../../io.h" #include "../../timer.h" @@ -61,24 +62,16 @@ #include "snd_sb.h" #include "snd_sb_dsp.h" + /*The recording safety margin is intended for uneven "len" calls to the get_buffer mixer calls on sound_sb*/ #define SB_DSP_REC_SAFEFTY_MARGIN 4096 -void pollsb(void *p); -void sb_poll_i(void *p); -//#define SB_DSP_RECORD_DEBUG -//#define SB_TEST_RECORDING_SAW +extern void pollsb(void *p); +extern void sb_poll_i(void *p); -#ifdef SB_DSP_RECORD_DEBUG -FILE* soundf = 0/*NULL*/; -#endif -#ifdef SB_TEST_RECORDING_SAW -int counttest; -#endif - -static int sbe2dat[4][9] = { +static const int sbe2dat[4][9] = { { 0x01, -0x02, -0x04, 0x08, -0x10, 0x20, 0x40, -0x80, -106 }, { -0x01, 0x02, -0x04, 0x08, 0x10, -0x20, 0x40, -0x80, 165 }, { -0x01, 0x02, 0x04, -0x08, 0x10, -0x20, -0x40, 0x80, -151 }, @@ -107,17 +100,17 @@ static int sb_commands[256]= -1,-1, 0,-1,-1,-1,-1,-1,-1, 1, 2,-1,-1,-1,-1, 0 }; -char sb16_copyright[] = "COPYRIGHT (C) CREATIVE TECHNOLOGY LTD, 1992."; -uint16_t sb_dsp_versions[] = {0, 0, 0x105, 0x200, 0x201, 0x300, 0x302, 0x405, 0x40d}; +const char sb16_copyright[] = "COPYRIGHT (C) CREATIVE TECHNOLOGY LTD, 1992."; +const uint16_t sb_dsp_versions[] = {0, 0, 0x105, 0x200, 0x201, 0x300, 0x302, 0x405, 0x40d}; /*These tables were 'borrowed' from DOSBox*/ - int8_t scaleMap4[64] = { + const int8_t scaleMap4[64] = { 0, 1, 2, 3, 4, 5, 6, 7, 0, -1, -2, -3, -4, -5, -6, -7, 1, 3, 5, 7, 9, 11, 13, 15, -1, -3, -5, -7, -9, -11, -13, -15, 2, 6, 10, 14, 18, 22, 26, 30, -2, -6, -10, -14, -18, -22, -26, -30, 4, 12, 20, 28, 36, 44, 52, 60, -4, -12, -20, -28, -36, -44, -52, -60 }; - uint8_t adjustMap4[64] = { + const uint8_t adjustMap4[64] = { 0, 0, 0, 0, 0, 16, 16, 16, 0, 0, 0, 0, 0, 16, 16, 16, 240, 0, 0, 0, 0, 16, 16, 16, @@ -128,14 +121,14 @@ uint16_t sb_dsp_versions[] = {0, 0, 0x105, 0x200, 0x201, 0x300, 0x302, 0x405, 0x 240, 0, 0, 0, 0, 0, 0, 0 }; - int8_t scaleMap26[40] = { + const int8_t scaleMap26[40] = { 0, 1, 2, 3, 0, -1, -2, -3, 1, 3, 5, 7, -1, -3, -5, -7, 2, 6, 10, 14, -2, -6, -10, -14, 4, 12, 20, 28, -4, -12, -20, -28, 5, 15, 25, 35, -5, -15, -25, -35 }; - uint8_t adjustMap26[40] = { + const uint8_t adjustMap26[40] = { 0, 0, 0, 8, 0, 0, 0, 8, 248, 0, 0, 8, 248, 0, 0, 8, 248, 0, 0, 8, 248, 0, 0, 8, @@ -143,12 +136,12 @@ uint16_t sb_dsp_versions[] = {0, 0, 0x105, 0x200, 0x201, 0x300, 0x302, 0x405, 0x 248, 0, 0, 0, 248, 0, 0, 0 }; - int8_t scaleMap2[24] = { + const int8_t scaleMap2[24] = { 0, 1, 0, -1, 1, 3, -1, -3, 2, 6, -2, -6, 4, 12, -4, -12, 8, 24, -8, -24, 6, 48, -16, -48 }; - uint8_t adjustMap2[24] = { + const uint8_t adjustMap2[24] = { 0, 4, 0, 4, 252, 4, 252, 4, 252, 4, 252, 4, 252, 4, 252, 4, 252, 4, 252, 4, @@ -157,6 +150,7 @@ uint16_t sb_dsp_versions[] = {0, 0, 0x105, 0x200, 0x201, 0x300, 0x302, 0x405, 0x float low_fir_sb16_coef[SB16_NCoef]; + static inline double sinc(double x) { return sin(M_PI * x) / (M_PI * x); @@ -165,7 +159,7 @@ static inline double sinc(double x) static void recalc_sb16_filter(int playback_freq) { /*Cutoff frequency = playback / 2*/ - float fC = (float) (((float)playback_freq / 2.0) / 48000.0); + float fC = (float)((float)playback_freq / (float)2.0) / (float)48000.0; float gain; int n; @@ -191,9 +185,10 @@ static void recalc_sb16_filter(int playback_freq) low_fir_sb16_coef[n] /= gain; } + void sb_irq(sb_dsp_t *dsp, int irq8) { -// pclog("IRQ %i %02X\n",irq8,pic.mask); + DBGLOG(1, "IRQ %i %02X\n",irq8,pic.mask); if (irq8) dsp->sb_irq8 = 1; else dsp->sb_irq16 = 1; picint(1 << dsp->sb_irqnum); @@ -232,14 +227,6 @@ void sb_dsp_reset(sb_dsp_t *dsp) picintc(1 << dsp->sb_irqnum); dsp->asp_data_len = 0; - - #ifdef SB_DSP_RECORD_DEBUG - if (soundf != 0) - { - fclose(soundf); - soundf=0; - } - #endif } void sb_doreset(sb_dsp_t *dsp) @@ -297,7 +284,6 @@ void sb_start_dma(sb_dsp_t *dsp, int dma8, int autoinit, uint8_t format, int len timer_update_outstanding(); dsp->sbleftright = 0; dsp->sbdacpos = 0; -// pclog("Start 8-bit DMA addr %06X len %04X\n",dma.ac[1]+(dma.page[1]<<16),len); } else { @@ -311,7 +297,6 @@ void sb_start_dma(sb_dsp_t *dsp, int dma8, int autoinit, uint8_t format, int len timer_process(); dsp->sbenable = dsp->sb_16_enable; timer_update_outstanding(); -// pclog("Start 16-bit DMA addr %06X len %04X\n",dma16.ac[1]+(dma16.page[1]<<16),len); } } @@ -319,13 +304,6 @@ void sb_start_dma_i(sb_dsp_t *dsp, int dma8, int autoinit, uint8_t format, int l { if (dma8) { -#ifdef SB_TEST_RECORDING_SAW - switch (dsp->sb_8_format) - { - case 00:case 20:counttest=0x80;break; - case 10:case 30:counttest=0;break; - } -#endif dsp->sb_8_length = len; dsp->sb_8_format = format; dsp->sb_8_autoinit = autoinit; @@ -336,17 +314,9 @@ void sb_start_dma_i(sb_dsp_t *dsp, int dma8, int autoinit, uint8_t format, int l timer_process(); dsp->sb_enable_i = dsp->sb_8_enable; timer_update_outstanding(); -// pclog("Start 8-bit input DMA addr %06X len %04X\n",dma.ac[1]+(dma.page[1]<<16),len); } else { -#ifdef SB_TEST_RECORDING_SAW - switch (dsp->sb_16_format) - { - case 00:case 20:counttest=0x8000;break; - case 10:case 30:counttest=0;break; - } -#endif dsp->sb_16_length = len; dsp->sb_16_format = format; dsp->sb_16_autoinit = autoinit; @@ -357,18 +327,8 @@ void sb_start_dma_i(sb_dsp_t *dsp, int dma8, int autoinit, uint8_t format, int l timer_process(); dsp->sb_enable_i = dsp->sb_16_enable; timer_update_outstanding(); -// pclog("Start 16-bit input DMA addr %06X len %04X\n",dma.ac[1]+(dma.page[1]<<16),len); } memset(dsp->record_buffer,0,sizeof(dsp->record_buffer)); - - #ifdef SB_DSP_RECORD_DEBUG - if (soundf != 0) - { - fclose(soundf); - soundf=0; - } - #endif - } int sb_8_read_dma(sb_dsp_t *dsp) @@ -378,43 +338,35 @@ int sb_8_read_dma(sb_dsp_t *dsp) void sb_8_write_dma(sb_dsp_t *dsp, uint8_t val) { dma_channel_write(dsp->sb_8_dmanum, val); -#ifdef SB_DSP_RECORD_DEBUG - if (!soundf) soundf=fopen("sound_dsp.pcm","wb"); - fwrite(&val,1,1,soundf); -#endif } -uint16_t sb_16_read_dma(sb_dsp_t *dsp) +int sb_16_read_dma(sb_dsp_t *dsp) { return dma_channel_read(dsp->sb_16_dmanum); } int sb_16_write_dma(sb_dsp_t *dsp, uint16_t val) { int ret = dma_channel_write(dsp->sb_16_dmanum, val); -#ifdef SB_DSP_RECORD_DEBUG - if (!soundf) soundf=fopen("sound_dsp.pcm","wb"); - fwrite(&val,2,1,soundf); -#endif return (ret == DMA_NODATA); } -void sb_dsp_setirq(sb_dsp_t *dsp, int irq_ch) +void sb_dsp_setirq(sb_dsp_t *dsp, int irq) { - dsp->sb_irqnum = irq_ch; + dsp->sb_irqnum = irq; } -void sb_dsp_setdma8(sb_dsp_t *dsp, int dma_ch) +void sb_dsp_setdma8(sb_dsp_t *dsp, int dma) { - dsp->sb_8_dmanum = dma_ch; + dsp->sb_8_dmanum = dma; } -void sb_dsp_setdma16(sb_dsp_t *dsp, int dma_ch) +void sb_dsp_setdma16(sb_dsp_t *dsp, int dma) { - dsp->sb_16_dmanum = dma_ch; + dsp->sb_16_dmanum = dma; } void sb_exec_command(sb_dsp_t *dsp) { int temp,c; -// pclog("sb_exec_command : SB command %02X\n", dsp->sb_command); + DBGLOG(1, "sb_exec_command : SB command %02X\n", dsp->sb_command); switch (dsp->sb_command) { case 0x01: /*???*/ @@ -434,7 +386,6 @@ void sb_exec_command(sb_dsp_t *dsp) case 0x17: /*2-bit ADPCM output with reference*/ dsp->sbref = sb_8_read_dma(dsp); dsp->sbstep = 0; -// pclog("Ref byte 2 %02X\n",sbref); case 0x16: /*2-bit ADPCM output*/ sb_start_dma(dsp, 1, 0, ADPCM_2, dsp->sb_data[0] + (dsp->sb_data[1] << 8)); dsp->sbdat2 = sb_8_read_dma(dsp); @@ -496,7 +447,7 @@ void sb_exec_command(sb_dsp_t *dsp) dsp->sblatcho = dsp->sblatchi = TIMER_USEC * (256 - dsp->sb_data[0]); temp = 256 - dsp->sb_data[0]; temp = 1000000 / temp; -// pclog("Sample rate - %ihz (%i)\n",temp, dsp->sblatcho); + DBGLOG(1, "Sample rate - %ihz (%i)\n",temp, dsp->sblatcho); if (dsp->sb_freq != temp && dsp->sb_type >= SB16) recalc_sb16_filter(temp); dsp->sb_freq = temp; @@ -505,7 +456,7 @@ void sb_exec_command(sb_dsp_t *dsp) case 0x42: /*Set input sampling rate*/ if (dsp->sb_type < SB16) break; dsp->sblatcho = (int)(TIMER_USEC * (1000000.0f / (float)(dsp->sb_data[1] + (dsp->sb_data[0] << 8)))); -// pclog("Sample rate - %ihz (%i)\n",dsp->sb_data[1]+(dsp->sb_data[0]<<8), dsp->sblatcho); + DBGLOG(1, "Sample rate - %ihz (%i)\n",dsp->sb_data[1]+(dsp->sb_data[0]<<8), dsp->sblatcho); temp = dsp->sb_freq; dsp->sb_freq = dsp->sb_data[1] + (dsp->sb_data[0] << 8); dsp->sb_timeo = 256LL + dsp->sb_freq; @@ -520,7 +471,6 @@ void sb_exec_command(sb_dsp_t *dsp) case 0x75: /*4-bit ADPCM output with reference*/ dsp->sbref = sb_8_read_dma(dsp); dsp->sbstep = 0; -// pclog("Ref byte 4 %02X\n",sbref); case 0x74: /*4-bit ADPCM output*/ sb_start_dma(dsp, 1, 0, ADPCM_4, dsp->sb_data[0] + (dsp->sb_data[1] << 8)); dsp->sbdat2 = sb_8_read_dma(dsp); @@ -531,7 +481,6 @@ void sb_exec_command(sb_dsp_t *dsp) case 0x77: /*2.6-bit ADPCM output with reference*/ dsp->sbref = sb_8_read_dma(dsp); dsp->sbstep = 0; -// pclog("Ref byte 26 %02X\n",sbref); case 0x76: /*2.6-bit ADPCM output*/ sb_start_dma(dsp, 1, 0, ADPCM_26, dsp->sb_data[0] + (dsp->sb_data[1] << 8)); dsp->sbdat2 = sb_8_read_dma(dsp); @@ -553,31 +502,30 @@ void sb_exec_command(sb_dsp_t *dsp) break; case 0x80: /*Pause DAC*/ dsp->sb_pausetime = dsp->sb_data[0] + (dsp->sb_data[1] << 8); -// pclog("SB pause %04X\n",sb_pausetime); timer_process(); dsp->sbenable = 1; timer_update_outstanding(); break; case 0x90: /*High speed 8-bit autoinit DMA output*/ - if (dsp->sb_type < SB2 || dsp->sb_type > SBPRO2) break; + if (dsp->sb_type < SB2) break; sb_start_dma(dsp, 1, 1, 0, dsp->sb_8_autolen); break; case 0x91: /*High speed 8-bit single cycle DMA output*/ - if (dsp->sb_type < SB2 || dsp->sb_type > SBPRO2) break; + if (dsp->sb_type < SB2) break; sb_start_dma(dsp, 1, 0, 0, dsp->sb_8_autolen); break; case 0x98: /*High speed 8-bit autoinit DMA input*/ - if (dsp->sb_type < SB2 || dsp->sb_type > SBPRO2) break; + if (dsp->sb_type < SB2) break; sb_start_dma_i(dsp, 1, 1, 0, dsp->sb_8_autolen); break; case 0x99: /*High speed 8-bit single cycle DMA input*/ - if (dsp->sb_type < SB2 || dsp->sb_type > SBPRO2) break; + if (dsp->sb_type < SB2) break; sb_start_dma_i(dsp, 1, 0, 0, dsp->sb_8_autolen); break; case 0xA0: /*Set input mode to mono*/ case 0xA8: /*Set input mode to stereo*/ if (dsp->sb_type < SB2 || dsp->sb_type > SBPRO2) break; - //TODO: Implement. 3.xx-only command. + /* TODO: Implement. 3.xx-only command. */ break; case 0xB0: case 0xB1: case 0xB2: case 0xB3: case 0xB4: case 0xB5: case 0xB6: case 0xB7: /*16-bit DMA output*/ @@ -669,11 +617,11 @@ void sb_exec_command(sb_dsp_t *dsp) sb_add_data(dsp, dsp->sb_test); break; case 0xF2: /*Trigger 8-bit IRQ*/ -// pclog("Trigger IRQ\n"); + DBGLOG(1, "Trigger IRQ\n"); sb_irq(dsp, 1); break; case 0xF3: /*Trigger 16-bit IRQ*/ -// pclog("Trigger IRQ\n"); + DBGLOG(1, "Trigger IRQ\n"); sb_irq(dsp, 0); break; case 0xE7: /*???*/ @@ -689,13 +637,10 @@ void sb_exec_command(sb_dsp_t *dsp) case 0x0E: /*ASP set register*/ if (dsp->sb_type < SB16) break; dsp->sb_asp_regs[dsp->sb_data[0]] = dsp->sb_data[1]; -// pclog("ASP write reg %02X %02X\n", sb_data[0], sb_data[1]); break; case 0x0F: /*ASP get register*/ if (dsp->sb_type < SB16) break; -// sb_add_data(0); sb_add_data(dsp, dsp->sb_asp_regs[dsp->sb_data[0]]); -// pclog("ASP read reg %02X %02X\n", sb_data[0], sb_asp_regs[sb_data[0]]); break; case 0xF8: if (dsp->sb_type >= SB16) break; @@ -710,10 +655,7 @@ void sb_exec_command(sb_dsp_t *dsp) case 0x04: case 0x05: break; -// default: -// fatal("Exec bad SB command %02X\n",sb_command); - - + /*TODO: Some more data about the DSP registeres * http://the.earth.li/~tfm/oldpage/sb_dsp.html * http://www.synchrondata.com/pheaven/www/area19.htm @@ -734,7 +676,6 @@ void sb_exec_command(sb_dsp_t *dsp) void sb_write(uint16_t a, uint8_t v, void *priv) { sb_dsp_t *dsp = (sb_dsp_t *)priv; -// pclog("sb_write : Write soundblaster %04X %02X %04X:%04X %02X\n",a,v,CS,pc,dsp->sb_command); switch (a&0xF) { case 6: /*Reset*/ @@ -758,7 +699,7 @@ void sb_write(uint16_t a, uint8_t v, void *priv) timer_update_outstanding(); if (dsp->asp_data_len) { -// pclog("ASP data %i\n", dsp->asp_data_len); + DBGLOG(1, "ASP data %i\n", dsp->asp_data_len); dsp->asp_data_len--; if (!dsp->asp_data_len) sb_add_data(dsp, 0); @@ -769,8 +710,6 @@ void sb_write(uint16_t a, uint8_t v, void *priv) dsp->sb_command = v; if (v == 0x01) sb_add_data(dsp, 0); -// if (sb_commands[v]==-1) -// fatal("Bad SB command %02X\n",v); dsp->sb_data_stat++; } else @@ -787,11 +726,10 @@ void sb_write(uint16_t a, uint8_t v, void *priv) uint8_t sb_read(uint16_t a, void *priv) { sb_dsp_t *dsp = (sb_dsp_t *)priv; -// pclog("sb_read : Read soundblaster %04X %04X:%04X\n",a,CS,pc); switch (a & 0xf) { case 0xA: /*Read data*/ - if (dsp->uart_midi) + if (mpu && dsp->uart_midi) { return MPU401_ReadData(mpu); } @@ -801,14 +739,13 @@ uint8_t sb_read(uint16_t a, void *priv) dsp->sb_read_rp++; dsp->sb_read_rp &= 0xFF; } -// pclog("SB read %02X\n",sbreaddat); return dsp->sbreaddat; case 0xC: /*Write data ready*/ - if (dsp->sb_8_enable || dsp->sb_type >= SB16 ) - dsp->busy_count = (dsp->busy_count + 1) & 15; + if (dsp->sb_8_enable || dsp->sb_type >= SB16) + dsp->busy_count = (dsp->busy_count + 1) & 3; else dsp->busy_count = 0; - if (dsp->wb_full || (dsp->busy_count & 8)) + if (dsp->wb_full || (dsp->busy_count & 2)) { dsp->wb_full = dsp->wb_time; return 0xff; @@ -846,6 +783,7 @@ void sb_dsp_init(sb_dsp_t *dsp, int type) dsp->sb_irqnum = 7; dsp->sb_8_dmanum = 1; dsp->sb_16_dmanum = 5; + mpu = NULL; sb_doreset(dsp); @@ -860,7 +798,7 @@ void sb_dsp_init(sb_dsp_t *dsp, int type) void sb_dsp_setaddr(sb_dsp_t *dsp, uint16_t addr) { -// pclog("sb_dsp_setaddr : %04X\n", addr); + DBGLOG(1, "sb_dsp_setaddr : %04X\n", addr); if (dsp->sb_addr != 0) { io_removehandler(dsp->sb_addr + 6, 0x0002, sb_read, NULL, NULL, sb_write, NULL, NULL, dsp); io_removehandler(dsp->sb_addr + 0xa, 0x0006, sb_read, NULL, NULL, sb_write, NULL, NULL, dsp); @@ -883,13 +821,11 @@ void pollsb(void *p) int tempi,ref; dsp->sbcount += dsp->sblatcho; -// pclog("PollSB %i %i %i %i\n",sb_8_enable,sb_8_pause,sb_pausetime,sb_8_output); if (dsp->sb_8_enable && !dsp->sb_8_pause && dsp->sb_pausetime < 0 && dsp->sb_8_output) { int data[2]; sb_dsp_update(dsp); -// pclog("Dopoll %i %02X %i\n", sb_8_length, sb_8_format, sblatcho); switch (dsp->sb_8_format) { case 0x00: /*Mono unsigned*/ @@ -1047,41 +983,55 @@ void pollsb(void *p) if (dsp->sb_8_length < 0) { if (dsp->sb_8_autoinit) dsp->sb_8_length = dsp->sb_8_autolen; - else dsp->sbenable = dsp->sb_8_enable=0; + else dsp->sbenable = dsp->sb_8_enable = 0; sb_irq(dsp, 1); } } if (dsp->sb_16_enable && !dsp->sb_16_pause && dsp->sb_pausetime < 0LL && dsp->sb_16_output) { + int data[2]; + sb_dsp_update(dsp); switch (dsp->sb_16_format) { case 0x00: /*Mono unsigned*/ - dsp->sbdatl = dsp->sbdatr = sb_16_read_dma(dsp) ^ 0x8000; + data[0] = sb_16_read_dma(dsp); + if (data[0] == DMA_NODATA) + break; + dsp->sbdatl = dsp->sbdatr = data[0] ^ 0x8000; dsp->sb_16_length--; break; case 0x10: /*Mono signed*/ - dsp->sbdatl = dsp->sbdatr = sb_16_read_dma(dsp); + data[0] = sb_16_read_dma(dsp); + if (data[0] == DMA_NODATA) + break; + dsp->sbdatl = dsp->sbdatr = data[0]; dsp->sb_16_length--; break; case 0x20: /*Stereo unsigned*/ - dsp->sbdatl = sb_16_read_dma(dsp) ^ 0x8000; - dsp->sbdatr = sb_16_read_dma(dsp) ^ 0x8000; + data[0] = sb_16_read_dma(dsp); + data[1] = sb_16_read_dma(dsp); + if (data[0] == DMA_NODATA || data[1] == DMA_NODATA) + break; + dsp->sbdatl = data[0] ^ 0x8000; + dsp->sbdatr = data[1] ^ 0x8000; dsp->sb_16_length -= 2; break; case 0x30: /*Stereo signed*/ - dsp->sbdatl = sb_16_read_dma(dsp); - dsp->sbdatr = sb_16_read_dma(dsp); + data[0] = sb_16_read_dma(dsp); + data[1] = sb_16_read_dma(dsp); + if (data[0] == DMA_NODATA || data[1] == DMA_NODATA) + break; + dsp->sbdatl = data[0]; + dsp->sbdatr = data[1]; dsp->sb_16_length -= 2; break; -// default: -// fatal("Unrecognised SB 16-bit format %02X\n",sb_16_format); } if (dsp->sb_16_length < 0) { -// pclog("16DMA over %i\n",dsp->sb_16_autoinit); + DBGLOG(1, "16DMA over %i\n",dsp->sb_16_autoinit); if (dsp->sb_16_autoinit) dsp->sb_16_length = dsp->sb_16_autolen; else dsp->sbenable = dsp->sb_16_enable = 0; sb_irq(dsp, 0); @@ -1094,7 +1044,7 @@ void pollsb(void *p) { sb_irq(dsp, 1); dsp->sbenable = dsp->sb_8_enable; -// pclog("SB pause over\n"); + DBGLOG(1, "SB pause over\n"); } } } @@ -1104,28 +1054,10 @@ void sb_poll_i(void *p) sb_dsp_t *dsp = (sb_dsp_t *)p; int processed=0; dsp->sb_count_i += dsp->sblatchi; -// pclog("PollSBi %i %i %i %i\n",sb_8_enable,sb_8_pause,sb_pausetime,sb_8_output); if (dsp->sb_8_enable && !dsp->sb_8_pause && dsp->sb_pausetime < 0 && !dsp->sb_8_output) { switch (dsp->sb_8_format) { -#ifdef SB_TEST_RECORDING_SAW - case 0x00: /*Unsigned mono. As the manual says, only the left channel is recorded*/ - case 0x10: /*Signed mono. As the manual says, only the left channel is recorded*/ - sb_8_write_dma(dsp, counttest); - counttest+=0x10; - counttest&=0xFF; - dsp->sb_8_length--; - break; - case 0x20: /*Unsigned stereo*/ - case 0x30: /*Signed stereo*/ - sb_8_write_dma(dsp, counttest); - sb_8_write_dma(dsp, counttest); - counttest+=0x10; - counttest&=0xFF; - dsp->sb_8_length -= 2; - break; -#else case 0x00: /*Mono unsigned As the manual says, only the left channel is recorded*/ sb_8_write_dma(dsp, (dsp->record_buffer[dsp->record_pos_read]>>8) ^0x80); dsp->sb_8_length--; @@ -1152,16 +1084,12 @@ void sb_poll_i(void *p) dsp->record_pos_read+=2; dsp->record_pos_read&=0xFFFF; break; -#endif -// default: -// fatal("Unrecognised SB 8-bit input format %02X\n",sb_8_format); } if (dsp->sb_8_length < 0) { -// pclog("Input DMA over %i\n",sb_8_autoinit); if (dsp->sb_8_autoinit) dsp->sb_8_length = dsp->sb_8_autolen; - else dsp->sb_enable_i = dsp->sb_8_enable = 0; + else dsp->sbenable = dsp->sb_8_enable = 0; sb_irq(dsp, 1); } processed=1; @@ -1170,25 +1098,6 @@ void sb_poll_i(void *p) { switch (dsp->sb_16_format) { -#ifdef SB_TEST_RECORDING_SAW - case 0x00: /*Unsigned mono. As the manual says, only the left channel is recorded*/ - case 0x10: /*Signed mono. As the manual says, only the left channel is recorded*/ - if (sb_16_write_dma(dsp, counttest)) - return; - counttest+=0x1000; - counttest&=0xFFFF; - dsp->sb_16_length--; - break; - case 0x20: /*Unsigned stereo*/ - case 0x30: /*Signed stereo*/ - if (sb_16_write_dma(dsp, counttest)) - return; - sb_16_write_dma(dsp, counttest); - counttest+=0x1000; - counttest&=0xFFFF; - dsp->sb_16_length -= 2; - break; -#else case 0x00: /*Unsigned mono. As the manual says, only the left channel is recorded*/ if (sb_16_write_dma(dsp, dsp->record_buffer[dsp->record_pos_read]^0x8000)) return; @@ -1219,21 +1128,17 @@ void sb_poll_i(void *p) dsp->record_pos_read+=2; dsp->record_pos_read&=0xFFFF; break; -#endif -// default: -// fatal("Unrecognised SB 16-bit input format %02X\n",sb_16_format); } if (dsp->sb_16_length < 0) { -// pclog("16iDMA over %i\n",sb_16_autoinit); if (dsp->sb_16_autoinit) dsp->sb_16_length = dsp->sb_16_autolen; - else dsp->sb_enable_i = dsp->sb_16_enable = 0; + else dsp->sbenable = dsp->sb_16_enable = 0; sb_irq(dsp, 0); } processed=1; } - //Assume this is direct mode + /* Assume this is direct mode */ if (!processed) { dsp->record_pos_read+=2; @@ -1254,77 +1159,7 @@ void sb_dsp_update(sb_dsp_t *dsp) dsp->buffer[dsp->pos*2 + 1] = dsp->sbdatr; } } + void sb_dsp_close(sb_dsp_t *dsp) { - #ifdef SB_DSP_RECORD_DEBUG - if (soundf != 0) - { - fclose(soundf); - soundf=0; - } - #endif -} - -void sb_dsp_add_status_info(char *s, int max_len, sb_dsp_t *dsp) -{ - char temps[128]; - int freq; - - if (dsp->sb_timeo < 256LL) - freq = (int) (1000000 / (256LL - dsp->sb_timeo)); - else - freq = (int) (dsp->sb_timeo - 256LL); - - if (dsp->sb_8_enable && dsp->sb_8_output) - { - switch (dsp->sb_8_format) - { - case 0x00: /*Mono unsigned*/ - case 0x10: /*Mono signed*/ - if (dsp->sb_type >= SBPRO && dsp->sb_type < SB16 && dsp->stereo) - { - strcpy(temps, "SB playback format : 8-bit stereo\n"); - freq /= 2; - } - else - strcpy(temps, "SB playback format : 8-bit mono\n"); - break; - case 0x20: /*Stereo unsigned*/ - case 0x30: /*Stereo signed*/ - strcpy(temps, "SB playback format : 8-bit stereo\n"); - break; - case ADPCM_4: - strcpy(temps, "SB playback format : 4-bit ADPCM\n"); - break; - case ADPCM_26: - strcpy(temps, "SB playback format : 2.6-bit ADPCM\n"); - break; - case ADPCM_2: - strcpy(temps, "SB playback format : 2-bit ADPCM\n"); - break; - } - } - else if (dsp->sb_16_enable && dsp->sb_16_output) - { - switch (dsp->sb_16_format) - { - case 0x00: /*Mono unsigned*/ - case 0x10: /*Mono signed*/ - strcpy(temps, "SB playback format : 16-bit mono\n"); - break; - case 0x20: /*Stereo unsigned*/ - case 0x30: /*Stereo signed*/ - strcpy(temps, "SB playback format : 16-bit stereo\n"); - break; - } - } - else - strcpy(temps, "SB playback stopped\n"); - strncat(s, temps, max_len); - - if ((dsp->sb_8_enable && dsp->sb_8_output) || (dsp->sb_16_enable && dsp->sb_16_output)) - { - sprintf(temps, "SB playback frequency : %iHz\n", freq); - strncat(s, temps, max_len); - } } diff --git a/src/devices/sound/snd_sb_dsp.h b/src/devices/sound/snd_sb_dsp.h index aefee8a..4e6b102 100644 --- a/src/devices/sound/snd_sb_dsp.h +++ b/src/devices/sound/snd_sb_dsp.h @@ -8,7 +8,7 @@ * * Definitions for the SoundBlaster DSP driver. * - * Version: @(#)snd_sb_dsp.h 1.0.1 2018/02/14 + * Version: @(#)snd_sb_dsp.h 1.0.2 2018/09/05 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -129,8 +129,6 @@ void sb_dsp_poll(sb_dsp_t *dsp, int16_t *l, int16_t *r); void sb_dsp_set_stereo(sb_dsp_t *dsp, int stereo); -void sb_dsp_add_status_info(char *s, int max_len, sb_dsp_t *dsp); - void sb_dsp_update(sb_dsp_t *dsp); diff --git a/src/devices/sound/snd_sn76489.c b/src/devices/sound/snd_sn76489.c index ffda12d..fd59408 100644 --- a/src/devices/sound/snd_sn76489.c +++ b/src/devices/sound/snd_sn76489.c @@ -8,7 +8,7 @@ * * Implementation of the TI SN74689 PSG sound devices. * - * Version: @(#)snd_sn76489.c 1.0.4 2018/05/06 + * Version: @(#)snd_sn76489.c 1.0.5 2018/09/22 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -42,6 +42,7 @@ #include #include #include +#define dbglog sound_dev_log #include "../../emu.h" #include "../../io.h" #include "../../device.h" @@ -245,7 +246,7 @@ void sn76489_init(sn76489_t *sn76489, uint16_t base, uint16_t size, int type, in void *sn76489_device_init(const device_t *info) { - sn76489_t *sn76489 = malloc(sizeof(sn76489_t)); + sn76489_t *sn76489 = (sn76489_t *)mem_alloc(sizeof(sn76489_t)); memset(sn76489, 0, sizeof(sn76489_t)); sn76489_init(sn76489, 0x00c0, 0x0008, SN76496, 3579545); @@ -254,7 +255,7 @@ void *sn76489_device_init(const device_t *info) } void *ncr8496_device_init(const device_t *info) { - sn76489_t *sn76489 = malloc(sizeof(sn76489_t)); + sn76489_t *sn76489 = (sn76489_t *)mem_alloc(sizeof(sn76489_t)); memset(sn76489, 0, sizeof(sn76489_t)); sn76489_init(sn76489, 0x00c0, 0x0008, NCR8496, 3579545); diff --git a/src/devices/sound/snd_speaker.c b/src/devices/sound/snd_speaker.c index 2ab7b46..f2c513e 100644 --- a/src/devices/sound/snd_speaker.c +++ b/src/devices/sound/snd_speaker.c @@ -8,7 +8,7 @@ * * Implementation of the PC-Speaker device. * - * Version: @(#)snd_speaker.c 1.0.2 2018/05/06 + * Version: @(#)snd_speaker.c 1.0.3 2018/09/22 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -40,67 +40,75 @@ #include #include #include +#define dbglog sound_dev_log #include "../../emu.h" #include "../system/pit.h" #include "sound.h" #include "snd_speaker.h" -int speaker_mute = 0; -int speaker_gated = 0; -int speaker_enable = 0, was_speaker_enable = 0; +int speaker_mute, + speaker_gated, + speaker_enable, + was_speaker_enable; + +int gated, + speakval, + speakon; -int gated,speakval,speakon; +static int16_t speaker_buffer[SOUNDBUFLEN]; +static int speaker_pos; -static int16_t speaker_buffer[SOUNDBUFLEN]; -static int speaker_pos = 0; - - -void speaker_update(void) +void +speaker_update(void) { - int16_t val; + int16_t val; + + for (; speaker_pos < sound_pos_global; speaker_pos++) { + if (speaker_gated && was_speaker_enable) { + if (!pit.m[2] || pit.m[2]==4) + val = speakval; + else if (pit.l[2] < 0x40) + val = 0x0a00; + else + val = speakon ? 0x1400 : 0; + } else + val = was_speaker_enable ? 0x1400 : 0; + + if (! speaker_enable) + was_speaker_enable = 0; + + speaker_buffer[speaker_pos] = val; + } +} + + +static void +get_buffer(int32_t *buffer, int len, void *p) +{ + int c; + + speaker_update(); - for (; speaker_pos < sound_pos_global; speaker_pos++) - { - if (speaker_gated && was_speaker_enable) - { - if (!pit.m[2] || pit.m[2]==4) - val = speakval; - else if (pit.l[2] < 0x40) - val = 0xa00; - else - val = speakon ? 0x1400 : 0; - } - else - val = was_speaker_enable ? 0x1400 : 0; + if (! speaker_mute) { + for (c = 0; c < len * 2; c++) + buffer[c] += speaker_buffer[c >> 1]; + } - if (!speaker_enable) - was_speaker_enable = 0; - - speaker_buffer[speaker_pos] = val; - } + speaker_pos = 0; } -static void speaker_get_buffer(int32_t *buffer, int len, void *p) + +void +speaker_reset(void) { - int c; + INFO("SPEAKER: reset\n"); - speaker_update(); - - if (!speaker_mute) - { - for (c = 0; c < len * 2; c++) - buffer[c] += speaker_buffer[c >> 1]; - } + sound_add_handler(get_buffer, NULL); - speaker_pos = 0; -} - - -void speaker_init(void) -{ - sound_add_handler(speaker_get_buffer, NULL); - speaker_mute = 0; + speaker_mute = speaker_gated = 0; + speaker_enable = was_speaker_enable = 0; + speaker_pos = 0; } diff --git a/src/devices/sound/snd_speaker.h b/src/devices/sound/snd_speaker.h index d465019..571d3fc 100644 --- a/src/devices/sound/snd_speaker.h +++ b/src/devices/sound/snd_speaker.h @@ -8,7 +8,7 @@ * * Definitions for the PC-Speaker driver. * - * Version: @(#)snd_speaker.h 1.0.1 2018/02/14 + * Version: @(#)snd_speaker.h 1.0.2 2018/09/22 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -40,14 +40,18 @@ # define SOUND_SPEAKER_H -extern int speaker_mute; +extern int speaker_mute; +extern int speaker_gated; +extern int speaker_enable, + was_speaker_enable; -extern int speaker_gated; -extern int speaker_enable, was_speaker_enable; +extern int gated, + speakval, + speakon; -extern void speaker_init(void); -extern void speaker_update(void); +extern void speaker_reset(void); +extern void speaker_update(void); #endif /*SOUND_SPEAKER_H*/ diff --git a/src/devices/sound/snd_ssi2001.c b/src/devices/sound/snd_ssi2001.c index 771db9d..bf58b79 100644 --- a/src/devices/sound/snd_ssi2001.c +++ b/src/devices/sound/snd_ssi2001.c @@ -8,7 +8,7 @@ * * Implementation of the SSI2001 sound device. * - * Version: @(#)snd_ssi2001.c 1.0.5 2018/05/06 + * Version: @(#)snd_ssi2001.c 1.0.6 2018/09/22 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -41,6 +41,7 @@ #include #include #include +#define dbglog sound_dev_log #include "../../emu.h" #include "../../io.h" #include "../../device.h" @@ -112,7 +113,7 @@ ssi_init(const device_t *info) { ssi2001_t *dev; - dev = malloc(sizeof(ssi2001_t)); + dev = (ssi2001_t *)mem_alloc(sizeof(ssi2001_t)); memset(dev, 0x00, sizeof(ssi2001_t)); /* Get the device configuration. We ignore the game port for now. */ @@ -149,48 +150,46 @@ ssi_close(void *priv) } -static const device_config_t ssi2001_config[] = -{ +static const device_config_t ssi2001_config[] = { + { + "base", "Address", CONFIG_HEX16, "", 0x280, { - "base", "Address", CONFIG_HEX16, "", 0x280, { - { - "0x280", 0x280 - }, - { - "0x2A0", 0x2a0 - }, - { - "0x2C0", 0x2c0 - }, - { - "0x2E0", 0x2e0 - }, - { - "" - } + "0x280", 0x280 }, - }, - { - "game_port", "Game Port", CONFIG_SELECTION, "", 0, { - { - "Disabled", 0 - }, - { - "Enabled", 1 - }, - { - "" - } + "0x2A0", 0x2a0 }, - }, - { - "", "", -1 + { + "0x2C0", 0x2c0 + }, + { + "0x2E0", 0x2e0 + }, + { + "" + } } + }, + { + "game_port", "Game Port", CONFIG_SELECTION, "", 0, + { + { + "Disabled", 0 + }, + { + "Enabled", 1 + }, + { + "" + } + } + }, + { + "", "", -1 + } }; - const device_t ssi2001_device = { "Innovation SSI-2001", DEVICE_ISA, diff --git a/src/devices/sound/snd_wss.c b/src/devices/sound/snd_wss.c index 81e4b45..8a87cb0 100644 --- a/src/devices/sound/snd_wss.c +++ b/src/devices/sound/snd_wss.c @@ -8,13 +8,15 @@ * * Implementation of the Windows Sound System sound device. * - * Version: @(#)snd_wss.c 1.0.4 2018/05/06 + * Version: @(#)snd_wss.c 1.0.5 2018/09/22 * * Authors: Fred N. van Kempen, + * TheCollector1995, * Miran Grca, * Sarah Walker, * * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2018 TheCollector1995. * Copyright 2016-2018 Miran Grca. * Copyright 2008-2018 Sarah Walker. * @@ -42,9 +44,11 @@ #include #include #include +#define dbglog sound_dev_log #include "../../emu.h" #include "../../io.h" #include "../../device.h" +#include "../system/mca.h" #include "../system/dma.h" #include "../system/pic.h" #include "sound.h" @@ -52,106 +56,190 @@ #include "snd_opl.h" -/*530, 11, 3 - 530=23*/ -/*530, 11, 1 - 530=22*/ -/*530, 11, 0 - 530=21*/ -/*530, 10, 1 - 530=1a*/ -/*530, 9, 1 - 530=12*/ -/*530, 7, 1 - 530=0a*/ -/*604, 11, 1 - 530=22*/ -/*e80, 11, 1 - 530=22*/ -/*f40, 11, 1 - 530=22*/ +/*Win95 only uses IRQ7-9, others may be wrong*/ +static const int wss_dmas[4] = { 0, 0, 1, 3 }; +static const int wss_irqs[8] = { 5, 7, 9, 10, 11, 12, 14, 15 }; -static int wss_dma[4] = {0, 0, 1, 3}; -static int wss_irq[8] = {5, 7, 9, 10, 11, 12, 14, 15}; /*W95 only uses 7-9, others may be wrong*/ +typedef struct { + const char *name; + int board; + uint8_t config; -typedef struct wss_t -{ - uint8_t config; + ad1848_t ad1848; - ad1848_t ad1848; - opl_t opl; + opl_t opl; + int opl_enabled; + + uint8_t pos_regs[8]; } wss_t; -uint8_t wss_read(uint16_t addr, void *p) + +static void +get_buffer(int32_t *buffer, int len, void *priv) { - wss_t *wss = (wss_t *)p; - uint8_t temp; - temp = 4 | (wss->config & 0x40); - return temp; + wss_t *dev = (wss_t *)priv; + int c; + + opl3_update2(&dev->opl); + + ad1848_update(&dev->ad1848); + + for (c = 0; c < len * 2; c++) { + buffer[c] += dev->opl.buffer[c]; + buffer[c] += (dev->ad1848.buffer[c] / 2); + } + + dev->opl.pos = 0; + dev->ad1848.pos = 0; } -void wss_write(uint16_t addr, uint8_t val, void *p) -{ - wss_t *wss = (wss_t *)p; - wss->config = val; - ad1848_setdma(&wss->ad1848, wss_dma[val & 3]); - ad1848_setirq(&wss->ad1848, wss_irq[(val >> 3) & 7]); +static uint8_t +wss_read(uint16_t addr, void *priv) +{ + wss_t *dev = (wss_t *)priv; + uint8_t ret; + + ret = 4 | (dev->config & 0x40); + + return(ret); } -static void wss_get_buffer(int32_t *buffer, int len, void *p) + +static void +wss_write(uint16_t addr, uint8_t val, void *priv) { - wss_t *wss = (wss_t *)p; - - int c; + wss_t *dev = (wss_t *)priv; - opl3_update2(&wss->opl); - ad1848_update(&wss->ad1848); - for (c = 0; c < len * 2; c++) - { - buffer[c] += wss->opl.buffer[c]; - buffer[c] += (wss->ad1848.buffer[c] / 2); - } + dev->config = val; - wss->opl.pos = 0; - wss->ad1848.pos = 0; + ad1848_setdma(&dev->ad1848, wss_dmas[val & 3]); + ad1848_setirq(&dev->ad1848, wss_irqs[(val >> 3) & 7]); } -void *wss_init(const device_t *info) + +static uint8_t +ncr_audio_mca_read(int port, void *priv) { - wss_t *wss = malloc(sizeof(wss_t)); + wss_t *dev = (wss_t *)priv; - memset(wss, 0, sizeof(wss_t)); - - opl3_init(&wss->opl); - ad1848_init(&wss->ad1848); - - ad1848_setirq(&wss->ad1848, 7); - ad1848_setdma(&wss->ad1848, 3); - - io_sethandler(0x0388, 0x0004, opl3_read, NULL, NULL, opl3_write, NULL, NULL, &wss->opl); - io_sethandler(0x0530, 0x0004, wss_read, NULL, NULL, wss_write, NULL, NULL, wss); - io_sethandler(0x0534, 0x0004, ad1848_read, NULL, NULL, ad1848_write, NULL, NULL, &wss->ad1848); - - sound_add_handler(wss_get_buffer, wss); - - return wss; + return(dev->pos_regs[port & 0x07]); } -void wss_close(void *p) + +static void +ncr_audio_mca_write(int port, uint8_t val, void *priv) { - wss_t *wss = (wss_t *)p; - - free(wss); + wss_t *dev = (wss_t *)priv; + uint16_t ports[] = { 0x0530, 0x0E80, 0x0F40, 0x0604 }; + uint16_t addr; + + if (port < 0x102) return; + + dev->opl_enabled = (dev->pos_regs[2] & 0x20) ? 1 : 0; + addr = ports[(dev->pos_regs[2] & 0x18) >> 3]; + + io_removehandler(0x0388, 4, + opl3_read,NULL,NULL, opl3_write,NULL,NULL, &dev->opl); + io_removehandler(addr, 4, + wss_read,NULL,NULL, wss_write,NULL,NULL, dev); + io_removehandler(addr+4, 4, + ad1848_read,NULL,NULL, ad1848_write,NULL,NULL, &dev->ad1848); + INFO("%s: OPL=%d, I/O=%04XH\n", dev->name, dev->opl_enabled, addr); + + dev->pos_regs[port & 7] = val; + if (dev->pos_regs[2] & 1) { + addr = ports[(dev->pos_regs[2] & 0x18) >> 3]; + + if (dev->opl_enabled) + io_sethandler(0x0388, 4, + opl3_read,NULL,NULL, opl3_write,NULL,NULL, &dev->opl); + io_sethandler(addr, 4, + wss_read,NULL,NULL, wss_write,NULL,NULL, dev); + io_sethandler(addr+4, 4, + ad1848_read,NULL,NULL, ad1848_write,NULL,NULL, &dev->ad1848); + } } -void wss_speed_changed(void *p) + +static void * +wss_init(const device_t *info) { - wss_t *wss = (wss_t *)p; - - ad1848_speed_changed(&wss->ad1848); + wss_t *dev; + + dev = (wss_t *)mem_alloc(sizeof(wss_t)); + memset(dev, 0x00, sizeof(wss_t)); + dev->name = info->name; + dev->board = info->local; + + switch(info->local) { + case 0: /* standard ISA controller */ + break; + + case 1: /* NCR Business Audio MCA */ + dev->pos_regs[0] = 0x16; + dev->pos_regs[1] = 0x51; + mca_add(ncr_audio_mca_read, ncr_audio_mca_write, dev); + break; + } + + opl3_init(&dev->opl); + + ad1848_init(&dev->ad1848); + ad1848_setirq(&dev->ad1848, 7); + ad1848_setdma(&dev->ad1848, 3); + + io_sethandler(0x0388, 4, + opl3_read,NULL,NULL, opl3_write,NULL,NULL, &dev->opl); + io_sethandler(0x0530, 4, + wss_read,NULL,NULL, wss_write,NULL,NULL, dev); + io_sethandler(0x0534, 4, + ad1848_read,NULL,NULL, ad1848_write,NULL,NULL, &dev->ad1848); + + sound_add_handler(get_buffer, dev); + + return(dev); } -const device_t wss_device = + +static void +wss_close(void *priv) { - "Windows Sound System", - DEVICE_ISA, 0, - wss_init, wss_close, NULL, - NULL, - wss_speed_changed, - NULL, NULL, - NULL + wss_t *dev = (wss_t *)priv; + + free(dev); +} + + +static void +wss_speed_changed(void *priv) +{ + wss_t *dev = (wss_t *)priv; + + ad1848_speed_changed(&dev->ad1848); +} + + +const device_t wss_device = { + "Windows Sound System", + DEVICE_ISA, + 0, + wss_init, wss_close, NULL, + NULL, + wss_speed_changed, + NULL, NULL, + NULL +}; + +const device_t ncr_business_audio_device = { + "NCR Business Audio", + DEVICE_MCA, + 1, + wss_init, wss_close, NULL, + NULL, + wss_speed_changed, + NULL, NULL, + NULL }; diff --git a/src/devices/sound/snd_ym7128.c b/src/devices/sound/snd_ym7128.c index 808bb21..0f00a12 100644 --- a/src/devices/sound/snd_ym7128.c +++ b/src/devices/sound/snd_ym7128.c @@ -8,7 +8,7 @@ * * Implementation of the Yamaha YM7128 sound device. * - * Version: @(#)snd_ym7128.c 1.0.2 2018/05/06 + * Version: @(#)snd_ym7128.c 1.0.3 2018/09/15 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -40,6 +40,7 @@ #include #include #include +#define dbglog sound_dev_log #include "../../emu.h" #include "snd_ym7128.h" @@ -48,7 +49,8 @@ static int attenuation[32]; static int tap_position[32]; -void ym7128_init(ym7128_t *ym7128) +void +ym7128_init(ym7128_t *ym7128) { int c; double out = 65536.0; diff --git a/src/devices/sound/sound.c b/src/devices/sound/sound.c index f892825..17626b9 100644 --- a/src/devices/sound/sound.c +++ b/src/devices/sound/sound.c @@ -8,7 +8,7 @@ * * Sound emulation core. * - * Version: @(#)sound.c 1.0.11 2018/05/06 + * Version: @(#)sound.c 1.0.12 2018/10/05 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -43,10 +43,12 @@ #include #include #define HAVE_STDARG_H +#define dbglog sound_log #include "../../emu.h" #include "../../timer.h" #include "../../device.h" #include "../../plat.h" +#include "../scsi/scsi_device.h" #include "../cdrom/cdrom.h" #include "sound.h" #include "midi.h" @@ -68,14 +70,15 @@ typedef struct { } sndhnd_t; +#ifdef ENABLE_SOUND_LOG +int sound_do_log = ENABLE_SOUND_LOG; +#endif int sound_pos_global = 0; volatile int soundon = 1; static sndhnd_t handlers[8]; -static sndhnd_t process_handlers[8]; static int handlers_num; -static int process_handlers_num; static int64_t poll_time = 0LL, poll_latch; static int32_t *outbuffer; @@ -100,11 +103,10 @@ cd_thread(void *param) { float cd_buffer_temp[2] = {0.0, 0.0}; float cd_buffer_temp2[2] = {0.0, 0.0}; - int32_t cd_buffer_temp4[2] = {0, 0}; int32_t audio_vol_l; int32_t audio_vol_r; int channel_select[2]; - int c, d, i, has_audio; + int c, i, r, has_audio; thread_set_event(cd_start_event); @@ -127,20 +129,33 @@ cd_thread(void *param) for (i = 0; i < CDROM_NUM; i++) { has_audio = 0; - if (cdrom_drives[i].bus_type == CDROM_BUS_DISABLED) continue; + if ((cdrom_drives[i].bus_type == CDROM_BUS_DISABLED) || + !cdrom[i] || !cdrom[i]->handler) continue; - if (cdrom_drives[i].handler->audio_callback) { - cdrom_drives[i].handler->audio_callback(i, cd_buffer[i], CD_BUFLEN*2); - has_audio = (cdrom_drives[i].bus_type && cdrom_drives[i].sound_on); + if (cdrom[i]->handler->audio_callback) { + r = cdrom[i]->handler->audio_callback(i, cd_buffer[i], CD_BUFLEN*2); + has_audio = (cdrom_drives[i].bus_type && cdrom_drives[i].sound_on/* && r*/); } else continue; if (soundon && has_audio) { - audio_vol_l = cdrom_mode_sense_get_volume(i, 0); - audio_vol_r = cdrom_mode_sense_get_volume(i, 1); + audio_vol_l = cdrom_mode_sense_get_volume(cdrom[i], 0); + audio_vol_r = cdrom_mode_sense_get_volume(cdrom[i], 1); - channel_select[0] = cdrom_mode_sense_get_channel(i, 0); - channel_select[1] = cdrom_mode_sense_get_channel(i, 1); + channel_select[0] = cdrom_mode_sense_get_channel(cdrom[i], 0); + channel_select[1] = cdrom_mode_sense_get_channel(cdrom[i], 1); + if (!r) { + for (c = 0; c < CD_BUFLEN*2; c += 2) { + if (sound_is_float) { + cd_out_buffer[c] += 0.0; + cd_out_buffer[c+1] += 0.0; + } else { + cd_out_buffer_int16[c] += 0; + cd_out_buffer_int16[c+1] += 0; + } + } + continue; + } for (c = 0; c < CD_BUFLEN*2; c += 2) { /* First, transfer the CD audio data to the temporary buffer. */ @@ -164,23 +179,12 @@ cd_thread(void *param) if (channel_select[1] & 2) cd_buffer_temp2[1] += cd_buffer_temp[1]; - if (process_handlers_num) { - cd_buffer_temp4[0] = (int32_t)cd_buffer_temp2[0]; - cd_buffer_temp4[1] = (int32_t)cd_buffer_temp2[1]; + /*Apply sound card CD volume*/ + cd_buffer_temp2[0] *= (float)cd_vol_l; + cd_buffer_temp2[0] /= 65535.0; - for (d = 0; d < process_handlers_num; d++) - process_handlers[d].get_buffer(cd_buffer_temp4, 1, process_handlers[d].priv); - - cd_buffer_temp2[0] = (float)cd_buffer_temp4[0]; - cd_buffer_temp2[1] = (float)cd_buffer_temp4[1]; - } else { - /*Apply sound card CD volume*/ - cd_buffer_temp2[0] *= (float)cd_vol_l; - cd_buffer_temp2[0] /= 65535.0; - - cd_buffer_temp2[1] *= (float)cd_vol_r; - cd_buffer_temp2[1] /= 65535.0; - } + cd_buffer_temp2[1] *= (float)cd_vol_r; + cd_buffer_temp2[1] /= 65535.0; if (sound_is_float) { cd_out_buffer[c] += (float)(cd_buffer_temp2[0] / 32768.0); @@ -203,9 +207,9 @@ cd_thread(void *param) } if (sound_is_float) - givealbuffer_cd(cd_out_buffer); + openal_buffer_cd(cd_out_buffer); else - givealbuffer_cd(cd_out_buffer_int16); + openal_buffer_cd(cd_out_buffer_int16); } } @@ -217,14 +221,12 @@ cd_thread_end(void) cd_audioon = 0; -#if 0 - pclog("Waiting for CD Audio thread to terminate...\n"); -#endif + DEBUG("Waiting for CD Audio thread to terminate...\n"); + thread_set_event(cd_event); thread_wait(cd_thread_h, -1); -#if 0 - pclog("CD Audio thread terminated...\n"); -#endif + + DEBUG("CD Audio thread terminated...\n"); if (cd_event) { thread_destroy_event(cd_event); @@ -267,12 +269,12 @@ sound_poll(void *priv) outbuffer_ex_int16[c] = outbuffer[c]; } } - + if (soundon) { if (sound_is_float) - givealbuffer(outbuffer_ex); + openal_buffer(outbuffer_ex); else - givealbuffer(outbuffer_ex_int16); + openal_buffer(outbuffer_ex_int16); } if (cd_thread_enable) { @@ -288,13 +290,28 @@ sound_poll(void *priv) } +void +sound_log(int level, const char *fmt, ...) +{ +#ifdef ENABLE_SOUND_LOG + va_list ap; + + if (sound_do_log >= level) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +#endif +} + + /* Reset the sound system. */ void sound_reset(void) { int i; - pclog("SOUND: reset (current=%d)\n", sound_card); + INFO("SOUND: reset (current=%i)\n", sound_card); /* Kill the CD-Audio thread. */ sound_cd_stop(); @@ -305,32 +322,35 @@ sound_reset(void) if (outbuffer_ex_int16 != NULL) free(outbuffer_ex_int16); if (sound_is_float) - outbuffer_ex = malloc(SOUNDBUFLEN * 2 * sizeof(float)); + outbuffer_ex = (float *)mem_alloc(SOUNDBUFLEN * 2 * sizeof(float)); else - outbuffer_ex_int16 = malloc(SOUNDBUFLEN * 2 * sizeof(int16_t)); + outbuffer_ex_int16 = (int16_t *)mem_alloc(SOUNDBUFLEN * 2 * sizeof(int16_t)); + + /* Reset the sound module data handlers. */ + handlers_num = 0; /* Reset the MIDI devices. */ midi_device_init(); /* Reset OpenAL. */ - inital(); + openal_reset(); timer_add(sound_poll, &poll_time, TIMER_ALWAYS_ENABLED, NULL); - handlers_num = 0; - - process_handlers_num = 0; - sound_cd_set_volume(65535, 65535); for (i = 0; i < CDROM_NUM; i++) { - if (cdrom_drives[i].handler->audio_stop) - cdrom_drives[i].handler->audio_stop(i); + if (cdrom[i] && cdrom[i]->handler && cdrom[i]->handler->audio_stop) + cdrom[i]->handler->audio_stop(i); } - /* Initialize the currently selected sound card. */ - snddev_reset(); + /* Initialize the PC Speaker device. */ + speaker_reset(); + /* Initialize the currently selected sound card. */ + sound_card_reset(); + + /* Enable the standlone MPU401 if needed. */ if (mpu401_standalone_enable) mpu401_device_add(); } @@ -340,27 +360,30 @@ sound_reset(void) void sound_init(void) { - int drives = 0; - int i; + int drives, i; /* Initialize the OpenAL module. */ - initalmain(0,NULL); + openal_init(); #ifdef USE_FLUIDSYNTH /* Initialize the FluidSynth module. */ fluidsynth_global_init(); #endif + handlers_num = 0; + outbuffer_ex = NULL; outbuffer_ex_int16 = NULL; - outbuffer = malloc(SOUNDBUFLEN * 2 * sizeof(int32_t)); + outbuffer = (int32_t *)mem_alloc(SOUNDBUFLEN * 2 * sizeof(int32_t)); /* Set up the CD-AUDIO thread. */ + drives = 0; for (i = 0; i < CDROM_NUM; i++) { - if (cdrom_drives[i].bus_type != CDROM_BUS_DISABLED) + if (cdrom[i] && (cdrom_drives[i].bus_type != CDROM_BUS_DISABLED)) drives++; } + if (drives) { cd_audioon = 1; @@ -369,14 +392,12 @@ sound_init(void) cd_event = thread_create_event(); cd_thread_h = thread_create(cd_thread, NULL); -#if 0 - pclog("Waiting for CD start event...\n"); -#endif + DEBUG("Waiting for CD start event...\n"); + thread_wait_event(cd_start_event, -1); thread_reset_event(cd_start_event); -#if 0 - pclog("Done!\n"); -#endif + + DEBUG("Done!\n"); } else cd_audioon = 0; @@ -395,7 +416,7 @@ sound_close(void) midi_close(); /* Close the OpenAL interface. */ - closeal(); + openal_close(); } @@ -406,7 +427,9 @@ sound_cd_stop(void) int i; for (i = 0; i < CDROM_NUM; i++) { - if (cdrom_drives[i].bus_type != CDROM_BUS_DISABLED) + if (cdrom[i] && cdrom[i]->handler && cdrom[i]->handler->audio_stop) + cdrom[i]->handler->audio_stop(i); + if ((cdrom_drives[i].bus_type != CDROM_BUS_DISABLED) && cdrom[i]) drives++; } if (drives && !cd_thread_enable) { @@ -444,15 +467,6 @@ sound_add_handler(void (*get_buffer)(int32_t *buffer, int len, void *p), void *p } -void -sound_add_process_handler(void (*get_buffer)(int32_t *buffer, int len, void *p), void *p) -{ - process_handlers[process_handlers_num].get_buffer = get_buffer; - process_handlers[process_handlers_num].priv = p; - process_handlers_num++; -} - - void sound_speed_changed(void) { diff --git a/src/devices/sound/sound.h b/src/devices/sound/sound.h index 22b860b..0950b65 100644 --- a/src/devices/sound/sound.h +++ b/src/devices/sound/sound.h @@ -8,7 +8,7 @@ * * Definitions for the Sound Emulation core. * - * Version: @(#)sound.h 1.0.7 2018/04/14 + * Version: @(#)sound.h 1.0.9 2018/09/22 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -53,24 +53,19 @@ extern "C" { #endif -extern int sound_dev_do_log; - -extern int ppispeakon; -extern int gated, - speakval, - speakon; +extern int sound_do_log, + sound_dev_do_log; extern int sound_pos_global; +extern volatile int soundon; -extern void snddev_log(const char *fmt, ...); +extern void sound_log(int level, const char *fmt, ...); +extern void sound_dev_log(int level, const char *fmt, ...); extern void sound_add_handler(void (*get_buffer)(int32_t *buffer, \ int len, void *p), void *p); -extern void sound_add_process_handler(void (*get_buffer)(int32_t *buffer, \ - int len, void *p), void *p); -extern void snddev_reset(void); extern int sound_card_available(int card); extern const char *sound_card_getname(int card); #ifdef EMU_DEVICE_H @@ -80,6 +75,7 @@ extern int sound_card_has_config(int card); extern const char *sound_card_get_internal_name(int card); extern int sound_card_get_from_internal_name(const char *s); extern void sound_card_init(void); +extern void sound_card_reset(void); extern void sound_speed_changed(void); @@ -90,11 +86,13 @@ extern void sound_close(void); extern void sound_cd_stop(void); extern void sound_cd_set_volume(unsigned int vol_l, unsigned int vol_r); -extern void closeal(void); -extern void initalmain(int argc, char *argv[]); -extern void inital(void); -extern void givealbuffer(void *buf); -extern void givealbuffer_cd(void *buf); +extern void openal_close(void); +extern void openal_init(void); +extern void openal_reset(void); +extern void openal_buffer(void *buf); +extern void openal_buffer_cd(void *buf); +extern void openal_buffer_midi(void *buf, uint32_t size); +extern void openal_set_midi(int freq, int buf_size); #ifdef __cplusplus } diff --git a/src/devices/sound/sound_dev.c b/src/devices/sound/sound_dev.c index e8f1b23..5508318 100644 --- a/src/devices/sound/sound_dev.c +++ b/src/devices/sound/sound_dev.c @@ -8,7 +8,7 @@ * * Sound devices support module. * - * Version: @(#)sound_dev.c 1.0.6 2018/05/06 + * Version: @(#)sound_dev.c 1.0.7 2018/09/22 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -43,19 +43,13 @@ #include #include #define HAVE_STDARG_H +#define dbglog sound_dev_log #include "../../emu.h" #include "../../device.h" #include "../../plat.h" #include "sound.h" -typedef struct { - const char *name; - const char *internal_name; - const device_t *device; -} sound_t; - - #ifdef ENABLE_SOUND_DEV_LOG int sound_dev_do_log = ENABLE_SOUND_DEV_LOG; #endif @@ -66,6 +60,7 @@ extern const device_t adlib_device; extern const device_t adlib_mca_device; extern const device_t adgold_device; extern const device_t es1371_device; +extern const device_t sbpci128_device; extern const device_t cms_device; extern const device_t gus_device; #if defined(DEV_BRANCH) && defined(USE_PAS16) @@ -82,43 +77,51 @@ extern const device_t sb_16_device; extern const device_t sb_awe32_device; extern const device_t ssi2001_device; extern const device_t wss_device; +extern const device_t ncr_business_audio_device; -static const sound_t sound_cards[] = { - {"Disabled", "none", NULL }, - {"Internal", "internal", NULL }, - {"[ISA] Adlib", "adlib", &adlib_device }, - {"[ISA] Adlib Gold", "adlibgold", &adgold_device }, - {"[ISA] Creative Music System", "cms", &cms_device }, - {"[ISA] Gravis Ultra Sound", "gus", &gus_device }, - {"[ISA] Innovation SSI-2001", "ssi2001", &ssi2001_device }, - {"[ISA] Sound Blaster 1.0", "sb", &sb_1_device }, - {"[ISA] Sound Blaster 1.5", "sb1.5", &sb_15_device }, - {"[ISA] Sound Blaster 2.0", "sb2.0", &sb_2_device }, - {"[ISA] Sound Blaster Pro v1", "sbprov1", &sb_pro_v1_device}, - {"[ISA] Sound Blaster Pro v2", "sbprov2", &sb_pro_v2_device}, - {"[ISA] Sound Blaster 16", "sb16", &sb_16_device }, - {"[ISA] Sound Blaster AWE32", "sbawe32", &sb_awe32_device}, +static struct { + const char *internal_name; + const device_t *device; +} sound_cards[] = { + { "none", NULL }, + { "internal", NULL }, + + { "adlib", &adlib_device }, + { "adlibgold", &adgold_device }, + { "cms", &cms_device }, + { "gus", &gus_device }, + { "ssi2001", &ssi2001_device }, + { "sb", &sb_1_device }, + { "sb1.5", &sb_15_device }, + { "sb2.0", &sb_2_device }, + { "sbprov1", &sb_pro_v1_device }, + { "sbprov2", &sb_pro_v2_device }, + { "sb16", &sb_16_device }, + { "sbawe32", &sb_awe32_device }, #if defined(DEV_BRANCH) && defined(USE_PAS16) - {"[ISA] Pro Audio Spectrum 16", "pas16", &pas16_device }, + { "pas16", &pas16_device }, #endif - {"[ISA] Windows Sound System", "wss", &wss_device }, - {"[MCA] Adlib", "adlib_mca", &adlib_mca_device}, - {"[MCA] Sound Blaster MCV", "sbmcv", &sb_mcv_device }, - {"[MCA] Sound Blaster Pro MCV", "sbpromcv", &sb_pro_mcv_device}, - {"[PCI] Ensoniq AudioPCI (ES1371)", "es1371", &es1371_device }, - {"[PCI] Sound Blaster PCI 128", "sbpci128", &es1371_device }, - {NULL, NULL, NULL } + { "wss", &wss_device }, + + { "adlib_mca", &adlib_mca_device }, + { "ncraudio", &ncr_business_audio_device }, + { "sbmcv", &sb_mcv_device }, + { "sbpromcv", &sb_pro_mcv_device }, + + { "es1371", &es1371_device }, + { "sbpci128", &sbpci128_device }, + { NULL, NULL } }; void -snddev_log(const char *fmt, ...) +sound_dev_log(int level, const char *fmt, ...) { #ifdef ENABLE_SOUND_DEV_LOG va_list ap; - if (sound_dev_do_log) { + if (sound_dev_do_log >= level) { va_start(ap, fmt); pclog_ex(fmt, ap); va_end(ap); @@ -128,8 +131,9 @@ snddev_log(const char *fmt, ...) void -snddev_reset(void) +sound_card_reset(void) { +pclog(0, "SOUND: dev_reset(%d)\n", sound_card); if (sound_cards[sound_card].device != NULL) device_add(sound_cards[sound_card].device); } @@ -148,7 +152,10 @@ sound_card_available(int card) const char * sound_card_getname(int card) { - return(sound_cards[card].name); + if (sound_cards[card].device != NULL) + return(sound_cards[card].device->name); + + return(NULL); } diff --git a/src/devices/system/i82335.c b/src/devices/system/i82335.c index 7038643..19b0118 100644 --- a/src/devices/system/i82335.c +++ b/src/devices/system/i82335.c @@ -8,7 +8,7 @@ * * Intel 82335 SX emulation, used by the Phoenix 386 clone. * - * Version: @(#)i82335.c 1.0.3 2018/05/06 + * Version: @(#)i82335.c 1.0.4 2018/09/13 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -57,14 +57,12 @@ static i82335_t i82335; static uint8_t i82335_read(uint16_t addr, UNUSED(void *priv)) { - // pclog("i82335_read(%04X)\n", addr); - if (addr == 0x22) { + DBGLOG(1, "i82335_read(%04X)\n", addr); + if (addr == 0x22) return(i82335.reg_22); - } - if (addr == 0x23) { + if (addr == 0x23) return(i82335.reg_23); - } return(0); } @@ -76,21 +74,19 @@ i82335_write(uint16_t addr, uint8_t val, UNUSED(void *priv)) int mem_write = 0; int i = 0; - // pclog("i82335_write(%04X, %02X)\n", addr, val); + DBGLOG(1, "i82335_write(%04X, %02X)\n", addr, val); switch (addr) { case 0x22: if ((val ^ i82335.reg_22) & 1) { if (val & 1) { - for (i=0; i<8; i++) { + for (i = 0; i < 8; i++) mem_set_mem_state(0xe0000, 0x20000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - shadowbios = 1; - } + shadowbios = 1; } else { - for (i=0; i<8; i++) { + for (i = 0; i < 8; i++) mem_set_mem_state(0xe0000, 0x20000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); - shadowbios = 0; - } + shadowbios = 0; } flushmmucache(); @@ -104,15 +100,13 @@ i82335_write(uint16_t addr, uint8_t val, UNUSED(void *priv)) if ((val ^ i82335.reg_22) & 2) { if (val & 2) { - for (i=0; i<8; i++) { + for (i = 0; i < 8; i++) mem_set_mem_state(0xc0000, 0x20000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - shadowbios = 1; - } + shadowbios = 1; } else { - for (i=0; i<8; i++) { + for (i = 0; i < 8; i++) mem_set_mem_state(0xc0000, 0x20000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); - shadowbios = 0; - } + shadowbios = 0; } } @@ -121,20 +115,19 @@ i82335_write(uint16_t addr, uint8_t val, UNUSED(void *priv)) for (i = 0; i < 8; i++) { mem_write = (val & 8) ? MEM_WRITE_DISABLED : MEM_WRITE_INTERNAL; mem_set_mem_state(0xa0000, 0x20000, MEM_READ_INTERNAL | mem_write); - shadowbios = 1; } + shadowbios = 1; } else { for (i = 0; i < 8; i++) { mem_write = (val & 8) ? MEM_WRITE_DISABLED : MEM_WRITE_EXTERNAL; mem_set_mem_state(0xa0000, 0x20000, MEM_READ_EXTERNAL | mem_write); - shadowbios = 0; } + shadowbios = 0; } } - if ((val ^ i82335.reg_22) & 0xe) { + if ((val ^ i82335.reg_22) & 0xe) flushmmucache(); - } if (val & 0x80) { io_removehandler(0x0022, 1, diff --git a/src/devices/system/intel_flash.c b/src/devices/system/intel_flash.c index c9d6657..e8642a3 100644 --- a/src/devices/system/intel_flash.c +++ b/src/devices/system/intel_flash.c @@ -8,7 +8,7 @@ * * Implementation of the Intel 2 Mbit 8-bit flash devices. * - * Version: @(#)intel_flash.c 1.0.6 2018/05/06 + * Version: @(#)intel_flash.c 1.0.7 2018/10/05 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -42,7 +42,6 @@ #include #include #include "../../emu.h" -#include "../../cpu/cpu.h" #include "../../machines/machine.h" #include "../../device.h" #include "../../mem.h" @@ -76,7 +75,7 @@ typedef struct flash_t uint8_t command, status; uint8_t flash_id; int invert_high_pin; - mem_mapping_t mapping[8], mapping_h[8]; + mem_map_t mapping[8], mapping_h[8]; uint32_t block_start[4], block_end[4], block_len[4]; uint8_t array[131072]; } flash_t; @@ -169,8 +168,8 @@ static void intel_flash_add_mappings(flash_t *flash) int i = 0; for (i = 0; i <= 7; i++) { - mem_mapping_add(&(flash->mapping[i]), 0xe0000 + (i << 14), 0x04000, flash_read, flash_readw, flash_readl, flash_write, mem_write_nullw, mem_write_nulll, flash->array + ((i << 14) & 0x1ffff), MEM_MAPPING_EXTERNAL, (void *)flash); - mem_mapping_add(&(flash->mapping_h[i]), 0xfffe0000 + (i << 14), 0x04000, flash_read, flash_readw, flash_readl, flash_write, mem_write_nullw, mem_write_nulll, flash->array + ((i << 14) & 0x1ffff), 0, (void *)flash); + mem_map_add(&(flash->mapping[i]), 0xe0000 + (i << 14), 0x04000, flash_read, flash_readw, flash_readl, flash_write, mem_write_nullw, mem_write_nulll, flash->array + ((i << 14) & 0x1ffff), MEM_MAPPING_EXTERNAL, (void *)flash); + mem_map_add(&(flash->mapping_h[i]), 0xfffe0000 + (i << 14), 0x04000, flash_read, flash_readw, flash_readl, flash_write, mem_write_nullw, mem_write_nulll, flash->array + ((i << 14) & 0x1ffff), 0, (void *)flash); } } @@ -180,8 +179,8 @@ static void intel_flash_add_mappings_inverted(flash_t *flash) int i = 0; for (i = 0; i <= 7; i++) { - mem_mapping_add(&(flash->mapping[i]), 0xe0000 + (i << 14), 0x04000, flash_read, flash_readw, flash_readl, flash_write, mem_write_nullw, mem_write_nulll, flash->array + (((i << 14) ^ 0x10000) & 0x1ffff), MEM_MAPPING_EXTERNAL, (void *)flash); - mem_mapping_add(&(flash->mapping_h[i]), 0xfffe0000 + (i << 14), 0x04000, flash_read, flash_readw, flash_readl, flash_write, mem_write_nullw, mem_write_nulll, flash->array + (((i << 14) ^ 0x10000) & 0x1ffff), 0, (void *)flash); + mem_map_add(&(flash->mapping[i]), 0xe0000 + (i << 14), 0x04000, flash_read, flash_readw, flash_readl, flash_write, mem_write_nullw, mem_write_nulll, flash->array + (((i << 14) ^ 0x10000) & 0x1ffff), MEM_MAPPING_EXTERNAL, (void *)flash); + mem_map_add(&(flash->mapping_h[i]), 0xfffe0000 + (i << 14), 0x04000, flash_read, flash_readw, flash_readl, flash_write, mem_write_nullw, mem_write_nulll, flash->array + (((i << 14) ^ 0x10000) & 0x1ffff), 0, (void *)flash); } } @@ -193,20 +192,18 @@ void *intel_flash_init(uint8_t type) wchar_t *machine_name; wchar_t *flash_name; - flash = malloc(sizeof(flash_t)); + flash = (flash_t *)mem_alloc(sizeof(flash_t)); memset(flash, 0, sizeof(flash_t)); l = strlen(machine_get_internal_name_ex(machine))+1; - machine_name = (wchar_t *) malloc(l * sizeof(wchar_t)); + machine_name = (wchar_t *)mem_alloc(l * sizeof(wchar_t)); mbstowcs(machine_name, machine_get_internal_name_ex(machine), l); l = wcslen(machine_name)+5; - flash_name = (wchar_t *)malloc(l*sizeof(wchar_t)); + flash_name = (wchar_t *)mem_alloc(l*sizeof(wchar_t)); swprintf(flash_name, l, L"%ls.bin", machine_name); wcscpy(flash_path, flash_name); - /* pclog("Flash path: %ls\n", flash_name); */ - flash->flash_id = (type & FLASH_IS_BXB) ? 0x95 : 0x94; flash->invert_high_pin = (type & FLASH_INVERT); @@ -237,8 +234,8 @@ void *intel_flash_init(uint8_t type) } for (i = 0; i < 8; i++) { - mem_mapping_disable(&bios_mapping[i]); - mem_mapping_disable(&bios_high_mapping[i]); + mem_map_disable(&bios_mapping[i]); + mem_map_disable(&bios_high_mapping[i]); } if (flash->invert_high_pin) { diff --git a/src/devices/system/intel_piix.c b/src/devices/system/intel_piix.c index 03ebd97..5a4bf68 100644 --- a/src/devices/system/intel_piix.c +++ b/src/devices/system/intel_piix.c @@ -12,7 +12,7 @@ * word 0 - base address * word 1 - bits 1-15 = byte count, bit 31 = end of transfer * - * Version: @(#)intel_piix.c 1.0.4 2018/05/06 + * Version: @(#)intel_piix.c 1.0.7 2018/10/05 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -42,6 +42,7 @@ */ #include #include +#include #include #include #include "../../emu.h" @@ -51,751 +52,852 @@ #include "../input/keyboard.h" #include "../disk/hdc.h" #include "../disk/hdc_ide.h" -#include "dma.h" +#include "../scsi/scsi_device.h" +#include "../cdrom/cdrom.h" +#include "../disk/zip.h" #include "pci.h" +#include "dma.h" +#include "pic.h" #include "intel_piix.h" -uint8_t piix_33 = 0; - -static uint8_t piix_type = 1; -static uint8_t card_piix[256], card_piix_ide[256]; - - -uint8_t piix_bus_master_read(uint16_t port, void *priv); -void piix_bus_master_write(uint16_t port, uint8_t val, void *priv); - - -void piix_write(int func, int addr, uint8_t val, void *priv) +typedef struct { - uint16_t old_base = (card_piix_ide[0x20] & 0xf0) | (card_piix_ide[0x21] << 8); - if (func > 1) - return; - - if (func == 1) /*IDE*/ - { - /* pclog("PIIX IDE write: %02X %02X\n", addr, val); */ + uint8_t command, status, + ptr0; + uint32_t ptr, ptr_cur, + addr; + int count, eot; +} piix_busmaster_t; - switch (addr) - { - case 0x04: - card_piix_ide[0x04] = (val & 5) | 2; - break; - case 0x07: - card_piix_ide[0x07] = val & 0x3e; - break; - case 0x0d: - card_piix_ide[0x0d] = val; - break; - - case 0x20: - card_piix_ide[0x20] = (val & ~0x0f) | 1; - break; - case 0x21: - card_piix_ide[0x21] = val; - break; - - case 0x40: - card_piix_ide[0x40] = val; - break; - case 0x41: - if ((val ^ card_piix_ide[0x41]) & 0x80) - { - ide_pri_disable(); - if (val & 0x80) - ide_pri_enable(); - } - card_piix_ide[0x41] = val; - break; - case 0x42: - card_piix_ide[0x42] = val; - break; - case 0x43: - if ((val ^ card_piix_ide[0x43]) & 0x80) - { - ide_sec_disable(); - if (val & 0x80) - ide_sec_enable(); - } - card_piix_ide[0x43] = val; - break; - case 0x44: - if (piix_type >= 3) card_piix_ide[0x44] = val; - break; - } - if (addr == 4 || (addr & ~3) == 0x20) /*Bus master base address*/ - { - uint16_t base = (card_piix_ide[0x20] & 0xf0) | (card_piix_ide[0x21] << 8); - if (old_base) - io_removehandler(old_base, 0x10, piix_bus_master_read, NULL, NULL, piix_bus_master_write, NULL, NULL, NULL); - if ((card_piix_ide[0x04] & 1) && base) - io_sethandler(base, 0x10, piix_bus_master_read, NULL, NULL, piix_bus_master_write, NULL, NULL, NULL); - } - } - else - { - /* pclog("PIIX writing value %02X to register %02X\n", val, addr); */ - if ((addr >= 0x0f) && (addr < 0x4c)) - return; +typedef struct +{ + int type; + uint8_t regs[256], regs_ide[256]; + piix_busmaster_t bm[2]; +} piix_t; - switch (addr) - { - case 0x00: case 0x01: case 0x02: case 0x03: - case 0x08: case 0x09: case 0x0a: case 0x0b: - case 0x0e: - return; - - case 0x60: - /* pclog("Set IRQ routing: INT A -> %02X\n", val); */ - if (val & 0x80) - pci_set_irq_routing(PCI_INTA, PCI_IRQ_DISABLED); - else - pci_set_irq_routing(PCI_INTA, val & 0xf); - break; - case 0x61: - /* pclog("Set IRQ routing: INT B -> %02X\n", val); */ - if (val & 0x80) - pci_set_irq_routing(PCI_INTB, PCI_IRQ_DISABLED); - else - pci_set_irq_routing(PCI_INTB, val & 0xf); - break; - case 0x62: - /* pclog("Set IRQ routing: INT C -> %02X\n", val); */ - if (val & 0x80) - pci_set_irq_routing(PCI_INTC, PCI_IRQ_DISABLED); - else - pci_set_irq_routing(PCI_INTC, val & 0xf); - break; - case 0x63: - /* pclog("Set IRQ routing: INT D -> %02X\n", val); */ - if (val & 0x80) - pci_set_irq_routing(PCI_INTD, PCI_IRQ_DISABLED); - else - pci_set_irq_routing(PCI_INTD, val & 0xf); - break; - case 0x70: - /* pclog("Set MIRQ routing: MIRQ0 -> %02X\n", val); */ - if (val & 0x80) - pci_set_mirq_routing(PCI_MIRQ0, PCI_IRQ_DISABLED); - else - pci_set_mirq_routing(PCI_MIRQ0, val & 0xf); - break; - /* pclog("MIRQ0 is %s\n", (val & 0x20) ? "disabled" : "enabled"); */ - case 0x71: - if (piix_type == 1) - { - /* pclog("Set MIRQ routing: MIRQ1 -> %02X\n", val); */ - if (val & 0x80) - pci_set_mirq_routing(PCI_MIRQ1, PCI_IRQ_DISABLED); - else - pci_set_mirq_routing(PCI_MIRQ1, val & 0xf); - } -#if 0 - else - { - pclog("Set unused MIRQ routing: MIRQ1 -> %02X\n", val); - } -#endif - break; - } - if (addr == 0x4C) - { - if (!((val ^ card_piix[addr]) & 0x80)) - { - card_piix[addr] = val; - return; - } - card_piix[addr] = val; - if (val & 0x80) - { - if (piix_type == 3) - { - dma_alias_remove(); - } - else - { - dma_alias_remove_piix(); - } - } - else - { - dma_alias_set(); - } - } - else if (addr == 0x4E) - { - keyboard_at_set_mouse_scan((val & 0x10) ? 1 : 0); - card_piix[addr] = val; - } - else if (addr == 0x6A) - { - if (piix_type == 1) - card_piix[addr] = (val & 0xFC) | (card_piix[addr] | 3); - else if (piix_type == 3) - card_piix[addr] = (val & 0xFD) | (card_piix[addr] | 2); - } - else - card_piix[addr] = val; - } +static uint8_t piix_bus_master_read(uint16_t port, void *priv); +static uint16_t piix_bus_master_readw(uint16_t port, void *priv); +static uint32_t piix_bus_master_readl(uint16_t port, void *priv); +static void piix_bus_master_write(uint16_t port, uint8_t val, void *priv); +static void piix_bus_master_writew(uint16_t port, uint16_t val, void *priv); +static void piix_bus_master_writel(uint16_t port, uint32_t val, void *priv); + + +static void +piix_bus_master_handlers(piix_t *dev, uint16_t old_base) +{ + uint16_t base; + + base = (dev->regs_ide[0x20] & 0xf0) | (dev->regs_ide[0x21] << 8); + io_removehandler(old_base, 0x08, + piix_bus_master_read, piix_bus_master_readw, piix_bus_master_readl, + piix_bus_master_write, piix_bus_master_writew, piix_bus_master_writel, + &dev->bm[0]); + io_removehandler(old_base + 8, 0x08, + piix_bus_master_read, piix_bus_master_readw, piix_bus_master_readl, + piix_bus_master_write, piix_bus_master_writew, piix_bus_master_writel, + &dev->bm[1]); + + if ((dev->regs_ide[0x04] & 1) && base) { + io_sethandler(base, 0x08, + piix_bus_master_read, piix_bus_master_readw, piix_bus_master_readl, + piix_bus_master_write, piix_bus_master_writew, piix_bus_master_writel, + &dev->bm[0]); + io_sethandler(base + 8, 0x08, + piix_bus_master_read, piix_bus_master_readw, piix_bus_master_readl, + piix_bus_master_write, piix_bus_master_writew, piix_bus_master_writel, + &dev->bm[1]); + } } -uint8_t piix_read(int func, int addr, void *priv) -{ - if (func > 1) - return 0xff; - if (func == 1) /*IDE*/ - { - if (addr == 4) - { - return (card_piix_ide[addr] & 5) | 2; - } - else if (addr == 5) - { - return 0; - } - else if (addr == 6) - { - return 0x80; - } - else if (addr == 7) - { - return card_piix_ide[addr] & 0x3E; - } - else if (addr == 0xD) - { - return card_piix_ide[addr] & 0xF0; - } - else if (addr == 0x20) - { - return (card_piix_ide[addr] & 0xF0) | 1; - } - else if (addr == 0x22) - { - return 0; - } - else if (addr == 0x23) - { - return 0; - } - else if (addr == 0x41) - { - if (piix_type == 1) - return card_piix_ide[addr] & 0xB3; - else if (piix_type == 3) - return card_piix_ide[addr] & 0xF3; - } - else if (addr == 0x43) - { - if (piix_type == 1) - return card_piix_ide[addr] & 0xB3; - else if (piix_type == 3) - return card_piix_ide[addr] & 0xF3; - } - else - { - return card_piix_ide[addr]; - } - } - else - { - if ((addr & 0xFC) == 0x60) - { - return card_piix[addr] & 0x8F; - } - if (addr == 4) - { - return (card_piix[addr] & 0x80) | 7; - } - else if (addr == 5) - { - if (piix_type == 1) - return 0; - else if (piix_type == 3) - return card_piix[addr] & 1; - } - else if (addr == 6) - { - return card_piix[addr] & 0x80; - } - else if (addr == 7) - { - if (piix_type == 1) - return card_piix[addr] & 0x3E; - else if (piix_type == 3) - return card_piix[addr]; - } - else if (addr == 0x4E) - { - return (card_piix[addr] & 0xEF) | keyboard_at_get_mouse_scan(); - } - else if (addr == 0x69) - { - return card_piix[addr] & 0xFE; - } - else if (addr == 0x6A) - { - if (piix_type == 1) - return card_piix[addr] & 0x07; - else if (piix_type == 3) - return card_piix[addr] & 0xD1; - } - else if (addr == 0x6B) - { - if (piix_type == 1) - return 0; - else if (piix_type == 3) - return card_piix[addr] & 0x80; - } - else if (addr == 0x70) - { - if (piix_type == 1) - return card_piix[addr] & 0xCF; - else if (piix_type == 3) - return card_piix[addr] & 0xEF; - } - else if (addr == 0x71) - { - if (piix_type == 1) - return card_piix[addr] & 0xCF; - else if (piix_type == 3) - return 0; - } - else if (addr == 0x76) - { - if (piix_type == 1) - return card_piix[addr] & 0x8F; - else if (piix_type == 3) - return card_piix[addr] & 0x87; - } - else if (addr == 0x77) - { - if (piix_type == 1) - return card_piix[addr] & 0x8F; - else if (piix_type == 3) - return card_piix[addr] & 0x87; - } - else if (addr == 0x80) - { - if (piix_type == 1) - return 0; - else if (piix_type == 3) - return card_piix[addr] & 0x7F; - } - else if (addr == 0x82) - { - if (piix_type == 1) - return 0; - else if (piix_type == 3) - return card_piix[addr] & 0x0F; - } - else if (addr == 0xA0) - { - return card_piix[addr] & 0x1F; - } - else if (addr == 0xA3) - { - if (piix_type == 1) - return 0; - else if (piix_type == 3) - return card_piix[addr] & 1; - } - else if (addr == 0xA7) - { - if (piix_type == 1) - return card_piix[addr] & 0xEF; - else if (piix_type == 3) - return card_piix[addr]; - } - else if (addr == 0xAB) - { - if (piix_type == 1) - return card_piix[addr] & 0xFE; - else if (piix_type == 3) - return card_piix[addr]; - } - else - return card_piix[addr]; +static void +piix_write(int func, int addr, uint8_t val, void *priv) +{ + piix_t *dev = (piix_t *) priv; + uint8_t valxor; + + uint16_t old_base = (dev->regs_ide[0x20] & 0xf0) | (dev->regs_ide[0x21] << 8); + if (func > 1) + return; + + if (func == 1) { /*IDE*/ + DBGLOG(1, "PIIX IDE write: %02X %02X\n", addr, val); + valxor = val ^ dev->regs_ide[addr]; + + switch (addr) { + case 0x04: + dev->regs_ide[0x04] = (val & 5) | 2; + if (valxor & 0x01) { + ide_pri_disable(); + ide_sec_disable(); + if (val & 0x01) { + if (dev->regs_ide[0x41] & 0x80) + ide_pri_enable(); + if (dev->regs_ide[0x43] & 0x80) + ide_sec_enable(); + } + + piix_bus_master_handlers(dev, old_base); + } + break; + case 0x07: + dev->regs_ide[0x07] = val & 0x3e; + break; + case 0x0d: + dev->regs_ide[0x0d] = val; + break; + + case 0x20: + dev->regs_ide[0x20] = (val & ~0x0f) | 1; + if (valxor) + piix_bus_master_handlers(dev, old_base); + break; + case 0x21: + dev->regs_ide[0x21] = val; + if (valxor) + piix_bus_master_handlers(dev, old_base); + break; + + case 0x40: + dev->regs_ide[0x40] = val; + break; + case 0x41: + dev->regs_ide[0x41] = val; + if (valxor & 0x80) { + ide_pri_disable(); + if ((val & 0x80) && (dev->regs_ide[0x04] & 0x01)) + ide_pri_enable(); + } + break; + case 0x42: + dev->regs_ide[0x42] = val; + break; + case 0x43: + dev->regs_ide[0x43] = val; + if (valxor & 0x80) { + ide_sec_disable(); + if ((val & 0x80) && (dev->regs_ide[0x04] & 0x01)) + ide_sec_enable(); + } + break; + case 0x44: + if (dev->type >= 3) dev->regs_ide[0x44] = val; + break; + } + } else { + DBGLOG(1, "PIIX writing value %02X to register %02X\n", val, addr); + valxor = val ^ dev->regs[addr]; + + if ((addr >= 0x0f) && (addr < 0x4c)) + return; + + switch (addr) { + case 0x00: case 0x01: case 0x02: case 0x03: + case 0x08: case 0x09: case 0x0a: case 0x0b: + case 0x0e: + return; + + case 0x4c: + if (valxor) { + if (val & 0x80) { + if (dev->type == 3) + dma_alias_remove(); + else + dma_alias_remove_piix(); + } else + dma_alias_set(); + } + break; + case 0x4e: + keyboard_at_set_mouse_scan((val & 0x10) ? 1 : 0); + break; + case 0x60: + DBGLOG(1, "Set IRQ routing: INT A -> %02X\n", val); + if (val & 0x80) + pci_set_irq_routing(PCI_INTA, PCI_IRQ_DISABLED); + else + pci_set_irq_routing(PCI_INTA, val & 0xf); + break; + case 0x61: + DBGLOG(1, "Set IRQ routing: INT B -> %02X\n", val); + if (val & 0x80) + pci_set_irq_routing(PCI_INTB, PCI_IRQ_DISABLED); + else + pci_set_irq_routing(PCI_INTB, val & 0xf); + break; + case 0x62: + DBGLOG(1, "Set IRQ routing: INT C -> %02X\n", val); + if (val & 0x80) + pci_set_irq_routing(PCI_INTC, PCI_IRQ_DISABLED); + else + pci_set_irq_routing(PCI_INTC, val & 0xf); + break; + case 0x63: + DBGLOG(1, "Set IRQ routing: INT D -> %02X\n", val); + if (val & 0x80) + pci_set_irq_routing(PCI_INTD, PCI_IRQ_DISABLED); + else + pci_set_irq_routing(PCI_INTD, val & 0xf); + break; + case 0x6a: + if (dev->type == 3) + dev->regs[addr] = (val & 0xFD) | (dev->regs[addr] | 2); + else + dev->regs[addr] = (val & 0xFC) | (dev->regs[addr] | 3); + return; + case 0x70: + DBGLOG(1, "Set MIRQ routing: MIRQ0 -> %02X\n", val); + if (val & 0x80) + pci_set_mirq_routing(PCI_MIRQ0, PCI_IRQ_DISABLED); + else + pci_set_mirq_routing(PCI_MIRQ0, val & 0xf); + break; + DBGLOG(1, "MIRQ0 is %s\n", (val & 0x20) ? "disabled" : "enabled"); + case 0x71: + if (dev->type == 1) { + DBGLOG(1, "Set MIRQ routing: MIRQ1 -> %02X\n", val); + if (val & 0x80) + pci_set_mirq_routing(PCI_MIRQ1, PCI_IRQ_DISABLED); + else + pci_set_mirq_routing(PCI_MIRQ1, val & 0xf); + } + break; } - return 0; + dev->regs[addr] = val; + } } -struct -{ - uint8_t command; - uint8_t status; - uint32_t ptr, ptr_cur; - int count; - uint32_t addr; - int eot; - uint8_t ptr0; -} piix_busmaster[2]; -static void piix_bus_master_next_addr(int channel) +static uint8_t +piix_read(int func, int addr, void *priv) { - DMAPageRead(piix_busmaster[channel].ptr_cur, (uint8_t *)&(piix_busmaster[channel].addr), 4); - DMAPageRead(piix_busmaster[channel].ptr_cur + 4, (uint8_t *)&(piix_busmaster[channel].count), 4); -#if 0 - pclog("PIIX Bus master DWORDs: %08X %08X\n", piix_busmaster[channel].addr, piix_busmaster[channel].count); + piix_t *dev = (piix_t *) priv; + + if ((func == 1) && (dev->type & 0x100)) /* PB640's PIIX has no IDE part. */ + return 0xff; + if (func > 1) + return 0xff; + + if (func == 1) { /*IDE*/ + if (addr == 4) + return (dev->regs_ide[addr] & 5) | 2; + else if (addr == 5) + return 0; + else if (addr == 6) + return 0x80; + else if (addr == 7) + return dev->regs_ide[addr] & 0x3E; + else if (addr == 0xD) + return dev->regs_ide[addr] & 0xF0; + else if (addr == 0x20) + return (dev->regs_ide[addr] & 0xF0) | 1; + else if (addr == 0x22) + return 0; + else if (addr == 0x23) + return 0; + else if (addr == 0x41) { + if (dev->type == 3) + return dev->regs_ide[addr] & 0xF3; + else + return dev->regs_ide[addr] & 0xB3; + } else if (addr == 0x43) { + if (dev->type == 3) + return dev->regs_ide[addr] & 0xF3; + else + return dev->regs_ide[addr] & 0xB3; + } else + return dev->regs_ide[addr]; + } else { + if ((addr & 0xFC) == 0x60) + return dev->regs[addr] & 0x8F; + + if (addr == 4) { + if (dev->type & 0x100) + return (dev->regs[addr] & 0x80) | 0x0F; + else + return (dev->regs[addr] & 0x80) | 7; + } else if (addr == 5) { + if (dev->type == 3) + return dev->regs[addr] & 1; + else + return 0; + } else if (addr == 6) + return dev->regs[addr] & 0x80; + else if (addr == 7) { + if (dev->type == 3) + return dev->regs[addr]; + else { + if (dev->type & 0x100) + return dev->regs[addr] & 0x02; + else + return dev->regs[addr] & 0x3E; + } + } else if (addr == 0x4E) + return (dev->regs[addr] & 0xEF) | keyboard_at_get_mouse_scan(); + else if (addr == 0x69) + return dev->regs[addr] & 0xFE; + else if (addr == 0x6A) { + if (dev->type == 3) + return dev->regs[addr] & 0xD1; + else + return dev->regs[addr] & 0x07; + } else if (addr == 0x6B) { + if (dev->type == 3) + return dev->regs[addr] & 0x80; + else + return 0; + } + else if (addr == 0x70) { + if (dev->type == 3) + return dev->regs[addr] & 0xEF; + else + return dev->regs[addr] & 0xCF; + } else if (addr == 0x71) { + if (dev->type == 3) + return 0; + else + return dev->regs[addr] & 0xCF; + } else if (addr == 0x76) { + if (dev->type == 3) + return dev->regs[addr] & 0x87; + else + return dev->regs[addr] & 0x8F; + } else if (addr == 0x77) { + if (dev->type == 3) + return dev->regs[addr] & 0x87; + else + return dev->regs[addr] & 0x8F; + } else if (addr == 0x80) { + if (dev->type == 3) + return dev->regs[addr] & 0x7F; + else if (dev->type == 1) + return 0; + } else if (addr == 0x82) { + if (dev->type == 3) + return dev->regs[addr] & 0x0F; + else + return 0; + } else if (addr == 0xA0) + return dev->regs[addr] & 0x1F; + else if (addr == 0xA3) { + if (dev->type == 3) + return dev->regs[addr] & 1; + else + return 0; + } else if (addr == 0xA7) { + if (dev->type == 3) + return dev->regs[addr]; + else + return dev->regs[addr] & 0xEF; + } else if (addr == 0xAB) { + if (dev->type == 3) + return dev->regs[addr]; + else + return dev->regs[addr] & 0xFE; + } else + return dev->regs[addr]; + } + + return 0; +} + + +static void +piix_bus_master_next_addr(piix_busmaster_t *dev) +{ + DMAPageRead(dev->ptr_cur, (uint8_t *)&(dev->addr), 4); + DMAPageRead(dev->ptr_cur + 4, (uint8_t *)&(dev->count), 4); + DBGLOG(1, "PIIX Bus master DWORDs: %08X %08X\n", dev->addr, dev->count); + dev->eot = dev->count >> 31; + dev->count &= 0xfffe; + if (!dev->count) + dev->count = 65536; + dev->addr &= 0xfffffffe; + dev->ptr_cur += 8; +} + + +static void +piix_bus_master_write(uint16_t port, uint8_t val, void *priv) +{ + piix_busmaster_t *dev = (piix_busmaster_t *) priv; +#ifdef _LOGGING + int channel = (port & 8) ? 1 : 0; #endif - piix_busmaster[channel].eot = piix_busmaster[channel].count >> 31; - piix_busmaster[channel].count &= 0xfffe; - if (!piix_busmaster[channel].count) - piix_busmaster[channel].count = 65536; - piix_busmaster[channel].addr &= 0xfffffffe; - piix_busmaster[channel].ptr_cur += 8; -} -void piix_bus_master_write(uint16_t port, uint8_t val, void *priv) -{ - /* pclog("PIIX Bus master write: %04X %02X\n", port, val); */ - int channel = (port & 8) ? 1 : 0; - switch (port & 7) { - case 0: - if ((val & 1) && !(piix_busmaster[channel].command & 1)) { /*Start*/ - piix_busmaster[channel].ptr_cur = piix_busmaster[channel].ptr; - piix_bus_master_next_addr(channel); - piix_busmaster[channel].status |= 1; - } - if (!(val & 1) && (piix_busmaster[channel].command & 1)) /*Stop*/ - piix_busmaster[channel].status &= ~1; - - piix_busmaster[channel].command = val; - break; - case 2: - piix_busmaster[channel].status &= 0x07; - piix_busmaster[channel].status |= (val & 0x60); + DBGLOG(1, "PIIX Bus master BYTE write: %04X %02X\n", port, val); + + switch (port & 7) { + case 0: + DBGLOG(1, "PIIX Cmd : val = %02X, old = %02X\n", val, dev->command); + if ((val & 1) && !(dev->command & 1)) { /*Start*/ + DBGLOG(1, "PIIX Bus Master start on channel %i\n", channel); + dev->ptr_cur = dev->ptr; + piix_bus_master_next_addr(dev); + dev->status |= 1; + } + if (!(val & 1) && (dev->command & 1)) { /*Stop*/ + DBGLOG(1, "PIIX Bus Master stop on channel %i\n", channel); + dev->status &= ~1; + } + + dev->command = val; + break; + case 2: + DBGLOG(1, "PIIX Status: val = %02X, old = %02X\n", val, dev->status); + dev->status &= 0x07; + dev->status |= (val & 0x60); if (val & 0x04) - piix_busmaster[channel].status &= ~0x04; + dev->status &= ~0x04; if (val & 0x02) - piix_busmaster[channel].status &= ~0x02; - /* piix_busmaster[channel].status = (val & 0x60) | ((piix_busmaster[channel].status & ~val) & 6) | (piix_busmaster[channel].status & 1); */ - break; - case 4: - piix_busmaster[channel].ptr = (piix_busmaster[channel].ptr & 0xffffff00) | (val & 0xfc); - piix_busmaster[channel].ptr %= (mem_size * 1024); - piix_busmaster[channel].ptr0 = val; - break; - case 5: - piix_busmaster[channel].ptr = (piix_busmaster[channel].ptr & 0xffff00fc) | (val << 8); - piix_busmaster[channel].ptr %= (mem_size * 1024); - break; - case 6: - piix_busmaster[channel].ptr = (piix_busmaster[channel].ptr & 0xff00fffc) | (val << 16); - piix_busmaster[channel].ptr %= (mem_size * 1024); - break; - case 7: - piix_busmaster[channel].ptr = (piix_busmaster[channel].ptr & 0x00fffffc) | (val << 24); - piix_busmaster[channel].ptr %= (mem_size * 1024); - break; - - } -} - -uint8_t piix_bus_master_read(uint16_t port, void *priv) -{ - /* pclog("PIIX Bus master read: %04X\n", port); */ - int channel = (port & 8) ? 1 : 0; - switch (port & 7) { - case 0: - return piix_busmaster[channel].command; - case 2: - return piix_busmaster[channel].status & 0x67; - case 4: - return piix_busmaster[channel].ptr0; - case 5: - return piix_busmaster[channel].ptr >> 8; - case 6: - return piix_busmaster[channel].ptr >> 16; - case 7: - return piix_busmaster[channel].ptr >> 24; - } - return 0xff; + dev->status &= ~0x02; + break; + case 4: + dev->ptr = (dev->ptr & 0xffffff00) | (val & 0xfc); + dev->ptr %= (mem_size * 1024); + dev->ptr0 = val; + break; + case 5: + dev->ptr = (dev->ptr & 0xffff00fc) | (val << 8); + dev->ptr %= (mem_size * 1024); + break; + case 6: + dev->ptr = (dev->ptr & 0xff00fffc) | (val << 16); + dev->ptr %= (mem_size * 1024); + break; + case 7: + dev->ptr = (dev->ptr & 0x00fffffc) | (val << 24); + dev->ptr %= (mem_size * 1024); + break; + } } -int piix_bus_master_get_count(int channel) + +static void +piix_bus_master_writew(uint16_t port, uint16_t val, void *priv) { - return piix_busmaster[channel].count; + piix_busmaster_t *dev = (piix_busmaster_t *) priv; + + DBGLOG(1, "PIIX Bus master WORD write: %04X %04X\n", port, val); + + switch (port & 7) { + case 0: + case 2: + piix_bus_master_write(port, val & 0xff, priv); + break; + case 4: + dev->ptr = (dev->ptr & 0xffff0000) | (val & 0xfffc); + dev->ptr %= (mem_size * 1024); + dev->ptr0 = val & 0xff; + break; + case 6: + dev->ptr = (dev->ptr & 0x0000fffc) | (val << 16); + dev->ptr %= (mem_size * 1024); + break; + } } -int piix_bus_master_get_eot(int channel) + +static void +piix_bus_master_writel(uint16_t port, uint32_t val, void *priv) { - return piix_busmaster[channel].eot; + piix_busmaster_t *dev = (piix_busmaster_t *) priv; + + DBGLOG(1, "PIIX Bus master DWORD write: %04X %08X\n", port, val); + + switch (port & 7) { + case 0: + case 2: + piix_bus_master_write(port, val & 0xff, priv); + break; + case 4: + dev->ptr = (val & 0xfffffffc); + dev->ptr %= (mem_size * 1024); + dev->ptr0 = val & 0xff; + break; + } } -int piix_bus_master_dma_read(int channel, uint8_t *data, int transfer_length) + +static uint8_t +piix_bus_master_read(uint16_t port, void *priv) { - int force_end = 0; - int buffer_pos = 0; - - if (!(piix_busmaster[channel].status & 1)) - return 1; /*DMA disabled*/ + piix_busmaster_t *dev = (piix_busmaster_t *) priv; -#if 0 - pclog("PIIX Bus master read: %i bytes\n", transfer_length); + uint8_t ret = 0xff; + + switch (port & 7) { + case 0: + ret = dev->command; + break; + case 2: + ret = dev->status & 0x67; + break; + case 4: + ret = dev->ptr0; + break; + case 5: + ret = dev->ptr >> 8; + break; + case 6: + ret = dev->ptr >> 16; + break; + case 7: + ret = dev->ptr >> 24; + break; + } + + DBGLOG(1, "PIIX Bus master BYTE read : %04X %02X\n", port, ret); + + return ret; +} + + +static uint16_t +piix_bus_master_readw(uint16_t port, void *priv) +{ + piix_busmaster_t *dev = (piix_busmaster_t *) priv; + + uint16_t ret = 0xffff; + + switch (port & 7) { + case 0: + case 2: + ret = (uint16_t) piix_bus_master_read(port, priv); + break; + case 4: + ret = dev->ptr0 | (dev->ptr & 0xff00); + break; + case 6: + ret = dev->ptr >> 16; + break; + } + + DBGLOG(1, "PIIX Bus master WORD read : %04X %04X\n", port, ret); + + return ret; +} + + +static uint32_t +piix_bus_master_readl(uint16_t port, void *priv) +{ + piix_busmaster_t *dev = (piix_busmaster_t *) priv; + + uint32_t ret = 0xffffffff; + + switch (port & 7) { + case 0: + case 2: + ret = (uint32_t) piix_bus_master_read(port, priv); + break; + case 4: + ret = dev->ptr0 | (dev->ptr & 0xffffff00); + break; + } + + DBGLOG(1, "PIIX Bus master DWORD read : %04X %08X\n", port, ret); + + return ret; +} + + +static int +piix_bus_master_dma_op(int channel, uint8_t *data, int transfer_length, int out, void *priv) +{ + piix_busmaster_t *dev = (piix_busmaster_t *) priv; + int force_end = 0, buffer_pos = 0; +#ifdef _LOGGING + char *sop = out ? "Writ" : "Read"; #endif - while (1) { - if (piix_busmaster[channel].count <= transfer_length) { -#if 0 - pclog("Writing %i bytes to %08X\n", piix_busmaster[channel].count, piix_busmaster[channel].addr); -#endif - DMAPageWrite(piix_busmaster[channel].addr, (uint8_t *)(data + buffer_pos), piix_busmaster[channel].count); - transfer_length -= piix_busmaster[channel].count; - buffer_pos += piix_busmaster[channel].count; - } else { -#if 0 - pclog("Writing %i bytes to %08X\n", piix_busmaster[channel].count, piix_busmaster[channel].addr); -#endif - DMAPageWrite(piix_busmaster[channel].addr, (uint8_t *)(data + buffer_pos), transfer_length); - transfer_length = 0; - force_end = 1; - } + if (! (dev->status & 1)) + return 2; /*DMA disabled*/ - if (force_end) { -#if 0 - pclog("Total transfer length smaller than sum of all blocks, partial block\n"); -#endif - piix_busmaster[channel].status &= ~2; - return 0; /* This block has exhausted the data to transfer and it was smaller than the count, break. */ + DBGLOG(1, "PIIX Bus master %s: %i bytes\n", out ? "read" : "write", transfer_length); + + while (1) { + if (dev->count <= transfer_length) { + DBGLOG(1, "%sing %i bytes to %08X\n", sop, dev->count, dev->addr); + if (out) + DMAPageWrite(dev->addr, (uint8_t *)(data + buffer_pos), dev->count); + else + DMAPageRead(dev->addr, (uint8_t *)(data + buffer_pos), dev->count); + transfer_length -= dev->count; + buffer_pos += dev->count; + } else { + DBGLOG(1, "%sing %i bytes to %08X\n", sop, transfer_length, dev->addr); + if (out) + DMAPageWrite(dev->addr, (uint8_t *)(data + buffer_pos), transfer_length); + else + DMAPageRead(dev->addr, (uint8_t *)(data + buffer_pos), transfer_length); + /* Increase addr and decrease count so that resumed transfers do not mess up. */ + dev->addr += transfer_length; + dev->count -= transfer_length; + transfer_length = 0; + force_end = 1; + } + + if (force_end) { + DBGLOG(1, "Total transfer length smaller than sum of all blocks, partial block\n"); + dev->status &= ~2; + return 0; /* This block has exhausted the data to transfer and it was smaller than the count, break. */ + } else { + if (!transfer_length && !dev->eot) { + DBGLOG(1, "Total transfer length smaller than sum of all blocks, full block\n"); + dev->status &= ~2; + return 0; /* We have exhausted the data to transfer but there's more blocks left, break. */ + } else if (transfer_length && dev->eot) { + DBGLOG(1, "Total transfer length greater than sum of all blocks\n"); + dev->status |= 2; + return 1; /* There is data left to transfer but we have reached EOT - return with error. */ + } else if (dev->eot) { + DBGLOG(1, "Regular EOT\n"); + dev->status &= ~3; + return 0; /* We have regularly reached EOT - clear status and break. */ } else { - if (!transfer_length && !piix_busmaster[channel].eot) { -#if 0 - pclog("Total transfer length smaller than sum of all blocks, full block\n"); -#endif - piix_busmaster[channel].status &= ~2; - return 0; /* We have exhausted the data to transfer but there's more blocks left, break. */ - } else if (transfer_length && piix_busmaster[channel].eot) { -#if 0 - pclog("Total transfer length greater than sum of all blocks\n"); -#endif - piix_busmaster[channel].status |= 2; - return 1; /* There is data left to transfer but we have reached EOT - return with error. */ - } else if (piix_busmaster[channel].eot) { -#if 0 - pclog("Regular EOT\n"); -#endif - piix_busmaster[channel].status &= ~3; - return 0; /* We have regularly reached EOT - clear status and break. */ - } else { - /* We have more to transfer and there are blocks left, get next block. */ - piix_bus_master_next_addr(channel); - } + /* We have more to transfer and there are blocks left, get next block. */ + piix_bus_master_next_addr(dev); } - } - return 0; -} - -int piix_bus_master_dma_write(int channel, uint8_t *data, int transfer_length) -{ - int force_end = 0; - int buffer_pos = 0; - - if (!(piix_busmaster[channel].status & 1)) - return 1; /*DMA disabled*/ - -#if 0 - pclog("PIIX Bus master write: %i bytes\n", transfer_length); -#endif - - while (1) { - if (piix_busmaster[channel].count <= transfer_length) { -#if 0 - pclog("Reading %i bytes from %08X\n", piix_busmaster[channel].count, piix_busmaster[channel].addr); -#endif - DMAPageRead(piix_busmaster[channel].addr, (uint8_t *)(data + buffer_pos), piix_busmaster[channel].count); - transfer_length -= piix_busmaster[channel].count; - buffer_pos += piix_busmaster[channel].count; - } else { -#if 0 - pclog("Reading %i bytes from %08X\n", piix_busmaster[channel].count, piix_busmaster[channel].addr); -#endif - DMAPageRead(piix_busmaster[channel].addr, (uint8_t *)(data + buffer_pos), transfer_length); - transfer_length = 0; - force_end = 1; - } - - if (force_end) { -#if 0 - pclog("Total transfer length smaller than sum of all blocks, partial block\n"); -#endif - piix_busmaster[channel].status &= ~2; - return 0; /* This block has exhausted the data to transfer and it was smaller than the count, break. */ - } else { - if (!transfer_length && !piix_busmaster[channel].eot) { -#if 0 - pclog("Total transfer length smaller than sum of all blocks, full block\n"); -#endif - piix_busmaster[channel].status &= ~2; - return 0; /* We have exhausted the data to transfer but there's more blocks left, break. */ - } else if (transfer_length && piix_busmaster[channel].eot) { -#if 0 - pclog("Total transfer length greater than sum of all blocks\n"); -#endif - piix_busmaster[channel].status |= 2; - return 1; /* There is data left to transfer but we have reached EOT - return with error. */ - } else if (piix_busmaster[channel].eot) { -#if 0 - pclog("Regular EOT\n"); -#endif - piix_busmaster[channel].status &= ~3; - return 0; /* We have regularly reached EOT - clear status and break. */ - } else { - /* We have more to transfer and there are blocks left, get next block. */ - piix_bus_master_next_addr(channel); - } - } - } - return 0; -} - -void piix_bus_master_set_irq(int channel) -{ - // piix_busmaster[channel].status |= 4; - piix_busmaster[channel & 0x0F].status &= ~4; - piix_busmaster[channel & 0x0F].status |= (channel >> 4); + } + } + return 0; } -static void piix_bus_master_reset(void) +int +piix_bus_master_dma_read(int channel, uint8_t *data, int transfer_length, void *priv) { - uint16_t old_base = (card_piix_ide[0x20] & 0xf0) | (card_piix_ide[0x21] << 8); - if (old_base) - io_removehandler(old_base, 0x10, piix_bus_master_read, NULL, NULL, piix_bus_master_write, NULL, NULL, NULL); + return piix_bus_master_dma_op(channel, data, transfer_length, 1, priv); } -void piix_reset(void) +int +piix_bus_master_dma_write(int channel, uint8_t *data, int transfer_length, void *priv) { - piix_bus_master_reset(); - memset(card_piix, 0, 256); - card_piix[0x00] = 0x86; card_piix[0x01] = 0x80; /*Intel*/ - card_piix[0x02] = 0x2e; card_piix[0x03] = 0x12; /*82371FB (PIIX)*/ - card_piix[0x04] = 0x07; card_piix[0x05] = 0x00; - card_piix[0x06] = 0x80; card_piix[0x07] = 0x02; - card_piix[0x08] = 0x00; /*A0 stepping*/ - card_piix[0x09] = 0x00; card_piix[0x0a] = 0x01; card_piix[0x0b] = 0x06; - card_piix[0x0e] = 0x80; /*Multi-function device*/ - card_piix[0x4c] = 0x4d; - card_piix[0x4e] = 0x03; - card_piix[0x60] = card_piix[0x61] = card_piix[0x62] = card_piix[0x63] = 0x80; - card_piix[0x69] = 0x02; - card_piix[0x70] = card_piix[0x71] = 0xc0; - card_piix[0x76] = card_piix[0x77] = 0x0c; - card_piix[0x78] = 0x02; card_piix[0x79] = 0x00; - card_piix[0xa0] = 0x08; - card_piix[0xa2] = card_piix[0xa3] = 0x00; - card_piix[0xa4] = card_piix[0xa5] = card_piix[0xa6] = card_piix[0xa7] = 0x00; - card_piix[0xa8] = 0x0f; - card_piix[0xaa] = card_piix[0xab] = 0x00; - card_piix[0xac] = 0x00; - card_piix[0xae] = 0x00; + return piix_bus_master_dma_op(channel, data, transfer_length, 0, priv); +} - card_piix_ide[0x00] = 0x86; card_piix_ide[0x01] = 0x80; /*Intel*/ - card_piix_ide[0x02] = 0x30; card_piix_ide[0x03] = 0x12; /*82371FB (PIIX)*/ - card_piix_ide[0x04] = 0x07; card_piix_ide[0x05] = 0x00; - card_piix_ide[0x06] = 0x80; card_piix_ide[0x07] = 0x02; - card_piix_ide[0x08] = 0x00; - card_piix_ide[0x09] = 0x80; card_piix_ide[0x0a] = 0x01; card_piix_ide[0x0b] = 0x01; - card_piix_ide[0x0d] = 0x00; - card_piix_ide[0x0e] = 0x00; - card_piix_ide[0x20] = 0x01; card_piix_ide[0x21] = card_piix_ide[0x22] = card_piix_ide[0x23] = 0x00; /*Bus master interface base address*/ - card_piix_ide[0x40] = card_piix_ide[0x42] = 0x00; - card_piix_ide[0x41] = card_piix_ide[0x43] = 0x80; - pci_set_mirq_routing(PCI_MIRQ0, PCI_IRQ_DISABLED); +void +piix_bus_master_set_irq(int channel, void *priv) +{ + piix_busmaster_t *dev = (piix_busmaster_t *) priv; + dev->status &= ~4; + dev->status |= (channel >> 4); + + channel &= 0x01; + if (dev->status & 0x04) { + if (channel && pci_use_mirq(0)) + pci_set_mirq(0); + else + picint(1 << (14 + channel)); + } else { + if ((channel & 1) && pci_use_mirq(0)) + pci_clear_mirq(0); + else + picintc(1 << (14 + channel)); + } +} + + +static void +piix_bus_master_reset(piix_t *dev) +{ + uint8_t i; + + uint16_t old_base = (dev->regs_ide[0x20] & 0xf0) | (dev->regs_ide[0x21] << 8); + if (old_base) { + io_removehandler(old_base, 0x08, + piix_bus_master_read, piix_bus_master_readw, piix_bus_master_readl, + piix_bus_master_write, piix_bus_master_writew, piix_bus_master_writel, + &dev->bm[0]); + io_removehandler(old_base + 8, 0x08, + piix_bus_master_read, piix_bus_master_readw, piix_bus_master_readl, + piix_bus_master_write, piix_bus_master_writew, piix_bus_master_writel, + &dev->bm[1]); + } + + for (i = 0; i < 2; i++) { + dev->bm[i].command = 0x00; + dev->bm[i].status = 0x00; + dev->bm[i].ptr = dev->bm[i].ptr_cur = 0x00000000; + dev->bm[i].addr = 0x00000000; + dev->bm[i].ptr0 = 0x00; + dev->bm[i].count = dev->bm[i].eot = 0x00000000; + } +} + + +static void +piix_reset_hard(void *priv) +{ + piix_t *piix = (piix_t *) priv; + + piix_bus_master_reset(piix); + + memset(piix->regs, 0, 256); + memset(piix->regs_ide, 0, 256); + + piix->regs[0x00] = 0x86; piix->regs[0x01] = 0x80; /*Intel*/ + if (piix->type == 3) { + piix->regs[0x02] = 0x00; piix->regs[0x03] = 0x70; /*82371SB (PIIX3)*/ + } else { + piix->regs[0x02] = 0x2e; piix->regs[0x03] = 0x12; /*82371FB (PIIX)*/ + } + if (piix->type & 0x100) + piix->regs[0x04] = 0x06; + else + piix->regs[0x04] = 0x07; + piix->regs[0x05] = 0x00; + piix->regs[0x06] = 0x80; piix->regs[0x07] = 0x02; + if (piix->type & 0x100) + piix->regs[0x08] = 0x02; /*A0 stepping*/ + else + piix->regs[0x08] = 0x00; /*A0 stepping*/ + piix->regs[0x09] = 0x00; piix->regs[0x0a] = 0x01; piix->regs[0x0b] = 0x06; + if (piix->type & 0x100) + piix->regs[0x0e] = 0x00; /*Single-function device*/ + else + piix->regs[0x0e] = 0x80; /*Multi-function device*/ + piix->regs[0x4c] = 0x4d; + piix->regs[0x4e] = 0x03; + if (piix->type == 3) + piix->regs[0x4f] = 0x00; + piix->regs[0x60] = piix->regs[0x61] = piix->regs[0x62] = piix->regs[0x63] = 0x80; + piix->regs[0x69] = 0x02; + piix->regs[0x70] = 0xc0; + if (piix->type != 3) + piix->regs[0x71] = 0xc0; + piix->regs[0x76] = piix->regs[0x77] = 0x0c; + piix->regs[0x78] = 0x02; piix->regs[0x79] = 0x00; + if (piix->type == 3) { + piix->regs[0x80] = piix->regs[0x82] = 0x00; + } + piix->regs[0xa0] = 0x08; + piix->regs[0xa2] = piix->regs[0xa3] = 0x00; + piix->regs[0xa4] = piix->regs[0xa5] = piix->regs[0xa6] = piix->regs[0xa7] = 0x00; + piix->regs[0xa8] = 0x0f; + piix->regs[0xaa] = piix->regs[0xab] = 0x00; + piix->regs[0xac] = 0x00; + piix->regs[0xae] = 0x00; + + piix->regs_ide[0x00] = 0x86; piix->regs_ide[0x01] = 0x80; /*Intel*/ + if (piix->type == 3) { + piix->regs_ide[0x02] = 0x10; piix->regs_ide[0x03] = 0x70; /*82371SB (PIIX3)*/ + } else { + piix->regs_ide[0x02] = 0x30; piix->regs_ide[0x03] = 0x12; /*82371FB (PIIX)*/ + } + piix->regs_ide[0x04] = 0x03; piix->regs_ide[0x05] = 0x00; + piix->regs_ide[0x06] = 0x80; piix->regs_ide[0x07] = 0x02; + piix->regs_ide[0x08] = 0x00; + piix->regs_ide[0x09] = 0x80; piix->regs_ide[0x0a] = 0x01; piix->regs_ide[0x0b] = 0x01; + piix->regs_ide[0x0d] = 0x00; + piix->regs_ide[0x0e] = 0x00; + piix->regs_ide[0x20] = 0x01; piix->regs_ide[0x21] = piix->regs_ide[0x22] = piix->regs_ide[0x23] = 0x00; /*Bus master interface base address*/ + piix->regs_ide[0x40] = piix->regs_ide[0x42] = 0x00; + piix->regs_ide[0x41] = piix->regs_ide[0x43] = 0x00; + if (piix->type == 3) + piix->regs_ide[0x44] = 0x00; + + pci_set_irq_routing(PCI_INTA, PCI_IRQ_DISABLED); + pci_set_irq_routing(PCI_INTB, PCI_IRQ_DISABLED); + pci_set_irq_routing(PCI_INTC, PCI_IRQ_DISABLED); + pci_set_irq_routing(PCI_INTD, PCI_IRQ_DISABLED); + + pci_set_mirq_routing(PCI_MIRQ0, PCI_IRQ_DISABLED); + if (piix->type != 3) pci_set_mirq_routing(PCI_MIRQ1, PCI_IRQ_DISABLED); + + ide_pri_disable(); + ide_sec_disable(); } -void piix3_reset(void) + +static void +piix_reset(void *p) { - piix_bus_master_reset(); - memset(card_piix, 0, 256); - card_piix[0x00] = 0x86; card_piix[0x01] = 0x80; /*Intel*/ - card_piix[0x02] = 0x00; card_piix[0x03] = 0x70; /*82371SB (PIIX3)*/ - card_piix[0x04] = 0x07; card_piix[0x05] = 0x00; - card_piix[0x06] = 0x80; card_piix[0x07] = 0x02; - card_piix[0x08] = 0x00; /*A0 stepping*/ - card_piix[0x09] = 0x00; card_piix[0x0a] = 0x01; card_piix[0x0b] = 0x06; - card_piix[0x0e] = 0x80; /*Multi-function device*/ - card_piix[0x4c] = 0x4d; - card_piix[0x4e] = 0x03; - card_piix[0x4f] = 0x00; - card_piix[0x60] = card_piix[0x61] = card_piix[0x62] = card_piix[0x63] = 0x80; - card_piix[0x69] = 0x02; - card_piix[0x70] = 0xc0; - card_piix[0x76] = card_piix[0x77] = 0x0c; - card_piix[0x78] = 0x02; card_piix[0x79] = 0x00; - card_piix[0x80] = card_piix[0x82] = 0x00; - card_piix[0xa0] = 0x08; - card_piix[0xa2] = card_piix[0xa3] = 0x00; - card_piix[0xa4] = card_piix[0xa5] = card_piix[0xa6] = card_piix[0xa7] = 0x00; - card_piix[0xa8] = 0x0f; - card_piix[0xaa] = card_piix[0xab] = 0x00; - card_piix[0xac] = 0x00; - card_piix[0xae] = 0x00; + int i; - card_piix_ide[0x00] = 0x86; card_piix_ide[0x01] = 0x80; /*Intel*/ - card_piix_ide[0x02] = 0x10; card_piix_ide[0x03] = 0x70; /*82371SB (PIIX3)*/ - card_piix_ide[0x04] = 0x07; card_piix_ide[0x05] = 0x00; - card_piix_ide[0x06] = 0x80; card_piix_ide[0x07] = 0x02; - card_piix_ide[0x08] = 0x00; - card_piix_ide[0x09] = 0x80; card_piix_ide[0x0a] = 0x01; card_piix_ide[0x0b] = 0x01; - card_piix_ide[0x0d] = 0x00; - card_piix_ide[0x0e] = 0x00; - card_piix_ide[0x20] = 0x01; card_piix_ide[0x21] = card_piix_ide[0x22] = card_piix_ide[0x23] = 0x00; /*Bus master interface base address*/ - card_piix_ide[0x40] = card_piix_ide[0x42] = 0x00; - card_piix_ide[0x41] = card_piix_ide[0x43] = 0x80; - card_piix_ide[0x44] = 0x00; + for (i = 0; i < CDROM_NUM; i++) { + if (cdrom_drives[i].bus_type == CDROM_BUS_ATAPI) + cdrom_reset(cdrom[i]); + } - pci_set_mirq_routing(PCI_MIRQ0, PCI_IRQ_DISABLED); + for (i = 0; i < ZIP_NUM; i++) { + if (zip_drives[i].bus_type == ZIP_BUS_ATAPI) + zip_reset(zip[i]); + } } -void piix_init(int card) + +static void +piix_close(void *p) { - device_add(&ide_pci_2ch_device); + piix_t *piix = (piix_t *)p; - pci_add_card(card, piix_read, piix_write, NULL); - - piix_reset(); - - piix_type = 1; - - ide_set_bus_master(piix_bus_master_dma_read, piix_bus_master_dma_write, piix_bus_master_set_irq); - - port_92_reset(); - - port_92_add(); - - dma_alias_set(); - - pci_reset_handler.pci_set_reset = piix_reset; - - pci_enable_mirq(0); - pci_enable_mirq(1); + free(piix); } -void piix3_init(int card) + +static void * +piix_init(const device_t *info) { - device_add(&ide_pci_2ch_device); + piix_t *piix = (piix_t *)mem_alloc(sizeof(piix_t)); + memset(piix, 0, sizeof(piix_t)); - pci_add_card(card, piix_read, piix_write, NULL); - - piix3_reset(); + device_add(&ide_pci_2ch_device); - piix_type = 3; - - ide_set_bus_master(piix_bus_master_dma_read, piix_bus_master_dma_write, piix_bus_master_set_irq); + pci_add_card(7, piix_read, piix_write, piix); - port_92_reset(); + piix->type = info->local; + piix_reset_hard(piix); - port_92_add(); + ide_set_bus_master(piix_bus_master_dma_read, piix_bus_master_dma_write, + piix_bus_master_set_irq, + &piix->bm[0], &piix->bm[1]); - dma_alias_set(); + port_92_reset(); - pci_reset_handler.pci_set_reset = piix3_reset; + port_92_add(); - pci_enable_mirq(0); + dma_alias_set(); + + pci_enable_mirq(0); + pci_enable_mirq(1); + + return piix; } + + +const device_t piix_device = { + "Intel 82371FB (PIIX)", + DEVICE_PCI, + 1, + piix_init, piix_close, piix_reset, + NULL, NULL, NULL, NULL, + NULL +}; + +const device_t piix_pb640_device = { + "Intel 82371FB (PIIX) (PB640)", + DEVICE_PCI, + 0x101, + piix_init, piix_close, piix_reset, + NULL, NULL, NULL, NULL, + NULL +}; + +const device_t piix3_device = { + "Intel 82371SB (PIIX3)", + DEVICE_PCI, + 3, + piix_init, piix_close, piix_reset, + NULL, NULL, NULL, NULL, + NULL +}; diff --git a/src/devices/system/intel_piix.h b/src/devices/system/intel_piix.h index 0a8b95c..ce0f03e 100644 --- a/src/devices/system/intel_piix.h +++ b/src/devices/system/intel_piix.h @@ -8,7 +8,7 @@ * * Emulation of the Intel PIIX and PIIX3 Xcelerators. * - * Version: @(#)intel_piix.h 1.0.1 2018/02/14 + * Version: @(#)intel_piix.h 1.0.2 2018/09/06 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -40,21 +40,17 @@ # define EMU_INTELPIIX_H -extern void piix_init(int card); +#ifdef EMU_DEVICE_H +extern const device_t piix_device; +extern const device_t piix3_device; +extern const device_t piix_pb640_device; +#endif -extern void piix3_init(int card); -extern void piix4_init(int card); +extern int piix_bus_master_dma_read(int channel, uint8_t *data, int transfer_length, void *priv); +extern int piix_bus_master_dma_write(int channel, uint8_t *data, int transfer_length, void *priv); -extern uint8_t piix_bus_master_read(uint16_t port, void *priv); -extern void piix_bus_master_write(uint16_t port, uint8_t val, void *priv); - -extern int piix_bus_master_get_count(int channel); - -extern int piix_bus_master_dma_read(int channel, uint8_t *data, int transfer_length); -extern int piix_bus_master_dma_write(int channel, uint8_t *data, int transfer_length); - -extern void piix_bus_master_set_irq(int channel); +extern void piix_bus_master_set_irq(int channel, void *priv); #endif /*EMU_INTELPIIX_H*/ diff --git a/src/devices/system/intel_piix4.c b/src/devices/system/intel_piix4.c deleted file mode 100644 index 9743b5a..0000000 --- a/src/devices/system/intel_piix4.c +++ /dev/null @@ -1,411 +0,0 @@ -/* - * VARCem Virtual ARchaeological Computer EMulator. - * An emulator of (mostly) x86-based PC systems and devices, - * using the ISA,EISA,VLB,MCA and PCI system buses, roughly - * spanning the era between 1981 and 1995. - * - * This file is part of the VARCem Project. - * - * Preliminary emulation of the Intel PIIX4 Xcelerator. - * - * PRD format : - * word 0 - base address - * word 1 - bits 1-15 = byte count, bit 31 = end of transfer - * - * Version: @(#)intel_piix4.c 1.0.3 2018/05/06 - * - * Author: Miran Grca, - * - * Copyright 2016-2018 Miran Grca. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the: - * - * Free Software Foundation, Inc. - * 59 Temple Place - Suite 330 - * Boston, MA 02111-1307 - * USA. - */ -#include -#include -#include -#include -#include "../../emu.h" -#include "../../io.h" -#include "../../mem.h" -#include "../../device.h" -#include "../input/keyboard.h" -#include "../disk/hdc.h" -#include "../disk/hdc_ide.h" -#include "dma.h" -#include "pci.h" -#include "intel_piix.h" - - -static uint8_t card_piix4[256], card_piix4_ide[256]; - - -static void piix4_write(int func, int addr, uint8_t val, void *priv) -{ - uint16_t old_base = (card_piix4_ide[0x20] & 0xf0) | (card_piix4_ide[0x21] << 8); - if (func > 1) - return; - - if (func == 1) /*IDE*/ - { - /* pclog("PIIX IDE write: %02X %02X\n", addr, val); */ - - switch (addr) - { - case 0x04: - card_piix4_ide[0x04] = (val & 5) | 2; - break; - case 0x07: - card_piix4_ide[0x07] = val & 0x3e; - break; - case 0x0d: - card_piix4_ide[0x0d] = val; - break; - - case 0x20: - card_piix4_ide[0x20] = (val & ~0x0f) | 1; - break; - case 0x21: - card_piix4_ide[0x21] = val; - break; - - case 0x40: - card_piix4_ide[0x40] = val; - break; - case 0x41: - if ((val ^ card_piix4_ide[0x41]) & 0x80) - { - ide_pri_disable(); - if (val & 0x80) - ide_pri_enable(); - } - card_piix4_ide[0x41] = val; - break; - case 0x42: - card_piix4_ide[0x42] = val; - break; - case 0x43: - if ((val ^ card_piix4_ide[0x43]) & 0x80) - { - ide_sec_disable(); - if (val & 0x80) - ide_sec_enable(); - } - card_piix4_ide[0x43] = val; - break; - case 0x44: - card_piix4_ide[0x44] = val; - break; - case 0x48: - card_piix4_ide[0x44] = val; - break; - case 0x4A: - card_piix4_ide[0x44] = val; - break; - case 0x4B: - card_piix4_ide[0x44] = val; - break; - } - if (addr == 4 || (addr & ~3) == 0x20) /*Bus master base address*/ - { - uint16_t base = (card_piix4_ide[0x20] & 0xf0) | (card_piix4_ide[0x21] << 8); - io_removehandler(old_base, 0x10, piix_bus_master_read, NULL, NULL, piix_bus_master_write, NULL, NULL, NULL); - if (card_piix4_ide[0x04] & 1) - { - io_sethandler(base, 0x10, piix_bus_master_read, NULL, NULL, piix_bus_master_write, NULL, NULL, NULL); - } - } - } - else - { - /* pclog("PIIX writing value %02X to register %02X\n", val, addr); */ - if ((addr >= 0x0f) && (addr < 0x4c)) - return; - - switch (addr) - { - case 0x00: case 0x01: case 0x02: case 0x03: - case 0x08: case 0x09: case 0x0a: case 0x0b: - case 0x0e: - return; - - case 0x60: - /* pclog("Set IRQ routing: INT A -> %02X\n", val); */ - if (val & 0x80) - pci_set_irq_routing(PCI_INTA, PCI_IRQ_DISABLED); - else - pci_set_irq_routing(PCI_INTA, val & 0xf); - break; - case 0x61: - /* pclog("Set IRQ routing: INT B -> %02X\n", val); */ - if (val & 0x80) - pci_set_irq_routing(PCI_INTB, PCI_IRQ_DISABLED); - else - pci_set_irq_routing(PCI_INTB, val & 0xf); - break; - case 0x62: - /* pclog("Set IRQ routing: INT C -> %02X\n", val); */ - if (val & 0x80) - pci_set_irq_routing(PCI_INTC, PCI_IRQ_DISABLED); - else - pci_set_irq_routing(PCI_INTC, val & 0xf); - break; - case 0x63: - /* pclog("Set IRQ routing: INT D -> %02X\n", val); */ - if (val & 0x80) - pci_set_irq_routing(PCI_INTD, PCI_IRQ_DISABLED); - else - pci_set_irq_routing(PCI_INTD, val & 0xf); - break; - } - if (addr == 0x4C) - { - if (!((val ^ card_piix4[addr]) & 0x80)) - { - card_piix4[addr] = val; - return; - } - - card_piix4[addr] = val; - if (val & 0x80) - { - dma_alias_remove(); - } - else - { - dma_alias_set(); - } - } - else if (addr == 0x4E) - { - keyboard_at_set_mouse_scan((val & 0x10) ? 1 : 0); - card_piix4[addr] = val; - } - else - card_piix4[addr] = val; - } -} - -static uint8_t piix4_read(int func, int addr, void *priv) -{ - if (func > 1) - return 0xff; - - if (func == 1) /*IDE*/ - { - if (addr == 4) - { - return (card_piix4_ide[addr] & 5); - } - else if (addr == 5) - { - return 0; - } - else if (addr == 6) - { - return 0x80; - } - else if (addr == 7) - { - return card_piix4_ide[addr] & 0x3E; - } - else if (addr == 0xD) - { - return card_piix4_ide[addr] & 0xF0; - } - else if (addr == 0x20) - { - return (card_piix4_ide[addr] & 0xF0) | 1; - } - else if (addr == 0x22) - { - return 0; - } - else if (addr == 0x23) - { - return 0; - } - else if (addr == 0x41) - { - return card_piix4_ide[addr] & 0xF3; - } - else if (addr == 0x43) - { - return card_piix4_ide[addr] & 0xF3; - } - else if (addr == 0x48) - { - return card_piix4_ide[addr] & 0x0F; - } - else if (addr == 0x4A) - { - return card_piix4_ide[addr] & 0x33; - } - else if (addr == 0x4B) - { - return card_piix4_ide[addr] & 0x33; - } - else - { - return card_piix4_ide[addr]; - } - } - else - { - if ((addr & 0xFC) == 0x60) - { - return card_piix4[addr] & 0x8F; - } - if (addr == 4) - { - return (card_piix4[addr] & 0x08) | 7; - } - else if (addr == 5) - { - return card_piix4[addr] & 0x01; - } - else if (addr == 6) - { - return 0x80; - } - else if (addr == 7) - { - return (card_piix4[addr] & 0x78) | 0x02; - } - else if (addr == 0x4E) - { - return (card_piix4[addr] & 0xEF) | keyboard_at_get_mouse_scan(); - } - else if (addr == 0x4F) - { - return card_piix4[addr] & 0x06; - } - else if (addr == 0x69) - { - return card_piix4[addr] & 0xFE; - } - else if (addr == 0x6A) - { - return card_piix4[addr] & 0x80; - } - else if (addr == 0x6B) - { - return card_piix4[addr] & 0x80; - } - else if (addr == 0x76) - { - return (card_piix4[addr] & 0x87) | 0x08; - } - else if (addr == 0x77) - { - return (card_piix4[addr] & 0x87) | 0x08; - } - else if (addr == 0x80) - { - return card_piix4[addr] & 0x7F; - } - else if (addr == 0x82) - { - return card_piix4[addr] & 0x0F; - } - else if (addr == 0x91) - { - return card_piix4[addr] & 0xFC; - } - else if (addr == 0x92) - { - return card_piix4[addr] & 0xC0; - } - else if (addr == 0x94) - { - return card_piix4[addr] & 0xC0; - } - else if (addr == 0xB0) - { - return card_piix4[addr] & 0x7F; - } - else if (addr == 0xB1) - { - return card_piix4[addr] & 0xDF; - } - else if (addr == 0xB3) - { - return card_piix4[addr] & 0xFD; - } - else if (addr == 0xCB) - { - return card_piix4[addr] & 0x3D; - } - else - return card_piix4[addr]; - } - - return 0; -} - -void piix4_reset(void) -{ - memset(card_piix4, 0, 256); - memset(card_piix4_ide, 0, 256); - - card_piix4[0x00] = 0x86; card_piix4[0x01] = 0x80; /*Intel*/ - card_piix4[0x02] = 0x10; card_piix4[0x03] = 0x71; /*82371AB (PIIX4)*/ - card_piix4[0x04] = 0x07; card_piix4[0x05] = 0x00; - card_piix4[0x06] = 0x80; card_piix4[0x07] = 0x02; - card_piix4[0x08] = 0x00; /*A0 stepping*/ - card_piix4[0x09] = 0x00; card_piix4[0x0a] = 0x01; card_piix4[0x0b] = 0x06; - card_piix4[0x0e] = 0x80; /*Multi-function device*/ - card_piix4[0x4c] = 0x4d; - card_piix4[0x4e] = 0x03; - card_piix4[0x60] = card_piix4[0x61] = card_piix4[0x62] = card_piix4[0x63] = 0x80; - card_piix4[0x64] = 0x10; - card_piix4[0x69] = 0x02; - card_piix4[0x76] = card_piix4[0x77] = 0x04; - card_piix4[0xcb] = 0x21; - - card_piix4_ide[0x00] = 0x86; card_piix4_ide[0x01] = 0x80; /*Intel*/ - card_piix4_ide[0x02] = 0x11; card_piix4_ide[0x03] = 0x71; /*82371AB (PIIX)*/ - card_piix4_ide[0x04] = 0x07; card_piix4_ide[0x05] = 0x00; - card_piix4_ide[0x06] = 0x80; card_piix4_ide[0x07] = 0x02; - card_piix4_ide[0x08] = 0x00; - card_piix4_ide[0x09] = 0x80; card_piix4_ide[0x0a] = 0x01; card_piix4_ide[0x0b] = 0x01; - card_piix4_ide[0x0d] = 0x00; - card_piix4_ide[0x0e] = 0x00; - card_piix4_ide[0x20] = 0x01; card_piix4_ide[0x21] = card_piix4_ide[0x22] = card_piix4_ide[0x23] = 0x00; /*Bus master interface base address*/ - card_piix4_ide[0x40] = card_piix4_ide[0x42] = 0x00; - card_piix4_ide[0x41] = card_piix4_ide[0x43] = 0x80; -} - -void piix4_init(int card) -{ - device_add(&ide_pci_2ch_device); - - pci_add_card(card, piix4_read, piix4_write, NULL); - - piix4_reset(); - - ide_set_bus_master(piix_bus_master_dma_read, piix_bus_master_dma_write, piix_bus_master_set_irq); - - port_92_reset(); - - port_92_add(); - - dma_alias_set(); - - pci_reset_handler.pci_set_reset = piix4_reset; -} diff --git a/src/devices/system/intel_sio.c b/src/devices/system/intel_sio.c index 91ab9e0..b3cca47 100644 --- a/src/devices/system/intel_sio.c +++ b/src/devices/system/intel_sio.c @@ -8,7 +8,7 @@ * * Emulation of Intel System I/O PCI chip. * - * Version: @(#)intel_sio.c 1.0.2 2018/05/06 + * Version: @(#)intel_sio.c 1.0.4 2018/10/05 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -38,154 +38,186 @@ */ #include #include +#include #include #include -#include "../../cpu/cpu.h" +#include "../../emu.h" #include "../../io.h" #include "../../mem.h" +#include "../../device.h" #include "dma.h" #include "pci.h" #include "intel_sio.h" -static uint8_t card_sio[256]; +typedef struct { + uint8_t regs[256]; +} sio_t; -static void sio_write(int func, int addr, uint8_t val, void *priv) +static void +sio_write(int func, int addr, uint8_t val, void *priv) { - if (func > 0) - return; - - if (addr >= 0x0f && addr < 0x4c) + sio_t *dev = (sio_t *) priv; + + if (func > 0) + return; + + if (addr >= 0x0f && addr < 0x4c) + return; + + switch (addr) { + case 0x00: case 0x01: case 0x02: case 0x03: + case 0x08: case 0x09: case 0x0a: case 0x0b: + case 0x0e: return; - switch (addr) - { - case 0x00: case 0x01: case 0x02: case 0x03: - case 0x08: case 0x09: case 0x0a: case 0x0b: - case 0x0e: - return; - - case 0x04: /*Command register*/ - val &= 0x08; - val |= 0x07; - break; - case 0x05: - val = 0; - break; - - case 0x06: /*Status*/ - val = 0; - break; - case 0x07: - val = 0x02; - break; - - case 0x40: - if (!((val ^ card_sio[addr]) & 0x40)) - { - return; - } - - if (val & 0x40) - { - dma_alias_remove(); - } - else - { - dma_alias_set(); - } + case 0x04: /*Command register*/ + val &= 0x08; + val |= 0x07; + break; + case 0x05: + val = 0; break; - case 0x4f: - if (!((val ^ card_sio[addr]) & 0x40)) - { + case 0x06: /*Status*/ + val = 0; + break; + case 0x07: + val = 0x02; + break; + + case 0x40: + if (!((val ^ dev->regs[addr]) & 0x40)) return; - } if (val & 0x40) - { - port_92_add(); - } + dma_alias_remove(); + else + dma_alias_set(); + break; + + case 0x4f: + if (!((val ^ dev->regs[addr]) & 0x40)) + return; + + if (val & 0x40) + port_92_add(); else - { port_92_remove(); - } - case 0x60: - if (val & 0x80) - pci_set_irq_routing(PCI_INTA, PCI_IRQ_DISABLED); - else - pci_set_irq_routing(PCI_INTA, val & 0xf); - break; - case 0x61: - if (val & 0x80) - pci_set_irq_routing(PCI_INTC, PCI_IRQ_DISABLED); - else - pci_set_irq_routing(PCI_INTC, val & 0xf); - break; - case 0x62: - if (val & 0x80) - pci_set_irq_routing(PCI_INTB, PCI_IRQ_DISABLED); - else - pci_set_irq_routing(PCI_INTB, val & 0xf); - break; - case 0x63: - if (val & 0x80) - pci_set_irq_routing(PCI_INTD, PCI_IRQ_DISABLED); - else - pci_set_irq_routing(PCI_INTD, val & 0xf); - break; - } - card_sio[addr] = val; + case 0x60: + if (val & 0x80) + pci_set_irq_routing(PCI_INTA, PCI_IRQ_DISABLED); + else + pci_set_irq_routing(PCI_INTA, val & 0xf); + break; + case 0x61: + if (val & 0x80) + pci_set_irq_routing(PCI_INTC, PCI_IRQ_DISABLED); + else + pci_set_irq_routing(PCI_INTC, val & 0xf); + break; + case 0x62: + if (val & 0x80) + pci_set_irq_routing(PCI_INTB, PCI_IRQ_DISABLED); + else + pci_set_irq_routing(PCI_INTB, val & 0xf); + break; + case 0x63: + if (val & 0x80) + pci_set_irq_routing(PCI_INTD, PCI_IRQ_DISABLED); + else + pci_set_irq_routing(PCI_INTD, val & 0xf); + break; + } + dev->regs[addr] = val; } -static uint8_t sio_read(int func, int addr, void *priv) +static uint8_t +sio_read(int func, int addr, void *priv) { - if (func > 0) - return 0xff; + sio_t *dev = (sio_t *) priv; + uint8_t ret; - return card_sio[addr]; + ret = 0xff; + + if (func == 0) + ret = dev->regs[addr]; + + return ret; } -static void sio_reset(void) +static void +sio_reset(void *priv) { - memset(card_sio, 0, 256); - card_sio[0x00] = 0x86; card_sio[0x01] = 0x80; /*Intel*/ - card_sio[0x02] = 0x84; card_sio[0x03] = 0x04; /*82378IB (SIO)*/ - card_sio[0x04] = 0x07; card_sio[0x05] = 0x00; - card_sio[0x06] = 0x00; card_sio[0x07] = 0x02; - card_sio[0x08] = 0x03; /*A0 stepping*/ + sio_t *dev = (sio_t *) priv; - card_sio[0x40] = 0x20; card_sio[0x41] = 0x00; - card_sio[0x42] = 0x04; card_sio[0x43] = 0x00; - card_sio[0x44] = 0x20; card_sio[0x45] = 0x10; - card_sio[0x46] = 0x0f; card_sio[0x47] = 0x00; - card_sio[0x48] = 0x01; card_sio[0x49] = 0x10; - card_sio[0x4a] = 0x10; card_sio[0x4b] = 0x0f; - card_sio[0x4c] = 0x56; card_sio[0x4d] = 0x40; - card_sio[0x4e] = 0x07; card_sio[0x4f] = 0x4f; - card_sio[0x54] = 0x00; card_sio[0x55] = 0x00; card_sio[0x56] = 0x00; - card_sio[0x60] = 0x80; card_sio[0x61] = 0x80; card_sio[0x62] = 0x80; card_sio[0x63] = 0x80; - card_sio[0x80] = 0x78; card_sio[0x81] = 0x00; - card_sio[0xa0] = 0x08; - card_sio[0xa8] = 0x0f; + memset(dev->regs, 0, 256); + + dev->regs[0x00] = 0x86; dev->regs[0x01] = 0x80; /*Intel*/ + dev->regs[0x02] = 0x84; dev->regs[0x03] = 0x04; /*82378IB (SIO)*/ + dev->regs[0x04] = 0x07; dev->regs[0x05] = 0x00; + dev->regs[0x06] = 0x00; dev->regs[0x07] = 0x02; + dev->regs[0x08] = 0x03; /*A0 stepping*/ + + dev->regs[0x40] = 0x20; dev->regs[0x41] = 0x00; + dev->regs[0x42] = 0x04; dev->regs[0x43] = 0x00; + dev->regs[0x44] = 0x20; dev->regs[0x45] = 0x10; + dev->regs[0x46] = 0x0f; dev->regs[0x47] = 0x00; + dev->regs[0x48] = 0x01; dev->regs[0x49] = 0x10; + dev->regs[0x4a] = 0x10; dev->regs[0x4b] = 0x0f; + dev->regs[0x4c] = 0x56; dev->regs[0x4d] = 0x40; + dev->regs[0x4e] = 0x07; dev->regs[0x4f] = 0x4f; + dev->regs[0x54] = 0x00; dev->regs[0x55] = 0x00; dev->regs[0x56] = 0x00; + dev->regs[0x60] = 0x80; dev->regs[0x61] = 0x80; dev->regs[0x62] = 0x80; dev->regs[0x63] = 0x80; + dev->regs[0x80] = 0x78; dev->regs[0x81] = 0x00; + dev->regs[0xa0] = 0x08; + dev->regs[0xa8] = 0x0f; + + pci_set_irq_routing(PCI_INTA, PCI_IRQ_DISABLED); + pci_set_irq_routing(PCI_INTB, PCI_IRQ_DISABLED); + pci_set_irq_routing(PCI_INTC, PCI_IRQ_DISABLED); + pci_set_irq_routing(PCI_INTD, PCI_IRQ_DISABLED); } -void sio_init(int card) +static void +sio_close(void *p) { - pci_add_card(card, sio_read, sio_write, NULL); + sio_t *sio = (sio_t *)p; + + free(sio); +} + + +static void * +sio_init(const device_t *info) +{ + sio_t *sio = (sio_t *)mem_alloc(sizeof(sio_t)); + memset(sio, 0, sizeof(sio_t)); + + pci_add_card(2, sio_read, sio_write, sio); - sio_reset(); + sio_reset(sio); - port_92_reset(); + port_92_reset(); - port_92_add(); + port_92_add(); - dma_alias_set(); + dma_alias_set(); - pci_reset_handler.pci_set_reset = sio_reset; + return sio; } + + +const device_t sio_device = { + "Intel 82378IB (SIO)", + DEVICE_PCI, + 0, + sio_init, sio_close, NULL, + NULL, NULL, NULL, NULL, + NULL +}; diff --git a/src/devices/system/intel_sio.h b/src/devices/system/intel_sio.h index 20058b7..48d62d8 100644 --- a/src/devices/system/intel_sio.h +++ b/src/devices/system/intel_sio.h @@ -8,7 +8,7 @@ * * Definitions for the Intel System I/O PCI chip handler. * - * Version: @(#)sio.h 1.0.1 2018/02/14 + * Version: @(#)sio.h 1.0.2 2018/09/04 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -40,7 +40,7 @@ # define EMU_INTELSIO_H -extern void sio_init(int card); +extern const device_t sio_device; #endif /*EMU_INTELSIO_H*/ diff --git a/src/devices/system/mcr.c b/src/devices/system/mcr.c index 0ce7baa..979fd1f 100644 --- a/src/devices/system/mcr.c +++ b/src/devices/system/mcr.c @@ -10,7 +10,7 @@ * This chip was used as part of many 386 chipsets. * It controls memory addressing and shadowing. * - * Version: @(#)mcr.c 1.0.2 2018/05/06 + * Version: @(#)mcr.c 1.0.3 2018/10/05 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -43,7 +43,6 @@ #include #include #include "../../emu.h" -#include "../../cpu/cpu.h" #include "../../mem.h" @@ -65,8 +64,6 @@ resetmcr(void) void writemcr(uint16_t addr, uint8_t val) { - pclog("MCR: write %04X %02X %04X:%04X\n",addr,val,CS,cpu_state.pc); - switch (addr) { case 0x22: if (val == 6 && mcr22 == 6) diff --git a/src/devices/system/memregs.c b/src/devices/system/memregs.c index e2f5520..1d4a758 100644 --- a/src/devices/system/memregs.c +++ b/src/devices/system/memregs.c @@ -9,7 +9,7 @@ * Emulation of the memory I/O scratch registers on ports 0xE1 * and 0xE2, used by just about any emulated machine. * - * Version: @(#)memregs.c 1.0.2 2018/05/06 + * Version: @(#)memregs.c 1.0.3 2018/09/06 * * Author: Miran Grca, * @@ -72,10 +72,6 @@ memregs_read(uint16_t port, void *priv) void memregs_init(void) { -#if 0 - pclog("Memory Registers Init\n"); -#endif - io_sethandler(0x00e1, 2, memregs_read,NULL,NULL, memregs_write,NULL,NULL, NULL); } @@ -84,10 +80,6 @@ memregs_init(void) void powermate_memregs_init(void) { -#if 0 - pclog("Memory Registers Init\n"); -#endif - io_sethandler(0x00ed, 2, memregs_read,NULL,NULL, memregs_write,NULL,NULL, NULL); diff --git a/src/devices/system/nvr_at.c b/src/devices/system/nvr_at.c index 466a18d..e43bede 100644 --- a/src/devices/system/nvr_at.c +++ b/src/devices/system/nvr_at.c @@ -189,7 +189,7 @@ * including the later update (DS12887A) which implemented a * "century" register to be compatible with Y2K. * - * Version: @(#)nvr_at.c 1.0.10 2018/08/27 + * Version: @(#)nvr_at.c 1.0.11 2018/09/22 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -232,9 +232,9 @@ #include "../../timer.h" #include "../../device.h" #include "../../nvr.h" +#include "nmi.h" #include "pic.h" #include "pit.h" -#include "nmi.h" /* RTC registers and bit definitions. */ @@ -283,7 +283,7 @@ typedef struct { - int8_t stat; + uint8_t stat; uint8_t cent; uint8_t addr; @@ -309,7 +309,8 @@ time_get(nvr_t *nvr, struct tm *tm) tm->tm_mday = nvr->regs[RTC_DOM]; tm->tm_mon = (nvr->regs[RTC_MONTH] - 1); tm->tm_year = nvr->regs[RTC_YEAR]; - tm->tm_year += (nvr->regs[local->cent] * 100) - 1900; + if (local->cent != 0xff) + tm->tm_year += (nvr->regs[local->cent] * 100) - 1900; } else { /* NVR is in BCD data mode. */ tm->tm_sec = RTC_DCB(nvr->regs[RTC_SECONDS]); @@ -319,7 +320,8 @@ time_get(nvr_t *nvr, struct tm *tm) tm->tm_mday = RTC_DCB(nvr->regs[RTC_DOM]); tm->tm_mon = (RTC_DCB(nvr->regs[RTC_MONTH]) - 1); tm->tm_year = RTC_DCB(nvr->regs[RTC_YEAR]); - tm->tm_year += (RTC_DCB(nvr->regs[local->cent]) * 100) - 1900; + if (local->cent != 0xff) + tm->tm_year += (RTC_DCB(nvr->regs[local->cent]) * 100) - 1900; } /* Adjust for 12/24 hour mode. */ @@ -345,7 +347,8 @@ time_set(nvr_t *nvr, struct tm *tm) nvr->regs[RTC_DOM] = tm->tm_mday; nvr->regs[RTC_MONTH] = (tm->tm_mon + 1); nvr->regs[RTC_YEAR] = (year % 100); - nvr->regs[local->cent] = (year / 100); + if (local->cent != 0xff) + nvr->regs[local->cent] = (year / 100); if (nvr->regs[RTC_REGB] & REGB_2412) { /* NVR is in 24h mode. */ @@ -364,7 +367,8 @@ time_set(nvr_t *nvr, struct tm *tm) nvr->regs[RTC_DOM] = RTC_BCD(tm->tm_mday); nvr->regs[RTC_MONTH] = RTC_BCD(tm->tm_mon + 1); nvr->regs[RTC_YEAR] = RTC_BCD(year % 100); - nvr->regs[local->cent] = RTC_BCD(year / 100); + if (local->cent != 0xff) + nvr->regs[local->cent] = RTC_BCD(year / 100); if (nvr->regs[RTC_REGB] & REGB_2412) { /* NVR is in 24h mode. */ @@ -448,10 +452,14 @@ timer_recalc(nvr_t *nvr, int add) int64_t c, nt; c = 1ULL << ((nvr->regs[RTC_REGA] & REGA_RS) - 1); - nt = (int64_t)(RTCCONST * c * (1<rtctime = nt; + return; + } else if (add == 1) local->rtctime += nt; - else if (local->rtctime > nt) + else if (local->rtctime > nt) local->rtctime = nt; } @@ -487,17 +495,12 @@ timer_tick(nvr_t *nvr) { local_t *local = (local_t *)nvr->data; - /* Only update it there is no SET in progress. */ + /* Only update if there is no SET in progress. */ if (nvr->regs[RTC_REGB] & REGB_SET) return; /* Set the UIP bit, announcing the update. */ local->stat = REGA_UIP; -#if 0 - /* Not sure if this is needed here. */ - timer_recalc(nvr, 0); -#endif - /* Schedule the actual update. */ local->ecount = (int64_t)((244.0 + 1984.0) * TIMER_USEC); } @@ -546,9 +549,9 @@ nvr_write(uint16_t addr, uint8_t val, void *priv) break; } - if ((local->addr < RTC_REGA) || (local->addr == local->cent)) { + if ((local->addr < RTC_REGA) || ((local->cent != 0xff) && (local->addr == local->cent))) { if ((local->addr != 1) && (local->addr != 3) && (local->addr != 5)) { - if ((old != val) && !enable_sync) { + if ((old != val) && (time_sync == TIME_SYNC_DISABLED)) { /* Update internal clock. */ time_get(nvr, &tm); nvr_time_set(&tm); @@ -559,7 +562,7 @@ nvr_write(uint16_t addr, uint8_t val, void *priv) } else { local->addr = (val & (nvr->size - 1)); if (!(machines[machine].flags & MACHINE_MCA) && - (romset != ROM_IBMPS1_2133)) + !(machines[machine].flags & MACHINE_NONMI)) nmi_mask = (~val & 0x80); } } @@ -612,7 +615,8 @@ nvr_reset(nvr_t *nvr) nvr->regs[RTC_DOM] = 1; nvr->regs[RTC_MONTH] = 1; nvr->regs[RTC_YEAR] = RTC_BCD(80); - nvr->regs[local->cent] = RTC_BCD(19); + if (local->cent != 0xff) + nvr->regs[local->cent] = RTC_BCD(19); } @@ -623,7 +627,7 @@ nvr_start(nvr_t *nvr) struct tm tm; /* Initialize the internal and chip times. */ - if (enable_sync) { + if (time_sync != TIME_SYNC_DISABLED) { /* Use the internal clock's time. */ nvr_time_get(&tm); time_set(nvr, &tm); @@ -640,6 +644,13 @@ nvr_start(nvr_t *nvr) } +static void +nvr_recalc(nvr_t *nvr) +{ + timer_recalc(nvr, 0); +} + + static void * nvr_at_init(const device_t *info) { @@ -647,28 +658,31 @@ nvr_at_init(const device_t *info) nvr_t *nvr; /* Allocate an NVR for this machine. */ - nvr = (nvr_t *)malloc(sizeof(nvr_t)); - if (nvr == NULL) return(NULL); + nvr = (nvr_t *)mem_alloc(sizeof(nvr_t)); memset(nvr, 0x00, sizeof(nvr_t)); - - local = (local_t *)malloc(sizeof(local_t)); + local = (local_t *)mem_alloc(sizeof(local_t)); memset(local, 0x00, sizeof(local_t)); nvr->data = local; /* This is machine specific. */ nvr->size = machines[machine].nvrsz; switch(info->local) { - case 0: /* standard AT */ + case 0: /* standard AT (no century register) */ + nvr->irq = 8; + local->cent = 0xff; + break; + + case 1: /* standard AT or compatible */ nvr->irq = 8; local->cent = RTC_CENTURY_AT; break; - case 1: /* PS/1 or PS/2 */ + case 2: /* PS/1 or PS/2 */ nvr->irq = 8; local->cent = RTC_CENTURY_PS; break; - case 2: /* Amstrad PC's */ + case 3: /* Amstrad PC's */ nvr->irq = 1; local->cent = RTC_CENTURY_AT; break; @@ -678,6 +692,7 @@ nvr_at_init(const device_t *info) nvr->reset = nvr_reset; nvr->start = nvr_start; nvr->tick = timer_tick; + nvr->recalc = nvr_recalc; /* Initialize the generic NVR. */ nvr_init(nvr); @@ -709,29 +724,38 @@ nvr_at_close(void *priv) } -const device_t at_nvr_device = { - "PC/AT NVRAM", +const device_t at_nvr_old_device = { + "PC/AT NVRAM (No Century)", DEVICE_ISA | DEVICE_AT, 0, nvr_at_init, nvr_at_close, NULL, - NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL +}; + +const device_t at_nvr_device = { + "PC/AT NVRAM", + DEVICE_ISA | DEVICE_AT, + 1, + nvr_at_init, nvr_at_close, NULL, + NULL, NULL, NULL, NULL, NULL }; const device_t ps_nvr_device = { "PS/1 or PS/2 NVRAM", DEVICE_PS2, - 1, + 2, nvr_at_init, nvr_at_close, NULL, - NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL }; const device_t amstrad_nvr_device = { "Amstrad NVRAM", MACHINE_ISA | MACHINE_AT, - 2, + 3, nvr_at_init, nvr_at_close, NULL, - NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL }; diff --git a/src/devices/system/nvr_ps2.c b/src/devices/system/nvr_ps2.c index 8085d6e..6ef74f3 100644 --- a/src/devices/system/nvr_ps2.c +++ b/src/devices/system/nvr_ps2.c @@ -8,7 +8,7 @@ * * Handling of the PS/2 series CMOS devices. * - * Version: @(#)nvr_ps2.c 1.0.7 2018/05/06 + * Version: @(#)nvr_ps2.c 1.0.8 2018/10/05 * * Authors: Fred N. van Kempen, * Sarah Walker, @@ -40,7 +40,6 @@ #include #include #include "../../emu.h" -#include "../../cpu/cpu.h" #include "../../machines/machine.h" #include "../../device.h" #include "../../io.h" @@ -49,10 +48,13 @@ #include "nvr_ps2.h" +#define NVR_RAM_SIZE 8192 + + typedef struct { int addr; - - uint8_t ram[8192]; + wchar_t *fn; + uint8_t ram[NVR_RAM_SIZE]; } ps2_nvr_t; @@ -104,35 +106,30 @@ ps2_nvr_write(uint16_t port, uint8_t val, void *priv) static void * ps2_nvr_init(const device_t *info) { + char temp[128]; ps2_nvr_t *nvr; - FILE *f = NULL; + FILE *fp; + int i; - nvr = (ps2_nvr_t *)malloc(sizeof(ps2_nvr_t)); + nvr = (ps2_nvr_t *)mem_alloc(sizeof(ps2_nvr_t)); memset(nvr, 0x00, sizeof(ps2_nvr_t)); + + /* Set up the NVR file's name. */ + sprintf(temp, "%s_sec.nvr", machine_get_internal_name()); + i = strlen(temp) + 1; + nvr->fn = (wchar_t *)mem_alloc(i * sizeof(wchar_t)); + mbstowcs(nvr->fn, temp, i); + memset(nvr->ram, 0xff, sizeof(nvr->ram)); + fp = plat_fopen(nvr_path(nvr->fn), L"rb"); + if (fp != NULL) { + (void)fread(nvr->ram, sizeof(nvr->ram), 1, fp); + fclose(fp); + } + io_sethandler(0x0074, 3, ps2_nvr_read,NULL,NULL, ps2_nvr_write,NULL,NULL, nvr); - switch (romset) { - case ROM_IBMPS2_M70_TYPE3: - f = plat_fopen(nvr_path(L"ibmps2_m70_type3_sec.nvr"), L"rb"); - break; - - case ROM_IBMPS2_M70_TYPE4: - f = plat_fopen(nvr_path(L"ibmps2_m70_type4_sec.nvr"), L"rb"); - break; - - case ROM_IBMPS2_M80: - f = plat_fopen(nvr_path(L"ibmps2_m80_sec.nvr"), L"rb"); - break; - } - - memset(nvr->ram, 0xff, 8192); - if (f != NULL) { - (void)fread(nvr->ram, 8192, 1, f); - fclose(f); - } - return(nvr); } @@ -141,29 +138,16 @@ static void ps2_nvr_close(void *priv) { ps2_nvr_t *nvr = (ps2_nvr_t *)priv; - FILE *f = NULL; + FILE *fp; - switch (romset) { - case ROM_IBMPS2_M70_TYPE3: - f = plat_fopen(nvr_path(L"ibmps2_m70_type3_sec.nvr"), L"wb"); - break; - - case ROM_IBMPS2_M70_TYPE4: - f = plat_fopen(nvr_path(L"ibmps2_m70_type4_sec.nvr"), L"wb"); - break; - - case ROM_IBMPS2_M80: - f = plat_fopen(nvr_path(L"ibmps2_m80_sec.nvr"), L"wb"); - break; - } - - if (f != NULL) { - (void)fwrite(nvr->ram, 8192, 1, f); - fclose(f); + fp = plat_fopen(nvr_path(nvr->fn), L"wb"); + if (fp != NULL) { + (void)fwrite(nvr->ram, sizeof(nvr->ram), 1, fp); + fclose(fp); } + free(nvr->fn); free(nvr->ram); - free(nvr); } diff --git a/src/devices/system/pci.c b/src/devices/system/pci.c index 4a5a404..3b4e30b 100644 --- a/src/devices/system/pci.c +++ b/src/devices/system/pci.c @@ -8,7 +8,7 @@ * * Implement the PCI bus. * - * Version: @(#)pci.c 1.0.5 2018/05/06 + * Version: @(#)pci.c 1.0.7 2018/09/17 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -49,12 +49,9 @@ #include "../../mem.h" #include "../../device.h" #include "../input/keyboard.h" -#include "../disk/hdc.h" -#include "../disk/hdc_ide.h" -#include "../disk/zip.h" -#include "../cdrom/cdrom.h" #include "pic.h" #include "pci.h" +#include "intel_piix.h" typedef struct @@ -90,7 +87,6 @@ int pci_burst_time, pci_nonburst_time; static int trc_reg = 0; -PCI_RESET pci_reset_handler; #ifdef ENABLE_BUS_LOG int pci_do_log = ENABLE_BUS_LOG; @@ -674,48 +670,10 @@ static uint8_t trc_read(uint16_t port, void *priv) static void trc_reset(uint8_t val) { - int i = 0; - - if (val & 2) - { - if (pci_reset_handler.pci_master_reset) - { - pci_reset_handler.pci_master_reset(); - } - - if (pci_reset_handler.pci_set_reset) - { - pci_reset_handler.pci_set_reset(); - } - - if (pci_reset_handler.super_io_reset) - { - pci_reset_handler.super_io_reset(); - } - -#if 0 - ide_reset(); -#else - ide_set_all_signatures(); -#endif - - for (i = 0; i < CDROM_NUM; i++) - { - if ((cdrom_drives[i].bus_type == CDROM_BUS_ATAPI_PIO_ONLY) || (cdrom_drives[i].bus_type == CDROM_BUS_ATAPI_PIO_AND_DMA)) - { - cdrom_reset(i); - } - } - for (i = 0; i < ZIP_NUM; i++) - { - if ((zip_drives[i].bus_type == ZIP_BUS_ATAPI_PIO_ONLY) || (zip_drives[i].bus_type == ZIP_BUS_ATAPI_PIO_AND_DMA)) - { - zip_reset(i); - } - } + if (val & 2) { + device_reset_all(DEVICE_PCI); port_92_reset(); - keyboard_at_reset(); pci_reset(); } @@ -774,10 +732,6 @@ void pci_init(int type) pci_mirqs[c].enabled = 0; pci_mirqs[c].irq_line = PCI_IRQ_DISABLED; } - - pci_reset_handler.pci_master_reset = NULL; - pci_reset_handler.pci_set_reset = NULL; - pci_reset_handler.super_io_reset = NULL; } void pci_register_slot(int card, int type, int inta, int intb, int intc, int intd) diff --git a/src/devices/system/pci.h b/src/devices/system/pci.h index 3d1824e..ea2e4be 100644 --- a/src/devices/system/pci.h +++ b/src/devices/system/pci.h @@ -8,7 +8,7 @@ * * Definitions for the PCI handler module. * - * Version: @(#)pci.h 1.0.1 2018/02/14 + * Version: @(#)pci.h 1.0.2 2018/09/04 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -73,14 +73,7 @@ typedef union { uint8_t addr_regs[4]; } bar_t; -typedef struct PCI_RESET { - void (*pci_master_reset)(void); - void (*pci_set_reset)(void); - void (*super_io_reset)(void); -} PCI_RESET; - -extern PCI_RESET pci_reset_handler; extern int pci_burst_time, pci_nonburst_time; @@ -103,6 +96,7 @@ extern void pci_reset(void); extern void pci_init(int type); extern void pci_register_slot(int card, int type, int inta, int intb, int intc, int intd); +extern void pci_close(void); extern uint8_t pci_add_card(uint8_t add_type, uint8_t (*read)(int func, int addr, void *priv), void (*write)(int func, int addr, uint8_t val, void *priv), void *priv); extern void trc_init(void); diff --git a/src/devices/system/pci_dummy.c b/src/devices/system/pci_dummy.c index bedc9a0..1ace871 100644 --- a/src/devices/system/pci_dummy.c +++ b/src/devices/system/pci_dummy.c @@ -8,7 +8,7 @@ * * Example implementation of a PCI device. * - * Version: @(#)pci_dummy.c 1.0.4 2018/07/26 + * Version: @(#)pci_dummy.c 1.0.5 2018/09/04 * * Author: Miran Grca, * diff --git a/src/devices/system/pic.c b/src/devices/system/pic.c index 69576cb..16204d7 100644 --- a/src/devices/system/pic.c +++ b/src/devices/system/pic.c @@ -8,7 +8,7 @@ * * Implementation of Intel 8259 interrupt controller. * - * Version: @(#)pic.c 1.0.2 2018/05/06 + * Version: @(#)pic.c 1.0.3 2018/10/05 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -48,229 +48,218 @@ #include "pit.h" -int output; int intclear; -int keywaiting=0; +int keywaiting = 0; int pic_intpending; PIC pic, pic2; uint16_t pic_current; -void pic_updatepending(void) +void +pic_updatepending(void) { - uint16_t temp_pending = 0; - if (AT) - { - if ((pic2.pend&~pic2.mask)&~pic2.mask2) - pic.pend |= pic.icw3; - else - pic.pend &= ~pic.icw3; - } - pic_intpending = (pic.pend & ~pic.mask) & ~pic.mask2; - if (AT) - { - if (!((pic.mask | pic.mask2) & pic.icw3)) - { - temp_pending = ((pic2.pend&~pic2.mask)&~pic2.mask2); - temp_pending <<= 8; - pic_intpending |= temp_pending; - } - } -/* pclog("pic_intpending = %i %02X %02X %02X %02X\n", pic_intpending, pic.ins, pic.pend, pic.mask, pic.mask2); - pclog(" %02X %02X %02X %02X %i %i\n", pic2.ins, pic2.pend, pic2.mask, pic2.mask2, ((pic.mask | pic.mask2) & (1 << 2)), ((pic2.pend&~pic2.mask)&~pic2.mask2)); */ -} + uint16_t temp_pending = 0; - -void pic_reset(void) -{ - pic.icw=0; - pic.mask=0xFF; - pic.mask2=0; - pic.pend=pic.ins=0; - pic.vector=8; - pic.read=1; - pic2.icw=0; - pic2.mask=0xFF; - pic.mask2=0; - pic2.pend=pic2.ins=0; - pic_intpending = 0; -} - -void pic_update_mask(uint8_t *mask, uint8_t ins) -{ - int c; - *mask = 0; - for (c = 0; c < 8; c++) - { - if (ins & (1 << c)) - { - *mask = 0xff << c; - return; - } - } -} - -static int picint_is_level(uint16_t irq) -{ - if (PCI) - { - return pci_irq_is_level(irq); - } + if (AT) { + if ((pic2.pend&~pic2.mask)&~pic2.mask2) + pic.pend |= pic.icw3; else - { - if (irq < 8) - { - return (pic.icw1 & 8) ? 1 : 0; - } - else - { - return (pic2.icw1 & 8) ? 1 : 0; - } + pic.pend &= ~pic.icw3; + } + + pic_intpending = (pic.pend & ~pic.mask) & ~pic.mask2; + + if (AT) { + if (!((pic.mask | pic.mask2) & pic.icw3)) { + temp_pending = ((pic2.pend&~pic2.mask)&~pic2.mask2); + temp_pending <<= 8; + pic_intpending |= temp_pending; } + } + +#if 0 + DBGLOG(1, "pic_intpending = %i %02X %02X %02X %02X\n", + pic_intpending, pic.ins, pic.pend, pic.mask, pic.mask2); + DBGLOG(1, " %02X %02X %02X %02X %i %i\n", + pic2.ins, pic2.pend, pic2.mask, pic2.mask2, + ((pic.mask | pic.mask2) & (1 << 2)), + ((pic2.pend&~pic2.mask)&~pic2.mask2)); +#endif } -static void pic_autoeoi(void) + +void +pic_reset(void) { - int c; - - for (c=0;c<8;c++) - { - if (pic.ins&(1<0xFF) - { - if (!AT) - { - return; - } + if (num > 0xFF) { + if (! AT) + return; - pic2.pend|=(num>>8); - if ((pic2.pend&~pic2.mask)&~pic2.mask2) - { - pic.pend |= (1 << pic2.icw3); - } - } - else - { - pic.pend|=num; - } - pic_updatepending(); - } + pic2.pend |= (num >> 8); + if ((pic2.pend & ~pic2.mask) & ~pic2.mask2) + pic.pend |= (1 << pic2.icw3); + } else + pic.pend |= num; + + pic_updatepending(); + } } @@ -491,133 +471,99 @@ picintc(uint16_t num) { int c = 0; - if (!num) - { - /* pclog("Attempting to lower null IRQ\n"); */ - return; - } + if (!num) { + ERRLOG("PIC: Attempting to lower null IRQ\n"); + return; + } - if (AT && (num == pic.icw3) && (pic.icw3 == 4)) - { - num = 1 << 9; - } + if (AT && (num == pic.icw3) && (pic.icw3 == 4)) + num = 1 << 9; - while (!(num & (1 << c))) c++; + while (!(num & (1 << c))) + c++; - if (AT && (num == pic.icw3) && (pic.icw3 != 4)) - { - /* pclog("Attempting to lower cascaded IRQ %i\n"); */ + if (AT && (num == pic.icw3) && (pic.icw3 != 4)) { + ERRLOG("PIC: Attempting to lower cascaded IRQ %i\n"); + return; + } + + if (pic_current & num) + pic_current &= ~num; + + DBGLOG(1, "PIC: Lowering IRQ %i\n", c); + + if (num > 0xff) { + if (! AT) return; - } - if (pic_current & num) - { - pic_current &= ~num; - } + pic2.pend &= ~(num >> 8); + if (! ((pic2.pend & ~pic2.mask) & ~pic2.mask2)) + pic.pend &= ~(1 << pic2.icw3); + } else + pic.pend &= ~num; - /* pclog("Lowering IRQ %i\n", c); */ - - if (num > 0xff) - { - if (!AT) - { - return; - } - - pic2.pend &= ~(num >> 8); - if (!((pic2.pend&~pic2.mask)&~pic2.mask2)) - { - pic.pend &= ~(1 << pic2.icw3); - } - } - else - { - pic.pend&=~num; - } - pic_updatepending(); + pic_updatepending(); } -/* TODO: Verify this whole level-edge thing... edge/level mode is supposedly handled by bit 3 of ICW1, - but the PIIX spec mandates it being able to be edge/level per IRQ... maybe the PCI-era on-board - PIC ignores bit 3 of ICW1 but instead uses whatever is set in ELCR? - - Edit: Yes, the PIIX (and I suppose also the SIO) disables bit 3 of ICW1 and instead, uses the ELCR. - - Also, shouldn't there be only one picint(), and then edge/level is handled on processing? */ - -static uint8_t pic_process_interrupt(PIC* target_pic, int c) +static uint8_t +pic_process_interrupt(PIC* target_pic, int c) { - uint8_t pending = target_pic->pend & ~target_pic->mask; + uint8_t pending = target_pic->pend & ~target_pic->mask; - int pic_int = c & 7; - int pic_int_num = 1 << pic_int; + int pic_int = c & 7; + int pic_int_num = 1 << pic_int; - /* int pic_cur_num = 1 << c; */ + if (pending & pic_int_num) { + target_pic->pend &= ~pic_int_num; + target_pic->ins |= pic_int_num; + pic_update_mask(&target_pic->mask2, target_pic->ins); - if (pending & pic_int_num) - { - target_pic->pend &= ~pic_int_num; - target_pic->ins |= pic_int_num; - pic_update_mask(&target_pic->mask2, target_pic->ins); - - if (c >= 8) - { - pic.ins |= (1 << pic2.icw3); /*Cascade IRQ*/ - pic_update_mask(&pic.mask2, pic.ins); - } - - pic_updatepending(); - - if (target_pic->icw4 & 0x02) - { - (c >= 8) ? pic2_autoeoi() : pic_autoeoi(); - } - - if (!c) - { - pit_set_gate(&pit2, 0, 0); - } - - return pic_int + target_pic->vector; - } - else - { - return 0xFF; + if (c >= 8) { + pic.ins |= (1 << pic2.icw3); /*Cascade IRQ*/ + pic_update_mask(&pic.mask2, pic.ins); } + + pic_updatepending(); + + if (target_pic->icw4 & 0x02) + (c >= 8) ? pic2_autoeoi() : pic_autoeoi(); + + if (! c) + pit_set_gate(&pit2, 0, 0); + + return pic_int + target_pic->vector; + } else + return 0xFF; } -uint8_t picinterrupt(void) +uint8_t +picinterrupt(void) { - int c, d; - uint8_t ret; + int c, d; + uint8_t ret; - for (c = 0; c <= 7; c++) - { - if (AT && ((1 << c) == pic.icw3)) - { - for (d = 8; d <= 15; d++) - { - ret = pic_process_interrupt(&pic2, d); - if (ret != 0xFF) return ret; - } - } - else - { - ret = pic_process_interrupt(&pic, c); + for (c = 0; c <= 7; c++) { + if (AT && ((1 << c) == pic.icw3)) { + for (d = 8; d <= 15; d++) { + ret = pic_process_interrupt(&pic2, d); if (ret != 0xFF) return ret; - } - } - return 0xFF; + } + } else { + ret = pic_process_interrupt(&pic, c); + if (ret != 0xFF) return ret; + } + } + + return 0xFF; } void dumppic(void) { - pclog("PIC1 : MASK %02X PEND %02X INS %02X LEVEL %02X VECTOR %02X CASCADE %02X\n", pic.mask, pic.pend, pic.ins, (pic.icw1 & 8) ? 1 : 0, pic.vector, pic.icw3); - if (AT) { - pclog("PIC2 : MASK %02X PEND %02X INS %02X LEVEL %02X VECTOR %02X CASCADE %02X\n", pic2.mask, pic2.pend, pic2.ins, (pic2.icw1 & 8) ? 1 : 0, pic2.vector, pic2.icw3); - } + DEBUG("PIC1 : MASK %02X PEND %02X INS %02X LEVEL %02X VECTOR %02X CASCADE %02X\n", pic.mask, pic.pend, pic.ins, (pic.icw1 & 8) ? 1 : 0, pic.vector, pic.icw3); + if (AT) + DEBUG("PIC2 : MASK %02X PEND %02X INS %02X LEVEL %02X VECTOR %02X CASCADE %02X\n", pic2.mask, pic2.pend, pic2.ins, (pic2.icw1 & 8) ? 1 : 0, pic2.vector, pic2.icw3); } diff --git a/src/devices/system/pic.h b/src/devices/system/pic.h index 76d5616..356a655 100644 --- a/src/devices/system/pic.h +++ b/src/devices/system/pic.h @@ -8,7 +8,7 @@ * * Definitions for the Intel 8259 module. * - * Version: @(#)pic.h 1.0.1 2018/02/14 + * Version: @(#)pic.h 1.0.2 2018/09/05 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -41,14 +41,21 @@ typedef struct PIC { - uint8_t icw1,icw3,icw4,mask,ins,pend,mask2; - int icw; - uint8_t vector; - int read; + uint8_t icw1, + icw3, + icw4, + mask, + ins, + pend, + mask2; + uint8_t vector; + int icw; + int read; } PIC; -extern PIC pic, pic2; +extern PIC pic, + pic2; extern int pic_intpending; diff --git a/src/devices/system/pit.c b/src/devices/system/pit.c index 094d32e..a1dcfe6 100644 --- a/src/devices/system/pit.c +++ b/src/devices/system/pit.c @@ -8,7 +8,12 @@ * * Implement the PIT (Programmable Interval Timer.) * - * Version: @(#)pit.c 1.0.6 2018/05/06 + * B0 to 40, two writes to 43, then two reads + * - value does not change! + * B4 to 40, two writes to 43, then two reads + * - value _does_ change! + * + * Version: @(#)pit.c 1.0.7 2018/09/22 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -36,6 +41,7 @@ * Boston, MA 02111-1307 * USA. */ +#include #include #include #include @@ -56,8 +62,6 @@ #include "ppi.h" -/*B0 to 40, two writes to 43, then two reads - value does not change!*/ -/*B4 to 40, two writes to 43, then two reads - value _does_ change!*/ int displine; int firsttime = 1; PIT pit, @@ -333,8 +337,6 @@ pit_write(uint16_t addr, uint8_t val, void *priv) PIT *dev = (PIT *)priv; int t; - cycles -= (int)PITCONST; - switch (addr & 3) { case 3: /*CTRL*/ if ((val & 0xc0) == 0xc0) { @@ -439,8 +441,6 @@ pit_read(uint16_t addr, void *priv) uint8_t temp = 0xff; int t; - cycles -= (int)PITCONST; - switch (addr&3) { case 0: /*Timers*/ case 1: @@ -633,15 +633,21 @@ pit_reset(PIT *dev) } +void +setrtcconst(float clock) +{ + RTCCONST = clock / (float)32768.0; + + TIMER_USEC = (int64_t)((clock / 1000000.0f) * (float)(1LL << TIMER_SHIFT)); +} + + void setpitclock(float clock) { cpuclock = clock; - TIMER_USEC = (int64_t)((clock / 1000000.0f) * (float)(1 << TIMER_SHIFT)); - PITCONST = clock/(1193181.0f + (2.0f / 3.0f)); - RTCCONST = clock/32768.0f; CGACONST = (clock/(19687503.0f/11.0f)); MDACONST = (clock/2032125.0f); VGACONST1 = (clock/25175000.0f); @@ -652,7 +658,8 @@ setpitclock(float clock) video_update_timing(); - xt_cpu_multi = (int)((14318184.0*(double)(1 << TIMER_SHIFT)) / (double)machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].rspeed); + xt_cpu_multi = (int)((14318184.0*(double)(1 << TIMER_SHIFT)) / (double)machine_speed()); +// TIMER_USEC = (int64_t)((clock / 1000000.0f) * (float)(1 << TIMER_SHIFT)); device_speed_changed(); } diff --git a/src/devices/system/pit.h b/src/devices/system/pit.h index 79984f0..9f9f9ee 100644 --- a/src/devices/system/pit.h +++ b/src/devices/system/pit.h @@ -8,7 +8,7 @@ * * Definitions for Intel 8253 timer module. * - * Version: @(#)pit.h 1.0.3 2018/03/27 + * Version: @(#)pit.h 1.0.4 2018/09/05 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -94,17 +94,14 @@ extern void pit_reset(PIT *pit); extern void pit_set_gate(PIT *pit, int channel, int gate); extern void pit_set_using_timer(PIT *pit, int t, int using_timer); extern void pit_set_out_func(PIT *pit, int t, void (*func)(int new_out, int old_out)); -//extern void pit_clock(PIT *pit, int t); -extern void setpitclock(float clock); extern float pit_timer0_freq(void); - -//extern void pit_null_timer(int new_out, int old_out); -//extern void pit_irq0_timer(int new_out, int old_out); -//extern void pit_speaker_timer(int new_out, int old_out); extern void pit_irq0_timer_pcjr(int new_out, int old_out); extern void pit_refresh_timer_xt(int new_out, int old_out); extern void pit_refresh_timer_at(int new_out, int old_out); +extern void setrtcconst(float clock); +extern void setpitclock(float clock); + #endif /*EMU_PIT_H*/ diff --git a/src/devices/video/vid_ati18800.c b/src/devices/video/vid_ati18800.c index bf5e4af..d9144ea 100644 --- a/src/devices/video/vid_ati18800.c +++ b/src/devices/video/vid_ati18800.c @@ -8,7 +8,7 @@ * * ATI 18800 emulation (VGA Edge-16) * - * Version: @(#)vid_ati18800.c 1.0.8 2018/05/06 + * Version: @(#)vid_ati18800.c 1.0.9 2018/10/05 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -42,7 +42,6 @@ #include #include #include "../../emu.h" -#include "../../cpu/cpu.h" #include "../../io.h" #include "../../mem.h" #include "../../rom.h" @@ -53,13 +52,19 @@ #include "vid_ati_eeprom.h" -#define BIOS_ROM_PATH_WONDER L"video/ati/ati18800/vga_wonder_v3-1.02.bin" +# define BIOS_ROM_PATH_WONDER L"video/ati/ati18800/vga_wonder_v3-1.02.bin" +#if defined(DEV_BRANCH) && defined(USE_WONDER) +#endif #define BIOS_ROM_PATH_VGA88 L"video/ati/ati18800/vga88.bin" #define BIOS_ROM_PATH_EDGE16 L"video/ati/ati18800/vgaedge16.vbi" enum { +#if defined(DEV_BRANCH) && defined(USE_WONDER) ATI18800_WONDER = 0, ATI18800_VGA88, +#else + ATI18800_VGA88 = 0, +#endif ATI18800_EDGE16 }; @@ -92,9 +97,6 @@ static void ati18800_out(uint16_t addr, uint8_t val, void *p) break; case 0x1cf: ati18800->regs[ati18800->index] = val; -#if 0 - pclog("ATI 18800 ATI register write %02x %02x\n", ati18800->index, val); -#endif switch (ati18800->index) { case 0xb0: @@ -175,9 +177,6 @@ static uint8_t ati18800_in(uint16_t addr, void *p) temp = svga_in(addr, svga); break; } -#if 0 - if (addr != 0x3da) pclog("%02X %04X:%04X\n", temp, CS,cpu_state.pc); -#endif return temp; } @@ -203,137 +202,143 @@ static void ati18800_recalctimings(svga_t *svga) } } -static void *ati18800_init(const device_t *info) -{ - ati18800_t *ati18800 = malloc(sizeof(ati18800_t)); - memset(ati18800, 0, sizeof(ati18800_t)); - switch (info->local) { +static void * +ati18800_init(const device_t *info) +{ + ati18800_t *dev; + const wchar_t *fn = NULL; + + dev = (ati18800_t *)mem_alloc(sizeof(ati18800_t)); + memset(dev, 0x00, sizeof(ati18800_t)); + + switch (info->local) { #if defined(DEV_BRANCH) && defined(USE_WONDER) - case ATI18800_WONDER: - rom_init(&ati18800->bios_rom, BIOS_ROM_PATH_WONDER, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); - break; + case ATI18800_WONDER: + fn = BIOS_ROM_PATH_WONDER; + break; #endif - case ATI18800_VGA88: - rom_init(&ati18800->bios_rom, BIOS_ROM_PATH_VGA88, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); - break; + case ATI18800_VGA88: + fn = BIOS_ROM_PATH_VGA88; + break; - case ATI18800_EDGE16: - rom_init(&ati18800->bios_rom, BIOS_ROM_PATH_EDGE16, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); - break; + case ATI18800_EDGE16: + fn = BIOS_ROM_PATH_EDGE16; + break; - default: - break; - }; + default: + break; + }; - svga_init(&ati18800->svga, ati18800, 1 << 19, /*512kb*/ - ati18800_recalctimings, - ati18800_in, ati18800_out, - NULL, - NULL); + if (fn != NULL) { + rom_init(&dev->bios_rom, fn, 0xc0000, 0x8000, 0x7fff, + 0, MEM_MAPPING_EXTERNAL); + } - io_sethandler(0x01ce, 0x0002, ati18800_in, NULL, NULL, ati18800_out, NULL, NULL, ati18800); - io_sethandler(0x03c0, 0x0020, ati18800_in, NULL, NULL, ati18800_out, NULL, NULL, ati18800); + svga_init(&dev->svga, dev, 1 << 19, /*512kb*/ + ati18800_recalctimings, ati18800_in, ati18800_out, NULL, NULL); - ati18800->svga.miscout = 1; + io_sethandler(0x01ce, 0x0002, + ati18800_in,NULL,NULL, ati18800_out,NULL,NULL, dev); + io_sethandler(0x03c0, 0x0020, + ati18800_in,NULL,NULL, ati18800_out,NULL,NULL, dev); - ati_eeprom_load(&ati18800->eeprom, L"ati18800.nvr", 0); + dev->svga.miscout = 1; - return ati18800; + ati_eeprom_load(&dev->eeprom, L"ati18800.nvr", 0); + + video_inform(VID_TYPE_SPEC, + (const video_timings_t *)info->vid_timing); + + return dev; } -#if defined(DEV_BRANCH) && defined(USE_WONDER) -static int ati18800_wonder_available(void) -{ - return rom_present(BIOS_ROM_PATH_WONDER); -} -#endif -static int ati18800_vga88_available(void) +static void +ati18800_close(void *priv) { - return rom_present(BIOS_ROM_PATH_VGA88); + ati18800_t *dev = (ati18800_t *)priv; + + free(dev); } -static int ati18800_available(void) -{ - return rom_present(BIOS_ROM_PATH_EDGE16); -} -static void ati18800_close(void *p) +static void +speed_changed(void *priv) { - ati18800_t *ati18800 = (ati18800_t *)p; - - svga_close(&ati18800->svga); + ati18800_t *dev = (ati18800_t *)priv; - free(ati18800); + svga_recalctimings(&dev->svga); } -static void ati18800_speed_changed(void *p) -{ - ati18800_t *ati18800 = (ati18800_t *)p; - - svga_recalctimings(&ati18800->svga); -} -static void ati18800_force_redraw(void *p) +static void +force_redraw(void *priv) { - ati18800_t *ati18800 = (ati18800_t *)p; + ati18800_t *dev = (ati18800_t *)priv; - ati18800->svga.fullchange = changeframecount; -} - -static void ati18800_add_status_info(char *s, int max_len, void *p) -{ - ati18800_t *ati18800 = (ati18800_t *)p; - - svga_add_status_info(s, max_len, &ati18800->svga); + dev->svga.fullchange = changeframecount; } #if defined(DEV_BRANCH) && defined(USE_WONDER) -const device_t ati18800_wonder_device = +static int +ati18800_wonder_available(void) { - "ATI-18800", - DEVICE_ISA | DEVICE_UNSTABLE, - ATI18800_WONDER, - ati18800_init, - ati18800_close, - NULL, - ati18800_wonder_available, - ati18800_speed_changed, - ati18800_force_redraw, - ati18800_add_status_info, - NULL + return rom_present(BIOS_ROM_PATH_WONDER); +} +#endif + +static int +ati18800_vga88_available(void) +{ + return rom_present(BIOS_ROM_PATH_VGA88); +} + +static int +ati18800_available(void) +{ + return rom_present(BIOS_ROM_PATH_EDGE16); +} + + +static const video_timings_t ati18800_timing = {VID_ISA,8,16,32,8,16,32}; + +#if defined(DEV_BRANCH) && defined(USE_WONDER) +const device_t ati18800_wonder_device = { + "ATI-18800", + DEVICE_ISA | DEVICE_UNSTABLE, + ATI18800_WONDER, + ati18800_init, ati18800_close, NULL, + ati18800_wonder_available, + speed_changed, + force_redraw, + &ati18800_timing, + NULL }; #endif -const device_t ati18800_vga88_device = -{ - "ATI-18800-1", - DEVICE_ISA, - ATI18800_VGA88, - ati18800_init, - ati18800_close, - NULL, - ati18800_vga88_available, - ati18800_speed_changed, - ati18800_force_redraw, - ati18800_add_status_info, - NULL +const device_t ati18800_vga88_device = { + "ATI-18800-1", + DEVICE_ISA, + ATI18800_VGA88, + ati18800_init, ati18800_close, NULL, + ati18800_vga88_available, + speed_changed, + force_redraw, + &ati18800_timing, + NULL }; -const device_t ati18800_device = -{ - "ATI-18800-5", - DEVICE_ISA, - ATI18800_EDGE16, - ati18800_init, - ati18800_close, - NULL, - ati18800_available, - ati18800_speed_changed, - ati18800_force_redraw, - ati18800_add_status_info, - NULL +const device_t ati18800_device = { + "ATI-18800-5", + DEVICE_ISA, + ATI18800_EDGE16, + ati18800_init, ati18800_close, NULL, + ati18800_available, + speed_changed, + force_redraw, + &ati18800_timing, + NULL }; diff --git a/src/devices/video/vid_ati28800.c b/src/devices/video/vid_ati28800.c index d21d86f..71d9a50 100644 --- a/src/devices/video/vid_ati28800.c +++ b/src/devices/video/vid_ati28800.c @@ -8,7 +8,7 @@ * * ATI 28800 emulation (VGA Charger and Korean VGA) * - * Version: @(#)vid_ati28800.c 1.0.15 2018/09/03 + * Version: @(#)vid_ati28800.c 1.0.15 2018/10/05 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -43,13 +43,10 @@ #include #include #include "../../emu.h" -#include "../../cpu/cpu.h" #include "../../io.h" #include "../../mem.h" #include "../../rom.h" -#include "../../timer.h" #include "../../device.h" -#include "../system/pit.h" #include "video.h" #include "vid_svga.h" #include "vid_svga_render.h" @@ -57,7 +54,18 @@ #include "vid_ati_eeprom.h" +enum { + VID_VGACHARGER = 0, /* ATI VGA Charger (28800-5) */ + VID_VGAWONDERXL, /* Compaq ATI VGA Wonder XL (28800-5) */ +#if defined(DEV_BRANCH) && defined(USE_XL24) + VID_VGAWONDERXL24, /* Compaq ATI VGA Wonder XL24 (28800-6) */ +#endif + VID_ATIKOREANVGA /* ATI Korean VGA (28800-5) */ +}; + + #define BIOS_ATIKOR_PATH L"video/ati/ati28800/atikorvga.bin" +#define FONT_ATIKOR_PATH L"video/ati/ati28800/ati_ksc5601.rom" #define BIOS_VGAXL_EVEN_PATH L"video/ati/ati28800/xleven.bin" #define BIOS_VGAXL_ODD_PATH L"video/ati/ati28800/xlodd.bin" @@ -82,8 +90,6 @@ typedef struct { uint32_t memory; uint8_t id; - sc1502x_ramdac_t ramdac; - uint8_t port_03dd_val; uint16_t get_korean_font_kind; int in_get_korean_font_kind_set; @@ -95,59 +101,54 @@ typedef struct { static void -ati28800_out(uint16_t addr, uint8_t val, void *p) +ati28800_out(uint16_t port, uint8_t val, void *priv) { - ati28800_t *ati = (ati28800_t *)p; - svga_t *svga = &ati->svga; + ati28800_t *dev = (ati28800_t *)priv; + svga_t *svga = &dev->svga; uint8_t old; -#if 0 - pclog("ati28800_out : %04X %02X %04X:%04X\n", addr, val, CS,pc); -#endif + if (((port&0xfff0) == 0x3d0 || + (port&0xfff0) == 0x3b0) && !(svga->miscout&1)) port ^= 0x60; - if (((addr&0xFFF0) == 0x3D0 || - (addr&0xFFF0) == 0x3B0) && !(svga->miscout&1)) - addr ^= 0x60; - - switch (addr) { - case 0x1CE: - ati->index = val; + switch (port) { + case 0x1ce: + dev->index = val; break; - case 0x1CF: - old = ati->regs[ati->index]; - ati->regs[ati->index] = val; -#if 0 - pclog("ATI write reg=%02x\n", ati->index); -#endif - switch (ati->index) { + case 0x1cf: + old = dev->regs[dev->index]; + dev->regs[dev->index] = val; + switch (dev->index) { case 0xb2: case 0xbd: case 0xbe: - if (ati->regs[0xbe] & 8) /*Read/write bank mode*/ { - if (ati->regs[0xbd] & 4) { - svga->read_bank = (((ati->regs[0xb2] >> 5) & 7) * 0x20000); - svga->write_bank = (((ati->regs[0xb2] >> 1) & 7) * 0x20000); + if (dev->regs[0xbe] & 8) /*Read/write bank mode*/ { + if (dev->regs[0xbd] & 4) { + svga->read_bank = (((dev->regs[0xb2] >> 5) & 7) * 0x20000); + svga->write_bank = (((dev->regs[0xb2] >> 1) & 7) * 0x20000); } else { - svga->read_bank = (((ati->regs[0xb2] >> 5) & 7) * 0x10000); - svga->write_bank = (((ati->regs[0xb2] >> 1) & 7) * 0x10000); + svga->read_bank = (((dev->regs[0xb2] >> 5) & 7) * 0x10000); + svga->write_bank = (((dev->regs[0xb2] >> 1) & 7) * 0x10000); } } else { /*Single bank mode*/ - if (ati->regs[0xbd] & 4) { - svga->read_bank = (((ati->regs[0xb2] >> 1) & 7) * 0x20000); - svga->write_bank = (((ati->regs[0xb2] >> 1) & 7) * 0x20000); + if (dev->regs[0xbd] & 4) { + svga->read_bank = (((dev->regs[0xb2] >> 1) & 7) * 0x20000); + svga->write_bank = (((dev->regs[0xb2] >> 1) & 7) * 0x20000); } else { - svga->read_bank = (((ati->regs[0xb2] >> 1) & 7) * 0x10000); - svga->write_bank = (((ati->regs[0xb2] >> 1) & 7) * 0x10000); + svga->read_bank = (((dev->regs[0xb2] >> 1) & 7) * 0x10000); + svga->write_bank = (((dev->regs[0xb2] >> 1) & 7) * 0x10000); } } break; case 0xb3: - ati_eeprom_write(&ati->eeprom, val & 8, val & 2, val & 1); + ati_eeprom_write(&dev->eeprom, val & 8, val & 2, val & 1); break; case 0xb6: + if (val & 1) + DEBUG("Extended 0xB6 bit 0 enabled\n"); + if ((old ^ val) & 0x10) svga_recalctimings(svga); break; @@ -163,18 +164,18 @@ ati28800_out(uint16_t addr, uint8_t val, void *p) } break; - case 0x3C6: - case 0x3C7: - case 0x3C8: - case 0x3C9: - sc1502x_ramdac_out(addr, val, &ati->ramdac, svga); + case 0x3c6: + case 0x3c7: + case 0x3c8: + case 0x3c9: + sc1502x_ramdac_out(port, val, svga->ramdac, svga); return; - - case 0x3D4: + + case 0x3d4: svga->crtcreg = val & 0x3f; return; - case 0x3D5: + case 0x3d5: if ((svga->crtcreg < 7) && (svga->crtc[0x11] & 0x80)) return; if ((svga->crtcreg == 7) && (svga->crtc[0x11] & 0x80)) @@ -190,210 +191,195 @@ ati28800_out(uint16_t addr, uint8_t val, void *p) break; } - svga_out(addr, val, svga); + svga_out(port, val, svga); } static void -ati28800k_out(uint16_t addr, uint8_t val, void *p) +ati28800k_out(uint16_t port, uint8_t val, void *priv) { - ati28800_t *ati = (ati28800_t *)p; - svga_t *svga = &ati->svga; - uint16_t oldaddr = addr; + ati28800_t *dev = (ati28800_t *)priv; + svga_t *svga = &dev->svga; + uint16_t oldport = port; - if (((addr&0xFFF0) == 0x3D0 || - (addr&0xFFF0) == 0x3B0) && !(svga->miscout&1)) - addr ^= 0x60; + if (((port&0xfff0) == 0x3d0 || + (port&0xfff0) == 0x3b0) && !(svga->miscout&1)) port ^= 0x60; - switch (addr) { - case 0x1CF: - if (ati->index == 0xBF && ((ati->regs[0xBF] ^ val) & 0x20)) { - ati->ksc5601_mode_enabled = val & 0x20; + switch (port) { + case 0x1cf: + if (dev->index == 0xBF && ((dev->regs[0xBF] ^ val) & 0x20)) { + dev->ksc5601_mode_enabled = val & 0x20; svga_recalctimings(svga); } - ati28800_out(oldaddr, val, p); + ati28800_out(oldport, val, priv); break; - case 0x3DD: - ati->port_03dd_val = val; - if (val == 1) ati->get_korean_font_enabled = 0; - if (ati->in_get_korean_font_kind_set) { - ati->get_korean_font_kind = (val << 8) | (ati->get_korean_font_kind & 0xFF); - ati->get_korean_font_enabled = 1; - ati->get_korean_font_index = 0; - ati->in_get_korean_font_kind_set = 0; + case 0x3dd: + dev->port_03dd_val = val; + if (val == 1) dev->get_korean_font_enabled = 0; + if (dev->in_get_korean_font_kind_set) { + dev->get_korean_font_kind = (val << 8) | (dev->get_korean_font_kind & 0xFF); + dev->get_korean_font_enabled = 1; + dev->get_korean_font_index = 0; + dev->in_get_korean_font_kind_set = 0; } break; - case 0x3DE: - ati->in_get_korean_font_kind_set = 0; - if (ati->get_korean_font_enabled && (ati->regs[0xBF] & 0x20)) { - if ((ati->get_korean_font_base & 0x7F) > 0x20 && (ati->get_korean_font_base & 0x7F) < 0x7F) - fontdatksc5601_user[(ati->get_korean_font_kind & 4) * 24 + (ati->get_korean_font_base & 0x7F) - 0x20].chr[ati->get_korean_font_index] = val; - ati->get_korean_font_index++; - ati->get_korean_font_index &= 0x1F; + case 0x3de: + dev->in_get_korean_font_kind_set = 0; + if (dev->get_korean_font_enabled) { + if ((dev->get_korean_font_base & 0x7F) > 0x20 && (dev->get_korean_font_base & 0x7F) < 0x7F) + fontdatksc5601_user[(dev->get_korean_font_kind & 4) * 24 + (dev->get_korean_font_base & 0x7F) - 0x20].chr[dev->get_korean_font_index] = val; + dev->get_korean_font_index++; + dev->get_korean_font_index &= 0x1F; } else { - switch(ati->port_03dd_val) { + switch(dev->port_03dd_val) { case 0x10: - ati->get_korean_font_base = ((val & 0x7F) << 7) | (ati->get_korean_font_base & 0x7F); + dev->get_korean_font_base = ((val & 0x7F) << 7) | (dev->get_korean_font_base & 0x7F); break; case 8: - ati->get_korean_font_base = (ati->get_korean_font_base & 0x3F80) | (val & 0x7F); + dev->get_korean_font_base = (dev->get_korean_font_base & 0x3F80) | (val & 0x7F); break; case 1: - ati->get_korean_font_kind = (ati->get_korean_font_kind & 0xFF00) | val; + dev->get_korean_font_kind = (dev->get_korean_font_kind & 0xFF00) | val; if (val & 2) - ati->in_get_korean_font_kind_set = 1; + dev->in_get_korean_font_kind_set = 1; break; } } break; default: - ati28800_out(oldaddr, val, p); + ati28800_out(oldport, val, priv); break; } } static uint8_t -ati28800_in(uint16_t addr, void *p) +ati28800_in(uint16_t port, void *priv) { - ati28800_t *ati = (ati28800_t *)p; - svga_t *svga = &ati->svga; - uint8_t temp; + ati28800_t *dev = (ati28800_t *)priv; + svga_t *svga = &dev->svga; + uint8_t ret = 0xff; -#if 0 - if (addr != 0x3da) pclog("ati28800_in : %04X ", addr); -#endif + if (((port&0xfff0) == 0x3d0 || + (port&0xfff0) == 0x3b0) && !(svga->miscout&1)) port ^= 0x60; - if (((addr&0xFFF0) == 0x3D0 || - (addr&0xFFF0) == 0x3B0) && !(svga->miscout&1)) addr ^= 0x60; - - switch (addr) { - case 0x1CE: - temp = ati->index; + switch (port) { + case 0x1ce: + ret = dev->index; break; - case 0x1CF: - switch (ati->index) { + case 0x1cf: + switch (dev->index) { case 0xaa: - temp = ati->id; + ret = dev->id; break; case 0xb0: - if (ati->memory == 1024) - temp = 0x08; - else if (ati->memory == 512) - temp = 0x10; + if (dev->memory == 1024) + ret = 0x08; + else if (dev->memory == 512) + ret = 0x10; else - temp = 0x00; - ati->regs[0xb0] |= temp; + ret = 0x00; + dev->regs[0xb0] |= ret; break; case 0xb7: - temp = ati->regs[ati->index] & ~8; - if (ati_eeprom_read(&ati->eeprom)) - temp |= 8; + ret = dev->regs[dev->index] & ~8; + if (ati_eeprom_read(&dev->eeprom)) + ret |= 8; break; default: - temp = ati->regs[ati->index]; + ret = dev->regs[dev->index]; break; } break; - case 0x3C2: + case 0x3c2: if ((svga->vgapal[0].r + svga->vgapal[0].g + svga->vgapal[0].b) >= 0x50) - temp = 0; + ret = 0; else - temp = 0x10; + ret = 0x10; break; - case 0x3C6: - case 0x3C7: - case 0x3C8: - case 0x3C9: - return sc1502x_ramdac_in(addr, &ati->ramdac, svga); + case 0x3c6: + case 0x3c7: + case 0x3c8: + case 0x3c9: + ret = sc1502x_ramdac_in(port, svga->ramdac, svga); - case 0x3D4: - temp = svga->crtcreg; + case 0x3d4: + ret = svga->crtcreg; break; - case 0x3D5: - temp = svga->crtc[svga->crtcreg]; + case 0x3d5: + ret = svga->crtc[svga->crtcreg]; break; default: - temp = svga_in(addr, svga); + ret = svga_in(port, svga); break; } -#if 0 - if (addr != 0x3da) pclog("%02X %04X:%04X\n", temp, CS,cpu_state.pc); -#endif - return temp; + return ret; } static uint8_t -ati28800k_in(uint16_t addr, void *p) +ati28800k_in(uint16_t port, void *priv) { - ati28800_t *ati = (ati28800_t *)p; - svga_t *svga = &ati->svga; - uint16_t oldaddr = addr; - uint8_t temp = 0xFF; + ati28800_t *dev = (ati28800_t *)priv; + svga_t *svga = &dev->svga; + uint16_t oldport = port; + uint8_t ret = 0xff; -#if 0 - if (addr != 0x3da) pclog("ati28800_in : %04X ", addr); -#endif + if (((port&0xfff0) == 0x3d0 || + (port&0xfff0) == 0x3b0) && !(svga->miscout&1)) port ^= 0x60; - if (((addr&0xFFF0) == 0x3D0 || - (addr&0xFFF0) == 0x3B0) && !(svga->miscout&1)) addr ^= 0x60; - - switch (addr) { - case 0x3DE: - if (ati->get_korean_font_enabled && (ati->regs[0xBF] & 0x20)) { - switch(ati->get_korean_font_kind >> 8) { + switch (port) { + case 0x3de: + if (dev->get_korean_font_enabled) { + switch(dev->get_korean_font_kind >> 8) { case 4: /* ROM font */ - temp = fontdatksc5601[ati->get_korean_font_base].chr[ati->get_korean_font_index++]; + ret = fontdatksc5601[dev->get_korean_font_base].chr[dev->get_korean_font_index++]; break; case 2: /* User defined font */ - if ((ati->get_korean_font_base & 0x7F) > 0x20 && (ati->get_korean_font_base & 0x7F) < 0x7F) - temp = fontdatksc5601_user[(ati->get_korean_font_kind & 4) * 24 + (ati->get_korean_font_base & 0x7F) - 0x20].chr[ati->get_korean_font_index]; + if ((dev->get_korean_font_base & 0x7F) > 0x20 && (dev->get_korean_font_base & 0x7F) < 0x7F) + ret = fontdatksc5601_user[(dev->get_korean_font_kind & 4) * 24 + (dev->get_korean_font_base & 0x7F) - 0x20].chr[dev->get_korean_font_index]; else - temp = 0xFF; - ati->get_korean_font_index++; + ret = 0xff; + dev->get_korean_font_index++; break; default: break; } - ati->get_korean_font_index &= 0x1F; + dev->get_korean_font_index &= 0x1F; } break; default: - temp = ati28800_in(oldaddr, p); + ret = ati28800_in(oldport, priv); break; } -#ifdef _DEBUG - if (addr != 0x3da) pclog("%02X %04X:%04X\n", temp, CS,cpu_state.pc); -#endif - return temp; + return ret; } static void ati28800_recalctimings(svga_t *svga) { - ati28800_t *ati = (ati28800_t *)svga->p; + ati28800_t *dev = (ati28800_t *)svga->p; - switch(((ati->regs[0xbe] & 0x10) >> 1) | ((ati->regs[0xb9] & 2) << 1) | ((svga->miscout & 0x0C) >> 2)) { + switch(((dev->regs[0xbe] & 0x10) >> 1) | ((dev->regs[0xb9] & 2) << 1) | ((svga->miscout & 0x0C) >> 2)) { case 0x00: svga->clock = cpuclock / 42954000.0; break; case 0x01: svga->clock = cpuclock / 48771000.0; break; case 0x03: svga->clock = cpuclock / 36000000.0; break; @@ -411,9 +397,9 @@ ati28800_recalctimings(svga_t *svga) default: break; } - if (ati->regs[0xb8] & 0x40) svga->clock *= 2; + if (dev->regs[0xb8] & 0x40) svga->clock *= 2; - if (ati->regs[0xb6] & 0x10) { + if (dev->regs[0xb6] & 0x10) { svga->hdisp <<= 1; svga->htotal <<= 1; svga->rowoffset <<= 1; @@ -427,7 +413,7 @@ ati28800_recalctimings(svga_t *svga) svga->vblankstart <<= 1; } - if (!svga->scrblank && (ati->regs[0xb0] & 0x20)) { + if (!svga->scrblank && (dev->regs[0xb0] & 0x20)) { /* Extended 256 color modes. */ switch (svga->bpp) { case 8: @@ -447,117 +433,124 @@ ati28800_recalctimings(svga_t *svga) } -static void * -ati28800_init(const device_t *info) -{ - ati28800_t *ati; - - ati = malloc(sizeof(ati28800_t)); - memset(ati, 0x00, sizeof(ati28800_t)); - - ati->memory = device_get_config_int("memory"); - - switch(info->local) { - case VID_VGAWONDERXL: - ati->id = 6; - rom_init_interleaved(&ati->bios_rom, - BIOS_VGAXL_EVEN_PATH, - BIOS_VGAXL_ODD_PATH, - 0xc0000, 0x10000, 0xffff, - 0, MEM_MAPPING_EXTERNAL); - break; - -#if defined(DEV_BRANCH) && defined(USE_XL24) - case VID_VGAWONDERXL24: - ati->id = 6; - rom_init_interleaved(&ati->bios_rom, - BIOS_XL24_EVEN_PATH, - BIOS_XL24_ODD_PATH, - 0xc0000, 0x10000, 0xffff, - 0, MEM_MAPPING_EXTERNAL); - break; -#endif - - default: - ati->id = 5; - rom_init(&ati->bios_rom, - BIOS_ROM_PATH, - 0xc0000, 0x8000, 0x7fff, - 0, MEM_MAPPING_EXTERNAL); - break; - } - - svga_init(&ati->svga, ati, ati->memory << 10, /*default: 512kb*/ - ati28800_recalctimings, - ati28800_in, ati28800_out, - NULL, - NULL); - - io_sethandler(0x01ce, 2, - ati28800_in, NULL, NULL, - ati28800_out, NULL, NULL, ati); - io_sethandler(0x03c0, 32, - ati28800_in, NULL, NULL, - ati28800_out, NULL, NULL, ati); - - ati->svga.miscout = 1; - - ati_eeprom_load(&ati->eeprom, L"ati28800.nvr", 0); - - return(ati); -} - - static void ati28800k_recalctimings(svga_t *svga) { - ati28800_t *ati = (ati28800_t *) svga->p; + ati28800_t *dev = (ati28800_t *)svga->p; ati28800_recalctimings(svga); - if (svga->render == svga_render_text_80 && ati->ksc5601_mode_enabled) { + if (svga->render == svga_render_text_80 && dev->ksc5601_mode_enabled) { svga->render = svga_render_text_80_ksc5601; } } static void * -ati28800k_init(const device_t *info) +ati28800_init(const device_t *info) { - ati28800_t *ati = malloc(sizeof(ati28800_t)); - memset(ati, 0, sizeof(ati28800_t)); + ati28800_t *dev; - ati->memory = device_get_config_int("memory"); + dev = (ati28800_t *)mem_alloc(sizeof(ati28800_t)); + memset(dev, 0x00, sizeof(ati28800_t)); - ati->port_03dd_val = 0; - ati->get_korean_font_base = 0; - ati->get_korean_font_index = 0; - ati->get_korean_font_enabled = 0; - ati->get_korean_font_kind = 0; - ati->in_get_korean_font_kind_set = 0; - ati->ksc5601_mode_enabled = 0; + dev->memory = device_get_config_int("memory"); - rom_init(&ati->bios_rom, BIOS_ATIKOR_PATH, - 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); - loadfont(FONT_ATIKOR_PATH, 6); + switch(info->local) { + case 0: + dev->id = 5; + rom_init(&dev->bios_rom, + BIOS_ROM_PATH, + 0xc0000, 0x8000, 0x7fff, + 0, MEM_MAPPING_EXTERNAL); + ati_eeprom_load(&dev->eeprom, L"ati28800.nvr", 0); + break; - svga_init(&ati->svga, ati, - ati->memory << 10, /*Memory size, default 512KB*/ - ati28800k_recalctimings, - ati28800k_in, ati28800k_out, - NULL, - NULL); + case VID_VGAWONDERXL: + dev->id = 6; + rom_init_interleaved(&dev->bios_rom, + BIOS_VGAXL_EVEN_PATH, + BIOS_VGAXL_ODD_PATH, + 0xc0000, 0x10000, 0xffff, + 0, MEM_MAPPING_EXTERNAL); + ati_eeprom_load(&dev->eeprom, L"ati28800xl.nvr", 0); + break; - io_sethandler(0x01ce, 2, - ati28800k_in,NULL,NULL, ati28800k_out,NULL,NULL, ati); - io_sethandler(0x03c0, 32, - ati28800k_in,NULL,NULL, ati28800k_out,NULL,NULL, ati); +#if defined(DEV_BRANCH) && defined(USE_XL24) + case VID_VGAWONDERXL24: + dev->id = 6; + rom_init_interleaved(&dev->bios_rom, + BIOS_XL24_EVEN_PATH, + BIOS_XL24_ODD_PATH, + 0xc0000, 0x10000, 0xffff, + 0, MEM_MAPPING_EXTERNAL); + ati_eeprom_load(&dev->eeprom, L"ati28800xl24.nvr", 0); + break; +#endif - ati->svga.miscout = 1; + case VID_ATIKOREANVGA: + dev->port_03dd_val = 0; + dev->get_korean_font_base = 0; + dev->get_korean_font_index = 0; + dev->get_korean_font_enabled = 0; + dev->get_korean_font_kind = 0; + dev->in_get_korean_font_kind_set = 0; + dev->ksc5601_mode_enabled = 0; - ati_eeprom_load(&ati->eeprom, L"atikorvga.nvr", 0); + video_load_font(FONT_ATIKOR_PATH, 6); - return(ati); + rom_init(&dev->bios_rom, BIOS_ATIKOR_PATH, + 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + ati_eeprom_load(&dev->eeprom, L"atikorvga.nvr", 0); + break; + + default: + break; + } + + if (info->local == VID_ATIKOREANVGA) { + svga_init(&dev->svga, dev, dev->memory << 10, /*default: 512KB*/ + ati28800k_recalctimings, + ati28800k_in, ati28800k_out, NULL, NULL); + dev->svga.ksc5601_sbyte_mask = 0; + + dev->svga.ramdac = device_add(&sc1502x_ramdac_device); + + io_sethandler(0x01ce, 2, + ati28800k_in,NULL,NULL, ati28800k_out,NULL,NULL, dev); + io_sethandler(0x03c0, 32, + ati28800k_in,NULL,NULL, ati28800k_out,NULL,NULL, dev); + + } else { + svga_init(&dev->svga, dev, dev->memory << 10, /*default: 512kb*/ + ati28800_recalctimings, + ati28800_in, ati28800_out, NULL, NULL); + + dev->svga.ramdac = device_add(&sc1502x_ramdac_device); + + io_sethandler(0x01ce, 2, + ati28800_in,NULL,NULL, ati28800_out,NULL,NULL, dev); + io_sethandler(0x03c0, 32, + ati28800_in,NULL,NULL, ati28800_out,NULL,NULL, dev); + } + + dev->svga.miscout = 1; + + video_inform(VID_TYPE_SPEC, + (const video_timings_t *)info->vid_timing); + + return(dev); +} + + +static void +ati28800_close(void *priv) +{ + ati28800_t *dev = (ati28800_t *)priv; + + svga_close(&dev->svga); + + free(dev); } @@ -567,7 +560,6 @@ ati28800_available(void) return(rom_present(BIOS_ROM_PATH)); } - static int ati28800k_available(void) { @@ -575,15 +567,13 @@ ati28800k_available(void) rom_present(FONT_ATIKOR_PATH))); } - static int -compaq_ati28800_available(void) +ati28800_compaq_available(void) { return((rom_present(BIOS_VGAXL_EVEN_PATH) && rom_present(BIOS_VGAXL_ODD_PATH))); } - #if defined(DEV_BRANCH) && defined(USE_XL24) static int ati28800_wonderxl24_available(void) @@ -595,149 +585,122 @@ ati28800_wonderxl24_available(void) static void -ati28800_close(void *priv) +speed_changed(void *priv) { - ati28800_t *ati = (ati28800_t *)priv; + ati28800_t *dev = (ati28800_t *)priv; - svga_close(&ati->svga); - - free(ati); + svga_recalctimings(&dev->svga); } static void -ati28800_speed_changed(void *p) +force_redraw(void *priv) { - ati28800_t *ati = (ati28800_t *)p; + ati28800_t *dev = (ati28800_t *)priv; - svga_recalctimings(&ati->svga); + dev->svga.fullchange = changeframecount; } -static void -ati28800_force_redraw(void *priv) -{ - ati28800_t *ati = (ati28800_t *)priv; - - ati->svga.fullchange = changeframecount; -} - -static void ati28800_add_status_info(char *s, int max_len, void *priv) -{ - ati28800_t *ati = (ati28800_t *)priv; - - svga_add_status_info(s, max_len, &ati->svga); -} - -void ati28800k_add_status_info(char *s, int max_len, void *p) -{ - char temps[128]; - ati28800_t *ati = (ati28800_t *)p; - - sprintf(temps, "Korean SVGA mode enabled : %s\n\n", - ati->ksc5601_mode_enabled ? "Yes" : "No"); - strncat(s, temps, max_len); - - ati28800_add_status_info(s, max_len, p); -} - - -static const device_config_t ati28800_config[] = -{ +static const device_config_t ati28800_config[] = { + { + "memory", "Memory size", CONFIG_SELECTION, "", 512, { - "memory", "Memory size", CONFIG_SELECTION, "", 512, { - { - "256 kB", 256 - }, - { - "512 kB", 512 - }, - { - "1024 kB", 1024 - }, - { - "" - } + "256 KB", 256 + }, + { + "512 KB", 512 + }, + { + "1 MB", 1024 + }, + { + "" } - }, - { - "", "", -1 } + }, + { + "", "", -1 + } }; #if defined(DEV_BRANCH) && defined(USE_XL24) -static const device_config_t ati28800_wonderxl_config[] = -{ +static const device_config_t ati28800_wonderxl_config[] = { + { + "memory", "Memory size", CONFIG_SELECTION, "", 512, { - "memory", "Memory size", CONFIG_SELECTION, "", 512, { - { - "256 kB", 256 - }, - { - "512 kB", 512 - }, - { - "1 MB", 1024 - }, - { - "" - } + "256 KB", 256 + }, + { + "512 KB", 512 + }, + { + "1 MB", 1024 + }, + { + "" } - }, - { - "", "", -1 } + }, + { + "", "", -1 + } }; #endif + +static const video_timings_t ati28800_timing = {VID_ISA,3,3,6,5,5,10}; const device_t ati28800_device = { "ATI-28800", DEVICE_ISA, 0, ati28800_init, ati28800_close, NULL, ati28800_available, - ati28800_speed_changed, - ati28800_force_redraw, - ati28800_add_status_info, + speed_changed, + force_redraw, + &ati28800_timing, ati28800_config }; +static const video_timings_t ati28800k_timing = {VID_ISA,3,3,6,5,5,10}; const device_t ati28800k_device = { "ATI Korean VGA", DEVICE_ISA, VID_ATIKOREANVGA, - ati28800k_init, ati28800_close, NULL, + ati28800_init, ati28800_close, NULL, ati28800k_available, - ati28800_speed_changed, - ati28800_force_redraw, - ati28800k_add_status_info, + speed_changed, + force_redraw, + &ati28800k_timing, ati28800_config }; -const device_t compaq_ati28800_device = { +static const video_timings_t ati28800_compaq_timing = {VID_ISA,3,3,6,5,5,10}; +const device_t ati28800_compaq_device = { "Compaq ATI-28800", DEVICE_ISA, VID_VGAWONDERXL, ati28800_init, ati28800_close, NULL, - compaq_ati28800_available, - ati28800_speed_changed, - ati28800_force_redraw, - ati28800_add_status_info, + ati28800_compaq_available, + speed_changed, + force_redraw, + &ati28800_compaq_timing, ati28800_config }; #if defined(DEV_BRANCH) && defined(USE_XL24) +static const video_timings_t ati28800w_timing = {VID_ISA,3,3,6,5,5,10}; const device_t ati28800_wonderxl24_device = { "ATI-28800 (VGA Wonder XL24)", DEVICE_ISA | DEVICE_UNSTABLE, VID_VGAWONDERXL24, ati28800_init, ati28800_close, NULL, ati28800_wonderxl24_available, - ati28800_speed_changed, - ati28800_force_redraw, - ati28800_add_status_info, + speed_changed, + force_redraw, + &ati28800w_timing, ati28800_wonderxl_config }; #endif diff --git a/src/devices/video/vid_ati68860_ramdac.c b/src/devices/video/vid_ati68860_ramdac.c index 0b76ac7..1833da2 100644 --- a/src/devices/video/vid_ati68860_ramdac.c +++ b/src/devices/video/vid_ati68860_ramdac.c @@ -28,7 +28,7 @@ * 7 If set can remove "snow" in some cases * (A860_Delay_L ?) ?? * - * Version: @(#)vid_ati68860.c 1.0.3 2018/05/06 + * Version: @(#)vid_ati68860.c 1.0.4 2018/10/05 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -59,9 +59,11 @@ #include #include #include +#include #include #include "../../emu.h" #include "../../mem.h" +#include "../../device.h" #include "video.h" #include "vid_svga.h" #include "vid_svga_render.h" @@ -69,7 +71,7 @@ void -ati68860_ramdac_out(uint16_t addr, uint8_t val, ati68860_ramdac_t *ramdac, svga_t *svga) +ati68860_ramdac_out(uint16_t addr, uint8_t val, ati68860_ramdac_t *dev, svga_t *svga) { switch (addr) { case 0: @@ -89,153 +91,187 @@ ati68860_ramdac_out(uint16_t addr, uint8_t val, ati68860_ramdac_t *ramdac, svga_ break; default: - ramdac->regs[addr & 0xf] = val; + dev->regs[addr & 0xf] = val; switch (addr & 0xf) { case 0x4: - ramdac->dac_write = val; - ramdac->dac_pos = 0; + dev->dac_addr = val; + dev->dac_pos = 0; break; case 0x5: - switch (ramdac->dac_pos) { - case 0: - ramdac->dac_r = val; - ramdac->dac_pos++; + switch (dev->dac_pos) { + case 0: + dev->dac_r = val; + dev->dac_pos++; break; - case 1: - ramdac->dac_g = val; - ramdac->dac_pos++; + case 1: + dev->dac_g = val; + dev->dac_pos++; break; - case 2: - if (ramdac->dac_write > 1) + case 2: + if (dev->dac_addr > 1) break; - ramdac->pal[ramdac->dac_write].r = ramdac->dac_r; - ramdac->pal[ramdac->dac_write].g = ramdac->dac_g; - ramdac->pal[ramdac->dac_write].b = val; - if (ramdac->ramdac_type == RAMDAC_8BIT) - ramdac->pallook[ramdac->dac_write] = makecol32(ramdac->pal[ramdac->dac_write].r, ramdac->pal[ramdac->dac_write].g, ramdac->pal[ramdac->dac_write].b); + dev->pal[dev->dac_addr].r = dev->dac_r; + dev->pal[dev->dac_addr].g = dev->dac_g; + dev->pal[dev->dac_addr].b = val; + if (dev->ramdac_type == RAMDAC_8BIT) + dev->pallook[dev->dac_addr] = makecol32(dev->pal[dev->dac_addr].r, + dev->pal[dev->dac_addr].g, + dev->pal[dev->dac_addr].b); else - ramdac->pallook[ramdac->dac_write] = makecol32((ramdac->pal[ramdac->dac_write].r & 0x3f) * 4, (ramdac->pal[ramdac->dac_write].g & 0x3f) * 4, (ramdac->pal[ramdac->dac_write].b & 0x3f) * 4); - ramdac->dac_pos = 0; - ramdac->dac_write = (ramdac->dac_write + 1) & 255; + dev->pallook[dev->dac_addr] = makecol32(video_6to8[dev->pal[dev->dac_addr].r & 0x3f], + video_6to8[dev->pal[dev->dac_addr].g & 0x3f], + video_6to8[dev->pal[dev->dac_addr].b & 0x3f]); + dev->dac_pos = 0; + dev->dac_addr = (dev->dac_addr + 1) & 255; break; } break; - + case 0xb: switch (val) { - case 0x82: - ramdac->render = svga_render_4bpp_highres; - break; + case 0x82: + dev->render = svga_render_4bpp_highres; + break; - case 0x83: - ramdac->render = svga_render_8bpp_highres; - break; + case 0x83: + dev->render = svga_render_8bpp_highres; + break; - case 0xa0: case 0xb0: - ramdac->render = svga_render_15bpp_highres; - break; + case 0xa0: case 0xb0: + dev->render = svga_render_15bpp_highres; + break; - case 0xa1: case 0xb1: - ramdac->render = svga_render_16bpp_highres; - break; + case 0xa1: case 0xb1: + dev->render = svga_render_16bpp_highres; + break; - case 0xc0: case 0xd0: - ramdac->render = svga_render_24bpp_highres; - break; + case 0xc0: case 0xd0: + dev->render = svga_render_24bpp_highres; + break; - case 0xe2: case 0xf7: - ramdac->render = svga_render_32bpp_highres; - break; + case 0xe2: case 0xf7: + dev->render = svga_render_32bpp_highres; + break; - case 0xe3: - ramdac->render = svga_render_ABGR8888_highres; - break; + case 0xe3: + dev->render = svga_render_ABGR8888_highres; + break; - case 0xf2: - ramdac->render = svga_render_RGBA8888_highres; - break; + case 0xf2: + dev->render = svga_render_RGBA8888_highres; + break; - default: - ramdac->render = svga_render_8bpp_highres; - break; - } - break; + default: + dev->render = svga_render_8bpp_highres; + break; + } + break; - case 0xc: - svga_set_ramdac_type(svga, (val & 1) ? RAMDAC_6BIT : RAMDAC_8BIT); - break; - } - break; + case 0xc: + svga_set_ramdac_type(svga, (val & 1) ? RAMDAC_6BIT : RAMDAC_8BIT); + break; + } + break; } } uint8_t -ati68860_ramdac_in(uint16_t addr, ati68860_ramdac_t *ramdac, svga_t *svga) +ati68860_ramdac_in(uint16_t addr, ati68860_ramdac_t *dev, svga_t *svga) { - uint8_t ret = 0; + uint8_t temp = 0; switch (addr) { case 0: - ret = svga_in(0x3c8, svga); + temp = svga_in(0x3c8, svga); break; case 1: - ret = svga_in(0x3c9, svga); + temp = svga_in(0x3c9, svga); break; case 2: - ret = svga_in(0x3c6, svga); + temp = svga_in(0x3c6, svga); break; case 3: - ret = svga_in(0x3c7, svga); + temp = svga_in(0x3c7, svga); break; case 4: case 8: - ret = 2; + temp = 2; break; case 6: case 0xa: - ret = 0x1d; + temp = 0x1d; break; case 0xf: - ret = 0xd0; + temp = 0xd0; break; default: - ret = ramdac->regs[addr & 0xf]; + temp = dev->regs[addr & 0xf]; break; } - return ret; + return temp; } void -ati68860_ramdac_init(ati68860_ramdac_t *ramdac) -{ - ramdac->render = svga_render_8bpp_highres; -} - - -void -ati68860_set_ramdac_type(ati68860_ramdac_t *ramdac, int type) +ati68860_set_ramdac_type(ati68860_ramdac_t *dev, int type) { int c; - if (ramdac->ramdac_type != type) { - ramdac->ramdac_type = type; - + if (dev->ramdac_type != type) { + dev->ramdac_type = type; for (c = 0; c < 2; c++) { - if (ramdac->ramdac_type == RAMDAC_8BIT) - ramdac->pallook[c] = makecol32(ramdac->pal[c].r, ramdac->pal[c].g, ramdac->pal[c].b); + if (dev->ramdac_type == RAMDAC_8BIT) + dev->pallook[c] = makecol32(dev->pal[c].r, + dev->pal[c].g, + dev->pal[c].b); else - ramdac->pallook[c] = makecol32((ramdac->pal[c].r & 0x3f) * 4, (ramdac->pal[c].g & 0x3f) * 4, (ramdac->pal[c].b & 0x3f) * 4); + dev->pallook[c] = makecol32(video_6to8[dev->pal[c].r & 0x3f], + video_6to8[dev->pal[c].g & 0x3f], + video_6to8[dev->pal[c].b & 0x3f]); } } } + + +static void * +ati68860_init(const device_t *info) +{ + ati68860_ramdac_t *dev; + + dev = (ati68860_ramdac_t *)mem_alloc(sizeof(ati68860_ramdac_t)); + memset(dev, 0x00, sizeof(ati68860_ramdac_t)); + + dev->render = svga_render_8bpp_highres; + + return dev; +} + + +static void +ati68860_close(void *priv) +{ + ati68860_ramdac_t *dev = (ati68860_ramdac_t *)priv; + + if (dev != NULL) + free(dev); +} + + +const device_t ati68860_ramdac_device = { + "ATi-68860 RAMDAC", + 0, + 0, + ati68860_init, ati68860_close, NULL, + NULL, NULL, NULL, NULL, + NULL +}; diff --git a/src/devices/video/vid_ati68860_ramdac.h b/src/devices/video/vid_ati68860_ramdac.h index f52d1e1..f2c35cf 100644 --- a/src/devices/video/vid_ati68860_ramdac.h +++ b/src/devices/video/vid_ati68860_ramdac.h @@ -8,7 +8,7 @@ * * Definitions for the ATI 68860 driver. * - * Version: @(#)vid_ati68860.h 1.0.1 2018/02/14 + * Version: @(#)vid_ati68860.h 1.0.2 2018/10/05 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -40,23 +40,29 @@ # define VIDEO_ATI68860_H -typedef struct ati68860_ramdac_t -{ - uint8_t regs[16]; - void (*render)(struct svga_t *svga); - - int dac_write, dac_pos; - int dac_r, dac_g; - PALETTE pal; - uint32_t pallook[2]; - - int ramdac_type; +typedef struct { + int ramdac_type; + uint8_t regs[16]; + int dac_addr, + dac_pos; + int dac_r, + dac_g; + PALETTE pal; + uint32_t pallook[2]; + void (*render)(struct svga_t *svga); } ati68860_ramdac_t; -void ati68860_ramdac_out(uint16_t addr, uint8_t val, ati68860_ramdac_t *ramdac, svga_t *svga); -uint8_t ati68860_ramdac_in(uint16_t addr, ati68860_ramdac_t *ramdac, svga_t *svga); -void ati68860_ramdac_init(ati68860_ramdac_t *ramdac); -void ati68860_set_ramdac_type(ati68860_ramdac_t *ramdac, int type); + +extern const device_t ati68860_ramdac_device; + + +extern void ati68860_set_ramdac_type(ati68860_ramdac_t *dev, int type); + +extern void ati68860_ramdac_out(uint16_t addr, uint8_t val, + ati68860_ramdac_t *dev, svga_t *svga); + +extern uint8_t ati68860_ramdac_in(uint16_t addr, ati68860_ramdac_t *dev, + svga_t *svga); #endif /*VIDEO_ATI68860_H*/ diff --git a/src/devices/video/vid_ati_eeprom.c b/src/devices/video/vid_ati_eeprom.c index a6a53ba..5006b4a 100644 --- a/src/devices/video/vid_ati_eeprom.c +++ b/src/devices/video/vid_ati_eeprom.c @@ -8,7 +8,7 @@ * * Emulation of the EEPROM on select ATI cards. * - * Version: @(#)vid_ati_eeprom.c 1.0.3 2018/05/06 + * Version: @(#)vid_ati_eeprom.c 1.0.4 2018/09/04 * * Authors: Fred N. van Kempen, * Miran Grca, diff --git a/src/devices/video/vid_ati_mach64.c b/src/devices/video/vid_ati_mach64.c index 293ce11..a6fd09d 100644 --- a/src/devices/video/vid_ati_mach64.c +++ b/src/devices/video/vid_ati_mach64.c @@ -8,7 +8,7 @@ * * ATi Mach64 graphics card emulation. * - * Version: @(#)vid_ati_mach64.c 1.0.12 2018/05/06 + * Version: @(#)vid_ati_mach64.c 1.0.13 2018/10/05 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -42,7 +42,6 @@ #include #include #include "../../emu.h" -#include "../../machines/machine.h" #include "../../device.h" #include "../../io.h" #include "../../mem.h" @@ -100,14 +99,12 @@ enum typedef struct mach64_t { - mem_mapping_t linear_mapping; - mem_mapping_t mmio_mapping; - mem_mapping_t mmio_linear_mapping; - mem_mapping_t mmio_linear_mapping_2; + mem_map_t linear_mapping; + mem_map_t mmio_mapping; + mem_map_t mmio_linear_mapping; + mem_map_t mmio_linear_mapping_2; - ati68860_ramdac_t ramdac; ati_eeprom_t eeprom; - ics2595_t ics2595; svga_t svga; rom_t bios_rom; @@ -115,7 +112,7 @@ typedef struct mach64_t uint8_t regs[256]; int index; - int type; + int type, pci; uint8_t pci_regs[256]; uint8_t int_line; @@ -364,7 +361,7 @@ void mach64_ext_writel(uint32_t addr, uint32_t val, void *priv); void mach64_out(uint16_t addr, uint8_t val, void *p) { - mach64_t *mach64 = p; + mach64_t *mach64 = (mach64_t *)p; svga_t *svga = &mach64->svga; uint8_t old; @@ -384,7 +381,7 @@ void mach64_out(uint16_t addr, uint8_t val, void *p) case 0x3C6: case 0x3C7: case 0x3C8: case 0x3C9: if (mach64->type == MACH64_GX) - ati68860_ramdac_out((addr & 3) | ((mach64->dac_cntl & 3) << 2), val, &mach64->ramdac, svga); + ati68860_ramdac_out((addr & 3) | ((mach64->dac_cntl & 3) << 2), val, svga->ramdac, svga); else svga_out(addr, val, svga); return; @@ -428,7 +425,7 @@ void mach64_out(uint16_t addr, uint8_t val, void *p) uint8_t mach64_in(uint16_t addr, void *p) { - mach64_t *mach64 = p; + mach64_t *mach64 = (mach64_t *)p; svga_t *svga = &mach64->svga; if (((addr&0xFFF0) == 0x3D0 || (addr&0xFFF0) == 0x3B0) && !(svga->miscout&1)) @@ -443,7 +440,7 @@ uint8_t mach64_in(uint16_t addr, void *p) case 0x3C6: case 0x3C7: case 0x3C8: case 0x3C9: if (mach64->type == MACH64_GX) - return ati68860_ramdac_in((addr & 3) | ((mach64->dac_cntl & 3) << 2), &mach64->ramdac, svga); + return ati68860_ramdac_in((addr & 3) | ((mach64->dac_cntl & 3) << 2), svga->ramdac, svga); return svga_in(addr, svga); case 0x3D4: @@ -459,6 +456,8 @@ uint8_t mach64_in(uint16_t addr, void *p) void mach64_recalctimings(svga_t *svga) { mach64_t *mach64 = (mach64_t *)svga->p; + ati68860_ramdac_t *ramdac = (ati68860_ramdac_t *) svga->ramdac; + ics2595_t *clock_gen = (ics2595_t *) svga->clock_gen; if (((mach64->crtc_gen_cntl >> 24) & 3) == 3) { @@ -468,7 +467,7 @@ void mach64_recalctimings(svga_t *svga) svga->hdisp_time = svga->hdisp = ((mach64->crtc_h_total_disp >> 16) & 255) + 1; svga->vsyncstart = (mach64->crtc_v_sync_strt_wid & 2047) + 1; svga->rowoffset = (mach64->crtc_off_pitch >> 22); - svga->clock = cpuclock / mach64->ics2595.output_clock; + svga->clock = cpuclock / clock_gen->output_clock; svga->ma_latch = (mach64->crtc_off_pitch & 0x1fffff) * 2; svga->linedbl = svga->rowcount = 0; svga->split = 0xffffff; @@ -476,7 +475,7 @@ void mach64_recalctimings(svga_t *svga) svga->rowcount = mach64->crtc_gen_cntl & 1; svga->rowoffset <<= 1; if (mach64->type == MACH64_GX) - svga->render = mach64->ramdac.render; + svga->render = ramdac->render; switch ((mach64->crtc_gen_cntl >> 8) & 7) { case 1: @@ -533,41 +532,41 @@ void mach64_updatemapping(mach64_t *mach64) if (!(mach64->pci_regs[PCI_REG_COMMAND] & PCI_COMMAND_MEM)) { - /* pclog("Update mapping - PCI disabled\n"); */ - mem_mapping_disable(&svga->mapping); - mem_mapping_disable(&mach64->linear_mapping); - mem_mapping_disable(&mach64->mmio_mapping); - mem_mapping_disable(&mach64->mmio_linear_mapping); - mem_mapping_disable(&mach64->mmio_linear_mapping_2); + /* DEBUG("Update mapping - PCI disabled\n"); */ + mem_map_disable(&svga->mapping); + mem_map_disable(&mach64->linear_mapping); + mem_map_disable(&mach64->mmio_mapping); + mem_map_disable(&mach64->mmio_linear_mapping); + mem_map_disable(&mach64->mmio_linear_mapping_2); return; } - mem_mapping_disable(&mach64->mmio_mapping); + mem_map_disable(&mach64->mmio_mapping); switch (svga->gdcreg[6] & 0xc) { case 0x0: /*128k at A0000*/ - mem_mapping_set_handler(&mach64->svga.mapping, mach64_read, mach64_readw, mach64_readl, mach64_write, mach64_writew, mach64_writel); - mem_mapping_set_p(&mach64->svga.mapping, mach64); - mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x20000); - mem_mapping_enable(&mach64->mmio_mapping); + mem_map_set_handler(&mach64->svga.mapping, mach64_read, mach64_readw, mach64_readl, mach64_write, mach64_writew, mach64_writel); + mem_map_set_p(&mach64->svga.mapping, mach64); + mem_map_set_addr(&svga->mapping, 0xa0000, 0x20000); + mem_map_enable(&mach64->mmio_mapping); svga->banked_mask = 0xffff; break; case 0x4: /*64k at A0000*/ - mem_mapping_set_handler(&mach64->svga.mapping, mach64_read, mach64_readw, mach64_readl, mach64_write, mach64_writew, mach64_writel); - mem_mapping_set_p(&mach64->svga.mapping, mach64); - mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000); + mem_map_set_handler(&mach64->svga.mapping, mach64_read, mach64_readw, mach64_readl, mach64_write, mach64_writew, mach64_writel); + mem_map_set_p(&mach64->svga.mapping, mach64); + mem_map_set_addr(&svga->mapping, 0xa0000, 0x10000); svga->banked_mask = 0xffff; break; case 0x8: /*32k at B0000*/ - mem_mapping_set_handler(&mach64->svga.mapping, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel); - mem_mapping_set_p(&mach64->svga.mapping, svga); - mem_mapping_set_addr(&svga->mapping, 0xb0000, 0x08000); + mem_map_set_handler(&mach64->svga.mapping, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel); + mem_map_set_p(&mach64->svga.mapping, svga); + mem_map_set_addr(&svga->mapping, 0xb0000, 0x08000); svga->banked_mask = 0x7fff; break; case 0xC: /*32k at B8000*/ - mem_mapping_set_handler(&mach64->svga.mapping, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel); - mem_mapping_set_p(&mach64->svga.mapping, svga); - mem_mapping_set_addr(&svga->mapping, 0xb8000, 0x08000); + mem_map_set_handler(&mach64->svga.mapping, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel); + mem_map_set_p(&mach64->svga.mapping, svga); + mem_map_set_addr(&svga->mapping, 0xb8000, 0x08000); svga->banked_mask = 0x7fff; break; } @@ -578,35 +577,39 @@ void mach64_updatemapping(mach64_t *mach64) if ((mach64->config_cntl & 3) == 2) { /*8 MB aperture*/ - mem_mapping_set_addr(&mach64->linear_mapping, mach64->linear_base, (8 << 20) - 0x4000); - mem_mapping_set_addr(&mach64->mmio_linear_mapping, mach64->linear_base + ((8 << 20) - 0x4000), 0x4000); + mem_map_set_addr(&mach64->linear_mapping, mach64->linear_base, (8 << 20) - 0x4000); + mem_map_set_addr(&mach64->mmio_linear_mapping, mach64->linear_base + ((8 << 20) - 0x4000), 0x4000); } else { /*4 MB aperture*/ - mem_mapping_set_addr(&mach64->linear_mapping, mach64->linear_base, (4 << 20) - 0x4000); - mem_mapping_set_addr(&mach64->mmio_linear_mapping, mach64->linear_base + ((4 << 20) - 0x4000), 0x4000); + mem_map_set_addr(&mach64->linear_mapping, mach64->linear_base, (4 << 20) - 0x4000); + mem_map_set_addr(&mach64->mmio_linear_mapping, mach64->linear_base + ((4 << 20) - 0x4000), 0x4000); } } else { /*2*8 MB aperture*/ - mem_mapping_set_addr(&mach64->linear_mapping, mach64->linear_base, (8 << 20) - 0x4000); - mem_mapping_set_addr(&mach64->mmio_linear_mapping, mach64->linear_base + ((8 << 20) - 0x4000), 0x4000); - mem_mapping_set_addr(&mach64->mmio_linear_mapping_2, mach64->linear_base + ((16 << 20) - 0x4000), 0x4000); + mem_map_set_addr(&mach64->linear_mapping, mach64->linear_base, (8 << 20) - 0x4000); + mem_map_set_addr(&mach64->mmio_linear_mapping, mach64->linear_base + ((8 << 20) - 0x4000), 0x4000); + mem_map_set_addr(&mach64->mmio_linear_mapping_2, mach64->linear_base + ((16 << 20) - 0x4000), 0x4000); } - svga->linear_base = mach64->linear_base; } else { - mem_mapping_disable(&mach64->linear_mapping); - mem_mapping_disable(&mach64->mmio_linear_mapping); - mem_mapping_disable(&mach64->mmio_linear_mapping_2); + mem_map_disable(&mach64->linear_mapping); + mem_map_disable(&mach64->mmio_linear_mapping); + mem_map_disable(&mach64->mmio_linear_mapping_2); } } static void mach64_update_irqs(mach64_t *mach64) { + if (!mach64->pci) + { + return; + } + if ((mach64->crtc_int_cntl & 0xaa0024) & ((mach64->crtc_int_cntl << 1) & 0xaa0024)) pci_set_irq(mach64->card, PCI_INTA); else @@ -859,13 +862,9 @@ static void mach64_accel_write_fifo_w(mach64_t *mach64, uint32_t addr, uint16_t break; default: -#ifdef MACH64_DEBUG - pclog(" "); -#endif + DEBUG(" "); mach64_accel_write_fifo(mach64, addr, val & 0xff); -#ifdef MACH64_DEBUG - pclog(" "); -#endif + DEBUG(" "); mach64_accel_write_fifo(mach64, addr + 1, val >> 8); break; } @@ -891,13 +890,9 @@ static void mach64_accel_write_fifo_l(mach64_t *mach64, uint32_t addr, uint32_t break; default: -#ifdef MACH64_DEBUG - pclog(" "); -#endif + DEBUG(" "); mach64_accel_write_fifo_w(mach64, addr, val); -#ifdef MACH64_DEBUG - pclog(" "); -#endif + DEBUG(" "); mach64_accel_write_fifo_w(mach64, addr + 2, val >> 16); break; } @@ -987,7 +982,7 @@ void mach64_start_fill(mach64_t *mach64) /* if ((((mach64->dp_src >> 16) & 7) == MONO_SRC_BLITSRC)) { - pclog("Byte Align set=%02x\n", mach64->dp_pix_width & DP_BYTE_PIX_ORDER); + DEBUG("Byte Align set=%02x\n", mach64->dp_pix_width & DP_BYTE_PIX_ORDER); } */ @@ -1215,9 +1210,7 @@ void mach64_blit(uint32_t cpu_dat, int count, mach64_t *mach64) if (!mach64->accel.busy) { -#ifdef MACH64_DEBUG - pclog("mach64_blit : return as not busy\n"); -#endif + DEBUG("mach64_blit : return as not busy\n"); return; } switch (mach64->accel.op) @@ -1525,9 +1518,7 @@ void mach64_blit(uint32_t cpu_dat, int count, mach64_t *mach64) if (mach64->accel.x_count <= 0) { /*Blit finished*/ -#ifdef MACH64_DEBUG - pclog("mach64 blit finished\n"); -#endif + DEBUG("mach64 blit finished\n"); mach64->accel.busy = 0; return; } @@ -1551,9 +1542,7 @@ void mach64_blit(uint32_t cpu_dat, int count, mach64_t *mach64) mach64->accel.dst_y++; break; } -#ifdef MACH64_DEBUG - pclog("x %i y %i err %i inc %i dec %i\n", mach64->accel.dst_x, mach64->accel.dst_y, mach64->accel.err, mach64->dst_bres_inc, mach64->dst_bres_dec); -#endif + DEBUG("x %i y %i err %i inc %i dec %i\n", mach64->accel.dst_x, mach64->accel.dst_y, mach64->accel.err, mach64->dst_bres_inc, mach64->dst_bres_dec); if (mach64->accel.err >= 0) { mach64->accel.err += mach64->dst_bres_dec; @@ -1594,9 +1583,7 @@ void mach64_load_context(mach64_t *mach64) { addr = ((0x3fff - (mach64->context_load_cntl & 0x3fff)) * 256) & mach64->vram_mask; mach64->context_mask = *(uint32_t *)&svga->vram[addr]; -#ifdef MACH64_DEBUG - pclog("mach64_load_context %08X from %08X : mask %08X\n", mach64->context_load_cntl, addr, mach64->context_mask); -#endif + DEBUG("mach64_load_context %08X from %08X : mask %08X\n", mach64->context_load_cntl, addr, mach64->context_mask); if (mach64->context_mask & (1 << 2)) mach64_accel_write_fifo_l(mach64, 0x100, *(uint32_t *)&svga->vram[addr + 0x08]); @@ -1672,7 +1659,7 @@ static void pll_write(mach64_t *mach64, uint32_t addr, uint8_t val) break; case 2: /*Data*/ mach64->pll_regs[mach64->pll_addr] = val; - /* pclog("pll_write %02x,%02x\n", mach64->pll_addr, val); */ + /* DEBUG("pll_write %02x,%02x\n", mach64->pll_addr, val); */ for (c = 0; c < 4; c++) { @@ -1681,9 +1668,9 @@ static void pll_write(mach64_t *mach64, uint32_t addr, uint8_t val) double r = 14318184.0; double p = (double)(1 << ((mach64->pll_regs[VCLK_POST_DIV] >> (c*2)) & 3)); - /* pclog("PLLfreq %i = %g %g m=%02x n=%02x p=%02x\n", c, (2.0 * r * n) / (m * p), p, mach64->pll_regs[PLL_REF_DIV], mach64->pll_regs[VCLK0_FB_DIV+c], mach64->pll_regs[VCLK_POST_DIV]); */ + /* DEBUG("PLLfreq %i = %g %g m=%02x n=%02x p=%02x\n", c, (2.0 * r * n) / (m * p), p, mach64->pll_regs[PLL_REF_DIV], mach64->pll_regs[VCLK0_FB_DIV+c], mach64->pll_regs[VCLK_POST_DIV]); */ mach64->pll_freq[c] = (2.0 * r * n) / (m * p); - /* pclog(" %g\n", mach64->pll_freq[c]); */ + /* DEBUG(" %g\n", mach64->pll_freq[c]); */ } break; } @@ -1716,12 +1703,12 @@ static void mach64_vblank_start(svga_t *svga) uint8_t mach64_ext_readb(uint32_t addr, void *p) { mach64_t *mach64 = (mach64_t *)p; + ati68860_ramdac_t *ramdac = (ati68860_ramdac_t *) mach64->svga.ramdac; uint8_t ret; + if (!(addr & 0x400)) { -#ifdef MACH64_DEBUG - pclog("nmach64_ext_readb: addr=%04x %04x(%08x):%08x\n", addr, CS, cs, cpu_state.pc); -#endif + DEBUG("nmach64_ext_readb: addr=%04x\n", addr); switch (addr & 0x3ff) { case 0x00: case 0x01: case 0x02: case 0x03: @@ -1842,9 +1829,9 @@ uint8_t mach64_ext_readb(uint32_t addr, void *p) case 0xc0: case 0xc1: case 0xc2: case 0xc3: if (mach64->type == MACH64_GX) - ret = ati68860_ramdac_in((addr & 3) | ((mach64->dac_cntl & 3) << 2), &mach64->ramdac, &mach64->svga); + ret = ati68860_ramdac_in((addr & 3) | ((mach64->dac_cntl & 3) << 2), ramdac, &mach64->svga); else - ret = ati68860_ramdac_in(addr & 3, &mach64->ramdac, &mach64->svga); + ret = ati68860_ramdac_in(addr & 3, ramdac, &mach64->svga); break; case 0xc4: case 0xc5: case 0xc6: case 0xc7: if (mach64->type == MACH64_VT2) @@ -2082,9 +2069,8 @@ uint8_t mach64_ext_readb(uint32_t addr, void *p) ret = 0; break; } -#ifdef MACH64_DEBUG - if ((addr & 0x3fc) != 0x018) pclog("mach64_ext_readb : addr %08X ret %02X\n", addr, ret); -#endif + if ((addr & 0x3fc) != 0x018) + DEBUG("mach64_ext_readb : addr %08X ret %02X\n", addr, ret); return ret; } uint16_t mach64_ext_readw(uint32_t addr, void *p) @@ -2092,27 +2078,20 @@ uint16_t mach64_ext_readw(uint32_t addr, void *p) uint16_t ret; if (!(addr & 0x400)) { -#ifdef MACH64_DEBUG - pclog("nmach64_ext_readw: addr=%04x %04x(%08x):%08x\n", addr, CS, cs, cpu_state.pc); -#endif + DEBUG("nmach64_ext_readw: addr=%04x\n", addr); ret = 0xffff; } else switch (addr & 0x3ff) { default: -#ifdef MACH64_DEBUG - pclog(" "); -#endif + DEBUG(" "); ret = mach64_ext_readb(addr, p); -#ifdef MACH64_DEBUG - pclog(" "); -#endif + DEBUG(" "); ret |= mach64_ext_readb(addr + 1, p) << 8; break; } -#ifdef MACH64_DEBUG - if ((addr & 0x3fc) != 0x018) pclog("mach64_ext_readw : addr %08X ret %04X\n", addr, ret); -#endif + if ((addr & 0x3fc) != 0x018) + DEBUG("mach64_ext_readw : addr %08X ret %04X\n", addr, ret); return ret; } uint32_t mach64_ext_readl(uint32_t addr, void *p) @@ -2121,9 +2100,7 @@ uint32_t mach64_ext_readl(uint32_t addr, void *p) uint32_t ret; if (!(addr & 0x400)) { -#ifdef MACH64_DEBUG - pclog("nmach64_ext_readl: addr=%04x %04x(%08x):%08x\n", addr, CS, cs, cpu_state.pc); -#endif + DEBUG("nmach64_ext_readl: addr=%04x\n", addr); ret = 0xffffffff; } else switch (addr & 0x3ff) @@ -2142,19 +2119,14 @@ uint32_t mach64_ext_readl(uint32_t addr, void *p) break; default: -#ifdef MACH64_DEBUG - pclog(" "); -#endif + DEBUG(" "); ret = mach64_ext_readw(addr, p); -#ifdef MACH64_DEBUG - pclog(" "); -#endif + DEBUG(" "); ret |= mach64_ext_readw(addr + 2, p) << 16; break; } -#ifdef MACH64_DEBUG - if ((addr & 0x3fc) != 0x018) pclog("mach64_ext_readl : addr %08X ret %08X\n", addr, ret); -#endif + if ((addr & 0x3fc) != 0x018) + DEBUG("mach64_ext_readl : addr %08X ret %08X\n", addr, ret); return ret; } @@ -2162,9 +2134,11 @@ void mach64_ext_writeb(uint32_t addr, uint8_t val, void *p) { mach64_t *mach64 = (mach64_t *)p; svga_t *svga = &mach64->svga; -#ifdef MACH64_DEBUG - pclog("mach64_ext_writeb : addr %08X val %02X %04x(%08x):%08x\n", addr, val, CS,cs,cpu_state.pc); -#endif + ati68860_ramdac_t *ramdac = (ati68860_ramdac_t *) svga->ramdac; + ics2595_t *clock_gen = (ics2595_t *) svga->clock_gen; + + DEBUG("mach64_ext_writeb : addr %08X val %02X\n", addr, val); + if (!(addr & 0x400)) { switch (addr & 0x3ff) @@ -2221,9 +2195,7 @@ void mach64_ext_writeb(uint32_t addr, uint8_t val, void *p) WRITE8(addr, mach64->buf_pitch[1], val); break; } -#ifdef MACH64_DEBUG - pclog("nmach64_ext_writeb: addr=%04x val=%02x\n", addr, val); -#endif + DEBUG("nmach64_ext_writeb: addr=%04x val=%02x\n", addr, val); } else if (addr & 0x300) { @@ -2279,12 +2251,12 @@ void mach64_ext_writeb(uint32_t addr, uint8_t val, void *p) case 0x60: case 0x61: case 0x62: case 0x63: WRITE8(addr, mach64->cur_clr0, val); if (mach64->type == MACH64_VT2) - mach64->ramdac.pallook[0] = makecol32((mach64->cur_clr0 >> 24) & 0xff, (mach64->cur_clr0 >> 16) & 0xff, (mach64->cur_clr0 >> 8) & 0xff); + ramdac->pallook[0] = makecol32((mach64->cur_clr0 >> 24) & 0xff, (mach64->cur_clr0 >> 16) & 0xff, (mach64->cur_clr0 >> 8) & 0xff); break; case 0x64: case 0x65: case 0x66: case 0x67: WRITE8(addr, mach64->cur_clr1, val); if (mach64->type == MACH64_VT2) - mach64->ramdac.pallook[1] = makecol32((mach64->cur_clr1 >> 24) & 0xff, (mach64->cur_clr1 >> 16) & 0xff, (mach64->cur_clr1 >> 8) & 0xff); + ramdac->pallook[1] = makecol32((mach64->cur_clr1 >> 24) & 0xff, (mach64->cur_clr1 >> 16) & 0xff, (mach64->cur_clr1 >> 8) & 0xff); break; case 0x68: case 0x69: case 0x6a: case 0x6b: WRITE8(addr, mach64->cur_offset, val); @@ -2314,11 +2286,11 @@ void mach64_ext_writeb(uint32_t addr, uint8_t val, void *p) case 0x90: case 0x91: case 0x92: case 0x93: WRITE8(addr, mach64->clock_cntl, val); if (mach64->type == MACH64_GX) - ics2595_write(&mach64->ics2595, val & 0x40, val & 0xf); + ics2595_write(clock_gen, val & 0x40, val & 0xf); else { pll_write(mach64, addr, val); - mach64->ics2595.output_clock = mach64->pll_freq[mach64->clock_cntl & 3]; + clock_gen->output_clock = mach64->pll_freq[mach64->clock_cntl & 3]; } svga_recalctimings(&mach64->svga); break; @@ -2329,39 +2301,31 @@ void mach64_ext_writeb(uint32_t addr, uint8_t val, void *p) case 0xb4: mach64->bank_w[0] = val * 32768; -#ifdef MACH64_DEBUG - pclog("mach64 : write bank A0000-A7FFF set to %08X\n", mach64->bank_w[0]); -#endif + DEBUG("mach64 : write bank A0000-A7FFF set to %08X\n", mach64->bank_w[0]); break; case 0xb5: case 0xb6: mach64->bank_w[1] = val * 32768; -#ifdef MACH64_DEBUG - pclog("mach64 : write bank A8000-AFFFF set to %08X\n", mach64->bank_w[1]); -#endif + DEBUG("mach64 : write bank A8000-AFFFF set to %08X\n", mach64->bank_w[1]); break; case 0xb8: mach64->bank_r[0] = val * 32768; -#ifdef MACH64_DEBUG - pclog("mach64 : read bank A0000-A7FFF set to %08X\n", mach64->bank_r[0]); -#endif + DEBUG("mach64 : read bank A0000-A7FFF set to %08X\n", mach64->bank_r[0]); break; case 0xb9: case 0xba: mach64->bank_r[1] = val * 32768; -#ifdef MACH64_DEBUG - pclog("mach64 : read bank A8000-AFFFF set to %08X\n", mach64->bank_r[1]); -#endif + DEBUG("mach64 : read bank A8000-AFFFF set to %08X\n", mach64->bank_r[1]); break; case 0xc0: case 0xc1: case 0xc2: case 0xc3: if (mach64->type == MACH64_GX) - ati68860_ramdac_out((addr & 3) | ((mach64->dac_cntl & 3) << 2), val, &mach64->ramdac, &mach64->svga); + ati68860_ramdac_out((addr & 3) | ((mach64->dac_cntl & 3) << 2), val, ramdac, &mach64->svga); else - ati68860_ramdac_out(addr & 3, val, &mach64->ramdac, &mach64->svga); + ati68860_ramdac_out(addr & 3, val, ramdac, &mach64->svga); break; case 0xc4: case 0xc5: case 0xc6: case 0xc7: WRITE8(addr, mach64->dac_cntl, val); svga_set_ramdac_type(svga, (mach64->dac_cntl & 0x100) ? RAMDAC_8BIT : RAMDAC_6BIT); - ati68860_set_ramdac_type(&mach64->ramdac, (mach64->dac_cntl & 0x100) ? RAMDAC_8BIT : RAMDAC_6BIT); + ati68860_set_ramdac_type(ramdac, (mach64->dac_cntl & 0x100) ? RAMDAC_8BIT : RAMDAC_6BIT); break; case 0xd0: case 0xd1: case 0xd2: case 0xd3: @@ -2386,14 +2350,10 @@ void mach64_ext_writeb(uint32_t addr, uint8_t val, void *p) void mach64_ext_writew(uint32_t addr, uint16_t val, void *p) { mach64_t *mach64 = (mach64_t *)p; -#ifdef MACH64_DEBUG - pclog("mach64_ext_writew : addr %08X val %04X\n", addr, val); -#endif + DEBUG("mach64_ext_writew : addr %08X val %04X\n", addr, val); if (!(addr & 0x400)) { -#ifdef MACH64_DEBUG - pclog("nmach64_ext_writew: addr=%04x val=%04x %04x(%08x):%08x\n", addr, val, CS, cs, cpu_state.pc); -#endif + DEBUG("nmach64_ext_writew: addr=%04x val=%04x\n", addr, val); mach64_ext_writeb(addr, val & 0xff, p); mach64_ext_writeb(addr + 1, val >> 8, p); } @@ -2404,13 +2364,9 @@ void mach64_ext_writew(uint32_t addr, uint16_t val, void *p) else switch (addr & 0x3fe) { default: -#ifdef MACH64_DEBUG - pclog(" "); -#endif + DEBUG(" "); mach64_ext_writeb(addr, val & 0xff, p); -#ifdef MACH64_DEBUG - pclog(" "); -#endif + DEBUG(" "); mach64_ext_writeb(addr + 1, val >> 8, p); break; } @@ -2418,15 +2374,14 @@ void mach64_ext_writew(uint32_t addr, uint16_t val, void *p) void mach64_ext_writel(uint32_t addr, uint32_t val, void *p) { mach64_t *mach64 = (mach64_t *)p; -#ifdef MACH64_DEBUG + if ((addr & 0x3c0) != 0x200) - pclog("mach64_ext_writel : addr %08X val %08X\n", addr, val); -#endif + DEBUG("mach64_ext_writel : addr %08X val %08X\n", addr, val); + if (!(addr & 0x400)) { -#ifdef MACH64_DEBUG - pclog("nmach64_ext_writel: addr=%04x val=%08x %04x(%08x):%08x\n", addr, val, CS, cs, cpu_state.pc); -#endif + DEBUG("nmach64_ext_writel: addr=%04x val=%08x\n", addr, val); + mach64_ext_writew(addr, val, p); mach64_ext_writew(addr + 2, val >> 16, p); } @@ -2437,13 +2392,9 @@ void mach64_ext_writel(uint32_t addr, uint32_t val, void *p) else switch (addr & 0x3fc) { default: -#ifdef MACH64_DEBUG - pclog(" "); -#endif + DEBUG(" "); mach64_ext_writew(addr, val, p); -#ifdef MACH64_DEBUG - pclog(" "); -#endif + DEBUG(" "); mach64_ext_writew(addr + 2, val >> 16, p); break; } @@ -2452,7 +2403,9 @@ void mach64_ext_writel(uint32_t addr, uint32_t val, void *p) uint8_t mach64_ext_inb(uint16_t port, void *p) { mach64_t *mach64 = (mach64_t *)p; + ati68860_ramdac_t *ramdac = (ati68860_ramdac_t *) mach64->svga.ramdac; uint8_t ret; + switch (port) { case 0x02ec: case 0x02ed: case 0x02ee: case 0x02ef: @@ -2537,9 +2490,9 @@ uint8_t mach64_ext_inb(uint16_t port, void *p) case 0x5eec: case 0x5eed: case 0x5eee: case 0x5eef: if (mach64->type == MACH64_GX) - ret = ati68860_ramdac_in((port & 3) | ((mach64->dac_cntl & 3) << 2), &mach64->ramdac, &mach64->svga); + ret = ati68860_ramdac_in((port & 3) | ((mach64->dac_cntl & 3) << 2), ramdac, &mach64->svga); else - ret = ati68860_ramdac_in(port & 3, &mach64->ramdac, &mach64->svga); + ret = ati68860_ramdac_in(port & 3, ramdac, &mach64->svga); break; case 0x62ec: case 0x62ed: case 0x62ee: case 0x62ef: @@ -2567,9 +2520,7 @@ uint8_t mach64_ext_inb(uint16_t port, void *p) ret = 0; break; } -#ifdef MACH64_DEBUG - pclog("mach64_ext_inb : port %04X ret %02X %04X:%04X\n", port, ret, CS,cpu_state.pc); -#endif + DEBUG("mach64_ext_inb : port %04X ret %02X\n", port, ret); return ret; } uint16_t mach64_ext_inw(uint16_t port, void *p) @@ -2578,19 +2529,13 @@ uint16_t mach64_ext_inw(uint16_t port, void *p) switch (port) { default: -#ifdef MACH64_DEBUG - pclog(" "); -#endif + DEBUG(" "); ret = mach64_ext_inb(port, p); -#ifdef MACH64_DEBUG - pclog(" "); -#endif + DEBUG(" "); ret |= (mach64_ext_inb(port + 1, p) << 8); break; } -#ifdef MACH64_DEBUG - pclog("mach64_ext_inw : port %04X ret %04X\n", port, ret); -#endif + DEBUG("mach64_ext_inw : port %04X ret %04X\n", port, ret); return ret; } uint32_t mach64_ext_inl(uint16_t port, void *p) @@ -2606,28 +2551,23 @@ uint32_t mach64_ext_inl(uint16_t port, void *p) break; default: -#ifdef MACH64_DEBUG - pclog(" "); -#endif + DEBUG(" "); ret = mach64_ext_inw(port, p); -#ifdef MACH64_DEBUG - pclog(" "); -#endif + DEBUG(" "); ret |= (mach64_ext_inw(port + 2, p) << 16); break; } -#ifdef MACH64_DEBUG - pclog("mach64_ext_inl : port %04X ret %08X\n", port, ret); -#endif + DEBUG("mach64_ext_inl : port %04X ret %08X\n", port, ret); return ret; } void mach64_ext_outb(uint16_t port, uint8_t val, void *p) { mach64_t *mach64 = (mach64_t *)p; -#ifdef MACH64_DEBUG - pclog("mach64_ext_outb : port %04X val %02X %04X:%04X\n", port, val, CS,cpu_state.pc); -#endif + ati68860_ramdac_t *ramdac = (ati68860_ramdac_t *) mach64->svga.ramdac; + + DEBUG("mach64_ext_outb : port %04X val %02X\n", port, val); + switch (port) { case 0x02ec: case 0x02ed: case 0x02ee: case 0x02ef: @@ -2708,9 +2648,9 @@ void mach64_ext_outb(uint16_t port, uint8_t val, void *p) case 0x5eec: case 0x5eed: case 0x5eee: case 0x5eef: if (mach64->type == MACH64_GX) - ati68860_ramdac_out((port & 3) | ((mach64->dac_cntl & 3) << 2), val, &mach64->ramdac, &mach64->svga); + ati68860_ramdac_out((port & 3) | ((mach64->dac_cntl & 3) << 2), val, ramdac, &mach64->svga); else - ati68860_ramdac_out(port & 3, val, &mach64->ramdac, &mach64->svga); + ati68860_ramdac_out(port & 3, val, ramdac, &mach64->svga); break; case 0x62ec: case 0x62ed: case 0x62ee: case 0x62ef: @@ -2729,36 +2669,27 @@ void mach64_ext_outb(uint16_t port, uint8_t val, void *p) } void mach64_ext_outw(uint16_t port, uint16_t val, void *p) { -#ifdef MACH64_DEBUG - pclog("mach64_ext_outw : port %04X val %04X\n", port, val); -#endif + DEBUG("mach64_ext_outw : port %04X val %04X\n", port, val); + switch (port) { default: -#ifdef MACH64_DEBUG - pclog(" "); -#endif + DEBUG(" "); mach64_ext_outb(port, val & 0xff, p); -#ifdef MACH64_DEBUG - pclog(" "); -#endif + DEBUG(" "); mach64_ext_outb(port + 1, val >> 8, p); break; } } void mach64_ext_outl(uint16_t port, uint32_t val, void *p) { - /* pclog("mach64_ext_outl : port %04X val %08X\n", port, val); */ + /* DEBUG("mach64_ext_outl : port %04X val %08X\n", port, val); */ switch (port) { default: -#ifdef MACH64_DEBUG - pclog(" "); -#endif + DEBUG(" "); mach64_ext_outw(port, val, p); -#ifdef MACH64_DEBUG - pclog(" "); -#endif + DEBUG(" "); mach64_ext_outw(port + 2, val >> 16, p); break; } @@ -2770,9 +2701,7 @@ static uint8_t mach64_block_inb(uint16_t port, void *p) uint8_t ret; ret = mach64_ext_readb(0x400 | (port & 0x3ff), mach64); -#ifdef MACH64_DEBUG - pclog("mach64_block_inb : port %04X ret %02X %04x:%04x\n", port, ret, CS,cpu_state.pc); -#endif + DEBUG("mach64_block_inb : port %04X ret %02X\n", port, ret); return ret; } static uint16_t mach64_block_inw(uint16_t port, void *p) @@ -2781,9 +2710,7 @@ static uint16_t mach64_block_inw(uint16_t port, void *p) uint16_t ret; ret = mach64_ext_readw(0x400 | (port & 0x3ff), mach64); -#ifdef MACH64_DEBUG - pclog("mach64_block_inw : port %04X ret %04X\n", port, ret); -#endif + DEBUG("mach64_block_inw : port %04X ret %04X\n", port, ret); return ret; } static uint32_t mach64_block_inl(uint16_t port, void *p) @@ -2792,9 +2719,7 @@ static uint32_t mach64_block_inl(uint16_t port, void *p) uint32_t ret; ret = mach64_ext_readl(0x400 | (port & 0x3ff), mach64); -#ifdef MACH64_DEBUG - pclog("mach64_block_inl : port %04X ret %08X\n", port, ret); -#endif + DEBUG("mach64_block_inl : port %04X ret %08X\n", port, ret); return ret; } @@ -2802,27 +2727,21 @@ static void mach64_block_outb(uint16_t port, uint8_t val, void *p) { mach64_t *mach64 = (mach64_t *)p; -#ifdef MACH64_DEBUG - pclog("mach64_block_outb : port %04X val %02X\n ", port, val); -#endif + DEBUG("mach64_block_outb : port %04X val %02X\n ", port, val); mach64_ext_writeb(0x400 | (port & 0x3ff), val, mach64); } static void mach64_block_outw(uint16_t port, uint16_t val, void *p) { mach64_t *mach64 = (mach64_t *)p; -#ifdef MACH64_DEBUG - pclog("mach64_block_outw : port %04X val %04X\n ", port, val); -#endif + DEBUG("mach64_block_outw : port %04X val %04X\n ", port, val); mach64_ext_writew(0x400 | (port & 0x3ff), val, mach64); } static void mach64_block_outl(uint16_t port, uint32_t val, void *p) { mach64_t *mach64 = (mach64_t *)p; - -#ifdef MACH64_DEBUG - pclog("mach64_block_outl : port %04X val %08X\n ", port, val); -#endif + + DEBUG("mach64_block_outl : port %04X val %08X\n ", port, val); mach64_ext_writel(0x400 | (port & 0x3ff), val, mach64); } @@ -2878,13 +2797,15 @@ uint32_t mach64_readl(uint32_t addr, void *p) void mach64_hwcursor_draw(svga_t *svga, int disp_line) { - mach64_t *mach64 = (mach64_t *)svga->p; + ati68860_ramdac_t *ramdac = (ati68860_ramdac_t *) svga->ramdac; int x, offset; uint8_t dat; - uint32_t col0 = mach64->ramdac.pallook[0]; - uint32_t col1 = mach64->ramdac.pallook[1]; - int y_add = (enable_overscan && !suppress_overscan) ? 16 : 0; - int x_add = (enable_overscan && !suppress_overscan) ? 8 : 0; + uint32_t col0 = ramdac->pallook[0]; + uint32_t col1 = ramdac->pallook[1]; + int y_add, x_add; + + y_add = (enable_overscan && !suppress_overscan) ? (overscan_y >> 1) : 0; + x_add = (enable_overscan && !suppress_overscan) ? 8 : 0; offset = svga->hwcursor_latch.xoff; for (x = 0; x < 64 - svga->hwcursor_latch.xoff; x += 4) @@ -3082,7 +3003,7 @@ void mach64_overlay_draw(svga_t *svga, int disp_line) break; default: - /* pclog("Unknown Mach64 scaler format %x\n", mach64->scaler_format); */ + /* DEBUG("Unknown Mach64 scaler format %x\n", mach64->scaler_format); */ /*Fill buffer with something recognisably wrong*/ for (x = 0; x < mach64->svga.overlay_latch.xsize; x++) mach64->overlay_dat[x] = 0xff00ff; @@ -3358,13 +3279,13 @@ void mach64_pci_write(int func, int addr, uint8_t val, void *p) if (mach64->pci_regs[0x30] & 0x01) { uint32_t a = (mach64->pci_regs[0x32] << 16) | (mach64->pci_regs[0x33] << 24); - /* pclog("Mach64 bios_rom enabled at %08x\n", a); */ - mem_mapping_set_addr(&mach64->bios_rom.mapping, a, 0x8000); + /* DEBUG("Mach64 bios_rom enabled at %08x\n", a); */ + mem_map_set_addr(&mach64->bios_rom.mapping, a, 0x8000); } else { - /* pclog("Mach64 bios_rom disabled\n"); */ - mem_mapping_disable(&mach64->bios_rom.mapping); + /* DEBUG("Mach64 bios_rom disabled\n"); */ + mem_map_disable(&mach64->bios_rom.mapping); } return; @@ -3386,7 +3307,7 @@ void mach64_pci_write(int func, int addr, uint8_t val, void *p) static void *mach64_common_init(const device_t *info) { - mach64_t *mach64 = malloc(sizeof(mach64_t)); + mach64_t *mach64 = (mach64_t *)mem_alloc(sizeof(mach64_t)); memset(mach64, 0, sizeof(mach64_t)); mach64->vram_size = device_get_config_int("memory"); @@ -3399,13 +3320,13 @@ static void *mach64_common_init(const device_t *info) mach64_overlay_draw); if (info->flags & DEVICE_PCI) - mem_mapping_disable(&mach64->bios_rom.mapping); + mem_map_disable(&mach64->bios_rom.mapping); - mem_mapping_add(&mach64->linear_mapping, 0, 0, svga_read_linear, svga_readw_linear, svga_readl_linear, svga_write_linear, svga_writew_linear, svga_writel_linear, NULL, 0, &mach64->svga); - mem_mapping_add(&mach64->mmio_linear_mapping, 0, 0, mach64_ext_readb, mach64_ext_readw, mach64_ext_readl, mach64_ext_writeb, mach64_ext_writew, mach64_ext_writel, NULL, 0, mach64); - mem_mapping_add(&mach64->mmio_linear_mapping_2, 0, 0, mach64_ext_readb, mach64_ext_readw, mach64_ext_readl, mach64_ext_writeb, mach64_ext_writew, mach64_ext_writel, NULL, 0, mach64); - mem_mapping_add(&mach64->mmio_mapping, 0xbc000, 0x04000, mach64_ext_readb, mach64_ext_readw, mach64_ext_readl, mach64_ext_writeb, mach64_ext_writew, mach64_ext_writel, NULL, 0, mach64); - mem_mapping_disable(&mach64->mmio_mapping); + mem_map_add(&mach64->linear_mapping, 0, 0, svga_read_linear, svga_readw_linear, svga_readl_linear, svga_write_linear, svga_writew_linear, svga_writel_linear, NULL, 0, &mach64->svga); + mem_map_add(&mach64->mmio_linear_mapping, 0, 0, mach64_ext_readb, mach64_ext_readw, mach64_ext_readl, mach64_ext_writeb, mach64_ext_writew, mach64_ext_writel, NULL, 0, mach64); + mem_map_add(&mach64->mmio_linear_mapping_2, 0, 0, mach64_ext_readb, mach64_ext_readw, mach64_ext_readl, mach64_ext_writeb, mach64_ext_writew, mach64_ext_writel, NULL, 0, mach64); + mem_map_add(&mach64->mmio_mapping, 0xbc000, 0x04000, mach64_ext_readb, mach64_ext_readw, mach64_ext_readl, mach64_ext_writeb, mach64_ext_writew, mach64_ext_writel, NULL, 0, mach64); + mem_map_disable(&mach64->mmio_mapping); mach64_io_set(mach64); @@ -3419,7 +3340,8 @@ static void *mach64_common_init(const device_t *info) mach64->pci_regs[0x32] = 0x0c; mach64->pci_regs[0x33] = 0x00; - ati68860_ramdac_init(&mach64->ramdac); + mach64->svga.ramdac = device_add(&ati68860_ramdac_device); + mach64->svga.clock_gen = device_add(&ics2595_device); mach64->dst_cntl = 3; @@ -3427,14 +3349,18 @@ static void *mach64_common_init(const device_t *info) mach64->fifo_not_full_event = thread_create_event(); mach64->fifo_thread = thread_create(fifo_thread, mach64); + video_inform(VID_TYPE_SPEC, + (const video_timings_t *)info->vid_timing); + return mach64; } static void *mach64gx_init(const device_t *info) { - mach64_t *mach64 = mach64_common_init(info); + mach64_t *mach64 = (mach64_t *)mach64_common_init(info); mach64->type = MACH64_GX; + mach64->pci = !!(info->flags & DEVICE_PCI); mach64->pci_id = (int)'X' | ((int)'G' << 8); mach64->config_chip_id = 0x020000d7; mach64->dac_cntl = 5 << 16; /*ATI 68860 RAMDAC*/ @@ -3457,15 +3383,16 @@ static void *mach64gx_init(const device_t *info) } static void *mach64vt2_init(const device_t *info) { - mach64_t *mach64 = mach64_common_init(info); + mach64_t *mach64 = (mach64_t *)mach64_common_init(info); svga_t *svga = &mach64->svga; mach64->type = MACH64_VT2; + mach64->pci = 1; mach64->pci_id = 0x5654; mach64->config_chip_id = 0x40005654; mach64->dac_cntl = 1 << 16; /*Internal 24-bit DAC*/ mach64->config_stat0 = 4; - mach64->use_block_decoded_io = PCI ? 4 : 0; + mach64->use_block_decoded_io = 4; ati_eeprom_load(&mach64->eeprom, L"mach64vt.nvr", 1); @@ -3520,52 +3447,6 @@ void mach64_force_redraw(void *p) mach64->svga.fullchange = changeframecount; } -void mach64_add_status_info(char *s, int max_len, void *p) -{ - mach64_t *mach64 = (mach64_t *)p; - char temps[256]; - uint64_t new_time = plat_timer_read(); - uint64_t status_diff = new_time - mach64->status_time; - mach64->status_time = new_time; - - if (((mach64->crtc_gen_cntl >> 24) & 3) == 3) - { - svga_t *svga = &mach64->svga; - int bpp = 4; - - strncat(s, "Mach64 in native mode\n", max_len); - - switch ((mach64->crtc_gen_cntl >> 8) & 7) - { - case 1: bpp = 4; break; - case 2: bpp = 8; break; - case 3: bpp = 15; break; - case 4: bpp = 16; break; - case 5: bpp = 24; break; - case 6: bpp = 32; break; - } - - sprintf(temps, "Mach64 colour depth : %i bpp\n", bpp); - strncat(s, temps, max_len); - - sprintf(temps, "Mach64 resolution : %i x %i\n", svga->hdisp, svga->dispend); - strncat(s, temps, max_len); - - sprintf(temps, "Mach64 refresh rate : %i Hz\n\n", svga->frames); - svga->frames = 0; - strncat(s, temps, max_len); - } - else - { - strncat(s, "Mach64 in SVGA mode\n", max_len); - svga_add_status_info(s, max_len, &mach64->svga); - } - - sprintf(temps, "%f%% CPU\n%f%% CPU (real)\n\n", ((double)mach64->blitter_time * 100.0) / timer_freq, ((double)mach64->blitter_time * 100.0) / status_diff); - strncat(s, temps, max_len); - - mach64->blitter_time = 0; -} static const device_config_t mach64gx_config[] = { @@ -3612,54 +3493,55 @@ static const device_config_t mach64vt2_config[] = } }; -const device_t mach64gx_isa_device = -{ - "ATI Mach64GX ISA", - DEVICE_AT | DEVICE_ISA, - 0, - mach64gx_init, mach64_close, NULL, - mach64gx_isa_available, - mach64_speed_changed, - mach64_force_redraw, - mach64_add_status_info, - mach64gx_config + +static const video_timings_t mach64gx_isa_timing = {VID_ISA,3,3,6,5,5,10}; +const device_t mach64gx_isa_device = { + "ATI Mach64GX ISA", + DEVICE_AT | DEVICE_ISA, + 0, + mach64gx_init, mach64_close, NULL, + mach64gx_isa_available, + mach64_speed_changed, + mach64_force_redraw, + &mach64gx_isa_timing, + mach64gx_config }; -const device_t mach64gx_vlb_device = -{ - "ATI Mach64GX VLB", - DEVICE_VLB, - 0, - mach64gx_init, mach64_close, NULL, - mach64gx_vlb_available, - mach64_speed_changed, - mach64_force_redraw, - mach64_add_status_info, - mach64gx_config +static const video_timings_t mach64gx_vlb_timing = {VID_BUS,2,2,1,20,20,21}; +const device_t mach64gx_vlb_device = { + "ATI Mach64GX VLB", + DEVICE_VLB, + 0, + mach64gx_init, mach64_close, NULL, + mach64gx_vlb_available, + mach64_speed_changed, + mach64_force_redraw, + &mach64gx_vlb_timing, + mach64gx_config }; -const device_t mach64gx_pci_device = -{ - "ATI Mach64GX PCI", - DEVICE_PCI, - 0, - mach64gx_init, mach64_close, NULL, - mach64gx_available, - mach64_speed_changed, - mach64_force_redraw, - mach64_add_status_info, - mach64gx_config +static const video_timings_t mach64gx_pci_timing = {VID_BUS,2,2,1,20,20,21}; +const device_t mach64gx_pci_device = { + "ATI Mach64GX PCI", + DEVICE_PCI, + 0, + mach64gx_init, mach64_close, NULL, + mach64gx_available, + mach64_speed_changed, + mach64_force_redraw, + &mach64gx_pci_timing, + mach64gx_config }; -const device_t mach64vt2_device = -{ - "ATI Mach64VT2", - DEVICE_PCI, - 0, - mach64vt2_init, mach64_close, NULL, - mach64vt2_available, - mach64_speed_changed, - mach64_force_redraw, - mach64_add_status_info, - mach64vt2_config +static const video_timings_t mach64vt2_timing = {VID_BUS,2,2,1,20,20,21}; +const device_t mach64vt2_device = { + "ATI Mach64VT2", + DEVICE_PCI, + 0, + mach64vt2_init, mach64_close, NULL, + mach64vt2_available, + mach64_speed_changed, + mach64_force_redraw, + &mach64vt2_timing, + mach64vt2_config }; diff --git a/src/devices/video/vid_bt485_ramdac.c b/src/devices/video/vid_bt485_ramdac.c deleted file mode 100644 index c18b0c8..0000000 --- a/src/devices/video/vid_bt485_ramdac.c +++ /dev/null @@ -1,212 +0,0 @@ -/* - * VARCem Virtual ARchaeological Computer EMulator. - * An emulator of (mostly) x86-based PC systems and devices, - * using the ISA,EISA,VLB,MCA and PCI system buses, roughly - * spanning the era between 1981 and 1995. - * - * This file is part of the VARCem Project. - * - * Brooktree BT485 true colour RAMDAC emulation. - * - * Currently only a dummy stub for logging and passing output - * to the generic SVGA handler. - * - * Version: @(#)vid_bt485_ramdac.c 1.0.3 2018/05/06 - * - * Authors: Fred N. van Kempen, - * Miran Grca, - * Sarah Walker, - * - * Copyright 2017,2018 Fred N. van Kempen. - * Copyright 2016-2018 Miran Grca. - * Copyright 2008-2018 Sarah Walker. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the: - * - * Free Software Foundation, Inc. - * 59 Temple Place - Suite 330 - * Boston, MA 02111-1307 - * USA. - */ -#include -#include -#include -#include -#include "../../emu.h" -#include "../../mem.h" -#include "video.h" -#include "vid_svga.h" -#include "vid_bt485_ramdac.h" - - -int bt485_get_clock_divider(bt485_ramdac_t *ramdac) -{ - return 1; /* Will be implemented later. */ -} - -void bt485_set_rs2(uint8_t rs2, bt485_ramdac_t *ramdac) -{ - ramdac->rs2 = rs2 ? 1 : 0; -} - -void bt485_set_rs3(uint8_t rs3, bt485_ramdac_t *ramdac) -{ - ramdac->rs3 = rs3 ? 1 : 0; -} - -void bt485_ramdac_out(uint16_t addr, uint8_t val, bt485_ramdac_t *ramdac, svga_t *svga) -{ -// /*if (CS!=0xC000) */pclog("OUT RAMDAC %04X %02X %i %04X:%04X %i\n",addr,val,sdac_ramdac.magic_count,CS,pc, sdac_ramdac.rs2); - uint8_t reg = addr & 3; - reg |= (ramdac->rs2 ? 4 : 0); - reg |= (ramdac->rs3 ? 8 : 0); - pclog("BT485 RAMDAC: Writing %02X to register %02X\n", val, reg); - svga_out(addr, val, svga); - return; - - switch (addr) - { - case 0x3C6: - if (val == 0xff) - { - ramdac->rs2 = 0; - ramdac->magic_count = 0; - break; - } - if (ramdac->magic_count < 4) break; - if (ramdac->magic_count == 4) - { - ramdac->command = val; -// pclog("RAMDAC command reg now %02X\n", val); - switch (val >> 4) - { - case 0x2: case 0x3: case 0xa: svga->bpp = 15; break; - case 0x4: case 0xe: svga->bpp = 24; break; - case 0x5: case 0x6: case 0xc: svga->bpp = 16; break; - case 0x7: svga->bpp = 32; break; - - case 0: case 1: default: svga->bpp = 8; break; - } - svga_recalctimings(svga); - } - //ramdac->magic_count = 0; - break; - - case 0x3C7: - ramdac->magic_count = 0; - if (ramdac->rs2) - ramdac->rindex = val; - break; - case 0x3C8: - ramdac->magic_count = 0; - if (ramdac->rs2) - ramdac->windex = val; - break; - case 0x3C9: - ramdac->magic_count = 0; - if (ramdac->rs2) - { - if (!ramdac->reg_ff) ramdac->regs[ramdac->windex] = (ramdac->regs[ramdac->windex] & 0xff00) | val; - else ramdac->regs[ramdac->windex] = (ramdac->regs[ramdac->windex] & 0x00ff) | (val << 8); - ramdac->reg_ff = !ramdac->reg_ff; -// pclog("RAMDAC reg %02X now %04X\n", ramdac->windex, ramdac->regs[ramdac->windex]); - if (!ramdac->reg_ff) ramdac->windex++; - } - break; - } - svga_out(addr, val, svga); -} - -uint8_t bt485_ramdac_in(uint16_t addr, bt485_ramdac_t *ramdac, svga_t *svga) -{ - uint8_t temp; -// /*if (CS!=0xC000) */pclog("IN RAMDAC %04X %04X:%04X %i\n",addr,CS,pc, ramdac->rs2); - uint8_t reg = addr & 3; - reg |= (ramdac->rs2 ? 4 : 0); - reg |= (ramdac->rs3 ? 8 : 0); - pclog("BT485 RAMDAC: Reading register %02X\n", reg); - return svga_in(addr, svga); - - switch (addr) - { - case 0x3C6: - ramdac->reg_ff = 0; - if (ramdac->magic_count < 5) - ramdac->magic_count++; - if (ramdac->magic_count == 4) - { - temp = 0x70; /*SDAC ID*/ - ramdac->rs2 = 1; - } - if (ramdac->magic_count == 5) - { - temp = ramdac->command; - ramdac->magic_count = 0; - } - return temp; - case 0x3C7: -// if (ramdac->magic_count < 4) -// { - ramdac->magic_count=0; -// break; -// } - if (ramdac->rs2) return ramdac->rindex; - break; - case 0x3C8: -// if (ramdac->magic_count < 4) -// { - ramdac->magic_count=0; -// break; -// } - if (ramdac->rs2) return ramdac->windex; - break; - case 0x3C9: -// if (ramdac->magic_count < 4) -// { - ramdac->magic_count=0; -// break; -// } - if (ramdac->rs2) - { - if (!ramdac->reg_ff) temp = ramdac->regs[ramdac->rindex] & 0xff; - else temp = ramdac->regs[ramdac->rindex] >> 8; - ramdac->reg_ff = !ramdac->reg_ff; - if (!ramdac->reg_ff) - { - ramdac->rindex++; - ramdac->magic_count = 0; - } - return temp; - } - break; - } - return svga_in(addr, svga); -} - -float bt485_getclock(int clock, void *p) -{ - bt485_ramdac_t *ramdac = (bt485_ramdac_t *)p; - float t; - int m, n1, n2; -// pclog("SDAC_Getclock %i %04X\n", clock, ramdac->regs[clock]); - if (clock == 0) return 25175000.0; - if (clock == 1) return 28322000.0; - clock ^= 1; /*Clocks 2 and 3 seem to be reversed*/ - m = (ramdac->regs[clock] & 0x7f) + 2; - n1 = ((ramdac->regs[clock] >> 8) & 0x1f) + 2; - n2 = ((ramdac->regs[clock] >> 13) & 0x07); - t = ((14318184.0f * (float)m / (float)n1)) / (float)(1 << n2); -// pclog("BT485 clock %i %i %i %f %04X %f %i\n", m, n1, n2, t, ramdac->regs[2], 14318184.0 * ((float)m / (float)n1), 1 << n2); - return t; -} diff --git a/src/devices/video/vid_bt48x_ramdac.c b/src/devices/video/vid_bt48x_ramdac.c new file mode 100644 index 0000000..b7caf75 --- /dev/null +++ b/src/devices/video/vid_bt48x_ramdac.c @@ -0,0 +1,588 @@ +/* + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. + * + * This file is part of the VARCem Project. + * + * Brooktree Bt48x series true color RAMDAC emulation. + * + * Version: @(#)vid_bt48x_ramdac.c 1.0.8 2018/10/06 + * + * Authors: Fred N. van Kempen, + * Miran Grca, + * + * Copyright 2018 Fred N. van Kempen. + * Copyright 2016-2018 Miran Grca. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the: + * + * Free Software Foundation, Inc. + * 59 Temple Place - Suite 330 + * Boston, MA 02111-1307 + * USA. + */ +#include +#include +#include +#include +#include +#include "../../emu.h" +#include "../../mem.h" +#include "../../device.h" +#include "video.h" +#include "vid_svga.h" +#include "vid_bt48x_ramdac.h" + + +enum { + BT484 = 0, + ATT20C504, + BT485, + ATT20C505, + BT485A +}; + + +static void +set_bpp(bt48x_ramdac_t *dev, svga_t *svga) +{ + if (dev->cr2 & 0x20) switch ((dev->cr1 >> 5) & 0x03) { + case 0: + svga->bpp = 32; + break; + + case 1: + if (dev->cr1 & 0x08) + svga->bpp = 16; + else + svga->bpp = 15; + break; + + case 2: + svga->bpp = 8; + break; + + case 3: + svga->bpp = 4; + break; + } else + svga->bpp = 8; + + svga_recalctimings(svga); +} + + +void +bt48x_ramdac_out(uint16_t addr, int rs2, int rs3, uint8_t val, bt48x_ramdac_t *dev, svga_t *svga) +{ + uint32_t o32; + uint16_t indx; + uint8_t *cd; + uint8_t rs = (addr & 0x03); + uint16_t da_mask = 0x03ff; + + if (dev->type < BT485) + da_mask = 0x00ff; + + rs |= (!!rs2 << 2); + rs |= (!!rs3 << 3); + + switch (rs) { + case 0x00: /* Palette Write Index Register (RS value = 0000) */ + case 0x03: + svga->dac_pos = 0; + svga->dac_status = addr & 0x03; + svga->dac_addr = val; + if (dev->type >= BT485) + svga->dac_addr |= ((int) (dev->cr3 & 0x03) << 8); + if (svga->dac_status) + svga->dac_addr = (svga->dac_addr + 1) & da_mask; + break; + + case 0x01: /* Palette Data Register (RS value = 0001) */ + case 0x02: /* Pixel Read Mask Register (RS value = 0010) */ + svga_out(addr, val, svga); + break; + + case 0x04: /* Ext Palette Write Index Register (RS value = 0100) */ + case 0x07: /* Ext Palette Read Index Register (RS value = 0111) */ + svga->dac_pos = 0; + svga->dac_status = rs & 0x03; + dev->ext_addr = (val + (rs & 0x01)) & 255; + break; + + case 0x05: /* Ext Palette Data Register (RS value = 0101) */ + svga->dac_status = 0; + svga->fullchange = changeframecount; + switch (svga->dac_pos) { + case 0: + svga->dac_r = val; + svga->dac_pos++; + break; + + case 1: + svga->dac_g = val; + svga->dac_pos++; + break; + + case 2: + indx = dev->ext_addr & 3; + dev->extpal[indx].r = svga->dac_r; + dev->extpal[indx].g = svga->dac_g; + dev->extpal[indx].b = val; + if (svga->ramdac_type == RAMDAC_8BIT) + dev->extpallook[indx] = makecol32(dev->extpal[indx].r, dev->extpal[indx].g, dev->extpal[indx].b); + else + dev->extpallook[indx] = makecol32(video_6to8[dev->extpal[indx].r & 0x3f], video_6to8[dev->extpal[indx].g & 0x3f], video_6to8[dev->extpal[indx].b & 0x3f]); + + if (svga->ext_overscan && !indx) { + o32 = svga->overscan_color; + svga->overscan_color = dev->extpallook[0]; + if (o32 != svga->overscan_color) + svga_recalctimings(svga); + } + dev->ext_addr = (dev->ext_addr + 1) & 0xff; + svga->dac_pos = 0; + break; + } + break; + + case 0x06: /* Command Register 0 (RS value = 0110) */ + dev->cr0 = val; + svga->ramdac_type = (val & 0x02) ? RAMDAC_8BIT : RAMDAC_6BIT; + break; + + case 0x08: /* Command Register 1 (RS value = 1000) */ + dev->cr1 = val; + set_bpp(dev, svga); + break; + + case 0x09: /* Command Register 2 (RS value = 1001) */ + dev->cr2 = val; + svga->hwcursor.ena = !!(val & 0x03); + set_bpp(dev, svga); + break; + + case 0x0a: + if ((dev->type >= BT485) && (dev->cr0 & 0x80)) { + switch ((svga->dac_addr & 0xff)) { + case 0x01: + /* Command Register 3 (RS value = 1010) */ + dev->cr3 = val; + svga->hwcursor.xsize = svga->hwcursor.ysize = (val & 4) ? 64 : 32; + svga->hwcursor.yoff = (svga->hwcursor.ysize == 32) ? 32 : 0; + svga->hwcursor.x = dev->hwc_x - svga->hwcursor.xsize; + svga->hwcursor.y = dev->hwc_y - svga->hwcursor.ysize; + svga->dac_addr = (svga->dac_addr & 0x00ff) | ((val & 0x03) << 8); + svga_recalctimings(svga); + break; + + case 0x02: + case 0x20: + case 0x21: + case 0x22: + if (dev->type != BT485A) + break; + else if (svga->dac_addr == 2) { + dev->cr4 = val; + break; + } + break; + } + } + break; + + case 0x0b: /* Cursor RAM Data Register (RS value = 1011) */ + indx = svga->dac_addr & 0x03ff; + if ((dev->type >= BT485) && (svga->hwcursor.xsize == 64)) + cd = (uint8_t *) dev->cursor64_data; + else + cd = (uint8_t *) dev->cursor32_data; + cd[indx] = val; + svga->dac_addr++; + svga->dac_addr = (svga->dac_addr + 1) & da_mask; + break; + + case 0x0c: /* Cursor X Low Register (RS value = 1100) */ + dev->hwc_x = (dev->hwc_x & 0x0f00) | val; + svga->hwcursor.x = dev->hwc_x - svga->hwcursor.xsize; + break; + + case 0x0d: /* Cursor X High Register (RS value = 1101) */ + dev->hwc_x = (dev->hwc_x & 0x00ff) | ((val & 0x0f) << 8); + svga->hwcursor.x = dev->hwc_x - svga->hwcursor.xsize; + break; + + case 0x0e: /* Cursor Y Low Register (RS value = 1110) */ + dev->hwc_y = (dev->hwc_y & 0x0f00) | val; + svga->hwcursor.y = dev->hwc_y - svga->hwcursor.ysize; + break; + + case 0x0f: /* Cursor Y High Register (RS value = 1111) */ + dev->hwc_y = (dev->hwc_y & 0x00ff) | ((val & 0x0f) << 8); + svga->hwcursor.y = dev->hwc_y - svga->hwcursor.ysize; + break; + } + + return; +} + + +uint8_t +bt48x_ramdac_in(uint16_t addr, int rs2, int rs3, bt48x_ramdac_t *dev, svga_t *svga) +{ + uint8_t temp = 0xff; + uint16_t indx; + uint8_t *cd; + uint8_t rs = (addr & 0x03); + uint16_t da_mask = 0x03ff; + + rs |= (!!rs2 << 2); + rs |= (!!rs3 << 3); + + switch (rs) { + case 0x00: /* Palette Write Index Register (RS value = 0000) */ + case 0x01: /* Palette Data Register (RS value = 0001) */ + case 0x02: /* Pixel Read Mask Register (RS value = 0010) */ + temp = svga_in(addr, svga); + break; + + case 0x03: /* Palette Read Index Register (RS value = 0011) */ + temp = svga->dac_addr & 0xff; + break; + + case 0x04: /* Ext Palette Write Index Register (RS value = 0100) */ + temp = dev->ext_addr; + break; + + case 0x05: /* Ext Palette Data Register (RS value = 0101) */ + indx = (dev->ext_addr - 1) & 3; + svga->dac_status = 3; + switch (svga->dac_pos) { + case 0: + svga->dac_pos++; + if (svga->ramdac_type == RAMDAC_8BIT) + temp = dev->extpal[indx].r; + else + temp = dev->extpal[indx].r & 0x3f; + break; + + case 1: + svga->dac_pos++; + if (svga->ramdac_type == RAMDAC_8BIT) + temp = dev->extpal[indx].g; + else + temp = dev->extpal[indx].g & 0x3f; + break; + + case 2: + svga->dac_pos = 0; + dev->ext_addr = dev->ext_addr + 1; + if (svga->ramdac_type == RAMDAC_8BIT) + temp = dev->extpal[indx].b; + else + temp = dev->extpal[indx].b & 0x3f; + break; + } + break; + + case 0x06: /* Command Register 0 (RS value = 0110) */ + temp = dev->cr0; + break; + + case 0x07: /* Ext Palette Read Index Register (RS value = 0111) */ + temp = dev->ext_addr; + break; + + case 0x08: /* Command Register 1 (RS value = 1000) */ + temp = dev->cr1; + break; + + case 0x09: /* Command Register 2 (RS value = 1001) */ + temp = dev->cr2; + break; + + case 0x0a: + if ((dev->type >= BT485) && (dev->cr0 & 0x80)) { + switch ((svga->dac_addr & 0xff)) { + case 0x00: + temp = dev->status | (svga->dac_status ? 0x04 : 0x00); + break; + + case 0x01: + temp = dev->cr3 & 0xfc; + temp |= (svga->dac_addr & 0x300) >> 8; + break; + + case 0x02: + case 0x20: + case 0x21: + case 0x22: + if (dev->type != BT485A) + break; + else if (svga->dac_addr == 2) { + temp = dev->cr4; + break; + } else { + /* TODO: Red, Green, and Blue Signature Analysis Registers */ + temp = 0xff; + break; + } + break; + } + } else + temp = dev->status | (svga->dac_status ? 0x04 : 0x00); + break; + + case 0x0b: /* Cursor RAM Data Register (RS value = 1011) */ + indx = (svga->dac_addr - 1) & da_mask; + if ((dev->type >= BT485) && (svga->hwcursor.xsize == 64)) + cd = (uint8_t *) dev->cursor64_data; + else + cd = (uint8_t *) dev->cursor32_data; + + temp = cd[indx]; + svga->dac_addr = (svga->dac_addr + 1) & da_mask; + break; + + case 0x0c: /* Cursor X Low Register (RS value = 1100) */ + temp = dev->hwc_x & 0xff; + break; + + case 0x0d: /* Cursor X High Register (RS value = 1101) */ + temp = (dev->hwc_x >> 8) & 0xff; + break; + + case 0x0e: /* Cursor Y Low Register (RS value = 1110) */ + temp = dev->hwc_y & 0xff; + break; + + case 0x0f: /* Cursor Y High Register (RS value = 1111) */ + temp = (dev->hwc_y >> 8) & 0xff; + break; + } + + return temp; +} + + +void +bt48x_hwcursor_draw(svga_t *svga, int displine) +{ + bt48x_ramdac_t *dev = (bt48x_ramdac_t *)svga->ramdac; + int x, xx, comb, b0, b1; + uint16_t dat[2]; + int offset = svga->hwcursor_latch.x - svga->hwcursor_latch.xoff; + int y_add, x_add; + int pitch, bppl, mode, x_pos, y_pos; + uint32_t clr1, clr2, clr3, *p; + uint8_t *cd; + + clr1 = dev->extpallook[1]; + clr2 = dev->extpallook[2]; + clr3 = dev->extpallook[3]; + + y_add = (enable_overscan && !suppress_overscan) ? (overscan_y >> 1) : 0; + x_add = (enable_overscan && !suppress_overscan) ? 8 : 0; + + /* The planes come in two parts, and each plane is 1bpp, + so a 32x32 cursor has 4 bytes per line, and a 64x64 + cursor has 8 bytes per line. */ + pitch = (svga->hwcursor_latch.xsize >> 3); /* Bytes per line. */ + + /* A 32x32 cursor has 128 bytes per line, and a 64x64 + cursor has 512 bytes per line. */ + bppl = (pitch * svga->hwcursor_latch.ysize); /* Bytes per plane. */ + mode = dev->cr2 & 0x03; + + if (svga->interlace && svga->hwcursor_oddeven) + svga->hwcursor_latch.addr += pitch; + if (svga->hwcursor_latch.xsize == 64) + cd = (uint8_t *) dev->cursor64_data; + else + cd = (uint8_t *) dev->cursor32_data; + + for (x = 0; x < svga->hwcursor_latch.xsize; x += 16) { + dat[0] = (cd[svga->hwcursor_latch.addr] << 8) | + cd[svga->hwcursor_latch.addr + 1]; + dat[1] = (cd[svga->hwcursor_latch.addr + bppl] << 8) | + cd[svga->hwcursor_latch.addr + bppl + 1]; + + for (xx = 0; xx < 16; xx++) { + b0 = (dat[0] >> (15 - xx)) & 1; + b1 = (dat[1] >> (15 - xx)) & 1; + comb = (b0 | (b1 << 1)); + + y_pos = displine + y_add; + x_pos = offset + 32 + x_add; + p = ((uint32_t *)buffer32->line[y_pos]); + + if (offset >= svga->hwcursor_latch.x) { + switch (mode) { + case 1: /* Three Color */ + switch (comb) { + case 1: + p[x_pos] = clr1; + break; + + case 2: + p[x_pos] = clr2; + break; + + case 3: + p[x_pos] = clr3; + break; + } + break; + + case 2: /* PM/Windows */ + switch (comb) { + case 0: + p[x_pos] = clr1; + break; + + case 1: + p[x_pos] = clr2; + break; + + case 3: + p[x_pos] ^= 0xffffff; + break; + } + break; + + case 3: /* X-Windows */ + switch (comb) { + case 2: + p[x_pos] = clr1; + break; + + case 3: + p[x_pos] = clr2; + break; + } + break; + } + } + + offset++; + } + + svga->hwcursor_latch.addr += 2; + } + + if (svga->interlace && !svga->hwcursor_oddeven) + svga->hwcursor_latch.addr += pitch; +} + + + +static void * +bt48x_init(const device_t *info) +{ + bt48x_ramdac_t *dev; + + dev = (bt48x_ramdac_t *)mem_alloc(sizeof(bt48x_ramdac_t)); + memset(dev, 0x00, sizeof(bt48x_ramdac_t)); + dev->type = info->local; + + /* + * Set the RAM DAC status byte to the correct ID bits. + * + * Both the BT484 and BT485 datasheets say this: + * SR7-SR6: These bits are identification values. SR7=0 and SR6=1. + * But all other sources seem to assume SR7=1 and SR6=0. + */ + switch (dev->type) { + case BT484: + dev->status = 0x40; + break; + + case ATT20C504: + dev->status = 0x40; + break; + + case BT485: + dev->status = 0x60; + break; + + case ATT20C505: + dev->status = 0xd0; + break; + + case BT485A: + dev->status = 0x20; + break; + } + + return(dev); +} + + +static void +bt48x_close(void *priv) +{ + bt48x_ramdac_t *dev = (bt48x_ramdac_t *)priv; + + if (dev != NULL) + free(dev); +} + + +const device_t bt484_ramdac_device = { + "Brooktree Bt484 RAMDAC", + 0, + BT484, + bt48x_init, bt48x_close, NULL, + NULL, NULL, NULL, NULL, + NULL +}; + +const device_t att20c504_ramdac_device = { + "AT&T 20c504 RAMDAC", + 0, + ATT20C504, + bt48x_init, bt48x_close, NULL, + NULL, NULL, NULL, NULL, + NULL +}; + +const device_t bt485_ramdac_device = { + "Brooktree Bt485 RAMDAC", + 0, + BT485, + bt48x_init, bt48x_close, NULL, + NULL, NULL, NULL, NULL, + NULL +}; + +const device_t att20c505_ramdac_device = { + "AT&T 20c505 RAMDAC", + 0, + ATT20C505, + bt48x_init, bt48x_close, NULL, + NULL, NULL, NULL, NULL, + NULL +}; + +const device_t bt485a_ramdac_device = { + "Brooktree Bt485A RAMDAC", + 0, + BT485A, + bt48x_init, bt48x_close, NULL, + NULL, NULL, NULL, NULL, + NULL +}; diff --git a/src/devices/video/vid_bt48x_ramdac.h b/src/devices/video/vid_bt48x_ramdac.h new file mode 100644 index 0000000..0db3450 --- /dev/null +++ b/src/devices/video/vid_bt48x_ramdac.h @@ -0,0 +1,75 @@ +/* + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. + * + * This file is part of the VARCem Project. + * + * Definitions for the Bt48x RAMDAC series driver. + * + * Version: @(#)vid_bt485_ramdac.h 1.0.3 2018/10/05 + * + * Authors: Fred N. van Kempen, + * Miran Grca, + * Sarah Walker, + * + * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2016-2018 Miran Grca. + * Copyright 2008-2018 Sarah Walker. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the: + * + * Free Software Foundation, Inc. + * 59 Temple Place - Suite 330 + * Boston, MA 02111-1307 + * USA. + */ +#ifndef VIDEO_BT48X_RAMDAC_H +# define VIDEO_BT48X_RAMDAC_H + + +typedef struct { + PALETTE extpal; + uint32_t extpallook[256]; + uint8_t cursor32_data[256]; + uint8_t cursor64_data[1024]; + int hwc_y, hwc_x; + uint8_t cr0; + uint8_t cr1; + uint8_t cr2; + uint8_t cr3; + uint8_t cr4; + uint8_t status; + uint8_t type; + uint8_t ext_addr; +} bt48x_ramdac_t; + + +extern const device_t bt484_ramdac_device; +extern const device_t att20c504_ramdac_device; +extern const device_t bt485_ramdac_device; +extern const device_t att20c505_ramdac_device; +extern const device_t bt485a_ramdac_device; + + +extern void bt48x_ramdac_out(uint16_t addr, int rs2, int rs3, uint8_t val, + bt48x_ramdac_t *dev, svga_t *svga); + +extern uint8_t bt48x_ramdac_in(uint16_t addr, int rs2, int rs3, + bt48x_ramdac_t *dev, svga_t *svga); + +extern void bt48x_hwcursor_draw(svga_t *svga, int displine); + +#endif /*VIDEO_BT48X_RAMDAC_H*/ diff --git a/src/devices/video/vid_cga.c b/src/devices/video/vid_cga.c index edd2a6f..592839d 100644 --- a/src/devices/video/vid_cga.c +++ b/src/devices/video/vid_cga.c @@ -8,7 +8,7 @@ * * Emulation of the old and new IBM CGA graphics cards. * - * Version: @(#)vid_cga.c 1.0.4 2018/05/06 + * Version: @(#)vid_cga.c 1.0.5 2018/09/22 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -55,572 +55,578 @@ #include "vid_cga_comp.h" +#define CGA_FONT_ROM_PATH L"video/ibm/cga/cga.rom" + #define CGA_RGB 0 #define CGA_COMPOSITE 1 #define COMPOSITE_OLD 0 #define COMPOSITE_NEW 1 -static uint8_t crtcmask[32] = -{ - 0xff, 0xff, 0xff, 0xff, 0x7f, 0x1f, 0x7f, 0x7f, 0xf3, 0x1f, 0x7f, 0x1f, 0x3f, 0xff, 0x3f, 0xff, - 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + +static const uint8_t crtcmask[32] = { + 0xff, 0xff, 0xff, 0xff, 0x7f, 0x1f, 0x7f, 0x7f, + 0xf3, 0x1f, 0x7f, 0x1f, 0x3f, 0xff, 0x3f, 0xff, + 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; -void cga_recalctimings(cga_t *cga); -void cga_out(uint16_t addr, uint8_t val, void *p) +void +cga_recalctimings(cga_t *dev) { - cga_t *cga = (cga_t *)p; - uint8_t old; - switch (addr) - { - case 0x3D4: - cga->crtcreg = val & 31; - return; - case 0x3D5: - old = cga->crtc[cga->crtcreg]; - cga->crtc[cga->crtcreg] = val & crtcmask[cga->crtcreg]; - if (old != val) - { - if (cga->crtcreg < 0xe || cga->crtcreg > 0x10) - { - fullchange = changeframecount; - cga_recalctimings(cga); - } - } - return; - case 0x3D8: - if (((cga->cgamode ^ val) & 5) != 0) - { - cga->cgamode = val; - update_cga16_color(cga->cgamode); - } + double disptime; + double _dispontime, _dispofftime; - if ((cga->cgamode ^ val) & 1) - { - cga_palette = (cga->rgb_type << 1); - cgapal_rebuild(); - } + if (dev->cgamode & 1) { + disptime = (double) (dev->crtc[0] + 1); + _dispontime = (double) dev->crtc[1]; + } else { + disptime = (double) ((dev->crtc[0] + 1) << 1); + _dispontime = (double) (dev->crtc[1] << 1); + } + _dispofftime = disptime - _dispontime; + _dispontime = _dispontime * CGACONST; + _dispofftime = _dispofftime * CGACONST; - cga->cgamode = val; - return; - case 0x3D9: - cga->cgacol = val; - return; - } -} - -uint8_t cga_in(uint16_t addr, void *p) -{ - cga_t *cga = (cga_t *)p; - switch (addr) - { - case 0x3D4: - return cga->crtcreg; - case 0x3D5: - return cga->crtc[cga->crtcreg]; - case 0x3DA: - return cga->cgastat; - } - return 0xFF; -} - -void cga_write(uint32_t addr, uint8_t val, void *p) -{ - cga_t *cga = (cga_t *)p; - - cga->vram[addr & 0x3fff] = val; - if (cga->snow_enabled) - { - cga->charbuffer[ ((int)(((cga->dispontime - cga->vidtime) * 2) / CGACONST)) & 0xfc] = val; - cga->charbuffer[(((int)(((cga->dispontime - cga->vidtime) * 2) / CGACONST)) & 0xfc) | 1] = val; - } - egawrites++; - cycles -= 4; -} - -uint8_t cga_read(uint32_t addr, void *p) -{ - cga_t *cga = (cga_t *)p; - cycles -= 4; - if (cga->snow_enabled) - { - cga->charbuffer[ ((int)(((cga->dispontime - cga->vidtime) * 2) / CGACONST)) & 0xfc] = cga->vram[addr & 0x3fff]; - cga->charbuffer[(((int)(((cga->dispontime - cga->vidtime) * 2) / CGACONST)) & 0xfc) | 1] = cga->vram[addr & 0x3fff]; - } - egareads++; - return cga->vram[addr & 0x3fff]; -} - -void cga_recalctimings(cga_t *cga) -{ - double disptime; - double _dispontime, _dispofftime; - /* pclog("Recalc - %i %i %i\n", cga->crtc[0], cga->crtc[1], cga->cgamode & 1); */ - if (cga->cgamode & 1) - { - disptime = (double) (cga->crtc[0] + 1); - _dispontime = (double) cga->crtc[1]; - } - else - { - disptime = (double) ((cga->crtc[0] + 1) << 1); - _dispontime = (double) (cga->crtc[1] << 1); - } - _dispofftime = disptime - _dispontime; - _dispontime = _dispontime * CGACONST; - _dispofftime = _dispofftime * CGACONST; - cga->dispontime = (int64_t)(_dispontime * (1LL << TIMER_SHIFT)); - cga->dispofftime = (int64_t)(_dispofftime * (1LL << TIMER_SHIFT)); -} - -void cga_poll(void *p) -{ - cga_t *cga = (cga_t *)p; - uint16_t ca = (cga->crtc[15] | (cga->crtc[14] << 8)) & 0x3fff; - int drawcursor; - int x, c; - int oldvc; - uint8_t chr, attr; - uint16_t dat; - int cols[4]; - int col; - int oldsc; - - if (!cga->linepos) - { - cga->vidtime += cga->dispofftime; - cga->cgastat |= 1; - cga->linepos = 1; - oldsc = cga->sc; - if ((cga->crtc[8] & 3) == 3) - cga->sc = ((cga->sc << 1) + cga->oddeven) & 7; - if (cga->cgadispon) - { - if (cga->displine < cga->firstline) - { - cga->firstline = cga->displine; - video_wait_for_buffer(); - } - cga->lastline = cga->displine; - for (c = 0; c < 8; c++) - { - if ((cga->cgamode & 0x12) == 0x12) - { - buffer->line[cga->displine][c] = 0; - if (cga->cgamode & 1) buffer->line[cga->displine][c + (cga->crtc[1] << 3) + 8] = 0; - else buffer->line[cga->displine][c + (cga->crtc[1] << 4) + 8] = 0; - } - else - { - buffer->line[cga->displine][c] = (cga->cgacol & 15) + 16; - if (cga->cgamode & 1) buffer->line[cga->displine][c + (cga->crtc[1] << 3) + 8] = (cga->cgacol & 15) + 16; - else buffer->line[cga->displine][c + (cga->crtc[1] << 4) + 8] = (cga->cgacol & 15) + 16; - } - } - if (cga->cgamode & 1) - { - for (x = 0; x < cga->crtc[1]; x++) - { - chr = cga->charbuffer[x << 1]; - attr = cga->charbuffer[(x << 1) + 1]; - drawcursor = ((cga->ma == ca) && cga->con && cga->cursoron); - if (cga->cgamode & 0x20) - { - cols[1] = (attr & 15) + 16; - cols[0] = ((attr >> 4) & 7) + 16; - if ((cga->cgablink & 8) && (attr & 0x80) && !cga->drawcursor) - cols[1] = cols[0]; - } - else - { - cols[1] = (attr & 15) + 16; - cols[0] = (attr >> 4) + 16; - } - if (drawcursor) - { - for (c = 0; c < 8; c++) - buffer->line[cga->displine][(x << 3) + c + 8] = cols[(fontdat[chr + cga->fontbase][cga->sc & 7] & (1 << (c ^ 7))) ? 1 : 0] ^ 15; - } - else - { - for (c = 0; c < 8; c++) - buffer->line[cga->displine][(x << 3) + c + 8] = cols[(fontdat[chr + cga->fontbase][cga->sc & 7] & (1 << (c ^ 7))) ? 1 : 0]; - } - cga->ma++; - } - } - else if (!(cga->cgamode & 2)) - { - for (x = 0; x < cga->crtc[1]; x++) - { - chr = cga->vram[((cga->ma << 1) & 0x3fff)]; - attr = cga->vram[(((cga->ma << 1) + 1) & 0x3fff)]; - drawcursor = ((cga->ma == ca) && cga->con && cga->cursoron); - if (cga->cgamode & 0x20) - { - cols[1] = (attr & 15) + 16; - cols[0] = ((attr >> 4) & 7) + 16; - if ((cga->cgablink & 8) && (attr & 0x80)) cols[1] = cols[0]; - } - else - { - cols[1] = (attr & 15) + 16; - cols[0] = (attr >> 4) + 16; - } - cga->ma++; - if (drawcursor) - { - for (c = 0; c < 8; c++) - buffer->line[cga->displine][(x << 4)+(c << 1) + 8] = buffer->line[cga->displine][(x << 4) + (c << 1) + 1 + 8] = cols[(fontdat[chr + cga->fontbase][cga->sc & 7] & (1 << (c ^ 7))) ? 1 : 0] ^ 15; - } - else - { - for (c = 0; c < 8; c++) - buffer->line[cga->displine][(x << 4) + (c << 1) + 8] = buffer->line[cga->displine][(x << 4) + (c << 1) + 1 + 8] = cols[(fontdat[chr + cga->fontbase][cga->sc & 7] & (1 << (c ^ 7))) ? 1 : 0]; - } - } - } - else if (!(cga->cgamode & 16)) - { - cols[0] = (cga->cgacol & 15) | 16; - col = (cga->cgacol & 16) ? 24 : 16; - if (cga->cgamode & 4) - { - cols[1] = col | 3; - cols[2] = col | 4; - cols[3] = col | 7; - } - else if (cga->cgacol & 32) - { - cols[1] = col | 3; - cols[2] = col | 5; - cols[3] = col | 7; - } - else - { - cols[1] = col | 2; - cols[2] = col | 4; - cols[3] = col | 6; - } - for (x = 0; x < cga->crtc[1]; x++) - { - dat = (cga->vram[((cga->ma << 1) & 0x1fff) + ((cga->sc & 1) * 0x2000)] << 8) | cga->vram[((cga->ma << 1) & 0x1fff) + ((cga->sc & 1) * 0x2000) + 1]; - cga->ma++; - for (c = 0; c < 8; c++) - { - buffer->line[cga->displine][(x << 4) + (c << 1) + 8] = - buffer->line[cga->displine][(x << 4) + (c << 1) + 1 + 8] = cols[dat >> 14]; - dat <<= 2; - } - } - } - else - { - cols[0] = 0; cols[1] = (cga->cgacol & 15) + 16; - for (x = 0; x < cga->crtc[1]; x++) - { - dat = (cga->vram[((cga->ma << 1) & 0x1fff) + ((cga->sc & 1) * 0x2000)] << 8) | cga->vram[((cga->ma << 1) & 0x1fff) + ((cga->sc & 1) * 0x2000) + 1]; - cga->ma++; - for (c = 0; c < 16; c++) - { - buffer->line[cga->displine][(x << 4) + c + 8] = cols[dat >> 15]; - dat <<= 1; - } - } - } - } - else - { - cols[0] = ((cga->cgamode & 0x12) == 0x12) ? 0 : (cga->cgacol & 15) + 16; - if (cga->cgamode & 1) hline(buffer, 0, cga->displine, (cga->crtc[1] << 3) + 16, cols[0]); - else hline(buffer, 0, cga->displine, (cga->crtc[1] << 4) + 16, cols[0]); - } - - if (cga->cgamode & 1) x = (cga->crtc[1] << 3) + 16; - else x = (cga->crtc[1] << 4) + 16; - - if (cga->composite) - { - for (c = 0; c < x; c++) - buffer32->line[cga->displine][c] = buffer->line[cga->displine][c] & 0xf; - - Composite_Process(cga->cgamode, 0, x >> 2, buffer32->line[cga->displine]); - } - - cga->sc = oldsc; - if (cga->vc == cga->crtc[7] && !cga->sc) - cga->cgastat |= 8; - cga->displine++; - if (cga->displine >= 360) - cga->displine = 0; - } - else - { - cga->vidtime += cga->dispontime; - cga->linepos = 0; - if (cga->vsynctime) - { - cga->vsynctime--; - if (!cga->vsynctime) - cga->cgastat &= ~8; - } - if (cga->sc == (cga->crtc[11] & 31) || ((cga->crtc[8] & 3) == 3 && cga->sc == ((cga->crtc[11] & 31) >> 1))) - { - cga->con = 0; - cga->coff = 1; - } - if ((cga->crtc[8] & 3) == 3 && cga->sc == (cga->crtc[9] >> 1)) - cga->maback = cga->ma; - if (cga->vadj) - { - cga->sc++; - cga->sc &= 31; - cga->ma = cga->maback; - cga->vadj--; - if (!cga->vadj) - { - cga->cgadispon = 1; - cga->ma = cga->maback = (cga->crtc[13] | (cga->crtc[12] << 8)) & 0x3fff; - cga->sc = 0; - } - } - else if (cga->sc == cga->crtc[9]) - { - cga->maback = cga->ma; - cga->sc = 0; - oldvc = cga->vc; - cga->vc++; - cga->vc &= 127; - - if (cga->vc == cga->crtc[6]) - cga->cgadispon = 0; - - if (oldvc == cga->crtc[4]) - { - cga->vc = 0; - cga->vadj = cga->crtc[5]; - if (!cga->vadj) cga->cgadispon = 1; - if (!cga->vadj) cga->ma = cga->maback = (cga->crtc[13] | (cga->crtc[12] << 8)) & 0x3fff; - if ((cga->crtc[10] & 0x60) == 0x20) cga->cursoron = 0; - else cga->cursoron = cga->cgablink & 8; - } - - if (cga->vc == cga->crtc[7]) - { - cga->cgadispon = 0; - cga->displine = 0; - cga->vsynctime = 16; - if (cga->crtc[7]) - { - if (cga->cgamode & 1) x = (cga->crtc[1] << 3) + 16; - else x = (cga->crtc[1] << 4) + 16; - cga->lastline++; - if ((x != xsize) || ((cga->lastline - cga->firstline) != ysize) || video_force_resize_get()) - { - xsize = x; - ysize = cga->lastline - cga->firstline; - if (xsize < 64) xsize = 656; - if (ysize < 32) ysize = 200; - set_screen_size(xsize, (ysize << 1) + 16); - - if (video_force_resize_get()) - video_force_resize_set(0); - } - - if (cga->composite) - video_blit_memtoscreen(0, cga->firstline - 4, 0, (cga->lastline - cga->firstline) + 8, xsize, (cga->lastline - cga->firstline) + 8); - else - video_blit_memtoscreen_8(0, cga->firstline - 4, 0, (cga->lastline - cga->firstline) + 8, xsize, (cga->lastline - cga->firstline) + 8); - frames++; - - video_res_x = xsize - 16; - video_res_y = ysize; - if (cga->cgamode & 1) - { - video_res_x /= 8; - video_res_y /= cga->crtc[9] + 1; - video_bpp = 0; - } - else if (!(cga->cgamode & 2)) - { - video_res_x /= 16; - video_res_y /= cga->crtc[9] + 1; - video_bpp = 0; - } - else if (!(cga->cgamode & 16)) - { - video_res_x /= 2; - video_bpp = 2; - } - else - { - video_bpp = 1; - } - } - cga->firstline = 1000; - cga->lastline = 0; - cga->cgablink++; - cga->oddeven ^= 1; - } - } - else - { - cga->sc++; - cga->sc &= 31; - cga->ma = cga->maback; - } - if (cga->cgadispon) - cga->cgastat &= ~1; - if ((cga->sc == (cga->crtc[10] & 31) || ((cga->crtc[8] & 3) == 3 && cga->sc == ((cga->crtc[10] & 31) >> 1)))) - cga->con = 1; - if (cga->cgadispon && (cga->cgamode & 1)) - { - for (x = 0; x < (cga->crtc[1] << 1); x++) - cga->charbuffer[x] = cga->vram[(((cga->ma << 1) + x) & 0x3fff)]; - } - } + dev->dispontime = (int64_t)(_dispontime * (1LL << TIMER_SHIFT)); + dev->dispofftime = (int64_t)(_dispofftime * (1LL << TIMER_SHIFT)); } void -cga_init(cga_t *cga) +cga_out(uint16_t port, uint8_t val, void *priv) { - cga->composite = 0; + cga_t *dev = (cga_t *)priv; + uint8_t old; + + switch (port) { + case 0x3d4: + dev->crtcreg = val & 31; + return; + + case 0x3d5: + old = dev->crtc[dev->crtcreg]; + dev->crtc[dev->crtcreg] = val & crtcmask[dev->crtcreg]; + if (old != val) { + if (dev->crtcreg < 0xe || dev->crtcreg > 0x10) { + fullchange = changeframecount; + cga_recalctimings(dev); + } + } + return; + + case 0x3d8: + if (((dev->cgamode ^ val) & 5) != 0) { + dev->cgamode = val; + update_cga16_color(dev->cgamode); + } + + if ((dev->cgamode ^ val) & 1) { + cga_palette = (dev->rgb_type << 1); + cgapal_rebuild(); + } + + dev->cgamode = val; + return; + + case 0x3d9: + dev->cgacol = val; + return; + } +} + + +uint8_t +cga_in(uint16_t port, void *priv) +{ + cga_t *dev = (cga_t *)priv; + uint8_t ret = 0xff; + + switch (port) { + case 0x3d4: + ret = dev->crtcreg; + break; + + case 0x3d5: + ret = dev->crtc[dev->crtcreg]; + break; + + case 0x3da: + ret = dev->cgastat; + break; + + default: + break; + } + + return ret; +} + + +void +cga_write(uint32_t addr, uint8_t val, void *priv) +{ + cga_t *dev = (cga_t *)priv; + + dev->vram[addr & 0x3fff] = val; + if (dev->snow_enabled) { + dev->charbuffer[ ((int)(((dev->dispontime - dev->vidtime) * 2) / CGACONST)) & 0xfc] = val; + dev->charbuffer[(((int)(((dev->dispontime - dev->vidtime) * 2) / CGACONST)) & 0xfc) | 1] = val; + } + + cycles -= 4; +} + + +uint8_t +cga_read(uint32_t addr, void *priv) +{ + cga_t *dev = (cga_t *)priv; + + cycles -= 4; + + if (dev->snow_enabled) { + dev->charbuffer[ ((int)(((dev->dispontime - dev->vidtime) * 2) / CGACONST)) & 0xfc] = dev->vram[addr & 0x3fff]; + dev->charbuffer[(((int)(((dev->dispontime - dev->vidtime) * 2) / CGACONST)) & 0xfc) | 1] = dev->vram[addr & 0x3fff]; + } + + return dev->vram[addr & 0x3fff]; +} + + +void +cga_hline(bitmap_t *b, int x1, int y, int x2, uint32_t col) +{ + if (y < 0 || y >= buffer->h) + return; + + if (b == buffer) + memset(&b->line[y][x1], col, x2 - x1); + else + memset(&((uint32_t *)b->line[y])[x1], col, (x2 - x1) * 4); +} + + +void +cga_poll(void *priv) +{ + cga_t *dev = (cga_t *)priv; + uint16_t ca = (dev->crtc[15] | (dev->crtc[14] << 8)) & 0x3fff; + int drawcursor; + int x, c; + int oldvc; + uint8_t chr, attr; + uint16_t dat; + int cols[4]; + int col; + int oldsc; + + if (! dev->linepos) { + dev->vidtime += dev->dispofftime; + dev->cgastat |= 1; + dev->linepos = 1; + oldsc = dev->sc; + + if ((dev->crtc[8] & 3) == 3) + dev->sc = ((dev->sc << 1) + dev->oddeven) & 7; + + if (dev->cgadispon) { + if (dev->displine < dev->firstline) { + dev->firstline = dev->displine; + video_wait_for_buffer(); + } + dev->lastline = dev->displine; + + for (c = 0; c < 8; c++) { + if ((dev->cgamode & 0x12) == 0x12) { + buffer->line[dev->displine][c] = 0; + if (dev->cgamode & 1) + buffer->line[dev->displine][c + (dev->crtc[1] << 3) + 8] = 0; + else + buffer->line[dev->displine][c + (dev->crtc[1] << 4) + 8] = 0; + } else { + buffer->line[dev->displine][c] = (dev->cgacol & 15) + 16; + if (dev->cgamode & 1) + buffer->line[dev->displine][c + (dev->crtc[1] << 3) + 8] = (dev->cgacol & 15) + 16; + else + buffer->line[dev->displine][c + (dev->crtc[1] << 4) + 8] = (dev->cgacol & 15) + 16; + } + } + + if (dev->cgamode & 1) { + for (x = 0; x < dev->crtc[1]; x++) { + chr = dev->charbuffer[x << 1]; + attr = dev->charbuffer[(x << 1) + 1]; + drawcursor = ((dev->ma == ca) && dev->con && dev->cursoron); + if (dev->cgamode & 0x20) { + cols[1] = (attr & 15) + 16; + cols[0] = ((attr >> 4) & 7) + 16; + if ((dev->cgablink & 8) && (attr & 0x80) && !dev->drawcursor) + cols[1] = cols[0]; + } else { + cols[1] = (attr & 15) + 16; + cols[0] = (attr >> 4) + 16; + } + + if (drawcursor) { + for (c = 0; c < 8; c++) + buffer->line[dev->displine][(x << 3) + c + 8] = cols[(fontdat[chr + dev->fontbase][dev->sc & 7] & (1 << (c ^ 7))) ? 1 : 0] ^ 15; + } else { + for (c = 0; c < 8; c++) + buffer->line[dev->displine][(x << 3) + c + 8] = cols[(fontdat[chr + dev->fontbase][dev->sc & 7] & (1 << (c ^ 7))) ? 1 : 0]; + } + dev->ma++; + } + } else if (!(dev->cgamode & 2)) { + for (x = 0; x < dev->crtc[1]; x++) { + chr = dev->vram[((dev->ma << 1) & 0x3fff)]; + attr = dev->vram[(((dev->ma << 1) + 1) & 0x3fff)]; + drawcursor = ((dev->ma == ca) && dev->con && dev->cursoron); + if (dev->cgamode & 0x20) { + cols[1] = (attr & 15) + 16; + cols[0] = ((attr >> 4) & 7) + 16; + if ((dev->cgablink & 8) && (attr & 0x80)) cols[1] = cols[0]; + } else { + cols[1] = (attr & 15) + 16; + cols[0] = (attr >> 4) + 16; + } + dev->ma++; + + if (drawcursor) { + for (c = 0; c < 8; c++) + buffer->line[dev->displine][(x << 4)+(c << 1) + 8] = buffer->line[dev->displine][(x << 4) + (c << 1) + 1 + 8] = cols[(fontdat[chr + dev->fontbase][dev->sc & 7] & (1 << (c ^ 7))) ? 1 : 0] ^ 15; + } else { + for (c = 0; c < 8; c++) + buffer->line[dev->displine][(x << 4) + (c << 1) + 8] = buffer->line[dev->displine][(x << 4) + (c << 1) + 1 + 8] = cols[(fontdat[chr + dev->fontbase][dev->sc & 7] & (1 << (c ^ 7))) ? 1 : 0]; + } + } + } else if (!(dev->cgamode & 16)) { + cols[0] = (dev->cgacol & 15) | 16; + col = (dev->cgacol & 16) ? 24 : 16; + if (dev->cgamode & 4) { + cols[1] = col | 3; + cols[2] = col | 4; + cols[3] = col | 7; + } else if (dev->cgacol & 32) { + cols[1] = col | 3; + cols[2] = col | 5; + cols[3] = col | 7; + } else { + cols[1] = col | 2; + cols[2] = col | 4; + cols[3] = col | 6; + } + + for (x = 0; x < dev->crtc[1]; x++) { + dat = (dev->vram[((dev->ma << 1) & 0x1fff) + ((dev->sc & 1) * 0x2000)] << 8) | dev->vram[((dev->ma << 1) & 0x1fff) + ((dev->sc & 1) * 0x2000) + 1]; + dev->ma++; + for (c = 0; c < 8; c++) { + buffer->line[dev->displine][(x << 4) + (c << 1) + 8] = buffer->line[dev->displine][(x << 4) + (c << 1) + 1 + 8] = cols[dat >> 14]; + dat <<= 2; + } + } + } else { + cols[0] = 0; cols[1] = (dev->cgacol & 15) + 16; + for (x = 0; x < dev->crtc[1]; x++) { + dat = (dev->vram[((dev->ma << 1) & 0x1fff) + ((dev->sc & 1) * 0x2000)] << 8) | dev->vram[((dev->ma << 1) & 0x1fff) + ((dev->sc & 1) * 0x2000) + 1]; + dev->ma++; + + for (c = 0; c < 16; c++) { + buffer->line[dev->displine][(x << 4) + c + 8] = cols[dat >> 15]; + dat <<= 1; + } + } + } + } else { + cols[0] = ((dev->cgamode & 0x12) == 0x12) ? 0 : (dev->cgacol & 15) + 16; + if (dev->cgamode & 1) + cga_hline(buffer, 0, dev->displine, (dev->crtc[1] << 3) + 16, cols[0]); + else + cga_hline(buffer, 0, dev->displine, (dev->crtc[1] << 4) + 16, cols[0]); + } + + if (dev->cgamode & 1) + x = (dev->crtc[1] << 3) + 16; + else + x = (dev->crtc[1] << 4) + 16; + + if (dev->composite) { + for (c = 0; c < x; c++) + buffer32->line[dev->displine][c] = buffer->line[dev->displine][c] & 0xf; + + Composite_Process(dev->cgamode, 0, x >> 2, buffer32->line[dev->displine]); + } + + dev->sc = oldsc; + if (dev->vc == dev->crtc[7] && !dev->sc) + dev->cgastat |= 8; + dev->displine++; + if (dev->displine >= 360) + dev->displine = 0; + } else { + dev->vidtime += dev->dispontime; + dev->linepos = 0; + if (dev->vsynctime) { + dev->vsynctime--; + if (!dev->vsynctime) + dev->cgastat &= ~8; + } + + if (dev->sc == (dev->crtc[11] & 31) || ((dev->crtc[8] & 3) == 3 && dev->sc == ((dev->crtc[11] & 31) >> 1))) { + dev->con = 0; + dev->coff = 1; + } + + if ((dev->crtc[8] & 3) == 3 && dev->sc == (dev->crtc[9] >> 1)) + dev->maback = dev->ma; + + if (dev->vadj) { + dev->sc++; + dev->sc &= 31; + dev->ma = dev->maback; + dev->vadj--; + if (! dev->vadj) { + dev->cgadispon = 1; + dev->ma = dev->maback = (dev->crtc[13] | (dev->crtc[12] << 8)) & 0x3fff; + dev->sc = 0; + } + } else if (dev->sc == dev->crtc[9]) { + dev->maback = dev->ma; + dev->sc = 0; + oldvc = dev->vc; + dev->vc++; + dev->vc &= 127; + + if (dev->vc == dev->crtc[6]) + dev->cgadispon = 0; + + if (oldvc == dev->crtc[4]) { + dev->vc = 0; + dev->vadj = dev->crtc[5]; + if (! dev->vadj) + dev->cgadispon = 1; + if (! dev->vadj) + dev->ma = dev->maback = (dev->crtc[13] | (dev->crtc[12] << 8)) & 0x3fff; + if ((dev->crtc[10] & 0x60) == 0x20) + dev->cursoron = 0; + else + dev->cursoron = dev->cgablink & 8; + } + + if (dev->vc == dev->crtc[7]) { + dev->cgadispon = 0; + dev->displine = 0; + dev->vsynctime = 16; + if (dev->crtc[7]) { + if (dev->cgamode & 1) + x = (dev->crtc[1] << 3) + 16; + else + x = (dev->crtc[1] << 4) + 16; + dev->lastline++; + + if ((x != xsize) || ((dev->lastline - dev->firstline) != ysize) || video_force_resize_get()) { + xsize = x; + ysize = dev->lastline - dev->firstline; + if (xsize < 64) xsize = 656; + if (ysize < 32) ysize = 200; + set_screen_size(xsize, (ysize << 1) + 16); + + if (video_force_resize_get()) + video_force_resize_set(0); + } + + if (dev->composite) + video_blit_memtoscreen(0, dev->firstline - 4, 0, (dev->lastline - dev->firstline) + 8, xsize, (dev->lastline - dev->firstline) + 8); + else + video_blit_memtoscreen_8(0, dev->firstline - 4, 0, (dev->lastline - dev->firstline) + 8, xsize, (dev->lastline - dev->firstline) + 8); + frames++; + + video_res_x = xsize - 16; + video_res_y = ysize; + if (dev->cgamode & 1) { + video_res_x /= 8; + video_res_y /= dev->crtc[9] + 1; + video_bpp = 0; + } else if (!(dev->cgamode & 2)) { + video_res_x /= 16; + video_res_y /= dev->crtc[9] + 1; + video_bpp = 0; + } else if (!(dev->cgamode & 16)) { + video_res_x /= 2; + video_bpp = 2; + } else { + video_bpp = 1; + } + } + dev->firstline = 1000; + dev->lastline = 0; + dev->cgablink++; + dev->oddeven ^= 1; + } + } else { + dev->sc++; + dev->sc &= 31; + dev->ma = dev->maback; + } + + if (dev->cgadispon) + dev->cgastat &= ~1; + + if ((dev->sc == (dev->crtc[10] & 31) || ((dev->crtc[8] & 3) == 3 && dev->sc == ((dev->crtc[10] & 31) >> 1)))) + dev->con = 1; + + if (dev->cgadispon && (dev->cgamode & 1)) { + for (x = 0; x < (dev->crtc[1] << 1); x++) + dev->charbuffer[x] = dev->vram[(((dev->ma << 1) + x) & 0x3fff)]; + } + } +} + + +void +cga_init(cga_t *dev) +{ + dev->composite = 0; } void * cga_standalone_init(const device_t *info) { + cga_t *dev; int display_type; - cga_t *cga = malloc(sizeof(cga_t)); - memset(cga, 0x00, sizeof(cga_t)); + dev = (cga_t *)mem_alloc(sizeof(cga_t)); + memset(dev, 0x00, sizeof(cga_t)); display_type = device_get_config_int("display_type"); - cga->composite = (display_type != CGA_RGB); - cga->revision = device_get_config_int("composite_type"); - cga->snow_enabled = device_get_config_int("snow_enabled"); - cga->font_type = device_get_config_int("font_type"); + dev->composite = (display_type != CGA_RGB); + dev->revision = device_get_config_int("composite_type"); + dev->snow_enabled = device_get_config_int("snow_enabled"); + dev->font_type = device_get_config_int("font_type"); + dev->rgb_type = device_get_config_int("rgb_type"); - cga->vram = malloc(0x4000); + dev->vram = (uint8_t *)mem_alloc(0x4000); + + cga_comp_init(dev->revision); + + timer_add(cga_poll, &dev->vidtime, TIMER_ALWAYS_ENABLED, dev); + + mem_map_add(&dev->mapping, 0xb8000, 0x08000, + cga_read,NULL,NULL, cga_write,NULL,NULL, + NULL, MEM_MAPPING_EXTERNAL, dev); - cga_comp_init(cga->revision); - timer_add(cga_poll, &cga->vidtime, TIMER_ALWAYS_ENABLED, cga); - mem_mapping_add(&cga->mapping, 0xb8000, 0x08000, - cga_read,NULL,NULL, cga_write,NULL,NULL, - NULL, MEM_MAPPING_EXTERNAL, cga); io_sethandler(0x03d0, 16, - cga_in,NULL,NULL, cga_out,NULL,NULL, cga); + cga_in,NULL,NULL, cga_out,NULL,NULL, dev); overscan_x = overscan_y = 16; - cga->rgb_type = device_get_config_int("rgb_type"); - cga_palette = (cga->rgb_type << 1); + cga_palette = (dev->rgb_type << 1); cgapal_rebuild(); - loadfont(L"video/ibm/cga/cga.rom", (cga->font_type) ? 8 : 2); + video_load_font(CGA_FONT_ROM_PATH, (dev->font_type) ? 8 : 2); - return cga; + video_inform(VID_TYPE_CGA, info->vid_timing); + + return dev; } void -cga_close(void *p) +cga_close(void *priv) { - cga_t *cga = (cga_t *)p; + cga_t *dev = (cga_t *)priv; - free(cga->vram); - free(cga); + free(dev->vram); + free(dev); } void -cga_speed_changed(void *p) +cga_speed_changed(void *priv) { - cga_t *cga = (cga_t *)p; + cga_t *dev = (cga_t *)priv; - cga_recalctimings(cga); + cga_recalctimings(dev); } -const device_config_t cga_config[] = -{ - { - "display_type", "Display type", CONFIG_SELECTION, "", CGA_RGB, - { - { - "RGB", CGA_RGB - }, - { - "Composite", CGA_COMPOSITE - }, - { - "" - } - } - }, - { - "composite_type", "Composite type", CONFIG_SELECTION, "", COMPOSITE_OLD, - { - { - "Old", COMPOSITE_OLD - }, - { - "New", COMPOSITE_NEW - }, - { - "" - } - } - }, - { - "rgb_type", "RGB type", CONFIG_SELECTION, "", 0, - { - { - "Color", 0 - }, - { - "Green Monochrome", 1 - }, - { - "Amber Monochrome", 2 - }, - { - "Gray Monochrome", 3 - }, - { - "Color (no brown)", 4 - }, - { - "" - } - } - }, - { - "font_type", "Font Selection", CONFIG_SELECTION, "", 1, - { - { - "Thin", 0 - }, - { - "Thick", 1 - }, - { - "" - } - } - }, - { - "snow_enabled", "Snow emulation", CONFIG_BINARY, "", 1 - }, - { - "", "", -1 - } +const device_config_t cga_config[] = { + { + "display_type", "Display type", CONFIG_SELECTION, "", CGA_RGB, + { + { + "RGB", CGA_RGB + }, + { + "Composite", CGA_COMPOSITE + }, + { + "" + } + } + }, + { + "composite_type", "Composite type", CONFIG_SELECTION, "", COMPOSITE_OLD, + { + { + "Old", COMPOSITE_OLD + }, + { + "New", COMPOSITE_NEW + }, + { + "" + } + } + }, + { + "rgb_type", "RGB type", CONFIG_SELECTION, "", 0, + { + { + "Color", 0 + }, + { + "Green Monochrome", 1 + }, + { + "Amber Monochrome", 2 + }, + { + "Gray Monochrome", 3 + }, + { + "Color (no brown)", 4 + }, + { + "" + } + } + }, + { + "font_type", "Font Selection", CONFIG_SELECTION, "", 1, + { + { + "Thin", 0 + }, + { + "Thick", 1 + }, + { + "" + } + } + }, + { + "snow_enabled", "Snow emulation", CONFIG_BINARY, "", 1 + }, + { + "", "", -1 + } }; +static const video_timings_t cga_timings = { VID_ISA,8,16,32,8,16,32 }; const device_t cga_device = { "CGA", @@ -629,6 +635,6 @@ const device_t cga_device = { NULL, cga_speed_changed, NULL, - NULL, + &cga_timings, cga_config }; diff --git a/src/devices/video/vid_cga.h b/src/devices/video/vid_cga.h index ec5366a..e47214e 100644 --- a/src/devices/video/vid_cga.h +++ b/src/devices/video/vid_cga.h @@ -8,7 +8,7 @@ * * Definitions for the CGA driver. * - * Version: @(#)vid_cga.h 1.0.4 2018/04/09 + * Version: @(#)vid_cga.h 1.0.5 2018/10/05 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -41,7 +41,7 @@ typedef struct { - mem_mapping_t mapping; + mem_map_t mapping; int crtcreg; uint8_t crtc[32]; @@ -94,6 +94,7 @@ extern void cga_write(uint32_t addr, uint8_t val, void *p); extern uint8_t cga_read(uint32_t addr, void *p); extern void cga_recalctimings(cga_t *cga); extern void cga_poll(void *p); +extern void cga_hline(bitmap_t *b, int x1, int y, int x2, uint32_t col); #endif /*VIDEO_CGA_H*/ diff --git a/src/devices/video/vid_cga_comp.c b/src/devices/video/vid_cga_comp.c index 82e6160..5e0772e 100644 --- a/src/devices/video/vid_cga_comp.c +++ b/src/devices/video/vid_cga_comp.c @@ -9,13 +9,14 @@ * IBM CGA composite filter, borrowed from reenigne's DOSBox * patch and ported to C. * - * Version: @(#)vid_cga_comp.c 1.0.4 2018/05/06 + * Version: @(#)vid_cga_comp.c 1.0.5 2018/10/05 * * Authors: Fred N. van Kempen, * Miran Grca, * reengine, * * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2015-2018 reenigne. * Copyright 2016-2018 Miran Grca. * * This program is free software; you can redistribute it and/or modify @@ -44,7 +45,7 @@ #include #include "../../emu.h" #include "../../mem.h" -#include "../../device.h" +#include "video.h" #include "vid_cga.h" #include "vid_cga_comp.h" diff --git a/src/devices/video/vid_cga_compaq.c b/src/devices/video/vid_cga_compaq.c new file mode 100644 index 0000000..c500639 --- /dev/null +++ b/src/devices/video/vid_cga_compaq.c @@ -0,0 +1,475 @@ +/* + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. + * + * This file is part of the VARCem Project. + * + * Implementation of CGA used by Compaq PC's. + * + * Version: @(#)vid_cga_compaq.c 1.0.4 2018/09/22 + * + * Authors: Fred N. van Kempen, + * Miran Grca, + * TheCollector1995, + * + * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2016-2018 Miran Grca. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the: + * + * Free Software Foundation, Inc. + * 59 Temple Place - Suite 330 + * Boston, MA 02111-1307 + * USA. + */ +#include +#include +#include +#include +#include +#include +#include "../../emu.h" +#include "../../cpu/cpu.h" +#include "../../io.h" +#include "../../mem.h" +#include "../../rom.h" +#include "../../timer.h" +#include "../../device.h" +#include "../system/pit.h" +#include "video.h" +#include "vid_cga.h" +#include "vid_cga_comp.h" + + +#define CGA_RGB 0 +#define CGA_COMPOSITE 1 + + +typedef struct { + cga_t cga; + uint32_t flags; + + uint8_t attr[256][2][2]; +} compaq_cga_t; + + +static void +recalc_timings(compaq_cga_t *dev) +{ + double _dispontime, _dispofftime, disptime; + disptime = dev->cga.crtc[0] + 1; + + _dispontime = dev->cga.crtc[1]; + _dispofftime = disptime - _dispontime; + _dispontime *= MDACONST; + _dispofftime *= MDACONST; + + dev->cga.dispontime = (int)(_dispontime * (1 << TIMER_SHIFT)); + dev->cga.dispofftime = (int)(_dispofftime * (1 << TIMER_SHIFT)); +} + + +static void +compaq_poll(void *priv) +{ + compaq_cga_t *dev = (compaq_cga_t *)priv; + uint16_t ca = (dev->cga.crtc[15] | (dev->cga.crtc[14] << 8)) & 0x3fff; + int drawcursor; + int x, c; + int oldvc; + uint8_t chr, attr; + uint32_t cols[4]; + int oldsc; + int underline = 0; + int blink = 0; + + /* If in graphics mode or character height is not 13, behave as CGA */ + if ((dev->cga.cgamode & 0x12) || (dev->cga.crtc[9] != 13)) { + overscan_x = overscan_y = 16; + cga_poll(&dev->cga); + return; + } else + overscan_x = overscan_y = 0; + + /* We are in Compaq 350-line CGA territory */ + if (! dev->cga.linepos) { + dev->cga.vidtime += dev->cga.dispofftime; + dev->cga.cgastat |= 1; + dev->cga.linepos = 1; + oldsc = dev->cga.sc; + + if ((dev->cga.crtc[8] & 3) == 3) + dev->cga.sc = ((dev->cga.sc << 1) + dev->cga.oddeven) & 7; + + if (dev->cga.cgadispon) { + if (dev->cga.displine < dev->cga.firstline) { + dev->cga.firstline = dev->cga.displine; + video_wait_for_buffer(); + } + dev->cga.lastline = dev->cga.displine; + + cols[0] = (dev->cga.cgacol & 15); + + for (c = 0; c < 8; c++) { + ((uint32_t *)buffer32->line[dev->cga.displine])[c] = cols[0]; + if (dev->cga.cgamode & 1) + ((uint32_t *)buffer32->line[dev->cga.displine])[c + (dev->cga.crtc[1] << 3) + 8] = cols[0]; + else + ((uint32_t *)buffer32->line[dev->cga.displine])[c + (dev->cga.crtc[1] << 4) + 8] = cols[0]; + } + + if (dev->cga.cgamode & 1) { + for (x = 0; x < dev->cga.crtc[1]; x++) { + chr = dev->cga.charbuffer[x << 1]; + attr = dev->cga.charbuffer[(x << 1) + 1]; + drawcursor = ((dev->cga.ma == ca) && dev->cga.con && dev->cga.cursoron); + if (dev->flags) { + underline = 0; + blink = ((dev->cga.cgablink & 8) && (dev->cga.cgamode & 0x20) && (attr & 0x80) && !drawcursor); + } + + if (dev->flags && (dev->cga.cgamode & 0x80)) { + cols[0] = dev->attr[attr][blink][0]; + cols[1] = dev->attr[attr][blink][1]; + if (dev->cga.sc == 12 && (attr & 7) == 1) underline = 1; + } else if (dev->cga.cgamode & 0x20) { + cols[1] = (attr & 15) + 16; + cols[0] = ((attr >> 4) & 7) + 16; + if (dev->flags) { + if (blink) + cols[1] = cols[0]; + } else { + if ((dev->cga.cgablink & 8) && (attr & 0x80) && !dev->cga.drawcursor) + cols[1] = cols[0]; + } + } else { + cols[1] = (attr & 15) + 16; + cols[0] = (attr >> 4) + 16; + } + + if (dev->flags && underline) { + for (c = 0; c < 8; c++) + ((uint32_t *)buffer32->line[dev->cga.displine])[(x << 3) + c + 8] = dev->attr[attr][blink][1]; + } else if (drawcursor) { + for (c = 0; c < 8; c++) + ((uint32_t *)buffer32->line[dev->cga.displine])[(x << 3) + c + 8] = cols[(fontdatm[chr + dev->cga.fontbase][dev->cga.sc & 15] & (1 << (c ^ 7))) ? 1 : 0] ^ 0xffffff; + } else { + for (c = 0; c < 8; c++) + ((uint32_t *)buffer32->line[dev->cga.displine])[(x << 3) + c + 8] = cols[(fontdatm[chr + dev->cga.fontbase][dev->cga.sc & 15] & (1 << (c ^ 7))) ? 1 : 0]; + } + dev->cga.ma++; + } + } else { + for (x = 0; x < dev->cga.crtc[1]; x++) { + chr = dev->cga.vram[((dev->cga.ma << 1) & 0x3fff)]; + attr = dev->cga.vram[(((dev->cga.ma << 1) + 1) & 0x3fff)]; + drawcursor = ((dev->cga.ma == ca) && dev->cga.con && dev->cga.cursoron); + if (dev->flags) { + underline = 0; + blink = ((dev->cga.cgablink & 8) && (dev->cga.cgamode & 0x20) && (attr & 0x80) && !drawcursor); + } + + if (dev->flags && (dev->cga.cgamode & 0x80)) { + cols[0] = dev->attr[attr][blink][0]; + cols[1] = dev->attr[attr][blink][1]; + if (dev->cga.sc == 12 && (attr & 7) == 1) underline = 1; + } else if (dev->cga.cgamode & 0x20) { + cols[1] = (attr & 15) + 16; + cols[0] = ((attr >> 4) & 7) + 16; + if (dev->flags) { + if (blink) + cols[1] = cols[0]; + } else { + if ((dev->cga.cgablink & 8) && (attr & 0x80) && !dev->cga.drawcursor) + cols[1] = cols[0]; + } + } else { + cols[1] = (attr & 15) + 16; + cols[0] = (attr >> 4) + 16; + } + dev->cga.ma++; + + if (dev->flags && underline) { + for (c = 0; c < 8; c++) + ((uint32_t *)buffer32->line[dev->cga.displine])[(x << 4)+(c << 1) + 8] = ((uint32_t *)buffer32->line[dev->cga.displine])[(x << 4)+(c << 1) + 9] = dev->attr[attr][blink][1]; + } else if (drawcursor) { + for (c = 0; c < 8; c++) + ((uint32_t *)buffer32->line[dev->cga.displine])[(x << 4)+(c << 1) + 8] = ((uint32_t *)buffer32->line[dev->cga.displine])[(x << 4) + (c << 1) + 1 + 8] = cols[(fontdatm[chr + dev->cga.fontbase][dev->cga.sc & 15] & (1 << (c ^ 7))) ? 1 : 0] ^ 15; + } else { + for (c = 0; c < 8; c++) + ((uint32_t *)buffer32->line[dev->cga.displine])[(x << 4) + (c << 1) + 8] = ((uint32_t *)buffer32->line[dev->cga.displine])[(x << 4) + (c << 1) + 1 + 8] = cols[(fontdatm[chr + dev->cga.fontbase][dev->cga.sc & 15] & (1 << (c ^ 7))) ? 1 : 0]; + } + } + } + } else { + cols[0] = (dev->cga.cgacol & 15) + 16; + if (dev->cga.cgamode & 1) + cga_hline(buffer32, 0, dev->cga.displine, (dev->cga.crtc[1] << 3) + 16, cols[0]); + else + cga_hline(buffer32, 0, dev->cga.displine, (dev->cga.crtc[1] << 4) + 16, cols[0]); + } + + if (dev->cga.cgamode & 1) + x = (dev->cga.crtc[1] << 3) + 16; + else + x = (dev->cga.crtc[1] << 4) + 16; + + if (dev->cga.composite) { + for (c = 0; c < x; c++) + buffer32->line[dev->cga.displine][c] = ((uint32_t *)buffer32->line[dev->cga.displine])[c] & 0xf; + + if (dev->flags) + Composite_Process(dev->cga.cgamode & 0x7F, 0, x >> 2, buffer32->line[dev->cga.displine]); + else + Composite_Process(dev->cga.cgamode, 0, x >> 2, buffer32->line[dev->cga.displine]); + } else { + for (c = 0; c < x; c++) + buffer->line[dev->cga.displine][c] = ((uint32_t *)buffer32->line[dev->cga.displine])[c]; + } + + dev->cga.sc = oldsc; + if (dev->cga.vc == dev->cga.crtc[7] && !dev->cga.sc) + dev->cga.cgastat |= 8; + dev->cga.displine++; + if (dev->cga.displine >= 500) + dev->cga.displine = 0; + } else { + dev->cga.vidtime += dev->cga.dispontime; + dev->cga.linepos = 0; + if (dev->cga.vsynctime) { + dev->cga.vsynctime--; + if (!dev->cga.vsynctime) + dev->cga.cgastat &= ~8; + } + + if (dev->cga.sc == (dev->cga.crtc[11] & 31) || ((dev->cga.crtc[8] & 3) == 3 && dev->cga.sc == ((dev->cga.crtc[11] & 31) >> 1))) { + dev->cga.con = 0; + dev->cga.coff = 1; + } + + if ((dev->cga.crtc[8] & 3) == 3 && dev->cga.sc == (dev->cga.crtc[9] >> 1)) + dev->cga.maback = dev->cga.ma; + + if (dev->cga.vadj) { + dev->cga.sc++; + dev->cga.sc &= 31; + dev->cga.ma = dev->cga.maback; + dev->cga.vadj--; + if (! dev->cga.vadj) { + dev->cga.cgadispon = 1; + dev->cga.ma = dev->cga.maback = (dev->cga.crtc[13] | (dev->cga.crtc[12] << 8)) & 0x3fff; + dev->cga.sc = 0; + } + } else if (dev->cga.sc == dev->cga.crtc[9]) { + dev->cga.maback = dev->cga.ma; + dev->cga.sc = 0; + oldvc = dev->cga.vc; + dev->cga.vc++; + dev->cga.vc &= 127; + + if (dev->cga.vc == dev->cga.crtc[6]) + dev->cga.cgadispon = 0; + + if (oldvc == dev->cga.crtc[4]) { + dev->cga.vc = 0; + dev->cga.vadj = dev->cga.crtc[5]; + if (! dev->cga.vadj) + dev->cga.cgadispon = 1; + if (! dev->cga.vadj) + dev->cga.ma = dev->cga.maback = (dev->cga.crtc[13] | (dev->cga.crtc[12] << 8)) & 0x3fff; + if ((dev->cga.crtc[10] & 0x60) == 0x20) + dev->cga.cursoron = 0; + else + dev->cga.cursoron = dev->cga.cgablink & 8; + } + + if (dev->cga.vc == dev->cga.crtc[7]) { + dev->cga.cgadispon = 0; + dev->cga.displine = 0; + dev->cga.vsynctime = 16; + if (dev->cga.crtc[7]) { + if (dev->cga.cgamode & 1) + x = (dev->cga.crtc[1] << 3); + else + x = (dev->cga.crtc[1] << 4); + dev->cga.lastline++; + + if (x != xsize || (dev->cga.lastline - dev->cga.firstline) != ysize) { + xsize= x; + ysize= dev->cga.lastline - dev->cga.firstline; + + if (xsize < 64) xsize = 656; + if (ysize < 32) ysize = 200; + set_screen_size(xsize, ysize); + } + + if (dev->cga.composite) + video_blit_memtoscreen(8, dev->cga.firstline, 0, ysize, xsize, ysize); + else + video_blit_memtoscreen_8(8, dev->cga.firstline, 0, ysize, xsize, ysize); + frames++; + + video_res_x = xsize - 16; + video_res_y = ysize; + if (dev->cga.cgamode & 1) { + video_res_x /= 8; + video_res_y /= dev->cga.crtc[9] + 1; + video_bpp = 0; + } else if (!(dev->cga.cgamode & 2)) { + video_res_x /= 16; + video_res_y /= dev->cga.crtc[9] + 1; + video_bpp = 0; + } else if (!(dev->cga.cgamode & 16)) { + video_res_x /= 2; + video_bpp = 2; + } else { + video_bpp = 1; + } + } + dev->cga.firstline = 1000; + dev->cga.lastline = 0; + dev->cga.cgablink++; + dev->cga.oddeven ^= 1; + } + } else { + dev->cga.sc++; + dev->cga.sc &= 31; + dev->cga.ma = dev->cga.maback; + } + + if (dev->cga.cgadispon) + dev->cga.cgastat &= ~1; + + if ((dev->cga.sc == (dev->cga.crtc[10] & 31) || ((dev->cga.crtc[8] & 3) == 3 && dev->cga.sc == ((dev->cga.crtc[10] & 31) >> 1)))) + dev->cga.con = 1; + + if (dev->cga.cgadispon && (dev->cga.cgamode & 1)) { + for (x = 0; x < (dev->cga.crtc[1] << 1); x++) + dev->cga.charbuffer[x] = dev->cga.vram[(((dev->cga.ma << 1) + x) & 0x3fff)]; + } + } +} + + +static void * +compaq_cga_init(const device_t *info) +{ + compaq_cga_t *dev; + int c, display_type; + + dev = (compaq_cga_t *)mem_alloc(sizeof(compaq_cga_t)); + memset(dev, 0x00, sizeof(compaq_cga_t)); + + display_type = device_get_config_int("display_type"); + dev->cga.composite = (display_type != CGA_RGB); + dev->cga.revision = device_get_config_int("composite_type"); + dev->cga.snow_enabled = device_get_config_int("snow_enabled"); + dev->cga.rgb_type = device_get_config_int("rgb_type"); + + dev->cga.vram = (uint8_t *)mem_alloc(0x4000); + + cga_comp_init(dev->cga.revision); + + timer_add(compaq_poll, &dev->cga.vidtime, TIMER_ALWAYS_ENABLED, dev); + + mem_map_add(&dev->cga.mapping, 0xb8000, 0x08000, + cga_read,NULL,NULL, cga_write,NULL,NULL, + NULL, MEM_MAPPING_EXTERNAL, dev); + + io_sethandler(0x03d0, 16, + cga_in,NULL,NULL, cga_out,NULL,NULL, dev); + + if (info->local) { + for (c = 0; c < 256; c++) { + dev->attr[c][0][0] = dev->attr[c][1][0] = dev->attr[c][1][1] = 16; + if (c & 8) + dev->attr[c][0][1] = 15 + 16; + else + dev->attr[c][0][1] = 7 + 16; + } + dev->attr[0x70][0][1] = 16; + dev->attr[0x70][0][0] = dev->attr[0x70][1][0] = dev->attr[0x70][1][1] = 16 + 15; + dev->attr[0xF0][0][1] = 16; + dev->attr[0xF0][0][0] = dev->attr[0xF0][1][0] = dev->attr[0xF0][1][1] = 16 + 15; + dev->attr[0x78][0][1] = 16 + 7; + dev->attr[0x78][0][0] = dev->attr[0x78][1][0] = dev->attr[0x78][1][1] = 16 + 15; + dev->attr[0xF8][0][1] = 16 + 7; + dev->attr[0xF8][0][0] = dev->attr[0xF8][1][0] = dev->attr[0xF8][1][1] = 16 + 15; + dev->attr[0x00][0][1] = dev->attr[0x00][1][1] = 16; + dev->attr[0x08][0][1] = dev->attr[0x08][1][1] = 16; + dev->attr[0x80][0][1] = dev->attr[0x80][1][1] = 16; + dev->attr[0x88][0][1] = dev->attr[0x88][1][1] = 16; + } + + dev->flags = info->local; + + overscan_x = overscan_y = 16; + + cga_palette = (dev->cga.rgb_type << 1); + cgapal_rebuild(); + + video_inform(VID_TYPE_CGA, info->vid_timing); + + return dev; +} + + +static void +compaq_cga_close(void *priv) +{ + compaq_cga_t *dev = (compaq_cga_t *)priv; + + free(dev->cga.vram); + free(dev); +} + + +static void +speed_changed(void *priv) +{ + compaq_cga_t *dev = (compaq_cga_t *)priv; + + if (dev->cga.crtc[9] == 13) /* Character height */ + recalc_timings(dev); + else + cga_recalctimings(&dev->cga); +} + + +extern const device_config_t cga_config[]; +static const video_timings_t cga_timings = { VID_ISA,8,16,32,8,16,32 }; + +const device_t cga_compaq_device = { + "Compaq CGA", + DEVICE_ISA, 0, + compaq_cga_init, compaq_cga_close, NULL, + NULL, + speed_changed, + NULL, + &cga_timings, + cga_config +}; + +const device_t cga_compaq2_device = { + "Compaq CGA 2", + DEVICE_ISA, 1, + compaq_cga_init, compaq_cga_close, NULL, + NULL, + speed_changed, + NULL, + &cga_timings, + cga_config +}; diff --git a/src/devices/video/vid_cl54xx.c b/src/devices/video/vid_cl54xx.c index 0004799..34946fc 100644 --- a/src/devices/video/vid_cl54xx.c +++ b/src/devices/video/vid_cl54xx.c @@ -9,7 +9,7 @@ * Emulation of select Cirrus Logic cards (CL-GD 5428, * CL-GD 5429, 5430, 5434 and 5436 are supported). * - * Version: @(#)vid_cl54xx.c 1.0.17 2018/05/06 + * Version: @(#)vid_cl54xx.c 1.0.19 2018/10/05 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -66,19 +66,23 @@ #define BIOS_GD5430_PCI_PATH L"video/cirruslogic/gd5430pci.bin" #define BIOS_GD5434_PATH L"video/cirruslogic/gd5434.bin" #define BIOS_GD5436_PATH L"video/cirruslogic/gd5436.vbi" +#define BIOS_GD5440_PATH L"video/cirruslogic/gd5440.bin" #define BIOS_GD5446_PATH L"video/cirruslogic/gd5446bv.vbi" #define BIOS_GD5446_STB_PATH L"video/cirruslogic/stb_nitro64v.bin" #define BIOS_GD5480_PATH L"video/cirruslogic/gd5480.rom" + #define CIRRUS_ID_CLGD5426 0x90 #define CIRRUS_ID_CLGD5428 0x98 #define CIRRUS_ID_CLGD5429 0x9c #define CIRRUS_ID_CLGD5430 0xa0 #define CIRRUS_ID_CLGD5434 0xa8 #define CIRRUS_ID_CLGD5436 0xac +#define CIRRUS_ID_CLGD5440 0xa0 /* yes, same ID as the 5430 */ #define CIRRUS_ID_CLGD5446 0xb8 #define CIRRUS_ID_CLGD5480 0xbc + /* sequencer 0x07 */ #define CIRRUS_SR7_BPP_VGA 0x00 #define CIRRUS_SR7_BPP_SVGA 0x01 @@ -104,7 +108,7 @@ #define CIRRUS_MMIO_USE_PCIADDR 0x40 /* 0xb8000 if cleared. */ #define CIRRUS_MEMSIZEEXT_DOUBLE 0x80 -/* control 0x0b */ +// control 0x0b #define CIRRUS_BANKING_DUAL 0x01 #define CIRRUS_BANKING_GRANULARITY_16K 0x20 /* set:16k, clear:4k */ @@ -121,14 +125,14 @@ #define CIRRUS_BLTMODE_PIXELWIDTH24 0x20 #define CIRRUS_BLTMODE_PIXELWIDTH32 0x30 -/* control 0x31 */ +// control 0x31 #define CIRRUS_BLT_BUSY 0x01 #define CIRRUS_BLT_START 0x02 #define CIRRUS_BLT_RESET 0x04 #define CIRRUS_BLT_FIFOUSED 0x10 #define CIRRUS_BLT_AUTOSTART 0x80 -/* control 0x33 */ +// control 0x33 #define CIRRUS_BLTMODEEXT_SOLIDFILL 0x04 #define CIRRUS_BLTMODEEXT_COLOREXPINV 0x02 #define CIRRUS_BLTMODEEXT_DWORDGRANULARITY 0x01 @@ -142,83 +146,87 @@ typedef struct gd54xx_t { - mem_mapping_t mmio_mapping; - mem_mapping_t linear_mapping; + mem_map_t mmio_mapping; + mem_map_t linear_mapping; - svga_t svga; + svga_t svga; - int has_bios; - rom_t bios_rom; + int has_bios, rev; + rom_t bios_rom; - uint32_t vram_size; - uint32_t vram_mask; + uint32_t vram_size; + uint32_t vram_mask; - uint8_t vclk_n[4]; - uint8_t vclk_d[4]; - uint32_t bank[2]; + uint8_t vclk_n[4]; + uint8_t vclk_d[4]; + uint32_t bank[2]; struct { - uint8_t state; - int ctrl; - } ramdac; + uint8_t state; + int ctrl; + } ramdac; struct { - uint32_t fg_col, bg_col; - uint16_t width, height; - uint16_t dst_pitch, src_pitch; - uint32_t dst_addr, src_addr; - uint8_t mask, mode, rop; - uint8_t modeext; - uint8_t status; - uint16_t trans_col, trans_mask; + uint32_t fg_col, bg_col; + uint16_t width, height; + uint16_t dst_pitch, src_pitch; + uint32_t dst_addr, src_addr; + uint8_t mask, mode, rop; + uint8_t modeext; + uint8_t status; + uint16_t trans_col, trans_mask; - uint32_t dst_addr_backup, src_addr_backup; - uint16_t width_backup, height_internal; + uint32_t dst_addr_backup, src_addr_backup; + uint16_t width_backup, height_internal; - int x_count, y_count; - int sys_tx; - uint8_t sys_cnt; - uint32_t sys_buf; - uint16_t pixel_cnt; - uint16_t scan_cnt; - } blt; + int x_count, y_count; + int sys_tx; + uint8_t sys_cnt; + uint32_t sys_buf; + uint16_t pixel_cnt; + uint16_t scan_cnt; + } blt; - int pci, vlb; + int pci, vlb; - uint8_t pci_regs[256]; - uint8_t int_line; + uint8_t pci_regs[256]; + uint8_t int_line; - int card; + int card; - uint32_t lfb_base; + uint32_t lfb_base; - int mmio_vram_overlap; + int mmio_vram_overlap; - uint32_t extpallook[256]; - PALETTE extpal; + uint32_t extpallook[256]; + PALETTE extpal; } gd54xx_t; -static void -gd543x_mmio_write(uint32_t addr, uint8_t val, void *p); -static void -gd543x_mmio_writew(uint32_t addr, uint16_t val, void *p); -static void -gd543x_mmio_writel(uint32_t addr, uint32_t val, void *p); -static uint8_t -gd543x_mmio_read(uint32_t addr, void *p); -static uint16_t -gd543x_mmio_readw(uint32_t addr, void *p); -static uint32_t -gd543x_mmio_readl(uint32_t addr, void *p); -static void -gd54xx_recalc_banking(gd54xx_t *gd54xx); +static void gd543x_mmio_write(uint32_t addr, uint8_t val, void *p); +static void gd543x_mmio_writew(uint32_t addr, uint16_t val, void *p); +static void gd543x_mmio_writel(uint32_t addr, uint32_t val, void *p); +static uint8_t gd543x_mmio_read(uint32_t addr, void *p); +static uint16_t gd543x_mmio_readw(uint32_t addr, void *p); +static uint32_t gd543x_mmio_readl(uint32_t addr, void *p); -static void -gd543x_recalc_mapping(gd54xx_t *gd54xx); +static void gd54xx_recalc_banking(gd54xx_t *gd54xx); + +static void gd543x_recalc_mapping(gd54xx_t *gd54xx); + +static void gd54xx_start_blit(uint32_t cpu_dat, int count, gd54xx_t *gd54xx, svga_t *svga); + + +/* Returns 1 if the card is a 5434, 5436/46, or 5480. */ +static int +gd54xx_is_5434(svga_t *svga) +{ + if (svga->crtc[0x27] >= CIRRUS_ID_CLGD5434) + return 1; + else + return 0; +} -static void -gd54xx_start_blit(uint32_t cpu_dat, int count, gd54xx_t *gd54xx, svga_t *svga); static void gd54xx_out(uint16_t addr, uint8_t val, void *p) @@ -227,7 +235,7 @@ gd54xx_out(uint16_t addr, uint8_t val, void *p) svga_t *svga = &gd54xx->svga; uint8_t old; int c; - uint8_t o; + uint8_t o, indx; uint32_t o32; if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) @@ -301,13 +309,15 @@ gd54xx_out(uint16_t addr, uint8_t val, void *p) svga->hwcursor.y = (val << 3) | (svga->seqaddr >> 5); break; case 0x12: - if (val & 0x80) + svga->ext_overscan = !!(val & 0x80); + if (svga->ext_overscan) svga->overscan_color = gd54xx->extpallook[2]; else svga->overscan_color = svga->pallook[svga->attrregs[0x11]]; svga_recalctimings(svga); svga->hwcursor.ena = val & CIRRUS_CURSOR_SHOW; svga->hwcursor.xsize = svga->hwcursor.ysize = (val & CIRRUS_CURSOR_LARGE) ? 64 : 32; + svga->hwcursor.yoff = (svga->hwcursor.ysize == 32) ? 32 : 0; if (val & CIRRUS_CURSOR_LARGE) svga->hwcursor.addr = (((gd54xx->vram_size<<20)-0x4000) + ((svga->seqregs[0x13] & 0x3c) * 256)); else @@ -322,7 +332,6 @@ gd54xx_out(uint16_t addr, uint8_t val, void *p) case 0x07: svga->set_reset_disabled = svga->seqregs[7] & 1; case 0x17: - /* svga->seqregs[0x17] = (svga->seqregs[0x17] & 0x38) | (val & 0xc7); */ gd543x_recalc_mapping(gd54xx); break; } @@ -351,25 +360,26 @@ gd54xx_out(uint16_t addr, uint8_t val, void *p) svga->dac_pos++; break; case 2: + indx = svga->dac_addr & 0xff; if (svga->seqregs[0x12] & 2) { - gd54xx->extpal[svga->dac_write].r = svga->dac_r; - gd54xx->extpal[svga->dac_write].g = svga->dac_g; - gd54xx->extpal[svga->dac_write].b = val; - gd54xx->extpallook[svga->dac_write & 15] = makecol32(video_6to8[gd54xx->extpal[svga->dac_write].r & 0x3f], video_6to8[gd54xx->extpal[svga->dac_write].g & 0x3f], video_6to8[gd54xx->extpal[svga->dac_write].b & 0x3f]); - if ((svga->seqregs[0x12] & 0x80) && ((svga->dac_write & 15) == 2)) { + indx &= 0x0f; + gd54xx->extpal[indx].r = svga->dac_r; + gd54xx->extpal[indx].g = svga->dac_g; + gd54xx->extpal[indx].b = val; + gd54xx->extpallook[indx] = makecol32(video_6to8[gd54xx->extpal[indx].r & 0x3f], video_6to8[gd54xx->extpal[indx].g & 0x3f], video_6to8[gd54xx->extpal[indx].b & 0x3f]); + if (svga->ext_overscan && (indx == 2)) { o32 = svga->overscan_color; svga->overscan_color = gd54xx->extpallook[2]; if (o32 != svga->overscan_color) svga_recalctimings(svga); } - svga->dac_write = (svga->dac_write + 1) & 15; } else { - svga->vgapal[svga->dac_write].r = svga->dac_r; - svga->vgapal[svga->dac_write].g = svga->dac_g; - svga->vgapal[svga->dac_write].b = val; - svga->pallook[svga->dac_write] = makecol32(video_6to8[svga->vgapal[svga->dac_write].r & 0x3f], video_6to8[svga->vgapal[svga->dac_write].g & 0x3f], video_6to8[svga->vgapal[svga->dac_write].b & 0x3f]); - svga->dac_write = (svga->dac_write + 1) & 255; + svga->vgapal[indx].r = svga->dac_r; + svga->vgapal[indx].g = svga->dac_g; + svga->vgapal[indx].b = val; + svga->pallook[indx] = makecol32(video_6to8[svga->vgapal[indx].r & 0x3f], video_6to8[svga->vgapal[indx].g & 0x3f], video_6to8[svga->vgapal[indx].b & 0x3f]); } + svga->dac_addr = (svga->dac_addr + 1) & 255; svga->dac_pos = 0; break; } @@ -542,8 +552,7 @@ gd54xx_in(uint16_t addr, void *p) { gd54xx_t *gd54xx = (gd54xx_t *)p; svga_t *svga = &gd54xx->svga; - - uint8_t temp; + uint8_t indx, temp; if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3d0) && !(svga->miscout & 1)) addr ^= 0x60; @@ -563,14 +572,14 @@ gd54xx_in(uint16_t addr, void *p) return temp; } return svga->seqaddr; - + case 0x3c5: if (svga->seqaddr > 5) { switch (svga->seqaddr) { case 6: - return ((svga->seqregs[6] & 0x17) == 0x12) ? 0x12 : 0x0f; + return ((svga->seqregs[6] & 0x17) == 0x12) ? 0x12 : 0x0f; case 0x0b: case 0x0c: case 0x0d: case 0x0e: - return gd54xx->vclk_n[svga->seqaddr-0x0b]; + return gd54xx->vclk_n[svga->seqaddr-0x0b]; case 0x17: temp = svga->gdcreg[0x17] & ~(7 << 3); if (svga->crtc[0x27] <= CIRRUS_ID_CLGD5429) { @@ -593,6 +602,33 @@ gd54xx_in(uint16_t addr, void *p) return svga->seqregs[svga->seqaddr & 0x3f]; } break; + case 0x3c9: + svga->dac_status = 3; + indx = (svga->dac_addr - 1) & 0xff; + if (svga->seqregs[0x12] & 2) + indx &= 0x0f; + switch (svga->dac_pos) { + case 0: + svga->dac_pos++; + if (svga->seqregs[0x12] & 2) + return gd54xx->extpal[indx].r & 0x3f; + else + return svga->vgapal[indx].r & 0x3f; + case 1: + svga->dac_pos++; + if (svga->seqregs[0x12] & 2) + return gd54xx->extpal[indx].g & 0x3f; + else + return svga->vgapal[indx].g & 0x3f; + case 2: + svga->dac_pos = 0; + svga->dac_addr = (svga->dac_addr + 1) & 255; + if (svga->seqregs[0x12] & 2) + return gd54xx->extpal[indx].b & 0x3f; + else + return svga->vgapal[indx].b & 0x3f; + } + return 0xFF; case 0x3C6: if (gd54xx->ramdac.state == 4) { gd54xx->ramdac.state = 0; @@ -600,32 +636,6 @@ gd54xx_in(uint16_t addr, void *p) } gd54xx->ramdac.state++; break; - case 0x3c9: - svga->dac_status = 3; - switch (svga->dac_pos) { - case 0: - svga->dac_pos++; - if (svga->seqregs[0x12] & 2) - return gd54xx->extpal[svga->dac_read].r & 0x3f; - else - return svga->vgapal[svga->dac_read].r & 0x3f; - case 1: - svga->dac_pos++; - if (svga->seqregs[0x12] & 2) - return gd54xx->extpal[svga->dac_read].g & 0x3f; - else - return svga->vgapal[svga->dac_read].g & 0x3f; - case 2: - svga->dac_pos=0; - if (svga->seqregs[0x12] & 2) { - svga->dac_read = (svga->dac_read + 1) & 15; - return gd54xx->extpal[(svga->dac_read - 1) & 15].b & 0x3f; - } else { - svga->dac_read = (svga->dac_read + 1) & 255; - return svga->vgapal[(svga->dac_read - 1) & 255].b & 0x3f; - } - } - return 0xFF; case 0x3cf: if (svga->gdcaddr > 8) { return svga->gdcreg[svga->gdcaddr & 0x3f]; @@ -638,12 +648,12 @@ gd54xx_in(uint16_t addr, void *p) case 0x24: /*Attribute controller toggle readback (R)*/ return svga->attrff << 7; case 0x26: /*Attribute controller index readback (R)*/ - return svga->attraddr & 0x3f; + return svga->attraddr & 0x3f; case 0x27: /*ID*/ return svga->crtc[0x27]; /*GD542x/GD543x*/ case 0x28: /*Class ID*/ - if (svga->crtc[0x27] == CIRRUS_ID_CLGD5430) - return 0xff; /*Standard CL-GD5430*/ + if ((svga->crtc[0x27] == CIRRUS_ID_CLGD5430) || (svga->crtc[0x27] == CIRRUS_ID_CLGD5440)) + return 0xff; /*Standard CL-GD5430/40*/ break; } return svga->crtc[svga->crtcreg]; @@ -678,39 +688,39 @@ gd543x_recalc_mapping(gd54xx_t *gd54xx) svga_t *svga = &gd54xx->svga; if (!(gd54xx->pci_regs[PCI_REG_COMMAND] & PCI_COMMAND_MEM)) { - mem_mapping_disable(&svga->mapping); - mem_mapping_disable(&gd54xx->linear_mapping); - mem_mapping_disable(&gd54xx->mmio_mapping); + mem_map_disable(&svga->mapping); + mem_map_disable(&gd54xx->linear_mapping); + mem_map_disable(&gd54xx->mmio_mapping); return; } gd54xx->mmio_vram_overlap = 0; if (!(svga->seqregs[7] & 0xf0)) { - mem_mapping_disable(&gd54xx->linear_mapping); + mem_map_disable(&gd54xx->linear_mapping); switch (svga->gdcreg[6] & 0x0c) { case 0x0: /*128k at A0000*/ - mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x20000); + mem_map_set_addr(&svga->mapping, 0xa0000, 0x20000); svga->banked_mask = 0xffff; break; case 0x4: /*64k at A0000*/ - mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000); + mem_map_set_addr(&svga->mapping, 0xa0000, 0x10000); svga->banked_mask = 0xffff; break; case 0x8: /*32k at B0000*/ - mem_mapping_set_addr(&svga->mapping, 0xb0000, 0x08000); + mem_map_set_addr(&svga->mapping, 0xb0000, 0x08000); svga->banked_mask = 0x7fff; break; case 0xC: /*32k at B8000*/ - mem_mapping_set_addr(&svga->mapping, 0xb8000, 0x08000); + mem_map_set_addr(&svga->mapping, 0xb8000, 0x08000); svga->banked_mask = 0x7fff; gd54xx->mmio_vram_overlap = 1; break; } if (svga->seqregs[0x17] & CIRRUS_MMIO_ENABLE) - mem_mapping_set_addr(&gd54xx->mmio_mapping, 0xb8000, 0x00100); + mem_map_set_addr(&gd54xx->mmio_mapping, 0xb8000, 0x00100); else - mem_mapping_disable(&gd54xx->mmio_mapping); + mem_map_disable(&gd54xx->mmio_mapping); } else { uint32_t base, size; @@ -736,21 +746,20 @@ gd543x_recalc_mapping(gd54xx_t *gd54xx) size = 4 * 1024 * 1024; } - mem_mapping_disable(&svga->mapping); - mem_mapping_set_addr(&gd54xx->linear_mapping, base, size); - svga->linear_base = base; + mem_map_disable(&svga->mapping); + mem_map_set_addr(&gd54xx->linear_mapping, base, size); if (svga->seqregs[0x17] & CIRRUS_MMIO_ENABLE) { if (svga->seqregs[0x17] & CIRRUS_MMIO_USE_PCIADDR) { if (size >= (4 * 1024 * 1024)) - mem_mapping_disable(&gd54xx->mmio_mapping); /* MMIO is handled in the linear read/write functions */ + mem_map_disable(&gd54xx->mmio_mapping); /* MMIO is handled in the linear read/write functions */ else { - mem_mapping_set_addr(&gd54xx->linear_mapping, base, size - 256); - mem_mapping_set_addr(&gd54xx->mmio_mapping, base + size - 256, 0x00100); + mem_map_set_addr(&gd54xx->linear_mapping, base, size - 256); + mem_map_set_addr(&gd54xx->mmio_mapping, base + size - 256, 0x00100); } } else - mem_mapping_set_addr(&gd54xx->mmio_mapping, 0xb8000, 0x00100); + mem_map_set_addr(&gd54xx->mmio_mapping, 0xb8000, 0x00100); } else - mem_mapping_disable(&gd54xx->mmio_mapping); + mem_map_disable(&gd54xx->mmio_mapping); } } @@ -765,85 +774,72 @@ gd54xx_recalctimings(svga_t *svga) svga->interlace = (svga->crtc[0x1a] & 0x01); + if (svga->seqregs[7] & CIRRUS_SR7_BPP_SVGA) + svga->render = svga_render_8bpp_highres; + else if (svga->gdcreg[5] & 0x40) + svga->render = svga_render_8bpp_lowres; + svga->ma_latch |= ((svga->crtc[0x1b] & 0x01) << 16) | ((svga->crtc[0x1b] & 0xc) << 15); - if (svga->seqregs[7] & CIRRUS_SR7_BPP_SVGA) - { - svga->bpp = 8; - svga->render = svga_render_8bpp_highres; - } - else if (svga->gdcreg[5] & 0x40) - { - svga->bpp = 8; - svga->render = svga_render_8bpp_lowres; - } + svga->bpp = 8; - if (gd54xx->ramdac.ctrl & 0x80) - { - if (gd54xx->ramdac.ctrl & 0x40) - { - switch (gd54xx->ramdac.ctrl & 0xf) - { - case 0: - svga->bpp = 15; - svga->render = svga_render_15bpp_highres; - break; - - case 1: - svga->bpp = 16; - svga->render = svga_render_16bpp_highres; - break; - - case 5: - if ((svga->crtc[0x27] >= CIRRUS_ID_CLGD5434) && (svga->seqregs[7] & CIRRUS_SR7_BPP_32)) - { + if (gd54xx->ramdac.ctrl & 0x80) { + if (gd54xx->ramdac.ctrl & 0x40) { + switch (gd54xx->ramdac.ctrl & 0xf) { + case 0: + svga->bpp = 15; + svga->render = svga_render_15bpp_highres; + break; + + case 1: + svga->bpp = 16; + svga->render = svga_render_16bpp_highres; + break; + + case 5: + if (gd54xx_is_5434(svga) && (svga->seqregs[7] & CIRRUS_SR7_BPP_32)) { + svga->bpp = 32; + svga->render = svga_render_32bpp_highres; + if (svga->crtc[0x27] < CIRRUS_ID_CLGD5436) + svga->rowoffset *= 2; + } else { + svga->bpp = 24; + svga->render = svga_render_24bpp_highres; + } + break; + + case 0xf: + switch (svga->seqregs[7] & CIRRUS_SR7_BPP_MASK) { + case CIRRUS_SR7_BPP_32: svga->bpp = 32; svga->render = svga_render_32bpp_highres; - if (svga->crtc[0x27] < CIRRUS_ID_CLGD5436) - svga->rowoffset *= 2; - } - else - { + svga->rowoffset *= 2; + break; + + case CIRRUS_SR7_BPP_24: svga->bpp = 24; svga->render = svga_render_24bpp_highres; - } - break; - - case 0xf: - switch (svga->seqregs[7] & CIRRUS_SR7_BPP_MASK) - { - case CIRRUS_SR7_BPP_32: - svga->bpp = 32; - svga->render = svga_render_32bpp_highres; - svga->rowoffset *= 2; - break; - - case CIRRUS_SR7_BPP_24: - svga->bpp = 24; - svga->render = svga_render_24bpp_highres; - break; - - case CIRRUS_SR7_BPP_16: - case CIRRUS_SR7_BPP_16_DOUBLEVCLK: - svga->bpp = 16; - svga->render = svga_render_16bpp_highres; - break; - - case CIRRUS_SR7_BPP_8: - svga->bpp = 8; - svga->render = svga_render_8bpp_highres; - break; - } - break; - } - } - else - { - svga->bpp = 15; - svga->render = svga_render_15bpp_highres; + break; + + case CIRRUS_SR7_BPP_16: + case CIRRUS_SR7_BPP_16_DOUBLEVCLK: + svga->bpp = 16; + svga->render = svga_render_16bpp_highres; + break; + + case CIRRUS_SR7_BPP_8: + svga->bpp = 8; + svga->render = svga_render_8bpp_highres; + break; + } + break; } + } else { + svga->bpp = 15; + svga->render = svga_render_15bpp_highres; } - + } + clocksel = (svga->miscout >> 2) & 3; if (!gd54xx->vclk_n[clocksel] || !gd54xx->vclk_d[clocksel]) @@ -852,37 +848,37 @@ gd54xx_recalctimings(svga_t *svga) int n = gd54xx->vclk_n[clocksel] & 0x7f; int d = (gd54xx->vclk_d[clocksel] & 0x3e) >> 1; int m = gd54xx->vclk_d[clocksel] & 0x01 ? 2 : 1; - float freq = (14318184.0f * (float)n) / ((float)d * m); - switch (svga->seqregs[7] & ((svga->crtc[0x27] >= CIRRUS_ID_CLGD5434) ? 0xe : 6)) - { - case 2: - freq /= 2.0; - break; - case 4: - if (svga->crtc[0x27] <= CIRRUS_ID_CLGD5434) + float freq = ((float)14318184.0 * ((float)n / ((float)d * m))); + switch (svga->seqregs[7] & (gd54xx_is_5434(svga) ? 0xe : 6)) { + case 2: + freq /= 2.0; + break; + case 4: + if (!gd54xx_is_5434(svga)) freq /= 3.0; - break; + break; } svga->clock = cpuclock / freq; } - + svga->vram_display_mask = (svga->crtc[0x1b] & 2) ? gd54xx->vram_mask : 0x3ffff; } - static -void gd54xx_hwcursor_draw(svga_t *svga, int disp_line) +void gd54xx_hwcursor_draw(svga_t *svga, int displine) { - gd54xx_t *gd54xx = (gd54xx_t *)svga->p; + gd54xx_t *gd54xx = (gd54xx_t *)svga->p; int x, xx, comb, b0, b1; uint8_t dat[2]; int offset = svga->hwcursor_latch.x - svga->hwcursor_latch.xoff; - int y_add = (enable_overscan && !suppress_overscan) ? 16 : 0; - int x_add = (enable_overscan && !suppress_overscan) ? 8 : 0; + int y_add, x_add; int pitch = (svga->hwcursor.xsize == 64) ? 16 : 4; uint32_t bgcol = gd54xx->extpallook[0x00]; uint32_t fgcol = gd54xx->extpallook[0x0f]; + y_add = (enable_overscan && !suppress_overscan) ? (overscan_y >> 1) : 0; + x_add = (enable_overscan && !suppress_overscan) ? 8 : 0; + if (svga->interlace && svga->hwcursor_oddeven) svga->hwcursor_latch.addr += pitch; @@ -903,33 +899,32 @@ void gd54xx_hwcursor_draw(svga_t *svga, int disp_line) break; case 1: /* The pixel is shown in the cursor background color */ - ((uint32_t *)buffer32->line[disp_line + y_add])[offset + 32 + x_add] = bgcol; + ((uint32_t *)buffer32->line[displine + y_add])[offset + 32 + x_add] = bgcol; break; case 2: /* The pixel is shown as the inverse of the original screen pixel (XOR cursor) */ - ((uint32_t *)buffer32->line[disp_line + y_add])[offset + 32 + x_add] ^= 0xffffff; + ((uint32_t *)buffer32->line[displine + y_add])[offset + 32 + x_add] ^= 0xffffff; break; case 3: /* The pixel is shown in the cursor foreground color */ - ((uint32_t *)buffer32->line[disp_line + y_add])[offset + 32 + x_add] = fgcol; + ((uint32_t *)buffer32->line[displine + y_add])[offset + 32 + x_add] = fgcol; break; } } - + offset++; } svga->hwcursor_latch.addr++; } - + if (svga->hwcursor.xsize == 64) svga->hwcursor_latch.addr += 8; - + if (svga->interlace && !svga->hwcursor_oddeven) svga->hwcursor_latch.addr += pitch; } - static void gd54xx_memsrc_rop(gd54xx_t *gd54xx, svga_t *svga, uint8_t src, uint8_t dst) { @@ -1016,9 +1011,6 @@ gd54xx_blt_write_l(uint32_t addr, uint32_t val, void *p) } -static void gd54xx_write_linear(uint32_t addr, uint8_t val, gd54xx_t *gd54xx); - - static void gd54xx_write(uint32_t addr, uint8_t val, void *p) { @@ -1040,7 +1032,8 @@ gd54xx_write(uint32_t addr, uint8_t val, void *p) addr &= svga->banked_mask; addr = (addr & 0x7fff) + gd54xx->bank[(addr >> 15) & 1]; - gd54xx_write_linear(addr, val, gd54xx); + + svga_write_linear(addr, val, svga); } @@ -1059,12 +1052,12 @@ gd54xx_writew(uint32_t addr, uint16_t val, void *p) addr &= svga->banked_mask; addr = (addr & 0x7fff) + gd54xx->bank[(addr >> 15) & 1]; - - if (svga->writemode < 4) - svga_writew_linear(addr, val, svga); + + if (svga->writemode < 4) + svga_writew_linear(addr, val, svga); else { - gd54xx_write_linear(addr, val & 0xff, gd54xx); - gd54xx_write_linear(addr+1, val >> 8, gd54xx); + svga_write_linear(addr, val & 0xff, svga); + svga_write_linear(addr + 1, val >> 8, svga); } } @@ -1077,7 +1070,7 @@ gd54xx_writel(uint32_t addr, uint32_t val, void *p) if (gd54xx->blt.sys_tx) { - gd54xx_write(addr, val, gd54xx); + gd54xx_write(addr, val & 0xff, gd54xx); gd54xx_write(addr+1, val >> 8, gd54xx); gd54xx_write(addr+2, val >> 16, gd54xx); gd54xx_write(addr+3, val >> 24, gd54xx); @@ -1090,52 +1083,24 @@ gd54xx_writel(uint32_t addr, uint32_t val, void *p) if (svga->writemode < 4) svga_writel_linear(addr, val, svga); else { - gd54xx_write_linear(addr, val, gd54xx); - gd54xx_write_linear(addr+1, val >> 8, gd54xx); - gd54xx_write_linear(addr+2, val >> 16, gd54xx); - gd54xx_write_linear(addr+3, val >> 24, gd54xx); + svga_write_linear(addr, val & 0xff, svga); + svga_write_linear(addr+1, val >> 8, svga); + svga_write_linear(addr+2, val >> 16, svga); + svga_write_linear(addr+3, val >> 24, svga); } } +/* This adds write modes 4 and 5 to SVGA. */ static void -gd54xx_write_linear(uint32_t addr, uint8_t val, gd54xx_t *gd54xx) +gd54xx_write_modes45(svga_t *svga, uint8_t val, uint32_t addr) { - svga_t *svga = &gd54xx->svga; - uint8_t vala, valb, valc, vald, wm = svga->writemask; - int writemask2 = svga->writemask; - int i; - uint8_t j; - - cycles -= video_timing_write_b; - cycles_lost += video_timing_write_b; - - egawrites++; - - if (!(svga->gdcreg[6] & 1)) - svga->fullchange = 2; - if ((svga->chain4 || svga->fb_only) && (svga->writemode < 4)) { - writemask2 = 1 << (addr & 3); - addr &= ~3; - } else if (svga->chain2_write) { - writemask2 &= ~0xa; - if (addr & 1) - writemask2 <<= 1; - addr &= ~1; - addr <<= 2; - } else - addr <<= 2; - addr &= svga->decode_mask; - if (addr >= svga->vram_max) - return; - addr &= svga->vram_mask; - svga->changedvram[addr >> 12]=changeframecount; + uint32_t i, j; switch (svga->writemode) { case 4: if (svga->gdcreg[0xb] & 0x10) { addr <<= 2; - svga->changedvram[addr >> 12] = changeframecount; for (i = 0; i < 8; i++) { if (val & svga->seqregs[2] & (0x80 >> i)) { @@ -1144,173 +1109,41 @@ gd54xx_write_linear(uint32_t addr, uint8_t val, gd54xx_t *gd54xx) } } } else { - addr <<= 1; - svga->changedvram[addr >> 12] = changeframecount; + addr <<= 1; for (i = 0; i < 8; i++) { - if (val & svga->seqregs[2] & (0x80 >> i)) - svga->vram[addr + i] = svga->gdcreg[1]; + if (val & svga->seqregs[2] & (0x80 >> i)) + svga->vram[addr + i] = svga->gdcreg[1]; } - } - break; - - case 5: - if (svga->gdcreg[0xb] & 0x10) - { - addr <<= 2; - svga->changedvram[addr >> 12] = changeframecount; + } + break; + + case 5: + if (svga->gdcreg[0xb] & 0x10) { + addr <<= 2; for (i = 0; i < 8; i++) { j = (0x80 >> i); if (svga->seqregs[2] & j) { - svga->vram[addr + (i << 1)] = (val & j) ? svga->gdcreg[1] : svga->gdcreg[0]; - svga->vram[addr + (i << 1) + 1] = (val & j) ? svga->gdcreg[0x11] : svga->gdcreg[0x10]; + svga->vram[addr + (i << 1)] = (val & j) ? + svga->gdcreg[1] : svga->gdcreg[0]; + svga->vram[addr + (i << 1) + 1] = (val & j) ? + svga->gdcreg[0x11] : svga->gdcreg[0x10]; } } - } - else - { - addr <<= 1; - svga->changedvram[addr >> 12] = changeframecount; + } else { + addr <<= 1; for (i = 0; i < 8; i++) { j = (0x80 >> i); if (svga->seqregs[2] & j) svga->vram[addr + i] = (val & j) ? svga->gdcreg[1] : svga->gdcreg[0]; } - } - break; - - case 1: - if (writemask2 & 1) svga->vram[addr] = svga->la; - if (writemask2 & 2) svga->vram[addr | 0x1] = svga->lb; - if (writemask2 & 4) svga->vram[addr | 0x2] = svga->lc; - if (writemask2 & 8) svga->vram[addr | 0x3] = svga->ld; - break; - case 0: - if (svga->gdcreg[3] & 7) - val = svga_rotate[svga->gdcreg[3] & 7][val]; - if (svga->gdcreg[8] == 0xff && !(svga->gdcreg[3] & 0x18) && (!svga->gdcreg[1] || svga->set_reset_disabled)) { - if (writemask2 & 1) svga->vram[addr] = val; - if (writemask2 & 2) svga->vram[addr | 0x1] = val; - if (writemask2 & 4) svga->vram[addr | 0x2] = val; - if (writemask2 & 8) svga->vram[addr | 0x3] = val; - } else { - if (svga->gdcreg[1] & 1) vala = (svga->gdcreg[0] & 1) ? 0xff : 0; - else vala = val; - if (svga->gdcreg[1] & 2) valb = (svga->gdcreg[0] & 2) ? 0xff : 0; - else valb = val; - if (svga->gdcreg[1] & 4) valc = (svga->gdcreg[0] & 4) ? 0xff : 0; - else valc = val; - if (svga->gdcreg[1] & 8) vald = (svga->gdcreg[0] & 8) ? 0xff : 0; - else vald = val; - - switch (svga->gdcreg[3] & 0x18) { - case 0: /*Set*/ - if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) | (svga->la & ~svga->gdcreg[8]); - if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) | (svga->lb & ~svga->gdcreg[8]); - if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) | (svga->lc & ~svga->gdcreg[8]); - if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) | (svga->ld & ~svga->gdcreg[8]); - break; - case 8: /*AND*/ - if (writemask2 & 1) svga->vram[addr] = (vala | ~svga->gdcreg[8]) & svga->la; - if (writemask2 & 2) svga->vram[addr | 0x1] = (valb | ~svga->gdcreg[8]) & svga->lb; - if (writemask2 & 4) svga->vram[addr | 0x2] = (valc | ~svga->gdcreg[8]) & svga->lc; - if (writemask2 & 8) svga->vram[addr | 0x3] = (vald | ~svga->gdcreg[8]) & svga->ld; - break; - case 0x10: /*OR*/ - if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) | svga->la; - if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) | svga->lb; - if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) | svga->lc; - if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) | svga->ld; - break; - case 0x18: /*XOR*/ - if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) ^ svga->la; - if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) ^ svga->lb; - if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) ^ svga->lc; - if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) ^ svga->ld; - break; - } } break; - case 2: - if (!(svga->gdcreg[3] & 0x18) && !svga->gdcreg[1]) { - if (writemask2 & 1) svga->vram[addr] = (((val & 1) ? 0xff : 0) & svga->gdcreg[8]) | (svga->la & ~svga->gdcreg[8]); - if (writemask2 & 2) svga->vram[addr | 0x1] = (((val & 2) ? 0xff : 0) & svga->gdcreg[8]) | (svga->lb & ~svga->gdcreg[8]); - if (writemask2 & 4) svga->vram[addr | 0x2] = (((val & 4) ? 0xff : 0) & svga->gdcreg[8]) | (svga->lc & ~svga->gdcreg[8]); - if (writemask2 & 8) svga->vram[addr | 0x3] = (((val & 8) ? 0xff : 0) & svga->gdcreg[8]) | (svga->ld & ~svga->gdcreg[8]); - } else { - vala = ((val & 1) ? 0xff : 0); - valb = ((val & 2) ? 0xff : 0); - valc = ((val & 4) ? 0xff : 0); - vald = ((val & 8) ? 0xff : 0); - switch (svga->gdcreg[3] & 0x18) { - case 0: /*Set*/ - if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) | (svga->la & ~svga->gdcreg[8]); - if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) | (svga->lb & ~svga->gdcreg[8]); - if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) | (svga->lc & ~svga->gdcreg[8]); - if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) | (svga->ld & ~svga->gdcreg[8]); - break; - case 8: /*AND*/ - if (writemask2 & 1) svga->vram[addr] = (vala | ~svga->gdcreg[8]) & svga->la; - if (writemask2 & 2) svga->vram[addr | 0x1] = (valb | ~svga->gdcreg[8]) & svga->lb; - if (writemask2 & 4) svga->vram[addr | 0x2] = (valc | ~svga->gdcreg[8]) & svga->lc; - if (writemask2 & 8) svga->vram[addr | 0x3] = (vald | ~svga->gdcreg[8]) & svga->ld; - break; - case 0x10: /*OR*/ - if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) | svga->la; - if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) | svga->lb; - if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) | svga->lc; - if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) | svga->ld; - break; - case 0x18: /*XOR*/ - if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) ^ svga->la; - if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) ^ svga->lb; - if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) ^ svga->lc; - if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) ^ svga->ld; - break; - } - } - break; - case 3: - if (svga->gdcreg[3] & 7) - val = svga_rotate[svga->gdcreg[3] & 7][val]; - wm = svga->gdcreg[8]; - svga->gdcreg[8] &= val; - - vala = (svga->gdcreg[0] & 1) ? 0xff : 0; - valb = (svga->gdcreg[0] & 2) ? 0xff : 0; - valc = (svga->gdcreg[0] & 4) ? 0xff : 0; - vald = (svga->gdcreg[0] & 8) ? 0xff : 0; - switch (svga->gdcreg[3] & 0x18) { - case 0: /*Set*/ - if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) | (svga->la & ~svga->gdcreg[8]); - if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) | (svga->lb & ~svga->gdcreg[8]); - if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) | (svga->lc & ~svga->gdcreg[8]); - if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) | (svga->ld & ~svga->gdcreg[8]); - break; - case 8: /*AND*/ - if (writemask2 & 1) svga->vram[addr] = (vala | ~svga->gdcreg[8]) & svga->la; - if (writemask2 & 2) svga->vram[addr | 0x1] = (valb | ~svga->gdcreg[8]) & svga->lb; - if (writemask2 & 4) svga->vram[addr | 0x2] = (valc | ~svga->gdcreg[8]) & svga->lc; - if (writemask2 & 8) svga->vram[addr | 0x3] = (vald | ~svga->gdcreg[8]) & svga->ld; - break; - case 0x10: /*OR*/ - if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) | svga->la; - if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) | svga->lb; - if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) | svga->lc; - if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) | svga->ld; - break; - case 0x18: /*XOR*/ - if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) ^ svga->la; - if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) ^ svga->lb; - if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) ^ svga->lc; - if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) ^ svga->ld; - break; - } - svga->gdcreg[8] = wm; - break; } + + svga->changedvram[addr >> 12] = changeframecount; } @@ -1400,10 +1233,8 @@ gd54xx_readw_linear(uint32_t addr, void *p) temp = svga_readb_linear(addr + 1, p); temp |= (svga_readb_linear(addr, p) << 8); - if (svga->fast) { + if (svga->fast) cycles -= video_timing_read_w; - cycles_lost += video_timing_read_w; - } return temp; case 3: @@ -1461,10 +1292,8 @@ gd54xx_readl_linear(uint32_t addr, void *p) temp |= (svga_readb_linear(addr + 3, p) << 16); temp |= (svga_readb_linear(addr + 2, p) << 24); - if (svga->fast) { + if (svga->fast) cycles -= video_timing_read_l; - cycles_lost += video_timing_read_l; - } return temp; case 2: @@ -1473,10 +1302,8 @@ gd54xx_readl_linear(uint32_t addr, void *p) temp |= (svga_readb_linear(addr + 1, p) << 16); temp |= (svga_readb_linear(addr, p) << 24); - if (svga->fast) { + if (svga->fast) cycles -= video_timing_read_l; - cycles_lost += video_timing_read_l; - } return temp; case 3: @@ -1528,10 +1355,7 @@ gd54xx_writeb_linear(uint32_t addr, uint8_t val, void *p) return; } - if (svga->writemode < 4) - svga_write_linear(addr, val, svga); - else - gd54xx_write_linear(addr, val & 0xff, gd54xx); + svga_write_linear(addr, val, svga); } @@ -1583,10 +1407,8 @@ gd54xx_writew_linear(uint32_t addr, uint16_t val, void *p) svga_writeb_linear(addr + 1, val & 0xff, svga); svga_writeb_linear(addr, val >> 8, svga); - if (svga->fast) { + if (svga->fast) cycles -= video_timing_write_w; - cycles_lost += video_timing_write_w; - } case 3: return; } @@ -1594,14 +1416,14 @@ gd54xx_writew_linear(uint32_t addr, uint16_t val, void *p) switch(ap) { case 0: default: - gd54xx_write_linear(addr, val & 0xff, gd54xx); - gd54xx_write_linear(addr + 1, val >> 8, gd54xx); + svga_write_linear(addr, val & 0xff, svga); + svga_write_linear(addr + 1, val >> 8, svga); return; case 2: addr ^= 0x00000002; case 1: - gd54xx_write_linear(addr + 1, val & 0xff, gd54xx); - gd54xx_write_linear(addr, val >> 8, gd54xx); + svga_write_linear(addr + 1, val & 0xff, svga); + svga_write_linear(addr, val >> 8, svga); case 3: return; } @@ -1676,30 +1498,28 @@ gd54xx_writel_linear(uint32_t addr, uint32_t val, void *p) return; } - if (svga->fast) { + if (svga->fast) cycles -= video_timing_write_l; - cycles_lost += video_timing_write_l; - } } else { switch(ap) { case 0: default: - gd54xx_write_linear(addr, val & 0xff, gd54xx); - gd54xx_write_linear(addr+1, val >> 8, gd54xx); - gd54xx_write_linear(addr+2, val >> 16, gd54xx); - gd54xx_write_linear(addr+3, val >> 24, gd54xx); + svga_write_linear(addr, val & 0xff, svga); + svga_write_linear(addr+1, val >> 8, svga); + svga_write_linear(addr+2, val >> 16, svga); + svga_write_linear(addr+3, val >> 24, svga); return; case 1: - gd54xx_write_linear(addr + 1, val & 0xff, gd54xx); - gd54xx_write_linear(addr, val >> 8, gd54xx); - gd54xx_write_linear(addr + 3, val >> 16, gd54xx); - gd54xx_write_linear(addr + 2, val >> 24, gd54xx); + svga_write_linear(addr + 1, val & 0xff, svga); + svga_write_linear(addr, val >> 8, svga); + svga_write_linear(addr + 3, val >> 16, svga); + svga_write_linear(addr + 2, val >> 24, svga); return; case 2: - gd54xx_write_linear(addr + 3, val & 0xff, gd54xx); - gd54xx_write_linear(addr + 2, val >> 8, gd54xx); - gd54xx_write_linear(addr + 1, val >> 16, gd54xx); - gd54xx_write_linear(addr, val >> 24, gd54xx); + svga_write_linear(addr + 3, val & 0xff, svga); + svga_write_linear(addr + 2, val >> 8, svga); + svga_write_linear(addr + 1, val >> 16, svga); + svga_write_linear(addr, val >> 24, svga); case 3: return; } @@ -1761,44 +1581,44 @@ gd543x_mmio_write(uint32_t addr, uint8_t val, void *p) if (gd543x_do_mmio(svga, addr)) { switch (addr & 0xff) { case 0x00: - if (svga->crtc[0x27] >= CIRRUS_ID_CLGD5434) + if (gd54xx_is_5434(svga)) gd54xx->blt.bg_col = (gd54xx->blt.bg_col & 0xffffff00) | val; else gd54xx->blt.bg_col = (gd54xx->blt.bg_col & 0xff00) | val; break; case 0x01: - if (svga->crtc[0x27] >= CIRRUS_ID_CLGD5434) + if (gd54xx_is_5434(svga)) gd54xx->blt.bg_col = (gd54xx->blt.bg_col & 0xffff00ff) | (val << 8); else gd54xx->blt.bg_col = (gd54xx->blt.bg_col & 0x00ff) | (val << 8); break; case 0x02: - if (svga->crtc[0x27] >= CIRRUS_ID_CLGD5434) + if (gd54xx_is_5434(svga)) gd54xx->blt.bg_col = (gd54xx->blt.bg_col & 0xff00ffff) | (val << 16); break; case 0x03: - if (svga->crtc[0x27] >= CIRRUS_ID_CLGD5434) + if (gd54xx_is_5434(svga)) gd54xx->blt.bg_col = (gd54xx->blt.bg_col & 0x00ffffff) | (val << 24); break; case 0x04: - if (svga->crtc[0x27] >= CIRRUS_ID_CLGD5434) + if (gd54xx_is_5434(svga)) gd54xx->blt.fg_col = (gd54xx->blt.fg_col & 0xffffff00) | val; else gd54xx->blt.fg_col = (gd54xx->blt.fg_col & 0xff00) | val; break; case 0x05: - if (svga->crtc[0x27] >= CIRRUS_ID_CLGD5434) + if (gd54xx_is_5434(svga)) gd54xx->blt.fg_col = (gd54xx->blt.fg_col & 0xffff00ff) | (val << 8); else gd54xx->blt.fg_col = (gd54xx->blt.fg_col & 0x00ff) | (val << 8); break; case 0x06: - if (svga->crtc[0x27] >= CIRRUS_ID_CLGD5434) + if (gd54xx_is_5434(svga)) gd54xx->blt.fg_col = (gd54xx->blt.fg_col & 0xff00ffff) | (val << 16); break; case 0x07: - if (svga->crtc[0x27] >= CIRRUS_ID_CLGD5434) + if (gd54xx_is_5434(svga)) gd54xx->blt.fg_col = (gd54xx->blt.fg_col & 0x00ffffff) | (val << 24); break; @@ -1807,7 +1627,7 @@ gd543x_mmio_write(uint32_t addr, uint8_t val, void *p) break; case 0x09: gd54xx->blt.width = (gd54xx->blt.width & 0x00ff) | (val << 8); - if (svga->crtc[0x27] >= CIRRUS_ID_CLGD5434) + if (gd54xx_is_5434(svga)) gd54xx->blt.width &= 0x1fff; else gd54xx->blt.width &= 0x07ff; @@ -1840,7 +1660,7 @@ gd543x_mmio_write(uint32_t addr, uint8_t val, void *p) break; case 0x12: gd54xx->blt.dst_addr = (gd54xx->blt.dst_addr & 0x00ffff) | (val << 16); - if (svga->crtc[0x27] >= CIRRUS_ID_CLGD5434) + if (gd54xx_is_5434(svga)) gd54xx->blt.dst_addr &= 0x3fffff; else gd54xx->blt.dst_addr &= 0x1fffff; @@ -1866,7 +1686,7 @@ gd543x_mmio_write(uint32_t addr, uint8_t val, void *p) break; case 0x16: gd54xx->blt.src_addr = (gd54xx->blt.src_addr & 0x00ffff) | (val << 16); - if (svga->crtc[0x27] >= CIRRUS_ID_CLGD5434) + if (gd54xx_is_5434(svga)) gd54xx->blt.src_addr &= 0x3fffff; else gd54xx->blt.src_addr &= 0x1fffff; @@ -2043,29 +1863,29 @@ gd54xx_start_blit(uint32_t cpu_dat, int count, gd54xx_t *gd54xx, svga_t *svga) gd54xx->blt.src_addr_backup = gd54xx->blt.src_addr; gd54xx->blt.width_backup = gd54xx->blt.width; gd54xx->blt.height_internal = gd54xx->blt.height; - gd54xx->blt.x_count = 0; + gd54xx->blt.x_count = 0; if ((gd54xx->blt.mode & (CIRRUS_BLTMODE_PATTERNCOPY|CIRRUS_BLTMODE_COLOREXPAND)) == (CIRRUS_BLTMODE_PATTERNCOPY|CIRRUS_BLTMODE_COLOREXPAND)) gd54xx->blt.y_count = gd54xx->blt.src_addr & 7; else gd54xx->blt.y_count = 0; - if ((gd54xx->blt.mode & (CIRRUS_BLTMODE_MEMSYSSRC|CIRRUS_BLTMODE_COLOREXPAND)) == (CIRRUS_BLTMODE_MEMSYSSRC|CIRRUS_BLTMODE_COLOREXPAND)) { + if (gd54xx->blt.mode & CIRRUS_BLTMODE_MEMSYSSRC) { if (!(svga->seqregs[7] & 0xf0)) { - mem_mapping_set_handler(&svga->mapping, NULL, NULL, NULL, NULL, gd54xx_blt_write_w, gd54xx_blt_write_l); - mem_mapping_set_p(&svga->mapping, gd54xx); + mem_map_set_handler(&svga->mapping, NULL, NULL, NULL, NULL, gd54xx_blt_write_w, gd54xx_blt_write_l); + mem_map_set_p(&svga->mapping, gd54xx); } else { - mem_mapping_set_handler(&gd54xx->linear_mapping, NULL, NULL, NULL, NULL, gd54xx_blt_write_w, gd54xx_blt_write_l); - mem_mapping_set_p(&gd54xx->linear_mapping, gd54xx); + mem_map_set_handler(&gd54xx->linear_mapping, NULL, NULL, NULL, NULL, gd54xx_blt_write_w, gd54xx_blt_write_l); + mem_map_set_p(&gd54xx->linear_mapping, gd54xx); } gd543x_recalc_mapping(gd54xx); return; - } else if (gd54xx->blt.mode != CIRRUS_BLTMODE_MEMSYSSRC) { + } else { if (!(svga->seqregs[7] & 0xf0)) { - mem_mapping_set_handler(&svga->mapping, gd54xx_read, gd54xx_readw, gd54xx_readl, gd54xx_write, gd54xx_writew, gd54xx_writel); - mem_mapping_set_p(&gd54xx->svga.mapping, gd54xx); + mem_map_set_handler(&svga->mapping, gd54xx_read, gd54xx_readw, gd54xx_readl, gd54xx_write, gd54xx_writew, gd54xx_writel); + mem_map_set_p(&gd54xx->svga.mapping, gd54xx); } else { - mem_mapping_set_handler(&gd54xx->linear_mapping, svga_readb_linear, svga_readw_linear, svga_readl_linear, gd54xx_writeb_linear, gd54xx_writew_linear, gd54xx_writel_linear); - mem_mapping_set_p(&gd54xx->linear_mapping, svga); + mem_map_set_handler(&gd54xx->linear_mapping, svga_readb_linear, svga_readw_linear, svga_readl_linear, gd54xx_writeb_linear, gd54xx_writew_linear, gd54xx_writel_linear); + mem_map_set_p(&gd54xx->linear_mapping, svga); } gd543x_recalc_mapping(gd54xx); } @@ -2077,24 +1897,24 @@ gd54xx_start_blit(uint32_t cpu_dat, int count, gd54xx_t *gd54xx, svga_t *svga) int mask = 0; if (gd54xx->blt.mode & CIRRUS_BLTMODE_MEMSYSSRC) { - if (gd54xx->blt.mode & CIRRUS_BLTMODE_COLOREXPAND) { + if (gd54xx->blt.mode & CIRRUS_BLTMODE_COLOREXPAND) { if (gd54xx->blt.modeext & CIRRUS_BLTMODEEXT_DWORDGRANULARITY) mask = (cpu_dat >> 31); else mask = cpu_dat & 0x80; switch (gd54xx->blt.mode & CIRRUS_BLTMODE_PIXELWIDTHMASK) { - case CIRRUS_BLTMODE_PIXELWIDTH8: + case CIRRUS_BLTMODE_PIXELWIDTH8: src = mask ? gd54xx->blt.fg_col : gd54xx->blt.bg_col; shift = 0; break; - case CIRRUS_BLTMODE_PIXELWIDTH16: + case CIRRUS_BLTMODE_PIXELWIDTH16: shift = (gd54xx->blt.x_count & 1); break; - case CIRRUS_BLTMODE_PIXELWIDTH24: + case CIRRUS_BLTMODE_PIXELWIDTH24: shift = (gd54xx->blt.x_count % 3); break; - case CIRRUS_BLTMODE_PIXELWIDTH32: + case CIRRUS_BLTMODE_PIXELWIDTH32: shift = (gd54xx->blt.x_count & 3); break; } @@ -2105,6 +1925,12 @@ gd54xx_start_blit(uint32_t cpu_dat, int count, gd54xx_t *gd54xx, svga_t *svga) cpu_dat <<= 1; count--; } + } else { + /*This must stay for general purpose Cirrus drivers to render fine in WinNT 3.5x*/ + src = cpu_dat & 0xff; + cpu_dat >>= 8; + count -= 8; + mask = 1; } } else { switch (gd54xx->blt.mode & (CIRRUS_BLTMODE_PATTERNCOPY|CIRRUS_BLTMODE_COLOREXPAND)) { @@ -2115,16 +1941,16 @@ gd54xx_start_blit(uint32_t cpu_dat, int count, gd54xx_t *gd54xx, svga_t *svga) break; case CIRRUS_BLTMODE_PATTERNCOPY: switch (gd54xx->blt.mode & CIRRUS_BLTMODE_PIXELWIDTHMASK) { - case CIRRUS_BLTMODE_PIXELWIDTH8: + case CIRRUS_BLTMODE_PIXELWIDTH8: src = svga->vram[(gd54xx->blt.src_addr & (svga->vram_mask & ~7)) + (gd54xx->blt.y_count << 3) + (gd54xx->blt.x_count & 7)]; break; - case CIRRUS_BLTMODE_PIXELWIDTH16: + case CIRRUS_BLTMODE_PIXELWIDTH16: src = svga->vram[(gd54xx->blt.src_addr & (svga->vram_mask & ~15)) + (gd54xx->blt.y_count << 4) + (gd54xx->blt.x_count & 15)]; break; - case CIRRUS_BLTMODE_PIXELWIDTH24: + case CIRRUS_BLTMODE_PIXELWIDTH24: src = svga->vram[(gd54xx->blt.src_addr & (svga->vram_mask & ~31)) + (gd54xx->blt.y_count << 5) + (gd54xx->blt.x_count % 24)]; break; - case CIRRUS_BLTMODE_PIXELWIDTH32: + case CIRRUS_BLTMODE_PIXELWIDTH32: src = svga->vram[(gd54xx->blt.src_addr & (svga->vram_mask & ~31)) + (gd54xx->blt.y_count << 5) + (gd54xx->blt.x_count & 31)]; break; } @@ -2132,19 +1958,19 @@ gd54xx_start_blit(uint32_t cpu_dat, int count, gd54xx_t *gd54xx, svga_t *svga) break; case CIRRUS_BLTMODE_COLOREXPAND: switch (gd54xx->blt.mode & CIRRUS_BLTMODE_PIXELWIDTHMASK) { - case CIRRUS_BLTMODE_PIXELWIDTH8: + case CIRRUS_BLTMODE_PIXELWIDTH8: mask = svga->vram[gd54xx->blt.src_addr & svga->vram_mask] & (0x80 >> gd54xx->blt.x_count); shift = 0; break; - case CIRRUS_BLTMODE_PIXELWIDTH16: + case CIRRUS_BLTMODE_PIXELWIDTH16: mask = svga->vram[gd54xx->blt.src_addr & svga->vram_mask] & (0x80 >> (gd54xx->blt.x_count >> 1)); shift = (gd54xx->blt.dst_addr & 1); break; - case CIRRUS_BLTMODE_PIXELWIDTH24: + case CIRRUS_BLTMODE_PIXELWIDTH24: mask = svga->vram[gd54xx->blt.src_addr & svga->vram_mask] & (0x80 >> (gd54xx->blt.x_count / 3)); shift = (gd54xx->blt.dst_addr % 3); break; - case CIRRUS_BLTMODE_PIXELWIDTH32: + case CIRRUS_BLTMODE_PIXELWIDTH32: mask = svga->vram[gd54xx->blt.src_addr & svga->vram_mask] & (0x80 >> (gd54xx->blt.x_count >> 2)); shift = (gd54xx->blt.dst_addr & 3); break; @@ -2154,36 +1980,35 @@ gd54xx_start_blit(uint32_t cpu_dat, int count, gd54xx_t *gd54xx, svga_t *svga) case CIRRUS_BLTMODE_PATTERNCOPY|CIRRUS_BLTMODE_COLOREXPAND: if (gd54xx->blt.modeext & CIRRUS_BLTMODEEXT_SOLIDFILL) { switch (gd54xx->blt.mode & CIRRUS_BLTMODE_PIXELWIDTHMASK) { - case CIRRUS_BLTMODE_PIXELWIDTH8: + case CIRRUS_BLTMODE_PIXELWIDTH8: shift = 0; break; - case CIRRUS_BLTMODE_PIXELWIDTH16: + case CIRRUS_BLTMODE_PIXELWIDTH16: shift = (gd54xx->blt.dst_addr & 1); break; - case CIRRUS_BLTMODE_PIXELWIDTH24: + case CIRRUS_BLTMODE_PIXELWIDTH24: shift = (gd54xx->blt.dst_addr % 3); break; - - case CIRRUS_BLTMODE_PIXELWIDTH32: + case CIRRUS_BLTMODE_PIXELWIDTH32: shift = (gd54xx->blt.dst_addr & 3); break; } src = (gd54xx->blt.fg_col >> (shift << 3)); } else { switch (gd54xx->blt.mode & CIRRUS_BLTMODE_PIXELWIDTHMASK) { - case CIRRUS_BLTMODE_PIXELWIDTH8: + case CIRRUS_BLTMODE_PIXELWIDTH8: mask = svga->vram[(gd54xx->blt.src_addr & svga->vram_mask & ~7) | gd54xx->blt.y_count] & (0x80 >> gd54xx->blt.x_count); shift = 0; break; - case CIRRUS_BLTMODE_PIXELWIDTH16: + case CIRRUS_BLTMODE_PIXELWIDTH16: mask = svga->vram[(gd54xx->blt.src_addr & svga->vram_mask & ~7) | gd54xx->blt.y_count] & (0x80 >> (gd54xx->blt.x_count >> 1)); shift = (gd54xx->blt.dst_addr & 1); break; - case CIRRUS_BLTMODE_PIXELWIDTH24: + case CIRRUS_BLTMODE_PIXELWIDTH24: mask = svga->vram[(gd54xx->blt.src_addr & svga->vram_mask & ~7) | gd54xx->blt.y_count] & (0x80 >> (gd54xx->blt.x_count / 3)); shift = (gd54xx->blt.dst_addr % 3); - break; - case CIRRUS_BLTMODE_PIXELWIDTH32: + break; + case CIRRUS_BLTMODE_PIXELWIDTH32: mask = svga->vram[(gd54xx->blt.src_addr & svga->vram_mask & ~7) | gd54xx->blt.y_count] & (0x80 >> (gd54xx->blt.x_count >> 2)); shift = (gd54xx->blt.dst_addr & 3); break; @@ -2201,7 +2026,7 @@ gd54xx_start_blit(uint32_t cpu_dat, int count, gd54xx_t *gd54xx, svga_t *svga) switch (gd54xx->blt.rop) { case 0x00: dst = 0; break; case 0x05: dst = src & dst; break; - case 0x06: /* dst = dst; */ break; + case 0x06: dst = dst; break; case 0x09: dst = src & ~dst; break; case 0x0b: dst = ~ dst; break; case 0x0d: dst = src; break; @@ -2264,11 +2089,11 @@ gd54xx_start_blit(uint32_t cpu_dat, int count, gd54xx_t *gd54xx, svga_t *svga) if (gd54xx->blt.height_internal == 0xffff) { if (gd54xx->blt.mode & CIRRUS_BLTMODE_MEMSYSSRC) { if (!(svga->seqregs[7] & 0xf0)) { - mem_mapping_set_handler(&svga->mapping, gd54xx_read, gd54xx_readw, gd54xx_readl, gd54xx_write, gd54xx_writew, gd54xx_writel); - mem_mapping_set_p(&svga->mapping, gd54xx); + mem_map_set_handler(&svga->mapping, gd54xx_read, gd54xx_readw, gd54xx_readl, gd54xx_write, gd54xx_writew, gd54xx_writel); + mem_map_set_p(&svga->mapping, gd54xx); } else { - mem_mapping_set_handler(&gd54xx->linear_mapping, svga_readb_linear, svga_readw_linear, svga_readl_linear, gd54xx_writeb_linear, gd54xx_writew_linear, gd54xx_writel_linear); - mem_mapping_set_p(&gd54xx->linear_mapping, svga); + mem_map_set_handler(&gd54xx->linear_mapping, svga_readb_linear, svga_readw_linear, svga_readl_linear, gd54xx_writeb_linear, gd54xx_writew_linear, gd54xx_writel_linear); + mem_map_set_p(&gd54xx->linear_mapping, svga); } gd543x_recalc_mapping(gd54xx); } @@ -2288,22 +2113,25 @@ cl_pci_read(int func, int addr, void *p) gd54xx_t *gd54xx = (gd54xx_t *)p; svga_t *svga = &gd54xx->svga; + if ((addr >= 0x30) && (addr <= 0x33) && (!gd54xx->has_bios)) + return 0; + switch (addr) { case 0x00: return 0x13; /*Cirrus Logic*/ case 0x01: return 0x10; case 0x02: return svga->crtc[0x27]; - case 0x03: return 0x00; - + case PCI_REG_COMMAND: return gd54xx->pci_regs[PCI_REG_COMMAND]; /*Respond to IO and memory accesses*/ - case 0x07: return 0 << 1; /*Fast DEVSEL timing*/ + // case 0x07: return 0 << 1; /*Fast DEVSEL timing*/ + case 0x07: return 0x02; /*Fast DEVSEL timing*/ - case 0x08: return 0; /*Revision ID*/ - case 0x09: return 0; /*Programming interface*/ + case 0x08: return gd54xx->rev; /*Revision ID*/ + case 0x09: return 0x00; /*Programming interface*/ case 0x0a: return 0x00; /*Supports VGA interface*/ case 0x0b: return 0x03; @@ -2330,6 +2158,9 @@ cl_pci_write(int func, int addr, uint8_t val, void *p) { gd54xx_t *gd54xx = (gd54xx_t *)p; + if ((addr >= 0x30) && (addr <= 0x33) && (!gd54xx->has_bios)) + return; + switch (addr) { case PCI_REG_COMMAND: gd54xx->pci_regs[PCI_REG_COMMAND] = val & 0x23; @@ -2347,10 +2178,10 @@ cl_pci_write(int func, int addr, uint8_t val, void *p) case 0x30: case 0x32: case 0x33: gd54xx->pci_regs[addr] = val; if (gd54xx->pci_regs[0x30] & 0x01) { - uint32_t a = (gd54xx->pci_regs[0x32] << 16) | (gd54xx->pci_regs[0x33] << 24); - mem_mapping_set_addr(&gd54xx->bios_rom.mapping, a, 0x8000); + uint32_t addr = (gd54xx->pci_regs[0x32] << 16) | (gd54xx->pci_regs[0x33] << 24); + mem_map_set_addr(&gd54xx->bios_rom.mapping, addr, 0x8000); } else - mem_mapping_disable(&gd54xx->bios_rom.mapping); + mem_map_disable(&gd54xx->bios_rom.mapping); return; case 0x3c: @@ -2363,7 +2194,7 @@ cl_pci_write(int func, int addr, uint8_t val, void *p) static void * gd54xx_init(const device_t *info) { - gd54xx_t *gd54xx = malloc(sizeof(gd54xx_t)); + gd54xx_t *gd54xx = (gd54xx_t *)mem_alloc(sizeof(gd54xx_t)); svga_t *svga = &gd54xx->svga; int id = info->local & 0xff; wchar_t *romfn = NULL; @@ -2372,11 +2203,13 @@ gd54xx_init(const device_t *info) gd54xx->pci = !!(info->flags & DEVICE_PCI); gd54xx->vlb = !!(info->flags & DEVICE_VLB); + gd54xx->rev = 0; + gd54xx->has_bios = 1; switch (id) { case CIRRUS_ID_CLGD5426: romfn = BIOS_GD5426_PATH; break; - + case CIRRUS_ID_CLGD5428: if (gd54xx->vlb) romfn = BIOS_GD5428_VLB_PATH; @@ -2388,13 +2221,6 @@ gd54xx_init(const device_t *info) romfn = BIOS_GD5429_PATH; break; - case CIRRUS_ID_CLGD5430: - if (gd54xx->pci) - romfn = BIOS_GD5430_PCI_PATH; - else - romfn = BIOS_GD5430_VLB_PATH; - break; - case CIRRUS_ID_CLGD5434: romfn = BIOS_GD5434_PATH; break; @@ -2403,6 +2229,24 @@ gd54xx_init(const device_t *info) romfn = BIOS_GD5436_PATH; break; + case CIRRUS_ID_CLGD5430: + if (info->local & 0x400) { + /* CL-GD 5440 */ + gd54xx->rev = 0x47; + if (info->local & 0x200) { + romfn = NULL; + gd54xx->has_bios = 0; + } else + romfn = BIOS_GD5440_PATH; + } else { + /* CL-GD 5430 */ + if (gd54xx->pci) + romfn = BIOS_GD5430_PCI_PATH; + else + romfn = BIOS_GD5430_VLB_PATH; + } + break; + case CIRRUS_ID_CLGD5446: if (info->local & 0x100) romfn = BIOS_GD5446_STB_PATH; @@ -2413,34 +2257,26 @@ gd54xx_init(const device_t *info) case CIRRUS_ID_CLGD5480: romfn = BIOS_GD5480_PATH; break; - } + } gd54xx->vram_size = device_get_config_int("memory"); gd54xx->vram_mask = (gd54xx->vram_size << 20) - 1; - rom_init(&gd54xx->bios_rom, romfn, - 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + if (romfn) + rom_init(&gd54xx->bios_rom, romfn, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); svga_init(&gd54xx->svga, gd54xx, gd54xx->vram_size << 20, gd54xx_recalctimings, gd54xx_in, gd54xx_out, gd54xx_hwcursor_draw, NULL); + svga->ven_write = gd54xx_write_modes45; - mem_mapping_set_handler(&svga->mapping, - gd54xx_read,gd54xx_readw,gd54xx_readl, - gd54xx_write,gd54xx_writew,gd54xx_writel); - mem_mapping_set_p(&svga->mapping, gd54xx); + mem_map_set_handler(&svga->mapping, gd54xx_read, gd54xx_readw, gd54xx_readl, gd54xx_write, gd54xx_writew, gd54xx_writel); + mem_map_set_p(&svga->mapping, gd54xx); - mem_mapping_add(&gd54xx->mmio_mapping, 0, 0, - gd543x_mmio_read,gd543x_mmio_readw,gd543x_mmio_readl, - gd543x_mmio_write,gd543x_mmio_writew,gd543x_mmio_writel, - NULL, 0, gd54xx); - mem_mapping_add(&gd54xx->linear_mapping, 0, 0, - gd54xx_readb_linear,gd54xx_readw_linear,gd54xx_readl_linear, - gd54xx_writeb_linear,gd54xx_writew_linear,gd54xx_writel_linear, - NULL, 0, svga); + mem_map_add(&gd54xx->mmio_mapping, 0, 0, gd543x_mmio_read, gd543x_mmio_readw, gd543x_mmio_readl, gd543x_mmio_write, gd543x_mmio_writew, gd543x_mmio_writel, NULL, 0, gd54xx); + mem_map_add(&gd54xx->linear_mapping, 0, 0, gd54xx_readb_linear, gd54xx_readw_linear, gd54xx_readl_linear, gd54xx_writeb_linear, gd54xx_writew_linear, gd54xx_writel_linear, NULL, 0, svga); - io_sethandler(0x03c0, 32, - gd54xx_in,NULL,NULL, gd54xx_out,NULL,NULL, gd54xx); + io_sethandler(0x03c0, 0x0020, gd54xx_in, NULL, NULL, gd54xx_out, NULL, NULL, gd54xx); svga->hwcursor.yoff = 32; svga->hwcursor.xoff = 0; @@ -2460,9 +2296,9 @@ gd54xx_init(const device_t *info) gd54xx->pci_regs[0x30] = 0x00; gd54xx->pci_regs[0x32] = 0x0c; gd54xx->pci_regs[0x33] = 0x00; - + svga->crtc[0x27] = id; - + return gd54xx; } @@ -2473,15 +2309,15 @@ gd5426_available(void) } static int -gd5428_isa_available(void) +gd5428_available(void) { - return rom_present(BIOS_GD5428_ISA_PATH); + return rom_present(BIOS_GD5428_VLB_PATH); } static int -gd5428_vlb_available(void) +gd5428_isa_available(void) { - return rom_present(BIOS_GD5428_VLB_PATH); + return rom_present(BIOS_GD5428_ISA_PATH); } static int @@ -2514,6 +2350,12 @@ gd5436_available(void) return rom_present(BIOS_GD5436_PATH); } +static int +gd5440_available(void) +{ + return rom_present(BIOS_GD5440_PATH); +} + static int gd5446_available(void) { @@ -2536,7 +2378,7 @@ void gd54xx_close(void *p) { gd54xx_t *gd54xx = (gd54xx_t *)p; - + svga_close(&gd54xx->svga); free(gd54xx); @@ -2561,73 +2403,72 @@ gd54xx_force_redraw(void *p) } -void -gd54xx_add_status_info(char *s, int max_len, void *p) -{ - gd54xx_t *gd54xx = (gd54xx_t *)p; - - svga_add_status_info(s, max_len, &gd54xx->svga); -} - - static const device_config_t gd5428_config[] = { { - .name = "memory", - .description = "Memory size", - .type = CONFIG_SELECTION, - .selection = + "memory","Memory size",CONFIG_SELECTION,"",2, { { - .description = "1 MB", - .value = 1 + "1 MB",1 }, { - .description = "2 MB", - .value = 2 + "2 MB",2 }, { - .description = "" + "" } }, - .default_int = 2 }, { - .type = -1 + "","",-1 + } +}; + +static const device_config_t gd5440_onboard_config[] = +{ + { + "memory","Video memory size",CONFIG_SELECTION,"",2, + { + { + "1 MB",1 + }, + { + "2 MB",2 + }, + { + "" + } + }, + }, + { + "","",-1 } }; static const device_config_t gd5434_config[] = { { - .name = "memory", - .description = "Memory size", - .type = CONFIG_SELECTION, - .selection = + "memory","Memory size",CONFIG_SELECTION,"",4, { { - .description = "2 MB", - .value = 2 + "2 MB",2 }, { - .description = "4 MB", - .value = 4 + "4 MB",4 }, { - .description = "" + "" } }, - .default_int = 4 }, { - .type = -1 + "","",-1 } }; - const device_t gd5426_vlb_device = { - "Cirrus Logic GD5426 (VLB)", + "Cirrus Logic CL-GD 5426 (VLB)", DEVICE_VLB, CIRRUS_ID_CLGD5426, gd54xx_init, @@ -2636,13 +2477,13 @@ const device_t gd5426_vlb_device = gd5426_available, gd54xx_speed_changed, gd54xx_force_redraw, - gd54xx_add_status_info, + NULL, gd5428_config }; const device_t gd5428_isa_device = { - "Cirrus Logic GD5428 (ISA)", + "Cirrus Logic CL-GD 5428 (ISA)", DEVICE_AT | DEVICE_ISA, CIRRUS_ID_CLGD5428, gd54xx_init, @@ -2651,28 +2492,28 @@ const device_t gd5428_isa_device = gd5428_isa_available, gd54xx_speed_changed, gd54xx_force_redraw, - gd54xx_add_status_info, + NULL, gd5428_config }; const device_t gd5428_vlb_device = { - "Cirrus Logic GD5428 (VLB)", + "Cirrus Logic CL-GD 5428 (VLB)", DEVICE_VLB, CIRRUS_ID_CLGD5428, gd54xx_init, gd54xx_close, NULL, - gd5428_vlb_available, + gd5428_available, gd54xx_speed_changed, gd54xx_force_redraw, - gd54xx_add_status_info, + NULL, gd5428_config }; const device_t gd5429_isa_device = { - "Cirrus Logic GD5429 (ISA)", + "Cirrus Logic CL-GD 5429 (ISA)", DEVICE_AT | DEVICE_ISA, CIRRUS_ID_CLGD5429, gd54xx_init, @@ -2681,13 +2522,13 @@ const device_t gd5429_isa_device = gd5429_available, gd54xx_speed_changed, gd54xx_force_redraw, - gd54xx_add_status_info, + NULL, gd5428_config }; const device_t gd5429_vlb_device = { - "Cirrus Logic GD5429 (VLB)", + "Cirrus Logic CL-GD 5429 (VLB)", DEVICE_VLB, CIRRUS_ID_CLGD5429, gd54xx_init, @@ -2696,13 +2537,13 @@ const device_t gd5429_vlb_device = gd5429_available, gd54xx_speed_changed, gd54xx_force_redraw, - gd54xx_add_status_info, + NULL, gd5428_config }; const device_t gd5430_vlb_device = { - "Cirrus Logic GD5430 (VLB)", + "Cirrus Logic CL-GD 5430 (VLB)", DEVICE_VLB, CIRRUS_ID_CLGD5430, gd54xx_init, @@ -2711,13 +2552,13 @@ const device_t gd5430_vlb_device = gd5430_vlb_available, gd54xx_speed_changed, gd54xx_force_redraw, - gd54xx_add_status_info, + NULL, gd5428_config }; const device_t gd5430_pci_device = { - "Cirrus Logic GD5430 (PCI)", + "Cirrus Logic CL-GD 5430 (PCI)", DEVICE_PCI, CIRRUS_ID_CLGD5430, gd54xx_init, @@ -2726,13 +2567,13 @@ const device_t gd5430_pci_device = gd5430_pci_available, gd54xx_speed_changed, gd54xx_force_redraw, - gd54xx_add_status_info, + NULL, gd5428_config }; const device_t gd5434_isa_device = { - "Cirrus Logic GD5434 (ISA)", + "Cirrus Logic CL-GD 5434 (ISA)", DEVICE_AT | DEVICE_ISA, CIRRUS_ID_CLGD5434, gd54xx_init, @@ -2741,13 +2582,13 @@ const device_t gd5434_isa_device = gd5434_available, gd54xx_speed_changed, gd54xx_force_redraw, - gd54xx_add_status_info, + NULL, gd5434_config }; const device_t gd5434_vlb_device = { - "Cirrus Logic GD5434 (VLB)", + "Cirrus Logic CL-GD 5434 (VLB)", DEVICE_VLB, CIRRUS_ID_CLGD5434, gd54xx_init, @@ -2756,13 +2597,13 @@ const device_t gd5434_vlb_device = gd5434_available, gd54xx_speed_changed, gd54xx_force_redraw, - gd54xx_add_status_info, + NULL, gd5434_config }; const device_t gd5434_pci_device = { - "Cirrus Logic GD5434 (PCI)", + "Cirrus Logic CL-GD 5434 (PCI)", DEVICE_PCI, CIRRUS_ID_CLGD5434, gd54xx_init, @@ -2771,13 +2612,13 @@ const device_t gd5434_pci_device = gd5434_available, gd54xx_speed_changed, gd54xx_force_redraw, - gd54xx_add_status_info, + NULL, gd5434_config }; const device_t gd5436_pci_device = { - "Cirrus Logic GD5436 (PCI)", + "Cirrus Logic CL-GD 5436 (PCI)", DEVICE_PCI, CIRRUS_ID_CLGD5436, gd54xx_init, @@ -2786,10 +2627,40 @@ const device_t gd5436_pci_device = gd5436_available, gd54xx_speed_changed, gd54xx_force_redraw, - gd54xx_add_status_info, + NULL, gd5434_config }; +const device_t gd5440_onboard_pci_device = +{ + "Cirrus Logic CL-GD 5440 (On-Board PCI)", + DEVICE_PCI, + CIRRUS_ID_CLGD5440 | 0x600, + gd54xx_init, + gd54xx_close, + NULL, + NULL, + gd54xx_speed_changed, + gd54xx_force_redraw, + NULL, + gd5440_onboard_config +}; + +const device_t gd5440_pci_device = +{ + "Cirrus Logic CL-GD 5440 (PCI)", + DEVICE_PCI, + CIRRUS_ID_CLGD5440 | 0x400, + gd54xx_init, + gd54xx_close, + NULL, + gd5440_available, + gd54xx_speed_changed, + gd54xx_force_redraw, + NULL, + gd5428_config +}; + const device_t gd5446_pci_device = { "Cirrus Logic CL-GD 5446 (PCI)", @@ -2801,7 +2672,7 @@ const device_t gd5446_pci_device = gd5446_available, gd54xx_speed_changed, gd54xx_force_redraw, - gd54xx_add_status_info, + NULL, gd5434_config }; @@ -2809,14 +2680,14 @@ const device_t gd5446_stb_pci_device = { "STB Nitro 64V (PCI)", DEVICE_PCI, - CIRRUS_ID_CLGD5446, + CIRRUS_ID_CLGD5446 | 0x100, gd54xx_init, gd54xx_close, NULL, gd5446_stb_available, gd54xx_speed_changed, gd54xx_force_redraw, - gd54xx_add_status_info, + NULL, gd5434_config }; @@ -2831,6 +2702,6 @@ const device_t gd5480_pci_device = gd5480_available, gd54xx_speed_changed, gd54xx_force_redraw, - gd54xx_add_status_info, + NULL, gd5434_config }; diff --git a/src/devices/video/vid_colorplus.c b/src/devices/video/vid_colorplus.c index 7bda2c3..3242de7 100644 --- a/src/devices/video/vid_colorplus.c +++ b/src/devices/video/vid_colorplus.c @@ -8,7 +8,7 @@ * * Plantronics ColorPlus emulation. * - * Version: @(#)vid_colorplus.c 1.0.7 2018/05/06 + * Version: @(#)vid_colorplus.c 1.0.8 2018/09/22 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -64,438 +64,416 @@ /* Bits in the CGA graphics mode register */ #define CGA_GRAPHICS_MODE 0x02 /* CGA graphics mode selected? */ -#define CGA_RGB 0 -#define CGA_COMPOSITE 1 +#define CGA_RGB 0 +#define CGA_COMPOSITE 1 -#define COMPOSITE_OLD 0 -#define COMPOSITE_NEW 1 +#define COMPOSITE_OLD 0 +#define COMPOSITE_NEW 1 -typedef struct -{ - cga_t cga; - uint8_t control; +typedef struct { + cga_t cga; + uint8_t control; } colorplus_t; -static void -colorplus_out(uint16_t addr, uint8_t val, void *p) -{ - colorplus_t *colorplus = (colorplus_t *)p; +static const int cols16[16] = { + 0x10,0x12,0x14,0x16, 0x18,0x1A,0x1C,0x1E, + 0x11,0x13,0x15,0x17, 0x19,0x1B,0x1D,0x1F +}; - if (addr == 0x3DD) - { - colorplus->control = val & 0x70; - } - else - { - cga_out(addr, val, &colorplus->cga); - } + +static void +colorplus_out(uint16_t port, uint8_t val, void *priv) +{ + colorplus_t *dev = (colorplus_t *)priv; + + if (port == 0x3dd) + dev->control = val & 0x70; + else + cga_out(port, val, &dev->cga); } static uint8_t -colorplus_in(uint16_t addr, void *p) +colorplus_in(uint16_t port, void *priv) { - colorplus_t *colorplus = (colorplus_t *)p; + colorplus_t *dev = (colorplus_t *)priv; - return cga_in(addr, &colorplus->cga); + return cga_in(port, &dev->cga); } static void -colorplus_write(uint32_t addr, uint8_t val, void *p) +colorplus_write(uint32_t addr, uint8_t val, void *priv) { - colorplus_t *colorplus = (colorplus_t *)p; + colorplus_t *dev = (colorplus_t *)priv; - if ((colorplus->control & COLORPLUS_PLANE_SWAP) && - (colorplus->control & COLORPLUS_EITHER_MODE) && - (colorplus->cga.cgamode & CGA_GRAPHICS_MODE)) - { - addr ^= 0x4000; - } - else if (!(colorplus->control & COLORPLUS_EITHER_MODE)) - { - addr &= 0x3FFF; - } - colorplus->cga.vram[addr & 0x7fff] = val; - if (colorplus->cga.snow_enabled) - { - colorplus->cga.charbuffer[ ((int)(((colorplus->cga.dispontime - colorplus->cga.vidtime) * 2) / CGACONST)) & 0xfc] = val; - colorplus->cga.charbuffer[(((int)(((colorplus->cga.dispontime - colorplus->cga.vidtime) * 2) / CGACONST)) & 0xfc) | 1] = val; - } - egawrites++; - cycles -= 4; + if ((dev->control & COLORPLUS_PLANE_SWAP) && + (dev->control & COLORPLUS_EITHER_MODE) && + (dev->cga.cgamode & CGA_GRAPHICS_MODE)) { + addr ^= 0x4000; + } else if (!(dev->control & COLORPLUS_EITHER_MODE)) { + addr &= 0x3fff; + } + dev->cga.vram[addr & 0x7fff] = val; + + if (dev->cga.snow_enabled) { + dev->cga.charbuffer[((int)(((dev->cga.dispontime - dev->cga.vidtime) * 2) / CGACONST)) & 0xfc] = val; + dev->cga.charbuffer[(((int)(((dev->cga.dispontime - dev->cga.vidtime) * 2) / CGACONST)) & 0xfc) | 1] = val; + } + + cycles -= 4; } static uint8_t -colorplus_read(uint32_t addr, void *p) +colorplus_read(uint32_t addr, void *priv) { - colorplus_t *colorplus = (colorplus_t *)p; + colorplus_t *dev = (colorplus_t *)priv; - if ((colorplus->control & COLORPLUS_PLANE_SWAP) && - (colorplus->control & COLORPLUS_EITHER_MODE) && - (colorplus->cga.cgamode & CGA_GRAPHICS_MODE)) - { - addr ^= 0x4000; - } - else if (!(colorplus->control & COLORPLUS_EITHER_MODE)) - { - addr &= 0x3FFF; - } - cycles -= 4; - if (colorplus->cga.snow_enabled) - { - colorplus->cga.charbuffer[ ((int)(((colorplus->cga.dispontime - colorplus->cga.vidtime) * 2) / CGACONST)) & 0xfc] = colorplus->cga.vram[addr & 0x7fff]; - colorplus->cga.charbuffer[(((int)(((colorplus->cga.dispontime - colorplus->cga.vidtime) * 2) / CGACONST)) & 0xfc) | 1] = colorplus->cga.vram[addr & 0x7fff]; - } - egareads++; - return colorplus->cga.vram[addr & 0x7fff]; + if ((dev->control & COLORPLUS_PLANE_SWAP) && + (dev->control & COLORPLUS_EITHER_MODE) && + (dev->cga.cgamode & CGA_GRAPHICS_MODE)) { + addr ^= 0x4000; + } else if (!(dev->control & COLORPLUS_EITHER_MODE)) { + addr &= 0x3fff; + } + + cycles -= 4; + + if (dev->cga.snow_enabled) { + dev->cga.charbuffer[ ((int)(((dev->cga.dispontime - dev->cga.vidtime) * 2) / CGACONST)) & 0xfc] = dev->cga.vram[addr & 0x7fff]; + dev->cga.charbuffer[(((int)(((dev->cga.dispontime - dev->cga.vidtime) * 2) / CGACONST)) & 0xfc) | 1] = dev->cga.vram[addr & 0x7fff]; + } + + return dev->cga.vram[addr & 0x7fff]; } static void -colorplus_poll(void *p) +colorplus_poll(void *priv) { - colorplus_t *colorplus = (colorplus_t *)p; - int x, c; - int oldvc; - uint16_t dat0, dat1; - int cols[4]; - int col; - int oldsc; - static const int cols16[16] = { 0x10,0x12,0x14,0x16, - 0x18,0x1A,0x1C,0x1E, - 0x11,0x13,0x15,0x17, - 0x19,0x1B,0x1D,0x1F }; - uint8_t *plane0 = colorplus->cga.vram; - uint8_t *plane1 = colorplus->cga.vram + 0x4000; + colorplus_t *dev = (colorplus_t *)priv; + uint8_t *plane0 = dev->cga.vram; + uint8_t *plane1 = dev->cga.vram + 0x4000; + int x, c; + int oldvc; + uint16_t dat0, dat1; + int cols[4]; + int col; + int oldsc; - /* If one of the extra modes is not selected, drop down to the CGA - * drawing code. */ - if (!((colorplus->control & COLORPLUS_EITHER_MODE) && - (colorplus->cga.cgamode & CGA_GRAPHICS_MODE))) - { - cga_poll(&colorplus->cga); - return; - } + /* If one of the extra modes is not selected, + * fall back to the CGA drawing code. + */ + if (!((dev->control & COLORPLUS_EITHER_MODE) && + (dev->cga.cgamode & CGA_GRAPHICS_MODE))) { + cga_poll(&dev->cga); + return; + } - if (!colorplus->cga.linepos) - { - colorplus->cga.vidtime += colorplus->cga.dispofftime; - colorplus->cga.cgastat |= 1; - colorplus->cga.linepos = 1; - oldsc = colorplus->cga.sc; - if ((colorplus->cga.crtc[8] & 3) == 3) - colorplus->cga.sc = ((colorplus->cga.sc << 1) + colorplus->cga.oddeven) & 7; - if (colorplus->cga.cgadispon) - { - if (colorplus->cga.displine < colorplus->cga.firstline) - { - colorplus->cga.firstline = colorplus->cga.displine; - video_wait_for_buffer(); - } - colorplus->cga.lastline = colorplus->cga.displine; - /* Left / right border */ - for (c = 0; c < 8; c++) - { - buffer->line[colorplus->cga.displine][c] = - buffer->line[colorplus->cga.displine][c + (colorplus->cga.crtc[1] << 4) + 8] = (colorplus->cga.cgacol & 15) + 16; - } - if (colorplus->control & COLORPLUS_320x200_MODE) - { - for (x = 0; x < colorplus->cga.crtc[1]; x++) - { - dat0 = (plane0[((colorplus->cga.ma << 1) & 0x1fff) + ((colorplus->cga.sc & 1) * 0x2000)] << 8) | - plane0[((colorplus->cga.ma << 1) & 0x1fff) + ((colorplus->cga.sc & 1) * 0x2000) + 1]; - dat1 = (plane1[((colorplus->cga.ma << 1) & 0x1fff) + ((colorplus->cga.sc & 1) * 0x2000)] << 8) | - plane1[((colorplus->cga.ma << 1) & 0x1fff) + ((colorplus->cga.sc & 1) * 0x2000) + 1]; - colorplus->cga.ma++; - for (c = 0; c < 8; c++) - { - buffer->line[colorplus->cga.displine][(x << 4) + (c << 1) + 8] = - buffer->line[colorplus->cga.displine][(x << 4) + (c << 1) + 1 + 8] = - cols16[(dat0 >> 14) | ((dat1 >> 14) << 2)]; - dat0 <<= 2; - dat1 <<= 2; - } - } + if (! dev->cga.linepos) { + dev->cga.vidtime += dev->cga.dispofftime; + dev->cga.cgastat |= 1; + dev->cga.linepos = 1; + oldsc = dev->cga.sc; + + if ((dev->cga.crtc[8] & 3) == 3) + dev->cga.sc = ((dev->cga.sc << 1) + dev->cga.oddeven) & 7; + + if (dev->cga.cgadispon) { + if (dev->cga.displine < dev->cga.firstline) { + dev->cga.firstline = dev->cga.displine; + video_wait_for_buffer(); + } + dev->cga.lastline = dev->cga.displine; + + /* Left / right border */ + for (c = 0; c < 8; c++) { + buffer->line[dev->cga.displine][c] = + buffer->line[dev->cga.displine][c + (dev->cga.crtc[1] << 4) + 8] = (dev->cga.cgacol & 15) + 16; + } + + if (dev->control & COLORPLUS_320x200_MODE) { + for (x = 0; x < dev->cga.crtc[1]; x++) { + dat0 = (plane0[((dev->cga.ma << 1) & 0x1fff) + ((dev->cga.sc & 1) * 0x2000)] << 8) | + plane0[((dev->cga.ma << 1) & 0x1fff) + ((dev->cga.sc & 1) * 0x2000) + 1]; + dat1 = (plane1[((dev->cga.ma << 1) & 0x1fff) + ((dev->cga.sc & 1) * 0x2000)] << 8) | + plane1[((dev->cga.ma << 1) & 0x1fff) + ((dev->cga.sc & 1) * 0x2000) + 1]; + dev->cga.ma++; + + for (c = 0; c < 8; c++) { + buffer->line[dev->cga.displine][(x << 4) + (c << 1) + 8] = buffer->line[dev->cga.displine][(x << 4) + (c << 1) + 1 + 8] = cols16[(dat0 >> 14) | ((dat1 >> 14) << 2)]; + dat0 <<= 2; + dat1 <<= 2; + } + } + } else if (dev->control & COLORPLUS_640x200_MODE) { + cols[0] = (dev->cga.cgacol & 15) | 16; + col = (dev->cga.cgacol & 16) ? 24 : 16; + if (dev->cga.cgamode & 4) { + cols[1] = col | 3; + cols[2] = col | 4; + cols[3] = col | 7; + } else if (dev->cga.cgacol & 32) { + cols[1] = col | 3; + cols[2] = col | 5; + cols[3] = col | 7; + } else { + cols[1] = col | 2; + cols[2] = col | 4; + cols[3] = col | 6; } - else if (colorplus->control & COLORPLUS_640x200_MODE) - { - cols[0] = (colorplus->cga.cgacol & 15) | 16; - col = (colorplus->cga.cgacol & 16) ? 24 : 16; - if (colorplus->cga.cgamode & 4) - { - cols[1] = col | 3; - cols[2] = col | 4; - cols[3] = col | 7; - } - else if (colorplus->cga.cgacol & 32) - { - cols[1] = col | 3; - cols[2] = col | 5; - cols[3] = col | 7; - } - else - { - cols[1] = col | 2; - cols[2] = col | 4; - cols[3] = col | 6; - } - for (x = 0; x < colorplus->cga.crtc[1]; x++) - { - dat0 = (plane0[((colorplus->cga.ma << 1) & 0x1fff) + ((colorplus->cga.sc & 1) * 0x2000)] << 8) | - plane0[((colorplus->cga.ma << 1) & 0x1fff) + ((colorplus->cga.sc & 1) * 0x2000) + 1]; - dat1 = (plane1[((colorplus->cga.ma << 1) & 0x1fff) + ((colorplus->cga.sc & 1) * 0x2000)] << 8) | - plane1[((colorplus->cga.ma << 1) & 0x1fff) + ((colorplus->cga.sc & 1) * 0x2000) + 1]; - colorplus->cga.ma++; - for (c = 0; c < 16; c++) - { - buffer->line[colorplus->cga.displine][(x << 4) + c + 8] = - cols[(dat0 >> 15) | ((dat1 >> 15) << 1)]; - dat0 <<= 1; - dat1 <<= 1; - } - } - } - } - else /* Top / bottom border */ - { - cols[0] = (colorplus->cga.cgacol & 15) + 16; - hline(buffer, 0, colorplus->cga.displine, (colorplus->cga.crtc[1] << 4) + 16, cols[0]); - } - x = (colorplus->cga.crtc[1] << 4) + 16; + for (x = 0; x < dev->cga.crtc[1]; x++) { + dat0 = (plane0[((dev->cga.ma << 1) & 0x1fff) + ((dev->cga.sc & 1) * 0x2000)] << 8) | + plane0[((dev->cga.ma << 1) & 0x1fff) + ((dev->cga.sc & 1) * 0x2000) + 1]; + dat1 = (plane1[((dev->cga.ma << 1) & 0x1fff) + ((dev->cga.sc & 1) * 0x2000)] << 8) | + plane1[((dev->cga.ma << 1) & 0x1fff) + ((dev->cga.sc & 1) * 0x2000) + 1]; + dev->cga.ma++; - if (colorplus->cga.composite) - { - for (c = 0; c < x; c++) - buffer32->line[colorplus->cga.displine][c] = buffer->line[colorplus->cga.displine][c] & 0xf; + for (c = 0; c < 16; c++) { + buffer->line[dev->cga.displine][(x << 4) + c + 8] = cols[(dat0 >> 15) | ((dat1 >> 15) << 1)]; + dat0 <<= 1; + dat1 <<= 1; + } + } + } + } else { /* Top / bottom border */ + cols[0] = (dev->cga.cgacol & 15) + 16; + cga_hline(buffer, 0, dev->cga.displine, (dev->cga.crtc[1] << 4) + 16, cols[0]); + } - Composite_Process(colorplus->cga.cgamode, 0, x >> 2, buffer32->line[colorplus->cga.displine]); - } + x = (dev->cga.crtc[1] << 4) + 16; - colorplus->cga.sc = oldsc; - if (colorplus->cga.vc == colorplus->cga.crtc[7] && !colorplus->cga.sc) - colorplus->cga.cgastat |= 8; - colorplus->cga.displine++; - if (colorplus->cga.displine >= 360) - colorplus->cga.displine = 0; - } - else - { - colorplus->cga.vidtime += colorplus->cga.dispontime; - colorplus->cga.linepos = 0; - if (colorplus->cga.vsynctime) - { - colorplus->cga.vsynctime--; - if (!colorplus->cga.vsynctime) - colorplus->cga.cgastat &= ~8; - } - if (colorplus->cga.sc == (colorplus->cga.crtc[11] & 31) || ((colorplus->cga.crtc[8] & 3) == 3 && colorplus->cga.sc == ((colorplus->cga.crtc[11] & 31) >> 1))) - { - colorplus->cga.con = 0; - colorplus->cga.coff = 1; - } - if ((colorplus->cga.crtc[8] & 3) == 3 && colorplus->cga.sc == (colorplus->cga.crtc[9] >> 1)) - colorplus->cga.maback = colorplus->cga.ma; - if (colorplus->cga.vadj) - { - colorplus->cga.sc++; - colorplus->cga.sc &= 31; - colorplus->cga.ma = colorplus->cga.maback; - colorplus->cga.vadj--; - if (!colorplus->cga.vadj) - { - colorplus->cga.cgadispon = 1; - colorplus->cga.ma = colorplus->cga.maback = (colorplus->cga.crtc[13] | (colorplus->cga.crtc[12] << 8)) & 0x3fff; - colorplus->cga.sc = 0; - } - } - else if (colorplus->cga.sc == colorplus->cga.crtc[9]) - { - colorplus->cga.maback = colorplus->cga.ma; - colorplus->cga.sc = 0; - oldvc = colorplus->cga.vc; - colorplus->cga.vc++; - colorplus->cga.vc &= 127; + if (dev->cga.composite) { + for (c = 0; c < x; c++) + buffer32->line[dev->cga.displine][c] = buffer->line[dev->cga.displine][c] & 0xf; - if (colorplus->cga.vc == colorplus->cga.crtc[6]) - colorplus->cga.cgadispon = 0; + Composite_Process(dev->cga.cgamode, 0, x >> 2, buffer32->line[dev->cga.displine]); + } - if (oldvc == colorplus->cga.crtc[4]) - { - colorplus->cga.vc = 0; - colorplus->cga.vadj = colorplus->cga.crtc[5]; - if (!colorplus->cga.vadj) colorplus->cga.cgadispon = 1; - if (!colorplus->cga.vadj) colorplus->cga.ma = colorplus->cga.maback = (colorplus->cga.crtc[13] | (colorplus->cga.crtc[12] << 8)) & 0x3fff; - if ((colorplus->cga.crtc[10] & 0x60) == 0x20) colorplus->cga.cursoron = 0; - else colorplus->cga.cursoron = colorplus->cga.cgablink & 8; - } + dev->cga.sc = oldsc; + if (dev->cga.vc == dev->cga.crtc[7] && !dev->cga.sc) + dev->cga.cgastat |= 8; - if (colorplus->cga.vc == colorplus->cga.crtc[7]) - { - colorplus->cga.cgadispon = 0; - colorplus->cga.displine = 0; - colorplus->cga.vsynctime = 16; - if (colorplus->cga.crtc[7]) - { - if (colorplus->cga.cgamode & 1) x = (colorplus->cga.crtc[1] << 3) + 16; - else x = (colorplus->cga.crtc[1] << 4) + 16; - colorplus->cga.lastline++; - if (x != xsize || (colorplus->cga.lastline - colorplus->cga.firstline) != ysize) - { - xsize = x; - ysize = colorplus->cga.lastline - colorplus->cga.firstline; - if (xsize < 64) xsize = 656; - if (ysize < 32) ysize = 200; - set_screen_size(xsize, (ysize << 1) + 16); - } - - if (colorplus->cga.composite) - video_blit_memtoscreen(0, colorplus->cga.firstline - 4, 0, (colorplus->cga.lastline - colorplus->cga.firstline) + 8, xsize, (colorplus->cga.lastline - colorplus->cga.firstline) + 8); - else - video_blit_memtoscreen_8(0, colorplus->cga.firstline - 4, 0, (colorplus->cga.lastline - colorplus->cga.firstline) + 8, xsize, (colorplus->cga.lastline - colorplus->cga.firstline) + 8); - frames++; + dev->cga.displine++; + if (dev->cga.displine >= 360) + dev->cga.displine = 0; + } else { + dev->cga.vidtime += dev->cga.dispontime; + dev->cga.linepos = 0; + if (dev->cga.vsynctime) { + dev->cga.vsynctime--; + if (! dev->cga.vsynctime) + dev->cga.cgastat &= ~8; + } - video_res_x = xsize - 16; - video_res_y = ysize; - if (colorplus->cga.cgamode & 1) - { - video_res_x /= 8; - video_res_y /= colorplus->cga.crtc[9] + 1; - video_bpp = 0; - } - else if (!(colorplus->cga.cgamode & 2)) - { - video_res_x /= 16; - video_res_y /= colorplus->cga.crtc[9] + 1; - video_bpp = 0; - } - else if (!(colorplus->cga.cgamode & 16)) - { - video_res_x /= 2; - video_bpp = 2; - } - else - { - video_bpp = 1; - } - } - colorplus->cga.firstline = 1000; - colorplus->cga.lastline = 0; - colorplus->cga.cgablink++; - colorplus->cga.oddeven ^= 1; - } - } - else - { - colorplus->cga.sc++; - colorplus->cga.sc &= 31; - colorplus->cga.ma = colorplus->cga.maback; - } - if (colorplus->cga.cgadispon) - colorplus->cga.cgastat &= ~1; - if ((colorplus->cga.sc == (colorplus->cga.crtc[10] & 31) || ((colorplus->cga.crtc[8] & 3) == 3 && colorplus->cga.sc == ((colorplus->cga.crtc[10] & 31) >> 1)))) - colorplus->cga.con = 1; - if (colorplus->cga.cgadispon && (colorplus->cga.cgamode & 1)) - { - for (x = 0; x < (colorplus->cga.crtc[1] << 1); x++) - colorplus->cga.charbuffer[x] = colorplus->cga.vram[(((colorplus->cga.ma << 1) + x) & 0x3fff)]; - } - } + if (dev->cga.sc == (dev->cga.crtc[11] & 31) || ((dev->cga.crtc[8] & 3) == 3 && dev->cga.sc == ((dev->cga.crtc[11] & 31) >> 1))) { + dev->cga.con = 0; + dev->cga.coff = 1; + } + + if ((dev->cga.crtc[8] & 3) == 3 && dev->cga.sc == (dev->cga.crtc[9] >> 1)) + dev->cga.maback = dev->cga.ma; + + if (dev->cga.vadj) { + dev->cga.sc++; + dev->cga.sc &= 31; + dev->cga.ma = dev->cga.maback; + dev->cga.vadj--; + if (! dev->cga.vadj) { + dev->cga.cgadispon = 1; + dev->cga.ma = dev->cga.maback = (dev->cga.crtc[13] | (dev->cga.crtc[12] << 8)) & 0x3fff; + dev->cga.sc = 0; + } + } else if (dev->cga.sc == dev->cga.crtc[9]) { + dev->cga.maback = dev->cga.ma; + dev->cga.sc = 0; + oldvc = dev->cga.vc; + dev->cga.vc++; + dev->cga.vc &= 127; + + if (dev->cga.vc == dev->cga.crtc[6]) + dev->cga.cgadispon = 0; + + if (oldvc == dev->cga.crtc[4]) { + dev->cga.vc = 0; + dev->cga.vadj = dev->cga.crtc[5]; + if (! dev->cga.vadj) + dev->cga.cgadispon = 1; + if (! dev->cga.vadj) + dev->cga.ma = dev->cga.maback = (dev->cga.crtc[13] | (dev->cga.crtc[12] << 8)) & 0x3fff; + if ((dev->cga.crtc[10] & 0x60) == 0x20) + dev->cga.cursoron = 0; + else + dev->cga.cursoron = dev->cga.cgablink & 8; + } + + if (dev->cga.vc == dev->cga.crtc[7]) { + dev->cga.cgadispon = 0; + dev->cga.displine = 0; + dev->cga.vsynctime = 16; + if (dev->cga.crtc[7]) { + if (dev->cga.cgamode & 1) + x = (dev->cga.crtc[1] << 3) + 16; + else + x = (dev->cga.crtc[1] << 4) + 16; + dev->cga.lastline++; + + if (x != xsize || (dev->cga.lastline - dev->cga.firstline) != ysize) { + xsize = x; + ysize = dev->cga.lastline - dev->cga.firstline; + if (xsize < 64) xsize = 656; + if (ysize < 32) ysize = 200; + set_screen_size(xsize, (ysize << 1) + 16); + } + + if (dev->cga.composite) + video_blit_memtoscreen(0, dev->cga.firstline - 4, 0, (dev->cga.lastline - dev->cga.firstline) + 8, xsize, (dev->cga.lastline - dev->cga.firstline) + 8); + else + video_blit_memtoscreen_8(0, dev->cga.firstline - 4, 0, (dev->cga.lastline - dev->cga.firstline) + 8, xsize, (dev->cga.lastline - dev->cga.firstline) + 8); + frames++; + + video_res_x = xsize - 16; + video_res_y = ysize; + if (dev->cga.cgamode & 1) { + video_res_x /= 8; + video_res_y /= dev->cga.crtc[9] + 1; + video_bpp = 0; + } else if (!(dev->cga.cgamode & 2)) { + video_res_x /= 16; + video_res_y /= dev->cga.crtc[9] + 1; + video_bpp = 0; + } else if (!(dev->cga.cgamode & 16)) { + video_res_x /= 2; + video_bpp = 2; + } else { + video_bpp = 1; + } + } + dev->cga.firstline = 1000; + dev->cga.lastline = 0; + dev->cga.cgablink++; + dev->cga.oddeven ^= 1; + } + } else { + dev->cga.sc++; + dev->cga.sc &= 31; + dev->cga.ma = dev->cga.maback; + } + + if (dev->cga.cgadispon) + dev->cga.cgastat &= ~1; + if ((dev->cga.sc == (dev->cga.crtc[10] & 31) || ((dev->cga.crtc[8] & 3) == 3 && dev->cga.sc == ((dev->cga.crtc[10] & 31) >> 1)))) + dev->cga.con = 1; + + if (dev->cga.cgadispon && (dev->cga.cgamode & 1)) { + for (x = 0; x < (dev->cga.crtc[1] << 1); x++) + dev->cga.charbuffer[x] = dev->cga.vram[(((dev->cga.ma << 1) + x) & 0x3fff)]; + } + } } static void * colorplus_init(const device_t *info) { - int display_type; - colorplus_t *colorplus = malloc(sizeof(colorplus_t)); + colorplus_t *dev; + int display_type; - memset(colorplus, 0, sizeof(colorplus_t)); + dev = (colorplus_t *)mem_alloc(sizeof(colorplus_t)); + memset(dev, 0x00, sizeof(colorplus_t)); - /* Copied from the CGA init. Ideally this would be done by - * calling a helper function rather than duplicating code */ - display_type = device_get_config_int("display_type"); - colorplus->cga.composite = (display_type != CGA_RGB); - colorplus->cga.revision = device_get_config_int("composite_type"); - colorplus->cga.snow_enabled = device_get_config_int("snow_enabled"); + /* Copied from the CGA init. Ideally this would be done by + * calling a helper function rather than duplicating code. + */ + display_type = device_get_config_int("display_type"); + dev->cga.composite = (display_type != CGA_RGB); + dev->cga.revision = device_get_config_int("composite_type"); + dev->cga.snow_enabled = device_get_config_int("snow_enabled"); - colorplus->cga.vram = malloc(0x8000); - - cga_comp_init(1); - timer_add(colorplus_poll, &colorplus->cga.vidtime, TIMER_ALWAYS_ENABLED, colorplus); - mem_mapping_add(&colorplus->cga.mapping, 0xb8000, 0x08000, colorplus_read, NULL, NULL, colorplus_write, NULL, NULL, NULL, MEM_MAPPING_EXTERNAL, colorplus); - io_sethandler(0x03d0, 0x0010, colorplus_in, NULL, NULL, colorplus_out, NULL, NULL, colorplus); + dev->cga.vram = (uint8_t *)mem_alloc(0x8000); + + cga_comp_init(1); - /* Force the LPT3 port to be enabled. */ - parallel_enabled[2] = 1; - parallel_setup(3, 0x3BC); + timer_add(colorplus_poll, &dev->cga.vidtime, TIMER_ALWAYS_ENABLED, dev); - return colorplus; + mem_map_add(&dev->cga.mapping, 0xb8000, 0x08000, + colorplus_read,NULL,NULL, colorplus_write,NULL,NULL, + NULL, MEM_MAPPING_EXTERNAL, dev); + + io_sethandler(0x03d0, 16, + colorplus_in,NULL,NULL, colorplus_out,NULL,NULL, dev); + + video_inform(VID_TYPE_CGA, info->vid_timing); + + /* Force the LPT3 port to be enabled. */ + parallel_enabled[2] = 1; + parallel_setup(3, 0x3BC); + + return dev; } static void -colorplus_close(void *p) +colorplus_close(void *priv) { - colorplus_t *colorplus = (colorplus_t *)p; + colorplus_t *dev = (colorplus_t *)priv; - free(colorplus->cga.vram); - free(colorplus); + free(dev->cga.vram); + free(dev); } static void -colorplus_speed_changed(void *p) +speed_changed(void *priv) { - colorplus_t *colorplus = (colorplus_t *)p; - - cga_recalctimings(&colorplus->cga); + colorplus_t *dev = (colorplus_t *)priv; + + cga_recalctimings(&dev->cga); } -static const device_config_t colorplus_config[] = -{ - { - "display_type", "Display type", CONFIG_SELECTION, "", CGA_RGB, - { - { - "RGB", CGA_RGB - }, - { - "Composite", CGA_COMPOSITE - }, - { - "" - } - } - }, - { - "composite_type", "Composite type", CONFIG_SELECTION, "", COMPOSITE_OLD, - { - { - "Old", COMPOSITE_OLD - }, - { - "New", COMPOSITE_NEW - }, - { - "" - } - } - }, - { - "snow_enabled", "Snow emulation", CONFIG_BINARY, "", 1 - }, - { - "", "", -1 - } +static const device_config_t colorplus_config[] = { + { + "display_type", "Display type", CONFIG_SELECTION, "", CGA_RGB, + { + { + "RGB", CGA_RGB + }, + { + "Composite", CGA_COMPOSITE + }, + { + "" + } + } + }, + { + "composite_type", "Composite type", CONFIG_SELECTION, "", COMPOSITE_OLD, + { + { + "Old", COMPOSITE_OLD + }, + { + "New", COMPOSITE_NEW + }, + { + "" + } + } + }, + { + "snow_enabled", "Snow emulation", CONFIG_BINARY, "", 1 + }, + { + "", "", -1 + } }; +static const video_timings_t colorplus_timings = { VID_ISA,8,16,32,8,16,32 }; const device_t colorplus_device = { "Plantronics ColorPlus", @@ -503,7 +481,8 @@ const device_t colorplus_device = { 0, colorplus_init, colorplus_close, NULL, NULL, - colorplus_speed_changed, - NULL, NULL, + speed_changed, + NULL, + &colorplus_timings, colorplus_config }; diff --git a/src/devices/video/vid_compaq_cga.c b/src/devices/video/vid_compaq_cga.c deleted file mode 100644 index 132c98e..0000000 --- a/src/devices/video/vid_compaq_cga.c +++ /dev/null @@ -1,502 +0,0 @@ -/* - * VARCem Virtual ARchaeological Computer EMulator. - * An emulator of (mostly) x86-based PC systems and devices, - * using the ISA,EISA,VLB,MCA and PCI system buses, roughly - * spanning the era between 1981 and 1995. - * - * This file is part of the VARCem Project. - * - * Implementation of CGA used by Compaq PC's. - * - * Version: @(#)vid_cga_compaq.c 1.0.4 2018/05/06 - * - * Authors: Fred N. van Kempen, - * Miran Grca, - * TheCollector1995, - * - * Copyright 2017,2018 Fred N. van Kempen. - * Copyright 2016-2018 Miran Grca. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the: - * - * Free Software Foundation, Inc. - * 59 Temple Place - Suite 330 - * Boston, MA 02111-1307 - * USA. - */ -#include -#include -#include -#include -#include -#include -#include "../../emu.h" -#include "../../cpu/cpu.h" -#include "../../io.h" -#include "../../mem.h" -#include "../../rom.h" -#include "../../timer.h" -#include "../../device.h" -#include "../system/pit.h" -#include "video.h" -#include "vid_cga.h" -#include "vid_cga_comp.h" - - -#define CGA_RGB 0 -#define CGA_COMPOSITE 1 - - -typedef struct -{ - cga_t cga; - uint32_t flags; -} compaq_cga_t; - -static uint8_t mdaattr[256][2][2]; - -void compaq_cga_recalctimings(compaq_cga_t *self) -{ - double _dispontime, _dispofftime, disptime; - disptime = self->cga.crtc[0] + 1; - _dispontime = self->cga.crtc[1]; - _dispofftime = disptime - _dispontime; - _dispontime *= MDACONST; - _dispofftime *= MDACONST; - self->cga.dispontime = (int)(_dispontime * (1 << TIMER_SHIFT)); - self->cga.dispofftime = (int)(_dispofftime * (1 << TIMER_SHIFT)); -} - -void compaq_cga_poll(void *p) -{ - compaq_cga_t *self = (compaq_cga_t *)p; - uint16_t ca = (self->cga.crtc[15] | (self->cga.crtc[14] << 8)) & 0x3fff; - int drawcursor; - int x, c; - int oldvc; - uint8_t chr, attr; - uint32_t cols[4]; - int oldsc; - int underline = 0; - int blink = 0; - - /* If in graphics mode or character height is not 13, behave as CGA */ - if ((self->cga.cgamode & 0x12) || (self->cga.crtc[9] != 13)) - { - overscan_x = overscan_y = 16; - cga_poll(&self->cga); - return; - } else - overscan_x = overscan_y = 0; - -/* We are in Compaq 350-line CGA territory */ - if (!self->cga.linepos) - { - self->cga.vidtime += self->cga.dispofftime; - self->cga.cgastat |= 1; - self->cga.linepos = 1; - oldsc = self->cga.sc; - if ((self->cga.crtc[8] & 3) == 3) - self->cga.sc = ((self->cga.sc << 1) + self->cga.oddeven) & 7; - if (self->cga.cgadispon) - { - if (self->cga.displine < self->cga.firstline) - { - self->cga.firstline = self->cga.displine; - video_wait_for_buffer(); -// printf("Firstline %i\n",firstline); - } - self->cga.lastline = self->cga.displine; - - cols[0] = (self->cga.cgacol & 15); - - for (c = 0; c < 8; c++) - { - ((uint32_t *)buffer32->line[self->cga.displine])[c] = cols[0]; - if (self->cga.cgamode & 1) - ((uint32_t *)buffer32->line[self->cga.displine])[c + (self->cga.crtc[1] << 3) + 8] = cols[0]; - else - ((uint32_t *)buffer32->line[self->cga.displine])[c + (self->cga.crtc[1] << 4) + 8] = cols[0]; - } - if (self->cga.cgamode & 1) - { - for (x = 0; x < self->cga.crtc[1]; x++) - { - chr = self->cga.charbuffer[x << 1]; - attr = self->cga.charbuffer[(x << 1) + 1]; - drawcursor = ((self->cga.ma == ca) && self->cga.con && self->cga.cursoron); - if (self->flags) { - underline = 0; - blink = ((self->cga.cgablink & 8) && (self->cga.cgamode & 0x20) && (attr & 0x80) && !drawcursor); - } - if (self->flags && (self->cga.cgamode & 0x80)) - { - cols[0] = mdaattr[attr][blink][0]; - cols[1] = mdaattr[attr][blink][1]; - if (self->cga.sc == 12 && (attr & 7) == 1) underline = 1; - } - else if (self->cga.cgamode & 0x20) - { - cols[1] = (attr & 15) + 16; - cols[0] = ((attr >> 4) & 7) + 16; - if (self->flags) { - if (blink) - cols[1] = cols[0]; - } else { - if ((self->cga.cgablink & 8) && (attr & 0x80) && !self->cga.drawcursor) - cols[1] = cols[0]; - } - } - else - { - cols[1] = (attr & 15) + 16; - cols[0] = (attr >> 4) + 16; - } - if (self->flags && underline) - { - for (c = 0; c < 8; c++) - ((uint32_t *)buffer32->line[self->cga.displine])[(x << 3) + c + 8] = mdaattr[attr][blink][1]; - } - else if (drawcursor) - { - for (c = 0; c < 8; c++) - ((uint32_t *)buffer32->line[self->cga.displine])[(x << 3) + c + 8] = cols[(fontdatm[chr + self->cga.fontbase][self->cga.sc & 15] & (1 << (c ^ 7))) ? 1 : 0] ^ 0xffffff; - } - else - { - for (c = 0; c < 8; c++) - ((uint32_t *)buffer32->line[self->cga.displine])[(x << 3) + c + 8] = cols[(fontdatm[chr + self->cga.fontbase][self->cga.sc & 15] & (1 << (c ^ 7))) ? 1 : 0]; - } - self->cga.ma++; - } - } - else - { - for (x = 0; x < self->cga.crtc[1]; x++) - { - chr = self->cga.vram[((self->cga.ma << 1) & 0x3fff)]; - attr = self->cga.vram[(((self->cga.ma << 1) + 1) & 0x3fff)]; - drawcursor = ((self->cga.ma == ca) && self->cga.con && self->cga.cursoron); - if (self->flags) { - underline = 0; - blink = ((self->cga.cgablink & 8) && (self->cga.cgamode & 0x20) && (attr & 0x80) && !drawcursor); - } - if (self->flags && (self->cga.cgamode & 0x80)) - { - cols[0] = mdaattr[attr][blink][0]; - cols[1] = mdaattr[attr][blink][1]; - if (self->cga.sc == 12 && (attr & 7) == 1) underline = 1; - } - else if (self->cga.cgamode & 0x20) - { - cols[1] = (attr & 15) + 16; - cols[0] = ((attr >> 4) & 7) + 16; - if (self->flags) { - if (blink) - cols[1] = cols[0]; - } else { - if ((self->cga.cgablink & 8) && (attr & 0x80) && !self->cga.drawcursor) - cols[1] = cols[0]; - } - } - else - { - cols[1] = (attr & 15) + 16; - cols[0] = (attr >> 4) + 16; - } - self->cga.ma++; - if (self->flags && underline) - { - for (c = 0; c < 8; c++) - ((uint32_t *)buffer32->line[self->cga.displine])[(x << 4)+(c << 1) + 8] = - ((uint32_t *)buffer32->line[self->cga.displine])[(x << 4)+(c << 1) + 9] = mdaattr[attr][blink][1]; - } - else if (drawcursor) - { - for (c = 0; c < 8; c++) - ((uint32_t *)buffer32->line[self->cga.displine])[(x << 4)+(c << 1) + 8] = - ((uint32_t *)buffer32->line[self->cga.displine])[(x << 4) + (c << 1) + 1 + 8] = cols[(fontdatm[chr + self->cga.fontbase][self->cga.sc & 15] & (1 << (c ^ 7))) ? 1 : 0] ^ 15; - } - else - { - for (c = 0; c < 8; c++) - ((uint32_t *)buffer32->line[self->cga.displine])[(x << 4) + (c << 1) + 8] = - ((uint32_t *)buffer32->line[self->cga.displine])[(x << 4) + (c << 1) + 1 + 8] = cols[(fontdatm[chr + self->cga.fontbase][self->cga.sc & 15] & (1 << (c ^ 7))) ? 1 : 0]; - } - } - } - } - else - { - cols[0] = (self->cga.cgacol & 15) + 16; - if (self->cga.cgamode & 1) hline(buffer32, 0, self->cga.displine, (self->cga.crtc[1] << 3) + 16, cols[0]); - else hline(buffer32, 0, self->cga.displine, (self->cga.crtc[1] << 4) + 16, cols[0]); - } - - if (self->cga.cgamode & 1) x = (self->cga.crtc[1] << 3) + 16; - else x = (self->cga.crtc[1] << 4) + 16; - - if (self->cga.composite) - { - for (c = 0; c < x; c++) - buffer32->line[self->cga.displine][c] = ((uint32_t *)buffer32->line[self->cga.displine])[c] & 0xf; - - if (self->flags) - Composite_Process(self->cga.cgamode & 0x7F, 0, x >> 2, buffer32->line[self->cga.displine]); - else - Composite_Process(self->cga.cgamode, 0, x >> 2, buffer32->line[self->cga.displine]); - } - else - { - for (c = 0; c < x; c++) - buffer->line[self->cga.displine][c] = ((uint32_t *)buffer32->line[self->cga.displine])[c]; - } - - self->cga.sc = oldsc; - if (self->cga.vc == self->cga.crtc[7] && !self->cga.sc) - self->cga.cgastat |= 8; - self->cga.displine++; - if (self->cga.displine >= 500) - self->cga.displine = 0; - } - else - { - self->cga.vidtime += self->cga.dispontime; - self->cga.linepos = 0; - if (self->cga.vsynctime) - { - self->cga.vsynctime--; - if (!self->cga.vsynctime) - self->cga.cgastat &= ~8; - } - if (self->cga.sc == (self->cga.crtc[11] & 31) || ((self->cga.crtc[8] & 3) == 3 && self->cga.sc == ((self->cga.crtc[11] & 31) >> 1))) - { - self->cga.con = 0; - self->cga.coff = 1; - } - if ((self->cga.crtc[8] & 3) == 3 && self->cga.sc == (self->cga.crtc[9] >> 1)) - self->cga.maback = self->cga.ma; - if (self->cga.vadj) - { - self->cga.sc++; - self->cga.sc &= 31; - self->cga.ma = self->cga.maback; - self->cga.vadj--; - if (!self->cga.vadj) - { - self->cga.cgadispon = 1; - self->cga.ma = self->cga.maback = (self->cga.crtc[13] | (self->cga.crtc[12] << 8)) & 0x3fff; - self->cga.sc = 0; - } - } - else if (self->cga.sc == self->cga.crtc[9]) - { - self->cga.maback = self->cga.ma; - self->cga.sc = 0; - oldvc = self->cga.vc; - self->cga.vc++; - self->cga.vc &= 127; - - if (self->cga.vc == self->cga.crtc[6]) - self->cga.cgadispon = 0; - - if (oldvc == self->cga.crtc[4]) - { - self->cga.vc = 0; - self->cga.vadj = self->cga.crtc[5]; - if (!self->cga.vadj) self->cga.cgadispon = 1; - if (!self->cga.vadj) self->cga.ma = self->cga.maback = (self->cga.crtc[13] | (self->cga.crtc[12] << 8)) & 0x3fff; - if ((self->cga.crtc[10] & 0x60) == 0x20) self->cga.cursoron = 0; - else self->cga.cursoron = self->cga.cgablink & 8; - } - - if (self->cga.vc == self->cga.crtc[7]) - { - self->cga.cgadispon = 0; - self->cga.displine = 0; - self->cga.vsynctime = 16; - if (self->cga.crtc[7]) - { -// printf("Lastline %i Firstline %i %i\n",self->cga.lastline,self->cga.firstline,self->cga.lastline-self->cga.firstline); - - if (self->cga.cgamode & 1) x = (self->cga.crtc[1] << 3); - else x = (self->cga.crtc[1] << 4); - self->cga.lastline++; - if (x != xsize || (self->cga.lastline - self->cga.firstline) != ysize) - { - xsize = x; - ysize = self->cga.lastline - self->cga.firstline; -// printf("Resize to %i,%i - R1 %i\n",xsize,ysize,self->cga.crtc[1]); - - if (xsize < 64) xsize = 656; - if (ysize < 32) ysize = 200; - set_screen_size(xsize, ysize); - } - - if (self->cga.composite) - video_blit_memtoscreen(8, self->cga.firstline, 0, ysize, xsize, ysize); - else - video_blit_memtoscreen_8(8, self->cga.firstline, 0, ysize, xsize, ysize); - frames++; - - video_res_x = xsize - 16; - video_res_y = ysize; - if (self->cga.cgamode & 1) - { - video_res_x /= 8; - video_res_y /= self->cga.crtc[9] + 1; - video_bpp = 0; - } - else if (!(self->cga.cgamode & 2)) - { - video_res_x /= 16; - video_res_y /= self->cga.crtc[9] + 1; - video_bpp = 0; - } - else if (!(self->cga.cgamode & 16)) - { - video_res_x /= 2; - video_bpp = 2; - } - else - { - video_bpp = 1; - } - } - self->cga.firstline = 1000; - self->cga.lastline = 0; - self->cga.cgablink++; - self->cga.oddeven ^= 1; - } - } - else - { - self->cga.sc++; - self->cga.sc &= 31; - self->cga.ma = self->cga.maback; - } - if (self->cga.cgadispon) - self->cga.cgastat &= ~1; - if ((self->cga.sc == (self->cga.crtc[10] & 31) || ((self->cga.crtc[8] & 3) == 3 && self->cga.sc == ((self->cga.crtc[10] & 31) >> 1)))) - self->cga.con = 1; - if (self->cga.cgadispon && (self->cga.cgamode & 1)) - { - for (x = 0; x < (self->cga.crtc[1] << 1); x++) - self->cga.charbuffer[x] = self->cga.vram[(((self->cga.ma << 1) + x) & 0x3fff)]; - } - } - -} - -void *compaq_cga_init(const device_t *info) -{ - int display_type; - int c; - compaq_cga_t *self = malloc(sizeof(compaq_cga_t)); - memset(self, 0, sizeof(compaq_cga_t)); - - display_type = device_get_config_int("display_type"); - self->cga.composite = (display_type != CGA_RGB); - self->cga.revision = device_get_config_int("composite_type"); - self->cga.snow_enabled = device_get_config_int("snow_enabled"); - - self->cga.vram = malloc(0x4000); - - cga_comp_init(self->cga.revision); - timer_add(compaq_cga_poll, &self->cga.vidtime, TIMER_ALWAYS_ENABLED, self); - mem_mapping_add(&self->cga.mapping, 0xb8000, 0x08000, cga_read, NULL, NULL, cga_write, NULL, NULL, NULL, MEM_MAPPING_EXTERNAL, self); - io_sethandler(0x03d0, 0x0010, cga_in, NULL, NULL, cga_out, NULL, NULL, self); - - if (info->local) { - for (c = 0; c < 256; c++) { - mdaattr[c][0][0] = mdaattr[c][1][0] = mdaattr[c][1][1] = 16; - if (c & 8) mdaattr[c][0][1] = 15 + 16; - else mdaattr[c][0][1] = 7 + 16; - } - mdaattr[0x70][0][1] = 16; - mdaattr[0x70][0][0] = mdaattr[0x70][1][0] = mdaattr[0x70][1][1] = 16 + 15; - mdaattr[0xF0][0][1] = 16; - mdaattr[0xF0][0][0] = mdaattr[0xF0][1][0] = mdaattr[0xF0][1][1] = 16 + 15; - mdaattr[0x78][0][1] = 16 + 7; - mdaattr[0x78][0][0] = mdaattr[0x78][1][0] = mdaattr[0x78][1][1] = 16 + 15; - mdaattr[0xF8][0][1] = 16 + 7; - mdaattr[0xF8][0][0] = mdaattr[0xF8][1][0] = mdaattr[0xF8][1][1] = 16 + 15; - mdaattr[0x00][0][1] = mdaattr[0x00][1][1] = 16; - mdaattr[0x08][0][1] = mdaattr[0x08][1][1] = 16; - mdaattr[0x80][0][1] = mdaattr[0x80][1][1] = 16; - mdaattr[0x88][0][1] = mdaattr[0x88][1][1] = 16; - } - - self->flags = info->local; - - overscan_x = overscan_y = 16; - - self->cga.rgb_type = device_get_config_int("rgb_type"); - cga_palette = (self->cga.rgb_type << 1); - cgapal_rebuild(); - - return self; -} - -void compaq_cga_close(void *p) -{ - compaq_cga_t *self = (compaq_cga_t *)p; - - free(self->cga.vram); - free(self); -} - -void compaq_cga_speed_changed(void *p) -{ - compaq_cga_t *self = (compaq_cga_t *)p; - - if (self->cga.crtc[9] == 13) /* Character height */ - { - compaq_cga_recalctimings(self); - } - else - { - cga_recalctimings(&self->cga); - } -} - -extern const device_config_t cga_config[]; - -const device_t compaq_cga_device = -{ - "Compaq CGA", - DEVICE_ISA, 0, - compaq_cga_init, - compaq_cga_close, - NULL, - NULL, - compaq_cga_speed_changed, - NULL, - NULL, - cga_config -}; - -const device_t compaq_cga_2_device = -{ - "Compaq CGA 2", - DEVICE_ISA, 1, - compaq_cga_init, - compaq_cga_close, - NULL, - NULL, - compaq_cga_speed_changed, - NULL, - NULL, - cga_config -}; diff --git a/src/devices/video/vid_ega.c b/src/devices/video/vid_ega.c index 414a09a..f59a02c 100644 --- a/src/devices/video/vid_ega.c +++ b/src/devices/video/vid_ega.c @@ -9,7 +9,7 @@ * Emulation of the EGA, Chips & Technologies SuperEGA, and * AX JEGA graphics cards. * - * Version: @(#)vid_ega.c 1.0.8 2018/05/06 + * Version: @(#)vid_ega.c 1.0.9 2018/09/22 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -61,1257 +61,1292 @@ enum { - EGA_IBM = 0, - EGA_COMPAQ, - EGA_SUPEREGA + EGA_IBM = 0, + EGA_COMPAQ, + EGA_SUPEREGA }; -extern uint8_t edatlookup[4][4]; - -static uint8_t ega_rotate[8][256]; - -static uint32_t pallook16[256], pallook64[256]; - -/*3C2 controls default mode on EGA. On VGA, it determines monitor type (mono or colour)*/ -int egaswitchread,egaswitches=9; /*7=CGA mode (200 lines), 9=EGA mode (350 lines), 8=EGA mode (200 lines)*/ - -static int old_overscan_color = 0; - +static uint8_t ega_rotate[8][256]; +static uint32_t pallook16[256], + pallook64[256]; +static int old_overscan_color = 0; +static int egaswitchread, + egaswitches = 9; /*7=CGA mode (200 lines), + *9=EGA mode (350 lines), + *8=EGA mode (200 lines)*/ #ifdef JEGA -uint8_t jfont_sbcs_19[SBCS19_LEN]; /* 256 * 19( * 8) */ -uint8_t jfont_dbcs_16[DBCS16_LEN]; /* 65536 * 16 * 2 (* 8) */ +static uint8_t jfont_sbcs_19[SBCS19_LEN]; /* 256 * 19( * 8) */ +static uint8_t jfont_dbcs_16[DBCS16_LEN]; /* 65536 * 16 * 2 (* 8) */ typedef struct { - char id[ID_LEN]; - char name[NAME_LEN]; - unsigned char width; - unsigned char height; - unsigned char type; + char id[ID_LEN]; + char name[NAME_LEN]; + uint8_t width; + uint8_t height; + uint8_t type; } fontx_h; typedef struct { - uint16_t start; - uint16_t end; + uint16_t start; + uint16_t end; } fontxTbl; static __inline int ega_jega_enabled(ega_t *ega) { - if (!ega->is_jega) - { + if (! ega->is_jega) return 0; - } - return !(ega->RMOD1 & 0x40); + return !(ega->RMOD1 & 0x40); } -void ega_jega_write_font(ega_t *ega) + +void +ega_jega_write_font(ega_t *ega) { - unsigned int chr = ega->RDFFB; - unsigned int chr_2 = ega->RDFSB; + unsigned int chr = ega->RDFFB; + unsigned int chr_2 = ega->RDFSB; - ega->RSTAT &= ~0x02; + ega->RSTAT &= ~0x02; - /* Check if the character code is in the Wide character set of Shift-JIS */ - if (((chr >= 0x40) && (chr <= 0x7e)) || ((chr >= 0x80) && (chr <= 0xfc))) - { - if (ega->font_index >= 32) - { - ega->font_index = 0; - } - chr <<= 8; - /* Fix vertical character position */ - chr |= chr_2; - if (ega->font_index < 16) - { - jfont_dbcs_16[(chr * 32) + (ega->font_index * 2)] = ega->RDFAP; /* 16x16 font */ - } - else - { - jfont_dbcs_16[(chr * 32) + ((ega->font_index - 16) * 2) + 1] = ega->RDFAP; /* 16x16 font */ - } + /* Check if the character code is in the Wide character set of Shift-JIS */ + if (((chr >= 0x40) && (chr <= 0x7e)) || ((chr >= 0x80) && (chr <= 0xfc))) { + if (ega->font_index >= 32) + ega->font_index = 0; + chr <<= 8; + + /* Fix vertical character position */ + chr |= chr_2; + if (ega->font_index < 16) { + jfont_dbcs_16[(chr * 32) + (ega->font_index * 2)] = ega->RDFAP; /* 16x16 font */ + } else { + jfont_dbcs_16[(chr * 32) + ((ega->font_index - 16) * 2) + 1] = ega->RDFAP; /* 16x16 font */ } - else - { - if (ega->font_index >= 19) - { - ega->font_index = 0; - } - jfont_sbcs_19[(chr * 19) + ega->font_index] = ega->RDFAP; /* 8x19 font */ - } - ega->font_index++; - ega->RSTAT |= 0x02; + } else { + if (ega->font_index >= 19) + ega->font_index = 0; + jfont_sbcs_19[(chr * 19) + ega->font_index] = ega->RDFAP; /* 8x19 font */ + } + ega->font_index++; + ega->RSTAT |= 0x02; } -void ega_jega_read_font(ega_t *ega) + +void +ega_jega_read_font(ega_t *ega) { - unsigned int chr = ega->RDFFB; - unsigned int chr_2 = ega->RDFSB; + unsigned int chr = ega->RDFFB; + unsigned int chr_2 = ega->RDFSB; - ega->RSTAT &= ~0x02; + ega->RSTAT &= ~0x02; - /* Check if the character code is in the Wide character set of Shift-JIS */ - if (((chr >= 0x40) && (chr <= 0x7e)) || ((chr >= 0x80) && (chr <= 0xfc))) - { - if (ega->font_index >= 32) - { - ega->font_index = 0; - } - chr <<= 8; - /* Fix vertical character position */ - chr |= chr_2; - if (ega->font_index < 16) - { - ega->RDFAP = jfont_dbcs_16[(chr * 32) + (ega->font_index * 2)]; /* 16x16 font */ - } - else - { - ega->RDFAP = jfont_dbcs_16[(chr * 32) + ((ega->font_index - 16) * 2) + 1]; /* 16x16 font */ - } + /* Check if the character code is in the Wide character set of Shift-JIS */ + if (((chr >= 0x40) && (chr <= 0x7e)) || ((chr >= 0x80) && (chr <= 0xfc))) { + if (ega->font_index >= 32) + ega->font_index = 0; + chr <<= 8; + + /* Fix vertical character position */ + chr |= chr_2; + if (ega->font_index < 16) { + ega->RDFAP = jfont_dbcs_16[(chr * 32) + (ega->font_index * 2)]; /* 16x16 font */ + } else { + ega->RDFAP = jfont_dbcs_16[(chr * 32) + ((ega->font_index - 16) * 2) + 1]; /* 16x16 font */ } - else - { - if (ega->font_index >= 19) - { - ega->font_index = 0; - } - ega->RDFAP = jfont_sbcs_19[(chr * 19) + ega->font_index]; /* 8x19 font */ - } - ega->font_index++; - ega->RSTAT |= 0x02; + } else { + if (ega->font_index >= 19) + ega->font_index = 0; + ega->RDFAP = jfont_sbcs_19[(chr * 19) + ega->font_index]; /* 8x19 font */ + } + ega->font_index++; + ega->RSTAT |= 0x02; } #endif -void ega_out(uint16_t addr, uint8_t val, void *p) +void +ega_recalctimings(ega_t *dev) { - ega_t *ega = (ega_t *)p; - int c; - uint8_t o, old; - - if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(ega->miscout & 1)) - addr ^= 0x60; - - switch (addr) - { - case 0x3c0: - case 0x3c1: - if (!ega->attrff) - ega->attraddr = val & 31; - else - { - ega->attrregs[ega->attraddr & 31] = val; - if (ega->attraddr < 16) - fullchange = changeframecount; - if (ega->attraddr == 0x10 || ega->attraddr == 0x14 || ega->attraddr < 0x10) - { - for (c = 0; c < 16; c++) - { - if (ega->attrregs[0x10] & 0x80) ega->egapal[c] = (ega->attrregs[c] & 0xf) | ((ega->attrregs[0x14] & 0xf) << 4); - else ega->egapal[c] = (ega->attrregs[c] & 0x3f) | ((ega->attrregs[0x14] & 0xc) << 4); - } - } - } - ega->attrff ^= 1; - break; - case 0x3c2: - egaswitchread = val & 0xc; - ega->vres = !(val & 0x80); - ega->pallook = ega->vres ? pallook16 : pallook64; - ega->vidclock = val & 4; /*printf("3C2 write %02X\n",val);*/ - ega->miscout=val; - break; - case 0x3c4: - ega->seqaddr = val; - break; - case 0x3c5: - o = ega->seqregs[ega->seqaddr & 0xf]; - ega->seqregs[ega->seqaddr & 0xf] = val; - if (o != val && (ega->seqaddr & 0xf) == 1) - ega_recalctimings(ega); - switch (ega->seqaddr & 0xf) - { - case 1: - if (ega->scrblank && !(val & 0x20)) - fullchange = 3; - ega->scrblank = (ega->scrblank & ~0x20) | (val & 0x20); - break; - case 2: - ega->writemask = val & 0xf; - break; - case 3: - ega->charsetb = (((val >> 2) & 3) * 0x10000) + 2; - ega->charseta = ((val & 3) * 0x10000) + 2; - break; - case 4: - ega->chain2_write = !(val & 4); - break; - } - break; - case 0x3ce: - ega->gdcaddr = val; - break; - case 0x3cf: - ega->gdcreg[ega->gdcaddr & 15] = val; - switch (ega->gdcaddr & 15) - { - case 2: - ega->colourcompare = val; - break; - case 4: - ega->readplane = val & 3; - break; - case 5: - ega->writemode = val & 3; - ega->readmode = val & 8; - ega->chain2_read = val & 0x10; - break; - case 6: - switch (val & 0xc) - { - case 0x0: /*128k at A0000*/ - mem_mapping_set_addr(&ega->mapping, 0xa0000, 0x20000); - break; - case 0x4: /*64k at A0000*/ - mem_mapping_set_addr(&ega->mapping, 0xa0000, 0x10000); - break; - case 0x8: /*32k at B0000*/ - mem_mapping_set_addr(&ega->mapping, 0xb0000, 0x08000); - break; - case 0xC: /*32k at B8000*/ - mem_mapping_set_addr(&ega->mapping, 0xb8000, 0x08000); - break; - } - break; - case 7: - ega->colournocare = val; - break; - } - break; - case 0x3d0: - case 0x3d4: - ega->crtcreg = val & 31; - return; - case 0x3d1: - case 0x3d5: - if (ega->crtcreg <= 7 && ega->crtc[0x11] & 0x80) return; - old = ega->crtc[ega->crtcreg]; - ega->crtc[ega->crtcreg] = val; - if (old != val) - { - if (ega->crtcreg < 0xe || ega->crtcreg > 0x10) - { - fullchange = changeframecount; - ega_recalctimings(ega); - } - } - break; - } -} + double _dispontime, _dispofftime, disptime; + double crtcconst; -uint8_t ega_in(uint16_t addr, void *p) -{ - ega_t *ega = (ega_t *)p; + dev->vtotal = dev->crtc[6]; + dev->dispend = dev->crtc[0x12]; + dev->vsyncstart = dev->crtc[0x10]; + dev->split = dev->crtc[0x18]; - if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(ega->miscout & 1)) - addr ^= 0x60; + if (dev->crtc[7] & 1) dev->vtotal |= 0x100; + if (dev->crtc[7] & 32) dev->vtotal |= 0x200; + dev->vtotal += 2; - switch (addr) - { - case 0x3c0: - return ega->attraddr; - case 0x3c1: - return ega->attrregs[ega->attraddr]; - case 0x3c2: - switch (egaswitchread) - { - case 0xc: return (egaswitches & 1) ? 0x10 : 0; - case 0x8: return (egaswitches & 2) ? 0x10 : 0; - case 0x4: return (egaswitches & 4) ? 0x10 : 0; - case 0x0: return (egaswitches & 8) ? 0x10 : 0; - } - break; - case 0x3c4: - return ega->seqaddr; - case 0x3c5: - return ega->seqregs[ega->seqaddr & 0xf]; - case 0x3c8: - return 2; - case 0x3cc: - return ega->miscout; - case 0x3ce: - return ega->gdcaddr; - case 0x3cf: - return ega->gdcreg[ega->gdcaddr & 0xf]; - case 0x3d0: - case 0x3d4: - return ega->crtcreg; - case 0x3d1: - case 0x3d5: - return ega->crtc[ega->crtcreg]; - case 0x3da: - ega->attrff = 0; - ega->stat ^= 0x30; /*Fools IBM EGA video BIOS self-test*/ - return ega->stat; - } - return 0xff; + if (dev->crtc[7] & 2) dev->dispend |= 0x100; + if (dev->crtc[7] & 64) dev->dispend |= 0x200; + dev->dispend++; + + if (dev->crtc[7] & 4) dev->vsyncstart |= 0x100; + if (dev->crtc[7] & 128) dev->vsyncstart |= 0x200; + dev->vsyncstart++; + + if (dev->crtc[7] & 0x10) dev->split |= 0x100; + if (dev->crtc[9] & 0x40) dev->split |= 0x200; + dev->split++; + + dev->hdisp = dev->crtc[1]; + dev->hdisp++; + + dev->rowoffset = dev->crtc[0x13]; + dev->rowcount = dev->crtc[9] & 0x1f; + overscan_y = (dev->rowcount + 1) << 1; + + if (dev->vidclock) + crtcconst = (dev->seqregs[1] & 1) ? MDACONST : (MDACONST * (9.0 / 8.0)); + else + crtcconst = (dev->seqregs[1] & 1) ? CGACONST : (CGACONST * (9.0 / 8.0)); + + if (dev->seqregs[1] & 8) { + disptime = (double) ((dev->crtc[0] + 2) << 1); + _dispontime = (double) ((dev->crtc[1] + 1) << 1); + + overscan_y <<= 1; + } else { + disptime = (double) (dev->crtc[0] + 2); + _dispontime = (double) (dev->crtc[1] + 1); + } + if (overscan_y < 16) + overscan_y = 16; + + _dispofftime = disptime - _dispontime; + _dispontime = _dispontime * crtcconst; + _dispofftime = _dispofftime * crtcconst; + + dev->dispontime = (int64_t)(_dispontime * (1LL << TIMER_SHIFT)); + dev->dispofftime = (int64_t)(_dispofftime * (1LL << TIMER_SHIFT)); } -void ega_recalctimings(ega_t *ega) +void +ega_poll(void *priv) { - double _dispontime, _dispofftime, disptime; - double crtcconst; + ega_t *dev = (ega_t *)priv; + int y_add = enable_overscan ? (overscan_y >> 1) : 0; + int x_add = enable_overscan ? 8 : 0; + int y_add_ex = enable_overscan ? overscan_y : 0; + int x_add_ex = enable_overscan ? 16 : 0; + int wx = 640, wy = 350; + int drawcursor = 0; + uint32_t *q; + int i, j, x; - ega->vtotal = ega->crtc[6]; - ega->dispend = ega->crtc[0x12]; - ega->vsyncstart = ega->crtc[0x10]; - ega->split = ega->crtc[0x18]; + if (! dev->linepos) { + dev->vidtime += dev->dispofftime; - if (ega->crtc[7] & 1) ega->vtotal |= 0x100; - if (ega->crtc[7] & 32) ega->vtotal |= 0x200; - ega->vtotal += 2; + dev->stat |= 1; + dev->linepos = 1; - if (ega->crtc[7] & 2) ega->dispend |= 0x100; - if (ega->crtc[7] & 64) ega->dispend |= 0x200; - ega->dispend++; + if (dev->dispon) { + if (dev->firstline == 2000) { + dev->firstline = dev->displine; + video_wait_for_buffer(); + } - if (ega->crtc[7] & 4) ega->vsyncstart |= 0x100; - if (ega->crtc[7] & 128) ega->vsyncstart |= 0x200; - ega->vsyncstart++; - - if (ega->crtc[7] & 0x10) ega->split |= 0x100; - if (ega->crtc[9] & 0x40) ega->split |= 0x200; - ega->split++; - - ega->hdisp = ega->crtc[1]; - ega->hdisp++; - - ega->rowoffset = ega->crtc[0x13]; - ega->rowcount = ega->crtc[9] & 0x1f; - overscan_y = (ega->rowcount + 1) << 1; - - if (ega->vidclock) crtcconst = (ega->seqregs[1] & 1) ? MDACONST : (MDACONST * (9.0 / 8.0)); - else crtcconst = (ega->seqregs[1] & 1) ? CGACONST : (CGACONST * (9.0 / 8.0)); - - if (ega->seqregs[1] & 8) - { - disptime = (double) ((ega->crtc[0] + 2) << 1); - _dispontime = (double) ((ega->crtc[1] + 1) << 1); - - overscan_y <<= 1; - } else { - disptime = (double) (ega->crtc[0] + 2); - _dispontime = (double) (ega->crtc[1] + 1); - } - if (overscan_y < 16) - { - overscan_y = 16; - } - _dispofftime = disptime - _dispontime; - _dispontime = _dispontime * crtcconst; - _dispofftime = _dispofftime * crtcconst; - - ega->dispontime = (int64_t)(_dispontime * (1LL << TIMER_SHIFT)); - ega->dispofftime = (int64_t)(_dispofftime * (1LL << TIMER_SHIFT)); -} - - -void ega_poll(void *p) -{ - ega_t *ega = (ega_t *)p; - int x; - int drawcursor = 0; - int y_add = enable_overscan ? (overscan_y >> 1) : 0; - int x_add = enable_overscan ? 8 : 0; - int y_add_ex = enable_overscan ? overscan_y : 0; - int x_add_ex = enable_overscan ? 16 : 0; - uint32_t *q; - int i, j; - int wx = 640, wy = 350; - - if (!ega->linepos) - { - ega->vidtime += ega->dispofftime; - - ega->stat |= 1; - ega->linepos = 1; - - if (ega->dispon) - { - if (ega->firstline == 2000) - { - ega->firstline = ega->displine; - video_wait_for_buffer(); - } - - if (ega->scrblank) - { - ega_render_blank(ega); - } - else if (!(ega->gdcreg[6] & 1)) - { - if (fullchange) - { + if (dev->scrblank) + ega_render_blank(dev); + else if (!(dev->gdcreg[6] & 1)) { + if (fullchange) { #ifdef JEGA - if (ega_jega_enabled(ega)) - { - ega_render_text_jega(ega, drawcursor); - } - else - { - ega_render_text_standard(ega, drawcursor); - } + if (ega_jega_enabled(dev)) { + ega_render_text_jega(dev, drawcursor); + } else { + ega_render_text_standard(dev, drawcursor); + } #else - ega_render_text_standard(ega, drawcursor); + ega_render_text_standard(dev, drawcursor); #endif - } - } - else - { - switch (ega->gdcreg[5] & 0x20) - { - case 0x00: - if (ega->seqregs[1] & 8) - { - ega_render_4bpp_lowres(ega); - } - else - { - ega_render_4bpp_highres(ega); - } - break; - case 0x20: - ega_render_2bpp(ega); - break; - } - } - if (ega->lastline < ega->displine) - ega->lastline = ega->displine; - } - - ega->displine++; - if (ega->interlace) - ega->displine++; - if ((ega->stat & 8) && ((ega->displine & 15) == (ega->crtc[0x11] & 15)) && ega->vslines) - ega->stat &= ~8; - ega->vslines++; - if (ega->displine > 500) - ega->displine = 0; - } - else - { - ega->vidtime += ega->dispontime; - if (ega->dispon) - ega->stat &= ~1; - ega->linepos = 0; - if (ega->sc == (ega->crtc[11] & 31)) - ega->con = 0; - if (ega->dispon) - { - if (ega->sc == (ega->crtc[9] & 31)) - { - ega->sc = 0; - if (ega->sc == (ega->crtc[11] & 31)) - ega->con = 0; - - ega->maback += (ega->rowoffset << 3); - if (ega->interlace) - ega->maback += (ega->rowoffset << 3); - ega->maback &= ega->vrammask; - ega->ma = ega->maback; - } - else - { - ega->sc++; - ega->sc &= 31; - ega->ma = ega->maback; - } - } - ega->vc++; - ega->vc &= 1023; - if (ega->vc == ega->split) - { - ega->ma = ega->maback = 0; - if (ega->attrregs[0x10] & 0x20) - ega->scrollcache = 0; - } - if (ega->vc == ega->dispend) - { - ega->dispon=0; - if (ega->crtc[10] & 0x20) ega->cursoron = 0; - else ega->cursoron = ega->blink & 16; - if (!(ega->gdcreg[6] & 1) && !(ega->blink & 15)) - fullchange = 2; - ega->blink++; - - if (fullchange) - fullchange--; - } - if (ega->vc == ega->vsyncstart) - { - ega->dispon = 0; - ega->stat |= 8; - if (ega->seqregs[1] & 8) x = ega->hdisp * ((ega->seqregs[1] & 1) ? 8 : 9) * 2; - else x = ega->hdisp * ((ega->seqregs[1] & 1) ? 8 : 9); - - if (ega->interlace && !ega->oddeven) ega->lastline++; - if (ega->interlace && ega->oddeven) ega->firstline--; - - if ((x != xsize || (ega->lastline - ega->firstline + 1) != ysize) || update_overscan || video_force_resize_get()) - { - xsize = x; - ysize = ega->lastline - ega->firstline + 1; - if (xsize < 64) xsize = 640; - if (ysize < 32) ysize = 200; - y_add = enable_overscan ? 14 : 0; - x_add = enable_overscan ? 8 : 0; - y_add_ex = enable_overscan ? 28 : 0; - x_add_ex = enable_overscan ? 16 : 0; - - if ((xsize > 2032) || ((ysize + y_add_ex) > 2048)) - { - x_add = x_add_ex = 0; - y_add = y_add_ex = 0; - suppress_overscan = 1; - } - else - { - suppress_overscan = 0; - } - - if (ega->vres) - set_screen_size(xsize + x_add_ex, (ysize << 1) + y_add_ex); - else - set_screen_size(xsize + x_add_ex, ysize + y_add_ex); - - if (video_force_resize_get()) - video_force_resize_set(0); - } - - if (enable_overscan) - { - if ((x >= 160) && ((ega->lastline - ega->firstline) >= 120)) - { - /* Draw (overscan_size - scroll size) lines of overscan on top. */ - for (i = 0; i < (y_add - (ega->crtc[8] & 0x1f)); i++) - { - q = &((uint32_t *)buffer32->line[i & 0x7ff])[32]; - - for (j = 0; j < (xsize + x_add_ex); j++) - { - q[j] = ega->pallook[ega->attrregs[0x11]]; - } - } - - /* Draw (overscan_size + scroll size) lines of overscan on the bottom. */ - for (i = 0; i < (y_add + (ega->crtc[8] & 0x1f)); i++) - { - q = &((uint32_t *)buffer32->line[(ysize + y_add + i - (ega->crtc[8] & 0x1f)) & 0x7ff])[32]; - - for (j = 0; j < (xsize + x_add_ex); j++) - { - q[j] = ega->pallook[ega->attrregs[0x11]]; - } - } - - for (i = (y_add - (ega->crtc[8] & 0x1f)); i < (ysize + y_add - (ega->crtc[8] & 0x1f)); i ++) - { - q = &((uint32_t *)buffer32->line[(i - (ega->crtc[8] & 0x1f)) & 0x7ff])[32]; - - for (j = 0; j < x_add; j++) - { - q[j] = ega->pallook[ega->attrregs[0x11]]; - q[xsize + x_add + j] = ega->pallook[ega->attrregs[0x11]]; - } - } - } } + } else { + switch (dev->gdcreg[5] & 0x20) { + case 0x00: + if (dev->seqregs[1] & 8) { + ega_render_4bpp_lowres(dev); + } else { + ega_render_4bpp_highres(dev); + } + break; + + case 0x20: + ega_render_2bpp(dev); + break; + } + } + if (dev->lastline < dev->displine) + dev->lastline = dev->displine; + } + + dev->displine++; + if (dev->interlace) + dev->displine++; + if ((dev->stat & 8) && ((dev->displine & 15) == (dev->crtc[0x11] & 15)) && dev->vslines) + dev->stat &= ~8; + dev->vslines++; + if (dev->displine > 500) + dev->displine = 0; + } else { + dev->vidtime += dev->dispontime; + if (dev->dispon) + dev->stat &= ~1; + dev->linepos = 0; + if (dev->sc == (dev->crtc[11] & 31)) + dev->con = 0; + if (dev->dispon) { + if (dev->sc == (dev->crtc[9] & 31)) { + dev->sc = 0; + if (dev->sc == (dev->crtc[11] & 31)) + dev->con = 0; + + dev->maback += (dev->rowoffset << 3); + if (dev->interlace) + dev->maback += (dev->rowoffset << 3); + dev->maback &= dev->vrammask; + dev->ma = dev->maback; + } else { + dev->sc++; + dev->sc &= 31; + dev->ma = dev->maback; + } + } + dev->vc++; + dev->vc &= 1023; + if (dev->vc == dev->split) { + dev->ma = dev->maback = 0; + if (dev->attrregs[0x10] & 0x20) + dev->scrollcache = 0; + } + + if (dev->vc == dev->dispend) { + dev->dispon=0; + if (dev->crtc[10] & 0x20) + dev->cursoron = 0; + else + dev->cursoron = dev->blink & 16; + if (!(dev->gdcreg[6] & 1) && !(dev->blink & 15)) + fullchange = 2; + dev->blink++; + + if (fullchange) + fullchange--; + } + + if (dev->vc == dev->vsyncstart) { + dev->dispon = 0; + dev->stat |= 8; + if (dev->seqregs[1] & 8) + x = dev->hdisp * ((dev->seqregs[1] & 1) ? 8 : 9) * 2; + else + x = dev->hdisp * ((dev->seqregs[1] & 1) ? 8 : 9); + + if (dev->interlace && !dev->oddeven) dev->lastline++; + if (dev->interlace && dev->oddeven) dev->firstline--; + + if ((x != xsize || (dev->lastline - dev->firstline + 1) != ysize) || update_overscan || video_force_resize_get()) { + xsize = x; + ysize = dev->lastline - dev->firstline + 1; + if (xsize < 64) xsize = 640; + if (ysize < 32) ysize = 200; + y_add = enable_overscan ? 14 : 0; + x_add = enable_overscan ? 8 : 0; + y_add_ex = enable_overscan ? 28 : 0; + x_add_ex = enable_overscan ? 16 : 0; + + if ((xsize > 2032) || ((ysize + y_add_ex) > 2048)) { + x_add = x_add_ex = 0; + y_add = y_add_ex = 0; + suppress_overscan = 1; + } else { + suppress_overscan = 0; + } + + if (dev->vres) + set_screen_size(xsize + x_add_ex, (ysize << 1) + y_add_ex); else - { - if (ega->crtc[8] & 0x1f) - { - /* Draw (scroll size) lines of overscan on the bottom. */ - for (i = 0; i < (ega->crtc[8] & 0x1f); i++) - { - q = &((uint32_t *)buffer32->line[(ysize + i - (ega->crtc[8] & 0x1f)) & 0x7ff])[32]; + set_screen_size(xsize + x_add_ex, ysize + y_add_ex); - for (j = 0; j < xsize; j++) - { - q[j] = ega->pallook[ega->attrregs[0x11]]; - } + if (video_force_resize_get()) + video_force_resize_set(0); + } + + if (enable_overscan) { + if ((x >= 160) && ((dev->lastline - dev->firstline) >= 120)) { + /* Draw (overscan_size - scroll size) lines of overscan on top. */ + for (i = 0; i < (y_add - (dev->crtc[8] & 0x1f)); i++) { + q = &((uint32_t *)buffer32->line[i & 0x7ff])[32]; + + for (j = 0; j < (xsize + x_add_ex); j++) { + q[j] = dev->pallook[dev->attrregs[0x11]]; + } + } + + /* Draw (overscan_size + scroll size) lines of overscan on the bottom. */ + for (i = 0; i < (y_add + (dev->crtc[8] & 0x1f)); i++) { + q = &((uint32_t *)buffer32->line[(ysize + y_add + i - (dev->crtc[8] & 0x1f)) & 0x7ff])[32]; + + for (j = 0; j < (xsize + x_add_ex); j++) { + q[j] = dev->pallook[dev->attrregs[0x11]]; + } + } + + for (i = (y_add - (dev->crtc[8] & 0x1f)); i < (ysize + y_add - (dev->crtc[8] & 0x1f)); i ++) { + q = &((uint32_t *)buffer32->line[(i - (dev->crtc[8] & 0x1f)) & 0x7ff])[32]; + + for (j = 0; j < x_add; j++) { + q[j] = dev->pallook[dev->attrregs[0x11]]; + q[xsize + x_add + j] = dev->pallook[dev->attrregs[0x11]]; } } } - - video_blit_memtoscreen(32, 0, ega->firstline, ega->lastline + 1 + y_add_ex, xsize + x_add_ex, ega->lastline - ega->firstline + 1 + y_add_ex); + } else { + if (dev->crtc[8] & 0x1f) { + /* Draw (scroll size) lines of overscan on the bottom. */ + for (i = 0; i < (dev->crtc[8] & 0x1f); i++) { + q = &((uint32_t *)buffer32->line[(ysize + i - (dev->crtc[8] & 0x1f)) & 0x7ff])[32]; - frames++; - - ega->video_res_x = wx; - ega->video_res_y = wy + 1; - if (!(ega->gdcreg[6] & 1)) /*Text mode*/ - { - ega->video_res_x /= (ega->seqregs[1] & 1) ? 8 : 9; - ega->video_res_y /= (ega->crtc[9] & 31) + 1; - ega->video_bpp = 0; - } - else - { - if (ega->crtc[9] & 0x80) - ega->video_res_y /= 2; - if (!(ega->crtc[0x17] & 1)) - ega->video_res_y *= 2; - ega->video_res_y /= (ega->crtc[9] & 31) + 1; - if (ega->seqregs[1] & 8) - ega->video_res_x /= 2; - ega->video_bpp = (ega->gdcreg[5] & 0x20) ? 2 : 4; - } - - ega->firstline = 2000; - ega->lastline = 0; - - ega->maback = ega->ma = (ega->crtc[0xc] << 8)| ega->crtc[0xd]; - ega->ca = (ega->crtc[0xe] << 8) | ega->crtc[0xf]; - ega->ma <<= 2; - ega->maback <<= 2; - ega->ca <<= 2; - changeframecount = 2; - ega->vslines = 0; - } - if (ega->vc == ega->vtotal) - { - ega->vc = 0; - ega->sc = 0; - ega->dispon = 1; - ega->displine = (ega->interlace && ega->oddeven) ? 1 : 0; - ega->scrollcache = ega->attrregs[0x13] & 7; - } - if (ega->sc == (ega->crtc[10] & 31)) - ega->con = 1; - } -} - - -void ega_write(uint32_t addr, uint8_t val, void *p) -{ - ega_t *ega = (ega_t *)p; - uint8_t vala, valb, valc, vald; - int writemask2 = ega->writemask; - - egawrites++; - cycles -= video_timing_write_b; - cycles_lost += video_timing_write_b; - - if (addr >= 0xB0000) addr &= 0x7fff; - else addr &= 0xffff; - - if (ega->chain2_write) - { - writemask2 &= ~0xa; - if (addr & 1) - writemask2 <<= 1; - addr &= ~1; - if (addr & 0x4000) - addr |= 1; - addr &= ~0x4000; - } - - addr <<= 2; - - if (addr >= ega->vram_limit) - return; - - if (!(ega->gdcreg[6] & 1)) - fullchange = 2; - - switch (ega->writemode) - { - case 1: - if (writemask2 & 1) ega->vram[addr] = ega->la; - if (writemask2 & 2) ega->vram[addr | 0x1] = ega->lb; - if (writemask2 & 4) ega->vram[addr | 0x2] = ega->lc; - if (writemask2 & 8) ega->vram[addr | 0x3] = ega->ld; - break; - case 0: - if (ega->gdcreg[3] & 7) - val = ega_rotate[ega->gdcreg[3] & 7][val]; - - if (ega->gdcreg[8] == 0xff && !(ega->gdcreg[3] & 0x18) && !ega->gdcreg[1]) - { - if (writemask2 & 1) ega->vram[addr] = val; - if (writemask2 & 2) ega->vram[addr | 0x1] = val; - if (writemask2 & 4) ega->vram[addr | 0x2] = val; - if (writemask2 & 8) ega->vram[addr | 0x3] = val; - } - else - { - if (ega->gdcreg[1] & 1) vala = (ega->gdcreg[0] & 1) ? 0xff : 0; - else vala = val; - if (ega->gdcreg[1] & 2) valb = (ega->gdcreg[0] & 2) ? 0xff : 0; - else valb = val; - if (ega->gdcreg[1] & 4) valc = (ega->gdcreg[0] & 4) ? 0xff : 0; - else valc = val; - if (ega->gdcreg[1] & 8) vald = (ega->gdcreg[0] & 8) ? 0xff : 0; - else vald = val; - switch (ega->gdcreg[3] & 0x18) - { - case 0: /*Set*/ - if (writemask2 & 1) ega->vram[addr] = (vala & ega->gdcreg[8]) | (ega->la & ~ega->gdcreg[8]); - if (writemask2 & 2) ega->vram[addr | 0x1] = (valb & ega->gdcreg[8]) | (ega->lb & ~ega->gdcreg[8]); - if (writemask2 & 4) ega->vram[addr | 0x2] = (valc & ega->gdcreg[8]) | (ega->lc & ~ega->gdcreg[8]); - if (writemask2 & 8) ega->vram[addr | 0x3] = (vald & ega->gdcreg[8]) | (ega->ld & ~ega->gdcreg[8]); - break; - case 8: /*AND*/ - if (writemask2 & 1) ega->vram[addr] = (vala | ~ega->gdcreg[8]) & ega->la; - if (writemask2 & 2) ega->vram[addr | 0x1] = (valb | ~ega->gdcreg[8]) & ega->lb; - if (writemask2 & 4) ega->vram[addr | 0x2] = (valc | ~ega->gdcreg[8]) & ega->lc; - if (writemask2 & 8) ega->vram[addr | 0x3] = (vald | ~ega->gdcreg[8]) & ega->ld; - break; - case 0x10: /*OR*/ - if (writemask2 & 1) ega->vram[addr] = (vala & ega->gdcreg[8]) | ega->la; - if (writemask2 & 2) ega->vram[addr | 0x1] = (valb & ega->gdcreg[8]) | ega->lb; - if (writemask2 & 4) ega->vram[addr | 0x2] = (valc & ega->gdcreg[8]) | ega->lc; - if (writemask2 & 8) ega->vram[addr | 0x3] = (vald & ega->gdcreg[8]) | ega->ld; - break; - case 0x18: /*XOR*/ - if (writemask2 & 1) ega->vram[addr] = (vala & ega->gdcreg[8]) ^ ega->la; - if (writemask2 & 2) ega->vram[addr | 0x1] = (valb & ega->gdcreg[8]) ^ ega->lb; - if (writemask2 & 4) ega->vram[addr | 0x2] = (valc & ega->gdcreg[8]) ^ ega->lc; - if (writemask2 & 8) ega->vram[addr | 0x3] = (vald & ega->gdcreg[8]) ^ ega->ld; - break; - } - } - break; - case 2: - if (!(ega->gdcreg[3] & 0x18) && !ega->gdcreg[1]) - { - if (writemask2 & 1) ega->vram[addr] = (((val & 1) ? 0xff : 0) & ega->gdcreg[8]) | (ega->la & ~ega->gdcreg[8]); - if (writemask2 & 2) ega->vram[addr | 0x1] = (((val & 2) ? 0xff : 0) & ega->gdcreg[8]) | (ega->lb & ~ega->gdcreg[8]); - if (writemask2 & 4) ega->vram[addr | 0x2] = (((val & 4) ? 0xff : 0) & ega->gdcreg[8]) | (ega->lc & ~ega->gdcreg[8]); - if (writemask2 & 8) ega->vram[addr | 0x3] = (((val & 8) ? 0xff : 0) & ega->gdcreg[8]) | (ega->ld & ~ega->gdcreg[8]); - } - else - { - vala = ((val & 1) ? 0xff : 0); - valb = ((val & 2) ? 0xff : 0); - valc = ((val & 4) ? 0xff : 0); - vald = ((val & 8) ? 0xff : 0); - switch (ega->gdcreg[3] & 0x18) - { - case 0: /*Set*/ - if (writemask2 & 1) ega->vram[addr] = (vala & ega->gdcreg[8]) | (ega->la & ~ega->gdcreg[8]); - if (writemask2 & 2) ega->vram[addr | 0x1] = (valb & ega->gdcreg[8]) | (ega->lb & ~ega->gdcreg[8]); - if (writemask2 & 4) ega->vram[addr | 0x2] = (valc & ega->gdcreg[8]) | (ega->lc & ~ega->gdcreg[8]); - if (writemask2 & 8) ega->vram[addr | 0x3] = (vald & ega->gdcreg[8]) | (ega->ld & ~ega->gdcreg[8]); - break; - case 8: /*AND*/ - if (writemask2 & 1) ega->vram[addr] = (vala | ~ega->gdcreg[8]) & ega->la; - if (writemask2 & 2) ega->vram[addr | 0x1] = (valb | ~ega->gdcreg[8]) & ega->lb; - if (writemask2 & 4) ega->vram[addr | 0x2] = (valc | ~ega->gdcreg[8]) & ega->lc; - if (writemask2 & 8) ega->vram[addr | 0x3] = (vald | ~ega->gdcreg[8]) & ega->ld; - break; - case 0x10: /*OR*/ - if (writemask2 & 1) ega->vram[addr] = (vala & ega->gdcreg[8]) | ega->la; - if (writemask2 & 2) ega->vram[addr | 0x1] = (valb & ega->gdcreg[8]) | ega->lb; - if (writemask2 & 4) ega->vram[addr | 0x2] = (valc & ega->gdcreg[8]) | ega->lc; - if (writemask2 & 8) ega->vram[addr | 0x3] = (vald & ega->gdcreg[8]) | ega->ld; - break; - case 0x18: /*XOR*/ - if (writemask2 & 1) ega->vram[addr] = (vala & ega->gdcreg[8]) ^ ega->la; - if (writemask2 & 2) ega->vram[addr | 0x1] = (valb & ega->gdcreg[8]) ^ ega->lb; - if (writemask2 & 4) ega->vram[addr | 0x2] = (valc & ega->gdcreg[8]) ^ ega->lc; - if (writemask2 & 8) ega->vram[addr | 0x3] = (vald & ega->gdcreg[8]) ^ ega->ld; - break; - } - } - break; - } -} - - -uint8_t ega_read(uint32_t addr, void *p) -{ - ega_t *ega = (ega_t *)p; - uint8_t temp, temp2, temp3, temp4; - int readplane = ega->readplane; - - egareads++; - cycles -= video_timing_read_b; - cycles_lost += video_timing_read_b; - if (addr >= 0xb0000) addr &= 0x7fff; - else addr &= 0xffff; - - if (ega->chain2_read) - { - readplane = (readplane & 2) | (addr & 1); - addr &= ~1; - if (addr & 0x4000) - addr |= 1; - addr &= ~0x4000; - } - - addr <<= 2; - - if (addr >= ega->vram_limit) - return 0xff; - - ega->la = ega->vram[addr]; - ega->lb = ega->vram[addr | 0x1]; - ega->lc = ega->vram[addr | 0x2]; - ega->ld = ega->vram[addr | 0x3]; - if (ega->readmode) - { - temp = ega->la; - temp ^= (ega->colourcompare & 1) ? 0xff : 0; - temp &= (ega->colournocare & 1) ? 0xff : 0; - temp2 = ega->lb; - temp2 ^= (ega->colourcompare & 2) ? 0xff : 0; - temp2 &= (ega->colournocare & 2) ? 0xff : 0; - temp3 = ega->lc; - temp3 ^= (ega->colourcompare & 4) ? 0xff : 0; - temp3 &= (ega->colournocare & 4) ? 0xff : 0; - temp4 = ega->ld; - temp4 ^= (ega->colourcompare & 8) ? 0xff : 0; - temp4 &= (ega->colournocare & 8) ? 0xff : 0; - return ~(temp | temp2 | temp3 | temp4); - } - return ega->vram[addr | readplane]; -} - - -void ega_init(ega_t *ega, int monitor_type, int is_mono) -{ - int c, d, e; - - ega->vram = malloc(0x40000); - ega->vrammask = 0x3ffff; - - for (c = 0; c < 256; c++) - { - e = c; - for (d = 0; d < 8; d++) - { - ega_rotate[d][c] = e; - e = (e >> 1) | ((e & 1) ? 0x80 : 0); - } - } - - for (c = 0; c < 4; c++) - { - for (d = 0; d < 4; d++) - { - edatlookup[c][d] = 0; - if (c & 1) edatlookup[c][d] |= 1; - if (d & 1) edatlookup[c][d] |= 2; - if (c & 2) edatlookup[c][d] |= 0x10; - if (d & 2) edatlookup[c][d] |= 0x20; - } - } - - if (is_mono) - { - for (c = 0; c < 256; c++) - { - switch (monitor_type >> 4) - { - case DISPLAY_GREEN: - switch ((c >> 3) & 3) - { - case 0: - pallook64[c] = pallook16[c] = makecol32(0, 0, 0); - break; - case 2: - pallook64[c] = pallook16[c] = makecol32(0x04, 0x8a, 0x20); - break; - case 1: - pallook64[c] = pallook16[c] = makecol32(0x08, 0xc7, 0x2c); - break; - case 3: - pallook64[c] = pallook16[c] = makecol32(0x34, 0xff, 0x5d); - break; - } - break; - case DISPLAY_AMBER: - switch ((c >> 3) & 3) - { - case 0: - pallook64[c] = pallook16[c] = makecol32(0, 0, 0); - break; - case 2: - pallook64[c] = pallook16[c] = makecol32(0xb2, 0x4d, 0x00); - break; - case 1: - pallook64[c] = pallook16[c] = makecol32(0xef, 0x79, 0x00); - break; - case 3: - pallook64[c] = pallook16[c] = makecol32(0xff, 0xe3, 0x34); - break; - } - break; - case DISPLAY_WHITE: default: - switch ((c >> 3) & 3) - { - case 0: - pallook64[c] = pallook16[c] = makecol32(0, 0, 0); - break; - case 2: - pallook64[c] = pallook16[c] = makecol32(0x7a, 0x81, 0x83); - break; - case 1: - pallook64[c] = pallook16[c] = makecol32(0xaf, 0xb3, 0xb0); - break; - case 3: - pallook64[c] = pallook16[c] = makecol32(0xff, 0xfd, 0xed); - break; - } - break; - } - } - } - else - { - for (c = 0; c < 256; c++) - { - pallook64[c] = makecol32(((c >> 2) & 1) * 0xaa, ((c >> 1) & 1) * 0xaa, (c & 1) * 0xaa); - pallook64[c] += makecol32(((c >> 5) & 1) * 0x55, ((c >> 4) & 1) * 0x55, ((c >> 3) & 1) * 0x55); - pallook16[c] = makecol32(((c >> 2) & 1) * 0xaa, ((c >> 1) & 1) * 0xaa, (c & 1) * 0xaa); - pallook16[c] += makecol32(((c >> 4) & 1) * 0x55, ((c >> 4) & 1) * 0x55, ((c >> 4) & 1) * 0x55); - if ((c & 0x17) == 6) - pallook16[c] = makecol32(0xaa, 0x55, 0); - } - } - ega->pallook = pallook16; - - egaswitches = monitor_type & 0xf; - - ega->vram_limit = 256 * 1024; - ega->vrammask = ega->vram_limit-1; - - old_overscan_color = 0; - - ega->miscout |= 0x22; - ega->oddeven_page = 0; - - ega->seqregs[4] |= 2; - ega->extvram = 1; - - update_overscan = 0; - - ega->crtc[0] = 63; - ega->crtc[6] = 255; - -#ifdef JEGA - ega->is_jega = 0; -#endif -} - - -static void *ega_standalone_init(const device_t *info) -{ - ega_t *ega = malloc(sizeof(ega_t)); - int monitor_type; - - memset(ega, 0, sizeof(ega_t)); - - overscan_x = 16; - overscan_y = 28; - - switch(info->local) { - case EGA_IBM: - default: - rom_init(&ega->bios_rom, BIOS_IBM_PATH, - 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); - break; - case EGA_COMPAQ: - rom_init(&ega->bios_rom, BIOS_CPQ_PATH, - 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); - break; - case EGA_SUPEREGA: - rom_init(&ega->bios_rom, BIOS_SEGA_PATH, - 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); - break; - } - - if (ega->bios_rom.rom[0x3ffe] == 0xaa && ega->bios_rom.rom[0x3fff] == 0x55) - { - int c; - - for (c = 0; c < 0x2000; c++) - { - uint8_t temp = ega->bios_rom.rom[c]; - ega->bios_rom.rom[c] = ega->bios_rom.rom[0x3fff - c]; - ega->bios_rom.rom[0x3fff - c] = temp; - } - } - - monitor_type = device_get_config_int("monitor_type"); - ega_init(ega, monitor_type, (monitor_type & 0xf) == 10); - - ega->vram_limit = device_get_config_int("memory") * 1024; - ega->vrammask = ega->vram_limit-1; - - mem_mapping_add(&ega->mapping, 0xa0000, 0x20000, ega_read, NULL, NULL, ega_write, NULL, NULL, NULL, MEM_MAPPING_EXTERNAL, ega); - timer_add(ega_poll, &ega->vidtime, TIMER_ALWAYS_ENABLED, ega); - io_sethandler(0x03a0, 0x0040, ega_in, NULL, NULL, ega_out, NULL, NULL, ega); - return ega; -} - -#ifdef JEGA -uint16_t chrtosht(FILE *fp) -{ - uint16_t i, j; - i = (uint8_t) getc(fp); - j = (uint8_t) getc(fp) << 8; - return (i | j); -} - -unsigned int getfontx2header(FILE *fp, fontx_h *header) -{ - fread(header->id, ID_LEN, 1, fp); - if (strncmp(header->id, "FONTX2", ID_LEN) != 0) - { - return 1; - } - fread(header->name, NAME_LEN, 1, fp); - header->width = (uint8_t)getc(fp); - header->height = (uint8_t)getc(fp); - header->type = (uint8_t)getc(fp); - return 0; -} - -void readfontxtbl(fontxTbl *table, unsigned int size, FILE *fp) -{ - while (size > 0) - { - table->start = chrtosht(fp); - table->end = chrtosht(fp); - ++table; - --size; - } -} - -static void LoadFontxFile(wchar_t *fname) -{ - fontx_h head; - fontxTbl *table; - unsigned int code; - uint8_t size; - unsigned int i; - - if (!fname) return; - if(*fname=='\0') return; - FILE * mfile=romfopen(fname,L"rb"); - if (!mfile) - { - pclog("MSG: Can't open FONTX2 file: %s\n",fname); - return; - } - if (getfontx2header(mfile, &head) != 0) - { - fclose(mfile); - pclog("MSG: FONTX2 header is incorrect\n"); - return; - } - /* switch whether the font is DBCS or not */ - if (head.type == DBCS) - { - if (head.width == 16 && head.height == 16) - { - size = getc(mfile); - table = (fontxTbl *)calloc(size, sizeof(fontxTbl)); - readfontxtbl(table, size, mfile); - for (i = 0; i < size; i++) - { - for (code = table[i].start; code <= table[i].end; code++) - { - fread(&jfont_dbcs_16[(code * 32)], sizeof(uint8_t), 32, mfile); + for (j = 0; j < xsize; j++) { + q[j] = dev->pallook[dev->attrregs[0x11]]; + } } } } - else - { - fclose(mfile); - pclog("MSG: FONTX2 DBCS font size is not correct\n"); - return; + + video_blit_memtoscreen(32, 0, dev->firstline, dev->lastline + 1 + y_add_ex, xsize + x_add_ex, dev->lastline - dev->firstline + 1 + y_add_ex); + + frames++; + + dev->video_res_x = wx; + dev->video_res_y = wy + 1; + if (!(dev->gdcreg[6] & 1)) { /*Text mode*/ + dev->video_res_x /= (dev->seqregs[1] & 1) ? 8 : 9; + dev->video_res_y /= (dev->crtc[9] & 31) + 1; + dev->video_bpp = 0; + } else { + if (dev->crtc[9] & 0x80) + dev->video_res_y /= 2; + if (!(dev->crtc[0x17] & 1)) + dev->video_res_y *= 2; + dev->video_res_y /= (dev->crtc[9] & 31) + 1; + if (dev->seqregs[1] & 8) + dev->video_res_x /= 2; + dev->video_bpp = (dev->gdcreg[5] & 0x20) ? 2 : 4; } + + dev->firstline = 2000; + dev->lastline = 0; + + dev->maback = dev->ma = (dev->crtc[0xc] << 8)| dev->crtc[0xd]; + dev->ca = (dev->crtc[0xe] << 8) | dev->crtc[0xf]; + dev->ma <<= 2; + dev->maback <<= 2; + dev->ca <<= 2; + changeframecount = 2; + dev->vslines = 0; } - else - { - if (head.width == 8 && head.height == 19) - { - fread(jfont_sbcs_19, sizeof(uint8_t), SBCS19_LEN, mfile); - } - else - { - fclose(mfile); - pclog("MSG: FONTX2 SBCS font size is not correct\n"); - return; - } + + if (dev->vc == dev->vtotal) { + dev->vc = 0; + dev->sc = 0; + dev->dispon = 1; + dev->displine = (dev->interlace && dev->oddeven) ? 1 : 0; + dev->scrollcache = dev->attrregs[0x13] & 7; } - fclose(mfile); + + if (dev->sc == (dev->crtc[10] & 31)) + dev->con = 1; + } } -void *jega_standalone_init(const device_t *info) + +void +ega_out(uint16_t port, uint8_t val, void *priv) { - ega_t *ega = (ega_t *)ega_standalone_init(info); + ega_t *dev = (ega_t *)priv; + uint8_t o, old; + int c; + + if (((port & 0xfff0) == 0x3d0 || + (port & 0xfff0) == 0x3b0) && !(dev->miscout & 1)) port ^= 0x60; + + switch (port) { + case 0x3c0: + case 0x3c1: + if (! dev->attrff) + dev->attraddr = val & 31; + else { + dev->attrregs[dev->attraddr & 31] = val; + if (dev->attraddr < 16) + fullchange = changeframecount; + if (dev->attraddr == 0x10 || dev->attraddr == 0x14 || dev->attraddr < 0x10) { + for (c = 0; c < 16; c++) { + if (dev->attrregs[0x10] & 0x80) + dev->egapal[c] = (dev->attrregs[c] & 0xf) | ((dev->attrregs[0x14] & 0xf) << 4); + else + dev->egapal[c] = (dev->attrregs[c] & 0x3f) | ((dev->attrregs[0x14] & 0xc) << 4); + } + } + } + dev->attrff ^= 1; + break; - LoadFontxFile(L"video/ibm/ega/jpnhn19x.fnt"); - LoadFontxFile(L"video/ibm/ega/jpnzn16x.fnt"); + case 0x3c2: + egaswitchread = val & 0xc; + dev->vres = !(val & 0x80); + dev->pallook = dev->vres ? pallook16 : pallook64; + dev->vidclock = val & 4; /*printf("3C2 write %02X\n",val);*/ + dev->miscout=val; + break; - ega->is_jega = 1; + case 0x3c4: + dev->seqaddr = val; + break; - return ega; + case 0x3c5: + o = dev->seqregs[dev->seqaddr & 0xf]; + dev->seqregs[dev->seqaddr & 0xf] = val; + if (o != val && (dev->seqaddr & 0xf) == 1) + ega_recalctimings(dev); + switch (dev->seqaddr & 0xf) { + case 1: + if (dev->scrblank && !(val & 0x20)) + fullchange = 3; + dev->scrblank = (dev->scrblank & ~0x20) | (val & 0x20); + break; + + case 2: + dev->writemask = val & 0xf; + break; + + case 3: + dev->charsetb = (((val >> 2) & 3) * 0x10000) + 2; + dev->charseta = ((val & 3) * 0x10000) + 2; + break; + + case 4: + dev->chain2_write = !(val & 4); + break; + } + break; + + case 0x3ce: + dev->gdcaddr = val; + break; + + case 0x3cf: + dev->gdcreg[dev->gdcaddr & 15] = val; + switch (dev->gdcaddr & 15) { + case 2: + dev->colourcompare = val; + break; + + case 4: + dev->readplane = val & 3; + break; + + case 5: + dev->writemode = val & 3; + dev->readmode = val & 8; + dev->chain2_read = val & 0x10; + break; + + case 6: + switch (val & 0xc) { + case 0x0: /*128k at A0000*/ + mem_map_set_addr(&dev->mapping, 0xa0000, 0x20000); + break; + + case 0x4: /*64k at A0000*/ + mem_map_set_addr(&dev->mapping, 0xa0000, 0x10000); + break; + + case 0x8: /*32k at B0000*/ + mem_map_set_addr(&dev->mapping, 0xb0000, 0x08000); + break; + + case 0xC: /*32k at B8000*/ + mem_map_set_addr(&dev->mapping, 0xb8000, 0x08000); + break; + } + break; + + case 7: + dev->colournocare = val; + break; + } + break; + + case 0x3d0: + case 0x3d4: + dev->crtcreg = val & 31; + return; + + case 0x3d1: + case 0x3d5: + if (dev->crtcreg <= 7 && dev->crtc[0x11] & 0x80) return; + old = dev->crtc[dev->crtcreg]; + dev->crtc[dev->crtcreg] = val; + if (old != val) { + if (dev->crtcreg < 0xe || dev->crtcreg > 0x10) { + fullchange = changeframecount; + ega_recalctimings(dev); + } + } + break; + } +} + + +uint8_t +ega_in(uint16_t port, void *priv) +{ + ega_t *dev = (ega_t *)priv; + uint8_t ret = 0xff; + + if (((port & 0xfff0) == 0x3d0 || + (port & 0xfff0) == 0x3b0) && !(dev->miscout & 1)) port ^= 0x60; + + switch (port) { + case 0x3c0: + ret = dev->attraddr; + break; + + case 0x3c1: + ret = dev->attrregs[dev->attraddr]; + break; + + case 0x3c2: + switch (egaswitchread) { + case 0xc: ret = (egaswitches & 1) ? 0x10 : 0; break; + case 0x8: ret = (egaswitches & 2) ? 0x10 : 0; break; + case 0x4: ret = (egaswitches & 4) ? 0x10 : 0; break; + case 0x0: ret = (egaswitches & 8) ? 0x10 : 0; break; + } + break; + + case 0x3c4: + ret = dev->seqaddr; + break; + + case 0x3c5: + ret = dev->seqregs[dev->seqaddr & 0xf]; + break; + + case 0x3c8: + ret = 2; + break; + + case 0x3cc: + ret = dev->miscout; + break; + + case 0x3ce: + ret = dev->gdcaddr; + break; + + case 0x3cf: + ret = dev->gdcreg[dev->gdcaddr & 0xf]; + break; + + case 0x3d0: + case 0x3d4: + ret = dev->crtcreg; + break; + + case 0x3d1: + case 0x3d5: + ret = dev->crtc[dev->crtcreg]; + break; + + case 0x3da: + dev->attrff = 0; + dev->stat ^= 0x30; /*Fools IBM EGA video BIOS self-test*/ + ret = dev->stat; + break; + } + + return ret; +} + + +void +ega_write(uint32_t addr, uint8_t val, void *priv) +{ + ega_t *dev = (ega_t *)priv; + uint8_t vala, valb, valc, vald; + int writemask2 = dev->writemask; + + cycles -= video_timing_write_b; + + if (addr >= 0xB0000) + addr &= 0x7fff; + else + addr &= 0xffff; + + if (dev->chain2_write) { + writemask2 &= ~0xa; + if (addr & 1) + writemask2 <<= 1; + addr &= ~1; + if (addr & 0x4000) + addr |= 1; + addr &= ~0x4000; + } + + addr <<= 2; + + if (addr >= dev->vram_limit) + return; + + if (!(dev->gdcreg[6] & 1)) + fullchange = 2; + + switch (dev->writemode) { + case 1: + if (writemask2 & 1) dev->vram[addr] = dev->la; + if (writemask2 & 2) dev->vram[addr | 0x1] = dev->lb; + if (writemask2 & 4) dev->vram[addr | 0x2] = dev->lc; + if (writemask2 & 8) dev->vram[addr | 0x3] = dev->ld; + break; + + case 0: + if (dev->gdcreg[3] & 7) + val = ega_rotate[dev->gdcreg[3] & 7][val]; + + if (dev->gdcreg[8] == 0xff && !(dev->gdcreg[3] & 0x18) && !dev->gdcreg[1]) { + if (writemask2 & 1) dev->vram[addr] = val; + if (writemask2 & 2) dev->vram[addr | 0x1] = val; + if (writemask2 & 4) dev->vram[addr | 0x2] = val; + if (writemask2 & 8) dev->vram[addr | 0x3] = val; + } else { + if (dev->gdcreg[1] & 1) + vala = (dev->gdcreg[0] & 1) ? 0xff : 0; + else + vala = val; + if (dev->gdcreg[1] & 2) + valb = (dev->gdcreg[0] & 2) ? 0xff : 0; + else + valb = val; + if (dev->gdcreg[1] & 4) + valc = (dev->gdcreg[0] & 4) ? 0xff : 0; + else + valc = val; + if (dev->gdcreg[1] & 8) + vald = (dev->gdcreg[0] & 8) ? 0xff : 0; + else + vald = val; + + switch (dev->gdcreg[3] & 0x18) { + case 0: /*Set*/ + if (writemask2 & 1) + dev->vram[addr] = (vala & dev->gdcreg[8]) | (dev->la & ~dev->gdcreg[8]); + if (writemask2 & 2) dev->vram[addr | 0x1] = (valb & dev->gdcreg[8]) | (dev->lb & ~dev->gdcreg[8]); + if (writemask2 & 4) + dev->vram[addr | 0x2] = (valc & dev->gdcreg[8]) | (dev->lc & ~dev->gdcreg[8]); + if (writemask2 & 8) + dev->vram[addr | 0x3] = (vald & dev->gdcreg[8]) | (dev->ld & ~dev->gdcreg[8]); + break; + + case 8: /*AND*/ + if (writemask2 & 1) + dev->vram[addr] = (vala | ~dev->gdcreg[8]) & dev->la; + if (writemask2 & 2) + dev->vram[addr | 0x1] = (valb | ~dev->gdcreg[8]) & dev->lb; + if (writemask2 & 4) + dev->vram[addr | 0x2] = (valc | ~dev->gdcreg[8]) & dev->lc; + if (writemask2 & 8) + dev->vram[addr | 0x3] = (vald | ~dev->gdcreg[8]) & dev->ld; + break; + + case 0x10: /*OR*/ + if (writemask2 & 1) + dev->vram[addr] = (vala & dev->gdcreg[8]) | dev->la; + if (writemask2 & 2) + dev->vram[addr | 0x1] = (valb & dev->gdcreg[8]) | dev->lb; + if (writemask2 & 4) + dev->vram[addr | 0x2] = (valc & dev->gdcreg[8]) | dev->lc; + if (writemask2 & 8) + dev->vram[addr | 0x3] = (vald & dev->gdcreg[8]) | dev->ld; + break; + + case 0x18: /*XOR*/ + if (writemask2 & 1) + dev->vram[addr] = (vala & dev->gdcreg[8]) ^ dev->la; + if (writemask2 & 2) + dev->vram[addr | 0x1] = (valb & dev->gdcreg[8]) ^ dev->lb; + if (writemask2 & 4) + dev->vram[addr | 0x2] = (valc & dev->gdcreg[8]) ^ dev->lc; + if (writemask2 & 8) + dev->vram[addr | 0x3] = (vald & dev->gdcreg[8]) ^ dev->ld; + break; + } + } + break; + + case 2: + if (!(dev->gdcreg[3] & 0x18) && !dev->gdcreg[1]) { + if (writemask2 & 1) + dev->vram[addr] = (((val & 1) ? 0xff : 0) & dev->gdcreg[8]) | (dev->la & ~dev->gdcreg[8]); + if (writemask2 & 2) + dev->vram[addr | 0x1] = (((val & 2) ? 0xff : 0) & dev->gdcreg[8]) | (dev->lb & ~dev->gdcreg[8]); + if (writemask2 & 4) + dev->vram[addr | 0x2] = (((val & 4) ? 0xff : 0) & dev->gdcreg[8]) | (dev->lc & ~dev->gdcreg[8]); + if (writemask2 & 8) + dev->vram[addr | 0x3] = (((val & 8) ? 0xff : 0) & dev->gdcreg[8]) | (dev->ld & ~dev->gdcreg[8]); + } else { + vala = ((val & 1) ? 0xff : 0); + valb = ((val & 2) ? 0xff : 0); + valc = ((val & 4) ? 0xff : 0); + vald = ((val & 8) ? 0xff : 0); + + switch (dev->gdcreg[3] & 0x18) { + case 0: /*Set*/ + if (writemask2 & 1) + dev->vram[addr] = (vala & dev->gdcreg[8]) | (dev->la & ~dev->gdcreg[8]); + if (writemask2 & 2) + dev->vram[addr | 0x1] = (valb & dev->gdcreg[8]) | (dev->lb & ~dev->gdcreg[8]); + if (writemask2 & 4) + dev->vram[addr | 0x2] = (valc & dev->gdcreg[8]) | (dev->lc & ~dev->gdcreg[8]); + if (writemask2 & 8) + dev->vram[addr | 0x3] = (vald & dev->gdcreg[8]) | (dev->ld & ~dev->gdcreg[8]); + break; + + case 8: /*AND*/ + if (writemask2 & 1) + dev->vram[addr] = (vala | ~dev->gdcreg[8]) & dev->la; + if (writemask2 & 2) + dev->vram[addr | 0x1] = (valb | ~dev->gdcreg[8]) & dev->lb; + if (writemask2 & 4) + dev->vram[addr | 0x2] = (valc | ~dev->gdcreg[8]) & dev->lc; + if (writemask2 & 8) + dev->vram[addr | 0x3] = (vald | ~dev->gdcreg[8]) & dev->ld; + break; + + case 0x10: /*OR*/ + if (writemask2 & 1) + dev->vram[addr] = (vala & dev->gdcreg[8]) | dev->la; + if (writemask2 & 2) + dev->vram[addr | 0x1] = (valb & dev->gdcreg[8]) | dev->lb; + if (writemask2 & 4) + dev->vram[addr | 0x2] = (valc & dev->gdcreg[8]) | dev->lc; + if (writemask2 & 8) + dev->vram[addr | 0x3] = (vald & dev->gdcreg[8]) | dev->ld; + break; + + case 0x18: /*XOR*/ + if (writemask2 & 1) + dev->vram[addr] = (vala & dev->gdcreg[8]) ^ dev->la; + if (writemask2 & 2) + dev->vram[addr | 0x1] = (valb & dev->gdcreg[8]) ^ dev->lb; + if (writemask2 & 4) + dev->vram[addr | 0x2] = (valc & dev->gdcreg[8]) ^ dev->lc; + if (writemask2 & 8) + dev->vram[addr | 0x3] = (vald & dev->gdcreg[8]) ^ dev->ld; + break; + } + } + break; + } +} + + +uint8_t +ega_read(uint32_t addr, void *priv) +{ + ega_t *dev = (ega_t *)priv; + uint8_t temp, temp2, temp3, temp4; + int readplane = dev->readplane; + + cycles -= video_timing_read_b; + + if (addr >= 0xb0000) + addr &= 0x7fff; + else + addr &= 0xffff; + + if (dev->chain2_read) { + readplane = (readplane & 2) | (addr & 1); + addr &= ~1; + if (addr & 0x4000) + addr |= 1; + addr &= ~0x4000; + } + + addr <<= 2; + + if (addr >= dev->vram_limit) + return 0xff; + + dev->la = dev->vram[addr]; + dev->lb = dev->vram[addr | 0x1]; + dev->lc = dev->vram[addr | 0x2]; + dev->ld = dev->vram[addr | 0x3]; + if (dev->readmode) { + temp = dev->la; + temp ^= (dev->colourcompare & 1) ? 0xff : 0; + temp &= (dev->colournocare & 1) ? 0xff : 0; + temp2 = dev->lb; + temp2 ^= (dev->colourcompare & 2) ? 0xff : 0; + temp2 &= (dev->colournocare & 2) ? 0xff : 0; + temp3 = dev->lc; + temp3 ^= (dev->colourcompare & 4) ? 0xff : 0; + temp3 &= (dev->colournocare & 4) ? 0xff : 0; + temp4 = dev->ld; + temp4 ^= (dev->colourcompare & 8) ? 0xff : 0; + temp4 &= (dev->colournocare & 8) ? 0xff : 0; + return ~(temp | temp2 | temp3 | temp4); + } + + return dev->vram[addr | readplane]; +} + + +void +ega_init(ega_t *dev, int monitor_type, int is_mono) +{ + int c, d, e; + + dev->vram = (uint8_t *)mem_alloc(0x40000); + dev->vram_limit = 256 * 1024; + dev->vrammask = dev->vram_limit-1; + + for (c = 0; c < 256; c++) { + e = c; + for (d = 0; d < 8; d++) { + ega_rotate[d][c] = e; + e = (e >> 1) | ((e & 1) ? 0x80 : 0); + } + } + + for (c = 0; c < 4; c++) { + for (d = 0; d < 4; d++) { + edatlookup[c][d] = 0; + if (c & 1) edatlookup[c][d] |= 1; + if (d & 1) edatlookup[c][d] |= 2; + if (c & 2) edatlookup[c][d] |= 0x10; + if (d & 2) edatlookup[c][d] |= 0x20; + } + } + + if (is_mono) { + for (c = 0; c < 256; c++) { + switch (monitor_type >> 4) { + case DISPLAY_GREEN: + switch ((c >> 3) & 3) { + case 0: + pallook64[c] = pallook16[c] = makecol32(0, 0, 0); + break; + + case 2: + pallook64[c] = pallook16[c] = makecol32(0x04, 0x8a, 0x20); + break; + + case 1: + pallook64[c] = pallook16[c] = makecol32(0x08, 0xc7, 0x2c); + break; + + case 3: + pallook64[c] = pallook16[c] = makecol32(0x34, 0xff, 0x5d); + break; + } + break; + + case DISPLAY_AMBER: + switch ((c >> 3) & 3) { + case 0: + pallook64[c] = pallook16[c] = makecol32(0, 0, 0); + break; + + case 2: + pallook64[c] = pallook16[c] = makecol32(0xb2, 0x4d, 0x00); + break; + + case 1: + pallook64[c] = pallook16[c] = makecol32(0xef, 0x79, 0x00); + break; + + case 3: + pallook64[c] = pallook16[c] = makecol32(0xff, 0xe3, 0x34); + break; + } + break; + + case DISPLAY_WHITE: + default: + switch ((c >> 3) & 3) { + case 0: + pallook64[c] = pallook16[c] = makecol32(0, 0, 0); + break; + + case 2: + pallook64[c] = pallook16[c] = makecol32(0x7a, 0x81, 0x83); + break; + + case 1: + pallook64[c] = pallook16[c] = makecol32(0xaf, 0xb3, 0xb0); + break; + + case 3: + pallook64[c] = pallook16[c] = makecol32(0xff, 0xfd, 0xed); + break; + } + break; + } + } + } else { + for (c = 0; c < 256; c++) { + pallook64[c] = makecol32(((c >> 2) & 1) * 0xaa, ((c >> 1) & 1) * 0xaa, (c & 1) * 0xaa); + pallook64[c] += makecol32(((c >> 5) & 1) * 0x55, ((c >> 4) & 1) * 0x55, ((c >> 3) & 1) * 0x55); + pallook16[c] = makecol32(((c >> 2) & 1) * 0xaa, ((c >> 1) & 1) * 0xaa, (c & 1) * 0xaa); + pallook16[c] += makecol32(((c >> 4) & 1) * 0x55, ((c >> 4) & 1) * 0x55, ((c >> 4) & 1) * 0x55); + if ((c & 0x17) == 6) + pallook16[c] = makecol32(0xaa, 0x55, 0); + } + } + + dev->pallook = pallook16; + + egaswitches = monitor_type & 0xf; + + old_overscan_color = 0; + + dev->miscout |= 0x22; + dev->oddeven_page = 0; + + dev->seqregs[4] |= 2; + dev->extvram = 1; + + update_overscan = 0; + + dev->crtc[0] = 63; + dev->crtc[6] = 255; + +#ifdef JEGA + dev->is_jega = 0; +#endif +} + + +static void +ega_close(void *priv) +{ + ega_t *dev = (ega_t *)priv; + + free(dev->vram); + free(dev); +} + + +static void +speed_changed(void *priv) +{ + ega_t *dev = (ega_t *)priv; + + ega_recalctimings(dev); +} + + +static void * +ega_standalone_init(const device_t *info) +{ + ega_t *dev; + const wchar_t *fn = NULL; + uint8_t temp; + int c; + + dev = (ega_t *)mem_alloc(sizeof(ega_t)); + memset(dev, 0x00, sizeof(ega_t)); + + overscan_x = 16; + overscan_y = 28; + + switch(info->local) { + case EGA_IBM: + fn = BIOS_IBM_PATH; + break; + + case EGA_COMPAQ: + fn = BIOS_CPQ_PATH; + break; + + case EGA_SUPEREGA: + fn = BIOS_SEGA_PATH; + break; + + default: + break; + } + + if (fn != NULL) { + rom_init(&dev->bios_rom, fn, + 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + + if (dev->bios_rom.rom[0x3ffe] == 0xaa && + dev->bios_rom.rom[0x3fff] == 0x55) { + for (c = 0; c < 0x2000; c++) { + temp = dev->bios_rom.rom[c]; + dev->bios_rom.rom[c] = dev->bios_rom.rom[0x3fff - c]; + dev->bios_rom.rom[0x3fff - c] = temp; + } + } + } + + c = device_get_config_int("monitor_type"); + ega_init(dev, c, (c & 0xf) == 10); + + dev->vram_limit = device_get_config_int("memory") * 1024; + dev->vrammask = dev->vram_limit-1; + + mem_map_add(&dev->mapping, 0xa0000, 0x20000, + ega_read,NULL,NULL, ega_write,NULL,NULL, + NULL, MEM_MAPPING_EXTERNAL, dev); + + timer_add(ega_poll, &dev->vidtime, TIMER_ALWAYS_ENABLED, dev); + + io_sethandler(0x03a0, 0x0040, + ega_in,NULL,NULL, ega_out,NULL,NULL, dev); + + video_inform(VID_TYPE_SPEC, + (const video_timings_t *)info->vid_timing); + + return dev; +} + + +#ifdef JEGA +static uint16_t +chrtosht(FILE *fp) +{ + uint16_t i, j; + + i = (uint8_t) fgetc(fp); + j = (uint8_t) fgetc(fp) << 8; + + return (i | j); +} + + +static unsigned int +getfontx2header(FILE *fp, fontx_h *header) +{ + fread(header->id, ID_LEN, 1, fp); + if (strncmp(header->id, "FONTX2", ID_LEN) != 0) { + return 1; + } + fread(header->name, NAME_LEN, 1, fp); + + header->width = (uint8_t)fgetc(fp); + header->height = (uint8_t)fgetc(fp); + header->type = (uint8_t)fgetc(fp); + + return 0; +} + + +static void +readfontxtbl(fontxTbl *table, unsigned int size, FILE *fp) +{ + while (size > 0) { + table->start = chrtosht(fp); + table->end = chrtosht(fp); + ++table; + --size; + } +} + + +static void +LoadFontxFile(wchar_t *fname) +{ + fontx_h head; + fontxTbl *table; + unsigned int code; + uint8_t size; + unsigned int i; + FILE *mfile; + + if (fname == NULL) return; + if (*fname == '\0') return; + + mfile = romfopen(fname, L"rb"); + if (mfile == NULL) { + DEBUG("MSG: Can't open FONTX2 file: %s\n",fname); + return; + } + + if (getfontx2header(mfile, &head) != 0) { + fclose(mfile); + DEBUG("MSG: FONTX2 header is incorrect\n"); + return; + } + + /* switch whether the font is DBCS or not */ + if (head.type == DBCS) { + if (head.width == 16 && head.height == 16) { + size = getc(mfile); + table = (fontxTbl *)calloc(size, sizeof(fontxTbl)); + readfontxtbl(table, size, mfile); + for (i = 0; i < size; i++) { + for (code = table[i].start; code <= table[i].end; code++) { + fread(&jfont_dbcs_16[(code * 32)], sizeof(uint8_t), 32, mfile); + } + } + } else { + fclose(mfile); + DEBUG("MSG: FONTX2 DBCS font size is not correct\n"); + return; + } + } else { + if (head.width == 8 && head.height == 19) { + fread(jfont_sbcs_19, sizeof(uint8_t), SBCS19_LEN, mfile); + } else { + fclose(mfile); + DEBUG("MSG: FONTX2 SBCS font size is not correct\n"); + return; + } + } + + fclose(mfile); +} + + +static void * +jega_standalone_init(const device_t *info) +{ + ega_t *dev = (ega_t *)ega_standalone_init(info); + + LoadFontxFile(L"video/ibm/ega/jpnhn19x.fnt"); + LoadFontxFile(L"video/ibm/ega/jpnzn16x.fnt"); + + dev->is_jega = 1; + + return dev; } #endif -static int ega_standalone_available(void) +static int +ega_standalone_available(void) { - return rom_present(BIOS_IBM_PATH); + return rom_present(BIOS_IBM_PATH); +} + +static int +cpqega_standalone_available(void) +{ + return rom_present(BIOS_CPQ_PATH); +} + +static int +sega_standalone_available(void) +{ + return rom_present(BIOS_SEGA_PATH); } -static int cpqega_standalone_available(void) -{ - return rom_present(BIOS_CPQ_PATH); -} - - -static int sega_standalone_available(void) -{ - return rom_present(BIOS_SEGA_PATH); -} - - -static void ega_close(void *p) -{ - ega_t *ega = (ega_t *)p; - - free(ega->vram); - free(ega); -} - - -static void ega_speed_changed(void *p) -{ - ega_t *ega = (ega_t *)p; - - ega_recalctimings(ega); -} - - -static const device_config_t ega_config[] = -{ - { - "memory", "Memory size", CONFIG_SELECTION, "", 256, - { - { - "64 kB", 64 - }, - { - "128 kB", 128 - }, - { - "256 kB", 256 - }, - { - "" - } - } - }, - { - .name = "monitor_type", - .description = "Monitor type", - .type = CONFIG_SELECTION, - .selection = - { - { - .description = "EGA Colour, 40x25", - .value = 6 - }, - { - .description = "EGA Colour, 80x25", - .value = 7 - }, - { - .description = "EGA Colour, ECD", - .value = 9 - }, - { - .description = "EGA Monochrome (white)", - .value = 10 | (DISPLAY_WHITE << 4) - }, - { - .description = "EGA Monochrome (green)", - .value = 10 | (DISPLAY_GREEN << 4) - }, - { - .description = "EGA Monochrome (amber)", - .value = 10 | (DISPLAY_AMBER << 4) - }, - { - .description = "" - } - }, - .default_int = 9 - }, - { - .type = -1 - } +static const device_config_t ega_config[] = { + { + "memory", "Memory size", CONFIG_SELECTION, "", 256, + { + { + "64 KB", 64 + }, + { + "128 KB", 128 + }, + { + "256 KB", 256 + }, + { + "" + } + } + }, + { + "monitor_type","Monitor type",CONFIG_SELECTION,"",9, + { + { + "EGA Color, 40x25",6 + }, + { + "EGA Color, 80x25",7 + }, + { + "EGA Color, ECD",9 + }, + { + "EGA Monochrome (white)",10 | (DISPLAY_WHITE << 4) + }, + { + "EGA Monochrome (green)",10 | (DISPLAY_GREEN << 4) + }, + { + "EGA Monochrome (amber)",10 | (DISPLAY_AMBER << 4) + }, + { + "" + } + } + }, + { + "","",-1 + } }; -const device_t ega_device = -{ - "EGA", - DEVICE_ISA, - EGA_IBM, - ega_standalone_init, ega_close, NULL, - ega_standalone_available, - ega_speed_changed, - NULL, - NULL, - ega_config +static const video_timings_t ega_timing = {VID_ISA,8,16,32,8,16,32}; +const device_t ega_device = { + "EGA", + DEVICE_ISA, + EGA_IBM, + ega_standalone_init, ega_close, NULL, + ega_standalone_available, + speed_changed, + NULL, + &ega_timing, + ega_config }; -const device_t cpqega_device = -{ - "Compaq EGA", - DEVICE_ISA, - EGA_COMPAQ, - ega_standalone_init, ega_close, NULL, - cpqega_standalone_available, - ega_speed_changed, - NULL, - NULL, - ega_config +static const video_timings_t ega_compaq_timing = {VID_ISA,8,16,32,8,16,32}; +const device_t ega_compaq_device = { + "Compaq EGA", + DEVICE_ISA, + EGA_COMPAQ, + ega_standalone_init, ega_close, NULL, + cpqega_standalone_available, + speed_changed, + NULL, + &ega_compaq_timing, + ega_config }; -const device_t sega_device = -{ - "SuperEGA", - DEVICE_ISA, - EGA_SUPEREGA, - ega_standalone_init, ega_close, NULL, - sega_standalone_available, - ega_speed_changed, - NULL, - NULL, - ega_config +static const video_timings_t sega_timing = {VID_ISA,8,16,32,8,16,32}; +const device_t sega_device = { + "SuperEGA", + DEVICE_ISA, + EGA_SUPEREGA, + ega_standalone_init, ega_close, NULL, + sega_standalone_available, + speed_changed, + NULL, + &sega_timing, + ega_config }; #ifdef JEGA -const device_t jega_device = -{ - "AX JEGA", - DEVICE_ISA, - EGA_SUPEREGA, - ega_standalone_init, ega_close, NULL, - sega_standalone_available, - ega_speed_changed, - NULL, - NULL, - ega_config +const device_t jega_device = { + "AX JEGA", + DEVICE_ISA, + EGA_SUPEREGA, + ega_standalone_init, ega_close, NULL, + sega_standalone_available, //FIXME: check JEGA roms/fonts?? --FvK + speed_changed, + NULL, + &sega_timing, //FIXME: check these?? --FvK + ega_config }; #endif diff --git a/src/devices/video/vid_ega.h b/src/devices/video/vid_ega.h index fd28210..d82acf2 100644 --- a/src/devices/video/vid_ega.h +++ b/src/devices/video/vid_ega.h @@ -8,7 +8,7 @@ * * Definitions for the IBM EGA driver. * - * Version: @(#)vid_ega.h 1.0.3 2018/04/09 + * Version: @(#)vid_ega.h 1.0.4 2018/09/11 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -60,7 +60,7 @@ #if defined(EMU_MEM_H) && defined(EMU_ROM_H) typedef struct { - mem_mapping_t mapping; + mem_map_t mapping; rom_t bios_rom; diff --git a/src/devices/video/vid_et4000.c b/src/devices/video/vid_et4000.c index 60b6498..f7cfeb9 100644 --- a/src/devices/video/vid_et4000.c +++ b/src/devices/video/vid_et4000.c @@ -8,10 +8,7 @@ * * Emulation of the Tseng Labs ET4000. * - * NOTE: The Korean variants cannot yet be used, we first have to - * sync up the SVGA backend with upstream. - * - * Version: @(#)vid_et4000.c 1.0.10 2018/08/26 + * Version: @(#)vid_et4000.c 1.0.12 2018/10/05 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -53,6 +50,7 @@ #include "../system/mca.h" #include "video.h" #include "vid_svga.h" +#include "vid_svga_render.h" #include "vid_sc1502x_ramdac.h" @@ -62,25 +60,25 @@ typedef struct { - const char *name; - int type; + const char *name; + int type; - svga_t svga; - sc1502x_ramdac_t ramdac; + svga_t svga; - uint8_t pos_regs[8]; + int is_mca; + uint8_t pos_regs[8]; - rom_t bios_rom; + rom_t bios_rom; - uint8_t banking; - uint32_t vram_size, - vram_mask; + uint8_t banking; + uint32_t vram_size, + vram_mask; - uint8_t port_22cb_val; - uint8_t port_32cb_val; - int get_korean_font_enabled; - int get_korean_font_index; - uint16_t get_korean_font_base; + uint8_t port_22cb_val; + uint8_t port_32cb_val; + int get_korean_font_enabled; + int get_korean_font_index; + uint16_t get_korean_font_base; } et4000_t; @@ -107,7 +105,7 @@ et4000_in(uint16_t addr, void *priv) switch (addr) { case 0x3c2: - if (dev->type == 1) { + if (dev->is_mca) { if ((svga->vgapal[0].r + svga->vgapal[0].g + svga->vgapal[0].b) >= 0x4e) return 0; else @@ -124,7 +122,7 @@ et4000_in(uint16_t addr, void *priv) case 0x3c7: case 0x3c8: case 0x3c9: - return sc1502x_ramdac_in(addr, &dev->ramdac, svga); + return sc1502x_ramdac_in(addr, svga->ramdac, svga); case 0x3cd: /*Banking*/ return dev->banking; @@ -146,7 +144,7 @@ et4000k_in(uint16_t addr, void *priv) et4000_t *dev = (et4000_t *)priv; uint8_t val = 0xff; -// if (addr != 0x3da) pclog("IN ET4000 %04X\n", addr); +// if (addr != 0x3da) DEBUG("IN ET4000 %04X\n", addr); switch (addr) { case 0x22cb: @@ -221,7 +219,7 @@ et4000_out(uint16_t addr, uint8_t val, void *priv) case 0x3c7: case 0x3c8: case 0x3c9: - sc1502x_ramdac_out(addr, val, &dev->ramdac, svga); + sc1502x_ramdac_out(addr, val, svga->ramdac, svga); return; case 0x3cd: /*Banking*/ @@ -281,43 +279,43 @@ et4000_out(uint16_t addr, uint8_t val, void *priv) case 0x00: case 0x01: if (svga->vram_max == 64 * 1024) - mem_mapping_enable(&svga->mapping); + mem_map_enable(&svga->mapping); else - mem_mapping_disable(&svga->mapping); + mem_map_disable(&svga->mapping); break; case 0x02: if (svga->vram_max == 128 * 1024) - mem_mapping_enable(&svga->mapping); + mem_map_enable(&svga->mapping); else - mem_mapping_disable(&svga->mapping); + mem_map_disable(&svga->mapping); break; case 0x03: case 0x08: case 0x09: if (svga->vram_max == 256 * 1024) - mem_mapping_enable(&svga->mapping); + mem_map_enable(&svga->mapping); else - mem_mapping_disable(&svga->mapping); + mem_map_disable(&svga->mapping); break; case 0x0a: if (svga->vram_max == 512 * 1024) - mem_mapping_enable(&svga->mapping); + mem_map_enable(&svga->mapping); else - mem_mapping_disable(&svga->mapping); + mem_map_disable(&svga->mapping); break; case 0x0b: if (svga->vram_max == 1024 * 1024) - mem_mapping_enable(&svga->mapping); + mem_map_enable(&svga->mapping); else - mem_mapping_disable(&svga->mapping); + mem_map_disable(&svga->mapping); break; default: - mem_mapping_enable(&svga->mapping); + mem_map_enable(&svga->mapping); break; } } @@ -333,7 +331,7 @@ et4000k_out(uint16_t addr, uint8_t val, void *priv) { et4000_t *dev = (et4000_t *)priv; -// pclog("ET4000k out %04X %02X\n", addr, val); +// DEBUG("ET4000k out %04X %02X\n", addr, val); switch (addr) { case 0x22cb: @@ -443,13 +441,11 @@ et4000_recalctimings(svga_t *svga) } if (dev->type == 2 || dev->type == 3) { -#if NOT_YET if ((svga->render == svga_render_text_80) && ((svga->crtc[0x37] & 0x0A) == 0x0A)) { if ((dev->port_32cb_val & 0xB4) == ((svga->crtc[0x37] & 3) == 2 ? 0xB4 : 0xB0)) { svga->render = svga_render_text_80_ksc5601; } } -#endif } } @@ -482,7 +478,7 @@ et4000_init(const device_t *info) const wchar_t *fn; et4000_t *dev; - dev = (et4000_t *)malloc(sizeof(et4000_t)); + dev = (et4000_t *)mem_alloc(sizeof(et4000_t)); memset(dev, 0x00, sizeof(et4000_t)); dev->name = info->name; dev->type = info->local; @@ -499,6 +495,7 @@ et4000_init(const device_t *info) break; case 1: /* MCA ET4000AX */ + dev->is_mca = 1; dev->vram_size = 1024 << 10; svga_init(&dev->svga, dev, dev->vram_size, et4000_recalctimings, et4000_in, et4000_out, @@ -515,9 +512,7 @@ et4000_init(const device_t *info) dev->vram_size = device_get_config_int("memory") << 10; dev->port_22cb_val = 0x60; dev->port_32cb_val = 0; -#if NOT_YET dev->svga.ksc5601_sbyte_mask = 0x80; -#endif svga_init(&dev->svga, dev, dev->vram_size, et4000_recalctimings, et4000k_in, et4000k_out, NULL, NULL); @@ -529,17 +524,19 @@ et4000_init(const device_t *info) et4000k_in,NULL,NULL, et4000k_out,NULL,NULL, dev); io_sethandler(0x32cb, 1, et4000k_in,NULL,NULL, et4000k_out,NULL,NULL, dev); - loadfont(KOREAN_FONT_ROM_PATH, 6); + video_load_font(KOREAN_FONT_ROM_PATH, 6); fn = KOREAN_BIOS_ROM_PATH; break; } + dev->svga.ramdac = device_add(&sc1502x_ramdac_device); + dev->vram_mask = dev->vram_size - 1; rom_init(&dev->bios_rom, fn, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); - pclog("VIDEO: %s (vram=%dKB)\n", dev->name, dev->vram_size>>10); + DEBUG("VIDEO: %s (vram=%dKB)\n", dev->name, dev->vram_size>>10); return(dev); } @@ -574,15 +571,6 @@ et4000_force_redraw(void *priv) } -static void -et4000_add_status_info(char *s, int max_len, void *priv) -{ - et4000_t *dev = (et4000_t *)priv; - - svga_add_status_info(s, max_len, &dev->svga); -} - - static int et4000_available(void) { @@ -630,7 +618,7 @@ const device_t et4000_isa_device = { et4000_available, et4000_speed_changed, et4000_force_redraw, - et4000_add_status_info, + NULL, et4000_config }; @@ -642,7 +630,7 @@ const device_t et4000_mca_device = { et4000_available, et4000_speed_changed, et4000_force_redraw, - et4000_add_status_info, + NULL, et4000_config }; @@ -654,7 +642,7 @@ const device_t et4000k_isa_device = { et4000k_available, et4000_speed_changed, et4000_force_redraw, - et4000_add_status_info, + NULL, et4000_config }; @@ -666,6 +654,6 @@ const device_t et4000k_tg286_isa_device = { et4000k_available, et4000_speed_changed, et4000_force_redraw, - et4000_add_status_info, + NULL, et4000_config }; diff --git a/src/devices/video/vid_et4000w32.c b/src/devices/video/vid_et4000w32.c index 14ba437..37cd550 100644 --- a/src/devices/video/vid_et4000w32.c +++ b/src/devices/video/vid_et4000w32.c @@ -10,7 +10,9 @@ * * Known bugs: Accelerator doesn't work in planar modes * - * Version: @(#)vid_et4000w32.c 1.0.12 2018/08/26 + * FIXME: Note the madness on line 1163, fix that somehow? --FvK + * + * Version: @(#)vid_et4000w32.c 1.0.14 2018/10/05 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -53,15 +55,11 @@ #include "../system/pci.h" #include "video.h" #include "vid_svga.h" -#if defined(DEV_BRANCH) && defined(USE_STEALTH32) #include "vid_icd2061.h" -#endif #include "vid_stg_ramdac.h" -#if defined(DEV_BRANCH) && defined(USE_STEALTH32) -# define BIOS_ROM_PATH_DIAMOND L"video/tseng/et4000w32/et4000w32.bin" -#endif +#define BIOS_ROM_PATH_DIAMOND L"video/tseng/et4000w32/et4000w32.bin" #define BIOS_ROM_PATH_CARDEX L"video/tseng/et4000w32/cardex.vbi" @@ -79,9 +77,7 @@ enum { ET4000W32_CARDEX = 0, -#if defined(DEV_BRANCH) && defined(USE_STEALTH32) ET4000W32_DIAMOND -#endif }; enum @@ -97,18 +93,14 @@ typedef struct uint32_t val; } fifo_entry_t; -typedef struct et4000w32p_t +typedef struct { - mem_mapping_t linear_mapping; - mem_mapping_t mmu_mapping; + mem_map_t linear_mapping; + mem_map_t mmu_mapping; rom_t bios_rom; svga_t svga; - stg_ramdac_t ramdac; -#if defined(DEV_BRANCH) && defined(USE_STEALTH32) - icd2061_t icd2061; -#endif int index; int pci; @@ -140,9 +132,9 @@ typedef struct et4000w32p_t } queued,internal; uint32_t pattern_addr,source_addr,dest_addr,mix_addr; uint32_t pattern_back,source_back,dest_back,mix_back; - int pattern_x,source_x; - int pattern_x_back,source_x_back; - int pattern_y,source_y; + unsigned int pattern_x,source_x; + unsigned int pattern_x_back,source_x_back; + unsigned int pattern_y,source_y; uint8_t status; uint64_t cpu_dat; int cpu_dat_pos; @@ -169,10 +161,10 @@ typedef struct et4000w32p_t } et4000w32p_t; -uint8_t et4000w32p_mmu_read(uint32_t addr, void *p); -void et4000w32p_mmu_write(uint32_t addr, uint8_t val, void *p); -void et4000w32_blit_start(et4000w32p_t *et4000); -void et4000w32_blit(int count, uint32_t mix, uint32_t sdat, int cpu_input, et4000w32p_t *et4000); +static uint8_t et4000w32p_mmu_read(uint32_t addr, void *p); +static void et4000w32p_mmu_write(uint32_t addr, uint8_t val, void *p); +static void et4000w32_blit_start(et4000w32p_t *et4000); +static void et4000w32_blit(int count, uint32_t mix, uint32_t sdat, int cpu_input, et4000w32p_t *et4000); static void @@ -182,18 +174,17 @@ et4000w32p_recalcmapping(et4000w32p_t *et4000) if (!(et4000->pci_regs[PCI_REG_COMMAND] & PCI_COMMAND_MEM)) { - mem_mapping_disable(&svga->mapping); - mem_mapping_disable(&et4000->linear_mapping); - mem_mapping_disable(&et4000->mmu_mapping); + mem_map_disable(&svga->mapping); + mem_map_disable(&et4000->linear_mapping); + mem_map_disable(&et4000->mmu_mapping); return; } if (svga->crtc[0x36] & 0x10) /*Linear frame buffer*/ { - mem_mapping_set_addr(&et4000->linear_mapping, et4000->linearbase, 0x200000); - svga->linear_base = et4000->linearbase; - mem_mapping_disable(&svga->mapping); - mem_mapping_disable(&et4000->mmu_mapping); + mem_map_set_addr(&et4000->linear_mapping, et4000->linearbase, 0x200000); + mem_map_disable(&svga->mapping); + mem_map_disable(&et4000->mmu_mapping); } else { @@ -203,56 +194,56 @@ et4000w32p_recalcmapping(et4000w32p_t *et4000) switch (map) { case 0x0: case 0x4: case 0x8: case 0xC: /*128k at A0000*/ - mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x20000); - mem_mapping_disable(&et4000->mmu_mapping); + mem_map_set_addr(&svga->mapping, 0xa0000, 0x20000); + mem_map_disable(&et4000->mmu_mapping); svga->banked_mask = 0xffff; break; case 0x1: /*64k at A0000*/ - mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000); - mem_mapping_disable(&et4000->mmu_mapping); + mem_map_set_addr(&svga->mapping, 0xa0000, 0x10000); + mem_map_disable(&et4000->mmu_mapping); svga->banked_mask = 0xffff; break; case 0x2: /*32k at B0000*/ - mem_mapping_set_addr(&svga->mapping, 0xb0000, 0x08000); - mem_mapping_disable(&et4000->mmu_mapping); + mem_map_set_addr(&svga->mapping, 0xb0000, 0x08000); + mem_map_disable(&et4000->mmu_mapping); svga->banked_mask = 0x7fff; break; case 0x3: /*32k at B8000*/ - mem_mapping_set_addr(&svga->mapping, 0xb8000, 0x08000); - mem_mapping_disable(&et4000->mmu_mapping); + mem_map_set_addr(&svga->mapping, 0xb8000, 0x08000); + mem_map_disable(&et4000->mmu_mapping); svga->banked_mask = 0x7fff; break; case 0x5: case 0x9: case 0xD: /*64k at A0000, MMU at B8000*/ - mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000); - mem_mapping_set_addr(&et4000->mmu_mapping, 0xb8000, 0x08000); + mem_map_set_addr(&svga->mapping, 0xa0000, 0x10000); + mem_map_set_addr(&et4000->mmu_mapping, 0xb8000, 0x08000); svga->banked_mask = 0xffff; break; case 0x6: case 0xA: case 0xE: /*32k at B0000, MMU at A8000*/ - mem_mapping_set_addr(&svga->mapping, 0xb0000, 0x08000); - mem_mapping_set_addr(&et4000->mmu_mapping, 0xa8000, 0x08000); + mem_map_set_addr(&svga->mapping, 0xb0000, 0x08000); + mem_map_set_addr(&et4000->mmu_mapping, 0xa8000, 0x08000); svga->banked_mask = 0x7fff; break; case 0x7: case 0xB: case 0xF: /*32k at B8000, MMU at A8000*/ - mem_mapping_set_addr(&svga->mapping, 0xb8000, 0x08000); - mem_mapping_set_addr(&et4000->mmu_mapping, 0xa8000, 0x08000); + mem_map_set_addr(&svga->mapping, 0xb8000, 0x08000); + mem_map_set_addr(&et4000->mmu_mapping, 0xa8000, 0x08000); svga->banked_mask = 0x7fff; break; } - mem_mapping_disable(&et4000->linear_mapping); + mem_map_disable(&et4000->linear_mapping); } et4000->linearbase_old = et4000->linearbase; if (!et4000->interleaved && (et4000->svga.crtc[0x32] & 0x80)) - mem_mapping_disable(&svga->mapping); + mem_map_disable(&svga->mapping); } static void et4000w32p_recalctimings(svga_t *svga) { - et4000w32p_t *et4000 = (et4000w32p_t *)svga->p; svga->ma_latch |= (svga->crtc[0x33] & 0x7) << 16; + if (svga->crtc[0x35] & 0x01) svga->vblankstart += 0x400; if (svga->crtc[0x35] & 0x02) svga->vtotal += 0x400; if (svga->crtc[0x35] & 0x04) svga->dispend += 0x400; @@ -262,22 +253,7 @@ et4000w32p_recalctimings(svga_t *svga) if (svga->crtc[0x3F] & 0x01) svga->htotal += 256; if (svga->attrregs[0x16] & 0x20) svga->hdisp <<= 1; -#if defined(DEV_BRANCH) && defined(USE_STEALTH32) - if (et4000->type == ET4000W32_DIAMOND) - { - switch ((svga->miscout >> 2) & 3) - { - case 0: case 1: break; - case 2: case 3: svga->clock = cpuclock / icd2061_getfreq(&et4000->icd2061, 2); break; - } - } - else - { -#endif - svga->clock = cpuclock / stg_getclock((svga->miscout >> 2) & 3, &et4000->ramdac); -#if defined(DEV_BRANCH) && defined(USE_STEALTH32) - } -#endif + svga->clock = cpuclock / svga->getclock((svga->miscout >> 2) & 3, svga->clock_gen); switch (svga->bpp) { @@ -308,7 +284,7 @@ et4000w32p_in(uint16_t addr, void *p) break; case 0x3C6: case 0x3C7: case 0x3C8: case 0x3C9: - return stg_ramdac_in(addr, &et4000->ramdac, svga); + return stg_ramdac_in(addr, svga->ramdac, svga); case 0x3CB: return et4000->banking2; @@ -358,15 +334,13 @@ et4000w32p_out(uint16_t addr, uint8_t val, void *p) switch (addr) { -#if defined(DEV_BRANCH) && defined(USE_STEALTH32) case 0x3c2: if (et4000->type == ET4000W32_DIAMOND) - icd2061_write(&et4000->icd2061, (val >> 2) & 3); + icd2061_write(svga->clock_gen, (val >> 2) & 3); break; -#endif case 0x3C6: case 0x3C7: case 0x3C8: case 0x3C9: - stg_ramdac_out(addr, val, &et4000->ramdac, svga); + stg_ramdac_out(addr, val, svga->ramdac, svga); return; case 0x3CB: /*Banking extension*/ @@ -622,7 +596,7 @@ static void et4000w32p_queue(et4000w32p_t *et4000, uint32_t addr, uint32_t val, wake_fifo_thread(et4000); } -void et4000w32p_mmu_write(uint32_t addr, uint8_t val, void *p) +static void et4000w32p_mmu_write(uint32_t addr, uint8_t val, void *p) { et4000w32p_t *et4000 = (et4000w32p_t *)p; svga_t *svga = &et4000->svga; @@ -671,7 +645,7 @@ void et4000w32p_mmu_write(uint32_t addr, uint8_t val, void *p) } } -uint8_t et4000w32p_mmu_read(uint32_t addr, void *p) +static uint8_t et4000w32p_mmu_read(uint32_t addr, void *p) { et4000w32p_t *et4000 = (et4000w32p_t *)p; svga_t *svga = &et4000->svga; @@ -765,12 +739,12 @@ uint8_t et4000w32p_mmu_read(uint32_t addr, void *p) return 0xff; } -static int et4000w32_max_x[8]={0,0,4,8,16,32,64,0x70000000}; -static int et4000w32_wrap_x[8]={0,0,3,7,15,31,63,0xFFFFFFFF}; -static int et4000w32_wrap_y[8]={1,2,4,8,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF}; +static unsigned int et4000w32_max_x[8]={0,0,4,8,16,32,64,0x70000000}; +static unsigned int et4000w32_wrap_x[8]={0,0,3,7,15,31,63,0xFFFFFFFF}; +static unsigned int et4000w32_wrap_y[8]={1,2,4,8,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF}; /* int bltout=0; */ -void et4000w32_blit_start(et4000w32p_t *et4000) +static void et4000w32_blit_start(et4000w32p_t *et4000) { if (!(et4000->acl.queued.xy_dir & 0x20)) et4000->acl.internal.error = et4000->acl.internal.dmaj / 2; @@ -821,7 +795,7 @@ void et4000w32_blit_start(et4000w32p_t *et4000) et4000->acl.pix_pos = 0; } -void et4000w32_incx(int c, et4000w32p_t *et4000) +static void et4000w32_incx(int c, et4000w32p_t *et4000) { et4000->acl.dest_addr += c; et4000->acl.pattern_x += c; @@ -882,7 +856,7 @@ void et4000w32_decy(et4000w32p_t *et4000) } } -void et4000w32_blit(int count, uint32_t mix, uint32_t sdat, int cpu_input, et4000w32p_t *et4000) +static void et4000w32_blit(int count, uint32_t mix, uint32_t sdat, int cpu_input, et4000w32p_t *et4000) { svga_t *svga = &et4000->svga; int c,d; @@ -895,10 +869,10 @@ void et4000w32_blit(int count, uint32_t mix, uint32_t sdat, int cpu_input, et400 { while (count--) { - /* if (bltout) pclog("%i,%i : ", et4000->acl.internal.pos_x, et4000->acl.internal.pos_y); */ + /* if (bltout) DEBUG("%i,%i : ", et4000->acl.internal.pos_x, et4000->acl.internal.pos_y); */ pattern = svga->vram[(et4000->acl.pattern_addr + et4000->acl.pattern_x) & 0x1fffff]; source = svga->vram[(et4000->acl.source_addr + et4000->acl.source_x) & 0x1fffff]; - /* if (bltout) pclog("%06X %06X ", (et4000->acl.pattern_addr + et4000->acl.pattern_x) & 0x1fffff, (et4000->acl.source_addr + et4000->acl.source_x) & 0x1fffff); */ + /* if (bltout) DEBUG("%06X %06X ", (et4000->acl.pattern_addr + et4000->acl.pattern_x) & 0x1fffff, (et4000->acl.source_addr + et4000->acl.source_x) & 0x1fffff); */ if (cpu_input == 2) { source = sdat & 0xff; @@ -906,11 +880,11 @@ void et4000w32_blit(int count, uint32_t mix, uint32_t sdat, int cpu_input, et400 } dest = svga->vram[et4000->acl.dest_addr & 0x1fffff]; out = 0; - /* if (bltout) pclog("%06X ", et4000->acl.dest_addr); */ + /* if (bltout) DEBUG("%06X ", et4000->acl.dest_addr); */ if ((et4000->acl.internal.ctrl_routing & 0xa) == 8) { mixdat = svga->vram[(et4000->acl.mix_addr >> 3) & 0x1fffff] & (1 << (et4000->acl.mix_addr & 7)); - /* if (bltout) pclog("%06X %02X ", et4000->acl.mix_addr, svga->vram[(et4000->acl.mix_addr >> 3) & 0x1fffff]); */ + /* if (bltout) DEBUG("%06X %02X ", et4000->acl.mix_addr, svga->vram[(et4000->acl.mix_addr >> 3) & 0x1fffff]); */ } else { @@ -927,7 +901,7 @@ void et4000w32_blit(int count, uint32_t mix, uint32_t sdat, int cpu_input, et400 if (pattern & (1 << c)) d |= 4; if (rop & (1 << d)) out |= (1 << c); } - /* if (bltout) pclog("%06X = %02X\n", et4000->acl.dest_addr & 0x1fffff, out); */ + /* if (bltout) DEBUG("%06X = %02X\n", et4000->acl.dest_addr & 0x1fffff, out); */ if (!(et4000->acl.internal.ctrl_routing & 0x40)) { svga->vram[et4000->acl.dest_addr & 0x1fffff] = out; @@ -1010,11 +984,11 @@ void et4000w32_blit(int count, uint32_t mix, uint32_t sdat, int cpu_input, et400 { while (count--) { - /* if (bltout) pclog("%i,%i : ", et4000->acl.internal.pos_x, et4000->acl.internal.pos_y); */ + /* if (bltout) DEBUG("%i,%i : ", et4000->acl.internal.pos_x, et4000->acl.internal.pos_y); */ pattern = svga->vram[(et4000->acl.pattern_addr + et4000->acl.pattern_x) & 0x1fffff]; source = svga->vram[(et4000->acl.source_addr + et4000->acl.source_x) & 0x1fffff]; - /* if (bltout) pclog("%i %06X %06X %02X %02X ", et4000->acl.pattern_y, (et4000->acl.pattern_addr + et4000->acl.pattern_x) & 0x1fffff, (et4000->acl.source_addr + et4000->acl.source_x) & 0x1fffff, pattern, source); */ + /* if (bltout) DEBUG("%i %06X %06X %02X %02X ", et4000->acl.pattern_y, (et4000->acl.pattern_addr + et4000->acl.pattern_x) & 0x1fffff, (et4000->acl.source_addr + et4000->acl.source_x) & 0x1fffff, pattern, source); */ if (cpu_input == 2) { @@ -1023,11 +997,11 @@ void et4000w32_blit(int count, uint32_t mix, uint32_t sdat, int cpu_input, et400 } dest = svga->vram[et4000->acl.dest_addr & 0x1fffff]; out = 0; - /* if (bltout) pclog("%06X %02X %i %08X %08X ", dest, et4000->acl.dest_addr, mix & 1, mix, et4000->acl.mix_addr); */ + /* if (bltout) DEBUG("%06X %02X %i %08X %08X ", dest, et4000->acl.dest_addr, mix & 1, mix, et4000->acl.mix_addr); */ if ((et4000->acl.internal.ctrl_routing & 0xa) == 8) { mixdat = svga->vram[(et4000->acl.mix_addr >> 3) & 0x1fffff] & (1 << (et4000->acl.mix_addr & 7)); - /* if (bltout) pclog("%06X %02X ", et4000->acl.mix_addr, svga->vram[(et4000->acl.mix_addr >> 3) & 0x1fffff]); */ + /* if (bltout) DEBUG("%06X %02X ", et4000->acl.mix_addr, svga->vram[(et4000->acl.mix_addr >> 3) & 0x1fffff]); */ } else { @@ -1044,7 +1018,7 @@ void et4000w32_blit(int count, uint32_t mix, uint32_t sdat, int cpu_input, et400 if (pattern & (1 << c)) d |= 4; if (rop & (1 << d)) out |= (1 << c); } - /* if (bltout) pclog("%06X = %02X\n", et4000->acl.dest_addr & 0x1fffff, out); */ + /* if (bltout) DEBUG("%06X = %02X\n", et4000->acl.dest_addr & 0x1fffff, out); */ if (!(et4000->acl.internal.ctrl_routing & 0x40)) { svga->vram[et4000->acl.dest_addr & 0x1fffff] = out; @@ -1098,14 +1072,17 @@ void et4000w32_blit(int count, uint32_t mix, uint32_t sdat, int cpu_input, et400 } -void et4000w32p_hwcursor_draw(svga_t *svga, int displine) +static void et4000w32p_hwcursor_draw(svga_t *svga, int displine) { int x, offset; uint8_t dat; - int y_add = (enable_overscan && !suppress_overscan) ? 16 : 0; - int x_add = (enable_overscan && !suppress_overscan) ? 8 : 0; + int y_add, x_add; + offset = svga->hwcursor_latch.xoff; + y_add = (enable_overscan && !suppress_overscan) ? (overscan_y >> 1) : 0; + x_add = (enable_overscan && !suppress_overscan) ? 8 : 0; + for (x = 0; x < 64 - svga->hwcursor_latch.xoff; x += 4) { dat = svga->vram[svga->hwcursor_latch.addr + (offset >> 2)]; @@ -1157,7 +1134,7 @@ static void et4000w32p_io_set(et4000w32p_t *et4000) io_sethandler(0x217A, 0x0002, et4000w32p_in, NULL, NULL, et4000w32p_out, NULL, NULL, et4000); } -uint8_t et4000w32p_pci_read(int func, int addr, void *p) +static uint8_t et4000w32p_pci_read(int func, int addr, void *p) { et4000w32p_t *et4000 = (et4000w32p_t *)p; @@ -1196,7 +1173,7 @@ uint8_t et4000w32p_pci_read(int func, int addr, void *p) return 0; } -void et4000w32p_pci_write(int func, int addr, uint8_t val, void *p) +static void et4000w32p_pci_write(int func, int addr, uint8_t val, void *p) { et4000w32p_t *et4000 = (et4000w32p_t *)p; svga_t *svga = &et4000->svga; @@ -1235,22 +1212,22 @@ void et4000w32p_pci_write(int func, int addr, uint8_t val, void *p) { a = 0xC0000; } - /* pclog("ET4000 bios_rom enabled at %08x\n", a); */ - mem_mapping_set_addr(&et4000->bios_rom.mapping, a, 0x8000); + /* DEBUG("ET4000 bios_rom enabled at %08x\n", a); */ + mem_map_set_addr(&et4000->bios_rom.mapping, a, 0x8000); } else { - /* pclog("ET4000 bios_rom disabled\n"); */ - mem_mapping_disable(&et4000->bios_rom.mapping); + /* DEBUG("ET4000 bios_rom disabled\n"); */ + mem_map_disable(&et4000->bios_rom.mapping); } return; } } -void *et4000w32p_init(const device_t *info) +static void *et4000w32p_init(const device_t *info) { int vram_size; - et4000w32p_t *et4000 = malloc(sizeof(et4000w32p_t)); + et4000w32p_t *et4000 = (et4000w32p_t *)mem_alloc(sizeof(et4000w32p_t)); memset(et4000, 0, sizeof(et4000w32p_t)); vram_size = device_get_config_int("memory"); @@ -1262,6 +1239,9 @@ void *et4000w32p_init(const device_t *info) et4000w32p_in, et4000w32p_out, et4000w32p_hwcursor_draw, NULL); + + et4000->svga.ramdac = device_add(&stg_ramdac_device); + et4000->vram_mask = (vram_size << 20) - 1; et4000->type = info->local; @@ -1270,20 +1250,26 @@ void *et4000w32p_init(const device_t *info) case ET4000W32_CARDEX: rom_init(&et4000->bios_rom, BIOS_ROM_PATH_CARDEX, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + + et4000->svga.clock_gen = et4000->svga.ramdac; + et4000->svga.getclock = stg_getclock; break; -#if defined(DEV_BRANCH) && defined(USE_STEALTH32) + case ET4000W32_DIAMOND: rom_init(&et4000->bios_rom, BIOS_ROM_PATH_DIAMOND, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + + + et4000->svga.clock_gen = device_add(&icd2061_device); + et4000->svga.getclock = icd2061_getclock; break; -#endif } et4000->pci = !!(info->flags & DEVICE_PCI); if (info->flags & DEVICE_PCI) - mem_mapping_disable(&et4000->bios_rom.mapping); + mem_map_disable(&et4000->bios_rom.mapping); - mem_mapping_add(&et4000->linear_mapping, 0, 0, svga_read_linear, svga_readw_linear, svga_readl_linear, svga_write_linear, svga_writew_linear, svga_writel_linear, NULL, 0, &et4000->svga); - mem_mapping_add(&et4000->mmu_mapping, 0, 0, et4000w32p_mmu_read, NULL, NULL, et4000w32p_mmu_write, NULL, NULL, NULL, 0, et4000); + mem_map_add(&et4000->linear_mapping, 0, 0, svga_read_linear, svga_readw_linear, svga_readl_linear, svga_write_linear, svga_writew_linear, svga_writel_linear, NULL, 0, &et4000->svga); + mem_map_add(&et4000->mmu_mapping, 0, 0, et4000w32p_mmu_read, NULL, NULL, et4000w32p_mmu_write, NULL, NULL, NULL, 0, et4000); et4000w32p_io_set(et4000); @@ -1312,19 +1298,17 @@ void *et4000w32p_init(const device_t *info) return et4000; } -#if defined(DEV_BRANCH) && defined(USE_STEALTH32) -int et4000w32p_available(void) +static int et4000w32p_available(void) { return rom_present(BIOS_ROM_PATH_DIAMOND); } -#endif -int et4000w32p_cardex_available(void) +static int et4000w32p_cardex_available(void) { return rom_present(BIOS_ROM_PATH_CARDEX); } -void et4000w32p_close(void *p) +static void et4000w32p_close(void *p) { et4000w32p_t *et4000 = (et4000w32p_t *)p; @@ -1337,35 +1321,20 @@ void et4000w32p_close(void *p) free(et4000); } -void et4000w32p_speed_changed(void *p) +static void et4000w32p_speed_changed(void *p) { et4000w32p_t *et4000 = (et4000w32p_t *)p; svga_recalctimings(&et4000->svga); } -void et4000w32p_force_redraw(void *p) +static void et4000w32p_force_redraw(void *p) { et4000w32p_t *et4000w32p = (et4000w32p_t *)p; et4000w32p->svga.fullchange = changeframecount; } -void et4000w32p_add_status_info(char *s, int max_len, void *p) -{ - et4000w32p_t *et4000 = (et4000w32p_t *)p; - char temps[256]; - uint64_t new_time = plat_timer_read(); - uint64_t status_diff = new_time - et4000->status_time; - et4000->status_time = new_time; - - svga_add_status_info(s, max_len, &et4000->svga); - - sprintf(temps, "%f%% CPU\n%f%% CPU (real)\n\n", ((double)et4000->blitter_time * 100.0) / timer_freq, ((double)et4000->blitter_time * 100.0) / status_diff); - strncat(s, temps, max_len); - - et4000->blitter_time = 0; -} static const device_config_t et4000w32p_config[] = { @@ -1388,54 +1357,50 @@ static const device_config_t et4000w32p_config[] = } }; -const device_t et4000w32p_cardex_vlb_device = -{ - "Tseng Labs ET4000/w32p VLB (Cardex)", - DEVICE_VLB, ET4000W32_CARDEX, - et4000w32p_init, et4000w32p_close, NULL, - et4000w32p_cardex_available, - et4000w32p_speed_changed, - et4000w32p_force_redraw, - et4000w32p_add_status_info, - et4000w32p_config +const device_t et4000w32p_cardex_vlb_device = { + "Tseng Labs ET4000/w32p (Cardex)", + DEVICE_VLB, + ET4000W32_CARDEX, + et4000w32p_init, et4000w32p_close, NULL, + et4000w32p_cardex_available, + et4000w32p_speed_changed, + et4000w32p_force_redraw, + NULL, + et4000w32p_config }; -const device_t et4000w32p_cardex_pci_device = -{ - "Tseng Labs ET4000/w32p PCI (Cardex)", - DEVICE_PCI, ET4000W32_CARDEX, - et4000w32p_init, et4000w32p_close, NULL, - et4000w32p_cardex_available, - et4000w32p_speed_changed, - et4000w32p_force_redraw, - et4000w32p_add_status_info, - et4000w32p_config +const device_t et4000w32p_cardex_pci_device = { + "Tseng Labs ET4000/w32p (Cardex)", + DEVICE_PCI, + ET4000W32_CARDEX, + et4000w32p_init, et4000w32p_close, NULL, + et4000w32p_cardex_available, + et4000w32p_speed_changed, + et4000w32p_force_redraw, + NULL, + et4000w32p_config }; -#if defined(DEV_BRANCH) && defined(USE_STEALTH32) -const device_t et4000w32p_vlb_device = -{ - "Tseng Labs ET4000/w32p VLB (Diamond)", - DEVICE_VLB | DEVICE_UNSTABLE, - ET4000W32_DIAMOND, - et4000w32p_init, et4000w32p_close, NULL, - et4000w32p_available, - et4000w32p_speed_changed, - et4000w32p_force_redraw, - et4000w32p_add_status_info, - et4000w32p_config +const device_t et4000w32p_vlb_device = { + "Tseng Labs ET4000/w32p (Diamond)", + DEVICE_VLB, + ET4000W32_DIAMOND, + et4000w32p_init, et4000w32p_close, NULL, + et4000w32p_available, + et4000w32p_speed_changed, + et4000w32p_force_redraw, + NULL, + et4000w32p_config }; -const device_t et4000w32p_pci_device = -{ - "Tseng Labs ET4000/w32p PCI (Diamond)", - DEVICE_PCI | DEVICE_UNSTABLE, - ET4000W32_DIAMOND, - et4000w32p_init, et4000w32p_close, NULL, - et4000w32p_available, - et4000w32p_speed_changed, - et4000w32p_force_redraw, - et4000w32p_add_status_info, - et4000w32p_config +const device_t et4000w32p_pci_device = { + "Tseng Labs ET4000/w32p (Diamond)", + DEVICE_PCI, + ET4000W32_DIAMOND, + et4000w32p_init, et4000w32p_close, NULL, + et4000w32p_available, + et4000w32p_speed_changed, + et4000w32p_force_redraw, + NULL, + et4000w32p_config }; -#endif diff --git a/src/devices/video/vid_et4000w32i.c b/src/devices/video/vid_et4000w32i.c index abd7443..8dc39cb 100644 --- a/src/devices/video/vid_et4000w32i.c +++ b/src/devices/video/vid_et4000w32i.c @@ -14,7 +14,7 @@ * * This might be of use for an attempt at an ET4000/W32i. * - * Version: @(#)vid_et4000w32i.c 1.0.2 2018/05/06 + * Version: @(#)vid_et4000w32i.c 1.0.3 2018/09/15 * * Author: Sarah Walker, * @@ -96,7 +96,7 @@ int et4000w32_vbus[4]={1,2,4,4}; void et4000w32_mmu_write(uint32_t addr, uint8_t val) { int bank; - pclog("ET4K write %08X %02X %i %02X %02X %04X(%08X):%08X %04X %04X %02X %08X\n",addr,val,acl.cpu_input_num,acl.status,acl.internal.ctrl_routing,CS,cs,pc,CS,DI,mmu.ctrl,mmu.base[2]); + DEBUG("ET4K write %08X %02X %i %02X %02X %04X(%08X):%08X %04X %04X %02X %08X\n",addr,val,acl.cpu_input_num,acl.status,acl.internal.ctrl_routing,CS,cs,pc,CS,DI,mmu.ctrl,mmu.base[2]); switch (addr&0x6000) { case 0x0000: /*MMU 0*/ @@ -107,14 +107,14 @@ void et4000w32_mmu_write(uint32_t addr, uint8_t val) { if (!(acl.status&ACL_XYST)) { -// pclog("!ACL_XYST\n"); +// DEBUG("!ACL_XYST\n"); /*if ((acl.internal.ctrl_routing&0x30)==0x10) */acl.queued.dest_addr=(addr&0x1FFF)+mmu.base[bank]; acl.internal=acl.queued; et4000w32_blit_start(); if (!(acl.internal.ctrl_routing&0x37)) et4000w32_blit(0xFFFFFF, ~0, 0, 0); acl.cpu_input_num=0; } -// else if (!(acl.internal.ctrl_routing&7)) pclog("ACL_XYST\n"); +// else if (!(acl.internal.ctrl_routing&7)) DEBUG("ACL_XYST\n"); if (acl.internal.ctrl_routing&7) { acl.cpu_input=(acl.cpu_input&~(0xFF<<(acl.cpu_input_num*8)))|(val<<(acl.cpu_input_num*8)); @@ -126,12 +126,12 @@ void et4000w32_mmu_write(uint32_t addr, uint8_t val) else if ((acl.internal.ctrl_routing&7)==1) et4000w32_blit(acl.cpu_input_num, ~0, acl.cpu_input, 2); else - pclog("Bad ET4K routing %i\n",acl.internal.ctrl_routing&7); + DEBUG("Bad ET4K routing %i\n",acl.internal.ctrl_routing&7); acl.cpu_input_num=0; } } // else -// pclog("Not ctrl_routing\n"); +// DEBUG("Not ctrl_routing\n"); } else { @@ -202,7 +202,7 @@ void et4000w32_mmu_write(uint32_t addr, uint8_t val) uint8_t et4000w32_mmu_read(uint32_t addr) { int bank; - pclog("ET4K read %08X %04X(%08X):%08X\n",addr,CS,cs,pc); + DEBUG("ET4K read %08X %04X(%08X):%08X\n",addr,CS,cs,pc); switch (addr&0x6000) { case 0x0000: /*MMU 0*/ @@ -275,7 +275,7 @@ int et4000w32_wrap_y[8]={1,2,4,8,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF}; void et4000w32_blit_start() { - pclog("Blit - %08X %08X %08X (%i,%i) %i %i %i %02X %02X %02X\n",acl.internal.pattern_addr,acl.internal.source_addr,acl.internal.dest_addr,acl.internal.dest_addr%640,acl.internal.dest_addr/640,acl.internal.xy_dir,acl.internal.count_x,acl.internal.count_y,acl.internal.rop_fg,acl.internal.rop_bg, acl.internal.ctrl_routing); + DEBUG("Blit - %08X %08X %08X (%i,%i) %i %i %i %02X %02X %02X\n",acl.internal.pattern_addr,acl.internal.source_addr,acl.internal.dest_addr,acl.internal.dest_addr%640,acl.internal.dest_addr/640,acl.internal.xy_dir,acl.internal.count_x,acl.internal.count_y,acl.internal.rop_fg,acl.internal.rop_bg, acl.internal.ctrl_routing); acl.pattern_addr=acl.internal.pattern_addr; acl.source_addr =acl.internal.source_addr; acl.dest_addr =acl.internal.dest_addr; @@ -304,22 +304,22 @@ void et4000w32_blit(int count, uint32_t mix, uint32_t sdat, int cpu_input) uint8_t pattern,source,dest,out; uint8_t rop; -// if (count>400) pclog("New blit - %i,%i %06X (%i,%i) %06X %06X\n",acl.internal.count_x,acl.internal.count_y,acl.dest_addr,acl.dest_addr%640,acl.dest_addr/640,acl.source_addr,acl.pattern_addr); -// pclog("Blit exec - %i %i %i\n",count,acl.internal.pos_x,acl.internal.pos_y); +// if (count>400) DEBUG("New blit - %i,%i %06X (%i,%i) %06X %06X\n",acl.internal.count_x,acl.internal.count_y,acl.dest_addr,acl.dest_addr%640,acl.dest_addr/640,acl.source_addr,acl.pattern_addr); +// DEBUG("Blit exec - %i %i %i\n",count,acl.internal.pos_x,acl.internal.pos_y); while (count--) { - pclog("%i,%i : ",acl.internal.pos_x,acl.internal.pos_y); + DEBUG("%i,%i : ",acl.internal.pos_x,acl.internal.pos_y); if (acl.internal.xy_dir&1) { pattern=vram[(acl.pattern_addr-acl.pattern_x)&0x1FFFFF]; source =vram[(acl.source_addr -acl.source_x) &0x1FFFFF]; - pclog("%06X %06X ",(acl.pattern_addr-acl.pattern_x)&0x1FFFFF,(acl.source_addr -acl.source_x) &0x1FFFFF); + DEBUG("%06X %06X ",(acl.pattern_addr-acl.pattern_x)&0x1FFFFF,(acl.source_addr -acl.source_x) &0x1FFFFF); } else { pattern=vram[(acl.pattern_addr+acl.pattern_x)&0x1FFFFF]; source =vram[(acl.source_addr +acl.source_x) &0x1FFFFF]; - pclog("%06X %06X ",(acl.pattern_addr+acl.pattern_x)&0x1FFFFF,(acl.source_addr +acl.source_x) &0x1FFFFF); + DEBUG("%06X %06X ",(acl.pattern_addr+acl.pattern_x)&0x1FFFFF,(acl.source_addr +acl.source_x) &0x1FFFFF); } if (cpu_input==2) { @@ -328,7 +328,7 @@ void et4000w32_blit(int count, uint32_t mix, uint32_t sdat, int cpu_input) } dest=vram[acl.dest_addr &0x1FFFFF]; out=0; - pclog("%06X %i %08X ",acl.dest_addr,mix&1,mix); + DEBUG("%06X %i %08X ",acl.dest_addr,mix&1,mix); rop = (mix & 1) ? acl.internal.rop_fg:acl.internal.rop_bg; mix>>=1; mix|=0x80000000; for (c=0;c<8;c++) @@ -338,7 +338,7 @@ void et4000w32_blit(int count, uint32_t mix, uint32_t sdat, int cpu_input) if (pattern & (1<>12]=changeframecount; diff --git a/src/devices/video/vid_genius.c b/src/devices/video/vid_genius.c index bb86e4b..3b77cdb 100644 --- a/src/devices/video/vid_genius.c +++ b/src/devices/video/vid_genius.c @@ -63,7 +63,7 @@ * reducing the height of characters so they fit in an 8x12 cell * if necessary. * - * Version: @(#)vid_genius.c 1.0.6 2018/04/06 + * Version: @(#)vid_genius.c 1.0.7 2018/09/22 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -115,7 +115,7 @@ typedef struct { - mem_mapping_t mapping; + mem_map_t mapping; uint8_t mda_crtc[32]; /* The 'CRTC' as the host PC sees it */ int mda_crtcreg; /* Current CRTC register */ @@ -150,46 +150,43 @@ typedef struct { int dispon, blink; int64_t vsynctime; - uint8_t *vram; + uint32_t pal[4]; + + int cols[256][2][2]; + + uint8_t *vram; } genius_t; -/* Mapping of attributes to colours, in MDA emulation mode */ -static int mdacols[256][2][2]; - - static void -recalc_timings(genius_t *genius) +recalc_timings(genius_t *dev) { - double disptime; double _dispontime, _dispofftime; + double disptime; disptime = 0x31; _dispontime = 0x28; _dispofftime = disptime - _dispontime; _dispontime *= MDACONST; _dispofftime *= MDACONST; - genius->dispontime = (int64_t)(_dispontime * (1LL << TIMER_SHIFT)); - genius->dispofftime = (int64_t)(_dispofftime * (1LL << TIMER_SHIFT)); + + dev->dispontime = (int64_t)(_dispontime * (1LL << TIMER_SHIFT)); + dev->dispofftime = (int64_t)(_dispofftime * (1LL << TIMER_SHIFT)); } static void -genius_out(uint16_t addr, uint8_t val, void *priv) +genius_out(uint16_t port, uint8_t val, void *priv) { genius_t *dev = (genius_t *)priv; - switch (addr) { + switch (port) { case 0x3b0: /* Command / control register */ dev->genius_control = val; if (val & 1) - { - mem_mapping_set_addr(&dev->mapping, 0xa0000, 0x28000); - } + mem_map_set_addr(&dev->mapping, 0xa0000, 0x28000); else - { - mem_mapping_set_addr(&dev->mapping, 0xb0000, 0x10000); - } + mem_map_set_addr(&dev->mapping, 0xb0000, 0x10000); break; case 0x3b1: @@ -215,12 +212,12 @@ genius_out(uint16_t addr, uint8_t val, void *priv) return; /* Emulated CGA control register */ - case 0x3D8: + case 0x3d8: dev->cga_ctrl = val; return; /* Emulated CGA colour register */ - case 0x3D9: + case 0x3d9: dev->cga_colour = val; return; } @@ -228,36 +225,47 @@ genius_out(uint16_t addr, uint8_t val, void *priv) static uint8_t -genius_in(uint16_t addr, void *priv) +genius_in(uint16_t port, void *priv) { genius_t *dev = (genius_t *)priv; + uint8_t ret = 0xff; - switch (addr) { + switch (port) { case 0x3b0: case 0x3b2: case 0x3b4: case 0x3b6: case 0x3d0: case 0x3d2: case 0x3d4: case 0x3d6: - return dev->mda_crtcreg; + ret = dev->mda_crtcreg; + break; case 0x3b1: case 0x3b3: case 0x3b5: case 0x3b7: case 0x3d1: case 0x3d3: case 0x3d5: case 0x3d7: - return dev->mda_crtc[dev->mda_crtcreg]; + ret = dev->mda_crtc[dev->mda_crtcreg]; + break; case 0x3b8: - return dev->mda_ctrl; + ret = dev->mda_ctrl; + break; case 0x3d9: - return dev->cga_colour; + ret = dev->cga_colour; + break; case 0x3ba: - return dev->mda_stat; + ret = dev->mda_stat; + break; case 0x3d8: - return dev->cga_ctrl; + ret = dev->cga_ctrl; + break; case 0x3da: - return dev->cga_stat; + ret = dev->cga_stat; + break; + + default: + break; } - return 0xff; + return ret; } @@ -266,13 +274,11 @@ genius_write(uint32_t addr, uint8_t val, void *priv) { genius_t *dev = (genius_t *)priv; - egawrites++; - if (dev->genius_control & 1) { addr = addr % 0x28000; } else { /* If hi-res memory is disabled, only visible in the B000 segment */ - addr = (addr & 0xFFFF) + 0x10000; + addr = (addr & 0xffff) + 0x10000; } dev->vram[addr] = val; @@ -284,13 +290,11 @@ genius_read(uint32_t addr, void *priv) { genius_t *dev = (genius_t *)priv; - egareads++; - if (dev->genius_control & 1) { addr = addr % 0x28000; } else { /* If hi-res memory is disabled, only visible in the B000 segment */ - addr = (addr & 0xFFFF) + 0x10000; + addr = (addr & 0xffff) + 0x10000; } return dev->vram[addr]; @@ -314,7 +318,7 @@ text_line(genius_t *dev, uint8_t background) uint16_t ma = (dev->mda_crtc[13] | (dev->mda_crtc[12] << 8)) & 0x3fff; uint16_t ca = (dev->mda_crtc[15] | (dev->mda_crtc[14] << 8)) & 0x3fff; unsigned char *framebuf = dev->vram + 0x10000; - uint8_t col; + uint32_t col; /* Character height is 12-15 */ charh = 15 - (dev->genius_charh & 3); @@ -354,48 +358,49 @@ text_line(genius_t *dev, uint8_t background) /* MDA underline */ if (sc == charh && ((attr & 7) == 1)) { - col = mdacols[attr][blink][1]; + col = dev->cols[attr][blink][1]; - if (dev->genius_control & 0x20) { - col ^= 15; - } + if (dev->genius_control & 0x20) + col ^= 0xffffff; for (c = 0; c < cw; c++) { if (col != background) - buffer->line[dev->displine][(x * cw) + c] = col; + ((uint32_t *)buffer32->line[dev->displine])[(x * cw) + c] = col; } } else { /* Draw 8 pixels of character */ bitmap[0] = fontdat8x12[chr][sc]; for (c = 0; c < 8; c++) { - col = mdacols[attr][blink][(bitmap[0] & (1 << (c ^ 7))) ? 1 : 0]; + col = dev->cols[attr][blink][(bitmap[0] & (1 << (c ^ 7))) ? 1 : 0]; if (!(dev->enabled) || !(dev->mda_ctrl & 8)) - col = mdacols[0][0][0]; + col = dev->cols[0][0][0]; - if (dev->genius_control & 0x20) { - col ^= 15; - } - if (col != background) { - buffer->line[dev->displine][(x * cw) + c] = col; - } + if (dev->genius_control & 0x20) + col ^= 0xffffff; + + if (col != background) + ((uint32_t *)buffer32->line[dev->displine])[(x * cw) + c] = col; } /* The ninth pixel column... */ if ((chr & ~0x1f) == 0xc0) { /* Echo column 8 for the graphics chars */ - col = buffer->line[dev->displine][(x * cw) + 7]; - if (col != background) buffer->line[dev->displine][(x * cw) + 8] = col; + col = ((uint32_t *)buffer32->line[dev->displine])[(x * cw) + 7]; + if (col != background) + ((uint32_t *)buffer32->line[dev->displine])[(x * cw) + 8] = col; } else { /* Otherwise fill with background */ - col = mdacols[attr][blink][0]; - if (dev->genius_control & 0x20) { - col ^= 15; - } - if (col != background) buffer->line[dev->displine][(x * cw) + 8] = col; + col = dev->cols[attr][blink][0]; + if (dev->genius_control & 0x20) + col ^= 0xffffff; + + if (col != background) + if (col != background) + ((uint32_t *)buffer32->line[dev->displine])[(x * cw) + 8] = col; } if (drawcursor) { for (c = 0; c < cw; c++) - buffer->line[dev->displine][(x * cw) + c] ^= mdacols[attr][0][1]; + ((uint32_t *)buffer32->line[dev->displine])[(x * cw) + c] ^= dev->cols[attr][0][1]; } ++ma; } @@ -409,10 +414,10 @@ cga_line(genius_t *dev) { int x, c; uint32_t dat; - uint8_t ink; + uint32_t ink; uint32_t addr; - ink = (dev->genius_control & 0x20) ? 16 : 16+15; + ink = (dev->genius_control & 0x20) ? dev->pal[0] : dev->pal[3]; /* We draw the CGA at row 600 */ if (dev->displine < 600) return; @@ -426,9 +431,8 @@ cga_line(genius_t *dev) addr++; for (c = 0; c < 8; c++) { - if (dat & 0x80) { - buffer->line[dev->displine][x*8 + c] = ink; - } + if (dat & 0x80) + ((uint32_t *)buffer32->line[dev->displine])[x*8 + c] = ink; dat = dat << 1; } } @@ -441,10 +445,10 @@ hires_line(genius_t *dev) { int x, c; uint32_t dat; - uint8_t ink; + uint32_t ink; uint32_t addr; - ink = (dev->genius_control & 0x20) ? 16 : 16+15; + ink = (dev->genius_control & 0x20) ? dev->pal[0] : dev->pal[3]; /* The first 512 lines live at A0000 */ if (dev->displine < 512) { @@ -460,7 +464,7 @@ hires_line(genius_t *dev) for (c = 0; c < 8; c++) { if (dat & 0x80) - buffer->line[dev->displine][x*8 + c] = ink; + ((uint32_t *)buffer32->line[dev->displine])[x*8 + c] = ink; dat = dat << 1; } } @@ -481,17 +485,16 @@ genius_poll(void *priv) dev->linepos = 1; if (dev->dispon) { if (dev->genius_control & 0x20) - background = 16 + 15; + background = dev->pal[3]; else - background = 16; + background = dev->pal[0]; if (dev->displine == 0) video_wait_for_buffer(); /* Start off with a blank line */ - for (x = 0; x < GENIUS_XSIZE; x++) { - buffer->line[dev->displine][x] = background; - } + for (x = 0; x < GENIUS_XSIZE; x++) + ((uint32_t *)buffer32->line[dev->displine])[x] = background; /* If graphics display enabled, draw graphics on top * of the blanked line */ @@ -532,7 +535,7 @@ genius_poll(void *priv) if (dev->displine == 1008) { /* Hardcode GENIUS_XSIZE * GENIUS_YSIZE window size */ - if ((GENIUS_XSIZE != xsize) || (GENIUS_YSIZE != ysize) || video_force_resize_get()) { + if (GENIUS_XSIZE != xsize || GENIUS_YSIZE != ysize) { xsize = GENIUS_XSIZE; ysize = GENIUS_YSIZE; if (xsize < 64) xsize = 656; @@ -542,7 +545,7 @@ genius_poll(void *priv) if (video_force_resize_get()) video_force_resize_set(0); } - video_blit_memtoscreen_8(0, 0, 0, ysize, xsize, ysize); + video_blit_memtoscreen(0, 0, 0, ysize, xsize, ysize); frames++; @@ -559,21 +562,24 @@ genius_poll(void *priv) static void * genius_init(const device_t *info) { + genius_t *dev; int c; - genius_t *dev = malloc(sizeof(genius_t)); - memset(dev, 0, sizeof(genius_t)); + dev = (genius_t *)mem_alloc(sizeof(genius_t)); + memset(dev, 0x00, sizeof(genius_t)); /* 160k video RAM */ - dev->vram = malloc(0x28000); + dev->vram = (uint8_t *)mem_alloc(0x28000); + + video_load_font(BIOS_ROM_PATH, 4); timer_add(genius_poll, &dev->vidtime, TIMER_ALWAYS_ENABLED, dev); /* Occupy memory between 0xB0000 and 0xBFFFF (moves to 0xA0000 in * high-resolution modes) */ - mem_mapping_add(&dev->mapping, 0xb0000, 0x10000, - genius_read,NULL,NULL, genius_write,NULL,NULL, - NULL, MEM_MAPPING_EXTERNAL, dev); + mem_map_add(&dev->mapping, 0xb0000, 0x10000, + genius_read,NULL,NULL, genius_write,NULL,NULL, + NULL, MEM_MAPPING_EXTERNAL, dev); /* Respond to both MDA and CGA I/O ports */ io_sethandler(0x03b0, 0x000C, @@ -581,28 +587,38 @@ genius_init(const device_t *info) io_sethandler(0x03d0, 0x0010, genius_in,NULL,NULL, genius_out,NULL,NULL, dev); + dev->pal[0] = makecol(0x00, 0x00, 0x00); + dev->pal[1] = makecol(0x55, 0x55, 0x55); + dev->pal[2] = makecol(0xaa, 0xaa, 0xaa); + dev->pal[3] = makecol(0xff, 0xff, 0xff); + /* MDA attributes */ /* I don't know if the Genius's MDA emulation actually does * emulate bright / non-bright. For the time being pretend it does. */ for (c = 0; c < 256; c++) { - mdacols[c][0][0] = mdacols[c][1][0] = mdacols[c][1][1] = 16; - if (c & 8) - mdacols[c][0][1] = 15 + 16; - else - mdacols[c][0][1] = 7 + 16; + dev->cols[c][0][0] = dev->cols[c][1][0] = + dev->cols[c][1][1] = dev->pal[0]; + if (c & 0x08) + dev->cols[c][0][1] = dev->pal[3]; + else + dev->cols[c][0][1] = dev->pal[2]; } - mdacols[0x70][0][1] = 16; - mdacols[0x70][0][0] = mdacols[0x70][1][0] = mdacols[0x70][1][1] = 16 + 15; - mdacols[0xF0][0][1] = 16; - mdacols[0xF0][0][0] = mdacols[0xF0][1][0] = mdacols[0xF0][1][1] = 16 + 15; - mdacols[0x78][0][1] = 16 + 7; - mdacols[0x78][0][0] = mdacols[0x78][1][0] = mdacols[0x78][1][1] = 16 + 15; - mdacols[0xF8][0][1] = 16 + 7; - mdacols[0xF8][0][0] = mdacols[0xF8][1][0] = mdacols[0xF8][1][1] = 16 + 15; - mdacols[0x00][0][1] = mdacols[0x00][1][1] = 16; - mdacols[0x08][0][1] = mdacols[0x08][1][1] = 16; - mdacols[0x80][0][1] = mdacols[0x80][1][1] = 16; - mdacols[0x88][0][1] = mdacols[0x88][1][1] = 16; + dev->cols[0x70][0][1] = dev->pal[0]; + dev->cols[0x70][0][0] = dev->cols[0x70][1][0] = + dev->cols[0x70][1][1] = dev->pal[3]; + dev->cols[0xF0][0][1] = dev->pal[0]; + dev->cols[0xF0][0][0] = dev->cols[0xF0][1][0] = + dev->cols[0xF0][1][1] = dev->pal[3]; + dev->cols[0x78][0][1] = dev->pal[2]; + dev->cols[0x78][0][0] = dev->cols[0x78][1][0] = + dev->cols[0x78][1][1] = dev->pal[3]; + dev->cols[0xF8][0][1] = dev->pal[2]; + dev->cols[0xF8][0][0] = dev->cols[0xF8][1][0] = + dev->cols[0xF8][1][1] = dev->pal[3]; + dev->cols[0x00][0][1] = dev->cols[0x00][1][1] = dev->pal[0]; + dev->cols[0x08][0][1] = dev->cols[0x08][1][1] = dev->pal[0]; + dev->cols[0x80][0][1] = dev->cols[0x80][1][1] = dev->pal[0]; + dev->cols[0x88][0][1] = dev->cols[0x88][1][1] = dev->pal[0]; /* Start off in 80x25 text mode */ dev->cga_stat = 0xF4; @@ -610,6 +626,8 @@ genius_init(const device_t *info) dev->enabled = 1; dev->genius_charh = 0x90; /* Native character height register */ + video_inform(VID_TYPE_MDA, info->vid_timing); + return dev; } @@ -620,7 +638,6 @@ genius_close(void *priv) genius_t *dev = (genius_t *)priv; free(dev->vram); - free(dev); } @@ -641,12 +658,15 @@ speed_changed(void *priv) } +static const video_timings_t genius_timings = { VID_ISA,8,16,32,8,16,32 }; + const device_t genius_device = { "Genius VHR", DEVICE_ISA, 0, genius_init, genius_close, NULL, genius_available, speed_changed, - NULL, NULL, + NULL, + &genius_timings, NULL }; diff --git a/src/devices/video/vid_hercules.c b/src/devices/video/vid_hercules.c index 050ddd4..f22c786 100644 --- a/src/devices/video/vid_hercules.c +++ b/src/devices/video/vid_hercules.c @@ -8,7 +8,7 @@ * * Hercules emulation. * - * Version: @(#)vid_hercules.c 1.0.6 2018/05/06 + * Version: @(#)vid_hercules.c 1.0.7 2018/09/22 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -52,402 +52,452 @@ #include "video.h" -typedef struct hercules_t -{ - mem_mapping_t mapping; - - uint8_t crtc[32]; - int crtcreg; +typedef struct { + mem_map_t mapping; - uint8_t ctrl, ctrl2, stat; + uint8_t crtc[32]; + int crtcreg; - int64_t dispontime, dispofftime; - int64_t vidtime; - - int firstline, lastline; + uint8_t ctrl, + ctrl2, + stat; - int linepos, displine; - int vc, sc; - uint16_t ma, maback; - int con, coff, cursoron; - int dispon, blink; - int64_t vsynctime; - int vadj; + int64_t dispontime, + dispofftime; + int64_t vidtime; - uint8_t *vram; + int firstline, + lastline; + + int linepos, + displine; + int vc, + sc; + uint16_t ma, + maback; + int con, coff, + cursoron; + int dispon, + blink; + int64_t vsynctime; + int vadj; + + int cols[256][2][2]; + + uint8_t *vram; } hercules_t; -static int mdacols[256][2][2]; -void hercules_recalctimings(hercules_t *hercules); -void hercules_write(uint32_t addr, uint8_t val, void *p); -uint8_t hercules_read(uint32_t addr, void *p); - - -void hercules_out(uint16_t addr, uint8_t val, void *p) +static void +recalc_timings(hercules_t *dev) { - hercules_t *hercules = (hercules_t *)p; -// pclog("Herc out %04X %02X\n",addr,val); - switch (addr) - { - case 0x3b0: case 0x3b2: case 0x3b4: case 0x3b6: - hercules->crtcreg = val & 31; - return; - case 0x3b1: case 0x3b3: case 0x3b5: case 0x3b7: - hercules->crtc[hercules->crtcreg] = val; - if (hercules->crtc[10] == 6 && hercules->crtc[11] == 7) /*Fix for Generic Turbo XT BIOS, which sets up cursor registers wrong*/ - { - hercules->crtc[10] = 0xb; - hercules->crtc[11] = 0xc; - } - hercules_recalctimings(hercules); - return; - case 0x3b8: - hercules->ctrl = val; - return; - case 0x3bf: - hercules->ctrl2 = val; - if (val & 2) - mem_mapping_set_addr(&hercules->mapping, 0xb0000, 0x10000); - else - mem_mapping_set_addr(&hercules->mapping, 0xb0000, 0x08000); - return; - } -} + double disptime; + double _dispontime, _dispofftime; -uint8_t hercules_in(uint16_t addr, void *p) -{ - hercules_t *hercules = (hercules_t *)p; - // pclog("Herc in %04X %02X %04X:%04X %04X\n",addr,(hercules_stat & 0xF) | ((hercules_stat & 8) << 4),CS,pc,CX); - switch (addr) - { - case 0x3b0: case 0x3b2: case 0x3b4: case 0x3b6: - return hercules->crtcreg; - case 0x3b1: case 0x3b3: case 0x3b5: case 0x3b7: - return hercules->crtc[hercules->crtcreg]; - case 0x3ba: - return (hercules->stat & 0xf) | ((hercules->stat & 8) << 4); - } - return 0xff; -} + disptime = dev->crtc[0] + 1; + _dispontime = dev->crtc[1]; + _dispofftime = disptime - _dispontime; + _dispontime *= MDACONST; + _dispofftime *= MDACONST; -void hercules_write(uint32_t addr, uint8_t val, void *p) -{ - hercules_t *hercules = (hercules_t *)p; - egawrites++; -// pclog("Herc write %08X %02X\n",addr,val); - hercules->vram[addr & 0xffff] = val; -} - -uint8_t hercules_read(uint32_t addr, void *p) -{ - hercules_t *hercules = (hercules_t *)p; - egareads++; - return hercules->vram[addr & 0xffff]; -} - -void hercules_recalctimings(hercules_t *hercules) -{ - double disptime; - double _dispontime, _dispofftime; - disptime = hercules->crtc[0] + 1; - _dispontime = hercules->crtc[1]; - _dispofftime = disptime - _dispontime; - _dispontime *= MDACONST; - _dispofftime *= MDACONST; - hercules->dispontime = (int64_t)(_dispontime * (1 << TIMER_SHIFT)); - hercules->dispofftime = (int64_t)(_dispofftime * (1 << TIMER_SHIFT)); -} - -void hercules_poll(void *p) -{ - hercules_t *hercules = (hercules_t *)p; - uint16_t ca = (hercules->crtc[15] | (hercules->crtc[14] << 8)) & 0x3fff; - int drawcursor; - int x, c; - int oldvc; - uint8_t chr, attr; - uint16_t dat; - int oldsc; - int blink; - if (!hercules->linepos) - { - //pclog("Poll %i %i\n",vc,sc); - hercules->vidtime += hercules->dispofftime; - hercules->stat |= 1; - hercules->linepos = 1; - oldsc = hercules->sc; - if ((hercules->crtc[8] & 3) == 3) - hercules->sc = (hercules->sc << 1) & 7; - if (hercules->dispon) - { - if (hercules->displine < hercules->firstline) - { - hercules->firstline = hercules->displine; - video_wait_for_buffer(); - } - hercules->lastline = hercules->displine; - if ((hercules->ctrl & 2) && (hercules->ctrl2 & 1)) - { - ca = (hercules->sc & 3) * 0x2000; - if ((hercules->ctrl & 0x80) && (hercules->ctrl2 & 2)) - ca += 0x8000; -// printf("Draw herc %04X\n",ca); - for (x = 0; x < hercules->crtc[1]; x++) - { - dat = (hercules->vram[((hercules->ma << 1) & 0x1fff) + ca] << 8) | hercules->vram[((hercules->ma << 1) & 0x1fff) + ca + 1]; - hercules->ma++; - for (c = 0; c < 16; c++) - buffer->line[hercules->displine][(x << 4) + c] = (dat & (32768 >> c)) ? 7 : 0; - } - } - else - { - for (x = 0; x < hercules->crtc[1]; x++) - { - chr = hercules->vram[(hercules->ma << 1) & 0xfff]; - attr = hercules->vram[((hercules->ma << 1) + 1) & 0xfff]; - drawcursor = ((hercules->ma == ca) && hercules->con && hercules->cursoron); - blink = ((hercules->blink & 16) && (hercules->ctrl & 0x20) && (attr & 0x80) && !drawcursor); - if (hercules->sc == 12 && ((attr & 7) == 1)) - { - for (c = 0; c < 9; c++) - buffer->line[hercules->displine][(x * 9) + c] = mdacols[attr][blink][1]; - } - else - { - for (c = 0; c < 8; c++) - buffer->line[hercules->displine][(x * 9) + c] = mdacols[attr][blink][(fontdatm[chr][hercules->sc] & (1 << (c ^ 7))) ? 1 : 0]; - if ((chr & ~0x1f) == 0xc0) buffer->line[hercules->displine][(x * 9) + 8] = mdacols[attr][blink][fontdatm[chr][hercules->sc] & 1]; - else buffer->line[hercules->displine][(x * 9) + 8] = mdacols[attr][blink][0]; - } - hercules->ma++; - if (drawcursor) - { - for (c = 0; c < 9; c++) - buffer->line[hercules->displine][(x * 9) + c] ^= mdacols[attr][0][1]; - } - } - } - } - hercules->sc = oldsc; - if (hercules->vc == hercules->crtc[7] && !hercules->sc) - { - hercules->stat |= 8; -// printf("VSYNC on %i %i\n",vc,sc); - } - hercules->displine++; - if (hercules->displine >= 500) - hercules->displine = 0; - } - else - { - hercules->vidtime += hercules->dispontime; - if (hercules->dispon) - hercules->stat &= ~1; - hercules->linepos = 0; - if (hercules->vsynctime) - { - hercules->vsynctime--; - if (!hercules->vsynctime) - { - hercules->stat &= ~8; -// printf("VSYNC off %i %i\n",vc,sc); - } - } - if (hercules->sc == (hercules->crtc[11] & 31) || ((hercules->crtc[8] & 3) == 3 && hercules->sc == ((hercules->crtc[11] & 31) >> 1))) - { - hercules->con = 0; - hercules->coff = 1; - } - if (hercules->vadj) - { - hercules->sc++; - hercules->sc &= 31; - hercules->ma = hercules->maback; - hercules->vadj--; - if (!hercules->vadj) - { - hercules->dispon = 1; - hercules->ma = hercules->maback = (hercules->crtc[13] | (hercules->crtc[12] << 8)) & 0x3fff; - hercules->sc = 0; - } - } - else if (hercules->sc == hercules->crtc[9] || ((hercules->crtc[8] & 3) == 3 && hercules->sc == (hercules->crtc[9] >> 1))) - { - hercules->maback = hercules->ma; - hercules->sc = 0; - oldvc = hercules->vc; - hercules->vc++; - hercules->vc &= 127; - if (hercules->vc == hercules->crtc[6]) - hercules->dispon = 0; - if (oldvc == hercules->crtc[4]) - { -// printf("Display over at %i\n",displine); - hercules->vc = 0; - hercules->vadj = hercules->crtc[5]; - if (!hercules->vadj) hercules->dispon=1; - if (!hercules->vadj) hercules->ma = hercules->maback = (hercules->crtc[13] | (hercules->crtc[12] << 8)) & 0x3fff; - if ((hercules->crtc[10] & 0x60) == 0x20) hercules->cursoron = 0; - else hercules->cursoron = hercules->blink & 16; - } - if (hercules->vc == hercules->crtc[7]) - { - hercules->dispon = 0; - hercules->displine = 0; - hercules->vsynctime = 16;//(crtcm[3]>>4)+1; - if (hercules->crtc[7]) - { -// printf("Lastline %i Firstline %i %i\n",lastline,firstline,lastline-firstline); - if ((hercules->ctrl & 2) && (hercules->ctrl2 & 1)) x = hercules->crtc[1] << 4; - else x = hercules->crtc[1] * 9; - hercules->lastline++; - if ((x != xsize) || ((hercules->lastline - hercules->firstline) != ysize) || video_force_resize_get()) - { - xsize = x; - ysize = hercules->lastline - hercules->firstline; -// printf("Resize to %i,%i - R1 %i\n",xsize,ysize,crtcm[1]); - if (xsize < 64) xsize = 656; - if (ysize < 32) ysize = 200; - set_screen_size(xsize, ysize); - - if (video_force_resize_get()) - video_force_resize_set(0); - } - video_blit_memtoscreen_8(0, hercules->firstline, 0, ysize, xsize, ysize); - frames++; - if ((hercules->ctrl & 2) && (hercules->ctrl2 & 1)) - { - video_res_x = hercules->crtc[1] * 16; - video_res_y = hercules->crtc[6] * 4; - video_bpp = 1; - } - else - { - video_res_x = hercules->crtc[1]; - video_res_y = hercules->crtc[6]; - video_bpp = 0; - } - } - hercules->firstline = 1000; - hercules->lastline = 0; - hercules->blink++; - } - } - else - { - hercules->sc++; - hercules->sc &= 31; - hercules->ma = hercules->maback; - } - if ((hercules->sc == (hercules->crtc[10] & 31) || ((hercules->crtc[8] & 3) == 3 && hercules->sc == ((hercules->crtc[10] & 31) >> 1)))) - { - hercules->con = 1; -// printf("Cursor on - %02X %02X %02X\n",crtcm[8],crtcm[10],crtcm[11]); - } - } + dev->dispontime = (int64_t)(_dispontime * (1LL << TIMER_SHIFT)); + dev->dispofftime = (int64_t)(_dispofftime * (1LL << TIMER_SHIFT)); } -void *hercules_init(const device_t *info) +static void +hercules_out(uint16_t addr, uint8_t val, void *priv) { - int c; - hercules_t *hercules = malloc(sizeof(hercules_t)); - memset(hercules, 0, sizeof(hercules_t)); + hercules_t *dev = (hercules_t *)priv; - hercules->vram = malloc(0x10000); + switch (addr) { + case 0x03b0: + case 0x03b2: + case 0x03b4: + case 0x03b6: + dev->crtcreg = val & 31; + break; - timer_add(hercules_poll, &hercules->vidtime, TIMER_ALWAYS_ENABLED, hercules); - mem_mapping_add(&hercules->mapping, 0xb0000, 0x08000, hercules_read, NULL, NULL, hercules_write, NULL, NULL, NULL, MEM_MAPPING_EXTERNAL, hercules); - io_sethandler(0x03b0, 0x0010, hercules_in, NULL, NULL, hercules_out, NULL, NULL, hercules); + case 0x03b1: + case 0x03b3: + case 0x03b5: + case 0x03b7: + dev->crtc[dev->crtcreg] = val; - for (c = 0; c < 256; c++) - { - mdacols[c][0][0] = mdacols[c][1][0] = mdacols[c][1][1] = 16; - if (c & 8) mdacols[c][0][1] = 15 + 16; - else mdacols[c][0][1] = 7 + 16; - } - mdacols[0x70][0][1] = 16; - mdacols[0x70][0][0] = mdacols[0x70][1][0] = mdacols[0x70][1][1] = 16 + 15; - mdacols[0xF0][0][1] = 16; - mdacols[0xF0][0][0] = mdacols[0xF0][1][0] = mdacols[0xF0][1][1] = 16 + 15; - mdacols[0x78][0][1] = 16 + 7; - mdacols[0x78][0][0] = mdacols[0x78][1][0] = mdacols[0x78][1][1] = 16 + 15; - mdacols[0xF8][0][1] = 16 + 7; - mdacols[0xF8][0][0] = mdacols[0xF8][1][0] = mdacols[0xF8][1][1] = 16 + 15; - mdacols[0x00][0][1] = mdacols[0x00][1][1] = 16; - mdacols[0x08][0][1] = mdacols[0x08][1][1] = 16; - mdacols[0x80][0][1] = mdacols[0x80][1][1] = 16; - mdacols[0x88][0][1] = mdacols[0x88][1][1] = 16; + /* + * Fix for Generic Turbo XT BIOS, which + * sets up cursor registers wrong. + */ + if (dev->crtc[10] == 6 && dev->crtc[11] == 7) { + dev->crtc[10] = 0xb; + dev->crtc[11] = 0xc; + } + recalc_timings(dev); + break; - overscan_x = overscan_y = 0; + case 0x03b8: + dev->ctrl = val; + break; - cga_palette = device_get_config_int("rgb_type") << 1; - if (cga_palette > 6) - { - cga_palette = 0; + case 0x03bf: + dev->ctrl2 = val; + if (val & 0x02) + mem_map_set_addr(&dev->mapping, 0xb0000, 0x10000); + else + mem_map_set_addr(&dev->mapping, 0xb0000, 0x08000); + break; + + default: + break; + } +} + + +static uint8_t +hercules_in(uint16_t addr, void *priv) +{ + hercules_t *dev = (hercules_t *)priv; + uint8_t ret = 0xff; + + switch (addr) { + case 0x03b0: + case 0x03b2: + case 0x03b4: + case 0x03b6: + ret = dev->crtcreg; + break; + + case 0x03b1: + case 0x03b3: + case 0x03b5: + case 0x03b7: + ret = dev->crtc[dev->crtcreg]; + break; + + case 0x03ba: + ret = (dev->stat & 0xf) | ((dev->stat & 8) << 4); + break; + + default: + break; + } + + return(ret); +} + + +static void +hercules_write(uint32_t addr, uint8_t val, void *priv) +{ + hercules_t *dev = (hercules_t *)priv; + + dev->vram[addr & 0xffff] = val; +} + + +static uint8_t +hercules_read(uint32_t addr, void *priv) +{ + hercules_t *dev = (hercules_t *)priv; + + return(dev->vram[addr & 0xffff]); +} + + +static void +hercules_poll(void *priv) +{ + hercules_t *dev = (hercules_t *)priv; + uint8_t chr, attr; + uint16_t ca, dat; + int oldsc, blink; + int x, c, oldvc; + int drawcursor; + + ca = (dev->crtc[15] | (dev->crtc[14] << 8)) & 0x3fff; + + if (! dev->linepos) { + dev->vidtime += dev->dispofftime; + dev->stat |= 1; + dev->linepos = 1; + oldsc = dev->sc; + + if ((dev->crtc[8] & 3) == 3) + dev->sc = (dev->sc << 1) & 7; + + if (dev->dispon) { + if (dev->displine < dev->firstline) { + dev->firstline = dev->displine; + video_wait_for_buffer(); + } + dev->lastline = dev->displine; + + if ((dev->ctrl & 2) && (dev->ctrl2 & 1)) { + ca = (dev->sc & 3) * 0x2000; + if ((dev->ctrl & 0x80) && (dev->ctrl2 & 2)) + ca += 0x8000; + + for (x = 0; x < dev->crtc[1]; x++) { + dat = (dev->vram[((dev->ma << 1) & 0x1fff) + ca] << 8) | dev->vram[((dev->ma << 1) & 0x1fff) + ca + 1]; + dev->ma++; + for (c = 0; c < 16; c++) + buffer->line[dev->displine][(x << 4) + c] = (dat & (32768 >> c)) ? 7 : 0; + } + } else { + for (x = 0; x < dev->crtc[1]; x++) { + chr = dev->vram[(dev->ma << 1) & 0xfff]; + attr = dev->vram[((dev->ma << 1) + 1) & 0xfff]; + drawcursor = ((dev->ma == ca) && dev->con && dev->cursoron); + blink = ((dev->blink & 16) && (dev->ctrl & 0x20) && (attr & 0x80) && !drawcursor); + + if (dev->sc == 12 && ((attr & 7) == 1)) { + for (c = 0; c < 9; c++) + buffer->line[dev->displine][(x * 9) + c] = dev->cols[attr][blink][1]; + } else { + for (c = 0; c < 8; c++) + buffer->line[dev->displine][(x * 9) + c] = dev->cols[attr][blink][(fontdatm[chr][dev->sc] & (1 << (c ^ 7))) ? 1 : 0]; + + if ((chr & ~0x1f) == 0xc0) + buffer->line[dev->displine][(x * 9) + 8] = dev->cols[attr][blink][fontdatm[chr][dev->sc] & 1]; + else + buffer->line[dev->displine][(x * 9) + 8] = dev->cols[attr][blink][0]; + } + dev->ma++; + + if (drawcursor) { + for (c = 0; c < 9; c++) + buffer->line[dev->displine][(x * 9) + c] ^= dev->cols[attr][0][1]; + } + } + } } - cgapal_rebuild(); + dev->sc = oldsc; - /* Force the LPT3 port to be enabled. */ - parallel_enabled[2] = 1; - parallel_setup(3, 0x3BC); + if (dev->vc == dev->crtc[7] && !dev->sc) + dev->stat |= 8; + dev->displine++; + if (dev->displine >= 500) + dev->displine = 0; + } else { + dev->vidtime += dev->dispontime; - return hercules; + if (dev->dispon) + dev->stat &= ~1; + + dev->linepos = 0; + if (dev->vsynctime) { + dev->vsynctime--; + if (! dev->vsynctime) + dev->stat &= ~8; + } + + if (dev->sc == (dev->crtc[11] & 31) || + ((dev->crtc[8] & 3)==3 && dev->sc == ((dev->crtc[11] & 31) >> 1))) { + dev->con = 0; + dev->coff = 1; + } + + if (dev->vadj) { + dev->sc++; + dev->sc &= 31; + dev->ma = dev->maback; + + dev->vadj--; + if (! dev->vadj) { + dev->dispon = 1; + dev->ma = dev->maback = (dev->crtc[13] | (dev->crtc[12] << 8)) & 0x3fff; + dev->sc = 0; + } + } else if (dev->sc == dev->crtc[9] || ((dev->crtc[8] & 3) == 3 && dev->sc == (dev->crtc[9] >> 1))) { + dev->maback = dev->ma; + dev->sc = 0; + oldvc = dev->vc; + dev->vc++; + dev->vc &= 127; + if (dev->vc == dev->crtc[6]) + dev->dispon = 0; + + if (oldvc == dev->crtc[4]) { + dev->vc = 0; + dev->vadj = dev->crtc[5]; + if (! dev->vadj) + dev->dispon = 1; + if (! dev->vadj) + dev->ma = dev->maback = (dev->crtc[13] | (dev->crtc[12] << 8)) & 0x3fff; + if ((dev->crtc[10] & 0x60) == 0x20) + dev->cursoron = 0; + else + dev->cursoron = dev->blink & 16; + } + + if (dev->vc == dev->crtc[7]) { + dev->dispon = 0; + dev->displine = 0; + dev->vsynctime = 16;//(crtcm[3]>>4)+1; + if (dev->crtc[7]) { + if ((dev->ctrl & 2) && (dev->ctrl2 & 1)) + x = dev->crtc[1] << 4; + else + x = dev->crtc[1] * 9; + + dev->lastline++; + if ((x != xsize) || ((dev->lastline - dev->firstline) != ysize) || video_force_resize_get()) { + xsize = x; + ysize = dev->lastline - dev->firstline; + if (xsize < 64) xsize = 656; + if (ysize < 32) ysize = 200; + set_screen_size(xsize, ysize); + + if (video_force_resize_get()) + video_force_resize_set(0); + } + + video_blit_memtoscreen_8(0, dev->firstline, 0, ysize, xsize, ysize); + frames++; + if ((dev->ctrl & 2) && (dev->ctrl2 & 1)) { + video_res_x = dev->crtc[1] * 16; + video_res_y = dev->crtc[6] * 4; + video_bpp = 1; + } else { + video_res_x = dev->crtc[1]; + video_res_y = dev->crtc[6]; + video_bpp = 0; + } + } + dev->firstline = 1000; + dev->lastline = 0; + dev->blink++; + } + } else { + dev->sc++; + dev->sc &= 31; + dev->ma = dev->maback; + } + + if ((dev->sc == (dev->crtc[10] & 31) || + ((dev->crtc[8] & 3)==3 && dev->sc == ((dev->crtc[10] & 31) >> 1)))) + dev->con = 1; + } } -void hercules_close(void *p) -{ - hercules_t *hercules = (hercules_t *)p; - free(hercules->vram); - free(hercules); +static void * +hercules_init(const device_t *info) +{ + hercules_t *dev; + int c; + + dev = (hercules_t *)mem_alloc(sizeof(hercules_t)); + memset(dev, 0x00, sizeof(hercules_t)); + + dev->vram = (uint8_t *)mem_alloc(0x10000); + + timer_add(hercules_poll, &dev->vidtime, TIMER_ALWAYS_ENABLED, dev); + + mem_map_add(&dev->mapping, 0xb0000, 0x08000, + hercules_read,NULL,NULL, hercules_write,NULL,NULL, + NULL, MEM_MAPPING_EXTERNAL, dev); + + io_sethandler(0x03b0, 16, + hercules_in,NULL,NULL, hercules_out,NULL,NULL, dev); + + for (c = 0; c < 256; c++) { + dev->cols[c][0][0] = dev->cols[c][1][0] = dev->cols[c][1][1] = 16; + + if (c & 0x08) + dev->cols[c][0][1] = 15 + 16; + else + dev->cols[c][0][1] = 7 + 16; + } + dev->cols[0x70][0][1] = 16; + dev->cols[0x70][0][0] = dev->cols[0x70][1][0] = + dev->cols[0x70][1][1] = 16 + 15; + dev->cols[0xF0][0][1] = 16; + dev->cols[0xF0][0][0] = dev->cols[0xF0][1][0] = + dev->cols[0xF0][1][1] = 16 + 15; + dev->cols[0x78][0][1] = 16 + 7; + dev->cols[0x78][0][0] = dev->cols[0x78][1][0] = + dev->cols[0x78][1][1] = 16 + 15; + dev->cols[0xF8][0][1] = 16 + 7; + dev->cols[0xF8][0][0] = dev->cols[0xF8][1][0] = + dev->cols[0xF8][1][1] = 16 + 15; + dev->cols[0x00][0][1] = dev->cols[0x00][1][1] = 16; + dev->cols[0x08][0][1] = dev->cols[0x08][1][1] = 16; + dev->cols[0x80][0][1] = dev->cols[0x80][1][1] = 16; + dev->cols[0x88][0][1] = dev->cols[0x88][1][1] = 16; + + overscan_x = overscan_y = 0; + + cga_palette = device_get_config_int("rgb_type") << 1; + if (cga_palette > 6) + cga_palette = 0; + cgapal_rebuild(); + + video_inform(VID_TYPE_MDA, info->vid_timing); + + /* Force the LPT3 port to be enabled. */ + parallel_enabled[2] = 1; + parallel_setup(3, 0x3BC); + + return(dev); } -void hercules_speed_changed(void *p) + +static void +hercules_close(void *priv) { - hercules_t *hercules = (hercules_t *)p; - - hercules_recalctimings(hercules); + hercules_t *dev = (hercules_t *)priv; + + free(dev->vram); + free(dev); } -static const device_config_t hercules_config[] = + +static void +speed_changed(void *priv) { - { - "rgb_type", "Display type", CONFIG_SELECTION, "", 0, - { - { - "Default", 0 - }, - { - "Green", 1 - }, - { - "Amber", 2 - }, - { - "Gray", 3 - }, - { - "" - } - } - }, - { - "", "", -1 - } + hercules_t *dev = (hercules_t *)priv; + + recalc_timings(dev); +} + + +static const device_config_t hercules_config[] = { + { + "rgb_type", "Display type", CONFIG_SELECTION, "", 0, + { + { + "Default", 0 + }, + { + "Green", 1 + }, + { + "Amber", 2 + }, + { + "Gray", 3 + }, + { + "" + } + } + }, + { + "", "", -1 + } }; +static const video_timings_t hercules_timings = { VID_ISA,8,16,32,8,16,32 }; -const device_t hercules_device = -{ - "Hercules", - DEVICE_ISA, 0, - hercules_init, hercules_close, NULL, - NULL, - hercules_speed_changed, - NULL, - NULL, - hercules_config +const device_t hercules_device = { + "Hercules", + DEVICE_ISA, + 0, + hercules_init, hercules_close, NULL, + NULL, + speed_changed, + NULL, + &hercules_timings, + hercules_config }; diff --git a/src/devices/video/vid_herculesplus.c b/src/devices/video/vid_herculesplus.c index aca4ec6..153de5a 100644 --- a/src/devices/video/vid_herculesplus.c +++ b/src/devices/video/vid_herculesplus.c @@ -8,7 +8,7 @@ * * Hercules InColor emulation. * - * Version: @(#)vid_hercules_plus.c 1.0.8 2018/05/06 + * Version: @(#)vid_hercules_plus.c 1.0.9 2018/09/22 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -58,7 +58,7 @@ #define HERCULESPLUS_CRTC_OVER 22 /* Overstrike */ /* character width */ -#define HERCULESPLUS_CW ((herculesplus->crtc[HERCULESPLUS_CRTC_XMODE] & HERCULESPLUS_XMODE_90COL) ? 8 : 9) +#define HERCULESPLUS_CW ((dev->crtc[HERCULESPLUS_CRTC_XMODE] & HERCULESPLUS_XMODE_90COL) ? 8 : 9) /* mode control register */ #define HERCULESPLUS_CTRL_GRAPH 0x02 @@ -81,682 +81,620 @@ #define HERCULESPLUS_XMODE_RAMFONT 0x01 #define HERCULESPLUS_XMODE_90COL 0x02 -typedef struct herculesplus_t -{ - mem_mapping_t mapping; - - uint8_t crtc[32]; - int crtcreg; - uint8_t ctrl, ctrl2, stat; +typedef struct { + mem_map_t mapping; - int64_t dispontime, dispofftime; - int64_t vidtime; - - int firstline, lastline; + uint8_t crtc[32]; + int crtcreg; - int linepos, displine; - int vc, sc; - uint16_t ma, maback; - int con, coff, cursoron; - int dispon, blink; - int64_t vsynctime; - int vadj; + uint8_t ctrl, ctrl2, stat; - uint8_t *vram; + int64_t dispontime, dispofftime; + int64_t vidtime; + + int firstline, lastline; + + int linepos, displine; + int vc, sc; + uint16_t ma, maback; + int con, coff, cursoron; + int dispon, blink; + int64_t vsynctime; + int vadj; + + int cols[256][2][2]; + + uint8_t *vram; } herculesplus_t; -void herculesplus_recalctimings(herculesplus_t *herculesplus); -void herculesplus_write(uint32_t addr, uint8_t val, void *p); -uint8_t herculesplus_read(uint32_t addr, void *p); -static int mdacols[256][2][2]; - -void herculesplus_out(uint16_t addr, uint8_t val, void *p) +static void +recalc_timings(herculesplus_t *dev) { - herculesplus_t *herculesplus = (herculesplus_t *)p; -/* pclog("InColor out %04X %02X\n",addr,val); */ - switch (addr) - { - case 0x3b0: case 0x3b2: case 0x3b4: case 0x3b6: - herculesplus->crtcreg = val & 31; - return; - case 0x3b1: case 0x3b3: case 0x3b5: case 0x3b7: - if (herculesplus->crtcreg > 22) return; - herculesplus->crtc[herculesplus->crtcreg] = val; - if (herculesplus->crtc[10] == 6 && herculesplus->crtc[11] == 7) /*Fix for Generic Turbo XT BIOS, which sets up cursor registers wrong*/ - { - herculesplus->crtc[10] = 0xb; - herculesplus->crtc[11] = 0xc; - } - herculesplus_recalctimings(herculesplus); - return; - case 0x3b8: - herculesplus->ctrl = val; - return; - case 0x3bf: - herculesplus->ctrl2 = val; - if (val & 2) - mem_mapping_set_addr(&herculesplus->mapping, 0xb0000, 0x10000); - else - mem_mapping_set_addr(&herculesplus->mapping, 0xb0000, 0x08000); - return; - } -} + double disptime; + double _dispontime, _dispofftime; -uint8_t herculesplus_in(uint16_t addr, void *p) -{ - herculesplus_t *herculesplus = (herculesplus_t *)p; -/* pclog("InColor in %04X %02X %04X:%04X %04X\n",addr,(herculesplus->stat & 0xF) | ((herculesplus->stat & 8) << 4),CS,pc,CX); */ - switch (addr) - { - case 0x3b0: case 0x3b2: case 0x3b4: case 0x3b6: - return herculesplus->crtcreg; - case 0x3b1: case 0x3b3: case 0x3b5: case 0x3b7: - if (herculesplus->crtcreg > 22) return 0xff; - return herculesplus->crtc[herculesplus->crtcreg]; - case 0x3ba: - /* 0x50: InColor card identity */ - return (herculesplus->stat & 0xf) | ((herculesplus->stat & 8) << 4) | 0x10; - } - return 0xff; -} + disptime = dev->crtc[0] + 1; + _dispontime = dev->crtc[1]; + _dispofftime = disptime - _dispontime; + _dispontime *= MDACONST; + _dispofftime *= MDACONST; -void herculesplus_write(uint32_t addr, uint8_t val, void *p) -{ - herculesplus_t *herculesplus = (herculesplus_t *)p; - - egawrites++; - - addr &= 0xFFFF; - - herculesplus->vram[addr] = val; -} - -uint8_t herculesplus_read(uint32_t addr, void *p) -{ - herculesplus_t *herculesplus = (herculesplus_t *)p; - - egareads++; - - addr &= 0xFFFF; - return herculesplus->vram[addr]; + dev->dispontime = (int64_t)(_dispontime * (1 << TIMER_SHIFT)); + dev->dispofftime = (int64_t)(_dispofftime * (1 << TIMER_SHIFT)); } - -void herculesplus_recalctimings(herculesplus_t *herculesplus) +static void +herculesplus_out(uint16_t port, uint8_t val, void *priv) { - double disptime; - double _dispontime, _dispofftime; - disptime = herculesplus->crtc[0] + 1; - _dispontime = herculesplus->crtc[1]; - _dispofftime = disptime - _dispontime; - _dispontime *= MDACONST; - _dispofftime *= MDACONST; - herculesplus->dispontime = (int64_t)(_dispontime * (1 << TIMER_SHIFT)); - herculesplus->dispofftime = (int64_t)(_dispofftime * (1 << TIMER_SHIFT)); -} + herculesplus_t *dev = (herculesplus_t *)priv; + switch (port) { + case 0x3b0: + case 0x3b2: + case 0x3b4: + case 0x3b6: + dev->crtcreg = val & 31; + return; -static void herculesplus_draw_char_rom(herculesplus_t *herculesplus, int x, uint8_t chr, uint8_t attr) -{ - int i; - int elg, blk; - unsigned ull; - unsigned val; - unsigned ifg, ibg; - const unsigned char *fnt; - int cw = HERCULESPLUS_CW; - - blk = 0; - if (herculesplus->ctrl & HERCULESPLUS_CTRL_BLINK) - { - if (attr & 0x80) - { - blk = (herculesplus->blink & 16); + case 0x3b1: + case 0x3b3: + case 0x3b5: + case 0x3b7: + if (dev->crtcreg > 22) return; + dev->crtc[dev->crtcreg] = val; + if (dev->crtc[10] == 6 && dev->crtc[11] == 7) { + /*Fix for Generic Turbo XT BIOS, + *which sets up cursor registers wrong*/ + dev->crtc[10] = 0xb; + dev->crtc[11] = 0xc; } - attr &= 0x7f; - } + recalc_timings(dev); + return; - /* MDA-compatible attributes */ - ibg = 0; - ifg = 7; - if ((attr & 0x77) == 0x70) /* Invert */ - { - ifg = 0; - ibg = 7; - } - if (attr & 8) - { - ifg |= 8; /* High intensity FG */ - } - if (attr & 0x80) - { - ibg |= 8; /* High intensity BG */ - } - if ((attr & 0x77) == 0) /* Blank */ - { - ifg = ibg; - } - ull = ((attr & 0x07) == 1) ? 13 : 0xffff; + case 0x3b8: + dev->ctrl = val; + return; - if (herculesplus->crtc[HERCULESPLUS_CRTC_XMODE] & HERCULESPLUS_XMODE_90COL) - { - elg = 0; - } - else - { - elg = ((chr >= 0xc0) && (chr <= 0xdf)); - } - - fnt = &(fontdatm[chr][herculesplus->sc]); - - if (blk) - { - val = 0x000; /* Blinking, draw all background */ - } - else if (herculesplus->sc == ull) - { - val = 0x1ff; /* Underscore, draw all foreground */ - } - else - { - val = fnt[0] << 1; - - if (elg) - { - val |= (val >> 1) & 1; - } - } - for (i = 0; i < cw; i++) - { - buffer->line[herculesplus->displine][x * cw + i] = (val & 0x100) ? ifg : ibg; - val = val << 1; - } -} - - -static void herculesplus_draw_char_ram4(herculesplus_t *herculesplus, int x, uint8_t chr, uint8_t attr) -{ - int i; - int elg, blk; - unsigned ull; - unsigned val; - unsigned ifg, ibg, cfg; - const unsigned char *fnt; - int cw = HERCULESPLUS_CW; - int blink = herculesplus->ctrl & HERCULESPLUS_CTRL_BLINK; - - blk = 0; - if (blink) - { - if (attr & 0x80) - { - blk = (herculesplus->blink & 16); - } - attr &= 0x7f; - } - - /* MDA-compatible attributes */ - ibg = 0; - ifg = 7; - if ((attr & 0x77) == 0x70) /* Invert */ - { - ifg = 0; - ibg = 7; - } - if (attr & 8) - { - ifg |= 8; /* High intensity FG */ - } - if (attr & 0x80) - { - ibg |= 8; /* High intensity BG */ - } - if ((attr & 0x77) == 0) /* Blank */ - { - ifg = ibg; - } - ull = ((attr & 0x07) == 1) ? 13 : 0xffff; - if (herculesplus->crtc[HERCULESPLUS_CRTC_XMODE] & HERCULESPLUS_XMODE_90COL) - { - elg = 0; - } - else - { - elg = ((chr >= 0xc0) && (chr <= 0xdf)); - } - fnt = herculesplus->vram + 0x4000 + 16 * chr + herculesplus->sc; - - if (blk) - { - /* Blinking, draw all background */ - val = 0x000; - } - else if (herculesplus->sc == ull) - { - /* Underscore, draw all foreground */ - val = 0x1ff; - } - else - { - val = fnt[0x00000] << 1; - - if (elg) - { - val |= (val >> 1) & 1; - } - } - for (i = 0; i < cw; i++) - { - /* Generate pixel colour */ - cfg = 0; - /* cfg = colour of foreground pixels */ - if ((attr & 0x77) == 0) cfg = ibg; /* 'blank' attribute */ - - buffer->line[herculesplus->displine][x * cw + i] = mdacols[attr][blink][cfg]; - val = val << 1; - } -} - - -static void herculesplus_draw_char_ram48(herculesplus_t *herculesplus, int x, uint8_t chr, uint8_t attr) -{ - int i; - int elg, blk, ul, ol, bld; - unsigned ull, oll, ulc = 0, olc = 0; - unsigned val; - unsigned ibg, cfg; - const unsigned char *fnt; - int cw = HERCULESPLUS_CW; - int blink = herculesplus->ctrl & HERCULESPLUS_CTRL_BLINK; - int font = (attr & 0x0F); - - if (font >= 12) font &= 7; - - blk = 0; - if (blink) - { - if (attr & 0x40) - { - blk = (herculesplus->blink & 16); - } - attr &= 0x7f; - } - /* MDA-compatible attributes */ - if (blink) - { - ibg = (attr & 0x80) ? 8 : 0; - bld = 0; - ol = (attr & 0x20) ? 1 : 0; - ul = (attr & 0x10) ? 1 : 0; - } - else - { - bld = (attr & 0x80) ? 1 : 0; - ibg = (attr & 0x40) ? 0x0F : 0; - ol = (attr & 0x20) ? 1 : 0; - ul = (attr & 0x10) ? 1 : 0; - } - if (ul) - { - ull = herculesplus->crtc[HERCULESPLUS_CRTC_UNDER] & 0x0F; - ulc = (herculesplus->crtc[HERCULESPLUS_CRTC_UNDER] >> 4) & 0x0F; - if (ulc == 0) ulc = 7; - } - else - { - ull = 0xFFFF; - } - if (ol) - { - oll = herculesplus->crtc[HERCULESPLUS_CRTC_OVER] & 0x0F; - olc = (herculesplus->crtc[HERCULESPLUS_CRTC_OVER] >> 4) & 0x0F; - if (olc == 0) olc = 7; - } - else - { - oll = 0xFFFF; - } - - if (herculesplus->crtc[HERCULESPLUS_CRTC_XMODE] & HERCULESPLUS_XMODE_90COL) - { - elg = 0; - } - else - { - elg = ((chr >= 0xc0) && (chr <= 0xdf)); - } - fnt = herculesplus->vram + 0x4000 + 16 * chr + 4096 * font + herculesplus->sc; - - if (blk) - { - /* Blinking, draw all background */ - val = 0x000; - } - else if (herculesplus->sc == ull) - { - /* Underscore, draw all foreground */ - val = 0x1ff; - } - else - { - val = fnt[0x00000] << 1; - - if (elg) - { - val |= (val >> 1) & 1; - } - if (bld) - { - val |= (val >> 1); - } - } - for (i = 0; i < cw; i++) - { - /* Generate pixel colour */ - cfg = val & 0x100; - if (herculesplus->sc == oll) - { - cfg = olc ^ ibg; /* Strikethrough */ - } - else if (herculesplus->sc == ull) - { - cfg = ulc ^ ibg; /* Underline */ - } + case 0x3bf: + dev->ctrl2 = val; + if (val & 2) + mem_map_set_addr(&dev->mapping, 0xb0000, 0x10000); else - { - cfg |= ibg; - } + mem_map_set_addr(&dev->mapping, 0xb0000, 0x08000); + return; + } +} + + +static uint8_t +herculesplus_in(uint16_t port, void *priv) +{ + herculesplus_t *dev = (herculesplus_t *)priv; + uint8_t ret = 0xff; + + switch (port) { + case 0x3b0: + case 0x3b2: + case 0x3b4: + case 0x3b6: + ret = dev->crtcreg; + break; + + case 0x3b1: + case 0x3b3: + case 0x3b5: + case 0x3b7: + if (dev->crtcreg <= 22) + ret = dev->crtc[dev->crtcreg]; + break; + + case 0x3ba: + /* 0x50: InColor card identity */ + ret = (dev->stat & 0xf) | ((dev->stat & 8) << 4) | 0x10; + break; + } + + return ret; +} + + +static void +herculesplus_write(uint32_t addr, uint8_t val, void *priv) +{ + herculesplus_t *dev = (herculesplus_t *)priv; + + dev->vram[addr & 0xffff] = val; +} + + +static uint8_t +herculesplus_read(uint32_t addr, void *priv) +{ + herculesplus_t *dev = (herculesplus_t *)priv; + + return dev->vram[addr & 0xffff]; +} + + +static void +draw_char_rom(herculesplus_t *dev, int x, uint8_t chr, uint8_t attr) +{ + unsigned ull, val, ifg, ibg; + const uint8_t *fnt; + int i, elg, blk; + int cw = HERCULESPLUS_CW; + + blk = 0; + if (dev->ctrl & HERCULESPLUS_CTRL_BLINK) { + if (attr & 0x80) + blk = (dev->blink & 16); + attr &= 0x7f; + } + + /* MDA-compatible attributes */ + ibg = 0; + ifg = 7; + if ((attr & 0x77) == 0x70) { /* Invert */ + ifg = 0; + ibg = 7; + } + if (attr & 8) + ifg |= 8; /* High intensity FG */ + if (attr & 0x80) + ibg |= 8; /* High intensity BG */ + if ((attr & 0x77) == 0) /* Blank */ + ifg = ibg; + ull = ((attr & 0x07) == 1) ? 13 : 0xffff; + + if (dev->crtc[HERCULESPLUS_CRTC_XMODE] & HERCULESPLUS_XMODE_90COL) + elg = 0; + else + elg = ((chr >= 0xc0) && (chr <= 0xdf)); + + fnt = &(fontdatm[chr][dev->sc]); + + if (blk) { + val = 0x000; /* Blinking, draw all background */ + } else if (dev->sc == ull) { + val = 0x1ff; /* Underscore, draw all foreground */ + } else { + val = fnt[0] << 1; + + if (elg) + val |= (val >> 1) & 1; + } + + for (i = 0; i < cw; i++) { + buffer->line[dev->displine][x * cw + i] = (val & 0x100) ? ifg : ibg; + val = val << 1; + } +} + + +static void +draw_char_ram4(herculesplus_t *dev, int x, uint8_t chr, uint8_t attr) +{ + unsigned ull, val, ifg, ibg, cfg; + const uint8_t *fnt; + int i, elg, blk; + int cw = HERCULESPLUS_CW; + int blink = dev->ctrl & HERCULESPLUS_CTRL_BLINK; + + blk = 0; + if (blink) { + if (attr & 0x80) + blk = (dev->blink & 16); + attr &= 0x7f; + } + + /* MDA-compatible attributes */ + ibg = 0; + ifg = 7; + if ((attr & 0x77) == 0x70) { /* Invert */ + ifg = 0; + ibg = 7; + } + if (attr & 8) + ifg |= 8; /* High intensity FG */ + if (attr & 0x80) + ibg |= 8; /* High intensity BG */ + if ((attr & 0x77) == 0) /* Blank */ + ifg = ibg; + ull = ((attr & 0x07) == 1) ? 13 : 0xffff; + if (dev->crtc[HERCULESPLUS_CRTC_XMODE] & HERCULESPLUS_XMODE_90COL) + elg = 0; + else + elg = ((chr >= 0xc0) && (chr <= 0xdf)); + fnt = dev->vram + 0x4000 + 16 * chr + dev->sc; + + if (blk) { + /* Blinking, draw all background */ + val = 0x000; + } else if (dev->sc == ull) { + /* Underscore, draw all foreground */ + val = 0x1ff; + } else { + val = fnt[0x00000] << 1; + + if (elg) + val |= (val >> 1) & 1; + } + + for (i = 0; i < cw; i++) { + /* Generate pixel colour */ + cfg = 0; + + /* cfg = colour of foreground pixels */ + if ((attr & 0x77) == 0) + cfg = ibg; /* 'blank' attribute */ + + buffer->line[dev->displine][x * cw + i] = dev->cols[attr][blink][cfg]; + val = val << 1; + } +} + + +static void +draw_char_ram48(herculesplus_t *dev, int x, uint8_t chr, uint8_t attr) +{ + int i, elg, blk, ul, ol, bld; + unsigned ull, oll, ulc = 0, olc = 0; + unsigned val, ibg, cfg; + const unsigned char *fnt; + int cw = HERCULESPLUS_CW; + int blink = dev->ctrl & HERCULESPLUS_CTRL_BLINK; + int font = (attr & 0x0F); + + if (font >= 12) font &= 7; + + blk = 0; + if (blink) { + if (attr & 0x40) + blk = (dev->blink & 16); + attr &= 0x7f; + } + + /* MDA-compatible attributes */ + if (blink) { + ibg = (attr & 0x80) ? 8 : 0; + bld = 0; + ol = (attr & 0x20) ? 1 : 0; + ul = (attr & 0x10) ? 1 : 0; + } else { + bld = (attr & 0x80) ? 1 : 0; + ibg = (attr & 0x40) ? 0x0F : 0; + ol = (attr & 0x20) ? 1 : 0; + ul = (attr & 0x10) ? 1 : 0; + } + + if (ul) { + ull = dev->crtc[HERCULESPLUS_CRTC_UNDER] & 0x0F; + ulc = (dev->crtc[HERCULESPLUS_CRTC_UNDER] >> 4) & 0x0F; + if (ulc == 0) ulc = 7; + } else { + ull = 0xFFFF; + } + + if (ol) { + oll = dev->crtc[HERCULESPLUS_CRTC_OVER] & 0x0F; + olc = (dev->crtc[HERCULESPLUS_CRTC_OVER] >> 4) & 0x0F; + if (olc == 0) olc = 7; + } else { + oll = 0xFFFF; + } + + if (dev->crtc[HERCULESPLUS_CRTC_XMODE] & HERCULESPLUS_XMODE_90COL) + elg = 0; + else + elg = ((chr >= 0xc0) && (chr <= 0xdf)); + fnt = dev->vram + 0x4000 + 16 * chr + 4096 * font + dev->sc; + + if (blk) { /* Blinking, draw all background */ + val = 0x000; + } else if (dev->sc == ull) { + /* Underscore, draw all foreground */ + val = 0x1ff; + } else { + val = fnt[0x00000] << 1; + + if (elg) + val |= (val >> 1) & 1; + if (bld) + val |= (val >> 1); + } + + for (i = 0; i < cw; i++) { + /* Generate pixel colour */ + cfg = val & 0x100; + if (dev->sc == oll) + cfg = olc ^ ibg; /* Strikethrough */ + else if (dev->sc == ull) + cfg = ulc ^ ibg; /* Underline */ + else + cfg |= ibg; - buffer->line[herculesplus->displine][(x * cw) + i] = mdacols[attr][blink][cfg]; - val = val << 1; - } + buffer->line[dev->displine][(x * cw) + i] = dev->cols[attr][blink][cfg]; + val = val << 1; + } } -static void herculesplus_text_line(herculesplus_t *herculesplus, uint16_t ca) + +static void +text_line(herculesplus_t *dev, uint16_t ca) { - int drawcursor; - int x, c; - uint8_t chr, attr; - uint32_t col; + int drawcursor; + int x, c; + uint8_t chr, attr; + uint32_t col; - for (x = 0; x < herculesplus->crtc[1]; x++) - { - chr = herculesplus->vram[(herculesplus->ma << 1) & 0xfff]; - attr = herculesplus->vram[((herculesplus->ma << 1) + 1) & 0xfff]; + for (x = 0; x < dev->crtc[1]; x++) { + chr = dev->vram[(dev->ma << 1) & 0xfff]; + attr = dev->vram[((dev->ma << 1) + 1) & 0xfff]; - drawcursor = ((herculesplus->ma == ca) && herculesplus->con && herculesplus->cursoron); + drawcursor = ((dev->ma == ca) && dev->con && dev->cursoron); - switch (herculesplus->crtc[HERCULESPLUS_CRTC_XMODE] & 5) - { - case 0: - case 4: /* ROM font */ - herculesplus_draw_char_rom(herculesplus, x, chr, attr); - break; - case 1: /* 4k RAMfont */ - herculesplus_draw_char_ram4(herculesplus, x, chr, attr); - break; - case 5: /* 48k RAMfont */ - herculesplus_draw_char_ram48(herculesplus, x, chr, attr); - break; + switch (dev->crtc[HERCULESPLUS_CRTC_XMODE] & 5) { + case 0: + case 4: /* ROM font */ + draw_char_rom(dev, x, chr, attr); + break; + case 1: /* 4k RAMfont */ + draw_char_ram4(dev, x, chr, attr); + break; + + case 5: /* 48k RAMfont */ + draw_char_ram48(dev, x, chr, attr); + break; + } + ++dev->ma; + + if (drawcursor) { + int cw = HERCULESPLUS_CW; + + col = dev->cols[attr][0][1]; + for (c = 0; c < cw; c++) + ((uint32_t *)buffer32->line[dev->displine])[x * cw + c] = col; + } + } +} + + +static void +graphics_line(herculesplus_t *dev) +{ + uint16_t ca; + int x, c, plane = 0; + uint16_t val; + + /* Graphics mode. */ + ca = (dev->sc & 3) * 0x2000; + if ((dev->ctrl & HERCULESPLUS_CTRL_PAGE1) && (dev->ctrl2 & HERCULESPLUS_CTRL2_PAGE1)) + ca += 0x8000; + + for (x = 0; x < dev->crtc[1]; x++) { + val = (dev->vram[((dev->ma << 1) & 0x1fff) + ca + 0x10000 * plane] << 8) + | dev->vram[((dev->ma << 1) & 0x1fff) + ca + 0x10000 * plane + 1]; + + dev->ma++; + for (c = 0; c < 16; c++) { + val >>= 1; + + ((uint32_t *)buffer32->line[dev->displine])[(x << 4) + c] = (val & 1) ? 7 : 0; + } + } +} + + +static void +herculesplus_poll(void *priv) +{ + herculesplus_t *dev = (herculesplus_t *)priv; + uint16_t ca = (dev->crtc[15] | (dev->crtc[14] << 8)) & 0x3fff; + int x, oldvc, oldsc; + + if (! dev->linepos) { + dev->vidtime += dev->dispofftime; + dev->stat |= 1; + dev->linepos = 1; + oldsc = dev->sc; + if ((dev->crtc[8] & 3) == 3) + dev->sc = (dev->sc << 1) & 7; + if (dev->dispon) { + if (dev->displine < dev->firstline) { + dev->firstline = dev->displine; + video_wait_for_buffer(); } - ++herculesplus->ma; - if (drawcursor) - { - int cw = HERCULESPLUS_CW; + dev->lastline = dev->displine; + if ((dev->ctrl & HERCULESPLUS_CTRL_GRAPH) && (dev->ctrl2 & HERCULESPLUS_CTRL2_GRAPH)) + graphics_line(dev); + else + text_line(dev, ca); + } + dev->sc = oldsc; + if (dev->vc == dev->crtc[7] && !dev->sc) + dev->stat |= 8; + dev->displine++; + if (dev->displine >= 500) + dev->displine = 0; + } else { + dev->vidtime += dev->dispontime; + if (dev->dispon) + dev->stat &= ~1; + dev->linepos = 0; + if (dev->vsynctime) { + dev->vsynctime--; + if (! dev->vsynctime) + dev->stat &= ~8; + } - col = mdacols[attr][0][1]; - for (c = 0; c < cw; c++) - { - ((uint32_t *)buffer32->line[herculesplus->displine])[x * cw + c] = col; + if (dev->sc == (dev->crtc[11] & 31) || ((dev->crtc[8] & 3) == 3 && dev->sc == ((dev->crtc[11] & 31) >> 1))) { + dev->con = 0; + dev->coff = 1; + } + if (dev->vadj) { + dev->sc++; + dev->sc &= 31; + dev->ma = dev->maback; + dev->vadj--; + if (! dev->vadj) { + dev->dispon = 1; + dev->ma = dev->maback = (dev->crtc[13] | (dev->crtc[12] << 8)) & 0x3fff; + dev->sc = 0; + } + } else if (dev->sc == dev->crtc[9] || ((dev->crtc[8] & 3) == 3 && dev->sc == (dev->crtc[9] >> 1))) { + dev->maback = dev->ma; + dev->sc = 0; + oldvc = dev->vc; + dev->vc++; + dev->vc &= 127; + if (dev->vc == dev->crtc[6]) + dev->dispon = 0; + if (oldvc == dev->crtc[4]) { + dev->vc = 0; + dev->vadj = dev->crtc[5]; + if (!dev->vadj) dev->dispon=1; + if (!dev->vadj) dev->ma = dev->maback = (dev->crtc[13] | (dev->crtc[12] << 8)) & 0x3fff; + if ((dev->crtc[10] & 0x60) == 0x20) + dev->cursoron = 0; + else + dev->cursoron = dev->blink & 16; + } + if (dev->vc == dev->crtc[7]) { + dev->dispon = 0; + dev->displine = 0; + dev->vsynctime = 16; + if (dev->crtc[7]) { + if ((dev->ctrl & HERCULESPLUS_CTRL_GRAPH) && (dev->ctrl2 & HERCULESPLUS_CTRL2_GRAPH)) + x = dev->crtc[1] << 4; + else + x = dev->crtc[1] * 9; + dev->lastline++; + if ((x != xsize) || ((dev->lastline - dev->firstline) != ysize) || video_force_resize_get()) { + xsize = x; + ysize = dev->lastline - dev->firstline; + if (xsize < 64) xsize = 656; + if (ysize < 32) ysize = 200; + set_screen_size(xsize, ysize); + + if (video_force_resize_get()) + video_force_resize_set(0); + } + video_blit_memtoscreen(0, dev->firstline, 0, dev->lastline - dev->firstline, xsize, dev->lastline - dev->firstline); + frames++; + if ((dev->ctrl & HERCULESPLUS_CTRL_GRAPH) && (dev->ctrl2 & HERCULESPLUS_CTRL2_GRAPH)) { + video_res_x = dev->crtc[1] * 16; + video_res_y = dev->crtc[6] * 4; + video_bpp = 1; + } else { + video_res_x = dev->crtc[1]; + video_res_y = dev->crtc[6]; + video_bpp = 0; + } } + dev->firstline = 1000; + dev->lastline = 0; + dev->blink++; } + } else { + dev->sc++; + dev->sc &= 31; + dev->ma = dev->maback; } + + if ((dev->sc == (dev->crtc[10] & 31) || ((dev->crtc[8] & 3) == 3 && dev->sc == ((dev->crtc[10] & 31) >> 1)))) + dev->con = 1; + } } -static void herculesplus_graphics_line(herculesplus_t *herculesplus) +static void * +herculesplus_init(const device_t *info) { - uint16_t ca; - int x, c, plane = 0; - uint16_t val; + herculesplus_t *dev; + int c; - /* Graphics mode. */ - ca = (herculesplus->sc & 3) * 0x2000; - if ((herculesplus->ctrl & HERCULESPLUS_CTRL_PAGE1) && (herculesplus->ctrl2 & HERCULESPLUS_CTRL2_PAGE1)) - ca += 0x8000; + dev = (herculesplus_t *)mem_alloc(sizeof(herculesplus_t)); + memset(dev, 0, sizeof(herculesplus_t)); - for (x = 0; x < herculesplus->crtc[1]; x++) - { - val = (herculesplus->vram[((herculesplus->ma << 1) & 0x1fff) + ca + 0x10000 * plane] << 8) - | herculesplus->vram[((herculesplus->ma << 1) & 0x1fff) + ca + 0x10000 * plane + 1]; + dev->vram = (uint8_t *)mem_alloc(0x10000); /* 64k VRAM */ - herculesplus->ma++; - for (c = 0; c < 16; c++) - { - val >>= 1; + timer_add(herculesplus_poll, &dev->vidtime, TIMER_ALWAYS_ENABLED, dev); - ((uint32_t *)buffer32->line[herculesplus->displine])[(x << 4) + c] = (val & 1) ? 7 : 0; - } - } + mem_map_add(&dev->mapping, 0xb0000, 0x10000, + herculesplus_read,NULL,NULL, + herculesplus_write,NULL,NULL, + NULL, MEM_MAPPING_EXTERNAL, dev); + + io_sethandler(0x03b0, 16, + herculesplus_in,NULL, NULL, herculesplus_out,NULL,NULL, dev); + + for (c = 0; c < 256; c++) { + dev->cols[c][0][0] = dev->cols[c][1][0] = dev->cols[c][1][1] = 16; + if (c & 8) + dev->cols[c][0][1] = 15 + 16; + else + dev->cols[c][0][1] = 7 + 16; + } + dev->cols[0x70][0][1] = 16; + dev->cols[0x70][0][0] = dev->cols[0x70][1][0] = + dev->cols[0x70][1][1] = 16 + 15; + dev->cols[0xF0][0][1] = 16; + dev->cols[0xF0][0][0] = dev->cols[0xF0][1][0] = + dev->cols[0xF0][1][1] = 16 + 15; + dev->cols[0x78][0][1] = 16 + 7; + dev->cols[0x78][0][0] = dev->cols[0x78][1][0] = + dev->cols[0x78][1][1] = 16 + 15; + dev->cols[0xF8][0][1] = 16 + 7; + dev->cols[0xF8][0][0] = dev->cols[0xF8][1][0] = + dev->cols[0xF8][1][1] = 16 + 15; + dev->cols[0x00][0][1] = dev->cols[0x00][1][1] = 16; + dev->cols[0x08][0][1] = dev->cols[0x08][1][1] = 16; + dev->cols[0x80][0][1] = dev->cols[0x80][1][1] = 16; + dev->cols[0x88][0][1] = dev->cols[0x88][1][1] = 16; + + video_inform(VID_TYPE_MDA, info->vid_timing); + + /* Force the LPT3 port to be enabled. */ + parallel_enabled[2] = 1; + parallel_setup(3, 0x3BC); + + return dev; } -void herculesplus_poll(void *p) + +static void +herculesplus_close(void *priv) { - herculesplus_t *herculesplus = (herculesplus_t *)p; - uint16_t ca = (herculesplus->crtc[15] | (herculesplus->crtc[14] << 8)) & 0x3fff; - int x; - int oldvc; - int oldsc; + herculesplus_t *dev = (herculesplus_t *)priv; - if (!herculesplus->linepos) - { - herculesplus->vidtime += herculesplus->dispofftime; - herculesplus->stat |= 1; - herculesplus->linepos = 1; - oldsc = herculesplus->sc; - if ((herculesplus->crtc[8] & 3) == 3) - herculesplus->sc = (herculesplus->sc << 1) & 7; - if (herculesplus->dispon) - { - if (herculesplus->displine < herculesplus->firstline) - { - herculesplus->firstline = herculesplus->displine; - video_wait_for_buffer(); - } - herculesplus->lastline = herculesplus->displine; - if ((herculesplus->ctrl & HERCULESPLUS_CTRL_GRAPH) && (herculesplus->ctrl2 & HERCULESPLUS_CTRL2_GRAPH)) - { - herculesplus_graphics_line(herculesplus); - } - else - { - herculesplus_text_line(herculesplus, ca); - } - } - herculesplus->sc = oldsc; - if (herculesplus->vc == herculesplus->crtc[7] && !herculesplus->sc) - { - herculesplus->stat |= 8; - } - herculesplus->displine++; - if (herculesplus->displine >= 500) - herculesplus->displine = 0; - } - else - { - herculesplus->vidtime += herculesplus->dispontime; - if (herculesplus->dispon) - herculesplus->stat &= ~1; - herculesplus->linepos = 0; - if (herculesplus->vsynctime) - { - herculesplus->vsynctime--; - if (!herculesplus->vsynctime) - { - herculesplus->stat &= ~8; - } - } - if (herculesplus->sc == (herculesplus->crtc[11] & 31) || ((herculesplus->crtc[8] & 3) == 3 && herculesplus->sc == ((herculesplus->crtc[11] & 31) >> 1))) - { - herculesplus->con = 0; - herculesplus->coff = 1; - } - if (herculesplus->vadj) - { - herculesplus->sc++; - herculesplus->sc &= 31; - herculesplus->ma = herculesplus->maback; - herculesplus->vadj--; - if (!herculesplus->vadj) - { - herculesplus->dispon = 1; - herculesplus->ma = herculesplus->maback = (herculesplus->crtc[13] | (herculesplus->crtc[12] << 8)) & 0x3fff; - herculesplus->sc = 0; - } - } - else if (herculesplus->sc == herculesplus->crtc[9] || ((herculesplus->crtc[8] & 3) == 3 && herculesplus->sc == (herculesplus->crtc[9] >> 1))) - { - herculesplus->maback = herculesplus->ma; - herculesplus->sc = 0; - oldvc = herculesplus->vc; - herculesplus->vc++; - herculesplus->vc &= 127; - if (herculesplus->vc == herculesplus->crtc[6]) - herculesplus->dispon = 0; - if (oldvc == herculesplus->crtc[4]) - { - herculesplus->vc = 0; - herculesplus->vadj = herculesplus->crtc[5]; - if (!herculesplus->vadj) herculesplus->dispon=1; - if (!herculesplus->vadj) herculesplus->ma = herculesplus->maback = (herculesplus->crtc[13] | (herculesplus->crtc[12] << 8)) & 0x3fff; - if ((herculesplus->crtc[10] & 0x60) == 0x20) herculesplus->cursoron = 0; - else herculesplus->cursoron = herculesplus->blink & 16; - } - if (herculesplus->vc == herculesplus->crtc[7]) - { - herculesplus->dispon = 0; - herculesplus->displine = 0; - herculesplus->vsynctime = 16; - if (herculesplus->crtc[7]) - { - if ((herculesplus->ctrl & HERCULESPLUS_CTRL_GRAPH) && (herculesplus->ctrl2 & HERCULESPLUS_CTRL2_GRAPH)) - { - x = herculesplus->crtc[1] << 4; - } - else - { - x = herculesplus->crtc[1] * 9; - } - herculesplus->lastline++; - if ((x != xsize) || ((herculesplus->lastline - herculesplus->firstline) != ysize) || video_force_resize_get()) - { - xsize = x; - ysize = herculesplus->lastline - herculesplus->firstline; - if (xsize < 64) xsize = 656; - if (ysize < 32) ysize = 200; - set_screen_size(xsize, ysize); - - if (video_force_resize_get()) - video_force_resize_set(0); - } - video_blit_memtoscreen(0, herculesplus->firstline, 0, herculesplus->lastline - herculesplus->firstline, xsize, herculesplus->lastline - herculesplus->firstline); - frames++; - if ((herculesplus->ctrl & HERCULESPLUS_CTRL_GRAPH) && (herculesplus->ctrl2 & HERCULESPLUS_CTRL2_GRAPH)) - { - video_res_x = herculesplus->crtc[1] * 16; - video_res_y = herculesplus->crtc[6] * 4; - video_bpp = 1; - } - else - { - video_res_x = herculesplus->crtc[1]; - video_res_y = herculesplus->crtc[6]; - video_bpp = 0; - } - } - herculesplus->firstline = 1000; - herculesplus->lastline = 0; - herculesplus->blink++; - } - } - else - { - herculesplus->sc++; - herculesplus->sc &= 31; - herculesplus->ma = herculesplus->maback; - } - if ((herculesplus->sc == (herculesplus->crtc[10] & 31) || ((herculesplus->crtc[8] & 3) == 3 && herculesplus->sc == ((herculesplus->crtc[10] & 31) >> 1)))) - { - herculesplus->con = 1; - } - } + free(dev->vram); + free(dev); } -void *herculesplus_init(const device_t *info) + +static void +speed_changed(void *priv) { - int c; - herculesplus_t *herculesplus = malloc(sizeof(herculesplus_t)); - memset(herculesplus, 0, sizeof(herculesplus_t)); + herculesplus_t *dev = (herculesplus_t *)priv; - herculesplus->vram = malloc(0x10000); /* 64k VRAM */ - - timer_add(herculesplus_poll, &herculesplus->vidtime, TIMER_ALWAYS_ENABLED, herculesplus); - mem_mapping_add(&herculesplus->mapping, 0xb0000, 0x10000, herculesplus_read, NULL, NULL, herculesplus_write, NULL, NULL, NULL, MEM_MAPPING_EXTERNAL, herculesplus); - io_sethandler(0x03b0, 0x0010, herculesplus_in, NULL, NULL, herculesplus_out, NULL, NULL, herculesplus); - - for (c = 0; c < 256; c++) - { - mdacols[c][0][0] = mdacols[c][1][0] = mdacols[c][1][1] = 16; - if (c & 8) mdacols[c][0][1] = 15 + 16; - else mdacols[c][0][1] = 7 + 16; - } - mdacols[0x70][0][1] = 16; - mdacols[0x70][0][0] = mdacols[0x70][1][0] = mdacols[0x70][1][1] = 16 + 15; - mdacols[0xF0][0][1] = 16; - mdacols[0xF0][0][0] = mdacols[0xF0][1][0] = mdacols[0xF0][1][1] = 16 + 15; - mdacols[0x78][0][1] = 16 + 7; - mdacols[0x78][0][0] = mdacols[0x78][1][0] = mdacols[0x78][1][1] = 16 + 15; - mdacols[0xF8][0][1] = 16 + 7; - mdacols[0xF8][0][0] = mdacols[0xF8][1][0] = mdacols[0xF8][1][1] = 16 + 15; - mdacols[0x00][0][1] = mdacols[0x00][1][1] = 16; - mdacols[0x08][0][1] = mdacols[0x08][1][1] = 16; - mdacols[0x80][0][1] = mdacols[0x80][1][1] = 16; - mdacols[0x88][0][1] = mdacols[0x88][1][1] = 16; - - /* Force the LPT3 port to be enabled. */ - parallel_enabled[2] = 1; - parallel_setup(3, 0x3BC); - - return herculesplus; + recalc_timings(dev); } -void herculesplus_close(void *p) -{ - herculesplus_t *herculesplus = (herculesplus_t *)p; - free(herculesplus->vram); - free(herculesplus); -} +static const video_timings_t herculesplus_timings = { VID_ISA,8,16,32,8,16,32 }; -void herculesplus_speed_changed(void *p) -{ - herculesplus_t *herculesplus = (herculesplus_t *)p; - - herculesplus_recalctimings(herculesplus); -} - -const device_t herculesplus_device = -{ - "Hercules Plus", - DEVICE_ISA, 0, - herculesplus_init, herculesplus_close, NULL, - NULL, - herculesplus_speed_changed, - NULL, - NULL, - NULL +const device_t herculesplus_device = { + "Hercules Plus", + DEVICE_ISA, + 0, + herculesplus_init, herculesplus_close, NULL, + NULL, + speed_changed, + NULL, + &herculesplus_timings, + NULL }; diff --git a/src/devices/video/vid_icd2061.c b/src/devices/video/vid_icd2061.c index 9f9b50e..bed113b 100644 --- a/src/devices/video/vid_icd2061.c +++ b/src/devices/video/vid_icd2061.c @@ -8,17 +8,17 @@ * * ICD2061 clock generator emulation. * - * Used by ET4000w32/p (Diamond Stealth 32) + * Also emulates the ICS9161 which is the same as the ICD2016, + * but without the need for tuning (which is irrelevant in + * emulation anyway). * - * Version: @(#)vid_icd2061.c 1.0.2 2018/05/06 + * Version: @(#)vid_icd2061.c 1.0.4 2018/10/05 * * Authors: Fred N. van Kempen, * Miran Grca, - * Sarah Walker, * - * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2018 Fred N. van Kempen. * Copyright 2016-2018 Miran Grca. - * Copyright 2008-2018 Sarah Walker. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -41,60 +41,134 @@ #include #include #include +#include #include #include "../../emu.h" +#include "../../device.h" +#include "video.h" #include "vid_icd2061.h" -void icd2061_write(icd2061_t *icd2061, int val) +void +icd2061_write(icd2061_t *dev, int val) { - int q, p, m, a; - if ((val & 1) && !(icd2061->state & 1)) - { - if (!icd2061->status) - { - if (val & 2) - icd2061->unlock++; - else - { - if (icd2061->unlock >= 5) - { - icd2061->status = 1; - icd2061->pos = 0; - } - else - icd2061->unlock = 0; - } - } - else if (val & 1) - { - icd2061->data = (icd2061->data >> 1) | (((val & 2) ? 1 : 0) << 24); - icd2061->pos++; - if (icd2061->pos == 26) - { - a = (icd2061->data >> 21) & 0x7; - if (!(a & 4)) - { - q = (icd2061->data & 0x7f) - 2; - m = 1 << ((icd2061->data >> 7) & 0x7); - p = ((icd2061->data >> 10) & 0x7f) - 3; - if (icd2061->ctrl & (1 << a)) - p <<= 1; - icd2061->freq[a] = ((double)p / (double)q) * 2.0 * 14318184.0 / (double)m; - } - else if (a == 6) - { - icd2061->ctrl = val; - } - icd2061->unlock = icd2061->data = 0; - icd2061->status = 0; - } - } - } - icd2061->state = val; + int /*od, */nd, oc, nc; + int a/*, i*/, qa, q, pa, p, m, ps; + +#if 0 + od = (dev->state & 2) >> 1; /* Old data. */ +#endif + nd = (val & 2) >> 1; /* Old data. */ + oc = dev->state & 1; /* Old clock. */ + nc = val & 1; /* New clock. */ + + dev->state = val; + + if (nc && !oc) { /* Low-to-high transition of CLK. */ + if (!dev->unlocked) { + if (nd) { /* DATA high. */ + dev->count++; + /* DEBUG("Low-to-high transition of CLK with DATA high, %i total\n", dev->count); */ + } else { /* DATA low. */ + if (dev->count >= 5) { + dev->unlocked = 1; + dev->bit_count = dev->data = 0; + /* DEBUG("ICD2061 unlocked\n"); */ + } else { + dev->count = 0; + /* DEBUG("ICD2061 locked\n"); */ + } + } + } else if (nc) { + dev->data |= (nd << dev->bit_count); + dev->bit_count++; + + if (dev->bit_count == 26) { + dev->data >>= 1; + /* DEBUG("26 bits received, data = %08X\n", dev->data); */ + + a = ((dev->data >> 22) & 0x07); /* A */ + /* DEBUG("A = %01X\n", a); */ + + if (a < 3) { +#if 0 + i = ((dev->data >> 18) & 0x0f); /* I */ +#endif + pa = ((dev->data >> 11) & 0x7f); /* P' (ICD2061) / N' (ICS9161) */ + m = ((dev->data >> 8) & 0x07); /* M (ICD2061) / R (ICS9161) */ + qa = ((dev->data >> 1) & 0x7f); /* Q' (ICD2061) / M' (ICS9161) */ + + p = pa + 3; /* P (ICD2061) / N (ICS9161) */ + m = 1 << m; + q = qa + 2; /* Q (ICD2061) / M (ICS9161) */ + ps = (dev->ctrl & (1 << a)) ? 4 : 2;/* Prescale */ + + dev->freq[a] = ((float)(p * ps) / (float)(q * m)) * 14318184.0f; + + /* DEBUG("P = %02X, M = %01X, Q = %02X, freq[%i] = %f\n", p, m, q, a, dev->freq[a]); */ + } else if (a == 6) { + dev->ctrl = ((dev->data >> 13) & 0xff); + /* DEBUG("ctrl = %02X\n", dev->ctrl); */ + } + dev->count = dev->bit_count = dev->data = 0; + dev->unlocked = 0; + /* DEBUG("ICD2061 locked\n"); */ + } + } + } } -double icd2061_getfreq(icd2061_t *icd2061, int i) + +float +icd2061_getclock(int clock, void *priv) { - return icd2061->freq[i]; + icd2061_t *dev = (icd2061_t *)priv; + + if (clock > 2) + clock = 2; + + return dev->freq[clock]; } + + +static void * +icd2061_init(const device_t *info) +{ + icd2061_t *dev = (icd2061_t *)mem_alloc(sizeof(icd2061_t)); + memset(dev, 0x00, sizeof(icd2061_t)); + + dev->freq[0] = 25175000.0; + dev->freq[1] = 28322000.0; + dev->freq[2] = 28322000.0; + + return(dev); +} + + +static void +icd2061_close(void *priv) +{ + icd2061_t *dev = (icd2061_t *)priv; + + if (dev != NULL) + free(dev); +} + + +const device_t icd2061_device = { + "ICD2061 Clock Generator", + 0, + 0, + icd2061_init, icd2061_close, NULL, + NULL, NULL, NULL, NULL, + NULL +}; + +const device_t ics9161_device = { + "ICS9161 Clock Generator", + 0, + 0, + icd2061_init, icd2061_close, NULL, + NULL, NULL, NULL, NULL, + NULL +}; diff --git a/src/devices/video/vid_icd2061.h b/src/devices/video/vid_icd2061.h index 4a4abfd..6353621 100644 --- a/src/devices/video/vid_icd2061.h +++ b/src/devices/video/vid_icd2061.h @@ -6,17 +6,15 @@ * * This file is part of the VARCem Project. * - * Definitions for the ICD2061 driver. + * Definitions for the ICD 2061/9161 driver. * - * Version: @(#)vid_icd2061.h 1.0.1 2018/02/14 + * Version: @(#)vid_icd2061.h 1.0.2 2018/10/05 * * Authors: Fred N. van Kempen, * Miran Grca, - * Sarah Walker, * * Copyright 2017,2018 Fred N. van Kempen. * Copyright 2016-2018 Miran Grca. - * Copyright 2008-2018 Sarah Walker. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -40,20 +38,28 @@ # define VIDEO_ICD2061_H -typedef struct icd2061_t -{ - int state; - int status; - int pos; - int unlock; - uint32_t data; +typedef struct { + float freq[3]; - double freq[4]; - uint32_t ctrl; + int count, + bit_count; + int unlocked, + state; + uint32_t data, + ctrl; } icd2061_t; -void icd2061_write(icd2061_t *icd2061, int val); -double icd2061_getfreq(icd2061_t *icd2061, int i); + +extern const device_t icd2061_device; +extern const device_t ics9161_device; + + +extern void icd2061_write(icd2061_t *icd2061, int val); +extern float icd2061_getclock(int clock, void *priv); + + +#define ics9161_write icd2061_write +#define ics9161_getclock icd2061_getclock #endif /*VIDEO_ICD2061_H*/ diff --git a/src/devices/video/vid_ics2595.c b/src/devices/video/vid_ics2595.c index 1d31c5c..0fcedb5 100644 --- a/src/devices/video/vid_ics2595.c +++ b/src/devices/video/vid_ics2595.c @@ -8,7 +8,7 @@ * * ICS2595 clock chip emulation. Used by ATI Mach64. * - * Version: @(#)vid_ics2595.c 1.0.2 2018/05/06 + * Version: @(#)vid_ics2595.c 1.0.3 2018/10/05 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -39,55 +39,86 @@ #include #include #include +#include #include #include "../../emu.h" +#include "../../device.h" #include "vid_ics2595.h" -enum -{ - ICS2595_IDLE = 0, - ICS2595_WRITE, - ICS2595_READ +enum { + ICS2595_IDLE = 0, + ICS2595_WRITE, + ICS2595_READ }; static int ics2595_div[4] = {8, 4, 2, 1}; -void ics2595_write(ics2595_t *ics2595, int strobe, int dat) +void +ics2595_write(ics2595_t *dev, int strobe, int dat) { - if (strobe) - { - if ((dat & 8) && !ics2595->oldfs3) /*Data clock*/ - { - switch (ics2595->state) - { - case ICS2595_IDLE: - ics2595->state = (dat & 4) ? ICS2595_WRITE : ICS2595_IDLE; - ics2595->pos = 0; - break; - case ICS2595_WRITE: - ics2595->dat = (ics2595->dat >> 1); - if (dat & 4) - ics2595->dat |= (1 << 19); - ics2595->pos++; - if (ics2595->pos == 20) - { - int d, n, l; - l = (ics2595->dat >> 2) & 0xf; - n = ((ics2595->dat >> 7) & 255) + 257; - d = ics2595_div[(ics2595->dat >> 16) & 3]; + int d, n, l; - ics2595->clocks[l] = (14318181.8 * ((double)n / 46.0)) / (double)d; - ics2595->state = ICS2595_IDLE; - } - break; - } - } - - ics2595->oldfs2 = dat & 4; - ics2595->oldfs3 = dat & 8; - } - ics2595->output_clock = ics2595->clocks[dat]; + if (strobe) { + if ((dat & 8) && !dev->oldfs3) { /*Data clock*/ + switch (dev->state) { + case ICS2595_IDLE: + dev->state = (dat & 4) ? ICS2595_WRITE : ICS2595_IDLE; + dev->pos = 0; + break; + + case ICS2595_WRITE: + dev->dat = (dev->dat >> 1); + if (dat & 4) + dev->dat |= (1 << 19); + dev->pos++; + if (dev->pos == 20) { + l = (dev->dat >> 2) & 0xf; + n = ((dev->dat >> 7) & 255) + 257; + d = ics2595_div[(dev->dat >> 16) & 3]; + + dev->clocks[l] = (14318181.8 * ((double)n / 46.0)) / (double)d; + dev->state = ICS2595_IDLE; + } + break; + } + } + + dev->oldfs2 = dat & 4; + dev->oldfs3 = dat & 8; + } + + dev->output_clock = dev->clocks[dat]; } + + +static void * +ics2595_init(const device_t *info) +{ + ics2595_t *dev = (ics2595_t *)mem_alloc(sizeof(ics2595_t)); + memset(dev, 0x00, sizeof(ics2595_t)); + + return dev; +} + + +static void +ics2595_close(void *priv) +{ + ics2595_t *dev = (ics2595_t *)priv; + + if (dev != NULL) + free(dev); +} + + +const device_t ics2595_device = { + "ICS2595 clock chip", + 0, + 0, + ics2595_init, ics2595_close, NULL, + NULL, NULL, NULL, NULL, + NULL +}; diff --git a/src/devices/video/vid_ics2595.h b/src/devices/video/vid_ics2595.h index 2ceddfc..f800d03 100644 --- a/src/devices/video/vid_ics2595.h +++ b/src/devices/video/vid_ics2595.h @@ -8,7 +8,7 @@ * * Definitions for the ICS2595 driver. * - * Version: @(#)vid_ics2595.h 1.0.1 2018/02/14 + * Version: @(#)vid_ics2595.h 1.0.2 2018/10/05 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -40,18 +40,19 @@ # define VIDEO_ICS2595_H -typedef struct ics2595_t -{ - int oldfs3, oldfs2; - int dat; - int pos; - int state; - - double clocks[16]; - double output_clock; +typedef struct { + int oldfs3, oldfs2; + int dat; + int pos, state; + double clocks[16]; + double output_clock; } ics2595_t; -void ics2595_write(ics2595_t *ics2595, int strobe, int dat); + +extern const device_t ics2595_device; + + +extern void ics2595_write(ics2595_t *dev, int strobe, int dat); #endif /*VIDEO_ICS2595_H*/ diff --git a/src/devices/video/vid_incolor.c b/src/devices/video/vid_incolor.c index 3402d94..8369628 100644 --- a/src/devices/video/vid_incolor.c +++ b/src/devices/video/vid_incolor.c @@ -8,7 +8,7 @@ * * Hercules InColor emulation. * - * Version: @(#)vid_incolor.c 1.0.8 2018/05/06 + * Version: @(#)vid_incolor.c 1.0.9 2018/09/22 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -64,7 +64,7 @@ #define INCOLOR_CRTC_PALETTE 28 /* Palette */ /* character width */ -#define INCOLOR_CW ((incolor->crtc[INCOLOR_CRTC_XMODE] & INCOLOR_XMODE_90COL) ? 8 : 9) +#define INCOLOR_CW ((dev->crtc[INCOLOR_CRTC_XMODE] & INCOLOR_XMODE_90COL) ? 8 : 9) /* mode control register */ #define INCOLOR_CTRL_GRAPH 0x02 @@ -100,13 +100,11 @@ /* Default palette */ -static uint8_t defpal[16] = { +static const uint8_t defpal[16] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F }; -static uint32_t incolor_rgb[64]; - /* Mapping of inks to RGB */ static const uint8_t init_rgb[64][3] = { /* rgbRGB */ @@ -177,256 +175,275 @@ static const uint8_t init_rgb[64][3] = { }; -typedef struct incolor_t -{ - mem_mapping_t mapping; - - uint8_t crtc[32]; - int crtcreg; +typedef struct { + mem_map_t mapping; - uint8_t ctrl, ctrl2, stat; + uint8_t crtc[32]; + int crtcreg; - int64_t dispontime, dispofftime; - int64_t vidtime; - - int firstline, lastline; + uint8_t ctrl, ctrl2, stat; - int linepos, displine; - int vc, sc; - uint16_t ma, maback; - int con, coff, cursoron; - int dispon, blink; - int64_t vsynctime; - int vadj; + int64_t dispontime, dispofftime; + int64_t vidtime; - uint8_t palette[16]; /* EGA-style 16 -> 64 palette registers */ - uint8_t palette_idx; /* Palette write index */ - uint8_t latch[4]; /* Memory read/write latches */ - uint8_t *vram; + int firstline, lastline; + + int linepos, displine; + int vc, sc; + uint16_t ma, maback; + int con, coff, cursoron; + int dispon, blink; + int64_t vsynctime; + int vadj; + + uint8_t palette[16]; /* EGA-style 16 -> 64 palette registers */ + uint8_t palette_idx; /* Palette write index */ + uint8_t latch[4]; /* Memory read/write latches */ + + uint32_t rgb[64]; + + uint8_t *vram; } incolor_t; -static void incolor_recalctimings(incolor_t *incolor); -static void incolor_write(uint32_t addr, uint8_t val, void *p); -static uint8_t incolor_read(uint32_t addr, void *p); - -static void incolor_out(uint16_t addr, uint8_t val, void *p) +static void +recalc_timings(incolor_t *dev) { - incolor_t *incolor = (incolor_t *)p; -/* pclog("InColor out %04X %02X\n",addr,val); */ - switch (addr) - { - case 0x3b0: case 0x3b2: case 0x3b4: case 0x3b6: - incolor->crtcreg = val & 31; - return; - case 0x3b1: case 0x3b3: case 0x3b5: case 0x3b7: - if (incolor->crtcreg > 28) return; - /* Palette load register */ - if (incolor->crtcreg == INCOLOR_CRTC_PALETTE) - { - incolor->palette[incolor->palette_idx % 16] = val; - ++incolor->palette_idx; - } - incolor->crtc[incolor->crtcreg] = val; - if (incolor->crtc[10] == 6 && incolor->crtc[11] == 7) /*Fix for Generic Turbo XT BIOS, which sets up cursor registers wrong*/ - { - incolor->crtc[10] = 0xb; - incolor->crtc[11] = 0xc; - } - incolor_recalctimings(incolor); - return; - case 0x3b8: - incolor->ctrl = val; - return; - case 0x3bf: - incolor->ctrl2 = val; - if (val & 2) - mem_mapping_set_addr(&incolor->mapping, 0xb0000, 0x10000); - else - mem_mapping_set_addr(&incolor->mapping, 0xb0000, 0x08000); - return; - } + double disptime; + double _dispontime, _dispofftime; + + disptime = dev->crtc[0] + 1; + _dispontime = dev->crtc[1]; + _dispofftime = disptime - _dispontime; + _dispontime *= MDACONST; + _dispofftime *= MDACONST; + + dev->dispontime = (int64_t)(_dispontime * (1 << TIMER_SHIFT)); + dev->dispofftime = (int64_t)(_dispofftime * (1 << TIMER_SHIFT)); } -static uint8_t incolor_in(uint16_t addr, void *p) + +static void +incolor_out(uint16_t port, uint8_t val, void *priv) { - incolor_t *incolor = (incolor_t *)p; -/* pclog("InColor in %04X %02X %04X:%04X %04X\n",addr,(incolor->stat & 0xF) | ((incolor->stat & 8) << 4),CS,pc,CX); */ - switch (addr) - { - case 0x3b0: case 0x3b2: case 0x3b4: case 0x3b6: - return incolor->crtcreg; - case 0x3b1: case 0x3b3: case 0x3b5: case 0x3b7: - if (incolor->crtcreg > 28) return 0xff; - incolor->palette_idx = 0; /* Read resets the palette index */ - return incolor->crtc[incolor->crtcreg]; - case 0x3ba: - /* 0x50: InColor card identity */ - return (incolor->stat & 0xf) | ((incolor->stat & 8) << 4) | 0x50; - } - return 0xff; -} + incolor_t *dev = (incolor_t *)priv; -static void incolor_write(uint32_t addr, uint8_t val, void *p) -{ - incolor_t *incolor = (incolor_t *)p; - - int plane; - - unsigned char wmask = incolor->crtc[INCOLOR_CRTC_MASK]; - unsigned char wmode = incolor->crtc[INCOLOR_CRTC_RWCTRL] & INCOLOR_RWCTRL_WRMODE; - unsigned char fg = incolor->crtc[INCOLOR_CRTC_RWCOL] & 0x0F; - unsigned char bg = (incolor->crtc[INCOLOR_CRTC_RWCOL] >> 4)&0x0F; - unsigned char w = 0; - unsigned char vmask; /* Mask of bit within byte */ - unsigned char pmask; /* Mask of plane within colour value */ - unsigned char latch; - - egawrites++; - - addr &= 0xFFFF; - - /* In text mode, writes to the bottom 16k always touch all 4 planes */ - if (!(incolor->ctrl & INCOLOR_CTRL_GRAPH) && addr < 0x4000) - { - incolor->vram[addr] = val; + switch (port) { + case 0x3b0: + case 0x3b2: + case 0x3b4: + case 0x3b6: + dev->crtcreg = val & 31; return; - } - /* There are four write modes: - * 0: 1 => foreground, 0 => background - * 1: 1 => foreground, 0 => source latch - * 2: 1 => source latch, 0 => background - * 3: 1 => source latch, 0 => ~source latch - */ - pmask = 1; - for (plane = 0; plane < 4; pmask <<= 1, wmask >>= 1, addr += 0x10000, - plane++) - { - if (wmask & 0x10) /* Ignore writes to selected plane */ - { - continue; + case 0x3b1: case 0x3b3: case 0x3b5: case 0x3b7: + if (dev->crtcreg > 28) return; + /* Palette load register */ + if (dev->crtcreg == INCOLOR_CRTC_PALETTE) { + dev->palette[dev->palette_idx % 16] = val; + ++dev->palette_idx; + } + dev->crtc[dev->crtcreg] = val; + + if (dev->crtc[10] == 6 && dev->crtc[11] == 7) { + /*Fix for Generic Turbo XT BIOS, + * which sets up cursor registers wrong*/ + dev->crtc[10] = 0xb; + dev->crtc[11] = 0xc; } - latch = incolor->latch[plane]; - for (vmask = 0x80; vmask != 0; vmask >>= 1) - { - switch (wmode) - { - case 0x00: - if (val & vmask) w = (fg & pmask); - else w = (bg & pmask); - break; - case 0x10: - if (val & vmask) w = (fg & pmask); - else w = (latch & vmask); - break; - case 0x20: - if (val & vmask) w = (latch & vmask); - else w = (bg & pmask); - break; - case 0x30: - if (val & vmask) w = (latch & vmask); - else w = ((~latch) & vmask); - break; - } + recalc_timings(dev); + return; + + case 0x3b8: + dev->ctrl = val; + return; + + case 0x3bf: + dev->ctrl2 = val; + if (val & 2) + mem_map_set_addr(&dev->mapping, 0xb0000, 0x10000); + else + mem_map_set_addr(&dev->mapping, 0xb0000, 0x08000); + return; + } +} + + +static uint8_t +incolor_in(uint16_t port, void *priv) +{ + incolor_t *dev = (incolor_t *)priv; + uint8_t ret = 0xff; + + switch (port) { + case 0x3b0: + case 0x3b2: + case 0x3b4: + case 0x3b6: + ret = dev->crtcreg; + break; + + case 0x3b1: + case 0x3b3: + case 0x3b5: + case 0x3b7: + if (dev->crtcreg > 28) break; + + dev->palette_idx = 0; /* Read resets the palette index */ + ret = dev->crtc[dev->crtcreg]; + break; + + case 0x3ba: + /* 0x50: InColor card identity */ + ret = (dev->stat & 0xf) | ((dev->stat & 8) << 4) | 0x50; + break; + + default: + break; + } + + return ret; +} + + +static void +incolor_write(uint32_t addr, uint8_t val, void *priv) +{ + incolor_t *dev = (incolor_t *)priv; + unsigned char wmask = dev->crtc[INCOLOR_CRTC_MASK]; + unsigned char wmode = dev->crtc[INCOLOR_CRTC_RWCTRL] & INCOLOR_RWCTRL_WRMODE; + unsigned char fg = dev->crtc[INCOLOR_CRTC_RWCOL] & 0x0F; + unsigned char bg = (dev->crtc[INCOLOR_CRTC_RWCOL] >> 4)&0x0F; + unsigned char w = 0; + unsigned char vmask; /* Mask of bit within byte */ + unsigned char pmask; /* Mask of plane within colour value */ + unsigned char latch; + int plane; + + addr &= 0xffff; + + /* In text mode, writes to the bottom 16k always touch all 4 planes */ + if (!(dev->ctrl & INCOLOR_CTRL_GRAPH) && addr < 0x4000) { + dev->vram[addr] = val; + return; + } + + /* There are four write modes: + * 0: 1 => foreground, 0 => background + * 1: 1 => foreground, 0 => source latch + * 2: 1 => source latch, 0 => background + * 3: 1 => source latch, 0 => ~source latch + */ + pmask = 1; + for (plane = 0; plane < 4; pmask <<= 1, wmask >>= 1, addr += 0x10000, plane++) { + if (wmask & 0x10) /* Ignore writes to selected plane */ + { + continue; + } + latch = dev->latch[plane]; + for (vmask = 0x80; vmask != 0; vmask >>= 1) { + switch (wmode) { + case 0x00: + if (val & vmask) w = (fg & pmask); + else w = (bg & pmask); + break; + + case 0x10: + if (val & vmask) w = (fg & pmask); + else w = (latch & vmask); + break; + + case 0x20: + if (val & vmask) w = (latch & vmask); + else w = (bg & pmask); + break; + + case 0x30: + if (val & vmask) w = (latch & vmask); + else w = ((~latch) & vmask); + break; + } + /* w is nonzero to write a 1, zero to write a 0 */ - if (w) incolor->vram[addr] |= vmask; - else incolor->vram[addr] &= ~vmask; + if (w) dev->vram[addr] |= vmask; + else dev->vram[addr] &= ~vmask; + } + } +} + + +static uint8_t +incolor_read(uint32_t addr, void *priv) +{ + incolor_t *dev = (incolor_t *)priv; + unsigned plane; + unsigned char lp = dev->crtc[INCOLOR_CRTC_PROTECT]; + unsigned char value = 0; + unsigned char dc; /* "don't care" register */ + unsigned char bg; /* background colour */ + unsigned char fg; + unsigned char mask, pmask; + + addr &= 0xffff; + + /* Read the four planes into latches */ + for (plane = 0; plane < 4; plane++, addr += 0x10000) { + dev->latch[plane] &= lp; + dev->latch[plane] |= (dev->vram[addr] & ~lp); + } + addr &= 0xffff; + + /* In text mode, reads from the bottom 16k assume all planes have + * the same contents */ + if (!(dev->ctrl & INCOLOR_CTRL_GRAPH) && addr < 0x4000) { + return dev->latch[0]; + } + + /* For each pixel, work out if its colour matches the background */ + for (mask = 0x80; mask != 0; mask >>= 1) { + fg = 0; + dc = dev->crtc[INCOLOR_CRTC_RWCTRL] & 0x0F; + bg = (dev->crtc[INCOLOR_CRTC_RWCOL] >> 4) & 0x0F; + for (plane = 0, pmask = 1; plane < 4; plane++, pmask <<= 1) { + if (dc & pmask) { + fg |= (bg & pmask); + } else if (dev->latch[plane] & mask) { + fg |= pmask; } - } -} + } + if (bg == fg) value |= mask; + } -static uint8_t incolor_read(uint32_t addr, void *p) -{ - incolor_t *incolor = (incolor_t *)p; - unsigned plane; - unsigned char lp = incolor->crtc[INCOLOR_CRTC_PROTECT]; - unsigned char value = 0; - unsigned char dc; /* "don't care" register */ - unsigned char bg; /* background colour */ - unsigned char fg; - unsigned char mask, pmask; + if (dev->crtc[INCOLOR_CRTC_RWCTRL] & INCOLOR_RWCTRL_POLARITY) + value = ~value; - egareads++; - - addr &= 0xFFFF; - /* Read the four planes into latches */ - for (plane = 0; plane < 4; plane++, addr += 0x10000) - { - incolor->latch[plane] &= lp; - incolor->latch[plane] |= (incolor->vram[addr] & ~lp); - } - addr &= 0xFFFF; - /* In text mode, reads from the bottom 16k assume all planes have - * the same contents */ - if (!(incolor->ctrl & INCOLOR_CTRL_GRAPH) && addr < 0x4000) - { - return incolor->latch[0]; - } - /* For each pixel, work out if its colour matches the background */ - for (mask = 0x80; mask != 0; mask >>= 1) - { - fg = 0; - dc = incolor->crtc[INCOLOR_CRTC_RWCTRL] & 0x0F; - bg = (incolor->crtc[INCOLOR_CRTC_RWCOL] >> 4) & 0x0F; - for (plane = 0, pmask = 1; plane < 4; plane++, pmask <<= 1) - { - if (dc & pmask) - { - fg |= (bg & pmask); - } - else if (incolor->latch[plane] & mask) - { - fg |= pmask; - } - } - if (bg == fg) value |= mask; - } - if (incolor->crtc[INCOLOR_CRTC_RWCTRL] & INCOLOR_RWCTRL_POLARITY) - { - value = ~value; - } - return value; + return value; } - -static void incolor_recalctimings(incolor_t *incolor) +static void +draw_char_rom(incolor_t *dev, int x, uint8_t chr, uint8_t attr) { - double disptime; - double _dispontime, _dispofftime; - disptime = incolor->crtc[0] + 1; - _dispontime = incolor->crtc[1]; - _dispofftime = disptime - _dispontime; - _dispontime *= MDACONST; - _dispofftime *= MDACONST; - incolor->dispontime = (int64_t)(_dispontime * (1 << TIMER_SHIFT)); - incolor->dispofftime = (int64_t)(_dispofftime * (1 << TIMER_SHIFT)); -} - - -static void incolor_draw_char_rom(incolor_t *incolor, int x, uint8_t chr, uint8_t attr) -{ - int i; - int elg, blk; - unsigned ull; - unsigned val; + int i; + int elg, blk; + unsigned ull; + unsigned val; unsigned ifg, ibg; const unsigned char *fnt; uint32_t fg, bg; int cw = INCOLOR_CW; blk = 0; - if (incolor->ctrl & INCOLOR_CTRL_BLINK) + if (dev->ctrl & INCOLOR_CTRL_BLINK) { if (attr & 0x80) { - blk = (incolor->blink & 16); + blk = (dev->blink & 16); } attr &= 0x7f; } - if (incolor->crtc[INCOLOR_CRTC_EXCEPT] & INCOLOR_EXCEPT_ALTATTR) + if (dev->crtc[INCOLOR_CRTC_EXCEPT] & INCOLOR_EXCEPT_ALTATTR) { /* MDA-compatible attributes */ ibg = 0; @@ -457,19 +474,19 @@ static void incolor_draw_char_rom(incolor_t *incolor, int x, uint8_t chr, uint8_ ifg = attr & 0x0F; ibg = (attr >> 4) & 0x0F; } - if (incolor->crtc[INCOLOR_CRTC_EXCEPT] & INCOLOR_EXCEPT_PALETTE) + if (dev->crtc[INCOLOR_CRTC_EXCEPT] & INCOLOR_EXCEPT_PALETTE) { - fg = incolor_rgb[incolor->palette[ifg]]; - bg = incolor_rgb[incolor->palette[ibg]]; + fg = dev->rgb[dev->palette[ifg]]; + bg = dev->rgb[dev->palette[ibg]]; } else { - fg = incolor_rgb[defpal[ifg]]; - bg = incolor_rgb[defpal[ibg]]; + fg = dev->rgb[defpal[ifg]]; + bg = dev->rgb[defpal[ibg]]; } /* ELG set to stretch 8px character to 9px */ - if (incolor->crtc[INCOLOR_CRTC_XMODE] & INCOLOR_XMODE_90COL) + if (dev->crtc[INCOLOR_CRTC_XMODE] & INCOLOR_XMODE_90COL) { elg = 0; } @@ -478,13 +495,13 @@ static void incolor_draw_char_rom(incolor_t *incolor, int x, uint8_t chr, uint8_ elg = ((chr >= 0xc0) && (chr <= 0xdf)); } - fnt = &(fontdatm[chr][incolor->sc]); + fnt = &(fontdatm[chr][dev->sc]); if (blk) { val = 0x000; /* Blinking, draw all background */ } - else if (incolor->sc == ull) + else if (dev->sc == ull) { val = 0x1ff; /* Underscore, draw all foreground */ } @@ -499,32 +516,33 @@ static void incolor_draw_char_rom(incolor_t *incolor, int x, uint8_t chr, uint8_ } for (i = 0; i < cw; i++) { - ((uint32_t *)buffer32->line[incolor->displine])[x * cw + i] = (val & 0x100) ? fg : bg; + ((uint32_t *)buffer32->line[dev->displine])[x * cw + i] = (val & 0x100) ? fg : bg; val = val << 1; } } -static void incolor_draw_char_ram4(incolor_t *incolor, int x, uint8_t chr, uint8_t attr) +static void +draw_char_ram4(incolor_t *dev, int x, uint8_t chr, uint8_t attr) { - int i; - int elg, blk; - unsigned ull; - unsigned val[4]; + int i; + int elg, blk; + unsigned ull; + unsigned val[4]; unsigned ifg, ibg, cfg, pmask, plane; const unsigned char *fnt; uint32_t fg; int cw = INCOLOR_CW; - int blink = incolor->ctrl & INCOLOR_CTRL_BLINK; - int altattr = incolor->crtc[INCOLOR_CRTC_EXCEPT] & INCOLOR_EXCEPT_ALTATTR; - int palette = incolor->crtc[INCOLOR_CRTC_EXCEPT] & INCOLOR_EXCEPT_PALETTE; + int blink = dev->ctrl & INCOLOR_CTRL_BLINK; + int altattr = dev->crtc[INCOLOR_CRTC_EXCEPT] & INCOLOR_EXCEPT_ALTATTR; + int palette = dev->crtc[INCOLOR_CRTC_EXCEPT] & INCOLOR_EXCEPT_PALETTE; blk = 0; if (blink) { if (attr & 0x80) { - blk = (incolor->blink & 16); + blk = (dev->blink & 16); } attr &= 0x7f; } @@ -560,7 +578,7 @@ static void incolor_draw_char_ram4(incolor_t *incolor, int x, uint8_t chr, uint8 ifg = attr & 0x0F; ibg = (attr >> 4) & 0x0F; } - if (incolor->crtc[INCOLOR_CRTC_XMODE] & INCOLOR_XMODE_90COL) + if (dev->crtc[INCOLOR_CRTC_XMODE] & INCOLOR_XMODE_90COL) { elg = 0; } @@ -568,14 +586,14 @@ static void incolor_draw_char_ram4(incolor_t *incolor, int x, uint8_t chr, uint8 { elg = ((chr >= 0xc0) && (chr <= 0xdf)); } - fnt = incolor->vram + 0x4000 + 16 * chr + incolor->sc; + fnt = dev->vram + 0x4000 + 16 * chr + dev->sc; if (blk) { /* Blinking, draw all background */ val[0] = val[1] = val[2] = val[3] = 0x000; } - else if (incolor->sc == ull) + else if (dev->sc == ull) { /* Underscore, draw all foreground */ val[0] = val[1] = val[2] = val[3] = 0x1ff; @@ -609,14 +627,14 @@ static void incolor_draw_char_ram4(incolor_t *incolor, int x, uint8_t chr, uint8 if (altattr && (attr & 0x77) == 0) cfg = ibg; /* 'blank' attribute */ if (palette) { - fg = incolor_rgb[incolor->palette[cfg]]; + fg = dev->rgb[dev->palette[cfg]]; } else { - fg = incolor_rgb[defpal[cfg]]; + fg = dev->rgb[defpal[cfg]]; } - ((uint32_t *)buffer32->line[incolor->displine])[x * cw + i] = fg; + ((uint32_t *)buffer32->line[dev->displine])[x * cw + i] = fg; val[0] = val[0] << 1; val[1] = val[1] << 1; val[2] = val[2] << 1; @@ -625,19 +643,20 @@ static void incolor_draw_char_ram4(incolor_t *incolor, int x, uint8_t chr, uint8 } -static void incolor_draw_char_ram48(incolor_t *incolor, int x, uint8_t chr, uint8_t attr) +static void +draw_char_ram48(incolor_t *dev, int x, uint8_t chr, uint8_t attr) { - int i; - int elg, blk, ul, ol, bld; - unsigned ull, oll, ulc = 0, olc = 0; - unsigned val[4]; + int i; + int elg, blk, ul, ol, bld; + unsigned ull, oll, ulc = 0, olc = 0; + unsigned val[4]; unsigned ifg = 0, ibg, cfg, pmask, plane; const unsigned char *fnt; uint32_t fg; int cw = INCOLOR_CW; - int blink = incolor->ctrl & INCOLOR_CTRL_BLINK; - int altattr = incolor->crtc[INCOLOR_CRTC_EXCEPT] & INCOLOR_EXCEPT_ALTATTR; - int palette = incolor->crtc[INCOLOR_CRTC_EXCEPT] & INCOLOR_EXCEPT_PALETTE; + int blink = dev->ctrl & INCOLOR_CTRL_BLINK; + int altattr = dev->crtc[INCOLOR_CRTC_EXCEPT] & INCOLOR_EXCEPT_ALTATTR; + int palette = dev->crtc[INCOLOR_CRTC_EXCEPT] & INCOLOR_EXCEPT_PALETTE; int font = (attr & 0x0F); if (font >= 12) font &= 7; @@ -647,7 +666,7 @@ static void incolor_draw_char_ram48(incolor_t *incolor, int x, uint8_t chr, uint { if (attr & 0x40) { - blk = (incolor->blink & 16); + blk = (dev->blink & 16); } attr &= 0x7f; } @@ -680,8 +699,8 @@ static void incolor_draw_char_ram48(incolor_t *incolor, int x, uint8_t chr, uint } if (ul) { - ull = incolor->crtc[INCOLOR_CRTC_UNDER] & 0x0F; - ulc = (incolor->crtc[INCOLOR_CRTC_UNDER] >> 4) & 0x0F; + ull = dev->crtc[INCOLOR_CRTC_UNDER] & 0x0F; + ulc = (dev->crtc[INCOLOR_CRTC_UNDER] >> 4) & 0x0F; if (ulc == 0) ulc = 7; } else @@ -690,8 +709,8 @@ static void incolor_draw_char_ram48(incolor_t *incolor, int x, uint8_t chr, uint } if (ol) { - oll = incolor->crtc[INCOLOR_CRTC_OVER] & 0x0F; - olc = (incolor->crtc[INCOLOR_CRTC_OVER] >> 4) & 0x0F; + oll = dev->crtc[INCOLOR_CRTC_OVER] & 0x0F; + olc = (dev->crtc[INCOLOR_CRTC_OVER] >> 4) & 0x0F; if (olc == 0) olc = 7; } else @@ -699,7 +718,7 @@ static void incolor_draw_char_ram48(incolor_t *incolor, int x, uint8_t chr, uint oll = 0xFFFF; } - if (incolor->crtc[INCOLOR_CRTC_XMODE] & INCOLOR_XMODE_90COL) + if (dev->crtc[INCOLOR_CRTC_XMODE] & INCOLOR_XMODE_90COL) { elg = 0; } @@ -707,14 +726,14 @@ static void incolor_draw_char_ram48(incolor_t *incolor, int x, uint8_t chr, uint { elg = ((chr >= 0xc0) && (chr <= 0xdf)); } - fnt = incolor->vram + 0x4000 + 16 * chr + 4096 * font + incolor->sc; + fnt = dev->vram + 0x4000 + 16 * chr + 4096 * font + dev->sc; if (blk) { /* Blinking, draw all background */ val[0] = val[1] = val[2] = val[3] = 0x000; } - else if (incolor->sc == ull) + else if (dev->sc == ull) { /* Underscore, draw all foreground */ val[0] = val[1] = val[2] = val[3] = 0x1ff; @@ -746,11 +765,11 @@ static void incolor_draw_char_ram48(incolor_t *incolor, int x, uint8_t chr, uint /* Generate pixel colour */ cfg = 0; pmask = 1; - if (incolor->sc == oll) + if (dev->sc == oll) { cfg = olc ^ ibg; /* Strikethrough */ } - else if (incolor->sc == ull) + else if (dev->sc == ull) { cfg = ulc ^ ibg; /* Underline */ } @@ -768,14 +787,14 @@ static void incolor_draw_char_ram48(incolor_t *incolor, int x, uint8_t chr, uint } if (palette) { - fg = incolor_rgb[incolor->palette[cfg]]; + fg = dev->rgb[dev->palette[cfg]]; } else { - fg = incolor_rgb[defpal[cfg]]; + fg = dev->rgb[defpal[cfg]]; } - ((uint32_t *)buffer32->line[incolor->displine])[x * cw + i] = fg; + ((uint32_t *)buffer32->line[dev->displine])[x * cw + i] = fg; val[0] = val[0] << 1; val[1] = val[1] << 1; val[2] = val[2] << 1; @@ -784,320 +803,306 @@ static void incolor_draw_char_ram48(incolor_t *incolor, int x, uint8_t chr, uint } - - - - -static void incolor_text_line(incolor_t *incolor, uint16_t ca) +static void +text_line(incolor_t *dev, uint16_t ca) { - int drawcursor; - int x, c; - uint8_t chr, attr; - uint32_t col; + int drawcursor; + int x, c; + uint8_t chr, attr; + uint32_t col; - for (x = 0; x < incolor->crtc[1]; x++) - { - chr = incolor->vram[(incolor->ma << 1) & 0xfff]; - attr = incolor->vram[((incolor->ma << 1) + 1) & 0xfff]; + for (x = 0; x < dev->crtc[1]; x++) { + chr = dev->vram[(dev->ma << 1) & 0xfff]; + attr = dev->vram[((dev->ma << 1) + 1) & 0xfff]; - drawcursor = ((incolor->ma == ca) && incolor->con && incolor->cursoron); + drawcursor = ((dev->ma == ca) && dev->con && dev->cursoron); - switch (incolor->crtc[INCOLOR_CRTC_XMODE] & 5) + switch (dev->crtc[INCOLOR_CRTC_XMODE] & 5) { + case 0: + case 4: /* ROM font */ + draw_char_rom(dev, x, chr, attr); + break; + + case 1: /* 4k RAMfont */ + draw_char_ram4(dev, x, chr, attr); + break; + + case 5: /* 48k RAMfont */ + draw_char_ram48(dev, x, chr, attr); + break; + } + ++dev->ma; + + if (drawcursor) { + int cw = INCOLOR_CW; + uint8_t ink = dev->crtc[INCOLOR_CRTC_EXCEPT] & INCOLOR_EXCEPT_CURSOR; + if (ink == 0) ink = (attr & 0x08) | 7; + + /* In MDA-compatible mode, cursor brightness comes from + * background */ + if (dev->crtc[INCOLOR_CRTC_EXCEPT] & INCOLOR_EXCEPT_ALTATTR) { - case 0: - case 4: /* ROM font */ - incolor_draw_char_rom(incolor, x, chr, attr); - break; - case 1: /* 4k RAMfont */ - incolor_draw_char_ram4(incolor, x, chr, attr); - break; - case 5: /* 48k RAMfont */ - incolor_draw_char_ram48(incolor, x, chr, attr); - break; - + ink = (attr & 0x08) | (ink & 7); } - ++incolor->ma; - if (drawcursor) - { - int cw = INCOLOR_CW; - uint8_t ink = incolor->crtc[INCOLOR_CRTC_EXCEPT] & INCOLOR_EXCEPT_CURSOR; - if (ink == 0) ink = (attr & 0x08) | 7; - - /* In MDA-compatible mode, cursor brightness comes from - * background */ - if (incolor->crtc[INCOLOR_CRTC_EXCEPT] & INCOLOR_EXCEPT_ALTATTR) - { - ink = (attr & 0x08) | (ink & 7); - } - if (incolor->crtc[INCOLOR_CRTC_EXCEPT] & INCOLOR_EXCEPT_PALETTE) - { - col = incolor_rgb[incolor->palette[ink]]; - } - else - { - col = incolor_rgb[defpal[ink]]; - } - for (c = 0; c < cw; c++) - { - ((uint32_t *)buffer32->line[incolor->displine])[x * cw + c] = col; - } - } - } -} - - -static void incolor_graphics_line(incolor_t *incolor) -{ - uint8_t mask; - uint16_t ca; - int x, c, plane, col; - uint8_t ink; - uint16_t val[4]; - - /* Graphics mode. */ - ca = (incolor->sc & 3) * 0x2000; - if ((incolor->ctrl & INCOLOR_CTRL_PAGE1) && (incolor->ctrl2 & INCOLOR_CTRL2_PAGE1)) - ca += 0x8000; - - for (x = 0; x < incolor->crtc[1]; x++) - { - mask = incolor->crtc[INCOLOR_CRTC_MASK]; /* Planes to display */ - for (plane = 0; plane < 4; plane++, mask = mask >> 1) + if (dev->crtc[INCOLOR_CRTC_EXCEPT] & INCOLOR_EXCEPT_PALETTE) { - if (mask & 1) - val[plane] = (incolor->vram[((incolor->ma << 1) & 0x1fff) + ca + 0x10000 * plane] << 8) | - incolor->vram[((incolor->ma << 1) & 0x1fff) + ca + 0x10000 * plane + 1]; - else val[plane] = 0; - } - incolor->ma++; - for (c = 0; c < 16; c++) + col = dev->rgb[dev->palette[ink]]; + } + else { - ink = 0; - for (plane = 0; plane < 4; plane++) - { - ink = ink >> 1; - if (val[plane] & 0x8000) ink |= 8; - val[plane] = val[plane] << 1; - } - /* Is palette in use? */ - if (incolor->crtc[INCOLOR_CRTC_EXCEPT] & INCOLOR_EXCEPT_PALETTE) - col = incolor->palette[ink]; - else col = defpal[ink]; - - ((uint32_t *)buffer32->line[incolor->displine])[(x << 4) + c] = incolor_rgb[col]; + col = dev->rgb[defpal[ink]]; + } + for (c = 0; c < cw; c++) + { + ((uint32_t *)buffer32->line[dev->displine])[x * cw + c] = col; } } + } } -static void incolor_poll(void *p) + +static void +graphics_line(incolor_t *dev) { - incolor_t *incolor = (incolor_t *)p; - uint16_t ca = (incolor->crtc[15] | (incolor->crtc[14] << 8)) & 0x3fff; - int x; - int oldvc; - int oldsc; + uint8_t mask; + uint16_t ca; + int x, c, plane, col; + uint8_t ink; + uint16_t val[4]; - if (!incolor->linepos) - { - incolor->vidtime += incolor->dispofftime; - incolor->stat |= 1; - incolor->linepos = 1; - oldsc = incolor->sc; - if ((incolor->crtc[8] & 3) == 3) - incolor->sc = (incolor->sc << 1) & 7; - if (incolor->dispon) - { - if (incolor->displine < incolor->firstline) - { - incolor->firstline = incolor->displine; - video_wait_for_buffer(); - } - incolor->lastline = incolor->displine; - if ((incolor->ctrl & INCOLOR_CTRL_GRAPH) && (incolor->ctrl2 & INCOLOR_CTRL2_GRAPH)) - { - incolor_graphics_line(incolor); - } - else - { - incolor_text_line(incolor, ca); - } - } - incolor->sc = oldsc; - if (incolor->vc == incolor->crtc[7] && !incolor->sc) - { - incolor->stat |= 8; - } - incolor->displine++; - if (incolor->displine >= 500) - incolor->displine = 0; - } - else - { - incolor->vidtime += incolor->dispontime; - if (incolor->dispon) - incolor->stat &= ~1; - incolor->linepos = 0; - if (incolor->vsynctime) - { - incolor->vsynctime--; - if (!incolor->vsynctime) - { - incolor->stat &= ~8; - } - } - if (incolor->sc == (incolor->crtc[11] & 31) || ((incolor->crtc[8] & 3) == 3 && incolor->sc == ((incolor->crtc[11] & 31) >> 1))) - { - incolor->con = 0; - incolor->coff = 1; - } - if (incolor->vadj) - { - incolor->sc++; - incolor->sc &= 31; - incolor->ma = incolor->maback; - incolor->vadj--; - if (!incolor->vadj) - { - incolor->dispon = 1; - incolor->ma = incolor->maback = (incolor->crtc[13] | (incolor->crtc[12] << 8)) & 0x3fff; - incolor->sc = 0; - } - } - else if (incolor->sc == incolor->crtc[9] || ((incolor->crtc[8] & 3) == 3 && incolor->sc == (incolor->crtc[9] >> 1))) - { - incolor->maback = incolor->ma; - incolor->sc = 0; - oldvc = incolor->vc; - incolor->vc++; - incolor->vc &= 127; - if (incolor->vc == incolor->crtc[6]) - incolor->dispon = 0; - if (oldvc == incolor->crtc[4]) - { - incolor->vc = 0; - incolor->vadj = incolor->crtc[5]; - if (!incolor->vadj) incolor->dispon=1; - if (!incolor->vadj) incolor->ma = incolor->maback = (incolor->crtc[13] | (incolor->crtc[12] << 8)) & 0x3fff; - if ((incolor->crtc[10] & 0x60) == 0x20) incolor->cursoron = 0; - else incolor->cursoron = incolor->blink & 16; - } - if (incolor->vc == incolor->crtc[7]) - { - incolor->dispon = 0; - incolor->displine = 0; - incolor->vsynctime = 16; - if (incolor->crtc[7]) - { - if ((incolor->ctrl & INCOLOR_CTRL_GRAPH) && (incolor->ctrl2 & INCOLOR_CTRL2_GRAPH)) - { - x = incolor->crtc[1] << 4; - } - else - { - x = incolor->crtc[1] * 9; - } - incolor->lastline++; - if ((x != xsize) || ((incolor->lastline - incolor->firstline) != ysize) || video_force_resize_get()) - { - xsize = x; - ysize = incolor->lastline - incolor->firstline; - if (xsize < 64) xsize = 656; - if (ysize < 32) ysize = 200; - set_screen_size(xsize, ysize); + /* Graphics mode. */ + ca = (dev->sc & 3) * 0x2000; + if ((dev->ctrl & INCOLOR_CTRL_PAGE1) && (dev->ctrl2 & INCOLOR_CTRL2_PAGE1)) + ca += 0x8000; - if (video_force_resize_get()) - video_force_resize_set(0); - } - video_blit_memtoscreen(0, incolor->firstline, 0, incolor->lastline - incolor->firstline, xsize, incolor->lastline - incolor->firstline); - frames++; - if ((incolor->ctrl & INCOLOR_CTRL_GRAPH) && (incolor->ctrl2 & INCOLOR_CTRL2_GRAPH)) - { - video_res_x = incolor->crtc[1] * 16; - video_res_y = incolor->crtc[6] * 4; - video_bpp = 1; - } - else - { - video_res_x = incolor->crtc[1]; - video_res_y = incolor->crtc[6]; - video_bpp = 0; - } - } - incolor->firstline = 1000; - incolor->lastline = 0; - incolor->blink++; - } - } - else - { - incolor->sc++; - incolor->sc &= 31; - incolor->ma = incolor->maback; - } - if ((incolor->sc == (incolor->crtc[10] & 31) || ((incolor->crtc[8] & 3) == 3 && incolor->sc == ((incolor->crtc[10] & 31) >> 1)))) - { - incolor->con = 1; - } - } -} - -static void *incolor_init(const device_t *info) -{ - int c; - incolor_t *incolor = malloc(sizeof(incolor_t)); - memset(incolor, 0, sizeof(incolor_t)); - - incolor->vram = malloc(0x40000); /* 4 planes of 64k */ - - timer_add(incolor_poll, &incolor->vidtime, TIMER_ALWAYS_ENABLED, incolor); - mem_mapping_add(&incolor->mapping, 0xb0000, 0x08000, incolor_read, NULL, NULL, incolor_write, NULL, NULL, NULL, MEM_MAPPING_EXTERNAL, incolor); - io_sethandler(0x03b0, 0x0010, incolor_in, NULL, NULL, incolor_out, NULL, NULL, incolor); - - for (c = 0; c < 64; c++) + for (x = 0; x < dev->crtc[1]; x++) { + mask = dev->crtc[INCOLOR_CRTC_MASK]; /* Planes to display */ + for (plane = 0; plane < 4; plane++, mask = mask >> 1) { - incolor_rgb[c] = makecol32(init_rgb[c][0], init_rgb[c][1], init_rgb[c][2]); + if (mask & 1) + val[plane] = (dev->vram[((dev->ma << 1) & 0x1fff) + ca + 0x10000 * plane] << 8) | + dev->vram[((dev->ma << 1) & 0x1fff) + ca + 0x10000 * plane + 1]; + else val[plane] = 0; + } + dev->ma++; + + for (c = 0; c < 16; c++) + { + ink = 0; + for (plane = 0; plane < 4; plane++) + { + ink = ink >> 1; + if (val[plane] & 0x8000) ink |= 8; + val[plane] = val[plane] << 1; + } + /* Is palette in use? */ + if (dev->crtc[INCOLOR_CRTC_EXCEPT] & INCOLOR_EXCEPT_PALETTE) + col = dev->palette[ink]; + else col = defpal[ink]; + + ((uint32_t *)buffer32->line[dev->displine])[(x << 4) + c] = dev->rgb[col]; + } + } +} + + +static void +incolor_poll(void *priv) +{ + incolor_t *dev = (incolor_t *)priv; + uint16_t ca = (dev->crtc[15] | (dev->crtc[14] << 8)) & 0x3fff; + int x; + int oldvc; + int oldsc; + + if (! dev->linepos) { + dev->vidtime += dev->dispofftime; + dev->stat |= 1; + dev->linepos = 1; + oldsc = dev->sc; + if ((dev->crtc[8] & 3) == 3) + dev->sc = (dev->sc << 1) & 7; + + if (dev->dispon) { + if (dev->displine < dev->firstline) { + dev->firstline = dev->displine; + video_wait_for_buffer(); + } + dev->lastline = dev->displine; + if ((dev->ctrl & INCOLOR_CTRL_GRAPH) && (dev->ctrl2 & INCOLOR_CTRL2_GRAPH)) + graphics_line(dev); + else + text_line(dev, ca); + } + dev->sc = oldsc; + if (dev->vc == dev->crtc[7] && !dev->sc) + dev->stat |= 8; + dev->displine++; + if (dev->displine >= 500) + dev->displine = 0; + } else { + dev->vidtime += dev->dispontime; + if (dev->dispon) + dev->stat &= ~1; + dev->linepos = 0; + if (dev->vsynctime) { + dev->vsynctime--; + if (! dev->vsynctime) + dev->stat &= ~8; } -/* Initialise CRTC regs to safe values */ - incolor->crtc[INCOLOR_CRTC_MASK ] = 0x0F; /* All planes displayed */ - incolor->crtc[INCOLOR_CRTC_RWCTRL] = INCOLOR_RWCTRL_POLARITY; - incolor->crtc[INCOLOR_CRTC_RWCOL ] = 0x0F; /* White on black */ - incolor->crtc[INCOLOR_CRTC_EXCEPT] = INCOLOR_EXCEPT_ALTATTR; - for (c = 0; c < 16; c++) - { - incolor->palette[c] = defpal[c]; + if (dev->sc == (dev->crtc[11] & 31) || ((dev->crtc[8] & 3) == 3 && dev->sc == ((dev->crtc[11] & 31) >> 1))) { + dev->con = 0; + dev->coff = 1; } - incolor->palette_idx = 0; - /* Force the LPT3 port to be enabled. */ - parallel_enabled[2] = 1; - parallel_setup(3, 0x3BC); + if (dev->vadj) { + dev->sc++; + dev->sc &= 31; + dev->ma = dev->maback; + dev->vadj--; + if (! dev->vadj) { + dev->dispon = 1; + dev->ma = dev->maback = (dev->crtc[13] | (dev->crtc[12] << 8)) & 0x3fff; + dev->sc = 0; + } + } else if (dev->sc == dev->crtc[9] || ((dev->crtc[8] & 3) == 3 && dev->sc == (dev->crtc[9] >> 1))) { + dev->maback = dev->ma; + dev->sc = 0; + oldvc = dev->vc; + dev->vc++; + dev->vc &= 127; + if (dev->vc == dev->crtc[6]) + dev->dispon = 0; + if (oldvc == dev->crtc[4]) { + dev->vc = 0; + dev->vadj = dev->crtc[5]; + if (!dev->vadj) dev->dispon=1; + if (!dev->vadj) dev->ma = dev->maback = (dev->crtc[13] | (dev->crtc[12] << 8)) & 0x3fff; + if ((dev->crtc[10] & 0x60) == 0x20) dev->cursoron = 0; + else dev->cursoron = dev->blink & 16; + } - return incolor; + if (dev->vc == dev->crtc[7]) { + dev->dispon = 0; + dev->displine = 0; + dev->vsynctime = 16; + if (dev->crtc[7]) { + if ((dev->ctrl & INCOLOR_CTRL_GRAPH) && (dev->ctrl2 & INCOLOR_CTRL2_GRAPH)) + x = dev->crtc[1] << 4; + else + x = dev->crtc[1] * 9; + dev->lastline++; + if ((x != xsize) || ((dev->lastline - dev->firstline) != ysize) || video_force_resize_get()) { + xsize = x; + ysize = dev->lastline - dev->firstline; + if (xsize < 64) xsize = 656; + if (ysize < 32) ysize = 200; + set_screen_size(xsize, ysize); + + if (video_force_resize_get()) + video_force_resize_set(0); + } + video_blit_memtoscreen(0, dev->firstline, 0, dev->lastline - dev->firstline, xsize, dev->lastline - dev->firstline); + frames++; + if ((dev->ctrl & INCOLOR_CTRL_GRAPH) && (dev->ctrl2 & INCOLOR_CTRL2_GRAPH)) { + video_res_x = dev->crtc[1] * 16; + video_res_y = dev->crtc[6] * 4; + video_bpp = 1; + } else { + video_res_x = dev->crtc[1]; + video_res_y = dev->crtc[6]; + video_bpp = 0; + } + } + dev->firstline = 1000; + dev->lastline = 0; + dev->blink++; + } + } else { + dev->sc++; + dev->sc &= 31; + dev->ma = dev->maback; + } + + if ((dev->sc == (dev->crtc[10] & 31) || ((dev->crtc[8] & 3) == 3 && dev->sc == ((dev->crtc[10] & 31) >> 1)))) + dev->con = 1; + } } -static void incolor_close(void *p) + +static void * +incolor_init(const device_t *info) { - incolor_t *incolor = (incolor_t *)p; + incolor_t *dev; + int c; - free(incolor->vram); - free(incolor); + dev = (incolor_t *)mem_alloc(sizeof(incolor_t)); + memset(dev, 0x00, sizeof(incolor_t)); + + dev->vram = (uint8_t *)mem_alloc(0x40000); /* 4 planes of 64k */ + + timer_add(incolor_poll, &dev->vidtime, TIMER_ALWAYS_ENABLED, dev); + + mem_map_add(&dev->mapping, 0xb0000, 0x08000, + incolor_read,NULL,NULL, incolor_write,NULL,NULL, + NULL, MEM_MAPPING_EXTERNAL, dev); + + io_sethandler(0x03b0, 16, + incolor_in,NULL,NULL, incolor_out,NULL,NULL, dev); + + for (c = 0; c < 64; c++) { + dev->rgb[c] = makecol32(init_rgb[c][0], init_rgb[c][1], init_rgb[c][2]); + } + + /* Initialise CRTC regs to safe values */ + dev->crtc[INCOLOR_CRTC_MASK ] = 0x0F; /* All planes displayed */ + dev->crtc[INCOLOR_CRTC_RWCTRL] = INCOLOR_RWCTRL_POLARITY; + dev->crtc[INCOLOR_CRTC_RWCOL ] = 0x0F; /* White on black */ + dev->crtc[INCOLOR_CRTC_EXCEPT] = INCOLOR_EXCEPT_ALTATTR; + for (c = 0; c < 16; c++) + dev->palette[c] = defpal[c]; + dev->palette_idx = 0; + + video_inform(VID_TYPE_MDA, info->vid_timing); + + /* Force the LPT3 port to be enabled. */ + parallel_enabled[2] = 1; + parallel_setup(3, 0x3BC); + + return dev; } -static void incolor_speed_changed(void *p) + +static void +incolor_close(void *priv) { - incolor_t *incolor = (incolor_t *)p; - - incolor_recalctimings(incolor); + incolor_t *dev = (incolor_t *)priv; + + free(dev->vram); + free(dev); } + +static void +speed_changed(void *priv) +{ + incolor_t *dev = (incolor_t *)priv; + + recalc_timings(dev); +} + + +static const video_timings_t incolor_timings = { VID_ISA,8,16,32,8,16,32 }; + const device_t incolor_device = { "Hercules InColor", DEVICE_ISA, 0, incolor_init, incolor_close, NULL, NULL, - incolor_speed_changed, - NULL, NULL, + speed_changed, + NULL, + &incolor_timings, NULL }; diff --git a/src/devices/video/vid_mda.c b/src/devices/video/vid_mda.c index 0098e8e..20336c1 100644 --- a/src/devices/video/vid_mda.c +++ b/src/devices/video/vid_mda.c @@ -8,7 +8,7 @@ * * MDA emulation. * - * Version: @(#)vid_mda.c 1.0.7 2018/05/06 + * Version: @(#)vid_mda.c 1.0.8 2018/09/22 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -52,352 +52,393 @@ #include "video.h" -typedef struct mda_t -{ - mem_mapping_t mapping; - - uint8_t crtc[32]; - int crtcreg; - - uint8_t ctrl, stat; - - int64_t dispontime, dispofftime; - int64_t vidtime; - - int firstline, lastline; +typedef struct { + mem_map_t mapping; - int linepos, displine; - int vc, sc; - uint16_t ma, maback; - int con, coff, cursoron; - int dispon, blink; - int64_t vsynctime; - int vadj; + uint8_t crtc[32]; + int crtcreg; - uint8_t *vram; + uint8_t ctrl, stat; + + int64_t dispontime, dispofftime; + int64_t vidtime; + + int firstline, lastline; + + int linepos, displine; + int vc, sc; + uint16_t ma, maback; + int con, coff, cursoron; + int dispon, blink; + int64_t vsynctime; + int vadj; + + int cols[256][2][2]; + + uint8_t *vram; } mda_t; -static int mdacols[256][2][2]; - - -static void mda_recalctimings(mda_t *mda); - - -static void mda_out(uint16_t addr, uint8_t val, void *p) +static void +recalc_timings(mda_t *dev) { - mda_t *mda = (mda_t *)p; - switch (addr) - { - case 0x3b0: case 0x3b2: case 0x3b4: case 0x3b6: - mda->crtcreg = val & 31; - return; - case 0x3b1: case 0x3b3: case 0x3b5: case 0x3b7: - mda->crtc[mda->crtcreg] = val; - if (mda->crtc[10] == 6 && mda->crtc[11] == 7) /*Fix for Generic Turbo XT BIOS, which sets up cursor registers wrong*/ - { - mda->crtc[10] = 0xb; - mda->crtc[11] = 0xc; - } - mda_recalctimings(mda); - return; - case 0x3b8: - mda->ctrl = val; - return; - } -} + double _dispontime, _dispofftime, disptime; -static uint8_t mda_in(uint16_t addr, void *p) -{ - mda_t *mda = (mda_t *)p; - switch (addr) - { - case 0x3b0: case 0x3b2: case 0x3b4: case 0x3b6: - return mda->crtcreg; - case 0x3b1: case 0x3b3: case 0x3b5: case 0x3b7: - return mda->crtc[mda->crtcreg]; - case 0x3ba: - return mda->stat | 0xF0; - } - return 0xff; -} + disptime = dev->crtc[0] + 1; + _dispontime = dev->crtc[1]; + _dispofftime = disptime - _dispontime; + _dispontime *= MDACONST; + _dispofftime *= MDACONST; -static void mda_write(uint32_t addr, uint8_t val, void *p) -{ - mda_t *mda = (mda_t *)p; - egawrites++; - mda->vram[addr & 0xfff] = val; -} - -static uint8_t mda_read(uint32_t addr, void *p) -{ - mda_t *mda = (mda_t *)p; - egareads++; - return mda->vram[addr & 0xfff]; -} - -static void mda_recalctimings(mda_t *mda) -{ - double _dispontime, _dispofftime, disptime; - disptime = mda->crtc[0] + 1; - _dispontime = mda->crtc[1]; - _dispofftime = disptime - _dispontime; - _dispontime *= MDACONST; - _dispofftime *= MDACONST; - mda->dispontime = (int64_t)(_dispontime * (1 << TIMER_SHIFT)); - mda->dispofftime = (int64_t)(_dispofftime * (1 << TIMER_SHIFT)); -} - -static void mda_poll(void *p) -{ - mda_t *mda = (mda_t *)p; - uint16_t ca = (mda->crtc[15] | (mda->crtc[14] << 8)) & 0x3fff; - int drawcursor; - int x, c; - int oldvc; - uint8_t chr, attr; - int oldsc; - int blink; - if (!mda->linepos) - { - mda->vidtime += mda->dispofftime; - mda->stat |= 1; - mda->linepos = 1; - oldsc = mda->sc; - if ((mda->crtc[8] & 3) == 3) - mda->sc = (mda->sc << 1) & 7; - if (mda->dispon) - { - if (mda->displine < mda->firstline) - { - mda->firstline = mda->displine; - } - mda->lastline = mda->displine; - for (x = 0; x < mda->crtc[1]; x++) - { - chr = mda->vram[(mda->ma << 1) & 0xfff]; - attr = mda->vram[((mda->ma << 1) + 1) & 0xfff]; - drawcursor = ((mda->ma == ca) && mda->con && mda->cursoron); - blink = ((mda->blink & 16) && (mda->ctrl & 0x20) && (attr & 0x80) && !drawcursor); - if (mda->sc == 12 && ((attr & 7) == 1)) - { - for (c = 0; c < 9; c++) - buffer->line[mda->displine][(x * 9) + c] = mdacols[attr][blink][1]; - } - else - { - for (c = 0; c < 8; c++) - buffer->line[mda->displine][(x * 9) + c] = mdacols[attr][blink][(fontdatm[chr][mda->sc] & (1 << (c ^ 7))) ? 1 : 0]; - if ((chr & ~0x1f) == 0xc0) buffer->line[mda->displine][(x * 9) + 8] = mdacols[attr][blink][fontdatm[chr][mda->sc] & 1]; - else buffer->line[mda->displine][(x * 9) + 8] = mdacols[attr][blink][0]; - } - mda->ma++; - if (drawcursor) - { - for (c = 0; c < 9; c++) - buffer->line[mda->displine][(x * 9) + c] ^= mdacols[attr][0][1]; - } - } - } - mda->sc = oldsc; - if (mda->vc == mda->crtc[7] && !mda->sc) - { - mda->stat |= 8; - } - mda->displine++; - if (mda->displine >= 500) - mda->displine=0; - } - else - { - mda->vidtime += mda->dispontime; - if (mda->dispon) mda->stat&=~1; - mda->linepos=0; - if (mda->vsynctime) - { - mda->vsynctime--; - if (!mda->vsynctime) - { - mda->stat&=~8; - } - } - if (mda->sc == (mda->crtc[11] & 31) || ((mda->crtc[8] & 3) == 3 && mda->sc == ((mda->crtc[11] & 31) >> 1))) - { - mda->con = 0; - mda->coff = 1; - } - if (mda->vadj) - { - mda->sc++; - mda->sc &= 31; - mda->ma = mda->maback; - mda->vadj--; - if (!mda->vadj) - { - mda->dispon = 1; - mda->ma = mda->maback = (mda->crtc[13] | (mda->crtc[12] << 8)) & 0x3fff; - mda->sc = 0; - } - } - else if (mda->sc == mda->crtc[9] || ((mda->crtc[8] & 3) == 3 && mda->sc == (mda->crtc[9] >> 1))) - { - mda->maback = mda->ma; - mda->sc = 0; - oldvc = mda->vc; - mda->vc++; - mda->vc &= 127; - if (mda->vc == mda->crtc[6]) - mda->dispon=0; - if (oldvc == mda->crtc[4]) - { - mda->vc = 0; - mda->vadj = mda->crtc[5]; - if (!mda->vadj) mda->dispon = 1; - if (!mda->vadj) mda->ma = mda->maback = (mda->crtc[13] | (mda->crtc[12] << 8)) & 0x3fff; - if ((mda->crtc[10] & 0x60) == 0x20) mda->cursoron = 0; - else mda->cursoron = mda->blink & 16; - } - if (mda->vc == mda->crtc[7]) - { - mda->dispon = 0; - mda->displine = 0; - mda->vsynctime = 16; - if (mda->crtc[7]) - { - x = mda->crtc[1] * 9; - mda->lastline++; - if ((x != xsize) || ((mda->lastline - mda->firstline) != ysize) || video_force_resize_get()) - { - xsize = x; - ysize = mda->lastline - mda->firstline; - if (xsize < 64) xsize = 656; - if (ysize < 32) ysize = 200; - set_screen_size(xsize, ysize); - - if (video_force_resize_get()) - video_force_resize_set(0); - } - video_blit_memtoscreen_8(0, mda->firstline, 0, ysize, xsize, ysize); - frames++; - video_res_x = mda->crtc[1]; - video_res_y = mda->crtc[6]; - video_bpp = 0; - } - mda->firstline = 1000; - mda->lastline = 0; - mda->blink++; - } - } - else - { - mda->sc++; - mda->sc &= 31; - mda->ma = mda->maback; - } - if ((mda->sc == (mda->crtc[10] & 31) || ((mda->crtc[8] & 3) == 3 && mda->sc == ((mda->crtc[10] & 31) >> 1)))) - { - mda->con = 1; - } - } + dev->dispontime = (int64_t)(_dispontime * (1 << TIMER_SHIFT)); + dev->dispofftime = (int64_t)(_dispofftime * (1 << TIMER_SHIFT)); } -static void *mda_init(const device_t *info) +static void +mda_out(uint16_t port, uint8_t val, void *priv) { - int c; - mda_t *mda = malloc(sizeof(mda_t)); - memset(mda, 0, sizeof(mda_t)); + mda_t *dev = (mda_t *)priv; - mda->vram = malloc(0x1000); + switch (port) { + case 0x3b0: + case 0x3b2: + case 0x3b4: + case 0x3b6: + dev->crtcreg = val & 31; + break; - timer_add(mda_poll, &mda->vidtime, TIMER_ALWAYS_ENABLED, mda); - mem_mapping_add(&mda->mapping, 0xb0000, 0x08000, mda_read, NULL, NULL, mda_write, NULL, NULL, NULL, MEM_MAPPING_EXTERNAL, mda); - io_sethandler(0x03b0, 0x0010, mda_in, NULL, NULL, mda_out, NULL, NULL, mda); + case 0x3b1: + case 0x3b3: + case 0x3b5: + case 0x3b7: + dev->crtc[dev->crtcreg] = val; + if (dev->crtc[10] == 6 && dev->crtc[11] == 7) { + /*Fix for Generic Turbo XT BIOS, + * which sets up cursor registers wrong*/ + dev->crtc[10] = 0xb; + dev->crtc[11] = 0xc; + } + recalc_timings(dev); + break; - for (c = 0; c < 256; c++) - { - mdacols[c][0][0] = mdacols[c][1][0] = mdacols[c][1][1] = 16; - if (c & 8) mdacols[c][0][1] = 15 + 16; - else mdacols[c][0][1] = 7 + 16; - } - mdacols[0x70][0][1] = 16; - mdacols[0x70][0][0] = mdacols[0x70][1][0] = mdacols[0x70][1][1] = 16 + 15; - mdacols[0xF0][0][1] = 16; - mdacols[0xF0][0][0] = mdacols[0xF0][1][0] = mdacols[0xF0][1][1] = 16 + 15; - mdacols[0x78][0][1] = 16 + 7; - mdacols[0x78][0][0] = mdacols[0x78][1][0] = mdacols[0x78][1][1] = 16 + 15; - mdacols[0xF8][0][1] = 16 + 7; - mdacols[0xF8][0][0] = mdacols[0xF8][1][0] = mdacols[0xF8][1][1] = 16 + 15; - mdacols[0x00][0][1] = mdacols[0x00][1][1] = 16; - mdacols[0x08][0][1] = mdacols[0x08][1][1] = 16; - mdacols[0x80][0][1] = mdacols[0x80][1][1] = 16; - mdacols[0x88][0][1] = mdacols[0x88][1][1] = 16; + case 0x3b8: + dev->ctrl = val; + break; + } +} - overscan_x = overscan_y = 0; - cga_palette = device_get_config_int("rgb_type") << 1; - if (cga_palette > 6) - { - cga_palette = 0; +static uint8_t +mda_in(uint16_t port, void *priv) +{ + mda_t *dev = (mda_t *)priv; + uint8_t ret = 0xff; + + switch (port) { + case 0x3b0: + case 0x3b2: + case 0x3b4: + case 0x3b6: + ret = dev->crtcreg; + break; + + case 0x3b1: + case 0x3b3: + case 0x3b5: + case 0x3b7: + ret = dev->crtc[dev->crtcreg]; + break; + + case 0x3ba: + ret = dev->stat | 0xF0; + break; + + default: + break; + } + + return ret; +} + + +static void +mda_write(uint32_t addr, uint8_t val, void *priv) +{ + mda_t *dev = (mda_t *)priv; + + dev->vram[addr & 0xfff] = val; +} + + +static uint8_t +mda_read(uint32_t addr, void *priv) +{ + mda_t *dev = (mda_t *)priv; + + return dev->vram[addr & 0xfff]; +} + + +static void +mda_poll(void *priv) +{ + mda_t *dev = (mda_t *)priv; + uint16_t ca = (dev->crtc[15] | (dev->crtc[14] << 8)) & 0x3fff; + int drawcursor; + int x, c; + int oldvc; + uint8_t chr, attr; + int oldsc; + int blink; + + if (! dev->linepos) { + dev->vidtime += dev->dispofftime; + dev->stat |= 1; + dev->linepos = 1; + oldsc = dev->sc; + + if ((dev->crtc[8] & 3) == 3) + dev->sc = (dev->sc << 1) & 7; + + if (dev->dispon) { + if (dev->displine < dev->firstline) + dev->firstline = dev->displine; + dev->lastline = dev->displine; + + for (x = 0; x < dev->crtc[1]; x++) { + chr = dev->vram[(dev->ma << 1) & 0xfff]; + attr = dev->vram[((dev->ma << 1) + 1) & 0xfff]; + drawcursor = ((dev->ma == ca) && dev->con && dev->cursoron); + blink = ((dev->blink & 16) && (dev->ctrl & 0x20) && (attr & 0x80) && !drawcursor); + if (dev->sc == 12 && ((attr & 7) == 1)) { + for (c = 0; c < 9; c++) + buffer->line[dev->displine][(x * 9) + c] = dev->cols[attr][blink][1]; + } else { + for (c = 0; c < 8; c++) + buffer->line[dev->displine][(x * 9) + c] = dev->cols[attr][blink][(fontdatm[chr][dev->sc] & (1 << (c ^ 7))) ? 1 : 0]; + if ((chr & ~0x1f) == 0xc0) + buffer->line[dev->displine][(x * 9) + 8] = dev->cols[attr][blink][fontdatm[chr][dev->sc] & 1]; + else + buffer->line[dev->displine][(x * 9) + 8] = dev->cols[attr][blink][0]; + } + dev->ma++; + + if (drawcursor) { + for (c = 0; c < 9; c++) + buffer->line[dev->displine][(x * 9) + c] ^= dev->cols[attr][0][1]; + } + } } - cgapal_rebuild(); + dev->sc = oldsc; - /* Force the LPT3 port to be enabled. */ - parallel_enabled[2] = 1; - parallel_setup(3, 0x3BC); + if (dev->vc == dev->crtc[7] && !dev->sc) + dev->stat |= 8; + dev->displine++; + if (dev->displine >= 500) + dev->displine=0; + } else { + dev->vidtime += dev->dispontime; + if (dev->dispon) + dev->stat &= ~1; + dev->linepos = 0; - return mda; + if (dev->vsynctime) { + dev->vsynctime--; + if (! dev->vsynctime) + dev->stat &= ~8; + } + + if (dev->sc == (dev->crtc[11] & 31) || ((dev->crtc[8] & 3) == 3 && dev->sc == ((dev->crtc[11] & 31) >> 1))) { + dev->con = 0; + dev->coff = 1; + } + + if (dev->vadj) { + dev->sc++; + dev->sc &= 31; + dev->ma = dev->maback; + dev->vadj--; + if (! dev->vadj) { + dev->dispon = 1; + dev->ma = dev->maback = (dev->crtc[13] | (dev->crtc[12] << 8)) & 0x3fff; + dev->sc = 0; + } + } else if (dev->sc == dev->crtc[9] || ((dev->crtc[8] & 3) == 3 && dev->sc == (dev->crtc[9] >> 1))) { + dev->maback = dev->ma; + dev->sc = 0; + oldvc = dev->vc; + dev->vc++; + dev->vc &= 127; + if (dev->vc == dev->crtc[6]) + dev->dispon = 0; + if (oldvc == dev->crtc[4]) { + dev->vc = 0; + dev->vadj = dev->crtc[5]; + if (!dev->vadj) dev->dispon = 1; + if (!dev->vadj) dev->ma = dev->maback = (dev->crtc[13] | (dev->crtc[12] << 8)) & 0x3fff; + if ((dev->crtc[10] & 0x60) == 0x20) + dev->cursoron = 0; + else + dev->cursoron = dev->blink & 16; + } + + if (dev->vc == dev->crtc[7]) { + dev->dispon = 0; + dev->displine = 0; + dev->vsynctime = 16; + if (dev->crtc[7]) { + x = dev->crtc[1] * 9; + dev->lastline++; + if ((x != xsize) || ((dev->lastline - dev->firstline) != ysize) || video_force_resize_get()) { + xsize = x; + ysize = dev->lastline - dev->firstline; + if (xsize < 64) xsize = 656; + if (ysize < 32) ysize = 200; + set_screen_size(xsize, ysize); + + if (video_force_resize_get()) + video_force_resize_set(0); + } + video_blit_memtoscreen_8(0, dev->firstline, 0, ysize, xsize, ysize); + frames++; + video_res_x = dev->crtc[1]; + video_res_y = dev->crtc[6]; + video_bpp = 0; + } + dev->firstline = 1000; + dev->lastline = 0; + dev->blink++; + } + } else { + dev->sc++; + dev->sc &= 31; + dev->ma = dev->maback; + } + + if ((dev->sc == (dev->crtc[10] & 31) || ((dev->crtc[8] & 3) == 3 && dev->sc == ((dev->crtc[10] & 31) >> 1)))) { + dev->con = 1; + } + } } -static void mda_close(void *p) -{ - mda_t *mda = (mda_t *)p; - free(mda->vram); - free(mda); +static void * +mda_init(const device_t *info) +{ + mda_t *dev; + int c; + + dev = (mda_t *)mem_alloc(sizeof(mda_t)); + memset(dev, 0x00, sizeof(mda_t)); + + dev->vram = (uint8_t *)mem_alloc(0x1000); + + timer_add(mda_poll, &dev->vidtime, TIMER_ALWAYS_ENABLED, dev); + + mem_map_add(&dev->mapping, 0xb0000, 0x08000, + mda_read,NULL,NULL, mda_write,NULL,NULL, + NULL, MEM_MAPPING_EXTERNAL, dev); + + io_sethandler(0x03b0, 16, + mda_in,NULL,NULL, mda_out,NULL,NULL, dev); + + for (c = 0; c < 256; c++) { + dev->cols[c][0][0] = dev->cols[c][1][0] = dev->cols[c][1][1] = 16; + if (c & 8) + dev->cols[c][0][1] = 15 + 16; + else + dev->cols[c][0][1] = 7 + 16; + } + dev->cols[0x70][0][1] = 16; + dev->cols[0x70][0][0] = dev->cols[0x70][1][0] = + dev->cols[0x70][1][1] = 16 + 15; + dev->cols[0xF0][0][1] = 16; + dev->cols[0xF0][0][0] = dev->cols[0xF0][1][0] = + dev->cols[0xF0][1][1] = 16 + 15; + dev->cols[0x78][0][1] = 16 + 7; + dev->cols[0x78][0][0] = dev->cols[0x78][1][0] = + dev->cols[0x78][1][1] = 16 + 15; + dev->cols[0xF8][0][1] = 16 + 7; + dev->cols[0xF8][0][0] = dev->cols[0xF8][1][0] = + dev->cols[0xF8][1][1] = 16 + 15; + dev->cols[0x00][0][1] = dev->cols[0x00][1][1] = 16; + dev->cols[0x08][0][1] = dev->cols[0x08][1][1] = 16; + dev->cols[0x80][0][1] = dev->cols[0x80][1][1] = 16; + dev->cols[0x88][0][1] = dev->cols[0x88][1][1] = 16; + + overscan_x = overscan_y = 0; + + cga_palette = device_get_config_int("rgb_type") << 1; + if (cga_palette > 6) + cga_palette = 0; + cgapal_rebuild(); + + video_inform(VID_TYPE_MDA, info->vid_timing); + + /* Force the LPT3 port to be enabled. */ + parallel_enabled[2] = 1; + parallel_setup(3, 0x3BC); + + return dev; } -static void mda_speed_changed(void *p) + +static void +mda_close(void *priv) { - mda_t *mda = (mda_t *)p; - - mda_recalctimings(mda); + mda_t *dev = (mda_t *)priv; + + free(dev->vram); + free(dev); } -static const device_config_t mda_config[] = + +static void +speed_changed(void *priv) { - { - "rgb_type", "Display type", CONFIG_SELECTION, "", 0, - { - { - "Default", 0 - }, - { - "Green", 1 - }, - { - "Amber", 2 - }, - { - "Gray", 3 - }, - { - "" - } - } - }, - { - "", "", -1 - } + mda_t *dev = (mda_t *)priv; + + recalc_timings(dev); +} + + +static const device_config_t mda_config[] = { + { + "rgb_type", "Display type", CONFIG_SELECTION, "", 0, + { + { + "Default", 0 + }, + { + "Green", 1 + }, + { + "Amber", 2 + }, + { + "Gray", 3 + }, + { + "" + } + } + }, + { + "", "", -1 + } }; +static const video_timings_t mda_timings = { VID_ISA,8,16,32,8,16,32 }; const device_t mda_device = { "MDA", - DEVICE_ISA, 0, + DEVICE_ISA, + 0, mda_init, mda_close, NULL, NULL, - mda_speed_changed, - NULL, NULL, + speed_changed, + NULL, + &mda_timings, mda_config }; diff --git a/src/devices/video/vid_oak_oti.c b/src/devices/video/vid_oak_oti.c index 0436fde..da68b78 100644 --- a/src/devices/video/vid_oak_oti.c +++ b/src/devices/video/vid_oak_oti.c @@ -8,7 +8,7 @@ * * Oak OTI037C/67/077 emulation. * - * Version: @(#)vid_oak_oti.c 1.0.10 2018/05/06 + * Version: @(#)vid_oak_oti.c 1.0.11 2018/10/05 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -50,54 +50,52 @@ #include "vid_svga.h" -#define BIOS_37C_PATH L"video/oti/oti037c/bios.bin" -//#define BIOS_67_PATH L"video/oti/oti067.bin" -#define BIOS_77_PATH L"video/oti/oti077.vbi" +#define BIOS_37C_PATH L"video/oti/oti037c/bios.bin" +//#define BIOS_67_PATH L"video/oti/oti067.bin" +#define BIOS_77_PATH L"video/oti/oti077.vbi" typedef struct { - svga_t svga; + uint8_t chip_id; + uint8_t enable_register; + uint8_t pos; + uint8_t indx; - rom_t bios_rom; + uint32_t vram_size; + uint32_t vram_mask; - int index; - uint8_t regs[32]; + rom_t bios_rom; - uint8_t pos; + uint8_t regs[32]; - uint8_t enable_register; - - uint32_t vram_size; - uint32_t vram_mask; - - uint8_t chip_id; + svga_t svga; } oti_t; static void -oti_out(uint16_t addr, uint8_t val, void *p) +oti_out(uint16_t addr, uint8_t val, void *priv) { - oti_t *oti = (oti_t *)p; - svga_t *svga = &oti->svga; - uint8_t old; - uint8_t idx; + oti_t *dev = (oti_t *)priv; + svga_t *svga = &dev->svga; + uint8_t old, idx; - if (!(oti->enable_register & 1) && addr != 0x3C3) - return; + if (!(dev->enable_register & 1) && addr != 0x03c3) return; - if ((((addr&0xFFF0) == 0x3D0 || (addr&0xFFF0) == 0x3B0) && addr < 0x3de) && + if ((((addr&0xfff0) == 0x03d0 || (addr&0xfff0) == 0x03b0) && addr < 0x3de) && !(svga->miscout & 1)) addr ^= 0x60; switch (addr) { - case 0x3C3: - oti->enable_register = val & 1; + case 0x03c3: + dev->enable_register = val & 1; return; - case 0x3D4: + case 0x03d4: svga->crtcreg = val; return; - case 0x3D5: + case 0x03d5: + if (svga->crtcreg & 0x20) + return; if (((svga->crtcreg & 31) < 7) && (svga->crtc[0x11] & 0x80)) return; if (((svga->crtcreg & 31) == 7) && (svga->crtc[0x11] & 0x80)) @@ -105,38 +103,35 @@ oti_out(uint16_t addr, uint8_t val, void *p) old = svga->crtc[svga->crtcreg & 31]; svga->crtc[svga->crtcreg & 31] = val; if (old != val) { - if ((svga->crtcreg & 31) < 0xE || (svga->crtcreg & 31) > 0x10) { + if ((svga->crtcreg & 31) < 0x0e || (svga->crtcreg & 31) > 0x10) { svga->fullchange = changeframecount; svga_recalctimings(svga); } } break; - case 0x3DE: - oti->index = val; + case 0x03de: + dev->indx = val; return; - case 0x3DF: - idx = oti->index & 0x1f; - oti->regs[idx] = val; + case 0x03df: + idx = dev->indx & 0x1f; + dev->regs[idx] = val; switch (idx) { - case 0xD: - if (oti->chip_id) - { - svga->vram_display_mask = (val & 0xc) ? oti->vram_mask : 0x3ffff; - if ((val & 0x80) && oti->vram_size == 256) - mem_mapping_disable(&svga->mapping); + case 0x0d: + if (dev->chip_id) { + svga->vram_display_mask = (val & 0xc) ? dev->vram_mask : 0x3ffff; + if ((val & 0x80) && dev->vram_size == 256) + mem_map_disable(&svga->mapping); else - mem_mapping_enable(&svga->mapping); + mem_map_enable(&svga->mapping); if (!(val & 0x80)) svga->vram_display_mask = 0x3ffff; - } - else - { + } else { if (val & 0x80) - mem_mapping_disable(&svga->mapping); + mem_map_disable(&svga->mapping); else - mem_mapping_enable(&svga->mapping); + mem_map_enable(&svga->mapping); } break; @@ -153,209 +148,218 @@ oti_out(uint16_t addr, uint8_t val, void *p) static uint8_t -oti_in(uint16_t addr, void *p) +oti_in(uint16_t addr, void *priv) { - oti_t *oti = (oti_t *)p; - svga_t *svga = &oti->svga; - uint8_t temp; + oti_t *dev = (oti_t *)priv; + svga_t *svga = &dev->svga; + uint8_t ret = 0xff; - if (!(oti->enable_register & 1) && addr != 0x3C3) - return 0xff; + if (!(dev->enable_register & 1) && addr != 0x03c3) return ret; - if ((((addr&0xFFF0) == 0x3D0 || (addr&0xFFF0) == 0x3B0) && addr < 0x3de) && + if ((((addr&0xfff0) == 0x03d0 || (addr&0xfff0) == 0x03b0) && addr < 0x3de) && !(svga->miscout & 1)) addr ^= 0x60; switch (addr) { - case 0x3C3: - temp = oti->enable_register; + case 0x03c3: + ret = dev->enable_register; break; - case 0x3D4: - temp = svga->crtcreg; + case 0x03d4: + ret = svga->crtcreg; break; - case 0x3D5: - temp = svga->crtc[svga->crtcreg & 31]; + case 0x03d5: + if (svga->crtcreg & 0x20) + ret = 0xff; + else + ret = svga->crtc[svga->crtcreg & 31]; break; - case 0x3DA: + case 0x03da: svga->attrff = 0; svga->attrff = 0; svga->cgastat &= ~0x30; + /* copy color diagnostic info from the overscan color register */ - switch (svga->attrregs[0x12] & 0x30) - { + switch (svga->attrregs[0x12] & 0x30) { case 0x00: /* P0 and P2 */ - if (svga->attrregs[0x11] & 0x01) - svga->cgastat |= 0x10; - if (svga->attrregs[0x11] & 0x04) - svga->cgastat |= 0x20; - break; + if (svga->attrregs[0x11] & 0x01) + svga->cgastat |= 0x10; + if (svga->attrregs[0x11] & 0x04) + svga->cgastat |= 0x20; + break; + case 0x10: /* P4 and P5 */ - if (svga->attrregs[0x11] & 0x10) - svga->cgastat |= 0x10; - if (svga->attrregs[0x11] & 0x20) - svga->cgastat |= 0x20; - break; + if (svga->attrregs[0x11] & 0x10) + svga->cgastat |= 0x10; + if (svga->attrregs[0x11] & 0x20) + svga->cgastat |= 0x20; + break; + case 0x20: /* P1 and P3 */ - if (svga->attrregs[0x11] & 0x02) - svga->cgastat |= 0x10; - if (svga->attrregs[0x11] & 0x08) - svga->cgastat |= 0x20; - break; + if (svga->attrregs[0x11] & 0x02) + svga->cgastat |= 0x10; + if (svga->attrregs[0x11] & 0x08) + svga->cgastat |= 0x20; + break; + case 0x30: /* P6 and P7 */ - if (svga->attrregs[0x11] & 0x40) - svga->cgastat |= 0x10; - if (svga->attrregs[0x11] & 0x80) - svga->cgastat |= 0x20; - break; + if (svga->attrregs[0x11] & 0x40) + svga->cgastat |= 0x10; + if (svga->attrregs[0x11] & 0x80) + svga->cgastat |= 0x20; + break; } return svga->cgastat; - case 0x3DE: - temp = oti->index | (oti->chip_id << 5); + case 0x03de: + ret = dev->indx | (dev->chip_id << 5); break; - case 0x3DF: - if ((oti->index & 0x1f)==0x10) - temp = 0x18; + case 0x03df: + if ((dev->indx & 0x1f)==0x10) + ret = 0x18; else - temp = oti->regs[oti->index & 0x1f]; + ret = dev->regs[dev->indx & 0x1f]; break; default: - temp = svga_in(addr, svga); + ret = svga_in(addr, svga); break; } - return(temp); + return(ret); } static void -oti_pos_out(uint16_t addr, uint8_t val, void *p) +oti_pos_out(uint16_t addr, uint8_t val, void *priv) { - oti_t *oti = (oti_t *)p; + oti_t *dev = (oti_t *)priv; - if ((val & 8) != (oti->pos & 8)) { + if ((val & 8) != (dev->pos & 8)) { if (val & 8) - io_sethandler(0x03c0, 32, oti_in, NULL, NULL, - oti_out, NULL, NULL, oti); + io_sethandler(0x03c0, 32, + oti_in,NULL,NULL, oti_out,NULL,NULL, dev); else - io_removehandler(0x03c0, 32, oti_in, NULL, NULL, - oti_out, NULL, NULL, oti); + io_removehandler(0x03c0, 32, + oti_in,NULL,NULL, oti_out,NULL,NULL, dev); } - oti->pos = val; + dev->pos = val; } static uint8_t -oti_pos_in(uint16_t addr, void *p) +oti_pos_in(uint16_t addr, void *priv) { - oti_t *oti = (oti_t *)p; + oti_t *dev = (oti_t *)priv; - return(oti->pos); + return(dev->pos); } static void -oti_recalctimings(svga_t *svga) +recalc_timings(svga_t *svga) { - oti_t *oti = (oti_t *)svga->p; + oti_t *dev = (oti_t *)svga->p; - if (oti->regs[0x14] & 0x08) svga->ma_latch |= 0x10000; + if (dev->regs[0x14] & 0x08) svga->ma_latch |= 0x10000; - if (oti->regs[0x0d] & 0x0c) svga->rowoffset <<= 1; + if (dev->regs[0x0d] & 0x0c) svga->rowoffset <<= 1; - svga->interlace = oti->regs[0x14] & 0x80; + svga->interlace = dev->regs[0x14] & 0x80; +} + + +static void +speed_changed(void *priv) +{ + oti_t *dev = (oti_t *)priv; + + svga_recalctimings(&dev->svga); +} + + +static void +force_redraw(void *priv) +{ + oti_t *dev = (oti_t *)priv; + + dev->svga.fullchange = changeframecount; } static void * oti_init(const device_t *info) { - oti_t *oti = malloc(sizeof(oti_t)); - wchar_t *romfn = NULL; + oti_t *dev; + wchar_t *fn; - memset(oti, 0x00, sizeof(oti_t)); - oti->chip_id = info->local; + dev = (oti_t *)mem_alloc(sizeof(oti_t)); + memset(dev, 0x00, sizeof(oti_t)); + dev->chip_id = info->local; - switch(oti->chip_id) { + fn = NULL; + switch(dev->chip_id) { case 0: - romfn = BIOS_37C_PATH; + fn = BIOS_37C_PATH; break; case 2: #ifdef BIOS_67_PATH - romfn = BIOS_67_PATH; - break; + fn = BIOS_67_PATH; +#else + fn = BIOS_77_PATH; #endif + break; + + case 2+128: + /* Onboard OTI067; ROM set up by machine. */ + dev->chip_id = 2; + break; + case 5: - romfn = BIOS_77_PATH; + fn = BIOS_77_PATH; break; } - rom_init(&oti->bios_rom, romfn, - 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + if (fn != NULL) + rom_init(&dev->bios_rom, fn, + 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); - oti->vram_size = device_get_config_int("memory"); - oti->vram_mask = (oti->vram_size << 10) - 1; + dev->vram_size = device_get_config_int("memory"); + dev->vram_mask = (dev->vram_size << 10) - 1; - svga_init(&oti->svga, oti, oti->vram_size << 10, - oti_recalctimings, oti_in, oti_out, NULL, NULL); + svga_init(&dev->svga, dev, dev->vram_size << 10, + recalc_timings, oti_in, oti_out, NULL, NULL); io_sethandler(0x03c0, 32, - oti_in,NULL,NULL, oti_out,NULL,NULL, oti); + oti_in,NULL,NULL, oti_out,NULL,NULL, dev); io_sethandler(0x46e8, 1, - oti_pos_in,NULL,NULL, oti_pos_out,NULL,NULL, oti); + oti_pos_in,NULL,NULL, oti_pos_out,NULL,NULL, dev); - oti->svga.miscout = 1; + dev->svga.miscout = 1; - oti->regs[0] = 0x08; /* fixme: bios wants to read this at index 0? this index is undocumented */ + /* FIXME: BIOS wants to read this there (undocumented.)*/ + dev->regs[0] = 0x08; - return(oti); + return(dev); } static void -oti_close(void *p) +oti_close(void *priv) { - oti_t *oti = (oti_t *)p; + oti_t *dev = (oti_t *)priv; - svga_close(&oti->svga); + svga_close(&dev->svga); - free(oti); + free(dev); } -static void -oti_speed_changed(void *p) -{ - oti_t *oti = (oti_t *)p; - - svga_recalctimings(&oti->svga); -} - - -static void -oti_force_redraw(void *p) -{ - oti_t *oti = (oti_t *)p; - - oti->svga.fullchange = changeframecount; -} - - -static void -oti_add_status_info(char *s, int max_len, void *p) -{ - oti_t *oti = (oti_t *)p; - - svga_add_status_info(s, max_len, &oti->svga); -} - static int oti037c_available(void) { @@ -373,8 +377,7 @@ oti067_available(void) } -static const device_config_t oti067_config[] = -{ +static const device_config_t oti067_config[] = { { "memory", "Memory size", CONFIG_SELECTION, "", 512, { @@ -402,8 +405,7 @@ oti077_available(void) } -static const device_config_t oti077_config[] = -{ +static const device_config_t oti077_config[] = { { "memory", "Memory size", CONFIG_SELECTION, "", 1024, { @@ -426,41 +428,50 @@ static const device_config_t oti077_config[] = } }; -const device_t oti037c_device = -{ - "Oak OTI-037C", - DEVICE_ISA, - 0, - oti_init, oti_close, NULL, - oti037c_available, - oti_speed_changed, - oti_force_redraw, - oti_add_status_info, - oti067_config +const device_t oti037c_device = { + "Oak OTI-037C", + DEVICE_ISA, + 0, + oti_init, oti_close, NULL, + oti037c_available, + speed_changed, + force_redraw, + NULL, + oti067_config }; -const device_t oti067_device = -{ - "Oak OTI-067", - DEVICE_ISA, - 2, - oti_init, oti_close, NULL, - oti067_available, - oti_speed_changed, - oti_force_redraw, - oti_add_status_info, - oti067_config +const device_t oti067_device = { + "Oak OTI-067", + DEVICE_ISA, + 2, + oti_init, oti_close, NULL, + oti067_available, + speed_changed, + force_redraw, + NULL, + oti067_config }; -const device_t oti077_device = -{ - "Oak OTI-077", - DEVICE_ISA, - 5, - oti_init, oti_close, NULL, - oti077_available, - oti_speed_changed, - oti_force_redraw, - oti_add_status_info, - oti077_config +const device_t oti067_onboard_device = { + "Oak OTI-067 (onboard)", + DEVICE_ISA, + 2+128, + oti_init, oti_close, NULL, + NULL, + speed_changed, + force_redraw, + NULL, + oti067_config +}; + +const device_t oti077_device = { + "Oak OTI-077", + DEVICE_ISA, + 5, + oti_init, oti_close, NULL, + oti077_available, + speed_changed, + force_redraw, + NULL, + oti077_config }; diff --git a/src/devices/video/vid_paradise.c b/src/devices/video/vid_paradise.c index e4912f7..8592009 100644 --- a/src/devices/video/vid_paradise.c +++ b/src/devices/video/vid_paradise.c @@ -13,7 +13,7 @@ * NOTE: The MegaPC video device should be moved to the MegaPC * machine file. * - * Version: @(#)vid_paradise.c 1.0.6 2018/05/06 + * Version: @(#)vid_paradise.c 1.0.7 2018/09/22 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -56,18 +56,21 @@ #include "vid_svga_render.h" +enum type +{ + PVGA1A = 0, + WD90C11, + WD90C30 +}; + + typedef struct paradise_t { svga_t svga; rom_t bios_rom; - - enum - { - PVGA1A = 0, - WD90C11, - WD90C30 - } type; + + enum type type; uint32_t read_bank[4], write_bank[4]; } paradise_t; @@ -111,19 +114,19 @@ static void paradise_out(uint16_t addr, uint8_t val, void *p) switch (val&0xC) { case 0x0: /*128k at A0000*/ - mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x20000); + mem_map_set_addr(&svga->mapping, 0xa0000, 0x20000); svga->banked_mask = 0xffff; break; case 0x4: /*64k at A0000*/ - mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000); + mem_map_set_addr(&svga->mapping, 0xa0000, 0x10000); svga->banked_mask = 0xffff; break; case 0x8: /*32k at B0000*/ - mem_mapping_set_addr(&svga->mapping, 0xb0000, 0x08000); + mem_map_set_addr(&svga->mapping, 0xb0000, 0x08000); svga->banked_mask = 0x7fff; break; case 0xC: /*32k at B8000*/ - mem_mapping_set_addr(&svga->mapping, 0xb8000, 0x08000); + mem_map_set_addr(&svga->mapping, 0xb8000, 0x08000); svga->banked_mask = 0x7fff; break; } @@ -147,12 +150,11 @@ static void paradise_out(uint16_t addr, uint8_t val, void *p) break; case 0x3D4: - if (paradise->type == PVGA1A) - svga->crtcreg = val & 0x1f; - else - svga->crtcreg = val & 0x3f; + svga->crtcreg = val & 0x3f; return; case 0x3D5: + if ((paradise->type == PVGA1A) && (svga->crtcreg & 0x20)) + return; if ((svga->crtcreg < 7) && (svga->crtc[0x11] & 0x80)) return; if ((svga->crtcreg == 7) && (svga->crtc[0x11] & 0x80)) @@ -217,6 +219,8 @@ static uint8_t paradise_in(uint16_t addr, void *p) case 0x3D4: return svga->crtcreg; case 0x3D5: + if ((paradise->type == PVGA1A) && (svga->crtcreg & 0x20)) + return 0xff; if (svga->crtcreg > 0x29 && svga->crtcreg < 0x30 && (svga->crtc[0x29] & 0x88) != 0x80) return 0xff; return svga->crtc[svga->crtcreg]; @@ -304,7 +308,7 @@ static uint16_t paradise_readw(uint32_t addr, void *p) static void *paradise_pvga1a_init(const device_t *info, uint32_t memsize) { - paradise_t *paradise = malloc(sizeof(paradise_t)); + paradise_t *paradise = (paradise_t *)mem_alloc(sizeof(paradise_t)); svga_t *svga = ¶dise->svga; memset(paradise, 0, sizeof(paradise_t)); @@ -316,8 +320,8 @@ static void *paradise_pvga1a_init(const device_t *info, uint32_t memsize) NULL, NULL); - mem_mapping_set_handler(¶dise->svga.mapping, paradise_read, paradise_readw, NULL, paradise_write, paradise_writew, NULL); - mem_mapping_set_p(¶dise->svga.mapping, paradise); + mem_map_set_handler(¶dise->svga.mapping, paradise_read, paradise_readw, NULL, paradise_write, paradise_writew, NULL); + mem_map_set_p(¶dise->svga.mapping, paradise); svga->crtc[0x31] = 'W'; svga->crtc[0x32] = 'D'; @@ -328,8 +332,6 @@ static void *paradise_pvga1a_init(const device_t *info, uint32_t memsize) svga->bpp = 8; svga->miscout = 1; - svga->linear_base = 0; - paradise->type = PVGA1A; return paradise; @@ -337,7 +339,7 @@ static void *paradise_pvga1a_init(const device_t *info, uint32_t memsize) static void *paradise_wd90c11_init(const device_t *info) { - paradise_t *paradise = malloc(sizeof(paradise_t)); + paradise_t *paradise = (paradise_t *)mem_alloc(sizeof(paradise_t)); svga_t *svga = ¶dise->svga; memset(paradise, 0, sizeof(paradise_t)); @@ -349,8 +351,8 @@ static void *paradise_wd90c11_init(const device_t *info) NULL, NULL); - mem_mapping_set_handler(¶dise->svga.mapping, paradise_read, paradise_readw, NULL, paradise_write, paradise_writew, NULL); - mem_mapping_set_p(¶dise->svga.mapping, paradise); + mem_map_set_handler(¶dise->svga.mapping, paradise_read, paradise_readw, NULL, paradise_write, paradise_writew, NULL); + mem_map_set_p(¶dise->svga.mapping, paradise); svga->crtc[0x31] = 'W'; svga->crtc[0x32] = 'D'; @@ -363,8 +365,6 @@ static void *paradise_wd90c11_init(const device_t *info) svga->bpp = 8; svga->miscout = 1; - svga->linear_base = 0; - paradise->type = WD90C11; return paradise; @@ -372,7 +372,7 @@ static void *paradise_wd90c11_init(const device_t *info) static void *paradise_wd90c30_init(const device_t *info, uint32_t memsize) { - paradise_t *paradise = malloc(sizeof(paradise_t)); + paradise_t *paradise = (paradise_t *)mem_alloc(sizeof(paradise_t)); svga_t *svga = ¶dise->svga; memset(paradise, 0, sizeof(paradise_t)); @@ -384,8 +384,8 @@ static void *paradise_wd90c30_init(const device_t *info, uint32_t memsize) NULL, NULL); - mem_mapping_set_handler(¶dise->svga.mapping, paradise_read, paradise_readw, NULL, paradise_write, paradise_writew, NULL); - mem_mapping_set_p(¶dise->svga.mapping, paradise); + mem_map_set_handler(¶dise->svga.mapping, paradise_read, paradise_readw, NULL, paradise_write, paradise_writew, NULL); + mem_map_set_p(¶dise->svga.mapping, paradise); svga->crtc[0x31] = 'W'; svga->crtc[0x32] = 'D'; @@ -398,8 +398,6 @@ static void *paradise_wd90c30_init(const device_t *info, uint32_t memsize) svga->bpp = 8; svga->miscout = 1; - svga->linear_base = 0; - paradise->type = WD90C11; return paradise; @@ -407,7 +405,7 @@ static void *paradise_wd90c30_init(const device_t *info, uint32_t memsize) static void *paradise_pvga1a_pc2086_init(const device_t *info) { - paradise_t *paradise = paradise_pvga1a_init(info, 1 << 18); + paradise_t *paradise = (paradise_t *)paradise_pvga1a_init(info, 1 << 18); if (paradise) rom_init(¶dise->bios_rom, L"machines/pc2086/40186.ic171", 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); @@ -416,7 +414,7 @@ static void *paradise_pvga1a_pc2086_init(const device_t *info) } static void *paradise_pvga1a_pc3086_init(const device_t *info) { - paradise_t *paradise = paradise_pvga1a_init(info, 1 << 18); + paradise_t *paradise = (paradise_t *)paradise_pvga1a_init(info, 1 << 18); if (paradise) rom_init(¶dise->bios_rom, L"machines/pc3086/c000.bin", 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); @@ -432,7 +430,7 @@ static void *paradise_pvga1a_standalone_init(const device_t *info) memory = device_get_config_int("memory"); memory <<= 10; - paradise = paradise_pvga1a_init(info, memory); + paradise = (paradise_t *)paradise_pvga1a_init(info, memory); if (paradise) rom_init(¶dise->bios_rom, L"video/paradise/pvga1a/bios.bin", 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); @@ -447,7 +445,7 @@ static int paradise_pvga1a_standalone_available(void) static void *paradise_wd90c11_megapc_init(const device_t *info) { - paradise_t *paradise = paradise_wd90c11_init(info); + paradise_t *paradise = (paradise_t *)paradise_wd90c11_init(info); if (paradise) rom_init_interleaved(¶dise->bios_rom, @@ -460,7 +458,7 @@ static void *paradise_wd90c11_megapc_init(const device_t *info) static void *paradise_wd90c11_standalone_init(const device_t *info) { - paradise_t *paradise = paradise_wd90c11_init(info); + paradise_t *paradise = (paradise_t *)paradise_wd90c11_init(info); if (paradise) rom_init(¶dise->bios_rom, L"video/wd/wd90c11/wd90c11.vbi", 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); @@ -481,7 +479,7 @@ static void *paradise_wd90c30_standalone_init(const device_t *info) memory = device_get_config_int("memory"); memory <<= 10; - paradise = paradise_wd90c30_init(info, memory); + paradise = (paradise_t *)paradise_wd90c30_init(info, memory); if (paradise) rom_init(¶dise->bios_rom, L"video/wd/wd90c30/90c30-lr.vbi", 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); @@ -517,39 +515,30 @@ static void paradise_force_redraw(void *p) paradise->svga.fullchange = changeframecount; } -static void paradise_add_status_info(char *s, int max_len, void *p) -{ - paradise_t *paradise = (paradise_t *)p; - - svga_add_status_info(s, max_len, ¶dise->svga); -} - const device_t paradise_pvga1a_pc2086_device = { "Paradise PVGA1A (Amstrad PC2086)", 0, 0, - paradise_pvga1a_pc2086_init, - paradise_close, - NULL, + paradise_pvga1a_pc2086_init, paradise_close, NULL, NULL, paradise_speed_changed, paradise_force_redraw, - paradise_add_status_info + NULL, + NULL }; const device_t paradise_pvga1a_pc3086_device = { "Paradise PVGA1A (Amstrad PC3086)", 0, 0, - paradise_pvga1a_pc3086_init, - paradise_close, - NULL, + paradise_pvga1a_pc3086_init, paradise_close, NULL, NULL, paradise_speed_changed, paradise_force_redraw, - paradise_add_status_info + NULL, + NULL }; static const device_config_t paradise_pvga1a_config[] = @@ -581,13 +570,11 @@ const device_t paradise_pvga1a_device = "Paradise PVGA1A", DEVICE_ISA, 0, - paradise_pvga1a_standalone_init, - paradise_close, - NULL, + paradise_pvga1a_standalone_init, paradise_close, NULL, paradise_pvga1a_standalone_available, paradise_speed_changed, paradise_force_redraw, - paradise_add_status_info, + NULL, paradise_pvga1a_config }; const device_t paradise_wd90c11_megapc_device = @@ -595,26 +582,24 @@ const device_t paradise_wd90c11_megapc_device = "Paradise WD90C11 (Amstrad MegaPC)", 0, 0, - paradise_wd90c11_megapc_init, - paradise_close, - NULL, + paradise_wd90c11_megapc_init, paradise_close, NULL, NULL, paradise_speed_changed, paradise_force_redraw, - paradise_add_status_info + NULL, + NULL }; const device_t paradise_wd90c11_device = { "Paradise WD90C11-LR", DEVICE_ISA, 0, - paradise_wd90c11_standalone_init, - paradise_close, - NULL, + paradise_wd90c11_standalone_init, paradise_close, NULL, paradise_wd90c11_standalone_available, paradise_speed_changed, paradise_force_redraw, - paradise_add_status_info + NULL, + NULL }; static const device_config_t paradise_wd90c30_config[] = @@ -643,12 +628,10 @@ const device_t paradise_wd90c30_device = "Paradise WD90C30-LR", DEVICE_ISA, 0, - paradise_wd90c30_standalone_init, - paradise_close, - NULL, + paradise_wd90c30_standalone_init, paradise_close, NULL, paradise_wd90c30_standalone_available, paradise_speed_changed, paradise_force_redraw, - paradise_add_status_info, + NULL, paradise_wd90c30_config }; diff --git a/src/devices/video/vid_s3.c b/src/devices/video/vid_s3.c index b6f0a06..5a2d1c7 100644 --- a/src/devices/video/vid_s3.c +++ b/src/devices/video/vid_s3.c @@ -10,7 +10,7 @@ * * NOTE: ROM images need more/better organization per chipset. * - * Version: @(#)vid_s3.c 1.0.10 2018/05/06 + * Version: @(#)vid_s3.c 1.0.12 2018/10/05 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -54,22 +54,50 @@ #include "vid_svga.h" #include "vid_svga_render.h" #include "vid_sdac_ramdac.h" +#include "vid_bt48x_ramdac.h" +#include "vid_icd2061.h" -enum -{ - S3_VISION864, - S3_TRIO32, - S3_TRIO64 +#define ROM_PARADISE_BAHAMAS64 L"video/s3/s3/bahamas64.bin" +#define ROM_PHOENIX_VISION864 L"video/s3/s3/86c864p.bin" +#define ROM_EXPERTCOLOR_DSV3868P_CF55 L"video/s3/s3/1-dsv3868.bin" +#define ROM_DIAMOND_STEALTH64_964 L"video/s3/s3/stealth64-vram.bin" +#define ROM_PHOENIX_TRIO32 L"video/s3/s3/86c732p.bin" +#define ROM_NUMBER9_9FX L"video/s3/s3/s3_764.bin" +#define ROM_PHOENIX_TRIO64 L"video/s3/s3/86c764x1.bin" +#define ROM_DIAMOND_STEALTH64_764 L"video/s3/s3/stealth64-dram.bin" + + +enum { + S3_NUMBER9_9FX, + S3_PARADISE_BAHAMAS64, + S3_DIAMOND_STEALTH64_964, + S3_PHOENIX_TRIO32, + S3_PHOENIX_TRIO64, + S3_PHOENIX_TRIO64_ONBOARD, + S3_PHOENIX_VISION864, + S3_DIAMOND_STEALTH64_764 }; -enum -{ - VRAM_4MB = 0, - VRAM_8MB = 3, - VRAM_2MB = 4, - VRAM_1MB = 6, - VRAM_512KB = 7 +enum { + S3_VISION864, + S3_VISION964, + S3_TRIO32, + S3_TRIO64 +}; + +static const video_timings_t timing_s3_stealth64 = {VID_BUS,2,2,4,26,26,42}; +static const video_timings_t timing_s3_vision864 = {VID_BUS,4,4,5,20,20,35}; +static const video_timings_t timing_s3_vision964 = {VID_BUS,2,2,4,20,20,35}; +static const video_timings_t timing_s3_trio32 = {VID_BUS,4,3,5,26,26,42}; +static const video_timings_t timing_s3_trio64 = {VID_BUS,3,2,4,25,25,40}; + +enum { + VRAM_4MB = 0, + VRAM_8MB = 3, + VRAM_2MB = 4, + VRAM_1MB = 6, + VRAM_512KB = 7 }; #define FIFO_SIZE 65536 @@ -83,2756 +111,3256 @@ enum #define FIFO_TYPE 0xff000000 #define FIFO_ADDR 0x00ffffff -enum -{ - FIFO_INVALID = (0x00 << 24), - FIFO_WRITE_BYTE = (0x01 << 24), - FIFO_WRITE_WORD = (0x02 << 24), - FIFO_WRITE_DWORD = (0x03 << 24), - FIFO_OUT_BYTE = (0x04 << 24), - FIFO_OUT_WORD = (0x05 << 24), - FIFO_OUT_DWORD = (0x06 << 24) +enum { + FIFO_INVALID = (0x00 << 24), + FIFO_WRITE_BYTE = (0x01 << 24), + FIFO_WRITE_WORD = (0x02 << 24), + FIFO_WRITE_DWORD = (0x03 << 24), + FIFO_OUT_BYTE = (0x04 << 24), + FIFO_OUT_WORD = (0x05 << 24), + FIFO_OUT_DWORD = (0x06 << 24) }; -typedef struct -{ - uint32_t addr_type; - uint32_t val; +typedef struct { + uint32_t addr_type; + uint32_t val; } fifo_entry_t; -typedef struct s3_t -{ - mem_mapping_t linear_mapping; - mem_mapping_t mmio_mapping; - - uint8_t has_bios; - rom_t bios_rom; +typedef struct { + mem_map_t linear_mapping; + mem_map_t mmio_mapping; + + uint8_t has_bios; + rom_t bios_rom; - svga_t svga; - sdac_ramdac_t ramdac; + svga_t svga; + icd2061_t icd2061; - uint8_t bank; - uint8_t ma_ext; - int width; - int bpp; + uint8_t bank; + uint8_t ma_ext; + int width; + int bpp; - int chip; - - uint8_t id, id_ext, id_ext_pci; - - uint8_t int_line; - - int packed_mmio; + int chip, pci; - uint32_t linear_base, linear_size; - - uint8_t pci_regs[256]; - int card; + uint8_t id, id_ext, id_ext_pci; - uint32_t vram_mask; - uint8_t status_9ae8; - - float (*getclock)(int clock, void *p); - void *getclock_p; + uint8_t int_line; - struct - { - uint16_t subsys_cntl; - uint16_t setup_md; - uint8_t advfunc_cntl; - uint16_t cur_y; - uint16_t cur_x; - int16_t desty_axstp; - int16_t destx_distp; - int16_t err_term; - int16_t maj_axis_pcnt; - uint16_t cmd; - uint16_t short_stroke; - uint32_t bkgd_color; - uint32_t frgd_color; - uint32_t wrt_mask; - uint32_t rd_mask; - uint32_t color_cmp; - uint8_t bkgd_mix; - uint8_t frgd_mix; - uint16_t multifunc_cntl; - uint16_t multifunc[16]; - uint8_t pix_trans[4]; - - int cx, cy; - int sx, sy; - int dx, dy; - uint32_t src, dest, pattern; - int pix_trans_count; - - uint32_t dat_buf; - int dat_count; - } accel; + int packed_mmio; - fifo_entry_t fifo[FIFO_SIZE]; - volatile int fifo_read_idx, fifo_write_idx; + int p86c911_compat; - thread_t *fifo_thread; - event_t *wake_fifo_thread; - event_t *fifo_not_full_event; - - int blitter_busy; - uint64_t blitter_time; - uint64_t status_time; - - uint8_t subsys_cntl, subsys_stat; - - uint32_t hwc_fg_col, hwc_bg_col; - int hwc_col_stack_pos; + uint32_t linear_base, linear_size; + + uint8_t pci_regs[256]; + int card; + + uint32_t vram_mask; + uint8_t status_9ae8; + + struct { + uint16_t subsys_cntl; + uint16_t setup_md; + uint8_t advfunc_cntl; + uint16_t cur_y, cur_y2; + uint16_t cur_x, cur_x2; + uint16_t x2; + int16_t desty_axstp, desty_axstp2; + int16_t destx_distp; + int16_t err_term, err_term2; + int16_t maj_axis_pcnt, maj_axis_pcnt2; + uint16_t cmd; + uint16_t short_stroke; + uint32_t bkgd_color; + uint32_t frgd_color; + uint32_t wrt_mask; + uint32_t rd_mask; + uint32_t color_cmp; + uint8_t bkgd_mix; + uint8_t frgd_mix; + uint16_t multifunc_cntl; + uint16_t multifunc[16]; + uint8_t pix_trans[4]; + + int cx, cy; + int sx, sy; + int dx, dy; + uint32_t src, dest, pattern; + int pix_trans_count; + + int poly_cx, poly_cx2; + int poly_cy, poly_cy2; + int point_1_updated, point_2_updated; + int poly_dx1, poly_dx2; + int poly_x; + + uint32_t dat_buf; + int dat_count; + } accel; + + fifo_entry_t fifo[FIFO_SIZE]; + volatile int fifo_read_idx, fifo_write_idx; + + thread_t *fifo_thread; + event_t *wake_fifo_thread; + event_t *fifo_not_full_event; + + int blitter_busy; + uint64_t blitter_time; + uint64_t status_time; + + uint8_t subsys_cntl, subsys_stat; + + uint32_t hwc_fg_col, hwc_bg_col; + int hwc_col_stack_pos; } s3_t; + #define INT_VSY (1 << 0) #define INT_GE_BSY (1 << 1) #define INT_FIFO_OVR (1 << 2) #define INT_FIFO_EMP (1 << 3) #define INT_MASK 0xf -void s3_updatemapping(); +void s3_updatemapping(); void s3_accel_write(uint32_t addr, uint8_t val, void *p); void s3_accel_write_w(uint32_t addr, uint16_t val, void *p); void s3_accel_write_l(uint32_t addr, uint32_t val, void *p); uint8_t s3_accel_read(uint32_t addr, void *p); -static inline void wake_fifo_thread(s3_t *s3) + +static __inline void +wake_fifo_thread(s3_t *s3) { - thread_set_event(s3->wake_fifo_thread); /*Wake up FIFO thread if moving from idle*/ + /*Wake up FIFO thread if moving from idle*/ + thread_set_event(s3->wake_fifo_thread); } + static void s3_wait_fifo_idle(s3_t *s3) { - while (!FIFO_EMPTY) - { - wake_fifo_thread(s3); - thread_wait_event(s3->fifo_not_full_event, 1); - } + while (!FIFO_EMPTY) + { + wake_fifo_thread(s3); + thread_wait_event(s3->fifo_not_full_event, 1); + } } static void s3_update_irqs(s3_t *s3) { - if (s3->subsys_cntl & s3->subsys_stat & INT_MASK) - pci_set_irq(s3->card, PCI_INTA); - else - pci_clear_irq(s3->card, PCI_INTA); + if (!s3->pci) + { + return; + } + + if (s3->subsys_cntl & s3->subsys_stat & INT_MASK) + pci_set_irq(s3->card, PCI_INTA); + else + pci_clear_irq(s3->card, PCI_INTA); } void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_t *s3); -#define WRITE8(addr, var, val) switch ((addr) & 3) \ - { \ - case 0: var = (var & 0xffffff00) | (val); break; \ - case 1: var = (var & 0xffff00ff) | ((val) << 8); break; \ - case 2: var = (var & 0xff00ffff) | ((val) << 16); break; \ - case 3: var = (var & 0x00ffffff) | ((val) << 24); break; \ - } +#define WRITE8(addr, var, val) switch ((addr) & 3) \ + { \ + case 0: var = (var & 0xffffff00) | (val); break; \ + case 1: var = (var & 0xffff00ff) | ((val) << 8); break; \ + case 2: var = (var & 0xff00ffff) | ((val) << 16); break; \ + case 3: var = (var & 0x00ffffff) | ((val) << 24); break; \ + } static void s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) { - switch (port) - { - case 0x82e8: - s3->accel.cur_y = (s3->accel.cur_y & 0xf00) | val; - break; - case 0x82e9: - s3->accel.cur_y = (s3->accel.cur_y & 0xff) | ((val & 0x1f) << 8); - break; - - case 0x86e8: - s3->accel.cur_x = (s3->accel.cur_x & 0xf00) | val; - break; - case 0x86e9: - s3->accel.cur_x = (s3->accel.cur_x & 0xff) | ((val & 0x1f) << 8); - break; - - case 0x8ae8: - s3->accel.desty_axstp = (s3->accel.desty_axstp & 0x3f00) | val; - break; - case 0x8ae9: - s3->accel.desty_axstp = (s3->accel.desty_axstp & 0xff) | ((val & 0x3f) << 8); - if (val & 0x20) - s3->accel.desty_axstp |= ~0x3fff; - break; - - case 0x8ee8: - s3->accel.destx_distp = (s3->accel.destx_distp & 0x3f00) | val; - break; - case 0x8ee9: - s3->accel.destx_distp = (s3->accel.destx_distp & 0xff) | ((val & 0x3f) << 8); - if (val & 0x20) - s3->accel.destx_distp |= ~0x3fff; - break; - - case 0x92e8: - s3->accel.err_term = (s3->accel.err_term & 0x3f00) | val; - break; - case 0x92e9: - s3->accel.err_term = (s3->accel.err_term & 0xff) | ((val & 0x3f) << 8); - if (val & 0x20) - s3->accel.err_term |= ~0x3fff; - break; + switch (port) + { + case 0x82e8: + s3->accel.cur_y = (s3->accel.cur_y & 0xf00) | val; + s3->accel.poly_cy = s3->accel.cur_y; + break; + case 0x82e9: + s3->accel.cur_y = (s3->accel.cur_y & 0xff) | ((val & 0x1f) << 8); + s3->accel.poly_cy = s3->accel.cur_y; + break; + case 0x82ea: + s3->accel.cur_y2 = (s3->accel.cur_y2 & 0xf00) | val; + s3->accel.poly_cy2 = s3->accel.cur_y2; + break; + case 0x82eb: + s3->accel.cur_y2 = (s3->accel.cur_y2 & 0xff) | ((val & 0x1f) << 8); + s3->accel.poly_cy2 = s3->accel.cur_y2; + break; + + case 0x86e8: + s3->accel.cur_x = (s3->accel.cur_x & 0xf00) | val; + s3->accel.poly_cx = s3->accel.cur_x << 20; + s3->accel.poly_x = s3->accel.poly_cx >> 20; + break; + case 0x86e9: + s3->accel.cur_x = (s3->accel.cur_x & 0xff) | ((val & 0x1f) << 8); + s3->accel.poly_cx = s3->accel.poly_x = s3->accel.cur_x << 20; + s3->accel.poly_x = s3->accel.poly_cx >> 20; + break; + case 0x86ea: + s3->accel.cur_x2 = (s3->accel.cur_x2 & 0xf00) | val; + s3->accel.poly_cx2 = s3->accel.cur_x2 << 20; + break; + case 0x86eb: + s3->accel.cur_x2 = (s3->accel.cur_x2 & 0xff) | ((val & 0x1f) << 8); + s3->accel.poly_cx2 = s3->accel.cur_x2 << 20; + break; + + case 0x8ae8: + s3->accel.desty_axstp = (s3->accel.desty_axstp & 0x3f00) | val; + s3->accel.point_1_updated = 1; + break; + case 0x8ae9: + s3->accel.desty_axstp = (s3->accel.desty_axstp & 0xff) | ((val & 0x3f) << 8); + if (val & 0x20) + s3->accel.desty_axstp |= ~0x3fff; + s3->accel.point_1_updated = 1; + break; + case 0x8aea: + s3->accel.desty_axstp2 = (s3->accel.desty_axstp2 & 0x3f00) | val; + s3->accel.point_2_updated = 1; + break; + case 0x8aeb: + s3->accel.desty_axstp2 = (s3->accel.desty_axstp2 & 0xff) | ((val & 0x3f) << 8); + if (val & 0x20) + s3->accel.desty_axstp2 |= ~0x3fff; + s3->accel.point_2_updated = 1; + break; + + case 0x8ee8: + s3->accel.destx_distp = (s3->accel.destx_distp & 0x3f00) | val; + s3->accel.point_1_updated = 1; + break; + case 0x8ee9: + s3->accel.destx_distp = (s3->accel.destx_distp & 0xff) | ((val & 0x3f) << 8); + if (val & 0x20) + s3->accel.destx_distp |= ~0x3fff; + s3->accel.point_1_updated = 1; + break; + case 0x8eea: + s3->accel.x2 = (s3->accel.x2 & 0xf00) | val; + s3->accel.point_2_updated = 1; + break; + case 0x8eeb: + s3->accel.x2 = (s3->accel.x2 & 0xff) | ((val & 0xf) << 8); + s3->accel.point_2_updated = 1; + break; + + case 0x92e8: + s3->accel.err_term = (s3->accel.err_term & 0x3f00) | val; + break; + case 0x92e9: + s3->accel.err_term = (s3->accel.err_term & 0xff) | ((val & 0x3f) << 8); + if (val & 0x20) + s3->accel.err_term |= ~0x3fff; + break; + case 0x92ea: + s3->accel.err_term2 = (s3->accel.err_term2 & 0x3f00) | val; + break; + case 0x92eb: + s3->accel.err_term2 = (s3->accel.err_term2 & 0xff) | ((val & 0x3f) << 8); + if (val & 0x20) + s3->accel.err_term2 |= ~0x3fff; + break; - case 0x96e8: - s3->accel.maj_axis_pcnt = (s3->accel.maj_axis_pcnt & 0x3f00) | val; - break; - case 0x96e9: - s3->accel.maj_axis_pcnt = (s3->accel.maj_axis_pcnt & 0xff) | ((val & 0x0f) << 8); - if (val & 0x08) - s3->accel.maj_axis_pcnt |= ~0x0fff; - break; + case 0x96e8: + s3->accel.maj_axis_pcnt = (s3->accel.maj_axis_pcnt & 0x3f00) | val; + break; + case 0x96e9: + s3->accel.maj_axis_pcnt = (s3->accel.maj_axis_pcnt & 0xff) | ((val & 0x0f) << 8); + if (val & 0x08) + s3->accel.maj_axis_pcnt |= ~0x0fff; + break; + case 0x96ea: + s3->accel.maj_axis_pcnt2 = (s3->accel.maj_axis_pcnt2 & 0xf00) | val; + break; + case 0x96eb: + s3->accel.maj_axis_pcnt2 = (s3->accel.maj_axis_pcnt2 & 0xff) | ((val & 0x0f) << 8); + if (val & 0x08) + s3->accel.maj_axis_pcnt2 |= ~0x0fff; + break; - case 0x9ae8: - s3->accel.cmd = (s3->accel.cmd & 0xff00) | val; - break; - case 0x9ae9: - s3->accel.cmd = (s3->accel.cmd & 0xff) | (val << 8); - s3_accel_start(-1, 0, 0xffffffff, 0, s3); - s3->accel.pix_trans_count = 0; - s3->accel.multifunc[0xe] &= ~0x10; /*hack*/ - break; + case 0x9ae8: + s3->accel.cmd = (s3->accel.cmd & 0xff00) | val; + break; + case 0x9ae9: + s3->accel.cmd = (s3->accel.cmd & 0xff) | (val << 8); + s3_accel_start(-1, 0, 0xffffffff, 0, s3); + s3->accel.pix_trans_count = 0; + s3->accel.multifunc[0xe] &= ~0x10; /*hack*/ + break; - case 0x9ee8: - s3->accel.short_stroke = (s3->accel.short_stroke & 0xff00) | val; - break; - case 0x9ee9: - s3->accel.short_stroke = (s3->accel.short_stroke & 0xff) | (val << 8); - break; + case 0x9ee8: + s3->accel.short_stroke = (s3->accel.short_stroke & 0xff00) | val; + break; + case 0x9ee9: + s3->accel.short_stroke = (s3->accel.short_stroke & 0xff) | (val << 8); + break; - case 0xa2e8: - if (s3->bpp == 3 && s3->accel.multifunc[0xe] & 0x10 && !(s3->accel.multifunc[0xe] & 0x200)) - s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0x00ff0000) | (val << 16); - else - s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0x000000ff) | val; - break; - case 0xa2e9: - if (s3->bpp == 3 && s3->accel.multifunc[0xe] & 0x10 && !(s3->accel.multifunc[0xe] & 0x200)) - s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0xff000000) | (val << 24); - else - s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0x0000ff00) | (val << 8); - if (!(s3->accel.multifunc[0xe] & 0x200)) - s3->accel.multifunc[0xe] ^= 0x10; - break; - case 0xa2ea: - if (s3->accel.multifunc[0xe] & 0x200) - s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0x00ff0000) | (val << 16); - break; - case 0xa2eb: - if (s3->accel.multifunc[0xe] & 0x200) - s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0xff000000) | (val << 24); - break; + case 0xa2e8: + if (s3->bpp == 3 && s3->accel.multifunc[0xe] & 0x10 && !(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0x00ff0000) | (val << 16); + else + s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0x000000ff) | val; + break; + case 0xa2e9: + if (s3->bpp == 3 && s3->accel.multifunc[0xe] & 0x10 && !(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0xff000000) | (val << 24); + else + s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0x0000ff00) | (val << 8); + if (!(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.multifunc[0xe] ^= 0x10; + break; + case 0xa2ea: + if (s3->accel.multifunc[0xe] & 0x200) + s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0x00ff0000) | (val << 16); + else if (s3->bpp == 3) + { + if (s3->accel.multifunc[0xe] & 0x10) + s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0x00ff0000) | (val << 16); + else + s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0x000000ff) | val; + } + break; + case 0xa2eb: + if (s3->accel.multifunc[0xe] & 0x200) + s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0xff000000) | (val << 24); + else if (s3->bpp == 3) + { + if (s3->accel.multifunc[0xe] & 0x10) + s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0xff000000) | (val << 24); + else + s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0x0000ff00) | (val << 8); + s3->accel.multifunc[0xe] ^= 0x10; + } + break; - case 0xa6e8: - if (s3->bpp == 3 && s3->accel.multifunc[0xe] & 0x10 && !(s3->accel.multifunc[0xe] & 0x200)) - s3->accel.frgd_color = (s3->accel.frgd_color & ~0x00ff0000) | (val << 16); - else - s3->accel.frgd_color = (s3->accel.frgd_color & ~0x000000ff) | val; - break; - case 0xa6e9: - if (s3->bpp == 3 && s3->accel.multifunc[0xe] & 0x10 && !(s3->accel.multifunc[0xe] & 0x200)) - s3->accel.frgd_color = (s3->accel.frgd_color & ~0xff000000) | (val << 24); - else - s3->accel.frgd_color = (s3->accel.frgd_color & ~0x0000ff00) | (val << 8); - if (!(s3->accel.multifunc[0xe] & 0x200)) - s3->accel.multifunc[0xe] ^= 0x10; - break; - case 0xa6ea: - if (s3->accel.multifunc[0xe] & 0x200) - s3->accel.frgd_color = (s3->accel.frgd_color & ~0x00ff0000) | (val << 16); - break; - case 0xa6eb: - if (s3->accel.multifunc[0xe] & 0x200) - s3->accel.frgd_color = (s3->accel.frgd_color & ~0xff000000) | (val << 24); - break; + case 0xa6e8: + if (s3->bpp == 3 && s3->accel.multifunc[0xe] & 0x10 && !(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.frgd_color = (s3->accel.frgd_color & ~0x00ff0000) | (val << 16); + else + s3->accel.frgd_color = (s3->accel.frgd_color & ~0x000000ff) | val; + break; + case 0xa6e9: + if (s3->bpp == 3 && s3->accel.multifunc[0xe] & 0x10 && !(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.frgd_color = (s3->accel.frgd_color & ~0xff000000) | (val << 24); + else + s3->accel.frgd_color = (s3->accel.frgd_color & ~0x0000ff00) | (val << 8); + if (!(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.multifunc[0xe] ^= 0x10; + break; + case 0xa6ea: + if (s3->accel.multifunc[0xe] & 0x200) + s3->accel.frgd_color = (s3->accel.frgd_color & ~0x00ff0000) | (val << 16); + else if (s3->bpp == 3) + { + if (s3->accel.multifunc[0xe] & 0x10) + s3->accel.frgd_color = (s3->accel.frgd_color & ~0x00ff0000) | (val << 16); + else + s3->accel.frgd_color = (s3->accel.frgd_color & ~0x000000ff) | val; + } + break; + case 0xa6eb: + if (s3->accel.multifunc[0xe] & 0x200) + s3->accel.frgd_color = (s3->accel.frgd_color & ~0xff000000) | (val << 24); + else if (s3->bpp == 3) + { + if (s3->accel.multifunc[0xe] & 0x10) + s3->accel.frgd_color = (s3->accel.frgd_color & ~0xff000000) | (val << 24); + else + s3->accel.frgd_color = (s3->accel.frgd_color & ~0x0000ff00) | (val << 8); + s3->accel.multifunc[0xe] ^= 0x10; + } + break; - case 0xaae8: - if (s3->bpp == 3 && s3->accel.multifunc[0xe] & 0x10 && !(s3->accel.multifunc[0xe] & 0x200)) - s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0x00ff0000) | (val << 16); - else - s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0x000000ff) | val; - break; - case 0xaae9: - if (s3->bpp == 3 && s3->accel.multifunc[0xe] & 0x10 && !(s3->accel.multifunc[0xe] & 0x200)) - s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0xff000000) | (val << 24); - else - s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0x0000ff00) | (val << 8); - if (!(s3->accel.multifunc[0xe] & 0x200)) - s3->accel.multifunc[0xe] ^= 0x10; - break; - case 0xaaea: - if (s3->accel.multifunc[0xe] & 0x200) - s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0x00ff0000) | (val << 16); - break; - case 0xaaeb: - if (s3->accel.multifunc[0xe] & 0x200) - s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0xff000000) | (val << 24); - break; + case 0xaae8: + if (s3->bpp == 3 && s3->accel.multifunc[0xe] & 0x10 && !(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0x00ff0000) | (val << 16); + else + s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0x000000ff) | val; + break; + case 0xaae9: + if (s3->bpp == 3 && s3->accel.multifunc[0xe] & 0x10 && !(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0xff000000) | (val << 24); + else + s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0x0000ff00) | (val << 8); + if (!(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.multifunc[0xe] ^= 0x10; + break; + case 0xaaea: + if (s3->accel.multifunc[0xe] & 0x200) + s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0x00ff0000) | (val << 16); + else if (s3->bpp == 3) + { + if (s3->accel.multifunc[0xe] & 0x10) + s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0x00ff0000) | (val << 16); + else + s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0x000000ff) | val; + } + break; + case 0xaaeb: + if (s3->accel.multifunc[0xe] & 0x200) + s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0xff000000) | (val << 24); + else if (s3->bpp == 3) + { + if (s3->accel.multifunc[0xe] & 0x10) + s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0xff000000) | (val << 24); + else + s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0x0000ff00) | (val << 8); + s3->accel.multifunc[0xe] ^= 0x10; + } + break; - case 0xaee8: - if (s3->bpp == 3 && s3->accel.multifunc[0xe] & 0x10 && !(s3->accel.multifunc[0xe] & 0x200)) - s3->accel.rd_mask = (s3->accel.rd_mask & ~0x00ff0000) | (val << 16); - else - s3->accel.rd_mask = (s3->accel.rd_mask & ~0x000000ff) | val; - break; - case 0xaee9: - if (s3->bpp == 3 && s3->accel.multifunc[0xe] & 0x10 && !(s3->accel.multifunc[0xe] & 0x200)) - s3->accel.rd_mask = (s3->accel.rd_mask & ~0xff000000) | (val << 24); - else - s3->accel.rd_mask = (s3->accel.rd_mask & ~0x0000ff00) | (val << 8); - if (!(s3->accel.multifunc[0xe] & 0x200)) - s3->accel.multifunc[0xe] ^= 0x10; - break; - case 0xaeea: - if (s3->accel.multifunc[0xe] & 0x200) - s3->accel.rd_mask = (s3->accel.rd_mask & ~0x00ff0000) | (val << 16); - break; - case 0xaeeb: - if (s3->accel.multifunc[0xe] & 0x200) - s3->accel.rd_mask = (s3->accel.rd_mask & ~0xff000000) | (val << 24); - break; + case 0xaee8: + if (s3->bpp == 3 && s3->accel.multifunc[0xe] & 0x10 && !(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.rd_mask = (s3->accel.rd_mask & ~0x00ff0000) | (val << 16); + else + s3->accel.rd_mask = (s3->accel.rd_mask & ~0x000000ff) | val; + break; + case 0xaee9: + if (s3->bpp == 3 && s3->accel.multifunc[0xe] & 0x10 && !(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.rd_mask = (s3->accel.rd_mask & ~0xff000000) | (val << 24); + else + s3->accel.rd_mask = (s3->accel.rd_mask & ~0x0000ff00) | (val << 8); + if (!(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.multifunc[0xe] ^= 0x10; + break; + case 0xaeea: + if (s3->accel.multifunc[0xe] & 0x200) + s3->accel.rd_mask = (s3->accel.rd_mask & ~0x00ff0000) | (val << 16); + else if (s3->bpp == 3) + { + if (s3->accel.multifunc[0xe] & 0x10) + s3->accel.rd_mask = (s3->accel.rd_mask & ~0x00ff0000) | (val << 16); + else + s3->accel.rd_mask = (s3->accel.rd_mask & ~0x000000ff) | val; + } + break; + case 0xaeeb: + if (s3->accel.multifunc[0xe] & 0x200) + s3->accel.rd_mask = (s3->accel.rd_mask & ~0xff000000) | (val << 24); + else if (s3->bpp == 3) + { + if (s3->accel.multifunc[0xe] & 0x10) + s3->accel.rd_mask = (s3->accel.rd_mask & ~0xff000000) | (val << 24); + else + s3->accel.rd_mask = (s3->accel.rd_mask & ~0x0000ff00) | (val << 8); + s3->accel.multifunc[0xe] ^= 0x10; + } + break; - case 0xb2e8: - if (s3->bpp == 3 && s3->accel.multifunc[0xe] & 0x10 && !(s3->accel.multifunc[0xe] & 0x200)) - s3->accel.color_cmp = (s3->accel.color_cmp & ~0x00ff0000) | (val << 16); - else - s3->accel.color_cmp = (s3->accel.color_cmp & ~0x000000ff) | val; - break; - case 0xb2e9: - if (s3->bpp == 3 && s3->accel.multifunc[0xe] & 0x10 && !(s3->accel.multifunc[0xe] & 0x200)) - s3->accel.color_cmp = (s3->accel.color_cmp & ~0xff000000) | (val << 24); - else - s3->accel.color_cmp = (s3->accel.color_cmp & ~0x0000ff00) | (val << 8); - if (!(s3->accel.multifunc[0xe] & 0x200)) - s3->accel.multifunc[0xe] ^= 0x10; - break; - case 0xb2ea: - if (s3->accel.multifunc[0xe] & 0x200) - s3->accel.color_cmp = (s3->accel.color_cmp & ~0x00ff0000) | (val << 16); - break; - case 0xb2eb: - if (s3->accel.multifunc[0xe] & 0x200) - s3->accel.color_cmp = (s3->accel.color_cmp & ~0xff000000) | (val << 24); - break; + case 0xb2e8: + if (s3->bpp == 3 && s3->accel.multifunc[0xe] & 0x10 && !(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.color_cmp = (s3->accel.color_cmp & ~0x00ff0000) | (val << 16); + else + s3->accel.color_cmp = (s3->accel.color_cmp & ~0x000000ff) | val; + break; + case 0xb2e9: + if (s3->bpp == 3 && s3->accel.multifunc[0xe] & 0x10 && !(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.color_cmp = (s3->accel.color_cmp & ~0xff000000) | (val << 24); + else + s3->accel.color_cmp = (s3->accel.color_cmp & ~0x0000ff00) | (val << 8); + if (!(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.multifunc[0xe] ^= 0x10; + break; + case 0xb2ea: + if (s3->accel.multifunc[0xe] & 0x200) + s3->accel.color_cmp = (s3->accel.color_cmp & ~0x00ff0000) | (val << 16); + else if (s3->bpp == 3) + { + if (s3->accel.multifunc[0xe] & 0x10) + s3->accel.color_cmp = (s3->accel.color_cmp & ~0x00ff0000) | (val << 16); + else + s3->accel.color_cmp = (s3->accel.color_cmp & ~0x000000ff) | val; + } + break; + case 0xb2eb: + if (s3->accel.multifunc[0xe] & 0x200) + s3->accel.color_cmp = (s3->accel.color_cmp & ~0xff000000) | (val << 24); + else if (s3->bpp == 3) + { + if (s3->accel.multifunc[0xe] & 0x10) + s3->accel.color_cmp = (s3->accel.color_cmp & ~0xff000000) | (val << 24); + else + s3->accel.color_cmp = (s3->accel.color_cmp & ~0x0000ff00) | (val << 8); + s3->accel.multifunc[0xe] ^= 0x10; + } + break; - case 0xb6e8: - s3->accel.bkgd_mix = val; - break; + case 0xb6e8: + s3->accel.bkgd_mix = val; + break; - case 0xbae8: - s3->accel.frgd_mix = val; - break; - - case 0xbee8: - s3->accel.multifunc_cntl = (s3->accel.multifunc_cntl & 0xff00) | val; - break; - case 0xbee9: - s3->accel.multifunc_cntl = (s3->accel.multifunc_cntl & 0xff) | (val << 8); - s3->accel.multifunc[s3->accel.multifunc_cntl >> 12] = s3->accel.multifunc_cntl & 0xfff; - break; + case 0xbae8: + s3->accel.frgd_mix = val; + break; + + case 0xbee8: + s3->accel.multifunc_cntl = (s3->accel.multifunc_cntl & 0xff00) | val; + break; + case 0xbee9: + s3->accel.multifunc_cntl = (s3->accel.multifunc_cntl & 0xff) | (val << 8); + s3->accel.multifunc[s3->accel.multifunc_cntl >> 12] = s3->accel.multifunc_cntl & 0xfff; + break; - case 0xe2e8: - s3->accel.pix_trans[0] = val; - if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && !(s3->accel.cmd & 0x600) && (s3->accel.cmd & 0x100)) - s3_accel_start(8, 1, s3->accel.pix_trans[0], 0, s3); - else if (!(s3->accel.cmd & 0x600) && (s3->accel.cmd & 0x100)) - s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0], s3); - break; - case 0xe2e9: - s3->accel.pix_trans[1] = val; - if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && (s3->accel.cmd & 0x600) == 0x200 && (s3->accel.cmd & 0x100)) - { - if (s3->accel.cmd & 0x1000) s3_accel_start(16, 1, s3->accel.pix_trans[1] | (s3->accel.pix_trans[0] << 8), 0, s3); - else s3_accel_start(16, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), 0, s3); - } - else if ((s3->accel.cmd & 0x600) == 0x200 && (s3->accel.cmd & 0x100)) - { - if (s3->accel.cmd & 0x1000) s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[1] | (s3->accel.pix_trans[0] << 8), s3); - else s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3); - } - break; - case 0xe2ea: - s3->accel.pix_trans[2] = val; - break; - case 0xe2eb: - s3->accel.pix_trans[3] = val; - if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && (s3->accel.cmd & 0x600) == 0x400 && (s3->accel.cmd & 0x100)) - s3_accel_start(32, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), 0, s3); - else if ((s3->accel.cmd & 0x600) == 0x400 && (s3->accel.cmd & 0x100)) - s3_accel_start(4, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), s3); - break; - } + case 0xe2e8: + s3->accel.pix_trans[0] = val; + if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && !(s3->accel.cmd & 0x600) && (s3->accel.cmd & 0x100)) + s3_accel_start(8, 1, s3->accel.pix_trans[0], 0, s3); + else if (!(s3->accel.cmd & 0x600) && (s3->accel.cmd & 0x100)) + s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0], s3); + break; + case 0xe2e9: + s3->accel.pix_trans[1] = val; + if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && (s3->accel.cmd & 0x600) == 0x200 && (s3->accel.cmd & 0x100)) + { + if (s3->accel.cmd & 0x1000) s3_accel_start(16, 1, s3->accel.pix_trans[1] | (s3->accel.pix_trans[0] << 8), 0, s3); + else s3_accel_start(16, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), 0, s3); + } + else if ((s3->accel.cmd & 0x600) == 0x200 && (s3->accel.cmd & 0x100)) + { + if (s3->accel.cmd & 0x1000) s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[1] | (s3->accel.pix_trans[0] << 8), s3); + else s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3); + } + break; + case 0xe2ea: + s3->accel.pix_trans[2] = val; + break; + case 0xe2eb: + s3->accel.pix_trans[3] = val; + if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && (s3->accel.cmd & 0x600) == 0x600 && (s3->accel.cmd & 0x100) && s3->chip == S3_TRIO32) + { + s3_accel_start(8, 1, s3->accel.pix_trans[3], 0, s3); + s3_accel_start(8, 1, s3->accel.pix_trans[2], 0, s3); + s3_accel_start(8, 1, s3->accel.pix_trans[1], 0, s3); + s3_accel_start(8, 1, s3->accel.pix_trans[0], 0, s3); + } + else if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && (s3->accel.cmd & 0x400) == 0x400 && (s3->accel.cmd & 0x100)) + s3_accel_start(32, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), 0, s3); + else if ((s3->accel.cmd & 0x600) == 0x400 && (s3->accel.cmd & 0x100)) + s3_accel_start(4, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), s3); + break; + } } static void s3_accel_out_fifo_w(s3_t *s3, uint16_t port, uint16_t val) { - if (s3->accel.cmd & 0x100) - { - if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80) - { - if (s3->accel.cmd & 0x1000) - val = (val >> 8) | (val << 8); - if ((s3->accel.cmd & 0x600) == 0x000) - s3_accel_start(8, 1, val | (val << 16), 0, s3); - else - s3_accel_start(16, 1, val | (val << 16), 0, s3); - } - else - { - if ((s3->accel.cmd & 0x600) == 0x000) - s3_accel_start(1, 1, 0xffffffff, val | (val << 16), s3); - else - s3_accel_start(2, 1, 0xffffffff, val | (val << 16), s3); - } - } + if (s3->accel.cmd & 0x100) + { + if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80) + { + if (s3->accel.cmd & 0x1000) + val = (val >> 8) | (val << 8); + if ((s3->accel.cmd & 0x600) == 0x600 && s3->chip == S3_TRIO32) + { + s3_accel_start(8, 1, (val >> 8) & 0xff, 0, s3); + s3_accel_start(8, 1, val & 0xff, 0, s3); + } + if ((s3->accel.cmd & 0x600) == 0x000) + s3_accel_start(8, 1, val | (val << 16), 0, s3); + else + s3_accel_start(16, 1, val | (val << 16), 0, s3); + } + else + { + if ((s3->accel.cmd & 0x600) == 0x000) + s3_accel_start(1, 1, 0xffffffff, val | (val << 16), s3); + else + s3_accel_start(2, 1, 0xffffffff, val | (val << 16), s3); + } + } } static void s3_accel_out_fifo_l(s3_t *s3, uint16_t port, uint32_t val) { - if (s3->accel.cmd & 0x100) - { - if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80) - { - if (s3->accel.cmd & 0x400) - { - if (s3->accel.cmd & 0x1000) - val = ((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24); - s3_accel_start(32, 1, val, 0, s3); - } - else if ((s3->accel.cmd & 0x600) == 0x200) - { - if (s3->accel.cmd & 0x1000) - val = ((val & 0xff00ff00) >> 8) | ((val & 0x00ff00ff) << 8); - s3_accel_start(16, 1, val, 0, s3); - s3_accel_start(16, 1, val >> 16, 0, s3); - } - else - { - if (s3->accel.cmd & 0x1000) - val = ((val & 0xff00ff00) >> 8) | ((val & 0x00ff00ff) << 8); - s3_accel_start(8, 1, val, 0, s3); - s3_accel_start(8, 1, val >> 16, 0, s3); - } - } - else - { - if (s3->accel.cmd & 0x400) - s3_accel_start(4, 1, 0xffffffff, val, s3); - else if ((s3->accel.cmd & 0x600) == 0x200) - { - s3_accel_start(2, 1, 0xffffffff, val, s3); - s3_accel_start(2, 1, 0xffffffff, val >> 16, s3); - } - else - { - s3_accel_start(1, 1, 0xffffffff, val, s3); - s3_accel_start(1, 1, 0xffffffff, val >> 16, s3); - } - } - } + if (s3->accel.cmd & 0x100) + { + if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80) + { + if ((s3->accel.cmd & 0x600) == 0x600 && s3->chip == S3_TRIO32) + { + if (s3->accel.cmd & 0x1000) + val = ((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24); + s3_accel_start(8, 1, (val >> 24) & 0xff, 0, s3); + s3_accel_start(8, 1, (val >> 16) & 0xff, 0, s3); + s3_accel_start(8, 1, (val >> 8) & 0xff, 0, s3); + s3_accel_start(8, 1, val & 0xff, 0, s3); + } + else if (s3->accel.cmd & 0x400) + { + if (s3->accel.cmd & 0x1000) + val = ((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24); + s3_accel_start(32, 1, val, 0, s3); + } + else if ((s3->accel.cmd & 0x600) == 0x200) + { + if (s3->accel.cmd & 0x1000) + val = ((val & 0xff00ff00) >> 8) | ((val & 0x00ff00ff) << 8); + s3_accel_start(16, 1, val, 0, s3); + s3_accel_start(16, 1, val >> 16, 0, s3); + } + else + { + if (s3->accel.cmd & 0x1000) + val = ((val & 0xff00ff00) >> 8) | ((val & 0x00ff00ff) << 8); + s3_accel_start(8, 1, val, 0, s3); + s3_accel_start(8, 1, val >> 16, 0, s3); + } + } + else + { + if (s3->accel.cmd & 0x400) + s3_accel_start(4, 1, 0xffffffff, val, s3); + else if ((s3->accel.cmd & 0x600) == 0x200) + { + s3_accel_start(2, 1, 0xffffffff, val, s3); + s3_accel_start(2, 1, 0xffffffff, val >> 16, s3); + } + else + { + s3_accel_start(1, 1, 0xffffffff, val, s3); + s3_accel_start(1, 1, 0xffffffff, val >> 16, s3); + } + } + } } static void s3_accel_write_fifo(s3_t *s3, uint32_t addr, uint8_t val) { - if (s3->packed_mmio) - { - int addr_lo = addr & 1; - switch (addr & 0xfffe) - { - case 0x8100: addr = 0x82e8; break; /*ALT_CURXY*/ - case 0x8102: addr = 0x86e8; break; - - case 0x8104: addr = 0x82ea; break; /*ALT_CURXY2*/ - case 0x8106: addr = 0x86ea; break; - - case 0x8108: addr = 0x8ae8; break; /*ALT_STEP*/ - case 0x810a: addr = 0x8ee8; break; - - case 0x810c: addr = 0x8aea; break; /*ALT_STEP2*/ - case 0x810e: addr = 0x8eea; break; + if (s3->packed_mmio) + { + int addr_lo = addr & 1; + switch (addr & 0xfffe) + { + case 0x8100: addr = 0x82e8; break; /*ALT_CURXY*/ + case 0x8102: addr = 0x86e8; break; + + case 0x8104: addr = 0x82ea; break; /*ALT_CURXY2*/ + case 0x8106: addr = 0x86ea; break; + + case 0x8108: addr = 0x8ae8; break; /*ALT_STEP*/ + case 0x810a: addr = 0x8ee8; break; + + case 0x810c: addr = 0x8aea; break; /*ALT_STEP2*/ + case 0x810e: addr = 0x8eea; break; - case 0x8110: addr = 0x92e8; break; /*ALT_ERR*/ - case 0x8112: addr = 0x92ee; break; + case 0x8110: addr = 0x92e8; break; /*ALT_ERR*/ + case 0x8112: addr = 0x92ee; break; - case 0x8118: addr = 0x9ae8; break; /*ALT_CMD*/ - case 0x811a: addr = 0x9aea; break; - - case 0x811c: addr = 0x9ee8; break; /*SHORT_STROKE*/ - - case 0x8120: case 0x8122: /*BKGD_COLOR*/ - WRITE8(addr, s3->accel.bkgd_color, val); - return; - - case 0x8124: case 0x8126: /*FRGD_COLOR*/ - WRITE8(addr, s3->accel.frgd_color, val); - return; + case 0x8118: addr = 0x9ae8; break; /*ALT_CMD*/ + case 0x811a: addr = 0x9aea; break; + + case 0x811c: addr = 0x9ee8; break; /*SHORT_STROKE*/ + + case 0x8120: case 0x8122: /*BKGD_COLOR*/ + WRITE8(addr, s3->accel.bkgd_color, val); + return; + + case 0x8124: case 0x8126: /*FRGD_COLOR*/ + WRITE8(addr, s3->accel.frgd_color, val); + return; - case 0x8128: case 0x812a: /*WRT_MASK*/ - WRITE8(addr, s3->accel.wrt_mask, val); - return; + case 0x8128: case 0x812a: /*WRT_MASK*/ + WRITE8(addr, s3->accel.wrt_mask, val); + return; - case 0x812c: case 0x812e: /*RD_MASK*/ - WRITE8(addr, s3->accel.rd_mask, val); - return; + case 0x812c: case 0x812e: /*RD_MASK*/ + WRITE8(addr, s3->accel.rd_mask, val); + return; - case 0x8130: case 0x8132: /*COLOR_CMP*/ - WRITE8(addr, s3->accel.color_cmp, val); - return; + case 0x8130: case 0x8132: /*COLOR_CMP*/ + WRITE8(addr, s3->accel.color_cmp, val); + return; - case 0x8134: addr = 0xb6e8; break; /*ALT_MIX*/ - case 0x8136: addr = 0xbae8; break; - - case 0x8138: /*SCISSORS_T*/ - WRITE8(addr & 1, s3->accel.multifunc[1], val); - return; - case 0x813a: /*SCISSORS_L*/ - WRITE8(addr & 1, s3->accel.multifunc[2], val); - return; - case 0x813c: /*SCISSORS_B*/ - WRITE8(addr & 1, s3->accel.multifunc[3], val); - return; - case 0x813e: /*SCISSORS_R*/ - WRITE8(addr & 1, s3->accel.multifunc[4], val); - return; + case 0x8134: addr = 0xb6e8; break; /*ALT_MIX*/ + case 0x8136: addr = 0xbae8; break; + + case 0x8138: /*SCISSORS_T*/ + WRITE8(addr & 1, s3->accel.multifunc[1], val); + return; + case 0x813a: /*SCISSORS_L*/ + WRITE8(addr & 1, s3->accel.multifunc[2], val); + return; + case 0x813c: /*SCISSORS_B*/ + WRITE8(addr & 1, s3->accel.multifunc[3], val); + return; + case 0x813e: /*SCISSORS_R*/ + WRITE8(addr & 1, s3->accel.multifunc[4], val); + return; - case 0x8140: /*PIX_CNTL*/ - WRITE8(addr & 1, s3->accel.multifunc[0xa], val); - return; - case 0x8142: /*MULT_MISC2*/ - WRITE8(addr & 1, s3->accel.multifunc[0xd], val); - return; - case 0x8144: /*MULT_MISC*/ - WRITE8(addr & 1, s3->accel.multifunc[0xe], val); - return; - case 0x8146: /*READ_SEL*/ - WRITE8(addr & 1, s3->accel.multifunc[0xf], val); - return; + case 0x8140: /*PIX_CNTL*/ + WRITE8(addr & 1, s3->accel.multifunc[0xa], val); + return; + case 0x8142: /*MULT_MISC2*/ + WRITE8(addr & 1, s3->accel.multifunc[0xd], val); + return; + case 0x8144: /*MULT_MISC*/ + WRITE8(addr & 1, s3->accel.multifunc[0xe], val); + return; + case 0x8146: /*READ_SEL*/ + WRITE8(addr & 1, s3->accel.multifunc[0xf], val); + return; - case 0x8148: /*ALT_PCNT*/ - WRITE8(addr & 1, s3->accel.multifunc[0], val); - return; - case 0x814a: addr = 0x96e8; break; - case 0x814c: addr = 0x96ea; break; + case 0x8148: /*ALT_PCNT*/ + WRITE8(addr & 1, s3->accel.multifunc[0], val); + return; + case 0x814a: addr = 0x96e8; break; + case 0x814c: addr = 0x96ea; break; - case 0x8168: addr = 0xeae8; break; - case 0x816a: addr = 0xeaea; break; - } - addr |= addr_lo; - } - + case 0x8168: addr = 0xeae8; break; + case 0x816a: addr = 0xeaea; break; + } + addr |= addr_lo; + } + - if (addr & 0x8000) - { - s3_accel_out_fifo(s3, addr & 0xffff, val); - } - else - { - if (s3->accel.cmd & 0x100) - { - if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80) - s3_accel_start(8, 1, val | (val << 8) | (val << 16) | (val << 24), 0, s3); - else - s3_accel_start(1, 1, 0xffffffff, val | (val << 8) | (val << 16) | (val << 24), s3); - } - } + if (addr & 0x8000) + { + s3_accel_out_fifo(s3, addr & 0xffff, val); + } + else + { + if (s3->accel.cmd & 0x100) + { + if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80) + s3_accel_start(8, 1, val | (val << 8) | (val << 16) | (val << 24), 0, s3); + else + s3_accel_start(1, 1, 0xffffffff, val | (val << 8) | (val << 16) | (val << 24), s3); + } + } } static void s3_accel_write_fifo_w(s3_t *s3, uint32_t addr, uint16_t val) { - if (addr & 0x8000) - { - s3_accel_write_fifo(s3, addr, val & 0xff); - s3_accel_write_fifo(s3, addr + 1, val >> 8); - } - else - { - if (s3->accel.cmd & 0x100) - { - if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80) - { - if (s3->accel.cmd & 0x1000) - val = (val >> 8) | (val << 8); - if ((s3->accel.cmd & 0x600) == 0x000) - s3_accel_start(8, 1, val | (val << 16), 0, s3); - else - s3_accel_start(16, 1, val | (val << 16), 0, s3); - } - else - { - if ((s3->accel.cmd & 0x600) == 0x000) - s3_accel_start(1, 1, 0xffffffff, val | (val << 16), s3); - else - s3_accel_start(2, 1, 0xffffffff, val | (val << 16), s3); - } - } - } + if (addr & 0x8000) + { + s3_accel_write_fifo(s3, addr, val & 0xff); + s3_accel_write_fifo(s3, addr + 1, val >> 8); + } + else + { + if (s3->accel.cmd & 0x100) + { + if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80) + { + if (s3->accel.cmd & 0x1000) + val = (val >> 8) | (val << 8); + if ((s3->accel.cmd & 0x600) == 0x600 && s3->chip == S3_TRIO32) + { + s3_accel_start(8, 1, (val >> 8) & 0xff, 0, s3); + s3_accel_start(8, 1, val & 0xff, 0, s3); + } + else if ((s3->accel.cmd & 0x600) == 0x000) + s3_accel_start(8, 1, val | (val << 16), 0, s3); + else + s3_accel_start(16, 1, val | (val << 16), 0, s3); + } + else + { + if ((s3->accel.cmd & 0x600) == 0x000) + s3_accel_start(1, 1, 0xffffffff, val | (val << 16), s3); + else + s3_accel_start(2, 1, 0xffffffff, val | (val << 16), s3); + } + } + } } static void s3_accel_write_fifo_l(s3_t *s3, uint32_t addr, uint32_t val) { - if (addr & 0x8000) - { - s3_accel_write_fifo(s3, addr, val); - s3_accel_write_fifo(s3, addr + 1, val >> 8); - s3_accel_write_fifo(s3, addr + 2, val >> 16); - s3_accel_write_fifo(s3, addr + 3, val >> 24); - } - else - { - if (s3->accel.cmd & 0x100) - { - if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80) - { - if (s3->accel.cmd & 0x400) - { - if (s3->accel.cmd & 0x1000) - val = ((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24); - s3_accel_start(32, 1, val, 0, s3); - } - else if ((s3->accel.cmd & 0x600) == 0x200) - { - if (s3->accel.cmd & 0x1000) - val = ((val & 0xff00ff00) >> 8) | ((val & 0x00ff00ff) << 8); - s3_accel_start(16, 1, val, 0, s3); - s3_accel_start(16, 1, val >> 16, 0, s3); - } - else - { - if (s3->accel.cmd & 0x1000) - val = ((val & 0xff00ff00) >> 8) | ((val & 0x00ff00ff) << 8); - s3_accel_start(8, 1, val, 0, s3); - s3_accel_start(8, 1, val >> 16, 0, s3); - } - } - else - { - if (s3->accel.cmd & 0x400) - s3_accel_start(4, 1, 0xffffffff, val, s3); - else if ((s3->accel.cmd & 0x600) == 0x200) - { - s3_accel_start(2, 1, 0xffffffff, val, s3); - s3_accel_start(2, 1, 0xffffffff, val >> 16, s3); - } - else - { - s3_accel_start(1, 1, 0xffffffff, val, s3); - s3_accel_start(1, 1, 0xffffffff, val >> 16, s3); - } - } - } - } + if (addr & 0x8000) + { + s3_accel_write_fifo(s3, addr, val); + s3_accel_write_fifo(s3, addr + 1, val >> 8); + s3_accel_write_fifo(s3, addr + 2, val >> 16); + s3_accel_write_fifo(s3, addr + 3, val >> 24); + } + else + { + if (s3->accel.cmd & 0x100) + { + if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80) + { + if ((s3->accel.cmd & 0x600) == 0x600 && s3->chip == S3_TRIO32) + { + if (s3->accel.cmd & 0x1000) + val = ((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24); + s3_accel_start(8, 1, (val >> 24) & 0xff, 0, s3); + s3_accel_start(8, 1, (val >> 16) & 0xff, 0, s3); + s3_accel_start(8, 1, (val >> 8) & 0xff, 0, s3); + s3_accel_start(8, 1, val & 0xff, 0, s3); + } + else if (s3->accel.cmd & 0x400) + { + if (s3->accel.cmd & 0x1000) + val = ((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24); + s3_accel_start(32, 1, val, 0, s3); + } + else if ((s3->accel.cmd & 0x600) == 0x200) + { + if (s3->accel.cmd & 0x1000) + val = ((val & 0xff00ff00) >> 8) | ((val & 0x00ff00ff) << 8); + s3_accel_start(16, 1, val, 0, s3); + s3_accel_start(16, 1, val >> 16, 0, s3); + } + else + { + if (s3->accel.cmd & 0x1000) + val = ((val & 0xff00ff00) >> 8) | ((val & 0x00ff00ff) << 8); + s3_accel_start(8, 1, val, 0, s3); + s3_accel_start(8, 1, val >> 16, 0, s3); + } + } + else + { + if (s3->accel.cmd & 0x400) + s3_accel_start(4, 1, 0xffffffff, val, s3); + else if ((s3->accel.cmd & 0x600) == 0x200) + { + s3_accel_start(2, 1, 0xffffffff, val, s3); + s3_accel_start(2, 1, 0xffffffff, val >> 16, s3); + } + else + { + s3_accel_start(1, 1, 0xffffffff, val, s3); + s3_accel_start(1, 1, 0xffffffff, val >> 16, s3); + } + } + } + } } static void fifo_thread(void *param) { - s3_t *s3 = (s3_t *)param; - - while (1) - { - thread_set_event(s3->fifo_not_full_event); - thread_wait_event(s3->wake_fifo_thread, -1); - thread_reset_event(s3->wake_fifo_thread); - s3->blitter_busy = 1; - while (!FIFO_EMPTY) - { - uint64_t start_time = plat_timer_read(); - uint64_t end_time; - fifo_entry_t *fifo = &s3->fifo[s3->fifo_read_idx & FIFO_MASK]; + s3_t *s3 = (s3_t *)param; + + while (1) + { + thread_set_event(s3->fifo_not_full_event); + thread_wait_event(s3->wake_fifo_thread, -1); + thread_reset_event(s3->wake_fifo_thread); + s3->blitter_busy = 1; + while (!FIFO_EMPTY) + { + uint64_t start_time = plat_timer_read(); + uint64_t end_time; + fifo_entry_t *fifo = &s3->fifo[s3->fifo_read_idx & FIFO_MASK]; - switch (fifo->addr_type & FIFO_TYPE) - { - case FIFO_WRITE_BYTE: - s3_accel_write_fifo(s3, fifo->addr_type & FIFO_ADDR, fifo->val); - break; - case FIFO_WRITE_WORD: - s3_accel_write_fifo_w(s3, fifo->addr_type & FIFO_ADDR, fifo->val); - break; - case FIFO_WRITE_DWORD: - s3_accel_write_fifo_l(s3, fifo->addr_type & FIFO_ADDR, fifo->val); - break; - case FIFO_OUT_BYTE: - s3_accel_out_fifo(s3, fifo->addr_type & FIFO_ADDR, fifo->val); - break; - case FIFO_OUT_WORD: - s3_accel_out_fifo_w(s3, fifo->addr_type & FIFO_ADDR, fifo->val); - break; - case FIFO_OUT_DWORD: - s3_accel_out_fifo_l(s3, fifo->addr_type & FIFO_ADDR, fifo->val); - break; - } - - s3->fifo_read_idx++; - fifo->addr_type = FIFO_INVALID; + switch (fifo->addr_type & FIFO_TYPE) + { + case FIFO_WRITE_BYTE: + s3_accel_write_fifo(s3, fifo->addr_type & FIFO_ADDR, fifo->val); + break; + case FIFO_WRITE_WORD: + s3_accel_write_fifo_w(s3, fifo->addr_type & FIFO_ADDR, fifo->val); + break; + case FIFO_WRITE_DWORD: + s3_accel_write_fifo_l(s3, fifo->addr_type & FIFO_ADDR, fifo->val); + break; + case FIFO_OUT_BYTE: + s3_accel_out_fifo(s3, fifo->addr_type & FIFO_ADDR, fifo->val); + break; + case FIFO_OUT_WORD: + s3_accel_out_fifo_w(s3, fifo->addr_type & FIFO_ADDR, fifo->val); + break; + case FIFO_OUT_DWORD: + s3_accel_out_fifo_l(s3, fifo->addr_type & FIFO_ADDR, fifo->val); + break; + } + + s3->fifo_read_idx++; + fifo->addr_type = FIFO_INVALID; - if (FIFO_ENTRIES > 0xe000) - thread_set_event(s3->fifo_not_full_event); + if (FIFO_ENTRIES > 0xe000) + thread_set_event(s3->fifo_not_full_event); - end_time = plat_timer_read(); - s3->blitter_time += end_time - start_time; - } - s3->blitter_busy = 0; - s3->subsys_stat |= INT_FIFO_EMP; - s3_update_irqs(s3); - } + end_time = plat_timer_read(); + s3->blitter_time += end_time - start_time; + } + s3->blitter_busy = 0; + s3->subsys_stat |= INT_FIFO_EMP; + s3_update_irqs(s3); + } } static void s3_vblank_start(svga_t *svga) { - s3_t *s3 = (s3_t *)svga->p; + s3_t *s3 = (s3_t *)svga->p; - s3->subsys_stat |= INT_VSY; - s3_update_irqs(s3); + s3->subsys_stat |= INT_VSY; + s3_update_irqs(s3); } static void s3_queue(s3_t *s3, uint32_t addr, uint32_t val, uint32_t type) { - fifo_entry_t *fifo = &s3->fifo[s3->fifo_write_idx & FIFO_MASK]; + fifo_entry_t *fifo = &s3->fifo[s3->fifo_write_idx & FIFO_MASK]; - if (FIFO_FULL) - { - thread_reset_event(s3->fifo_not_full_event); - if (FIFO_FULL) - { - thread_wait_event(s3->fifo_not_full_event, -1); /*Wait for room in ringbuffer*/ - } - } + if (FIFO_FULL) + { + thread_reset_event(s3->fifo_not_full_event); + if (FIFO_FULL) + { + thread_wait_event(s3->fifo_not_full_event, -1); /*Wait for room in ringbuffer*/ + } + } - fifo->val = val; - fifo->addr_type = (addr & FIFO_ADDR) | type; + fifo->val = val; + fifo->addr_type = (addr & FIFO_ADDR) | type; - s3->fifo_write_idx++; - - if (FIFO_ENTRIES > 0xe000 || FIFO_ENTRIES < 8) - wake_fifo_thread(s3); + s3->fifo_write_idx++; + + if (FIFO_ENTRIES > 0xe000 || FIFO_ENTRIES < 8) + wake_fifo_thread(s3); } void s3_out(uint16_t addr, uint8_t val, void *p) { - s3_t *s3 = (s3_t *)p; - svga_t *svga = &s3->svga; - uint8_t old; + s3_t *s3 = (s3_t *)p; + svga_t *svga = &s3->svga; + uint8_t old; + int rs2, rs3; - if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) - addr ^= 0x60; + if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) + addr ^= 0x60; - switch (addr) - { - case 0x3c5: - if (svga->seqaddr >= 0x10 && svga->seqaddr < 0x20) - { - svga->seqregs[svga->seqaddr] = val; - switch (svga->seqaddr) - { - case 0x12: case 0x13: - svga_recalctimings(svga); - return; - } - } - if (svga->seqaddr == 4) /*Chain-4 - update banking*/ - { - if (val & 8) - svga->write_bank = svga->read_bank = s3->bank << 16; - else - svga->write_bank = svga->read_bank = s3->bank << 14; - } + switch (addr) + { + case 0x3c2: + if (s3->chip == S3_VISION964) { + if (((val >> 2) & 3) != 3) + icd2061_write(&s3->icd2061, (val >> 2) & 3); + } break; - - case 0x3C6: case 0x3C7: case 0x3C8: case 0x3C9: - if (s3->chip == S3_TRIO32 || s3->chip == S3_TRIO64) - svga_out(addr, val, svga); - else - { - if ((svga->crtc[0x55] & 1) || (svga->crtc[0x43] & 2)) - sdac_ramdac_out((addr & 3) | 4, val, &s3->ramdac, svga); - else - sdac_ramdac_out(addr & 3, val, &s3->ramdac, svga); - } - return; - case 0x3D4: - svga->crtcreg = val & 0x7f; - return; - case 0x3D5: - if ((svga->crtcreg < 7) && (svga->crtc[0x11] & 0x80)) - return; - if ((svga->crtcreg == 7) && (svga->crtc[0x11] & 0x80)) - val = (svga->crtc[7] & ~0x10) | (val & 0x10); - if (svga->crtcreg >= 0x20 && svga->crtcreg != 0x38 && (svga->crtc[0x38] & 0xcc) != 0x48) return; - old = svga->crtc[svga->crtcreg]; - svga->crtc[svga->crtcreg] = val; - switch (svga->crtcreg) - { - case 0x31: - s3->ma_ext = (s3->ma_ext & 0x1c) | ((val & 0x30) >> 4); - break; - case 0x32: - svga->vram_display_mask = (val & 0x40) ? 0x3ffff : s3->vram_mask; - break; - - case 0x50: - switch (svga->crtc[0x50] & 0xc1) - { - case 0x00: s3->width = (svga->crtc[0x31] & 2) ? 2048 : 1024; break; - case 0x01: s3->width = 1152; break; - case 0x40: s3->width = 640; break; - case 0x80: s3->width = 800; break; - case 0x81: s3->width = 1600; break; - case 0xc0: s3->width = 1280; break; - } - s3->bpp = (svga->crtc[0x50] >> 4) & 3; - break; - case 0x69: - s3->ma_ext = val & 0x1f; - break; - - case 0x35: - s3->bank = (s3->bank & 0x70) | (val & 0xf); - if (svga->chain4) - svga->write_bank = svga->read_bank = s3->bank << 16; - else - svga->write_bank = svga->read_bank = s3->bank << 14; - break; - case 0x51: - s3->bank = (s3->bank & 0x4f) | ((val & 0xc) << 2); - if (svga->chain4) - svga->write_bank = svga->read_bank = s3->bank << 16; - else - svga->write_bank = svga->read_bank = s3->bank << 14; - s3->ma_ext = (s3->ma_ext & ~0xc) | ((val & 3) << 2); - break; - case 0x6a: - s3->bank = val; - if (svga->chain4) - svga->write_bank = svga->read_bank = s3->bank << 16; - else - svga->write_bank = svga->read_bank = s3->bank << 14; - break; - - case 0x3a: - if (val & 0x10) - svga->gdcreg[5] |= 0x40; /*Horrible cheat*/ - break; - - case 0x45: - svga->hwcursor.ena = val & 1; - break; - case 0x48: - svga->hwcursor.x = ((svga->crtc[0x46] << 8) | svga->crtc[0x47]) & 0x7ff; - if (svga->bpp == 32) svga->hwcursor.x >>= 1; - svga->hwcursor.y = ((svga->crtc[0x48] << 8) | svga->crtc[0x49]) & 0x7ff; - svga->hwcursor.xoff = svga->crtc[0x4e] & 63; - svga->hwcursor.yoff = svga->crtc[0x4f] & 63; - svga->hwcursor.addr = ((((svga->crtc[0x4c] << 8) | svga->crtc[0x4d]) & 0xfff) * 1024) + (svga->hwcursor.yoff * 16); - if ((s3->chip == S3_TRIO32 || s3->chip == S3_TRIO64) && svga->bpp == 32) - svga->hwcursor.x <<= 1; - break; + case 0x3c5: + if (svga->seqaddr >= 0x10 && svga->seqaddr < 0x20) + { + svga->seqregs[svga->seqaddr] = val; + switch (svga->seqaddr) + { + case 0x12: case 0x13: + svga_recalctimings(svga); + return; + } + } + if (svga->seqaddr == 4) /*Chain-4 - update banking*/ + { + if (val & 8) + svga->write_bank = svga->read_bank = s3->bank << 16; + else + svga->write_bank = svga->read_bank = s3->bank << 14; + } + break; + + case 0x3C6: case 0x3C7: case 0x3C8: case 0x3C9: + if ((svga->crtc[0x55] & 0x03) == 0x00) + rs2 = !!(svga->crtc[0x43] & 2); + else + rs2 = (svga->crtc[0x55] & 0x01); + if (s3->chip == S3_TRIO32 || s3->chip == S3_TRIO64) + svga_out(addr, val, svga); + else if (s3->chip == S3_VISION964) { + if (!(svga->crtc[0x45] & 0x02)) + rs3 = !!(svga->crtc[0x55] & 0x02); + else + rs3 = 0; + bt48x_ramdac_out(addr, rs2, rs3, val, svga->ramdac, svga); + } else + sdac_ramdac_out(addr, rs2, val, svga->ramdac, svga); + return; - case 0x4a: - switch (s3->hwc_col_stack_pos) - { - case 0: - s3->hwc_fg_col = (s3->hwc_fg_col & 0xffff00) | val; - break; - case 1: - s3->hwc_fg_col = (s3->hwc_fg_col & 0xff00ff) | (val << 8); - break; - case 2: - s3->hwc_fg_col = (s3->hwc_fg_col & 0x00ffff) | (val << 16); - break; - } - s3->hwc_col_stack_pos = (s3->hwc_col_stack_pos + 1) % 3; - break; - case 0x4b: - switch (s3->hwc_col_stack_pos) - { - case 0: - s3->hwc_bg_col = (s3->hwc_bg_col & 0xffff00) | val; - break; - case 1: - s3->hwc_bg_col = (s3->hwc_bg_col & 0xff00ff) | (val << 8); - break; - case 2: - s3->hwc_bg_col = (s3->hwc_bg_col & 0x00ffff) | (val << 16); - break; - } - s3->hwc_col_stack_pos = (s3->hwc_col_stack_pos + 1) % 3; - break; + case 0x3D4: + svga->crtcreg = val & 0x7f; + return; + case 0x3D5: + if ((svga->crtcreg < 7) && (svga->crtc[0x11] & 0x80)) + return; + if ((svga->crtcreg == 7) && (svga->crtc[0x11] & 0x80)) + val = (svga->crtc[7] & ~0x10) | (val & 0x10); + if (svga->crtcreg >= 0x20 && svga->crtcreg != 0x38 && (svga->crtc[0x38] & 0xcc) != 0x48) return; + old = svga->crtc[svga->crtcreg]; + svga->crtc[svga->crtcreg] = val; + switch (svga->crtcreg) + { + case 0x31: + s3->ma_ext = (s3->ma_ext & 0x1c) | ((val & 0x30) >> 4); + break; + case 0x32: + svga->vram_display_mask = (val & 0x40) ? 0x3ffff : s3->vram_mask; + break; - case 0x53: - case 0x58: case 0x59: case 0x5a: - s3_updatemapping(s3); - break; - - case 0x67: - if (s3->chip == S3_TRIO32 || s3->chip == S3_TRIO64) - { - switch (val >> 4) - { - case 3: svga->bpp = 15; break; - case 5: svga->bpp = 16; break; - case 7: svga->bpp = 24; break; - case 13: svga->bpp = 32; break; - default: svga->bpp = 8; break; - } - } - break; - } - if (old != val) - { - if (svga->crtcreg < 0xe || svga->crtcreg > 0x10) - { - svga->fullchange = changeframecount; - svga_recalctimings(svga); - } - } - break; - } - svga_out(addr, val, svga); + case 0x50: + switch (svga->crtc[0x50] & 0xc1) + { + case 0x00: s3->width = (svga->crtc[0x31] & 2) ? 2048 : 1024; break; + case 0x01: s3->width = 1152; break; + case 0x40: s3->width = 640; break; + case 0x80: s3->width = 800; break; + case 0x81: s3->width = 1600; break; + case 0xc0: s3->width = 1280; break; + } + s3->bpp = (svga->crtc[0x50] >> 4) & 3; + break; + case 0x69: + s3->ma_ext = val & 0x1f; + break; + + case 0x35: + s3->bank = (s3->bank & 0x70) | (val & 0xf); + if (svga->chain4) + svga->write_bank = svga->read_bank = s3->bank << 16; + else + svga->write_bank = svga->read_bank = s3->bank << 14; + break; + case 0x51: + s3->bank = (s3->bank & 0x4f) | ((val & 0xc) << 2); + if (svga->chain4) + svga->write_bank = svga->read_bank = s3->bank << 16; + else + svga->write_bank = svga->read_bank = s3->bank << 14; + s3->ma_ext = (s3->ma_ext & ~0xc) | ((val & 3) << 2); + break; + case 0x6a: + s3->bank = val; + if (svga->chain4) + svga->write_bank = svga->read_bank = s3->bank << 16; + else + svga->write_bank = svga->read_bank = s3->bank << 14; + break; + + case 0x3a: + if (val & 0x10) + svga->gdcreg[5] |= 0x40; /*Horrible cheat*/ + break; + + case 0x45: + if (s3->chip == S3_VISION964) + break; + svga->hwcursor.ena = val & 1; + break; + case 0x48: + if (s3->chip == S3_VISION964) + break; + svga->hwcursor.x = ((svga->crtc[0x46] << 8) | svga->crtc[0x47]) & 0x7ff; + if (svga->bpp == 32) svga->hwcursor.x >>= 1; + svga->hwcursor.y = ((svga->crtc[0x48] << 8) | svga->crtc[0x49]) & 0x7ff; + svga->hwcursor.xoff = svga->crtc[0x4e] & 63; + svga->hwcursor.yoff = svga->crtc[0x4f] & 63; + svga->hwcursor.addr = ((((svga->crtc[0x4c] << 8) | svga->crtc[0x4d]) & 0xfff) * 1024) + (svga->hwcursor.yoff * 16); + if ((s3->chip == S3_TRIO32 || s3->chip == S3_TRIO64) && svga->bpp == 32) + svga->hwcursor.x <<= 1; + break; + + case 0x4a: + switch (s3->hwc_col_stack_pos) + { + case 0: + s3->hwc_fg_col = (s3->hwc_fg_col & 0xffff00) | val; + break; + case 1: + s3->hwc_fg_col = (s3->hwc_fg_col & 0xff00ff) | (val << 8); + break; + case 2: + s3->hwc_fg_col = (s3->hwc_fg_col & 0x00ffff) | (val << 16); + break; + } + s3->hwc_col_stack_pos = (s3->hwc_col_stack_pos + 1) % 3; + break; + case 0x4b: + switch (s3->hwc_col_stack_pos) + { + case 0: + s3->hwc_bg_col = (s3->hwc_bg_col & 0xffff00) | val; + break; + case 1: + s3->hwc_bg_col = (s3->hwc_bg_col & 0xff00ff) | (val << 8); + break; + case 2: + s3->hwc_bg_col = (s3->hwc_bg_col & 0x00ffff) | (val << 16); + break; + } + s3->hwc_col_stack_pos = (s3->hwc_col_stack_pos + 1) % 3; + break; + + case 0x53: + case 0x58: case 0x59: case 0x5a: + s3_updatemapping(s3); + break; + + case 0x42: + if (s3->chip == S3_VISION964) { + if (((svga->miscout >> 2) & 3) == 3) + icd2061_write(&s3->icd2061, svga->crtc[0x42] & 0x0f); + } + break; + + case 0x67: + if (s3->chip == S3_TRIO32 || s3->chip == S3_TRIO64) + { + switch (val >> 4) + { + case 3: svga->bpp = 15; break; + case 5: svga->bpp = 16; break; + case 7: svga->bpp = 24; break; + case 13: svga->bpp = 32; break; + default: svga->bpp = 8; break; + } + } + break; + } + if (old != val) + { + if (svga->crtcreg < 0xe || svga->crtcreg > 0x10) + { + svga->fullchange = changeframecount; + svga_recalctimings(svga); + } + } + break; + } + svga_out(addr, val, svga); } uint8_t s3_in(uint16_t addr, void *p) { - s3_t *s3 = (s3_t *)p; - svga_t *svga = &s3->svga; + s3_t *s3 = (s3_t *)p; + svga_t *svga = &s3->svga; + int rs2, rs3; + uint8_t temp; - if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) - addr ^= 0x60; + if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) + addr ^= 0x60; - switch (addr) - { - case 0x3c1: - if (svga->attraddr > 0x14) - return 0xff; - break; - - case 0x3c5: - if (svga->seqaddr >= 0x10 && svga->seqaddr < 0x20) - return svga->seqregs[svga->seqaddr]; - break; - - case 0x3c6: case 0x3c7: case 0x3c8: case 0x3c9: - if (s3->chip == S3_TRIO32 || s3->chip == S3_TRIO64) - return svga_in(addr, svga); - if ((svga->crtc[0x55] & 1) || (svga->crtc[0x43] & 2)) - return sdac_ramdac_in((addr & 3) | 4, &s3->ramdac, svga); - return sdac_ramdac_in(addr & 3, &s3->ramdac, svga); + switch (addr) + { + case 0x3c1: + if (svga->attraddr > 0x14) + return 0xff; + break; - case 0x3d4: - return svga->crtcreg; - case 0x3d5: - switch (svga->crtcreg) - { - case 0x2d: return 0x88; /*Extended chip ID*/ - case 0x2e: return s3->id_ext; /*New chip ID*/ - case 0x2f: return 0; /*Revision level*/ - case 0x30: return s3->id; /*Chip ID*/ - case 0x31: return (svga->crtc[0x31] & 0xcf) | ((s3->ma_ext & 3) << 4); - case 0x35: return (svga->crtc[0x35] & 0xf0) | (s3->bank & 0xf); - case 0x45: s3->hwc_col_stack_pos = 0; break; - case 0x51: return (svga->crtc[0x51] & 0xf0) | ((s3->bank >> 2) & 0xc) | ((s3->ma_ext >> 2) & 3); - case 0x69: return s3->ma_ext; - case 0x6a: return s3->bank; - } - return svga->crtc[svga->crtcreg]; - } - return svga_in(addr, svga); + case 0x3c5: + if (svga->seqaddr >= 0x10 && svga->seqaddr < 0x20) + return svga->seqregs[svga->seqaddr]; + break; + + case 0x3c6: case 0x3c7: case 0x3c8: case 0x3c9: + rs2 = (svga->crtc[0x55] & 0x01) || !!(svga->crtc[0x43] & 2); + if (s3->chip == S3_TRIO32 || s3->chip == S3_TRIO64) + return svga_in(addr, svga); + else if (s3->chip == S3_VISION964) { + rs3 = !!(svga->crtc[0x55] & 0x02); + return bt48x_ramdac_in(addr, rs2, rs3, svga->ramdac, svga); + } else + return sdac_ramdac_in(addr, rs2, svga->ramdac, svga); + break; + + case 0x3d4: + return svga->crtcreg; + case 0x3d5: + switch (svga->crtcreg) + { + case 0x2d: return 0x88; /*Extended chip ID*/ + case 0x2e: return s3->id_ext; /*New chip ID*/ + case 0x2f: return 0; /*Revision level*/ + case 0x30: return s3->id; /*Chip ID*/ + case 0x31: return (svga->crtc[0x31] & 0xcf) | ((s3->ma_ext & 3) << 4); + case 0x35: return (svga->crtc[0x35] & 0xf0) | (s3->bank & 0xf); + case 0x45: s3->hwc_col_stack_pos = 0; break; + case 0x51: return (svga->crtc[0x51] & 0xf0) | ((s3->bank >> 2) & 0xc) | ((s3->ma_ext >> 2) & 3); + case 0x5c: /* General Output Port Register */ + temp = svga->crtc[svga->crtcreg] & 0xf0; + if (((svga->miscout >> 2) & 3) == 3) + temp |= svga->crtc[0x42] & 0x0f; + else + temp |= ((svga->miscout >> 2) & 3); + return temp; + case 0x69: return s3->ma_ext; + case 0x6a: return s3->bank; + } + return svga->crtc[svga->crtcreg]; + } + return svga_in(addr, svga); } void s3_recalctimings(svga_t *svga) { - s3_t *s3 = (s3_t *)svga->p; - svga->hdisp = svga->hdisp_old; + s3_t *s3 = (s3_t *)svga->p; + bt48x_ramdac_t *ramdac = (bt48x_ramdac_t *)svga->ramdac; - svga->ma_latch |= (s3->ma_ext << 16); - if (svga->crtc[0x5d] & 0x01) svga->htotal += 0x100; - if (svga->crtc[0x5d] & 0x02) - { - svga->hdisp_time += 0x100; - svga->hdisp += 0x100 * ((svga->seqregs[1] & 8) ? 16 : 8); - } - if (svga->crtc[0x5e] & 0x01) svga->vtotal += 0x400; - if (svga->crtc[0x5e] & 0x02) svga->dispend += 0x400; - if (svga->crtc[0x5e] & 0x04) svga->vblankstart += 0x400; - if (svga->crtc[0x5e] & 0x10) svga->vsyncstart += 0x400; - if (svga->crtc[0x5e] & 0x40) svga->split += 0x400; - if (svga->crtc[0x51] & 0x30) svga->rowoffset += (svga->crtc[0x51] & 0x30) << 4; - else if (svga->crtc[0x43] & 0x04) svga->rowoffset += 0x100; - if (!svga->rowoffset) svga->rowoffset = 256; - svga->interlace = svga->crtc[0x42] & 0x20; - svga->clock = cpuclock / s3->getclock((svga->miscout >> 2) & 3, s3->getclock_p); + svga->hdisp = svga->hdisp_old; - switch (svga->crtc[0x67] >> 4) - { - case 3: case 5: case 7: - svga->clock /= 2; - break; - } + svga->ma_latch |= (s3->ma_ext << 16); + if (svga->crtc[0x5d] & 0x01) svga->htotal += 0x100; + if (svga->crtc[0x5d] & 0x02) + { + svga->hdisp_time += 0x100; + svga->hdisp += 0x100 * ((svga->seqregs[1] & 8) ? 16 : 8); + } + if (svga->crtc[0x5e] & 0x01) svga->vtotal += 0x400; + if (svga->crtc[0x5e] & 0x02) svga->dispend += 0x400; + if (svga->crtc[0x5e] & 0x04) svga->vblankstart += 0x400; + if (svga->crtc[0x5e] & 0x10) svga->vsyncstart += 0x400; + if (svga->crtc[0x5e] & 0x40) svga->split += 0x400; + if (svga->crtc[0x51] & 0x30) svga->rowoffset += (svga->crtc[0x51] & 0x30) << 4; + else if (svga->crtc[0x43] & 0x04) svga->rowoffset += 0x100; + if (!svga->rowoffset) svga->rowoffset = 256; - svga->lowres = !((svga->gdcreg[5] & 0x40) && (svga->crtc[0x3a] & 0x10)); - if ((svga->gdcreg[5] & 0x40) && (svga->crtc[0x3a] & 0x10)) - { - switch (svga->bpp) - { - case 8: - svga->render = svga_render_8bpp_highres; - break; - case 15: - svga->render = svga_render_15bpp_highres; - svga->hdisp /= 2; - break; - case 16: - svga->render = svga_render_16bpp_highres; - svga->hdisp /= 2; - break; - case 24: - svga->render = svga_render_24bpp_highres; - svga->hdisp /= 3; - break; - case 32: - svga->render = svga_render_32bpp_highres; - if (s3->chip != S3_TRIO32 && s3->chip != S3_TRIO64) - svga->hdisp /= 4; - break; - } - } + if (s3->chip == S3_VISION964) { + svga->interlace = ramdac->cr2 & 0x08; + if (ramdac->cr3 & 0x08) + svga->hdisp *= 2; /* x2 clock multiplier */ + if (((svga->miscout >> 2) & 3) == 3) + svga->clock = cpuclock / svga->getclock(svga->crtc[0x42] & 0x0f, svga->clock_gen); + else + svga->clock = cpuclock / svga->getclock((svga->miscout >> 2) & 3, svga->clock_gen); + } else { + svga->interlace = svga->crtc[0x42] & 0x20; + svga->clock = cpuclock / svga->getclock((svga->miscout >> 2) & 3, svga->clock_gen); + } + + switch (svga->crtc[0x67] >> 4) + { + case 3: case 5: case 7: + svga->clock /= 2; + break; + } + + svga->lowres = !((svga->gdcreg[5] & 0x40) && (svga->crtc[0x3a] & 0x10)); + if ((svga->gdcreg[5] & 0x40) && (svga->crtc[0x3a] & 0x10)) + { + switch (svga->bpp) + { + case 8: + svga->render = svga_render_8bpp_highres; + break; + case 15: + svga->render = svga_render_15bpp_highres; + if (s3->chip != S3_VISION964) + svga->hdisp /= 2; + break; + case 16: + svga->render = svga_render_16bpp_highres; + if (s3->chip != S3_VISION964) + svga->hdisp /= 2; + break; + case 24: + svga->render = svga_render_24bpp_highres; + svga->hdisp /= 3; + break; + case 32: + svga->render = svga_render_32bpp_highres; + if ((s3->chip != S3_TRIO32) && (s3->chip != S3_TRIO64) && (s3->chip != S3_VISION964)) + svga->hdisp /= 4; + break; + } + } } void s3_updatemapping(s3_t *s3) { - svga_t *svga = &s3->svga; - - if (!(s3->pci_regs[PCI_REG_COMMAND] & PCI_COMMAND_MEM)) - { - mem_mapping_disable(&svga->mapping); - mem_mapping_disable(&s3->linear_mapping); - mem_mapping_disable(&s3->mmio_mapping); - return; - } + svga_t *svga = &s3->svga; + + if (!(s3->pci_regs[PCI_REG_COMMAND] & PCI_COMMAND_MEM)) + { + mem_map_disable(&svga->mapping); + mem_map_disable(&s3->linear_mapping); + mem_map_disable(&s3->mmio_mapping); + return; + } /*Banked framebuffer*/ - if (svga->crtc[0x31] & 0x08) /*Enhanced mode mappings*/ - { + if (svga->crtc[0x31] & 0x08) /*Enhanced mode mappings*/ + { /* Enhanced mode forces 64kb at 0xa0000*/ - mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000); - svga->banked_mask = 0xffff; - } - else switch (svga->gdcreg[6] & 0xc) /*VGA mapping*/ - { - case 0x0: /*128k at A0000*/ - mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x20000); - svga->banked_mask = 0xffff; - break; - case 0x4: /*64k at A0000*/ - mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000); - svga->banked_mask = 0xffff; - break; - case 0x8: /*32k at B0000*/ - mem_mapping_set_addr(&svga->mapping, 0xb0000, 0x08000); - svga->banked_mask = 0x7fff; - break; - case 0xC: /*32k at B8000*/ - mem_mapping_set_addr(&svga->mapping, 0xb8000, 0x08000); - svga->banked_mask = 0x7fff; - break; - } - - if (svga->crtc[0x58] & 0x10) /*Linear framebuffer*/ - { - mem_mapping_disable(&svga->mapping); - - s3->linear_base = (svga->crtc[0x5a] << 16) | (svga->crtc[0x59] << 24); - switch (svga->crtc[0x58] & 3) - { - case 0: /*64k*/ - s3->linear_size = 0x10000; - break; - case 1: /*1mb*/ - s3->linear_size = 0x100000; - break; - case 2: /*2mb*/ - s3->linear_size = 0x200000; - break; - case 3: /*8mb*/ - s3->linear_size = 0x800000; - break; - } - s3->linear_base &= ~(s3->linear_size - 1); - svga->linear_base = s3->linear_base; - if (s3->linear_base == 0xa0000) - { - mem_mapping_disable(&s3->linear_mapping); - if (!(svga->crtc[0x53] & 0x10)) - { - mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000); - svga->banked_mask = 0xffff; - } - } - else - mem_mapping_set_addr(&s3->linear_mapping, s3->linear_base, s3->linear_size); - } - else - mem_mapping_disable(&s3->linear_mapping); - - if (svga->crtc[0x53] & 0x10) /*Memory mapped IO*/ - { - mem_mapping_disable(&svga->mapping); - mem_mapping_enable(&s3->mmio_mapping); - } - else - mem_mapping_disable(&s3->mmio_mapping); + mem_map_set_addr(&svga->mapping, 0xa0000, 0x10000); + svga->banked_mask = 0xffff; + } + else switch (svga->gdcreg[6] & 0xc) /*VGA mapping*/ + { + case 0x0: /*128k at A0000*/ + mem_map_set_addr(&svga->mapping, 0xa0000, 0x20000); + svga->banked_mask = 0xffff; + break; + case 0x4: /*64k at A0000*/ + mem_map_set_addr(&svga->mapping, 0xa0000, 0x10000); + svga->banked_mask = 0xffff; + break; + case 0x8: /*32k at B0000*/ + mem_map_set_addr(&svga->mapping, 0xb0000, 0x08000); + svga->banked_mask = 0x7fff; + break; + case 0xC: /*32k at B8000*/ + mem_map_set_addr(&svga->mapping, 0xb8000, 0x08000); + svga->banked_mask = 0x7fff; + break; + } + + if (svga->crtc[0x58] & 0x10) /*Linear framebuffer*/ + { + mem_map_disable(&svga->mapping); + + s3->linear_base = (svga->crtc[0x5a] << 16) | (svga->crtc[0x59] << 24); + switch (svga->crtc[0x58] & 3) + { + case 0: /*64k*/ + s3->linear_size = 0x10000; + break; + case 1: /*1mb*/ + s3->linear_size = 0x100000; + break; + case 2: /*2mb*/ + s3->linear_size = 0x200000; + break; + case 3: /*8mb*/ + switch (s3->chip) { + case S3_TRIO32: + case S3_TRIO64: + s3->linear_size = 0x400000; + break; + default: + s3->linear_size = 0x800000; + break; + } + break; + } + s3->linear_base &= ~(s3->linear_size - 1); + if (s3->linear_base == 0xa0000) + { + mem_map_disable(&s3->linear_mapping); + if (!(svga->crtc[0x53] & 0x10)) + { + mem_map_set_addr(&svga->mapping, 0xa0000, 0x10000); + svga->banked_mask = 0xffff; + } + } + else + mem_map_set_addr(&s3->linear_mapping, s3->linear_base, s3->linear_size); + } + else + mem_map_disable(&s3->linear_mapping); + + /* Memory mapped I/O. */ + if (svga->crtc[0x53] & 0x10) { + /* Old MMIO. */ + mem_map_disable(&svga->mapping); + mem_map_enable(&s3->mmio_mapping); + } else + mem_map_disable(&s3->mmio_mapping); } static float s3_trio64_getclock(int clock, void *p) { - s3_t *s3 = (s3_t *)p; - svga_t *svga = &s3->svga; - float t; - int m, n1, n2; - if (clock == 0) return 25175000.0; - if (clock == 1) return 28322000.0; - m = svga->seqregs[0x13] + 2; - n1 = (svga->seqregs[0x12] & 0x1f) + 2; - n2 = ((svga->seqregs[0x12] >> 5) & 0x07); - t = (14318184.0f * (float)m / (float)n1) / (float)(1 << n2); - return t; + s3_t *s3 = (s3_t *)p; + svga_t *svga = &s3->svga; + float t; + int m, n1, n2; + if (clock == 0) return 25175000.0; + if (clock == 1) return 28322000.0; + m = svga->seqregs[0x13] + 2; + n1 = (svga->seqregs[0x12] & 0x1f) + 2; + n2 = ((svga->seqregs[0x12] >> 5) & 0x07); + t = (float)((float)14318184.0 * ((float)m / (float)n1)) / (float)(1 << n2); + return t; } void s3_accel_out(uint16_t port, uint8_t val, void *p) { - s3_t *s3 = (s3_t *)p; - - if (port >= 0x8000) - { - s3_queue(s3, port, val, FIFO_OUT_BYTE); - } - else switch (port) - { - case 0x42e8: - s3->subsys_stat &= ~val; - s3_update_irqs(s3); - break; - case 0x42e9: - s3->subsys_cntl = val; - s3_update_irqs(s3); - break; - case 0x46e8: - s3->accel.setup_md = val; - break; - case 0x4ae8: - s3->accel.advfunc_cntl = val; - break; - } + s3_t *s3 = (s3_t *)p; + + if (port >= 0x8000) + { + s3_queue(s3, port, val, FIFO_OUT_BYTE); + } + else switch (port) + { + case 0x42e8: + s3->subsys_stat &= ~val; + s3_update_irqs(s3); + break; + case 0x42e9: + s3->subsys_cntl = val; + s3_update_irqs(s3); + break; + case 0x46e8: + s3->accel.setup_md = val; + break; + case 0x4ae8: + s3->accel.advfunc_cntl = val; + break; + } } void s3_accel_out_w(uint16_t port, uint16_t val, void *p) { - s3_t *s3 = (s3_t *)p; - s3_queue(s3, port, val, FIFO_OUT_WORD); + s3_t *s3 = (s3_t *)p; + s3_queue(s3, port, val, FIFO_OUT_WORD); } void s3_accel_out_l(uint16_t port, uint32_t val, void *p) { - s3_t *s3 = (s3_t *)p; - s3_queue(s3, port, val, FIFO_OUT_DWORD); + s3_t *s3 = (s3_t *)p; + s3_queue(s3, port, val, FIFO_OUT_DWORD); } uint8_t s3_accel_in(uint16_t port, void *p) { - s3_t *s3 = (s3_t *)p; - int temp; - switch (port) - { - case 0x42e8: - return s3->subsys_stat; - case 0x42e9: - return s3->subsys_cntl; + s3_t *s3 = (s3_t *)p; + int temp; + switch (port) + { + case 0x42e8: + return s3->subsys_stat; + case 0x42e9: + return s3->subsys_cntl; - case 0x82e8: - s3_wait_fifo_idle(s3); - return s3->accel.cur_y & 0xff; - case 0x82e9: - s3_wait_fifo_idle(s3); - return s3->accel.cur_y >> 8; + case 0x82e8: + s3_wait_fifo_idle(s3); + return s3->accel.cur_y & 0xff; + case 0x82e9: + s3_wait_fifo_idle(s3); + return s3->accel.cur_y >> 8; - case 0x86e8: - s3_wait_fifo_idle(s3); - return s3->accel.cur_x & 0xff; - case 0x86e9: - s3_wait_fifo_idle(s3); - return s3->accel.cur_x >> 8; + case 0x86e8: + s3_wait_fifo_idle(s3); + return s3->accel.cur_x & 0xff; + case 0x86e9: + s3_wait_fifo_idle(s3); + return s3->accel.cur_x >> 8; - case 0x8ae8: - s3_wait_fifo_idle(s3); - return s3->accel.desty_axstp & 0xff; - case 0x8ae9: - s3_wait_fifo_idle(s3); - return s3->accel.desty_axstp >> 8; + case 0x8ae8: + s3_wait_fifo_idle(s3); + return s3->accel.desty_axstp & 0xff; + case 0x8ae9: + s3_wait_fifo_idle(s3); + return s3->accel.desty_axstp >> 8; - case 0x8ee8: - s3_wait_fifo_idle(s3); - return s3->accel.destx_distp & 0xff; - case 0x8ee9: - s3_wait_fifo_idle(s3); - return s3->accel.destx_distp >> 8; + case 0x8ee8: + s3_wait_fifo_idle(s3); + return s3->accel.destx_distp & 0xff; + case 0x8ee9: + s3_wait_fifo_idle(s3); + return s3->accel.destx_distp >> 8; - case 0x92e8: - s3_wait_fifo_idle(s3); - return s3->accel.err_term & 0xff; - case 0x92e9: - s3_wait_fifo_idle(s3); - return s3->accel.err_term >> 8; + case 0x92e8: + s3_wait_fifo_idle(s3); + return s3->accel.err_term & 0xff; + case 0x92e9: + s3_wait_fifo_idle(s3); + return s3->accel.err_term >> 8; - case 0x96e8: - s3_wait_fifo_idle(s3); - return s3->accel.maj_axis_pcnt & 0xff; - case 0x96e9: - s3_wait_fifo_idle(s3); - return s3->accel.maj_axis_pcnt >> 8; + case 0x96e8: + s3_wait_fifo_idle(s3); + return s3->accel.maj_axis_pcnt & 0xff; + case 0x96e9: + s3_wait_fifo_idle(s3); + return s3->accel.maj_axis_pcnt >> 8; - case 0x9ae8: - if (!s3->blitter_busy) - wake_fifo_thread(s3); - if (FIFO_FULL) - return 0xff; /*FIFO full*/ - return 0; /*FIFO empty*/ - case 0x9ae9: - if (!s3->blitter_busy) - wake_fifo_thread(s3); - temp = 0; - if (!FIFO_EMPTY) - temp |= 0x02; /*Hardware busy*/ - else - temp |= s3->status_9ae8; /*FIFO empty*/ - if (FIFO_FULL) - temp |= 0xf8; /*FIFO full*/ - return temp; + case 0x9ae8: + if (!s3->blitter_busy) + wake_fifo_thread(s3); + if (FIFO_FULL) + return 0xff; /*FIFO full*/ + return 0; /*FIFO empty*/ + case 0x9ae9: + if (!s3->blitter_busy) + wake_fifo_thread(s3); + temp = 0; + if (!FIFO_EMPTY) + temp |= 0x02; /*Hardware busy*/ + else + temp |= s3->status_9ae8; /*FIFO empty*/ + if (FIFO_FULL) + temp |= 0xf8; /*FIFO full*/ + return temp; - case 0xa2e8: - s3_wait_fifo_idle(s3); - return s3->accel.bkgd_color & 0xff; - case 0xa2e9: - s3_wait_fifo_idle(s3); - return s3->accel.bkgd_color >> 8; - case 0xa2ea: - s3_wait_fifo_idle(s3); - return s3->accel.bkgd_color >> 16; - case 0xa2eb: - s3_wait_fifo_idle(s3); - return s3->accel.bkgd_color >> 24; + case 0xa2e8: + s3_wait_fifo_idle(s3); + return s3->accel.bkgd_color & 0xff; + case 0xa2e9: + s3_wait_fifo_idle(s3); + return s3->accel.bkgd_color >> 8; + case 0xa2ea: + s3_wait_fifo_idle(s3); + return s3->accel.bkgd_color >> 16; + case 0xa2eb: + s3_wait_fifo_idle(s3); + return s3->accel.bkgd_color >> 24; - case 0xa6e8: - s3_wait_fifo_idle(s3); - return s3->accel.frgd_color & 0xff; - case 0xa6e9: - s3_wait_fifo_idle(s3); - return s3->accel.frgd_color >> 8; - case 0xa6ea: - s3_wait_fifo_idle(s3); - return s3->accel.frgd_color >> 16; - case 0xa6eb: - s3_wait_fifo_idle(s3); - return s3->accel.frgd_color >> 24; + case 0xa6e8: + s3_wait_fifo_idle(s3); + return s3->accel.frgd_color & 0xff; + case 0xa6e9: + s3_wait_fifo_idle(s3); + return s3->accel.frgd_color >> 8; + case 0xa6ea: + s3_wait_fifo_idle(s3); + return s3->accel.frgd_color >> 16; + case 0xa6eb: + s3_wait_fifo_idle(s3); + return s3->accel.frgd_color >> 24; - case 0xaae8: - s3_wait_fifo_idle(s3); - return s3->accel.wrt_mask & 0xff; - case 0xaae9: - s3_wait_fifo_idle(s3); - return s3->accel.wrt_mask >> 8; - case 0xaaea: - s3_wait_fifo_idle(s3); - return s3->accel.wrt_mask >> 16; - case 0xaaeb: - s3_wait_fifo_idle(s3); - return s3->accel.wrt_mask >> 24; + case 0xaae8: + s3_wait_fifo_idle(s3); + return s3->accel.wrt_mask & 0xff; + case 0xaae9: + s3_wait_fifo_idle(s3); + return s3->accel.wrt_mask >> 8; + case 0xaaea: + s3_wait_fifo_idle(s3); + return s3->accel.wrt_mask >> 16; + case 0xaaeb: + s3_wait_fifo_idle(s3); + return s3->accel.wrt_mask >> 24; - case 0xaee8: - s3_wait_fifo_idle(s3); - return s3->accel.rd_mask & 0xff; - case 0xaee9: - s3_wait_fifo_idle(s3); - return s3->accel.rd_mask >> 8; - case 0xaeea: - s3_wait_fifo_idle(s3); - return s3->accel.rd_mask >> 16; - case 0xaeeb: - s3_wait_fifo_idle(s3); - return s3->accel.rd_mask >> 24; + case 0xaee8: + s3_wait_fifo_idle(s3); + return s3->accel.rd_mask & 0xff; + case 0xaee9: + s3_wait_fifo_idle(s3); + return s3->accel.rd_mask >> 8; + case 0xaeea: + s3_wait_fifo_idle(s3); + return s3->accel.rd_mask >> 16; + case 0xaeeb: + s3_wait_fifo_idle(s3); + return s3->accel.rd_mask >> 24; - case 0xb2e8: - s3_wait_fifo_idle(s3); - return s3->accel.color_cmp & 0xff; - case 0xb2e9: - s3_wait_fifo_idle(s3); - return s3->accel.color_cmp >> 8; - case 0xb2ea: - s3_wait_fifo_idle(s3); - return s3->accel.color_cmp >> 16; - case 0xb2eb: - s3_wait_fifo_idle(s3); - return s3->accel.color_cmp >> 24; + case 0xb2e8: + s3_wait_fifo_idle(s3); + return s3->accel.color_cmp & 0xff; + case 0xb2e9: + s3_wait_fifo_idle(s3); + return s3->accel.color_cmp >> 8; + case 0xb2ea: + s3_wait_fifo_idle(s3); + return s3->accel.color_cmp >> 16; + case 0xb2eb: + s3_wait_fifo_idle(s3); + return s3->accel.color_cmp >> 24; - case 0xb6e8: - s3_wait_fifo_idle(s3); - return s3->accel.bkgd_mix; + case 0xb6e8: + s3_wait_fifo_idle(s3); + return s3->accel.bkgd_mix; - case 0xbae8: - s3_wait_fifo_idle(s3); - return s3->accel.frgd_mix; + case 0xbae8: + s3_wait_fifo_idle(s3); + return s3->accel.frgd_mix; - case 0xbee8: - s3_wait_fifo_idle(s3); - temp = s3->accel.multifunc[0xf] & 0xf; - switch (temp) - { - case 0x0: return s3->accel.multifunc[0x0] & 0xff; - case 0x1: return s3->accel.multifunc[0x1] & 0xff; - case 0x2: return s3->accel.multifunc[0x2] & 0xff; - case 0x3: return s3->accel.multifunc[0x3] & 0xff; - case 0x4: return s3->accel.multifunc[0x4] & 0xff; - case 0x5: return s3->accel.multifunc[0xa] & 0xff; - case 0x6: return s3->accel.multifunc[0xe] & 0xff; - case 0x7: return s3->accel.cmd & 0xff; - case 0x8: return s3->accel.subsys_cntl & 0xff; - case 0x9: return s3->accel.setup_md & 0xff; - case 0xa: return s3->accel.multifunc[0xd] & 0xff; - } - return 0xff; - case 0xbee9: - s3_wait_fifo_idle(s3); - temp = s3->accel.multifunc[0xf] & 0xf; - s3->accel.multifunc[0xf]++; - switch (temp) - { - case 0x0: return s3->accel.multifunc[0x0] >> 8; - case 0x1: return s3->accel.multifunc[0x1] >> 8; - case 0x2: return s3->accel.multifunc[0x2] >> 8; - case 0x3: return s3->accel.multifunc[0x3] >> 8; - case 0x4: return s3->accel.multifunc[0x4] >> 8; - case 0x5: return s3->accel.multifunc[0xa] >> 8; - case 0x6: return s3->accel.multifunc[0xe] >> 8; - case 0x7: return s3->accel.cmd >> 8; - case 0x8: return (s3->accel.subsys_cntl >> 8) & ~0xe000; - case 0x9: return (s3->accel.setup_md >> 8) & ~0xf000; - case 0xa: return s3->accel.multifunc[0xd] >> 8; - } - return 0xff; + case 0xbee8: + s3_wait_fifo_idle(s3); + temp = s3->accel.multifunc[0xf] & 0xf; + switch (temp) + { + case 0x0: return s3->accel.multifunc[0x0] & 0xff; + case 0x1: return s3->accel.multifunc[0x1] & 0xff; + case 0x2: return s3->accel.multifunc[0x2] & 0xff; + case 0x3: return s3->accel.multifunc[0x3] & 0xff; + case 0x4: return s3->accel.multifunc[0x4] & 0xff; + case 0x5: return s3->accel.multifunc[0xa] & 0xff; + case 0x6: return s3->accel.multifunc[0xe] & 0xff; + case 0x7: return s3->accel.cmd & 0xff; + case 0x8: return s3->accel.subsys_cntl & 0xff; + case 0x9: return s3->accel.setup_md & 0xff; + case 0xa: return s3->accel.multifunc[0xd] & 0xff; + } + return 0xff; + case 0xbee9: + s3_wait_fifo_idle(s3); + temp = s3->accel.multifunc[0xf] & 0xf; + s3->accel.multifunc[0xf]++; + switch (temp) + { + case 0x0: return s3->accel.multifunc[0x0] >> 8; + case 0x1: return s3->accel.multifunc[0x1] >> 8; + case 0x2: return s3->accel.multifunc[0x2] >> 8; + case 0x3: return s3->accel.multifunc[0x3] >> 8; + case 0x4: return s3->accel.multifunc[0x4] >> 8; + case 0x5: return s3->accel.multifunc[0xa] >> 8; + case 0x6: return s3->accel.multifunc[0xe] >> 8; + case 0x7: return s3->accel.cmd >> 8; + case 0x8: return (s3->accel.subsys_cntl >> 8) & ~0xe000; + case 0x9: return (s3->accel.setup_md >> 8) & ~0xf000; + case 0xa: return s3->accel.multifunc[0xd] >> 8; + } + return 0xff; - case 0xe2e8: case 0xe2e9: case 0xe2ea: case 0xe2eb: /*PIX_TRANS*/ - break; - } - return 0; + case 0xe2e8: case 0xe2e9: case 0xe2ea: case 0xe2eb: /*PIX_TRANS*/ + break; + } + return 0; } void s3_accel_write(uint32_t addr, uint8_t val, void *p) { - s3_t *s3 = (s3_t *)p; - s3_queue(s3, addr & 0xffff, val, FIFO_WRITE_BYTE); + s3_t *s3 = (s3_t *)p; + s3_queue(s3, addr & 0xffff, val, FIFO_WRITE_BYTE); } void s3_accel_write_w(uint32_t addr, uint16_t val, void *p) { - s3_t *s3 = (s3_t *)p; - s3_queue(s3, addr & 0xffff, val, FIFO_WRITE_WORD); + s3_t *s3 = (s3_t *)p; + s3_queue(s3, addr & 0xffff, val, FIFO_WRITE_WORD); } void s3_accel_write_l(uint32_t addr, uint32_t val, void *p) { - s3_t *s3 = (s3_t *)p; - s3_queue(s3, addr & 0xffff, val, FIFO_WRITE_DWORD); + s3_t *s3 = (s3_t *)p; + s3_queue(s3, addr & 0xffff, val, FIFO_WRITE_DWORD); } uint8_t s3_accel_read(uint32_t addr, void *p) { - if (addr & 0x8000) - return s3_accel_in(addr & 0xffff, p); - return 0; + if (addr & 0x8000) + return s3_accel_in(addr & 0xffff, p); + return 0; } -#define READ(addr, dat) if (s3->bpp == 0) dat = svga->vram[ (addr) & s3->vram_mask]; \ - else if (s3->bpp == 1) dat = vram_w[(addr) & (s3->vram_mask >> 1)]; \ - else dat = vram_l[(addr) & (s3->vram_mask >> 2)]; +static void polygon_setup(s3_t *s3) +{ + if (s3->accel.point_1_updated) + { + int start_x = s3->accel.poly_cx; + int start_y = s3->accel.poly_cy; + int end_x = s3->accel.destx_distp << 20; + int end_y = s3->accel.desty_axstp; + + if (end_y - start_y) + s3->accel.poly_dx1 = (end_x - start_x) / (end_y - start_y); + else + s3->accel.poly_dx1 = 0; + + s3->accel.point_1_updated = 0; -#define MIX switch ((mix_dat & mix_mask) ? (s3->accel.frgd_mix & 0xf) : (s3->accel.bkgd_mix & 0xf)) \ - { \ - case 0x0: dest_dat = ~dest_dat; break; \ - case 0x1: dest_dat = 0; break; \ - case 0x2: dest_dat = ~0; break; \ - case 0x3: dest_dat = dest_dat; break; \ - case 0x4: dest_dat = ~src_dat; break; \ - case 0x5: dest_dat = src_dat ^ dest_dat; break; \ - case 0x6: dest_dat = ~(src_dat ^ dest_dat); break; \ - case 0x7: dest_dat = src_dat; break; \ - case 0x8: dest_dat = ~(src_dat & dest_dat); break; \ - case 0x9: dest_dat = ~src_dat | dest_dat; break; \ - case 0xa: dest_dat = src_dat | ~dest_dat; break; \ - case 0xb: dest_dat = src_dat | dest_dat; break; \ - case 0xc: dest_dat = src_dat & dest_dat; break; \ - case 0xd: dest_dat = src_dat & ~dest_dat; break; \ - case 0xe: dest_dat = ~src_dat & dest_dat; break; \ - case 0xf: dest_dat = ~(src_dat | dest_dat); break; \ - } + if (end_y == s3->accel.poly_cy) + { + s3->accel.poly_cx = end_x; + s3->accel.poly_x = end_x >> 20; + } + } + if (s3->accel.point_2_updated) + { + int start_x = s3->accel.poly_cx2; + int start_y = s3->accel.poly_cy2; + int end_x = s3->accel.x2 << 20; + int end_y = s3->accel.desty_axstp2; + + if (end_y - start_y) + s3->accel.poly_dx2 = (end_x - start_x) / (end_y - start_y); + else + s3->accel.poly_dx2 = 0; + + s3->accel.point_2_updated = 0; + + if (end_y == s3->accel.poly_cy) + s3->accel.poly_cx2 = end_x; + } +} + +#define READ_SRC(addr, dat) if (s3->bpp == 0) dat = svga->vram[ (addr) & s3->vram_mask]; \ + else if (s3->bpp == 1) dat = vram_w[(addr) & (s3->vram_mask >> 1)]; \ + else dat = vram_l[(addr) & (s3->vram_mask >> 2)]; \ + if (vram_mask) \ + dat = ((dat & rd_mask) == rd_mask); + +#define READ_DST(addr, dat) if (s3->bpp == 0) dat = svga->vram[ (addr) & s3->vram_mask]; \ + else if (s3->bpp == 1) dat = vram_w[(addr) & (s3->vram_mask >> 1)]; \ + else dat = vram_l[(addr) & (s3->vram_mask >> 2)]; + +#define MIX { \ + uint32_t old_dest_dat = dest_dat; \ + switch ((mix_dat & mix_mask) ? (s3->accel.frgd_mix & 0xf) : (s3->accel.bkgd_mix & 0xf)) \ + { \ + case 0x0: dest_dat = ~dest_dat; break; \ + case 0x1: dest_dat = 0; break; \ + case 0x2: dest_dat = ~0; break; \ + case 0x3: dest_dat = dest_dat; break; \ + case 0x4: dest_dat = ~src_dat; break; \ + case 0x5: dest_dat = src_dat ^ dest_dat; break; \ + case 0x6: dest_dat = ~(src_dat ^ dest_dat); break; \ + case 0x7: dest_dat = src_dat; break; \ + case 0x8: dest_dat = ~(src_dat & dest_dat); break; \ + case 0x9: dest_dat = ~src_dat | dest_dat; break; \ + case 0xa: dest_dat = src_dat | ~dest_dat; break; \ + case 0xb: dest_dat = src_dat | dest_dat; break; \ + case 0xc: dest_dat = src_dat & dest_dat; break; \ + case 0xd: dest_dat = src_dat & ~dest_dat; break; \ + case 0xe: dest_dat = ~src_dat & dest_dat; break; \ + case 0xf: dest_dat = ~(src_dat | dest_dat); break; \ + } \ + dest_dat = (dest_dat & s3->accel.wrt_mask) | (old_dest_dat & ~s3->accel.wrt_mask); \ + } -#define WRITE(addr) if (s3->bpp == 0) \ - { \ - svga->vram[(addr) & s3->vram_mask] = dest_dat; \ - svga->changedvram[((addr) & s3->vram_mask) >> 12] = changeframecount; \ - } \ - else if (s3->bpp == 1) \ - { \ - vram_w[(addr) & (s3->vram_mask >> 1)] = dest_dat; \ - svga->changedvram[((addr) & (s3->vram_mask >> 1)) >> 11] = changeframecount; \ - } \ - else \ - { \ - vram_l[(addr) & (s3->vram_mask >> 2)] = dest_dat; \ - svga->changedvram[((addr) & (s3->vram_mask >> 2)) >> 10] = changeframecount; \ - } +#define WRITE(addr) if (s3->bpp == 0) \ + { \ + svga->vram[(addr) & s3->vram_mask] = dest_dat; \ + svga->changedvram[((addr) & s3->vram_mask) >> 12] = changeframecount; \ + } \ + else if (s3->bpp == 1) \ + { \ + vram_w[(addr) & (s3->vram_mask >> 1)] = dest_dat; \ + svga->changedvram[((addr) & (s3->vram_mask >> 1)) >> 11] = changeframecount; \ + } \ + else \ + { \ + vram_l[(addr) & (s3->vram_mask >> 2)] = dest_dat; \ + svga->changedvram[((addr) & (s3->vram_mask >> 2)) >> 10] = changeframecount; \ + } void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_t *s3) { - svga_t *svga = &s3->svga; - uint32_t src_dat = 0, dest_dat; - int frgd_mix, bkgd_mix; - int clip_t = s3->accel.multifunc[1] & 0xfff; - int clip_l = s3->accel.multifunc[2] & 0xfff; - int clip_b = s3->accel.multifunc[3] & 0xfff; - int clip_r = s3->accel.multifunc[4] & 0xfff; - int vram_mask = (s3->accel.multifunc[0xa] & 0xc0) == 0xc0; - uint32_t mix_mask = 0; - uint16_t *vram_w = (uint16_t *)svga->vram; - uint32_t *vram_l = (uint32_t *)svga->vram; - uint32_t compare = s3->accel.color_cmp; - int compare_mode = (s3->accel.multifunc[0xe] >> 7) & 3; + svga_t *svga = &s3->svga; + uint32_t src_dat = 0, dest_dat; + int frgd_mix, bkgd_mix; + int clip_t = s3->accel.multifunc[1] & 0xfff; + int clip_l = s3->accel.multifunc[2] & 0xfff; + int clip_b = s3->accel.multifunc[3] & 0xfff; + int clip_r = s3->accel.multifunc[4] & 0xfff; + int vram_mask = (s3->accel.multifunc[0xa] & 0xc0) == 0xc0; + uint32_t mix_mask = 0; + uint16_t *vram_w = (uint16_t *)svga->vram; + uint32_t *vram_l = (uint32_t *)svga->vram; + uint32_t compare = s3->accel.color_cmp; + int compare_mode = (s3->accel.multifunc[0xe] >> 7) & 3; + uint32_t rd_mask = s3->accel.rd_mask; + int cmd = s3->accel.cmd >> 13; + + if ((s3->chip == S3_TRIO64) && (s3->accel.cmd & (1 << 11))) + cmd |= 8; - if (!cpu_input) s3->accel.dat_count = 0; - if (cpu_input && (s3->accel.multifunc[0xa] & 0xc0) != 0x80) - { - if (s3->bpp == 3 && count == 2) - { - if (s3->accel.dat_count) - { - cpu_dat = ((cpu_dat & 0xffff) << 16) | s3->accel.dat_buf; - count = 4; - s3->accel.dat_count = 0; - } - else - { - s3->accel.dat_buf = cpu_dat & 0xffff; - s3->accel.dat_count = 1; - } - } - if (s3->bpp == 1) count >>= 1; - if (s3->bpp == 3) count >>= 2; - } - - switch (s3->accel.cmd & 0x600) - { - case 0x000: mix_mask = 0x80; break; - case 0x200: mix_mask = 0x8000; break; - case 0x400: mix_mask = 0x80000000; break; - case 0x600: mix_mask = 0x80000000; break; - } + if (!cpu_input) s3->accel.dat_count = 0; + if (cpu_input && (s3->accel.multifunc[0xa] & 0xc0) != 0x80) + { + if (s3->bpp == 3 && count == 2) + { + if (s3->accel.dat_count) + { + cpu_dat = ((cpu_dat & 0xffff) << 16) | s3->accel.dat_buf; + count = 4; + s3->accel.dat_count = 0; + } + else + { + s3->accel.dat_buf = cpu_dat & 0xffff; + s3->accel.dat_count = 1; + } + } + if (s3->bpp == 1) count >>= 1; + if (s3->bpp == 3) count >>= 2; + } - if (s3->bpp == 0) compare &= 0xff; - if (s3->bpp == 1) compare &= 0xffff; - switch (s3->accel.cmd >> 13) - { - case 1: /*Draw line*/ - if (!cpu_input) /*!cpu_input is trigger to start operation*/ - { - s3->accel.cx = s3->accel.cur_x; - if (s3->accel.cur_x & 0x1000) s3->accel.cx |= ~0xfff; - s3->accel.cy = s3->accel.cur_y; - if (s3->accel.cur_y & 0x1000) s3->accel.cy |= ~0xfff; - - s3->accel.sy = s3->accel.maj_axis_pcnt; - } - if ((s3->accel.cmd & 0x100) && !cpu_input) return; /*Wait for data from CPU*/ + if (s3->bpp == 0) + rd_mask &= 0xff; + else if (s3->bpp == 1) + rd_mask &= 0xffff; - frgd_mix = (s3->accel.frgd_mix >> 5) & 3; - bkgd_mix = (s3->accel.bkgd_mix >> 5) & 3; + switch (s3->accel.cmd & 0x600) + { + case 0x000: mix_mask = 0x80; break; + case 0x200: mix_mask = 0x8000; break; + case 0x400: mix_mask = 0x80000000; break; + case 0x600: mix_mask = (s3->chip == S3_TRIO32) ? 0x80 : 0x80000000; break; + } - if (s3->accel.cmd & 8) /*Radial*/ - { - while (count-- && s3->accel.sy >= 0) - { - if (s3->accel.cx >= clip_l && s3->accel.cx <= clip_r && - s3->accel.cy >= clip_t && s3->accel.cy <= clip_b) - { - switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) - { - case 0: src_dat = s3->accel.bkgd_color; break; - case 1: src_dat = s3->accel.frgd_color; break; - case 2: src_dat = cpu_dat; break; - case 3: src_dat = 0; break; - } + if (s3->bpp == 0) compare &= 0xff; + if (s3->bpp == 1) compare &= 0xffff; + switch (cmd) + { + case 1: /*Draw line*/ + if (!cpu_input) /*!cpu_input is trigger to start operation*/ + { + s3->accel.cx = s3->accel.cur_x; + if (s3->accel.cur_x & 0x1000) s3->accel.cx |= ~0xfff; + s3->accel.cy = s3->accel.cur_y; + if (s3->accel.cur_y & 0x1000) s3->accel.cy |= ~0xfff; + + s3->accel.sy = s3->accel.maj_axis_pcnt; + } - if ((compare_mode == 2 && src_dat != compare) || - (compare_mode == 3 && src_dat == compare) || - compare_mode < 2) - { - READ((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat); + s3->status_9ae8 = 4; /*To avoid the spam from OS/2's drivers*/ - MIX + if ((s3->accel.cmd & 0x100) && !cpu_input) + { + s3->status_9ae8 = 2; /*To avoid the spam from OS/2's drivers*/ + return; /*Wait for data from CPU*/ + } - WRITE((s3->accel.cy * s3->width) + s3->accel.cx); - } - } + if ((s3->accel.cmd & 0x100) && !cpu_input) return; /*Wait for data from CPU*/ - mix_dat <<= 1; - mix_dat |= 1; - if (s3->bpp == 0) cpu_dat >>= 8; - else cpu_dat >>= 16; - if (!s3->accel.sy) - break; + frgd_mix = (s3->accel.frgd_mix >> 5) & 3; + bkgd_mix = (s3->accel.bkgd_mix >> 5) & 3; - switch (s3->accel.cmd & 0xe0) - { - case 0x00: s3->accel.cx++; break; - case 0x20: s3->accel.cx++; s3->accel.cy--; break; - case 0x40: s3->accel.cy--; break; - case 0x60: s3->accel.cx--; s3->accel.cy--; break; - case 0x80: s3->accel.cx--; break; - case 0xa0: s3->accel.cx--; s3->accel.cy++; break; - case 0xc0: s3->accel.cy++; break; - case 0xe0: s3->accel.cx++; s3->accel.cy++; break; - } - s3->accel.sy--; - } - s3->accel.cur_x = s3->accel.cx; - s3->accel.cur_y = s3->accel.cy; - } - else /*Bresenham*/ - { - while (count-- && s3->accel.sy >= 0) - { - if (s3->accel.cx >= clip_l && s3->accel.cx <= clip_r && - s3->accel.cy >= clip_t && s3->accel.cy <= clip_b) - { - switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) - { - case 0: src_dat = s3->accel.bkgd_color; break; - case 1: src_dat = s3->accel.frgd_color; break; - case 2: src_dat = cpu_dat; break; - case 3: src_dat = 0; break; - } - - if ((compare_mode == 2 && src_dat != compare) || - (compare_mode == 3 && src_dat == compare) || - compare_mode < 2) - { - READ((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat); - - MIX - - WRITE((s3->accel.cy * s3->width) + s3->accel.cx); - } - } - - mix_dat <<= 1; - mix_dat |= 1; - if (s3->bpp == 0) cpu_dat >>= 8; - else cpu_dat >>= 16; - - if (!s3->accel.sy) - break; - - if (s3->accel.err_term >= s3->accel.maj_axis_pcnt) - { - s3->accel.err_term += s3->accel.destx_distp; - /*Step minor axis*/ - switch (s3->accel.cmd & 0xe0) - { - case 0x00: s3->accel.cy--; break; - case 0x20: s3->accel.cy--; break; - case 0x40: s3->accel.cx--; break; - case 0x60: s3->accel.cx++; break; - case 0x80: s3->accel.cy++; break; - case 0xa0: s3->accel.cy++; break; - case 0xc0: s3->accel.cx--; break; - case 0xe0: s3->accel.cx++; break; - } - } - else - s3->accel.err_term += s3->accel.desty_axstp; - - /*Step major axis*/ - switch (s3->accel.cmd & 0xe0) - { - case 0x00: s3->accel.cx--; break; - case 0x20: s3->accel.cx++; break; - case 0x40: s3->accel.cy--; break; - case 0x60: s3->accel.cy--; break; - case 0x80: s3->accel.cx--; break; - case 0xa0: s3->accel.cx++; break; - case 0xc0: s3->accel.cy++; break; - case 0xe0: s3->accel.cy++; break; - } - s3->accel.sy--; - } - s3->accel.cur_x = s3->accel.cx; - s3->accel.cur_y = s3->accel.cy; - } - break; - - case 2: /*Rectangle fill*/ - if (!cpu_input) /*!cpu_input is trigger to start operation*/ - { - s3->accel.sx = s3->accel.maj_axis_pcnt & 0xfff; - s3->accel.sy = s3->accel.multifunc[0] & 0xfff; - s3->accel.cx = s3->accel.cur_x; - if (s3->accel.cur_x & 0x1000) s3->accel.cx |= ~0xfff; - s3->accel.cy = s3->accel.cur_y; - if (s3->accel.cur_y & 0x1000) s3->accel.cy |= ~0xfff; - - s3->accel.dest = s3->accel.cy * s3->width; - } - - s3->status_9ae8 = 4; /*To avoid the spam from OS/2's drivers*/ - - if ((s3->accel.cmd & 0x100) && !cpu_input) + if (s3->accel.cmd & 8) /*Radial*/ + { + while (count-- && s3->accel.sy >= 0) + { + if (s3->accel.cx >= clip_l && s3->accel.cx <= clip_r && + s3->accel.cy >= clip_t && s3->accel.cy <= clip_b) { - s3->status_9ae8 = 2; /*To avoid the spam from OS/2's drivers*/ - return; /*Wait for data from CPU*/ - } + switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) + { + case 0: src_dat = s3->accel.bkgd_color; break; + case 1: src_dat = s3->accel.frgd_color; break; + case 2: src_dat = cpu_dat; break; + case 3: src_dat = 0; break; + } + + if ((compare_mode == 2 && src_dat != compare) || + (compare_mode == 3 && src_dat == compare) || + compare_mode < 2) + { + READ_DST((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat); + + MIX + + WRITE((s3->accel.cy * s3->width) + s3->accel.cx); + } + } + + mix_dat <<= 1; + mix_dat |= 1; + if (s3->bpp == 0) cpu_dat >>= 8; + else cpu_dat >>= 16; + if (!s3->accel.sy) + break; + + switch (s3->accel.cmd & 0xe0) + { + case 0x00: s3->accel.cx++; break; + case 0x20: s3->accel.cx++; s3->accel.cy--; break; + case 0x40: s3->accel.cy--; break; + case 0x60: s3->accel.cx--; s3->accel.cy--; break; + case 0x80: s3->accel.cx--; break; + case 0xa0: s3->accel.cx--; s3->accel.cy++; break; + case 0xc0: s3->accel.cy++; break; + case 0xe0: s3->accel.cx++; s3->accel.cy++; break; + } + s3->accel.sy--; + } + s3->accel.cur_x = s3->accel.cx; + s3->accel.cur_y = s3->accel.cy; + } + else /*Bresenham*/ + { + while (count-- && s3->accel.sy >= 0) + { + if (s3->accel.cx >= clip_l && s3->accel.cx <= clip_r && + s3->accel.cy >= clip_t && s3->accel.cy <= clip_b) + { + switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) + { + case 0: src_dat = s3->accel.bkgd_color; break; + case 1: src_dat = s3->accel.frgd_color; break; + case 2: src_dat = cpu_dat; break; + case 3: src_dat = 0; break; + } + + if ((compare_mode == 2 && src_dat != compare) || + (compare_mode == 3 && src_dat == compare) || + compare_mode < 2) + { + READ_DST((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat); + + MIX + + WRITE((s3->accel.cy * s3->width) + s3->accel.cx); + } + } + + mix_dat <<= 1; + mix_dat |= 1; + if (s3->bpp == 0) cpu_dat >>= 8; + else cpu_dat >>= 16; + + if (!s3->accel.sy) + break; + + if (s3->accel.err_term >= s3->accel.maj_axis_pcnt) + { + s3->accel.err_term += s3->accel.destx_distp; + /*Step minor axis*/ + switch (s3->accel.cmd & 0xe0) + { + case 0x00: s3->accel.cy--; break; + case 0x20: s3->accel.cy--; break; + case 0x40: s3->accel.cx--; break; + case 0x60: s3->accel.cx++; break; + case 0x80: s3->accel.cy++; break; + case 0xa0: s3->accel.cy++; break; + case 0xc0: s3->accel.cx--; break; + case 0xe0: s3->accel.cx++; break; + } + } + else + s3->accel.err_term += s3->accel.desty_axstp; + + /*Step major axis*/ + switch (s3->accel.cmd & 0xe0) + { + case 0x00: s3->accel.cx--; break; + case 0x20: s3->accel.cx++; break; + case 0x40: s3->accel.cy--; break; + case 0x60: s3->accel.cy--; break; + case 0x80: s3->accel.cx--; break; + case 0xa0: s3->accel.cx++; break; + case 0xc0: s3->accel.cy++; break; + case 0xe0: s3->accel.cy++; break; + } + s3->accel.sy--; + } + s3->accel.cur_x = s3->accel.cx; + s3->accel.cur_y = s3->accel.cy; + } + break; + + case 2: /*Rectangle fill*/ + if (!cpu_input) /*!cpu_input is trigger to start operation*/ + { + s3->accel.sx = s3->accel.maj_axis_pcnt & 0xfff; + s3->accel.sy = s3->accel.multifunc[0] & 0xfff; + s3->accel.cx = s3->accel.cur_x; + if (s3->accel.cur_x & 0x1000) s3->accel.cx |= ~0xfff; + s3->accel.cy = s3->accel.cur_y; + if (s3->accel.cur_y & 0x1000) s3->accel.cy |= ~0xfff; + + s3->accel.dest = s3->accel.cy * s3->width; + } + + s3->status_9ae8 = 4; /*To avoid the spam from OS/2's drivers*/ + + if ((s3->accel.cmd & 0x100) && !cpu_input) + { + s3->status_9ae8 = 2; /*To avoid the spam from OS/2's drivers*/ + return; /*Wait for data from CPU*/ + } + + if ((s3->accel.cmd & 0x100) && !cpu_input) return; /*Wait for data from CPU*/ + + frgd_mix = (s3->accel.frgd_mix >> 5) & 3; + bkgd_mix = (s3->accel.bkgd_mix >> 5) & 3; - if ((s3->accel.cmd & 0x100) && !cpu_input) return; /*Wait for data from CPU*/ + while (count-- && s3->accel.sy >= 0) + { + if (s3->accel.cx >= clip_l && s3->accel.cx <= clip_r && + s3->accel.cy >= clip_t && s3->accel.cy <= clip_b) + { + switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) + { + case 0: src_dat = s3->accel.bkgd_color; break; + case 1: src_dat = s3->accel.frgd_color; break; + case 2: src_dat = cpu_dat; break; + case 3: src_dat = 0; break; + } - frgd_mix = (s3->accel.frgd_mix >> 5) & 3; - bkgd_mix = (s3->accel.bkgd_mix >> 5) & 3; + if ((compare_mode == 2 && src_dat != compare) || + (compare_mode == 3 && src_dat == compare) || + compare_mode < 2) + { + READ_DST(s3->accel.dest + s3->accel.cx, dest_dat); + + MIX + + WRITE(s3->accel.dest + s3->accel.cx); + } + } + + mix_dat <<= 1; + mix_dat |= 1; + if (s3->bpp == 0) cpu_dat >>= 8; + else cpu_dat >>= 16; + + if (s3->accel.cmd & 0x20) s3->accel.cx++; + else s3->accel.cx--; + s3->accel.sx--; + if (s3->accel.sx < 0) + { + if (s3->accel.cmd & 0x20) s3->accel.cx -= (s3->accel.maj_axis_pcnt & 0xfff) + 1; + else s3->accel.cx += (s3->accel.maj_axis_pcnt & 0xfff) + 1; + s3->accel.sx = s3->accel.maj_axis_pcnt & 0xfff; + + if (s3->accel.cmd & 0x80) s3->accel.cy++; + else s3->accel.cy--; - while (count-- && s3->accel.sy >= 0) - { - if (s3->accel.cx >= clip_l && s3->accel.cx <= clip_r && - s3->accel.cy >= clip_t && s3->accel.cy <= clip_b) - { - switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) - { - case 0: src_dat = s3->accel.bkgd_color; break; - case 1: src_dat = s3->accel.frgd_color; break; - case 2: src_dat = cpu_dat; break; - case 3: src_dat = 0; break; - } + s3->accel.dest = s3->accel.cy * s3->width; + s3->accel.sy--; - if ((compare_mode == 2 && src_dat != compare) || - (compare_mode == 3 && src_dat == compare) || - compare_mode < 2) - { - READ(s3->accel.dest + s3->accel.cx, dest_dat); + if (cpu_input/* && (s3->accel.multifunc[0xa] & 0xc0) == 0x80*/) return; + if (s3->accel.sy < 0) + { + s3->accel.cur_x = s3->accel.cx; + s3->accel.cur_y = s3->accel.cy; + return; + } + } + } + break; - MIX + case 6: /*BitBlt*/ + if (!cpu_input) /*!cpu_input is trigger to start operation*/ + { + s3->accel.sx = s3->accel.maj_axis_pcnt & 0xfff; + s3->accel.sy = s3->accel.multifunc[0] & 0xfff; - WRITE(s3->accel.dest + s3->accel.cx); - } - } - - mix_dat <<= 1; - mix_dat |= 1; - if (s3->bpp == 0) cpu_dat >>= 8; - else cpu_dat >>= 16; - - if (s3->accel.cmd & 0x20) s3->accel.cx++; - else s3->accel.cx--; - s3->accel.sx--; - if (s3->accel.sx < 0) - { - if (s3->accel.cmd & 0x20) s3->accel.cx -= (s3->accel.maj_axis_pcnt & 0xfff) + 1; - else s3->accel.cx += (s3->accel.maj_axis_pcnt & 0xfff) + 1; - s3->accel.sx = s3->accel.maj_axis_pcnt & 0xfff; + s3->accel.dx = s3->accel.destx_distp & 0xfff; + if (s3->accel.destx_distp & 0x1000) s3->accel.dx |= ~0xfff; + s3->accel.dy = s3->accel.desty_axstp & 0xfff; + if (s3->accel.desty_axstp & 0x1000) s3->accel.dy |= ~0xfff; - if (s3->accel.cmd & 0x80) s3->accel.cy++; - else s3->accel.cy--; - - s3->accel.dest = s3->accel.cy * s3->width; - s3->accel.sy--; + s3->accel.cx = s3->accel.cur_x & 0xfff; + if (s3->accel.cur_x & 0x1000) s3->accel.cx |= ~0xfff; + s3->accel.cy = s3->accel.cur_y & 0xfff; + if (s3->accel.cur_y & 0x1000) s3->accel.cy |= ~0xfff; - if (cpu_input/* && (s3->accel.multifunc[0xa] & 0xc0) == 0x80*/) return; - if (s3->accel.sy < 0) - { - s3->accel.cur_x = s3->accel.cx; - s3->accel.cur_y = s3->accel.cy; - return; - } - } - } - break; + s3->accel.src = s3->accel.cy * s3->width; + s3->accel.dest = s3->accel.dy * s3->width; + } - case 6: /*BitBlt*/ - if (!cpu_input) /*!cpu_input is trigger to start operation*/ - { - s3->accel.sx = s3->accel.maj_axis_pcnt & 0xfff; - s3->accel.sy = s3->accel.multifunc[0] & 0xfff; + s3->status_9ae8 = 4; /*To avoid the spam from OS/2's drivers*/ - s3->accel.dx = s3->accel.destx_distp & 0xfff; - if (s3->accel.destx_distp & 0x1000) s3->accel.dx |= ~0xfff; - s3->accel.dy = s3->accel.desty_axstp & 0xfff; - if (s3->accel.desty_axstp & 0x1000) s3->accel.dy |= ~0xfff; + if ((s3->accel.cmd & 0x100) && !cpu_input) + { + s3->status_9ae8 = 2; /*To avoid the spam from OS/2's drivers*/ + return; /*Wait for data from CPU*/ + } - s3->accel.cx = s3->accel.cur_x & 0xfff; - if (s3->accel.cur_x & 0x1000) s3->accel.cx |= ~0xfff; - s3->accel.cy = s3->accel.cur_y & 0xfff; - if (s3->accel.cur_y & 0x1000) s3->accel.cy |= ~0xfff; + if ((s3->accel.cmd & 0x100) && !cpu_input) return; /*Wait for data from CPU*/ - s3->accel.src = s3->accel.cy * s3->width; - s3->accel.dest = s3->accel.dy * s3->width; - } - if ((s3->accel.cmd & 0x100) && !cpu_input) return; /*Wait for data from CPU*/ + if (s3->accel.sy < 0) + return; - if (s3->accel.sy < 0) - return; - - frgd_mix = (s3->accel.frgd_mix >> 5) & 3; - bkgd_mix = (s3->accel.bkgd_mix >> 5) & 3; - - if (!cpu_input && frgd_mix == 3 && !vram_mask && !compare_mode && - (s3->accel.cmd & 0xa0) == 0xa0 && (s3->accel.frgd_mix & 0xf) == 7 && + frgd_mix = (s3->accel.frgd_mix >> 5) & 3; + bkgd_mix = (s3->accel.bkgd_mix >> 5) & 3; + + if (!cpu_input && frgd_mix == 3 && !vram_mask && !compare_mode && + (s3->accel.cmd & 0xa0) == 0xa0 && (s3->accel.frgd_mix & 0xf) == 7 && (s3->accel.bkgd_mix & 0xf) == 7) - { - while (1) - { - if (s3->accel.dx >= clip_l && s3->accel.dx <= clip_r && - s3->accel.dy >= clip_t && s3->accel.dy <= clip_b) - { - READ(s3->accel.src + s3->accel.cx, src_dat); - - dest_dat = src_dat; - - WRITE(s3->accel.dest + s3->accel.dx); - } - - s3->accel.cx++; - s3->accel.dx++; - s3->accel.sx--; - if (s3->accel.sx < 0) - { - s3->accel.cx -= (s3->accel.maj_axis_pcnt & 0xfff) + 1; - s3->accel.dx -= (s3->accel.maj_axis_pcnt & 0xfff) + 1; - s3->accel.sx = s3->accel.maj_axis_pcnt & 0xfff; - - s3->accel.cy++; - s3->accel.dy++; - - s3->accel.src = s3->accel.cy * s3->width; - s3->accel.dest = s3->accel.dy * s3->width; - - s3->accel.sy--; - - if (s3->accel.sy < 0) - { - return; - } - } - } - } - else - { - while (count-- && s3->accel.sy >= 0) - { - if (s3->accel.dx >= clip_l && s3->accel.dx <= clip_r && - s3->accel.dy >= clip_t && s3->accel.dy <= clip_b) - { - if (vram_mask) - { - READ(s3->accel.src + s3->accel.cx, mix_dat) - mix_dat = mix_dat ? mix_mask : 0; - } - switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) - { - case 0: src_dat = s3->accel.bkgd_color; break; - case 1: src_dat = s3->accel.frgd_color; break; - case 2: src_dat = cpu_dat; break; - case 3: READ(s3->accel.src + s3->accel.cx, src_dat); break; - } + { + while (1) + { + if (s3->accel.dx >= clip_l && s3->accel.dx <= clip_r && + s3->accel.dy >= clip_t && s3->accel.dy <= clip_b) + { + READ_SRC(s3->accel.src + s3->accel.cx, src_dat); + READ_DST(s3->accel.dest + s3->accel.dx, dest_dat); - if ((compare_mode == 2 && src_dat != compare) || - (compare_mode == 3 && src_dat == compare) || - compare_mode < 2) - { - READ(s3->accel.dest + s3->accel.dx, dest_dat); + dest_dat = (src_dat & s3->accel.wrt_mask) | (dest_dat & ~s3->accel.wrt_mask); - MIX + WRITE(s3->accel.dest + s3->accel.dx); + } + + s3->accel.cx++; + s3->accel.dx++; + s3->accel.sx--; + if (s3->accel.sx < 0) + { + s3->accel.cx -= (s3->accel.maj_axis_pcnt & 0xfff) + 1; + s3->accel.dx -= (s3->accel.maj_axis_pcnt & 0xfff) + 1; + s3->accel.sx = s3->accel.maj_axis_pcnt & 0xfff; + + s3->accel.cy++; + s3->accel.dy++; + + s3->accel.src = s3->accel.cy * s3->width; + s3->accel.dest = s3->accel.dy * s3->width; + + s3->accel.sy--; + + if (s3->accel.sy < 0) + { + return; + } + } + } + } + else + { + while (count-- && s3->accel.sy >= 0) + { + if (s3->accel.dx >= clip_l && s3->accel.dx <= clip_r && + s3->accel.dy >= clip_t && s3->accel.dy <= clip_b) + { + if (vram_mask) + { + READ_SRC(s3->accel.src + s3->accel.cx, mix_dat) + mix_dat = mix_dat ? mix_mask : 0; + } + switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) + { + case 0: src_dat = s3->accel.bkgd_color; break; + case 1: src_dat = s3->accel.frgd_color; break; + case 2: src_dat = cpu_dat; break; + case 3: READ_SRC(s3->accel.src + s3->accel.cx, src_dat); break; + } - WRITE(s3->accel.dest + s3->accel.dx); - } - } + if ((compare_mode == 2 && src_dat != compare) || + (compare_mode == 3 && src_dat == compare) || + compare_mode < 2) + { + READ_DST(s3->accel.dest + s3->accel.dx, dest_dat); - mix_dat <<= 1; - mix_dat |= 1; - if (s3->bpp == 0) cpu_dat >>= 8; - else cpu_dat >>= 16; + MIX - if (s3->accel.cmd & 0x20) - { - s3->accel.cx++; - s3->accel.dx++; - } - else - { - s3->accel.cx--; - s3->accel.dx--; - } - s3->accel.sx--; - if (s3->accel.sx < 0) - { - if (s3->accel.cmd & 0x20) - { - s3->accel.cx -= (s3->accel.maj_axis_pcnt & 0xfff) + 1; - s3->accel.dx -= (s3->accel.maj_axis_pcnt & 0xfff) + 1; - } - else - { - s3->accel.cx += (s3->accel.maj_axis_pcnt & 0xfff) + 1; - s3->accel.dx += (s3->accel.maj_axis_pcnt & 0xfff) + 1; - } - s3->accel.sx = s3->accel.maj_axis_pcnt & 0xfff; + WRITE(s3->accel.dest + s3->accel.dx); + } + } - if (s3->accel.cmd & 0x80) - { - s3->accel.cy++; - s3->accel.dy++; - } - else - { - s3->accel.cy--; - s3->accel.dy--; - } + mix_dat <<= 1; + mix_dat |= 1; + if (s3->bpp == 0) cpu_dat >>= 8; + else cpu_dat >>= 16; - s3->accel.src = s3->accel.cy * s3->width; - s3->accel.dest = s3->accel.dy * s3->width; + if (s3->accel.cmd & 0x20) + { + s3->accel.cx++; + s3->accel.dx++; + } + else + { + s3->accel.cx--; + s3->accel.dx--; + } + s3->accel.sx--; + if (s3->accel.sx < 0) + { + if (s3->accel.cmd & 0x20) + { + s3->accel.cx -= (s3->accel.maj_axis_pcnt & 0xfff) + 1; + s3->accel.dx -= (s3->accel.maj_axis_pcnt & 0xfff) + 1; + } + else + { + s3->accel.cx += (s3->accel.maj_axis_pcnt & 0xfff) + 1; + s3->accel.dx += (s3->accel.maj_axis_pcnt & 0xfff) + 1; + } + s3->accel.sx = s3->accel.maj_axis_pcnt & 0xfff; - s3->accel.sy--; + if (s3->accel.cmd & 0x80) + { + s3->accel.cy++; + s3->accel.dy++; + } + else + { + s3->accel.cy--; + s3->accel.dy--; + } - if (cpu_input/* && (s3->accel.multifunc[0xa] & 0xc0) == 0x80*/) return; - if (s3->accel.sy < 0) - { - return; - } - } - } - } - break; + s3->accel.src = s3->accel.cy * s3->width; + s3->accel.dest = s3->accel.dy * s3->width; - case 7: /*Pattern fill - BitBlt but with source limited to 8x8*/ - if (!cpu_input) /*!cpu_input is trigger to start operation*/ - { - s3->accel.sx = s3->accel.maj_axis_pcnt & 0xfff; - s3->accel.sy = s3->accel.multifunc[0] & 0xfff; + s3->accel.sy--; - s3->accel.dx = s3->accel.destx_distp & 0xfff; - if (s3->accel.destx_distp & 0x1000) s3->accel.dx |= ~0xfff; - s3->accel.dy = s3->accel.desty_axstp & 0xfff; - if (s3->accel.desty_axstp & 0x1000) s3->accel.dy |= ~0xfff; + if (cpu_input/* && (s3->accel.multifunc[0xa] & 0xc0) == 0x80*/) return; + if (s3->accel.sy < 0) + { + return; + } + } + } + } + break; - s3->accel.cx = s3->accel.cur_x & 0xfff; - if (s3->accel.cur_x & 0x1000) s3->accel.cx |= ~0xfff; - s3->accel.cy = s3->accel.cur_y & 0xfff; - if (s3->accel.cur_y & 0x1000) s3->accel.cy |= ~0xfff; - - /*Align source with destination*/ - s3->accel.pattern = (s3->accel.cy * s3->width) + s3->accel.cx; - s3->accel.dest = s3->accel.dy * s3->width; - - s3->accel.cx = s3->accel.dx & 7; - s3->accel.cy = s3->accel.dy & 7; - - s3->accel.src = s3->accel.pattern + (s3->accel.cy * s3->width); - } - if ((s3->accel.cmd & 0x100) && !cpu_input) return; /*Wait for data from CPU*/ + case 7: /*Pattern fill - BitBlt but with source limited to 8x8*/ + if (!cpu_input) /*!cpu_input is trigger to start operation*/ + { + s3->accel.sx = s3->accel.maj_axis_pcnt & 0xfff; + s3->accel.sy = s3->accel.multifunc[0] & 0xfff; - frgd_mix = (s3->accel.frgd_mix >> 5) & 3; - bkgd_mix = (s3->accel.bkgd_mix >> 5) & 3; + s3->accel.dx = s3->accel.destx_distp & 0xfff; + if (s3->accel.destx_distp & 0x1000) s3->accel.dx |= ~0xfff; + s3->accel.dy = s3->accel.desty_axstp & 0xfff; + if (s3->accel.desty_axstp & 0x1000) s3->accel.dy |= ~0xfff; - while (count-- && s3->accel.sy >= 0) - { - if (s3->accel.dx >= clip_l && s3->accel.dx <= clip_r && - s3->accel.dy >= clip_t && s3->accel.dy <= clip_b) - { - if (vram_mask) - { - READ(s3->accel.src + s3->accel.cx, mix_dat) - mix_dat = mix_dat ? mix_mask : 0; - } - switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) - { - case 0: src_dat = s3->accel.bkgd_color; break; - case 1: src_dat = s3->accel.frgd_color; break; - case 2: src_dat = cpu_dat; break; - case 3: READ(s3->accel.src + s3->accel.cx, src_dat); break; - } + s3->accel.cx = s3->accel.cur_x & 0xfff; + if (s3->accel.cur_x & 0x1000) s3->accel.cx |= ~0xfff; + s3->accel.cy = s3->accel.cur_y & 0xfff; + if (s3->accel.cur_y & 0x1000) s3->accel.cy |= ~0xfff; + + /*Align source with destination*/ + s3->accel.pattern = (s3->accel.cy * s3->width) + s3->accel.cx; + s3->accel.dest = s3->accel.dy * s3->width; + + s3->accel.cx = s3->accel.dx & 7; + s3->accel.cy = s3->accel.dy & 7; + + s3->accel.src = s3->accel.pattern + (s3->accel.cy * s3->width); + } - if ((compare_mode == 2 && src_dat != compare) || - (compare_mode == 3 && src_dat == compare) || - compare_mode < 2) - { - READ(s3->accel.dest + s3->accel.dx, dest_dat); + s3->status_9ae8 = 4; /*To avoid the spam from OS/2's drivers*/ - MIX + if ((s3->accel.cmd & 0x100) && !cpu_input) + { + s3->status_9ae8 = 2; /*To avoid the spam from OS/2's drivers*/ + return; /*Wait for data from CPU*/ + } - WRITE(s3->accel.dest + s3->accel.dx); - } - } + if ((s3->accel.cmd & 0x100) && !cpu_input) return; /*Wait for data from CPU*/ - mix_dat <<= 1; - mix_dat |= 1; - if (s3->bpp == 0) cpu_dat >>= 8; - else cpu_dat >>= 16; + frgd_mix = (s3->accel.frgd_mix >> 5) & 3; + bkgd_mix = (s3->accel.bkgd_mix >> 5) & 3; - if (s3->accel.cmd & 0x20) - { - s3->accel.cx = ((s3->accel.cx + 1) & 7) | (s3->accel.cx & ~7); - s3->accel.dx++; - } - else - { - s3->accel.cx = ((s3->accel.cx - 1) & 7) | (s3->accel.cx & ~7); - s3->accel.dx--; - } - s3->accel.sx--; - if (s3->accel.sx < 0) - { - if (s3->accel.cmd & 0x20) - { - s3->accel.cx = ((s3->accel.cx - ((s3->accel.maj_axis_pcnt & 0xfff) + 1)) & 7) | (s3->accel.cx & ~7); - s3->accel.dx -= (s3->accel.maj_axis_pcnt & 0xfff) + 1; - } - else - { - s3->accel.cx = ((s3->accel.cx + ((s3->accel.maj_axis_pcnt & 0xfff) + 1)) & 7) | (s3->accel.cx & ~7); - s3->accel.dx += (s3->accel.maj_axis_pcnt & 0xfff) + 1; - } - s3->accel.sx = s3->accel.maj_axis_pcnt & 0xfff; + while (count-- && s3->accel.sy >= 0) + { + if (s3->accel.dx >= clip_l && s3->accel.dx <= clip_r && + s3->accel.dy >= clip_t && s3->accel.dy <= clip_b) + { + if (vram_mask) + { + READ_SRC(s3->accel.src + s3->accel.cx, mix_dat) + mix_dat = mix_dat ? mix_mask : 0; + } + switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) + { + case 0: src_dat = s3->accel.bkgd_color; break; + case 1: src_dat = s3->accel.frgd_color; break; + case 2: src_dat = cpu_dat; break; + case 3: READ_SRC(s3->accel.src + s3->accel.cx, src_dat); break; + } - if (s3->accel.cmd & 0x80) - { - s3->accel.cy = ((s3->accel.cy + 1) & 7) | (s3->accel.cy & ~7); - s3->accel.dy++; - } - else - { - s3->accel.cy = ((s3->accel.cy - 1) & 7) | (s3->accel.cy & ~7); - s3->accel.dy--; - } + if ((compare_mode == 2 && src_dat != compare) || + (compare_mode == 3 && src_dat == compare) || + compare_mode < 2) + { + READ_DST(s3->accel.dest + s3->accel.dx, dest_dat); - s3->accel.src = s3->accel.pattern + (s3->accel.cy * s3->width); - s3->accel.dest = s3->accel.dy * s3->width; + MIX - s3->accel.sy--; + WRITE(s3->accel.dest + s3->accel.dx); + } + } - if (cpu_input/* && (s3->accel.multifunc[0xa] & 0xc0) == 0x80*/) return; - if (s3->accel.sy < 0) - return; - } - } - break; - } + mix_dat <<= 1; + mix_dat |= 1; + if (s3->bpp == 0) cpu_dat >>= 8; + else cpu_dat >>= 16; + + if (s3->accel.cmd & 0x20) + { + s3->accel.cx = ((s3->accel.cx + 1) & 7) | (s3->accel.cx & ~7); + s3->accel.dx++; + } + else + { + s3->accel.cx = ((s3->accel.cx - 1) & 7) | (s3->accel.cx & ~7); + s3->accel.dx--; + } + s3->accel.sx--; + if (s3->accel.sx < 0) + { + if (s3->accel.cmd & 0x20) + { + s3->accel.cx = ((s3->accel.cx - ((s3->accel.maj_axis_pcnt & 0xfff) + 1)) & 7) | (s3->accel.cx & ~7); + s3->accel.dx -= (s3->accel.maj_axis_pcnt & 0xfff) + 1; + } + else + { + s3->accel.cx = ((s3->accel.cx + ((s3->accel.maj_axis_pcnt & 0xfff) + 1)) & 7) | (s3->accel.cx & ~7); + s3->accel.dx += (s3->accel.maj_axis_pcnt & 0xfff) + 1; + } + s3->accel.sx = s3->accel.maj_axis_pcnt & 0xfff; + + if (s3->accel.cmd & 0x80) + { + s3->accel.cy = ((s3->accel.cy + 1) & 7) | (s3->accel.cy & ~7); + s3->accel.dy++; + } + else + { + s3->accel.cy = ((s3->accel.cy - 1) & 7) | (s3->accel.cy & ~7); + s3->accel.dy--; + } + + s3->accel.src = s3->accel.pattern + (s3->accel.cy * s3->width); + s3->accel.dest = s3->accel.dy * s3->width; + + s3->accel.sy--; + + if (cpu_input/* && (s3->accel.multifunc[0xa] & 0xc0) == 0x80*/) return; + if (s3->accel.sy < 0) + return; + } + } + break; + + case 3: /*Polygon Fill Solid (Trio64 only)*/ + { + int end_y1, end_y2; + + if (s3->chip != S3_TRIO64) + break; + + polygon_setup(s3); + + s3->status_9ae8 = 4; /*To avoid the spam from OS/2's drivers*/ + + if ((s3->accel.cmd & 0x100) && !cpu_input) + { + s3->status_9ae8 = 2; /*To avoid the spam from OS/2's drivers*/ + return; /*Wait for data from CPU*/ + } + + if ((s3->accel.cmd & 0x100) && !cpu_input) return; /*Wait for data from CPU*/ + + end_y1 = s3->accel.desty_axstp; + end_y2 = s3->accel.desty_axstp2; + + frgd_mix = (s3->accel.frgd_mix >> 5) & 3; + + while ((s3->accel.poly_cy < end_y1) && (s3->accel.poly_cy2 < end_y2)) + { + int y = s3->accel.poly_cy; + int x_count = ABS((s3->accel.poly_cx2 >> 20) - s3->accel.poly_x) + 1; + + s3->accel.dest = y * s3->width; + + while (x_count-- && count--) + { + if (s3->accel.poly_x >= clip_l && s3->accel.poly_x <= clip_r && + s3->accel.poly_cy >= clip_t && s3->accel.poly_cy <= clip_b) + { + switch (frgd_mix) + { + case 0: src_dat = s3->accel.bkgd_color; break; + case 1: src_dat = s3->accel.frgd_color; break; + case 2: src_dat = cpu_dat; break; + case 3: src_dat = 0; /*Nor supported?*/ break; + } + + if ((compare_mode == 2 && src_dat != compare) || + (compare_mode == 3 && src_dat == compare) || + compare_mode < 2) + { + READ_DST(s3->accel.dest + s3->accel.poly_x, dest_dat); + + MIX + + WRITE(s3->accel.dest + s3->accel.poly_x); + } + } + if (s3->bpp == 0) cpu_dat >>= 8; + else cpu_dat >>= 16; + + if (s3->accel.poly_x < (s3->accel.poly_cx2 >> 20)) + s3->accel.poly_x++; + else + s3->accel.poly_x--; + } + + s3->accel.poly_cx += s3->accel.poly_dx1; + s3->accel.poly_cx2 += s3->accel.poly_dx2; + s3->accel.poly_x = s3->accel.poly_cx >> 20; + + s3->accel.poly_cy++; + s3->accel.poly_cy2++; + + if (!count) + break; + } + + s3->accel.cur_x = s3->accel.poly_cx & 0xfff; + s3->accel.cur_y = s3->accel.poly_cy & 0xfff; + s3->accel.cur_x2 = s3->accel.poly_cx2 & 0xfff; + s3->accel.cur_y2 = s3->accel.poly_cy & 0xfff; + } + break; + + case 11: /*Polygon Fill Pattern (Trio64 only)*/ + { + int end_y1, end_y2; + + if (s3->chip != S3_TRIO64) + break; + + polygon_setup(s3); + + s3->status_9ae8 = 4; /*To avoid the spam from OS/2's drivers*/ + + if ((s3->accel.cmd & 0x100) && !cpu_input) + { + s3->status_9ae8 = 2; /*To avoid the spam from OS/2's drivers*/ + return; /*Wait for data from CPU*/ + } + + if ((s3->accel.cmd & 0x100) && !cpu_input) return; /*Wait for data from CPU*/ + + end_y1 = s3->accel.desty_axstp; + end_y2 = s3->accel.desty_axstp2; + + frgd_mix = (s3->accel.frgd_mix >> 5) & 3; + bkgd_mix = (s3->accel.bkgd_mix >> 5) & 3; + + while ((s3->accel.poly_cy < end_y1) && (s3->accel.poly_cy2 < end_y2)) + { + int y = s3->accel.poly_cy; + int x_count = ABS((s3->accel.poly_cx2 >> 20) - s3->accel.poly_x) + 1; + + s3->accel.src = s3->accel.pattern + ((y & 7) * s3->width); + s3->accel.dest = y * s3->width; + + while (x_count-- && count--) + { + int pat_x = s3->accel.poly_x & 7; + + if (s3->accel.poly_x >= clip_l && s3->accel.poly_x <= clip_r && + s3->accel.poly_cy >= clip_t && s3->accel.poly_cy <= clip_b) + { + if (vram_mask) + { + READ_SRC(s3->accel.src + pat_x, mix_dat) + mix_dat = mix_dat ? mix_mask : 0; + } + switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) + { + case 0: src_dat = s3->accel.bkgd_color; break; + case 1: src_dat = s3->accel.frgd_color; break; + case 2: src_dat = cpu_dat; break; + case 3: READ_SRC(s3->accel.src + pat_x, src_dat); break; + } + + if ((compare_mode == 2 && src_dat != compare) || + (compare_mode == 3 && src_dat == compare) || + compare_mode < 2) + { + READ_DST(s3->accel.dest + s3->accel.poly_x, dest_dat); + + MIX + + WRITE(s3->accel.dest + s3->accel.poly_x); + } + } + if (s3->bpp == 0) cpu_dat >>= 8; + else cpu_dat >>= 16; + + mix_dat <<= 1; + mix_dat |= 1; + + if (s3->accel.poly_x < (s3->accel.poly_cx2 >> 20)) + s3->accel.poly_x++; + else + s3->accel.poly_x--; + } + + s3->accel.poly_cx += s3->accel.poly_dx1; + s3->accel.poly_cx2 += s3->accel.poly_dx2; + s3->accel.poly_x = s3->accel.poly_cx >> 20; + + s3->accel.poly_cy++; + s3->accel.poly_cy2++; + + if (!count) + break; + } + + s3->accel.cur_x = s3->accel.poly_cx & 0xfff; + s3->accel.cur_y = s3->accel.poly_cy & 0xfff; + s3->accel.cur_x2 = s3->accel.poly_cx2 & 0xfff; + s3->accel.cur_y2 = s3->accel.poly_cy & 0xfff; + } + break; + } } -void s3_hwcursor_draw(svga_t *svga, int disp_line) +void s3_hwcursor_draw(svga_t *svga, int displine) { s3_t *s3 = (s3_t *)svga->p; - int x; - uint16_t dat[2]; - int xx; - int offset = svga->hwcursor_latch.x - svga->hwcursor_latch.xoff; - int y_add = (enable_overscan && !suppress_overscan) ? 16 : 0; - int x_add = (enable_overscan && !suppress_overscan) ? 8 : 0; + int x; + uint16_t dat[2]; + int xx; + int offset = svga->hwcursor_latch.x - svga->hwcursor_latch.xoff; + int y_add, x_add; + uint32_t fg, bg; - uint32_t fg = 0, bg = 0; + y_add = (enable_overscan && !suppress_overscan) ? (overscan_y >> 1) : 0; + x_add = (enable_overscan && !suppress_overscan) ? 8 : 0; - switch (svga->bpp) - { - case 15: - fg = video_15to32[s3->hwc_fg_col & 0xffff]; - bg = video_15to32[s3->hwc_bg_col & 0xffff]; - break; + switch (svga->bpp) + { + case 15: + fg = video_15to32[s3->hwc_fg_col & 0xffff]; + bg = video_15to32[s3->hwc_bg_col & 0xffff]; + break; + + case 16: + fg = video_16to32[s3->hwc_fg_col & 0xffff]; + bg = video_16to32[s3->hwc_bg_col & 0xffff]; + break; + + case 24: case 32: + fg = s3->hwc_fg_col; + bg = s3->hwc_bg_col; + break; - case 16: - fg = video_16to32[s3->hwc_fg_col & 0xffff]; - bg = video_16to32[s3->hwc_bg_col & 0xffff]; - break; + default: + if (s3->chip == S3_TRIO32 || s3->chip == S3_TRIO64) + { + fg = svga->pallook[s3->hwc_fg_col & 0xff]; + bg = svga->pallook[s3->hwc_bg_col & 0xff]; + } + else + { + fg = svga->pallook[svga->crtc[0xe]]; + bg = svga->pallook[svga->crtc[0xf]]; + } + break; + } - case 24: case 32: - fg = s3->hwc_fg_col; - bg = s3->hwc_bg_col; - break; + if (svga->interlace && svga->hwcursor_oddeven) + svga->hwcursor_latch.addr += 16; - default: - if (s3->chip == S3_TRIO32 || s3->chip == S3_TRIO64) - { - fg = svga->pallook[s3->hwc_fg_col & 0xff]; - bg = svga->pallook[s3->hwc_bg_col & 0xff]; - } - else - { - fg = svga->pallook[svga->crtc[0xe]]; - bg = svga->pallook[svga->crtc[0xf]]; - } - break; - } - - if (svga->interlace && svga->hwcursor_oddeven) - svga->hwcursor_latch.addr += 16; - - for (x = 0; x < 64; x += 16) - { - dat[0] = (svga->vram[svga->hwcursor_latch.addr] << 8) | svga->vram[svga->hwcursor_latch.addr + 1]; - dat[1] = (svga->vram[svga->hwcursor_latch.addr + 2] << 8) | svga->vram[svga->hwcursor_latch.addr + 3]; - for (xx = 0; xx < 16; xx++) - { - if (offset >= svga->hwcursor_latch.x) - { - if (!(dat[0] & 0x8000)) - ((uint32_t *)buffer32->line[disp_line + y_add])[offset + 32 + x_add] = (dat[1] & 0x8000) ? fg : bg; - else if (dat[1] & 0x8000) - ((uint32_t *)buffer32->line[disp_line + y_add])[offset + 32 + x_add] ^= 0xffffff; - } - - offset++; - dat[0] <<= 1; - dat[1] <<= 1; - } - svga->hwcursor_latch.addr += 4; - } - if (svga->interlace && !svga->hwcursor_oddeven) - svga->hwcursor_latch.addr += 16; + for (x = 0; x < 64; x += 16) + { + dat[0] = (svga->vram[svga->hwcursor_latch.addr] << 8) | svga->vram[svga->hwcursor_latch.addr + 1]; + dat[1] = (svga->vram[svga->hwcursor_latch.addr + 2] << 8) | svga->vram[svga->hwcursor_latch.addr + 3]; + for (xx = 0; xx < 16; xx++) + { + if (offset >= svga->hwcursor_latch.x) + { + if (!(dat[0] & 0x8000)) + ((uint32_t *)buffer32->line[displine + y_add])[offset + 32 + x_add] = (dat[1] & 0x8000) ? fg : bg; + else if (dat[1] & 0x8000) + ((uint32_t *)buffer32->line[displine + y_add])[offset + 32 + x_add] ^= 0xffffff; + } + + offset++; + dat[0] <<= 1; + dat[1] <<= 1; + } + svga->hwcursor_latch.addr += 4; + } + if (svga->interlace && !svga->hwcursor_oddeven) + svga->hwcursor_latch.addr += 16; } - static void s3_io_remove(s3_t *s3) { - io_removehandler(0x03c0, 0x0020, s3_in, NULL, NULL, s3_out, NULL, NULL, s3); - - io_removehandler(0x42e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_removehandler(0x46e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_removehandler(0x4ae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_removehandler(0x82e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_removehandler(0x86e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_removehandler(0x8ae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_removehandler(0x8ee8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_removehandler(0x92e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_removehandler(0x96e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_removehandler(0x9ae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_removehandler(0x9ee8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_removehandler(0xa2e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_removehandler(0xa6e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_removehandler(0xaae8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_removehandler(0xaee8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_removehandler(0xb2e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_removehandler(0xb6e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_removehandler(0xbae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_removehandler(0xbee8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_removehandler(0xe2e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, s3_accel_out_w, s3_accel_out_l, s3); + io_removehandler(0x03c0, 0x0020, s3_in, NULL, NULL, s3_out, NULL, NULL, s3); + + io_removehandler(0x42e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_removehandler(0x46e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_removehandler(0x4ae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + if (s3->chip == S3_TRIO64) + { + io_sethandler(0x82e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0x86e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0x8ae8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0x8ee8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0x92e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0x96e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + } + else + { + io_sethandler(0x82e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0x86e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0x8ae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0x8ee8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0x92e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0x96e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + } + io_removehandler(0x9ae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_removehandler(0x9ee8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_removehandler(0xa2e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_removehandler(0xa6e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_removehandler(0xaae8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_removehandler(0xaee8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_removehandler(0xb2e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_removehandler(0xb6e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_removehandler(0xbae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_removehandler(0xbee8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_removehandler(0xe2e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, s3_accel_out_w, s3_accel_out_l, s3); } static void s3_io_set(s3_t *s3) { - s3_io_remove(s3); + s3_io_remove(s3); - io_sethandler(0x03c0, 0x0020, s3_in, NULL, NULL, s3_out, NULL, NULL, s3); - - io_sethandler(0x42e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_sethandler(0x46e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_sethandler(0x4ae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_sethandler(0x82e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_sethandler(0x86e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_sethandler(0x8ae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_sethandler(0x8ee8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_sethandler(0x92e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_sethandler(0x96e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_sethandler(0x9ae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_sethandler(0x9ee8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_sethandler(0xa2e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_sethandler(0xa6e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_sethandler(0xaae8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_sethandler(0xaee8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_sethandler(0xb2e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_sethandler(0xb6e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_sethandler(0xbae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_sethandler(0xbee8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_sethandler(0xe2e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, s3_accel_out_w, s3_accel_out_l, s3); + io_sethandler(0x03c0, 0x0020, s3_in, NULL, NULL, s3_out, NULL, NULL, s3); + + io_sethandler(0x42e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0x46e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0x4ae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0x82e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0x86e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0x8ae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0x8ee8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0x92e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0x96e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0x9ae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0x9ee8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0xa2e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0xa6e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0xaae8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0xaee8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0xb2e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0xb6e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0xbae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0xbee8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_sethandler(0xe2e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, s3_accel_out_w, s3_accel_out_l, s3); } - + uint8_t s3_pci_read(int func, int addr, void *p) { - s3_t *s3 = (s3_t *)p; - svga_t *svga = &s3->svga; - switch (addr) - { - case 0x00: return 0x33; /*'S3'*/ - case 0x01: return 0x53; - - case 0x02: return s3->id_ext_pci; - case 0x03: return 0x88; - - case PCI_REG_COMMAND: - return s3->pci_regs[PCI_REG_COMMAND]; /*Respond to IO and memory accesses*/ + s3_t *s3 = (s3_t *)p; + svga_t *svga = &s3->svga; + switch (addr) + { + case 0x00: return 0x33; /*'S3'*/ + case 0x01: return 0x53; + + case 0x02: return s3->id_ext_pci; + case 0x03: return 0x88; + + case PCI_REG_COMMAND: + return s3->pci_regs[PCI_REG_COMMAND]; /*Respond to IO and memory accesses*/ - case 0x07: return 1 << 1; /*Medium DEVSEL timing*/ - - case 0x08: return 0; /*Revision ID*/ - case 0x09: return 0; /*Programming interface*/ - - case 0x0a: return 0x00; /*Supports VGA interface*/ - case 0x0b: return 0x03; - - case 0x10: return 0x00; /*Linear frame buffer address*/ - case 0x11: return 0x00; - case 0x12: return svga->crtc[0x5a] & 0x80; - case 0x13: return svga->crtc[0x59]; + case 0x07: return 1 << 1; /*Medium DEVSEL timing*/ + + case 0x08: return 0; /*Revision ID*/ + case 0x09: return 0; /*Programming interface*/ + + case 0x0a: + if ((s3->chip == S3_TRIO32) || (s3->chip == S3_TRIO64)) + return 0x00; /*Supports VGA interface*/ + else + return 0x01; + case 0x0b: + if ((s3->chip == S3_TRIO32) || (s3->chip == S3_TRIO64)) + return 0x03; + else + return 0x00; + + case 0x10: return 0x00; /*Linear frame buffer address*/ + case 0x11: return 0x00; + case 0x12: return svga->crtc[0x5a] & 0x80; + case 0x13: return svga->crtc[0x59]; - case 0x30: return s3->has_bios ? (s3->pci_regs[0x30] & 0x01) : 0x00; /*BIOS ROM address*/ - case 0x31: return 0x00; - case 0x32: return s3->has_bios ? s3->pci_regs[0x32] : 0x00; - case 0x33: return s3->has_bios ? s3->pci_regs[0x33] : 0x00; - - case 0x3c: return s3->int_line; - case 0x3d: return PCI_INTA; - } - return 0; + case 0x30: return s3->has_bios ? (s3->pci_regs[0x30] & 0x01) : 0x00; /*BIOS ROM address*/ + case 0x31: return 0x00; + case 0x32: return s3->has_bios ? s3->pci_regs[0x32] : 0x00; + case 0x33: return s3->has_bios ? s3->pci_regs[0x33] : 0x00; + + case 0x3c: return s3->int_line; + case 0x3d: return PCI_INTA; + } + return 0; } void s3_pci_write(int func, int addr, uint8_t val, void *p) { - s3_t *s3 = (s3_t *)p; - svga_t *svga = &s3->svga; - switch (addr) - { - case PCI_REG_COMMAND: - s3->pci_regs[PCI_REG_COMMAND] = val & 0x23; - if (val & PCI_COMMAND_IO) - s3_io_set(s3); - else - s3_io_remove(s3); - s3_updatemapping(s3); - break; - - case 0x12: - svga->crtc[0x5a] = val & 0x80; - s3_updatemapping(s3); - break; - case 0x13: - svga->crtc[0x59] = val; - s3_updatemapping(s3); - break; + s3_t *s3 = (s3_t *)p; + svga_t *svga = &s3->svga; + switch (addr) + { + case PCI_REG_COMMAND: + s3->pci_regs[PCI_REG_COMMAND] = val & 0x23; + if (val & PCI_COMMAND_IO) + s3_io_set(s3); + else + s3_io_remove(s3); + s3_updatemapping(s3); + break; + + case 0x12: + svga->crtc[0x5a] = val & 0x80; +#if 0 + svga->crtc[0x5a] = (svga->crtc[0x5a] & 0x7f) | (val & 0x80); +#endif + s3_updatemapping(s3); + break; + case 0x13: + svga->crtc[0x59] = val; + s3_updatemapping(s3); + break; - case 0x30: case 0x32: case 0x33: + case 0x30: case 0x32: case 0x33: if (!s3->has_bios) return; - s3->pci_regs[addr] = val; - if (s3->pci_regs[0x30] & 0x01) - { - uint32_t a = (s3->pci_regs[0x32] << 16) | (s3->pci_regs[0x33] << 24); - mem_mapping_set_addr(&s3->bios_rom.mapping, a, 0x8000); - } - else - { - mem_mapping_disable(&s3->bios_rom.mapping); - } - return; - - case 0x3c: - s3->int_line = val; - return; - } + s3->pci_regs[addr] = val; + if (s3->pci_regs[0x30] & 0x01) + { + uint32_t addr = (s3->pci_regs[0x32] << 16) | (s3->pci_regs[0x33] << 24); + mem_map_set_addr(&s3->bios_rom.mapping, addr, 0x8000); + } + else + { + mem_map_disable(&s3->bios_rom.mapping); + } + return; + + case 0x3c: + s3->int_line = val; + return; + } } static int vram_sizes[] = { - 7, /*512 kB*/ - 6, /*1 MB*/ - 4, /*2 MB*/ - 0, - 0, /*4 MB*/ - 0, - 0, - 0, - 3 /*8 MB*/ + 7, /*512 kB*/ + 6, /*1 MB*/ + 4, /*2 MB*/ + 0, + 0, /*4 MB*/ + 0, + 0, + 0, + 3 /*8 MB*/ }; -static void *s3_init(const device_t *info, wchar_t *bios_fn, int chip) -{ - s3_t *s3 = malloc(sizeof(s3_t)); - svga_t *svga = &s3->svga; - int vram; - uint32_t vram_size; - - memset(s3, 0, sizeof(s3_t)); - - vram = device_get_config_int("memory"); - if (vram) - vram_size = vram << 20; - else - vram_size = 512 << 10; - s3->vram_mask = vram_size - 1; - s3->has_bios = !info->local; +static void * +s3_init(const device_t *info) +{ + const wchar_t *bios_fn; + int chip, stepping; + s3_t *s3 = (s3_t *)mem_alloc(sizeof(s3_t)); + svga_t *svga = &s3->svga; + int vram; + uint32_t vram_size; + + switch(info->local) { + case S3_PARADISE_BAHAMAS64: + bios_fn = ROM_PARADISE_BAHAMAS64; + chip = S3_VISION864; + video_inform(VID_TYPE_SPEC, &timing_s3_vision864); + break; + case S3_PHOENIX_VISION864: + bios_fn = ROM_PHOENIX_VISION864; + chip = S3_VISION864; + video_inform(VID_TYPE_SPEC, &timing_s3_vision864); + break; + case S3_DIAMOND_STEALTH64_964: + bios_fn = ROM_DIAMOND_STEALTH64_964; + chip = S3_VISION964; + video_inform(VID_TYPE_SPEC, &timing_s3_vision964); + break; + case S3_PHOENIX_TRIO32: + bios_fn = ROM_PHOENIX_TRIO32; + chip = S3_TRIO32; + video_inform(VID_TYPE_SPEC, &timing_s3_trio32); + break; + case S3_PHOENIX_TRIO64: + bios_fn = ROM_PHOENIX_TRIO64; + chip = S3_TRIO64; + video_inform(VID_TYPE_SPEC, &timing_s3_trio64); + break; + case S3_PHOENIX_TRIO64_ONBOARD: + bios_fn = NULL; + chip = S3_TRIO64; + video_inform(VID_TYPE_SPEC, &timing_s3_trio64); + break; + case S3_DIAMOND_STEALTH64_764: + bios_fn = ROM_DIAMOND_STEALTH64_764; + chip = S3_TRIO64; + video_inform(VID_TYPE_SPEC, &timing_s3_stealth64); + break; + case S3_NUMBER9_9FX: + bios_fn = ROM_NUMBER9_9FX; + chip = S3_TRIO64; + video_inform(VID_TYPE_SPEC, &timing_s3_trio64); + break; + default: + free(s3); + return NULL; + } + + memset(s3, 0, sizeof(s3_t)); + + vram = device_get_config_int("memory"); + + if (vram) + vram_size = vram << 20; + else + vram_size = 512 << 10; + s3->vram_mask = vram_size - 1; + + s3->has_bios = (bios_fn != NULL); if (s3->has_bios) { - rom_init(&s3->bios_rom, bios_fn, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + rom_init(&s3->bios_rom, (wchar_t *) bios_fn, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); if (info->flags & DEVICE_PCI) - mem_mapping_disable(&s3->bios_rom.mapping); + mem_map_disable(&s3->bios_rom.mapping); } - mem_mapping_add(&s3->linear_mapping, 0, 0, svga_read_linear, svga_readw_linear, svga_readl_linear, svga_write_linear, svga_writew_linear, svga_writel_linear, NULL, MEM_MAPPING_EXTERNAL, &s3->svga); - mem_mapping_add(&s3->mmio_mapping, 0xa0000, 0x10000, s3_accel_read, NULL, NULL, s3_accel_write, s3_accel_write_w, s3_accel_write_l, NULL, MEM_MAPPING_EXTERNAL, s3); - mem_mapping_disable(&s3->mmio_mapping); + s3->pci = !!(info->flags & DEVICE_PCI); - svga_init(&s3->svga, s3, vram_size, /*4mb - 864 supports 8mb but buggy VESA driver reports 0mb*/ - s3_recalctimings, - s3_in, s3_out, - s3_hwcursor_draw, - NULL); + mem_map_add(&s3->linear_mapping, 0, 0, + svga_read_linear, svga_readw_linear, svga_readl_linear, + svga_write_linear, svga_writew_linear, svga_writel_linear, + NULL, MEM_MAPPING_EXTERNAL, &s3->svga); + mem_map_add(&s3->mmio_mapping, 0xa0000, 0x10000, + s3_accel_read, NULL, NULL, + s3_accel_write, s3_accel_write_w, s3_accel_write_l, + NULL, MEM_MAPPING_EXTERNAL, s3); + mem_map_disable(&s3->mmio_mapping); + + if (chip == S3_VISION964) + svga_init(&s3->svga, s3, vram_size, + s3_recalctimings, + s3_in, s3_out, + bt48x_hwcursor_draw, + NULL); + else + svga_init(&s3->svga, s3, vram_size, + s3_recalctimings, + s3_in, s3_out, + s3_hwcursor_draw, + NULL); - svga->decode_mask = (4 << 20) - 1; - switch (vram) - { - case 0: /*512kb*/ - svga->vram_mask = (1 << 19) - 1; - svga->vram_max = 2 << 20; - break; - case 1: /*1MB*/ - /*VRAM in first MB, mirrored in 2nd MB, 3rd and 4th MBs are open bus*/ - /*This works with the #9 9FX BIOS, and matches how my real Trio64 behaves, - but does not work with the Phoenix EDO BIOS. Possibly an FPM/EDO difference?*/ - svga->vram_mask = (1 << 20) - 1; - svga->vram_max = 2 << 20; - break; - case 2: default: /*2MB*/ - /*VRAM in first 2 MB, 3rd and 4th MBs are open bus*/ - svga->vram_mask = (2 << 20) - 1; - svga->vram_max = 2 << 20; - break; - case 4: /*4MB*/ - svga->vram_mask = (4 << 20) - 1; - svga->vram_max = 4 << 20; - break; - case 8: /*4MB*/ - svga->vram_mask = (8 << 20) - 1; - svga->vram_max = 8 << 20; - break; - } - - if (info->flags & DEVICE_PCI) - svga->crtc[0x36] = 2 | (3 << 2) | (1 << 4) | (vram_sizes[vram] << 5); - else - svga->crtc[0x36] = 1 | (3 << 2) | (1 << 4) | (vram_sizes[vram] << 5); - svga->crtc[0x37] = 1 | (7 << 5); - - svga->vblank_start = s3_vblank_start; - - s3_io_set(s3); - - if (info->flags & DEVICE_PCI) - { - s3->card = pci_add_card(PCI_ADD_VIDEO, s3_pci_read, s3_pci_write, s3); + switch (vram) { + case 0: /* 512 kB */ + svga->vram_mask = (1 << 19) - 1; + svga->vram_max = 2 << 20; + break; + case 1: /* 1 MB */ + /* VRAM in first MB, mirrored in 2nd MB, 3rd and 4th MBs are open bus. + This works with the #9 9FX BIOS, and matches how my real Trio64 behaves, + but does not work with the Phoenix EDO BIOS. Possibly an FPM/EDO difference? */ + svga->vram_mask = (1 << 20) - 1; + svga->vram_max = 2 << 20; + break; + case 2: + default: /*2 MB */ + /* VRAM in first 2 MB, 3rd and 4th MBs are open bus. */ + svga->vram_mask = (2 << 20) - 1; + svga->vram_max = 2 << 20; + break; + case 4: /*4MB*/ + svga->vram_mask = (4 << 20) - 1; + svga->vram_max = 4 << 20; + break; + case 8: /*8MB*/ + svga->vram_mask = (8 << 20) - 1; + svga->vram_max = 8 << 20; + break; } - s3->pci_regs[0x04] = 7; - - s3->pci_regs[0x30] = 0x00; - s3->pci_regs[0x32] = 0x0c; - s3->pci_regs[0x33] = 0x00; - - s3->chip = chip; + if (info->flags & DEVICE_PCI) + svga->crtc[0x36] = 2 | (3 << 2) | (1 << 4) | (vram_sizes[vram] << 5); + else + svga->crtc[0x36] = 1 | (3 << 2) | (1 << 4) | (vram_sizes[vram] << 5); + svga->crtc[0x37] = 1 | (7 << 5); - s3->wake_fifo_thread = thread_create_event(); - s3->fifo_not_full_event = thread_create_event(); - s3->fifo_thread = thread_create(fifo_thread, s3); - - s3->int_line = 0; - - return s3; -} + svga->vblank_start = s3_vblank_start; -void *s3_vision864_init(const device_t *info, wchar_t *bios_fn) -{ - s3_t *s3 = s3_init(info, bios_fn, S3_VISION864); + s3_io_set(s3); - s3->id = 0xc1; /*Vision864P*/ - s3->id_ext = s3->id_ext_pci = 0xc1; - s3->packed_mmio = 0; - - s3->getclock = sdac_getclock; - s3->getclock_p = &s3->ramdac; - sdac_init(&s3->ramdac); + if (info->flags & DEVICE_PCI) + s3->card = pci_add_card(PCI_ADD_VIDEO, s3_pci_read, s3_pci_write, s3); - return s3; -} + s3->pci_regs[0x04] = 7; + s3->pci_regs[0x30] = 0x00; + s3->pci_regs[0x32] = 0x0c; + s3->pci_regs[0x33] = 0x00; -static void *s3_bahamas64_init(const device_t *info) -{ - s3_t *s3 = s3_vision864_init(info, L"video/s3/s3/bahamas64.bin"); - return s3; -} + s3->chip = chip; + + s3->wake_fifo_thread = thread_create_event(); + s3->fifo_not_full_event = thread_create_event(); + s3->fifo_thread = thread_create(fifo_thread, s3); + + s3->int_line = 0; + + switch(info->local) { + case S3_PARADISE_BAHAMAS64: + case S3_PHOENIX_VISION864: + svga->decode_mask = (8 << 20) - 1; + if (info->local == S3_PARADISE_BAHAMAS64) + stepping = 0xc0; /*Vision864*/ + else + stepping = 0xc1; /*Vision864P*/ + s3->id = stepping; + s3->id_ext = s3->id_ext_pci = stepping; + s3->packed_mmio = 0; + + svga->ramdac = device_add(&sdac_ramdac_device); + svga->clock_gen = svga->ramdac; + svga->getclock = sdac_getclock; + break; + + case S3_DIAMOND_STEALTH64_964: + svga->decode_mask = (8 << 20) - 1; + stepping = 0xd0; /*Vision964P*/ + s3->id = stepping; + s3->id_ext = s3->id_ext_pci = stepping; + s3->packed_mmio = 1; + svga->crtc[0x5a] = 0x0a; + + svga->ramdac = device_add(&bt485_ramdac_device); + svga->clock_gen = device_add(&icd2061_device); + svga->getclock = icd2061_getclock; + break; + + case S3_PHOENIX_TRIO32: + svga->decode_mask = (4 << 20) - 1; + s3->id = 0xe1; /*Trio32*/ + s3->id_ext = 0x10; + s3->id_ext_pci = 0x11; + s3->packed_mmio = 1; + + svga->clock_gen = s3; + svga->getclock = s3_trio64_getclock; + break; + + case S3_PHOENIX_TRIO64: + case S3_PHOENIX_TRIO64_ONBOARD: + case S3_DIAMOND_STEALTH64_764: + if (device_get_config_int("memory") == 1) + s3->svga.vram_max = 1 << 20; /* Phoenix BIOS does not expect VRAM to be mirrored. */ + /*FALLTHROUGH*/ + + case S3_NUMBER9_9FX: + svga->decode_mask = (4 << 20) - 1; + s3->id = 0xe1; /*Trio64*/ + s3->id_ext = s3->id_ext_pci = 0x11; + s3->packed_mmio = 1; + + svga->clock_gen = s3; + svga->getclock = s3_trio64_getclock; + break; + + default: + return NULL; + } -static void *s3_phoenix_vision864_init(const device_t *info) -{ - s3_t *s3 = s3_vision864_init(info, L"video/s3/s3/86c864p.bin"); return s3; } static int s3_bahamas64_available(void) { - return rom_present(L"video/s3/s3/bahamas64.bin"); + return rom_present(ROM_PARADISE_BAHAMAS64); } static int s3_phoenix_vision864_available(void) { - return rom_present(L"video/s3/s3/86c864p.bin"); + return rom_present(ROM_PHOENIX_VISION864); } -static void *s3_phoenix_trio32_init(const device_t *info) +static int s3_diamond_stealth64_964_available(void) { - s3_t *s3 = s3_init(info, L"video/s3/s3/86c732p.bin", S3_TRIO32); - - s3->id = 0xe1; /*Trio32*/ - s3->id_ext = 0x10; - s3->id_ext_pci = 0x11; - s3->packed_mmio = 1; - - s3->getclock = s3_trio64_getclock; - s3->getclock_p = s3; - - return s3; + return rom_present(ROM_DIAMOND_STEALTH64_964); } static int s3_phoenix_trio32_available(void) { - return rom_present(L"video/s3/s3/86c732p.bin"); -} - -static void *s3_trio64_init(const device_t *info, wchar_t *bios_fn) -{ - s3_t *s3 = s3_init(info, bios_fn, S3_TRIO64); - - s3->id = 0xe1; /*Trio64*/ - s3->id_ext = s3->id_ext_pci = 0x11; - s3->packed_mmio = 1; - - s3->getclock = s3_trio64_getclock; - s3->getclock_p = s3; - - return s3; -} - -static void *s3_9fx_init(const device_t *info) -{ - s3_t *s3 = s3_trio64_init(info, L"video/s3/s3/s3_764.bin"); - return s3; -} - -static void *s3_phoenix_trio64_init(const device_t *info) -{ - s3_t *s3 = s3_trio64_init(info, L"video/s3/s3/86c764x1.bin"); - if (device_get_config_int("memory") == 1) - s3->svga.vram_max = 1 << 20; /*Phoenix BIOS does not expect VRAM to be mirrored*/ - return s3; -} - -static void *s3_phoenix_trio64_onboard_init(const device_t *info) -{ - s3_t *s3 = s3_trio64_init(info, NULL); - if (device_get_config_int("memory") == 1) - s3->svga.vram_max = 1 << 20; /*Phoenix BIOS does not expect VRAM to be mirrored*/ - return s3; -} - -static void *s3_diamond_stealth64_init(const device_t *info) -{ - s3_t *s3 = s3_trio64_init(info, L"video/s3/s3/stealth64.bin"); - if (device_get_config_int("memory") == 1) - s3->svga.vram_max = 1 << 20; /*Phoenix BIOS does not expect VRAM to be mirrored*/ - return s3; + return rom_present(ROM_PHOENIX_TRIO32); } static int s3_9fx_available(void) { - return rom_present(L"video/s3/s3/s3_764.bin"); + return rom_present(ROM_NUMBER9_9FX); } static int s3_phoenix_trio64_available(void) { - return rom_present(L"video/s3/s3/86c764x1.bin"); + return rom_present(ROM_PHOENIX_TRIO64); } -static int s3_diamond_stealth64_available(void) +static int s3_diamond_stealth64_764_available(void) { - return rom_present(L"video/s3/s3/stealth64.bin"); + return rom_present(ROM_DIAMOND_STEALTH64_764); } static void s3_close(void *p) { - s3_t *s3 = (s3_t *)p; + s3_t *s3 = (s3_t *)p; - svga_close(&s3->svga); - - thread_kill(s3->fifo_thread); - thread_destroy_event(s3->wake_fifo_thread); - thread_destroy_event(s3->fifo_not_full_event); + svga_close(&s3->svga); + + thread_kill(s3->fifo_thread); + thread_destroy_event(s3->wake_fifo_thread); + thread_destroy_event(s3->fifo_not_full_event); - free(s3); + free(s3); } static void s3_speed_changed(void *p) { - s3_t *s3 = (s3_t *)p; - - svga_recalctimings(&s3->svga); + s3_t *s3 = (s3_t *)p; + + svga_recalctimings(&s3->svga); } static void s3_force_redraw(void *p) { - s3_t *s3 = (s3_t *)p; + s3_t *s3 = (s3_t *)p; - s3->svga.fullchange = changeframecount; + s3->svga.fullchange = changeframecount; } -static void s3_add_status_info(char *s, int max_len, void *p) -{ - s3_t *s3 = (s3_t *)p; - char temps[256]; - uint64_t new_time = plat_timer_read(); - uint64_t status_diff = new_time - s3->status_time; - s3->status_time = new_time; - - if (!status_diff) - status_diff = 1; - - svga_add_status_info(s, max_len, &s3->svga); - sprintf(temps, "%f%% CPU\n%f%% CPU (real)\n\n", ((double)s3->blitter_time * 100.0) / timer_freq, ((double)s3->blitter_time * 100.0) / status_diff); - strncat(s, temps, max_len); - - s3->blitter_time = 0; -} - -static const device_config_t s3_bahamas64_config[] = -{ - { - "memory", "Memory size", CONFIG_SELECTION, "", 4, - { - { - "1 MB", 1 - }, - { - "2 MB", 2 - }, - { - "4 MB", 4 - }, - /*Vision864 also supports 8 MB, however the Paradise BIOS is buggy (VESA modes don't work correctly)*/ - { - "" - } - } - }, - { - "", "", -1 - } -}; - static const device_config_t s3_9fx_config[] = { - { - "memory", "Memory size", CONFIG_SELECTION, "", 2, - { - { - "1 MB", 1 - }, - { - "2 MB", 2 - }, - /*Trio64 also supports 4 MB, however the Number Nine BIOS does not*/ - { - "" - } - } - }, - { - "is_pci", "Bus", CONFIG_SELECTION, "", 1, - { - { - "VLB", 0 - }, - { - "PCI", 1 - }, - { - "" - } - } - }, - { - "", "", -1 - } + { + "memory", "Memory size", CONFIG_SELECTION, "", 2, + { + { + "1 MB", 1 + }, + { + "2 MB", 2 + }, + /*Trio64 also supports 4 MB, however the Number Nine BIOS does not*/ + { + "" + } + } + }, + { + "", "", -1 + } }; static const device_config_t s3_phoenix_trio32_config[] = { - { - "memory", "Memory size", CONFIG_SELECTION, "", 2, - { - { - "512 KB", 0 - }, - { - "1 MB", 1 - }, - { - "2 MB", 2 - }, - { - "" - } - } - }, - { - "", "", -1 - } + { + "memory", "Memory size", CONFIG_SELECTION, "", 2, + { + { + "512 KB", 0 + }, + { + "1 MB", 1 + }, + { + "2 MB", 2 + }, + { + "" + } + } + }, + { + "", "", -1 + } }; static const device_config_t s3_phoenix_trio64_onboard_config[] = { - { - "memory", "Video memory size", CONFIG_SELECTION, "", 4, - { - { - "1 MB", 1 - }, - { - "2 MB", 2 - }, - { - "4 MB", 4 - }, - { - "" - } - } - }, - { - "", "", -1 - } + { + "memory", "Video memory size", CONFIG_SELECTION, "", 4, + { + { + "1 MB", 1 + }, + { + "2 MB", 2 + }, + { + "4 MB", 4 + }, + { + "" + } + } + }, + { + "", "", -1 + } }; -static const device_config_t s3_phoenix_trio64_config[] = +static const device_config_t s3_config[] = { - { - "memory", "Memory size", CONFIG_SELECTION, "", 4, - { - { - "1 MB", 1 - }, - { - "2 MB", 2 - }, - { - "4 MB", 4 - }, - { - "" - } - } - }, - { - "", "", -1 - } + { + "memory", "Memory size", CONFIG_SELECTION, "", 4, + { + { + "1 MB", 1 + }, + { + "2 MB", 2 + }, + { + "4 MB", 4 + }, + { + "" + } + } + }, + { + "", "", -1 + } }; -const device_t s3_bahamas64_vlb_device = -{ - "Paradise Bahamas 64 (S3 Vision864) VLB", - DEVICE_VLB, - 0, - s3_bahamas64_init, - s3_close, - NULL, - s3_bahamas64_available, - s3_speed_changed, - s3_force_redraw, - s3_add_status_info, - s3_bahamas64_config + +const device_t s3_bahamas64_vlb_device = { + "Paradise Bahamas 64 (S3 Vision864)", + DEVICE_VLB, + S3_PARADISE_BAHAMAS64, + s3_init, s3_close, NULL, + s3_bahamas64_available, + s3_speed_changed, + s3_force_redraw, + NULL, + s3_config }; -const device_t s3_bahamas64_pci_device = -{ - "Paradise Bahamas 64 (S3 Vision864) PCI", - DEVICE_PCI, - 0, - s3_bahamas64_init, - s3_close, - NULL, - s3_bahamas64_available, - s3_speed_changed, - s3_force_redraw, - s3_add_status_info, - s3_bahamas64_config +const device_t s3_bahamas64_pci_device = { + "Paradise Bahamas 64 (S3 Vision864)", + DEVICE_PCI, + S3_PARADISE_BAHAMAS64, + s3_init, s3_close, NULL, + s3_bahamas64_available, + s3_speed_changed, + s3_force_redraw, + NULL, + s3_config }; -const device_t s3_9fx_vlb_device = -{ - "Number 9 9FX (S3 Trio64) VLB", - DEVICE_VLB, - 0, - s3_9fx_init, - s3_close, - NULL, - s3_9fx_available, - s3_speed_changed, - s3_force_redraw, - s3_add_status_info, - s3_9fx_config +const device_t s3_diamond_stealth64_964_vlb_device = { + "S3 Vision964 (Diamond Stealth64 VRAM)", + DEVICE_VLB, + S3_DIAMOND_STEALTH64_964, + s3_init, s3_close, NULL, + s3_diamond_stealth64_964_available, + s3_speed_changed, + s3_force_redraw, + NULL, + s3_config }; -const device_t s3_9fx_pci_device = -{ - "Number 9 9FX (S3 Trio64) PCI", - DEVICE_PCI, - 0, - s3_9fx_init, - s3_close, - NULL, - s3_9fx_available, - s3_speed_changed, - s3_force_redraw, - s3_add_status_info, - s3_9fx_config +const device_t s3_diamond_stealth64_964_pci_device = { + "S3 Vision964 (Diamond Stealth64 VRAM)", + DEVICE_PCI, + S3_DIAMOND_STEALTH64_964, + s3_init, s3_close, NULL, + s3_diamond_stealth64_964_available, + s3_speed_changed, + s3_force_redraw, + NULL, + s3_config }; -const device_t s3_phoenix_trio32_vlb_device = -{ - "Phoenix S3 Trio32 VLB", - DEVICE_VLB, - 0, - s3_phoenix_trio32_init, - s3_close, - NULL, - s3_phoenix_trio32_available, - s3_speed_changed, - s3_force_redraw, - s3_add_status_info, - s3_phoenix_trio32_config +const device_t s3_9fx_vlb_device = { + "Number 9 9FX (S3 Trio64)", + DEVICE_VLB, + S3_NUMBER9_9FX, + s3_init, s3_close, NULL, + s3_9fx_available, + s3_speed_changed, + s3_force_redraw, + NULL, + s3_9fx_config }; -const device_t s3_phoenix_trio32_pci_device = -{ - "Phoenix S3 Trio32 PCI", - DEVICE_PCI, - 0, - s3_phoenix_trio32_init, - s3_close, - NULL, - s3_phoenix_trio32_available, - s3_speed_changed, - s3_force_redraw, - s3_add_status_info, - s3_phoenix_trio32_config +const device_t s3_9fx_pci_device = { + "Number 9 9FX (S3 Trio64) PCI", + DEVICE_PCI, + S3_NUMBER9_9FX, + s3_init, s3_close, NULL, + s3_9fx_available, + s3_speed_changed, + s3_force_redraw, + NULL, + s3_9fx_config }; -const device_t s3_phoenix_trio64_vlb_device = -{ - "Phoenix S3 Trio64 VLB", - DEVICE_VLB, - 0, - s3_phoenix_trio64_init, - s3_close, - NULL, - s3_phoenix_trio64_available, - s3_speed_changed, - s3_force_redraw, - s3_add_status_info, - s3_phoenix_trio64_config +const device_t s3_phoenix_trio32_vlb_device = { + "Phoenix S3 Trio32", + DEVICE_VLB, + S3_PHOENIX_TRIO32, + s3_init, s3_close, NULL, + s3_phoenix_trio32_available, + s3_speed_changed, + s3_force_redraw, + NULL, + s3_phoenix_trio32_config }; -const device_t s3_phoenix_trio64_onboard_pci_device = -{ - "Phoenix S3 Trio64 On-Board PCI", - DEVICE_PCI, - 1, - s3_phoenix_trio64_onboard_init, - s3_close, - NULL, - NULL, - s3_speed_changed, - s3_force_redraw, - s3_add_status_info, - s3_phoenix_trio64_onboard_config +const device_t s3_phoenix_trio32_pci_device = { + "Phoenix S3 Trio32", + DEVICE_PCI, + S3_PHOENIX_TRIO32, + s3_init, s3_close, NULL, + s3_phoenix_trio32_available, + s3_speed_changed, + s3_force_redraw, + NULL, + s3_phoenix_trio32_config }; -const device_t s3_phoenix_trio64_pci_device = -{ - "Phoenix S3 Trio64 PCI", - DEVICE_PCI, - 0, - s3_phoenix_trio64_init, - s3_close, - NULL, - s3_phoenix_trio64_available, - s3_speed_changed, - s3_force_redraw, - s3_add_status_info, - s3_phoenix_trio64_config +const device_t s3_phoenix_trio64_vlb_device = { + "Phoenix S3 Trio64", + DEVICE_VLB, + S3_PHOENIX_TRIO64, + s3_init, s3_close, NULL, + s3_phoenix_trio64_available, + s3_speed_changed, + s3_force_redraw, + NULL, + s3_config }; -const device_t s3_phoenix_vision864_vlb_device = -{ - "Phoenix S3 Vision864 VLB", - DEVICE_VLB, - 0, - s3_phoenix_vision864_init, - s3_close, - NULL, - s3_phoenix_vision864_available, - s3_speed_changed, - s3_force_redraw, - s3_add_status_info, - s3_bahamas64_config +const device_t s3_phoenix_trio64_pci_device = { + "Phoenix S3 Trio64 PCI", + DEVICE_PCI, + S3_PHOENIX_TRIO64, + s3_init, s3_close, NULL, + s3_phoenix_trio64_available, + s3_speed_changed, + s3_force_redraw, + NULL, + s3_config }; -const device_t s3_phoenix_vision864_pci_device = -{ - "Phoenix S3 Vision864 PCI", - DEVICE_PCI, - 0, - s3_phoenix_vision864_init, - s3_close, - NULL, - s3_phoenix_vision864_available, - s3_speed_changed, - s3_force_redraw, - s3_add_status_info, - s3_bahamas64_config +const device_t s3_phoenix_trio64_onboard_pci_device = { + "Phoenix S3 Trio64 On-Board", + DEVICE_PCI, + S3_PHOENIX_TRIO64_ONBOARD, + s3_init, s3_close, NULL, + NULL, + s3_speed_changed, + s3_force_redraw, + NULL, + s3_phoenix_trio64_onboard_config }; -const device_t s3_diamond_stealth64_vlb_device = -{ - "S3 Trio64 (Diamond Stealth64 DRAM) VLB", - DEVICE_PCI, - 0, - s3_diamond_stealth64_init, - s3_close, - NULL, - s3_diamond_stealth64_available, - s3_speed_changed, - s3_force_redraw, - s3_add_status_info, - s3_phoenix_trio64_config +const device_t s3_phoenix_vision864_vlb_device = { + "Phoenix S3 Vision864", + DEVICE_VLB, + S3_PHOENIX_VISION864, + s3_init, s3_close, NULL, + s3_phoenix_vision864_available, + s3_speed_changed, + s3_force_redraw, + NULL, + s3_config }; -const device_t s3_diamond_stealth64_pci_device = -{ - "S3 Trio64 (Diamond Stealth64 DRAM) PCI", - DEVICE_PCI, - 0, - s3_diamond_stealth64_init, - s3_close, - NULL, - s3_diamond_stealth64_available, - s3_speed_changed, - s3_force_redraw, - s3_add_status_info, - s3_phoenix_trio64_config +const device_t s3_phoenix_vision864_pci_device = { + "Phoenix S3 Vision864", + DEVICE_PCI, + S3_PHOENIX_VISION864, + s3_init, s3_close, NULL, + s3_phoenix_vision864_available, + s3_speed_changed, + s3_force_redraw, + NULL, + s3_config +}; + +const device_t s3_diamond_stealth64_vlb_device = { + "S3 Trio64 (Diamond Stealth64 DRAM)", + DEVICE_PCI, + S3_DIAMOND_STEALTH64_764, + s3_init, s3_close, NULL, + s3_diamond_stealth64_764_available, + s3_speed_changed, + s3_force_redraw, + s3_config +}; + +const device_t s3_diamond_stealth64_pci_device = { + "S3 Trio64 (Diamond Stealth64 DRAM) PCI", + DEVICE_PCI, + S3_DIAMOND_STEALTH64_764, + s3_init, s3_close, NULL, + s3_diamond_stealth64_764_available, + s3_speed_changed, + s3_force_redraw, + NULL, + s3_config }; diff --git a/src/devices/video/vid_s3_virge.c b/src/devices/video/vid_s3_virge.c index 04c0355..4ebdc34 100644 --- a/src/devices/video/vid_s3_virge.c +++ b/src/devices/video/vid_s3_virge.c @@ -8,7 +8,7 @@ * * S3 ViRGE emulation. * - * Version: @(#)vid_s3_virge.c 1.0.11 2018/05/06 + * Version: @(#)vid_s3_virge.c 1.0.12 2018/09/22 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -53,12 +53,11 @@ #include "vid_svga_render.h" + static uint64_t virge_time = 0; -static uint64_t status_time = 0; static int reg_writes = 0, reg_reads = 0; - -static const int8_t dither[4][4] = +static int dither[4][4] = { {0, 4, 1, 5}, {6, 2, 7, 3}, @@ -84,6 +83,26 @@ static const int8_t dither[4][4] = #define FIFO_TYPE 0xff000000 #define FIFO_ADDR 0x00ffffff +#define ROM_DIAMOND_STEALTH3D_2000 L"video/s3/s3virge/s3virge.bin" +#define ROM_DIAMOND_STEALTH3D_3000 L"video/s3/s3virge/diamondstealth3000.vbi" +#define ROM_VIRGE_DX L"video/s3/s3virge/86c375_1.bin" +#define ROM_VIRGE_DX_VBE20 L"video/s3/s3virge/86c375_4.bin" + +enum +{ + S3_DIAMOND_STEALTH3D_2000, + S3_DIAMOND_STEALTH3D_3000, + S3_VIRGE_DX, + S3_VIRGE_DX_VBE20 +}; + +enum +{ + S3_VIRGE, + S3_VIRGEVX, + S3_VIRGEDX +}; + enum { FIFO_INVALID = (0x00 << 24), @@ -102,10 +121,10 @@ typedef struct s3d_t { uint32_t cmd_set; int clip_l, clip_r, clip_t, clip_b; - + uint32_t dest_base; uint32_t dest_str; - + uint32_t z_base; uint32_t z_str; @@ -121,14 +140,14 @@ typedef struct s3d_t int32_t TdWdX, TdWdY; uint32_t tws; - + int32_t TdDdX, TdDdY; uint32_t tds; - + int16_t TdGdX, TdBdX, TdRdX, TdAdX; int16_t TdGdY, TdBdY, TdRdY, TdAdY; uint32_t tgs, tbs, trs, tas; - + uint32_t TdXdY12; uint32_t txend12; uint32_t TdXdY01; @@ -141,14 +160,14 @@ typedef struct s3d_t typedef struct virge_t { - mem_mapping_t linear_mapping; - mem_mapping_t mmio_mapping; - mem_mapping_t new_mmio_mapping; - + mem_map_t linear_mapping; + mem_map_t mmio_mapping; + mem_map_t new_mmio_mapping; + rom_t bios_rom; - + svga_t svga; - + uint8_t bank; uint8_t ma_ext; @@ -160,22 +179,22 @@ typedef struct virge_t int card; int pci; - int is_375; + int chip; int bilinear_enabled; int dithering_enabled; int memory_size; - + int pixel_count, tri_count; - + thread_t *render_thread; event_t *wake_render_thread; event_t *wake_main_thread; event_t *not_full_event; - + uint32_t hwc_fg_col, hwc_bg_col; int hwc_col_stack_pos; - + struct { uint32_t src_base; @@ -192,21 +211,21 @@ typedef struct virge_t int r_width, r_height; int rsrc_x, rsrc_y; int rdest_x, rdest_y; - + int lxend0, lxend1; int32_t ldx; uint32_t lxstart, lystart; int lycnt; int line_dir; - + int src_x, src_y; int dest_x, dest_y; int w, h; uint8_t rop; - + int data_left_count; uint32_t data_left; - + uint32_t pattern_8[8*8]; uint32_t pattern_16[8*8]; uint32_t pattern_32[8*8]; @@ -219,13 +238,13 @@ typedef struct virge_t uint32_t pycnt; uint32_t dest_l, dest_r; } s3d; - + s3d_t s3d_tri; s3d_t s3d_buffer[RB_SIZE]; int s3d_read_idx, s3d_write_idx; int s3d_busy; - + struct { uint32_t pri_ctrl; @@ -251,9 +270,9 @@ typedef struct virge_t uint32_t pri_size; uint32_t sec_start; uint32_t sec_size; - + int sdif; - + int pri_x, pri_y, pri_w, pri_h; int sec_x, sec_y, sec_w, sec_h; } streams; @@ -264,12 +283,16 @@ typedef struct virge_t thread_t *fifo_thread; event_t *wake_fifo_thread; event_t *fifo_not_full_event; - + int virge_busy; uint8_t subsys_stat, subsys_cntl; } virge_t; +static video_timings_t timing_diamond_stealth3d_2000 = {VID_BUS, 2, 2, 3, 28, 28, 45}; +static video_timings_t timing_diamond_stealth3d_3000 = {VID_BUS, 2, 2, 4, 26, 26, 42}; +static video_timings_t timing_virge_dx = {VID_BUS, 2, 2, 3, 28, 28, 45}; + static __inline void wake_fifo_thread(virge_t *virge) { thread_set_event(virge->wake_fifo_thread); /*Wake up FIFO thread if moving from idle*/ @@ -293,29 +316,29 @@ enum { CMD_SET_AE = 1, CMD_SET_HC = (1 << 1), - + CMD_SET_FORMAT_MASK = (7 << 2), CMD_SET_FORMAT_8 = (0 << 2), CMD_SET_FORMAT_16 = (1 << 2), CMD_SET_FORMAT_24 = (2 << 2), - + CMD_SET_MS = (1 << 6), CMD_SET_IDS = (1 << 7), CMD_SET_MP = (1 << 8), CMD_SET_TP = (1 << 9), - + CMD_SET_ITA_MASK = (3 << 10), CMD_SET_ITA_BYTE = (0 << 10), CMD_SET_ITA_WORD = (1 << 10), CMD_SET_ITA_DWORD = (2 << 10), - + CMD_SET_ZUP = (1 << 23), - + CMD_SET_ZB_MODE = (3 << 24), CMD_SET_XP = (1 << 25), CMD_SET_YP = (1 << 26), - + CMD_SET_COMMAND_MASK = (15 << 27) }; @@ -339,6 +362,27 @@ enum #define INT_3DF_EMP (1 << 6) #define INT_MASK 0xff + +#ifdef ENABLE_S3_VIRGE_LOG +int s3_virge_do_log = ENABLE_S3_VIRGE_LOG; +#endif + + +static void +s3_virge_log(const char *format, ...) +{ +#ifdef ENABLE_S3_VIRGE_LOG + va_list ap; + + if (s3_virge_do_log) { + va_start(ap, format); + pclog_ex(format, ap); + va_end(ap); + } +#endif +} + + static void s3_virge_update_irqs(virge_t *virge) { if (!virge->pci) @@ -360,7 +404,7 @@ static void s3_virge_out(uint16_t addr, uint8_t val, void *p) if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) addr ^= 0x60; - + switch (addr) { case 0x3c5: @@ -376,7 +420,7 @@ static void s3_virge_out(uint16_t addr, uint8_t val, void *p) else svga->write_bank = svga->read_bank = virge->bank << 14; } break; - + case 0x3d4: svga->crtcreg = val; return; @@ -399,11 +443,11 @@ static void s3_virge_out(uint16_t addr, uint8_t val, void *p) case 0x32: s3_virge_update_irqs(virge); break; - + case 0x69: virge->ma_ext = val & 0x1f; break; - + case 0x35: virge->bank = (virge->bank & 0x70) | (val & 0xf); if (svga->chain4) svga->write_bank = svga->read_bank = virge->bank << 16; @@ -420,11 +464,11 @@ static void s3_virge_out(uint16_t addr, uint8_t val, void *p) if (svga->chain4) svga->write_bank = svga->read_bank = virge->bank << 16; else svga->write_bank = svga->read_bank = virge->bank << 14; break; - + case 0x3a: if (val & 0x10) svga->gdcreg[5] |= 0x40; /*Horrible cheat*/ break; - + case 0x45: svga->hwcursor.ena = val & 1; break; @@ -436,7 +480,7 @@ static void s3_virge_out(uint16_t addr, uint8_t val, void *p) svga->hwcursor.yoff = svga->crtc[0x4f] & 63; svga->hwcursor.addr = ((((svga->crtc[0x4c] << 8) | svga->crtc[0x4d]) & 0xfff) * 1024) + (svga->hwcursor.yoff * 16); break; - + case 0x4a: switch (virge->hwc_col_stack_pos) { @@ -472,14 +516,14 @@ static void s3_virge_out(uint16_t addr, uint8_t val, void *p) case 0x58: case 0x59: case 0x5a: s3_virge_updatemapping(virge); break; - + case 0x67: switch (val >> 4) { case 2: case 3: svga->bpp = 15; break; case 4: case 5: svga->bpp = 16; break; case 7: svga->bpp = 24; break; - case 13: svga->bpp = ((video_card == VID_VIRGEVX_VLB) || (video_card == VID_VIRGEVX_PCI)) ? 24 : 32; break; + case 13: svga->bpp = (virge->chip == S3_VIRGEVX) ? 24 : 32; break; default: svga->bpp = 8; break; } break; @@ -502,7 +546,7 @@ static uint8_t s3_virge_in(uint16_t addr, void *p) virge_t *virge = (virge_t *)p; svga_t *svga = &virge->svga; uint8_t ret; - + if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) addr ^= 0x60; @@ -513,7 +557,7 @@ static uint8_t s3_virge_in(uint16_t addr, void *p) ret = 0xff; else ret = svga_in(addr, svga); - break; + break; case 0x3c5: if (svga->seqaddr >= 8) @@ -544,7 +588,7 @@ static uint8_t s3_virge_in(uint16_t addr, void *p) default: ret = svga->crtc[svga->crtcreg]; break; } break; - + default: ret = svga_in(addr, svga); break; @@ -576,25 +620,25 @@ static void s3_virge_recalctimings(svga_t *svga) { switch (svga->bpp) { - case 8: - svga->render = svga_render_8bpp_highres; + case 8: + svga->render = svga_render_8bpp_highres; break; - case 15: - svga->render = svga_render_15bpp_highres; + case 15: + svga->render = svga_render_15bpp_highres; break; - case 16: - svga->render = svga_render_16bpp_highres; + case 16: + svga->render = svga_render_16bpp_highres; break; - case 24: - svga->render = svga_render_24bpp_highres; + case 24: + svga->render = svga_render_24bpp_highres; break; - case 32: - svga->render = svga_render_32bpp_highres; + case 32: + svga->render = svga_render_32bpp_highres; break; } } - if ((video_card != VID_VIRGEVX_VLB) && (video_card != VID_VIRGEVX_PCI)) + if (virge->chip == S3_VIRGEVX) { if ((svga->bpp == 15) || (svga->bpp == 16)) { @@ -614,11 +658,11 @@ static void s3_virge_recalctimings(svga_t *svga) svga->ma_latch = virge->streams.pri_fb1 >> 2; else svga->ma_latch = virge->streams.pri_fb0 >> 2; - + svga->hdisp = virge->streams.pri_w + 1; if (virge->streams.pri_h < svga->dispend) svga->dispend = virge->streams.pri_h; - + svga->overlay.x = virge->streams.sec_x - virge->streams.pri_x; svga->overlay.y = virge->streams.sec_y - virge->streams.pri_y; svga->overlay.ysize = virge->streams.sec_h; @@ -635,21 +679,21 @@ static void s3_virge_recalctimings(svga_t *svga) switch ((virge->streams.pri_ctrl >> 24) & 0x7) { case 0: /*RGB-8 (CLUT)*/ - svga->render = svga_render_8bpp_highres; + svga->render = svga_render_8bpp_highres; break; case 3: /*KRGB-16 (1.5.5.5)*/ svga->htotal >>= 1; - svga->render = svga_render_15bpp_highres; + svga->render = svga_render_15bpp_highres; break; - case 5: /*RGB-16 (5.6.5)*/ + case 5: /*RGB-16 (5.6.5)*/ svga->htotal >>= 1; - svga->render = svga_render_16bpp_highres; + svga->render = svga_render_16bpp_highres; break; - case 6: /*RGB-24 (8.8.8)*/ - svga->render = svga_render_24bpp_highres; + case 6: /*RGB-24 (8.8.8)*/ + svga->render = svga_render_24bpp_highres; break; case 7: /*XRGB-32 (X.8.8.8)*/ - svga->render = svga_render_32bpp_highres; + svga->render = svga_render_32bpp_highres; break; } svga->vram_display_mask = (virge->memory_size << 20) - 1; @@ -658,7 +702,7 @@ static void s3_virge_recalctimings(svga_t *svga) if (((svga->miscout >> 2) & 3) == 3) { int n = svga->seqregs[0x12] & 0x1f; - int r = (svga->seqregs[0x12] >> 5) & ((virge->is_375 || ((video_card == VID_VIRGEVX_VLB) || (video_card == VID_VIRGEVX_PCI))) ? 7 : 3); + int r = (svga->seqregs[0x12] >> 5) & (((virge->chip == S3_VIRGEVX) || (virge->chip == S3_VIRGEDX)) ? 7 : 3); int m = svga->seqregs[0x13] & 0x7f; double freq = (((double)m + 2) / (((double)n + 2) * (double)(1 << r))) * 14318184.0; @@ -672,37 +716,37 @@ static void s3_virge_updatemapping(virge_t *virge) if (!(virge->pci_regs[PCI_REG_COMMAND] & PCI_COMMAND_MEM)) { - mem_mapping_disable(&svga->mapping); - mem_mapping_disable(&virge->linear_mapping); - mem_mapping_disable(&virge->mmio_mapping); - mem_mapping_disable(&virge->new_mmio_mapping); + mem_map_disable(&svga->mapping); + mem_map_disable(&virge->linear_mapping); + mem_map_disable(&virge->mmio_mapping); + mem_map_disable(&virge->new_mmio_mapping); return; } - //pclog("Update mapping - bank %02X ", svga->gdcreg[6] & 0xc); + s3_virge_log("Update mapping - bank %02X ", svga->gdcreg[6] & 0xc); switch (svga->gdcreg[6] & 0xc) /*Banked framebuffer*/ { case 0x0: /*128k at A0000*/ - mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x20000); + mem_map_set_addr(&svga->mapping, 0xa0000, 0x20000); svga->banked_mask = 0xffff; break; case 0x4: /*64k at A0000*/ - mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000); + mem_map_set_addr(&svga->mapping, 0xa0000, 0x10000); svga->banked_mask = 0xffff; break; case 0x8: /*32k at B0000*/ - mem_mapping_set_addr(&svga->mapping, 0xb0000, 0x08000); + mem_map_set_addr(&svga->mapping, 0xb0000, 0x08000); svga->banked_mask = 0x7fff; break; case 0xC: /*32k at B8000*/ - mem_mapping_set_addr(&svga->mapping, 0xb8000, 0x08000); + mem_map_set_addr(&svga->mapping, 0xb8000, 0x08000); svga->banked_mask = 0x7fff; break; } virge->linear_base = (svga->crtc[0x5a] << 16) | (svga->crtc[0x59] << 24); - //pclog("Linear framebuffer %02X ", svga->crtc[0x58] & 0x10); + s3_virge_log("Linear framebuffer %02X ", svga->crtc[0x58] & 0x10); if (svga->crtc[0x58] & 0x10) /*Linear framebuffer*/ { switch (svga->crtc[0x58] & 3) @@ -721,39 +765,39 @@ static void s3_virge_updatemapping(virge_t *virge) break; } virge->linear_base &= ~(virge->linear_size - 1); - svga->linear_base = virge->linear_base; - //pclog("Linear framebuffer at %08X size %08X\n", virge->linear_base, virge->linear_size); + s3_virge_log("Linear framebuffer at %08X size %08X\n", virge->linear_base, virge->linear_size); if (virge->linear_base == 0xa0000) { - mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000); - mem_mapping_disable(&virge->linear_mapping); + mem_map_set_addr(&svga->mapping, 0xa0000, 0x10000); + mem_map_disable(&virge->linear_mapping); } else - mem_mapping_set_addr(&virge->linear_mapping, virge->linear_base, virge->linear_size); + mem_map_set_addr(&virge->linear_mapping, virge->linear_base, virge->linear_size); svga->fb_only = 1; } else { - mem_mapping_disable(&virge->linear_mapping); + mem_map_disable(&virge->linear_mapping); svga->fb_only = 0; } - //pclog("Memory mapped IO %02X\n", svga->crtc[0x53] & 0x18); - if (svga->crtc[0x53] & 0x10) /*Old MMIO*/ - { - if (svga->crtc[0x53] & 0x20) - mem_mapping_set_addr(&virge->mmio_mapping, 0xb8000, 0x8000); - else - mem_mapping_set_addr(&virge->mmio_mapping, 0xa0000, 0x10000); - } - else - mem_mapping_disable(&virge->mmio_mapping); + /* Memory mapped I/O. */ + s3_virge_log("Memory mapped IO %02X\n", svga->crtc[0x53] & 0x18); - if (svga->crtc[0x53] & 0x08) /*New MMIO*/ - mem_mapping_set_addr(&virge->new_mmio_mapping, virge->linear_base + 0x1000000, 0x10000); - else - mem_mapping_disable(&virge->new_mmio_mapping); + /* Old MMIO. */ + if (svga->crtc[0x53] & 0x10) { + if (svga->crtc[0x53] & 0x20) + mem_map_set_addr(&virge->mmio_mapping, 0xb8000, 0x8000); + else + mem_map_set_addr(&virge->mmio_mapping, 0xa0000, 0x10000); + } else + mem_map_disable(&virge->mmio_mapping); + /* New MMIO. */ + if (svga->crtc[0x53] & 0x08) + mem_map_set_addr(&virge->new_mmio_mapping, virge->linear_base + 0x1000000, 0x10000); + else + mem_map_disable(&virge->new_mmio_mapping); } static void s3_virge_vblank_start(svga_t *svga) @@ -889,7 +933,7 @@ static uint32_t s3_virge_mmio_read_l(uint32_t addr, void *p) case 0x81fc: ret = virge->streams.sec_size; break; - + case 0x8504: if (virge->s3d_busy || virge->virge_busy || !FIFO_EMPTY) ret = (0x10 << 8); @@ -959,7 +1003,7 @@ static uint32_t s3_virge_mmio_read_l(uint32_t addr, void *p) s3_virge_wait_fifo_idle(virge); ret = (virge->s3d.rdest_x << 16) | virge->s3d.rdest_y; break; - + default: ret = s3_virge_mmio_read_w(addr, p) | (s3_virge_mmio_read_w(addr + 2, p) << 16); } @@ -969,7 +1013,7 @@ static uint32_t s3_virge_mmio_read_l(uint32_t addr, void *p) static void fifo_thread(void *param) { virge_t *virge = (virge_t *)param; - + while (1) { thread_set_event(virge->fifo_not_full_event); @@ -1260,7 +1304,7 @@ static void fifo_thread(void *param) virge->s3d_tri.tas = (val >> 16) & 0xffff; virge->s3d_tri.trs = val & 0xffff; break; - + case 0xb554: virge->s3d_tri.TdZdX = val; break; @@ -1302,7 +1346,7 @@ static void fifo_thread(void *param) } break; } - + virge->fifo_read_idx++; fifo->addr_type = FIFO_INVALID; @@ -1333,7 +1377,7 @@ static void s3_virge_queue(virge_t *virge, uint32_t addr, uint32_t val, uint32_t fifo->addr_type = (addr & FIFO_ADDR) | type; virge->fifo_write_idx++; - + /* if (FIFO_ENTRIES > 0xe000) wake_fifo_thread(virge); */ if (FIFO_ENTRIES > 0xe000 || FIFO_ENTRIES < 8) @@ -1343,8 +1387,8 @@ static void s3_virge_queue(virge_t *virge, uint32_t addr, uint32_t val, uint32_t static void s3_virge_mmio_write(uint32_t addr, uint8_t val, void *p) { virge_t *virge = (virge_t *)p; - - reg_writes++; + + reg_writes++; if ((addr & 0xfffc) < 0x8000) { s3_virge_queue(virge, addr, val, FIFO_WRITE_BYTE); @@ -1398,7 +1442,7 @@ static void s3_virge_mmio_write_l(uint32_t addr, uint32_t val, void *p) if (virge->s3d.cmd_set & CMD_SET_MS) s3_virge_bitblt(virge, 32, ((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24)); else - s3_virge_bitblt(virge, 32, val); + s3_virge_bitblt(virge, 32, val); } else { @@ -1413,7 +1457,7 @@ static void s3_virge_mmio_write_l(uint32_t addr, uint32_t val, void *p) else s3_virge_bitblt(virge, 32, val); break; - + case 0x8180: virge->streams.pri_ctrl = val; svga_recalctimings(svga); @@ -1503,28 +1547,28 @@ static void s3_virge_mmio_write_l(uint32_t addr, uint32_t val, void *p) case 0x81f0: virge->streams.pri_start = val; virge->streams.pri_x = (val >> 16) & 0x7ff; - virge->streams.pri_y = val & 0x7ff; + virge->streams.pri_y = val & 0x7ff; svga_recalctimings(svga); svga->fullchange = changeframecount; break; case 0x81f4: virge->streams.pri_size = val; virge->streams.pri_w = (val >> 16) & 0x7ff; - virge->streams.pri_h = val & 0x7ff; + virge->streams.pri_h = val & 0x7ff; svga_recalctimings(svga); svga->fullchange = changeframecount; break; case 0x81f8: virge->streams.sec_start = val; virge->streams.sec_x = (val >> 16) & 0x7ff; - virge->streams.sec_y = val & 0x7ff; + virge->streams.sec_y = val & 0x7ff; svga_recalctimings(svga); svga->fullchange = changeframecount; break; case 0x81fc: virge->streams.sec_size = val; virge->streams.sec_w = (val >> 16) & 0x7ff; - virge->streams.sec_h = val & 0x7ff; + virge->streams.sec_h = val & 0x7ff; svga_recalctimings(svga); svga->fullchange = changeframecount; break; @@ -1534,7 +1578,7 @@ static void s3_virge_mmio_write_l(uint32_t addr, uint32_t val, void *p) virge->subsys_cntl = (val >> 8); s3_virge_update_irqs(virge); break; - + case 0xa000: case 0xa004: case 0xa008: case 0xa00c: case 0xa010: case 0xa014: case 0xa018: case 0xa01c: case 0xa020: case 0xa024: case 0xa028: case 0xa02c: @@ -1574,7 +1618,7 @@ static void s3_virge_mmio_write_l(uint32_t addr, uint32_t val, void *p) virge->s3d.pattern_8[y*8 + x + 1] = val >> 8; virge->s3d.pattern_8[y*8 + x + 2] = val >> 16; virge->s3d.pattern_8[y*8 + x + 3] = val >> 24; - + x = (addr >> 1) & 6; y = (addr >> 4) & 7; virge->s3d.pattern_16[y*8 + x] = val & 0xffff; @@ -1686,7 +1730,7 @@ static void s3_virge_mmio_write_l(uint32_t addr, uint32_t val, void *p) if (virge->s3d.cmd_set & CMD_SET_AE) s3_virge_bitblt(virge, -1, 0); break; - + case 0xb4d4: virge->s3d_tri.z_base = val & 0x3ffff8; break; @@ -1785,7 +1829,7 @@ static void s3_virge_mmio_write_l(uint32_t addr, uint32_t val, void *p) virge->s3d_tri.tas = (val >> 16) & 0xffff; virge->s3d_tri.trs = val & 0xffff; break; - + case 0xb554: virge->s3d_tri.TdZdX = val; break; @@ -1938,7 +1982,7 @@ static void s3_virge_bitblt(virge_t *virge, int count, uint32_t cpu_dat) uint32_t source = 0, dest = 0, pattern; uint32_t out = 0; int update; - + switch (virge->s3d.cmd_set & CMD_SET_FORMAT_MASK) { case CMD_SET_FORMAT_8: @@ -1969,7 +2013,7 @@ static void s3_virge_bitblt(virge_t *virge, int count, uint32_t cpu_dat) } if (virge->s3d.cmd_set & CMD_SET_MP) pattern_data = mono_pattern; - + switch (virge->s3d.cmd_set & CMD_SET_ITA_MASK) { case CMD_SET_ITA_BYTE: @@ -2005,7 +2049,7 @@ static void s3_virge_bitblt(virge_t *virge, int count, uint32_t cpu_dat) { case CMD_SET_COMMAND_NOP: break; - + case CMD_SET_COMMAND_BITBLT: if (count == -1) { @@ -2017,8 +2061,8 @@ static void s3_virge_bitblt(virge_t *virge, int count, uint32_t cpu_dat) virge->s3d.h = virge->s3d.r_height; virge->s3d.rop = (virge->s3d.cmd_set >> 17) & 0xff; virge->s3d.data_left_count = 0; - -/* pclog("BitBlt start %i,%i %i,%i %i,%i %02X %x %x\n", + + s3_virge_log("BitBlt start %i,%i %i,%i %i,%i %02X %x %x\n", virge->s3d.src_x, virge->s3d.src_y, virge->s3d.dest_x, @@ -2027,8 +2071,8 @@ static void s3_virge_bitblt(virge_t *virge, int count, uint32_t cpu_dat) virge->s3d.h, virge->s3d.rop, virge->s3d.src_base, - virge->s3d.dest_base);*/ - + virge->s3d.dest_base); + if (virge->s3d.cmd_set & CMD_SET_IDS) return; } @@ -2099,7 +2143,7 @@ static void s3_virge_bitblt(virge_t *virge, int count, uint32_t cpu_dat) WRITE(dest_addr, out); } - + virge->s3d.src_x += x_inc; virge->s3d.src_x &= 0x7ff; virge->s3d.dest_x += x_inc; @@ -2133,10 +2177,10 @@ static void s3_virge_bitblt(virge_t *virge, int count, uint32_t cpu_dat) } } else - virge->s3d.w--; + virge->s3d.w--; } break; - + case CMD_SET_COMMAND_RECTFILL: /*No source, pattern = pat_fg_clr*/ if (count == -1) @@ -2148,32 +2192,30 @@ static void s3_virge_bitblt(virge_t *virge, int count, uint32_t cpu_dat) virge->s3d.w = virge->s3d.r_width; virge->s3d.h = virge->s3d.r_height; virge->s3d.rop = (virge->s3d.cmd_set >> 17) & 0xff; - -/* pclog("RctFll start %i,%i %i,%i %02X %08x\n", virge->s3d.dest_x, + + s3_virge_log("RctFll start %i,%i %i,%i %02X %08x\n", virge->s3d.dest_x, virge->s3d.dest_y, virge->s3d.w, virge->s3d.h, - virge->s3d.rop, virge->s3d.dest_base);*/ + virge->s3d.rop, virge->s3d.dest_base); } while (count && virge->s3d.h) { - uint32_t daddr = virge->s3d.dest_base + (virge->s3d.dest_x * x_mul) + (virge->s3d.dest_y * virge->s3d.dest_str); - source = 0; - dest = 0; - pattern = virge->s3d.pat_fg_clr; - out = 0; - update = 1; + uint32_t dest_addr = virge->s3d.dest_base + (virge->s3d.dest_x * x_mul) + (virge->s3d.dest_y * virge->s3d.dest_str); + uint32_t source = 0, dest = 0, pattern = virge->s3d.pat_fg_clr; + uint32_t out = 0; + int update = 1; CLIP(virge->s3d.dest_x, virge->s3d.dest_y); if (update) { - READ(daddr, dest); + READ(dest_addr, dest); MIX(); - WRITE(daddr, out); + WRITE(dest_addr, out); } virge->s3d.src_x += x_inc; @@ -2195,11 +2237,11 @@ static void s3_virge_bitblt(virge_t *virge, int count, uint32_t cpu_dat) } } else - virge->s3d.w--; + virge->s3d.w--; count--; } break; - + case CMD_SET_COMMAND_LINE: if (count == -1) { @@ -2213,7 +2255,7 @@ static void s3_virge_bitblt(virge_t *virge, int count, uint32_t cpu_dat) int x; int new_x; int first_pixel = 1; - + x = virge->s3d.dest_x >> 20; if (virge->s3d.h == virge->s3d.lycnt && @@ -2226,18 +2268,17 @@ static void s3_virge_bitblt(virge_t *virge, int count, uint32_t cpu_dat) else new_x = (virge->s3d.dest_x + virge->s3d.ldx) >> 20; - + if ((virge->s3d.line_dir && x > new_x) || (!virge->s3d.line_dir && x < new_x)) goto skip_line; - + do { - uint32_t daddr = virge->s3d.dest_base + (x * x_mul) + (virge->s3d.dest_y * virge->s3d.dest_str); - source = 0; - dest = 0; - out = 0; - update = 1; + uint32_t dest_addr = virge->s3d.dest_base + (x * x_mul) + (virge->s3d.dest_y * virge->s3d.dest_str); + uint32_t source = 0, dest = 0, pattern; + uint32_t out = 0; + int update = 1; if ((virge->s3d.h == virge->s3d.lycnt || !first_pixel) && ((virge->s3d.line_dir && x < virge->s3d.lxend0) || @@ -2253,14 +2294,14 @@ static void s3_virge_bitblt(virge_t *virge, int count, uint32_t cpu_dat) if (update) { - READ(daddr, dest); + READ(dest_addr, dest); pattern = virge->s3d.pat_fg_clr; MIX(); - WRITE(daddr, out); + WRITE(dest_addr, out); } - + if (x < new_x) x++; else if (x > new_x) @@ -2291,23 +2332,22 @@ skip_line: int xdir = (x < xend) ? 1 : -1; do { - uint32_t daddr = virge->s3d.dest_base + (x * x_mul) + (y * virge->s3d.dest_str); - source = 0; - dest = 0; - out = 0; - update = 1; + uint32_t dest_addr = virge->s3d.dest_base + (x * x_mul) + (y * virge->s3d.dest_str); + uint32_t source = 0, dest = 0, pattern; + uint32_t out = 0; + int update = 1; CLIP(x, y); if (update) { - READ(daddr, dest); + READ(dest_addr, dest); pattern = pattern_data[(y & 7)*8 + (x & 7)]; MIX(); - WRITE(daddr, out); + WRITE(dest_addr, out); } - + x = (x + xdir) & 0x7ff; } while (x != (xend + xdir)); @@ -2356,21 +2396,21 @@ typedef struct s3d_state_t int32_t r, g, b, a, u, v, d, w; int32_t base_r, base_g, base_b, base_a, base_u, base_v, base_d, base_w; - + uint32_t base_z; uint32_t tbu, tbv; uint32_t cmd_set; int max_d; - + uint16_t *texture[10]; - + uint32_t tex_bdr_clr; - + int32_t x1, x2; int y; - + rgba_t dest_rgba; } s3d_state_t; @@ -2378,7 +2418,7 @@ typedef struct s3d_texture_state_t { int level; int texture_shift; - + int32_t u, v; } s3d_texture_state_t; @@ -2512,12 +2552,12 @@ static void tex_sample_normal_filter(s3d_state_t *state) texture_state.u = state->u + state->tbu + tex_offset; texture_state.v = state->v + state->tbv + tex_offset; tex_read(state, &texture_state, &tex_samples[3]); - + d[0] = (256 - du) * (256 - dv); d[1] = du * (256 - dv); d[2] = (256 - du) * dv; d[3] = du * dv; - + state->dest_rgba.r = (tex_samples[0].r * d[0] + tex_samples[1].r * d[1] + tex_samples[2].r * d[2] + tex_samples[3].r * d[3]) >> 16; state->dest_rgba.g = (tex_samples[0].g * d[0] + tex_samples[1].g * d[1] + tex_samples[2].g * d[2] + tex_samples[3].g * d[3]) >> 16; state->dest_rgba.b = (tex_samples[0].b * d[0] + tex_samples[1].b * d[1] + tex_samples[2].b * d[2] + tex_samples[3].b * d[3]) >> 16; @@ -2551,7 +2591,7 @@ static void tex_sample_mipmap_filter(s3d_state_t *state) texture_state.level = 0; texture_state.texture_shift = 18 + (9 - texture_state.level); tex_offset = 1 << texture_state.texture_shift; - + texture_state.u = state->u + state->tbu; texture_state.v = state->v + state->tbv; tex_read(state, &texture_state, &tex_samples[0]); @@ -2574,7 +2614,7 @@ static void tex_sample_mipmap_filter(s3d_state_t *state) d[1] = du * (256 - dv); d[2] = (256 - du) * dv; d[3] = du * dv; - + state->dest_rgba.r = (tex_samples[0].r * d[0] + tex_samples[1].r * d[1] + tex_samples[2].r * d[2] + tex_samples[3].r * d[3]) >> 16; state->dest_rgba.g = (tex_samples[0].g * d[0] + tex_samples[1].g * d[1] + tex_samples[2].g * d[2] + tex_samples[3].g * d[3]) >> 16; state->dest_rgba.b = (tex_samples[0].b * d[0] + tex_samples[1].b * d[1] + tex_samples[2].b * d[2] + tex_samples[3].b * d[3]) >> 16; @@ -2588,7 +2628,7 @@ static void tex_sample_persp_normal(s3d_state_t *state) if (state->w) w = (int32_t)(((1ULL << 27) << 19) / (int64_t)state->w); - + texture_state.level = state->max_d; texture_state.texture_shift = 18 + (9 - texture_state.level); texture_state.u = (int32_t)(((int64_t)state->u * (int64_t)w) >> (12 + state->max_d)) + state->tbu; @@ -2615,7 +2655,7 @@ static void tex_sample_persp_normal_filter(s3d_state_t *state) texture_state.level = state->max_d; texture_state.texture_shift = 18 + (9 - texture_state.level); tex_offset = 1 << texture_state.texture_shift; - + texture_state.u = u; texture_state.v = v; tex_read(state, &texture_state, &tex_samples[0]); @@ -2638,7 +2678,7 @@ static void tex_sample_persp_normal_filter(s3d_state_t *state) d[1] = du * (256 - dv); d[2] = (256 - du) * dv; d[3] = du * dv; - + state->dest_rgba.r = (tex_samples[0].r * d[0] + tex_samples[1].r * d[1] + tex_samples[2].r * d[2] + tex_samples[3].r * d[3]) >> 16; state->dest_rgba.g = (tex_samples[0].g * d[0] + tex_samples[1].g * d[1] + tex_samples[2].g * d[2] + tex_samples[3].g * d[3]) >> 16; state->dest_rgba.b = (tex_samples[0].b * d[0] + tex_samples[1].b * d[1] + tex_samples[2].b * d[2] + tex_samples[3].b * d[3]) >> 16; @@ -2652,7 +2692,7 @@ static void tex_sample_persp_normal_375(s3d_state_t *state) if (state->w) w = (int32_t)(((1ULL << 27) << 19) / (int64_t)state->w); - + texture_state.level = state->max_d; texture_state.texture_shift = 18 + (9 - texture_state.level); texture_state.u = (int32_t)(((int64_t)state->u * (int64_t)w) >> (8 + state->max_d)) + state->tbu; @@ -2675,7 +2715,7 @@ static void tex_sample_persp_normal_filter_375(s3d_state_t *state) u = (int32_t)(((int64_t)state->u * (int64_t)w) >> (8 + state->max_d)) + state->tbu; v = (int32_t)(((int64_t)state->v * (int64_t)w) >> (8 + state->max_d)) + state->tbv; - + texture_state.level = state->max_d; texture_state.texture_shift = 18 + (9 - texture_state.level); tex_offset = 1 << texture_state.texture_shift; @@ -2702,7 +2742,7 @@ static void tex_sample_persp_normal_filter_375(s3d_state_t *state) d[1] = du * (256 - dv); d[2] = (256 - du) * dv; d[3] = du * dv; - + state->dest_rgba.r = (tex_samples[0].r * d[0] + tex_samples[1].r * d[1] + tex_samples[2].r * d[2] + tex_samples[3].r * d[3]) >> 16; state->dest_rgba.g = (tex_samples[0].g * d[0] + tex_samples[1].g * d[1] + tex_samples[2].g * d[2] + tex_samples[3].g * d[3]) >> 16; state->dest_rgba.b = (tex_samples[0].b * d[0] + tex_samples[1].b * d[1] + tex_samples[2].b * d[2] + tex_samples[3].b * d[3]) >> 16; @@ -2717,7 +2757,7 @@ static void tex_sample_persp_mipmap(s3d_state_t *state) if (state->w) w = (int32_t)(((1ULL << 27) << 19) / (int64_t)state->w); - + texture_state.level = (state->d < 0) ? state->max_d : state->max_d - ((state->d >> 27) & 0xf); if (texture_state.level < 0) texture_state.level = 0; @@ -2742,7 +2782,7 @@ static void tex_sample_persp_mipmap_filter(s3d_state_t *state) u = (int32_t)(((int64_t)state->u * (int64_t)w) >> (12 + state->max_d)) + state->tbu; v = (int32_t)(((int64_t)state->v * (int64_t)w) >> (12 + state->max_d)) + state->tbv; - + texture_state.level = (state->d < 0) ? state->max_d : state->max_d - ((state->d >> 27) & 0xf); if (texture_state.level < 0) texture_state.level = 0; @@ -2771,7 +2811,7 @@ static void tex_sample_persp_mipmap_filter(s3d_state_t *state) d[1] = du * (256 - dv); d[2] = (256 - du) * dv; d[3] = du * dv; - + state->dest_rgba.r = (tex_samples[0].r * d[0] + tex_samples[1].r * d[1] + tex_samples[2].r * d[2] + tex_samples[3].r * d[3]) >> 16; state->dest_rgba.g = (tex_samples[0].g * d[0] + tex_samples[1].g * d[1] + tex_samples[2].g * d[2] + tex_samples[3].g * d[3]) >> 16; state->dest_rgba.b = (tex_samples[0].b * d[0] + tex_samples[1].b * d[1] + tex_samples[2].b * d[2] + tex_samples[3].b * d[3]) >> 16; @@ -2785,7 +2825,7 @@ static void tex_sample_persp_mipmap_375(s3d_state_t *state) if (state->w) w = (int32_t)(((1ULL << 27) << 19) / (int64_t)state->w); - + texture_state.level = (state->d < 0) ? state->max_d : state->max_d - ((state->d >> 27) & 0xf); if (texture_state.level < 0) texture_state.level = 0; @@ -2810,13 +2850,13 @@ static void tex_sample_persp_mipmap_filter_375(s3d_state_t *state) u = (int32_t)(((int64_t)state->u * (int64_t)w) >> (8 + state->max_d)) + state->tbu; v = (int32_t)(((int64_t)state->v * (int64_t)w) >> (8 + state->max_d)) + state->tbv; - + texture_state.level = (state->d < 0) ? state->max_d : state->max_d - ((state->d >> 27) & 0xf); if (texture_state.level < 0) texture_state.level = 0; texture_state.texture_shift = 18 + (9 - texture_state.level); tex_offset = 1 << texture_state.texture_shift; - + texture_state.u = u; texture_state.v = v; tex_read(state, &texture_state, &tex_samples[0]); @@ -2839,7 +2879,7 @@ static void tex_sample_persp_mipmap_filter_375(s3d_state_t *state) d[1] = du * (256 - dv); d[2] = (256 - du) * dv; d[3] = du * dv; - + state->dest_rgba.r = (tex_samples[0].r * d[0] + tex_samples[1].r * d[1] + tex_samples[2].r * d[2] + tex_samples[3].r * d[3]) >> 16; state->dest_rgba.g = (tex_samples[0].g * d[0] + tex_samples[1].g * d[1] + tex_samples[2].g * d[2] + tex_samples[3].g * d[3]) >> 16; state->dest_rgba.b = (tex_samples[0].b * d[0] + tex_samples[1].b * d[1] + tex_samples[2].b * d[2] + tex_samples[3].b * d[3]) >> 16; @@ -2928,11 +2968,11 @@ static void dest_pixel_lit_texture_reflection(s3d_state_t *state) static void dest_pixel_lit_texture_modulate(s3d_state_t *state) { int r = state->r >> 7, g = state->g >> 7, b = state->b >> 7, a = state->a >> 7; - + tex_sample(state); - + CLAMP_RGBA(r, g, b, a); - + state->dest_rgba.r = ((state->dest_rgba.r) * r) >> 8; state->dest_rgba.g = ((state->dest_rgba.g) * g) >> 8; state->dest_rgba.b = ((state->dest_rgba.b) * b) >> 8; @@ -2947,13 +2987,13 @@ static void tri(virge_t *virge, s3d_t *s3d_tri, s3d_state_t *state, int yc, int3 uint8_t *vram = virge->svga.vram; int x_dir = s3d_tri->tlr ? 1 : -1; - + int use_z = !(s3d_tri->cmd_set & CMD_SET_ZB_MODE); int y_count = yc; - + int bpp = (s3d_tri->cmd_set >> 2) & 7; - + uint32_t dest_offset = 0, z_offset = 0; uint32_t src_col; @@ -2978,10 +3018,10 @@ static void tri(virge_t *virge, s3d_t *s3d_tri, s3d_state_t *state, int yc, int3 if (state->y > s3d_tri->clip_b) { int diff_y = state->y - s3d_tri->clip_b; - + if (diff_y > y_count) diff_y = y_count; - + state->base_u += (s3d_tri->TdUdY * diff_y); state->base_v += (s3d_tri->TdVdY * diff_y); state->base_z += (s3d_tri->TdZdY * diff_y); @@ -3004,7 +3044,7 @@ static void tri(virge_t *virge, s3d_t *s3d_tri, s3d_state_t *state, int yc, int3 dest_offset = s3d_tri->dest_base + (state->y * s3d_tri->dest_str); z_offset = s3d_tri->z_base + (state->y * s3d_tri->z_str); - + for (; y_count > 0; y_count--) { x = (state->x1 + ((1 << 20) - 1)) >> 20; @@ -3046,7 +3086,7 @@ static void tri(virge_t *virge, s3d_t *s3d_tri, s3d_state_t *state, int yc, int3 if (x < s3d_tri->clip_l) { int diff_x = s3d_tri->clip_l - x; - + z += (s3d_tri->TdZdX * diff_x); state->u += (s3d_tri->TdUdX * diff_x); state->v += (s3d_tri->TdVdX * diff_x); @@ -3056,7 +3096,7 @@ static void tri(virge_t *virge, s3d_t *s3d_tri, s3d_state_t *state, int yc, int3 state->a += (s3d_tri->TdAdX * diff_x); state->d += (s3d_tri->TdDdX * diff_x); state->w += (s3d_tri->TdWdX * diff_x); - + x = s3d_tri->clip_l; } } @@ -3071,7 +3111,7 @@ static void tri(virge_t *virge, s3d_t *s3d_tri, s3d_state_t *state, int yc, int3 if (x > s3d_tri->clip_r) { int diff_x = x - s3d_tri->clip_r; - + z += (s3d_tri->TdZdX * diff_x); state->u += (s3d_tri->TdUdX * diff_x); state->v += (s3d_tri->TdVdX * diff_x); @@ -3081,7 +3121,7 @@ static void tri(virge_t *virge, s3d_t *s3d_tri, s3d_state_t *state, int yc, int3 state->a += (s3d_tri->TdAdX * diff_x); state->d += (s3d_tri->TdDdX * diff_x); state->w += (s3d_tri->TdWdX * diff_x); - + x = s3d_tri->clip_r; } } @@ -3208,11 +3248,11 @@ static void s3_virge_triangle(virge_t *virge, s3d_t *s3d_tri) state.tbu = s3d_tri->tbu << 11; state.tbv = s3d_tri->tbv << 11; - + state.max_d = (s3d_tri->cmd_set >> 8) & 15; - + state.tex_bdr_clr = s3d_tri->tex_bdr_clr; - + state.cmd_set = s3d_tri->cmd_set; state.base_u = s3d_tri->tus; @@ -3224,7 +3264,7 @@ static void s3_virge_triangle(virge_t *virge, s3d_t *s3d_tri) state.base_a = (int32_t)s3d_tri->tas; state.base_d = s3d_tri->tds; state.base_w = s3d_tri->tws; - + tex_base = s3d_tri->tex_base; for (c = 9; c >= 0; c--) { @@ -3252,7 +3292,7 @@ static void s3_virge_triangle(virge_t *virge, s3d_t *s3d_tri) dest_pixel = dest_pixel_lit_texture_decal; break; default: - /* pclog("bad triangle type %x\n", (s3d_tri->cmd_set >> 27) & 0xf); */ + s3_virge_log("bad triangle type %x\n", (s3d_tri->cmd_set >> 27) & 0xf); return; } break; @@ -3261,10 +3301,10 @@ static void s3_virge_triangle(virge_t *virge, s3d_t *s3d_tri) dest_pixel = dest_pixel_unlit_texture_triangle; break; default: - /* pclog("bad triangle type %x\n", (s3d_tri->cmd_set >> 27) & 0xf); */ + s3_virge_log("bad triangle type %x\n", (s3d_tri->cmd_set >> 27) & 0xf); return; - } - + } + switch (((s3d_tri->cmd_set >> 12) & 7) | ((s3d_tri->cmd_set & (1 << 29)) ? 8 : 0)) { case 0: case 1: @@ -3280,31 +3320,31 @@ static void s3_virge_triangle(virge_t *virge, s3d_t *s3d_tri) tex_sample = virge->bilinear_enabled ? tex_sample_normal_filter : tex_sample_normal; break; case (0 | 8): case (1 | 8): - if (virge->is_375) + if (virge->chip == S3_VIRGEDX) tex_sample = tex_sample_persp_mipmap_375; else tex_sample = tex_sample_persp_mipmap; break; case (2 | 8): case (3 | 8): - if (virge->is_375) + if (virge->chip == S3_VIRGEDX) tex_sample = virge->bilinear_enabled ? tex_sample_persp_mipmap_filter_375 : tex_sample_persp_mipmap_375; else tex_sample = virge->bilinear_enabled ? tex_sample_persp_mipmap_filter : tex_sample_persp_mipmap; break; case (4 | 8): case (5 | 8): - if (virge->is_375) + if (virge->chip == S3_VIRGEDX) tex_sample = tex_sample_persp_normal_375; else tex_sample = tex_sample_persp_normal; break; case (6 | 8): case (7 | 8): - if (virge->is_375) + if (virge->chip == S3_VIRGEDX) tex_sample = virge->bilinear_enabled ? tex_sample_persp_normal_filter_375 : tex_sample_persp_normal_375; else tex_sample = virge->bilinear_enabled ? tex_sample_persp_normal_filter : tex_sample_persp_normal; break; } - + switch ((s3d_tri->cmd_set >> 5) & 7) { case 0: @@ -3317,7 +3357,7 @@ static void s3_virge_triangle(virge_t *virge, s3d_t *s3d_tri) tex_read = (s3d_tri->cmd_set & CMD_SET_TWE) ? tex_ARGB1555 : tex_ARGB1555_nowrap; break; default: - /* pclog("bad texture type %i\n", (s3d_tri->cmd_set >> 5) & 7); */ + s3_virge_log("bad texture type %i\n", (s3d_tri->cmd_set >> 5) & 7); tex_read = (s3d_tri->cmd_set & CMD_SET_TWE) ? tex_ARGB1555 : tex_ARGB1555_nowrap; break; } @@ -3332,14 +3372,14 @@ static void s3_virge_triangle(virge_t *virge, s3d_t *s3d_tri) virge->tri_count++; end_time = plat_timer_read(); - + virge_time += end_time - start_time; } static void render_thread(void *param) { virge_t *virge = (virge_t *)param; - + while (1) { thread_wait_event(virge->wake_render_thread, -1); @@ -3373,17 +3413,19 @@ static void queue_triangle(virge_t *virge) thread_set_event(virge->wake_render_thread); /*Wake up render thread if moving from idle*/ } -static void s3_virge_hwcursor_draw(svga_t *svga, int disp_line) +static void s3_virge_hwcursor_draw(svga_t *svga, int displine) { virge_t *virge = (virge_t *)svga->p; int x; uint16_t dat[2]; int xx; int offset = svga->hwcursor_latch.x - svga->hwcursor_latch.xoff; + int y_add, x_add; uint32_t fg, bg; - int y_add = (enable_overscan && !suppress_overscan) ? 16 : 0; - int x_add = (enable_overscan && !suppress_overscan) ? 8 : 0; + y_add = (enable_overscan && !suppress_overscan) ? (overscan_y >> 1) : 0; + x_add = (enable_overscan && !suppress_overscan) ? 8 : 0; + if (svga->interlace && svga->hwcursor_oddeven) svga->hwcursor_latch.addr += 16; @@ -3393,12 +3435,12 @@ static void s3_virge_hwcursor_draw(svga_t *svga, int disp_line) fg = video_15to32[virge->hwc_fg_col & 0xffff]; bg = video_15to32[virge->hwc_bg_col & 0xffff]; break; - + case 16: fg = video_16to32[virge->hwc_fg_col & 0xffff]; bg = video_16to32[virge->hwc_bg_col & 0xffff]; break; - + case 24: case 32: fg = virge->hwc_fg_col; bg = virge->hwc_bg_col; @@ -3422,9 +3464,9 @@ static void s3_virge_hwcursor_draw(svga_t *svga, int disp_line) if (offset >= svga->hwcursor_latch.x) { if (dat[0] & 0x8000) - ((uint32_t *)buffer32->line[disp_line + y_add])[offset + 32 + x_add] = (dat[1] & 0x8000) ? fg : bg; + ((uint32_t *)buffer32->line[displine + y_add])[offset + 32 + x_add] = (dat[1] & 0x8000) ? fg : bg; } - + offset++; dat[0] <<= 1; dat[1] <<= 1; @@ -3438,11 +3480,11 @@ static void s3_virge_hwcursor_draw(svga_t *svga, int disp_line) if (offset >= svga->hwcursor_latch.x) { if (!(dat[0] & 0x8000)) - ((uint32_t *)buffer32->line[disp_line + y_add])[offset + 32 + x_add] = (dat[1] & 0x8000) ? fg : bg; + ((uint32_t *)buffer32->line[displine + y_add])[offset + 32 + x_add] = (dat[1] & 0x8000) ? fg : bg; else if (dat[1] & 0x8000) - ((uint32_t *)buffer32->line[disp_line + y_add])[offset + 32 + x_add] ^= 0xffffff; + ((uint32_t *)buffer32->line[displine + y_add])[offset + 32 + x_add] ^= 0xffffff; } - + offset++; dat[0] <<= 1; dat[1] <<= 1; @@ -3681,7 +3723,7 @@ static void s3_virge_hwcursor_draw(svga_t *svga, int disp_line) } \ } while (0) -static void s3_virge_overlay_draw(svga_t *svga, int disp_line) +static void s3_virge_overlay_draw(svga_t *svga, int displine) { virge_t *virge = (virge_t *)svga->p; int offset = (virge->streams.sec_x - virge->streams.pri_x) + 1; @@ -3693,16 +3735,16 @@ static void s3_virge_overlay_draw(svga_t *svga, int disp_line) uint8_t *src = &svga->vram[svga->overlay_latch.addr]; int y_add = enable_overscan ? 16 : 0; int x_add = enable_overscan ? 8 : 0; - - p = &((uint32_t *)buffer32->line[disp_line + y_add])[offset + 32 + x_add]; - + + p = &((uint32_t *)buffer32->line[displine + y_add])[offset + 32 + x_add]; + if ((offset + virge->streams.sec_w) > virge->streams.pri_w) x_size = (virge->streams.pri_w - virge->streams.sec_x) + 1; else x_size = virge->streams.sec_w + 1; OVERLAY_SAMPLE(); - + for (x = 0; x < x_size; x++) { *p++ = r[x_read] | (g[x_read] << 8) | (b[x_read] << 16); @@ -3735,22 +3777,22 @@ static uint8_t s3_virge_pci_read(int func, int addr, void *p) { case 0x00: ret = 0x33; break; /*'S3'*/ case 0x01: ret = 0x53; break; - + case 0x02: ret = virge->virge_id_low; break; case 0x03: ret = virge->virge_id_high; break; case 0x04: ret = virge->pci_regs[0x04] & 0x27; break; - + case 0x07: ret = virge->pci_regs[0x07] & 0x36; break; - + case 0x08: ret = 0; break; /*Revision ID*/ case 0x09: ret = 0; break; /*Programming interface*/ - + case 0x0a: ret = 0x00; break; /*Supports VGA interface*/ case 0x0b: ret = 0x03; /*output = 3; */break; case 0x0d: ret = virge->pci_regs[0x0d] & 0xf8; break; - + case 0x10: ret = 0x00; break;/*Linear frame buffer address*/ case 0x11: ret = 0x00; break; case 0x12: ret = 0x00; break; @@ -3762,11 +3804,12 @@ static uint8_t s3_virge_pci_read(int func, int addr, void *p) case 0x33: ret = virge->pci_regs[0x33]; break; case 0x3c: ret = virge->pci_regs[0x3c]; break; - + case 0x3d: ret = 0x01; break; /*INTA*/ - + case 0x3e: ret = 0x04; break; case 0x3f: ret = 0xff; break; + } return ret; } @@ -3781,7 +3824,7 @@ static void s3_virge_pci_write(int func, int addr, uint8_t val, void *p) case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x3d: case 0x3e: case 0x3f: return; - + case PCI_REG_COMMAND: if (val & PCI_COMMAND_IO) { @@ -3791,7 +3834,7 @@ static void s3_virge_pci_write(int func, int addr, uint8_t val, void *p) else io_removehandler(0x03c0, 0x0020, s3_virge_in, NULL, NULL, s3_virge_out, NULL, NULL, virge); virge->pci_regs[PCI_REG_COMMAND] = val & 0x27; - s3_virge_updatemapping(virge); + s3_virge_updatemapping(virge); return; case 0x07: virge->pci_regs[0x07] = val & 0x3e; @@ -3799,412 +3842,220 @@ static void s3_virge_pci_write(int func, int addr, uint8_t val, void *p) case 0x0d: virge->pci_regs[0x0d] = val & 0xf8; return; - - case 0x13: - svga->crtc[0x59] = val & 0xfc; - s3_virge_updatemapping(virge); + + case 0x13: + svga->crtc[0x59] = val & 0xfc; + s3_virge_updatemapping(virge); return; case 0x30: case 0x32: case 0x33: virge->pci_regs[addr] = val; if (virge->pci_regs[0x30] & 0x01) { - uint32_t a = (virge->pci_regs[0x32] << 16) | (virge->pci_regs[0x33] << 24); - mem_mapping_set_addr(&virge->bios_rom.mapping, a, 0x8000); - mem_mapping_enable(&virge->bios_rom.mapping); + uint32_t addr = (virge->pci_regs[0x32] << 16) | (virge->pci_regs[0x33] << 24); + mem_map_set_addr(&virge->bios_rom.mapping, addr, 0x8000); + mem_map_enable(&virge->bios_rom.mapping); } else { - mem_mapping_disable(&virge->bios_rom.mapping); + mem_map_disable(&virge->bios_rom.mapping); } return; - case 0x3c: + case 0x3c: virge->pci_regs[0x3c] = val; return; } } -static void *s3_virge_init(const device_t *info) + +static void * +s3_virge_init(const device_t *info) { - virge_t *virge = malloc(sizeof(virge_t)); - memset(virge, 0, sizeof(virge_t)); + virge_t *virge; + const wchar_t *bios_fn; - virge->bilinear_enabled = device_get_config_int("bilinear"); - virge->dithering_enabled = device_get_config_int("dithering"); - virge->memory_size = device_get_config_int("memory"); + virge = (virge_t *)mem_alloc(sizeof(virge_t)); + memset(virge, 0, sizeof(virge_t)); - svga_init(&virge->svga, virge, virge->memory_size << 20, - s3_virge_recalctimings, - s3_virge_in, s3_virge_out, - s3_virge_hwcursor_draw, - s3_virge_overlay_draw); - virge->svga.vblank_start = s3_virge_vblank_start; + virge->bilinear_enabled = device_get_config_int("bilinear"); + virge->dithering_enabled = device_get_config_int("dithering"); + virge->memory_size = device_get_config_int("memory"); + + switch(info->local) { + case S3_DIAMOND_STEALTH3D_2000: + bios_fn = ROM_DIAMOND_STEALTH3D_2000; + break; - virge->pci = !!(info->flags & DEVICE_PCI); + case S3_DIAMOND_STEALTH3D_3000: + bios_fn = ROM_DIAMOND_STEALTH3D_3000; + break; - rom_init(&virge->bios_rom, L"video/s3/s3virge/s3virge.bin", 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); - if (info->flags & DEVICE_PCI) - mem_mapping_disable(&virge->bios_rom.mapping); + case S3_VIRGE_DX: + bios_fn = ROM_VIRGE_DX; + break; - mem_mapping_add(&virge->mmio_mapping, 0, 0, s3_virge_mmio_read, - s3_virge_mmio_read_w, - s3_virge_mmio_read_l, - s3_virge_mmio_write, - s3_virge_mmio_write_w, - s3_virge_mmio_write_l, - NULL, - 0, - virge); - mem_mapping_add(&virge->new_mmio_mapping, 0, 0, s3_virge_mmio_read, - s3_virge_mmio_read_w, - s3_virge_mmio_read_l, - s3_virge_mmio_write, - s3_virge_mmio_write_w, - s3_virge_mmio_write_l, - NULL, - 0, - virge); - mem_mapping_add(&virge->linear_mapping, 0, 0, svga_read_linear, - svga_readw_linear, - svga_readl_linear, - svga_write_linear, - svga_writew_linear, - svga_writel_linear, - NULL, - 0, - &virge->svga); + case S3_VIRGE_DX_VBE20: + bios_fn = ROM_VIRGE_DX_VBE20; + break; - io_sethandler(0x03c0, 0x0020, s3_virge_in, NULL, NULL, s3_virge_out, NULL, NULL, virge); + default: + free(virge); + return NULL; + } - virge->pci_regs[4] = 3; - virge->pci_regs[5] = 0; - virge->pci_regs[6] = 0; - virge->pci_regs[7] = 2; - virge->pci_regs[0x32] = 0x0c; - virge->pci_regs[0x3d] = 1; - virge->pci_regs[0x3e] = 4; - virge->pci_regs[0x3f] = 0xff; + svga_init(&virge->svga, virge, virge->memory_size << 20, + s3_virge_recalctimings, + s3_virge_in, s3_virge_out, + s3_virge_hwcursor_draw, + s3_virge_overlay_draw); + virge->svga.vblank_start = s3_virge_vblank_start; - virge->virge_id_high = 0x56; - virge->virge_id_low = 0x31; - virge->virge_rev = 0; - virge->virge_id = 0xe1; + virge->pci = !!(info->flags & DEVICE_PCI); - switch (virge->memory_size) - { - case 2: + rom_init(&virge->bios_rom, bios_fn, + 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + if (info->flags & DEVICE_PCI) + mem_map_disable(&virge->bios_rom.mapping); + + mem_map_add(&virge->mmio_mapping, 0, 0, + s3_virge_mmio_read,s3_virge_mmio_read_w,s3_virge_mmio_read_l, + s3_virge_mmio_write,s3_virge_mmio_write_w,s3_virge_mmio_write_l, + NULL, 0, virge); + mem_map_add(&virge->new_mmio_mapping, 0, 0, + s3_virge_mmio_read,s3_virge_mmio_read_w,s3_virge_mmio_read_l, + s3_virge_mmio_write,s3_virge_mmio_write_w,s3_virge_mmio_write_l, + NULL, 0, virge); + mem_map_add(&virge->linear_mapping, 0, 0, + svga_read_linear, svga_readw_linear, svga_readl_linear, + svga_write_linear, svga_writew_linear, svga_writel_linear, + NULL, 0, &virge->svga); + + io_sethandler(0x03c0, 0x0020, + s3_virge_in,NULL,NULL, s3_virge_out,NULL,NULL, virge); + + virge->pci_regs[4] = 3; + virge->pci_regs[5] = 0; + virge->pci_regs[6] = 0; + virge->pci_regs[7] = 2; + virge->pci_regs[0x32] = 0x0c; + virge->pci_regs[0x3d] = 1; + virge->pci_regs[0x3e] = 4; + virge->pci_regs[0x3f] = 0xff; + + virge->virge_rev = 0; + virge->virge_id = 0xe1; + + switch (virge->memory_size) { + case 2: virge->svga.crtc[0x36] = 2 | (0 << 2) | (1 << 4) | (4 << 5); break; - case 4: + case 4: default: virge->svga.crtc[0x36] = 2 | (0 << 2) | (1 << 4) | (0 << 5); break; - } + } - virge->svga.crtc[0x37] = 1; - virge->svga.crtc[0x53] = 1 << 3; - virge->svga.crtc[0x59] = 0x70; + virge->svga.crtc[0x37] = 1; + virge->svga.crtc[0x53] = 1 << 3; + virge->svga.crtc[0x59] = 0x70; - virge->is_375 = 0; + switch(info->local) { + case S3_DIAMOND_STEALTH3D_2000: + virge->svga.vblank_start = s3_virge_vblank_start; + virge->virge_id_high = 0x56; + virge->virge_id_low = 0x31; + virge->chip = S3_VIRGE; + video_inform(VID_TYPE_SPEC, &timing_diamond_stealth3d_2000); + break; - if (info->flags & DEVICE_PCI) - { - virge->card = pci_add_card(PCI_ADD_VIDEO, s3_virge_pci_read, s3_virge_pci_write, virge); - } + case S3_DIAMOND_STEALTH3D_3000: + virge->virge_id_high = 0x88; + virge->virge_id_low = 0x3d; + virge->chip = S3_VIRGEVX; + video_inform(VID_TYPE_SPEC, &timing_diamond_stealth3d_3000); + break; - virge->wake_render_thread = thread_create_event(); - virge->wake_main_thread = thread_create_event(); - virge->not_full_event = thread_create_event(); - virge->render_thread = thread_create(render_thread, virge); + default: + virge->svga.crtc[0x6c] = 0x01; + virge->virge_id_high = 0x8a; + virge->virge_id_low = 0x01; + virge->chip = S3_VIRGEDX; + video_inform(VID_TYPE_SPEC, &timing_virge_dx); + break; + } - virge->wake_fifo_thread = thread_create_event(); - virge->fifo_not_full_event = thread_create_event(); - virge->fifo_thread = thread_create(fifo_thread, virge); + if (info->flags & DEVICE_PCI) + virge->card = pci_add_card(PCI_ADD_VIDEO, + s3_virge_pci_read,s3_virge_pci_write, virge); - return virge; -} + virge->wake_render_thread = thread_create_event(); + virge->wake_main_thread = thread_create_event(); + virge->not_full_event = thread_create_event(); + virge->render_thread = thread_create(render_thread, virge); -static void *s3_virge_988_init(const device_t *info) -{ - virge_t *virge = malloc(sizeof(virge_t)); - memset(virge, 0, sizeof(virge_t)); - - virge->bilinear_enabled = device_get_config_int("bilinear"); - virge->dithering_enabled = device_get_config_int("dithering"); - virge->memory_size = device_get_config_int("memory"); - - svga_init(&virge->svga, virge, virge->memory_size << 20, - s3_virge_recalctimings, - s3_virge_in, s3_virge_out, - s3_virge_hwcursor_draw, - s3_virge_overlay_draw); - - virge->pci = !!(info->flags & DEVICE_PCI); - - rom_init(&virge->bios_rom, L"video/s3/s3virge/diamondstealth3000.vbi", 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); - if (info->flags & DEVICE_PCI) - mem_mapping_disable(&virge->bios_rom.mapping); - - mem_mapping_add(&virge->mmio_mapping, 0, 0, s3_virge_mmio_read, - s3_virge_mmio_read_w, - s3_virge_mmio_read_l, - s3_virge_mmio_write, - s3_virge_mmio_write_w, - s3_virge_mmio_write_l, - NULL, - 0, - virge); - mem_mapping_add(&virge->new_mmio_mapping, 0, 0, s3_virge_mmio_read, - s3_virge_mmio_read_w, - s3_virge_mmio_read_l, - s3_virge_mmio_write, - s3_virge_mmio_write_w, - s3_virge_mmio_write_l, - NULL, - 0, - virge); - mem_mapping_add(&virge->linear_mapping, 0, 0, svga_read_linear, - svga_readw_linear, - svga_readl_linear, - svga_write_linear, - svga_writew_linear, - svga_writel_linear, - NULL, - 0, - &virge->svga); - - io_sethandler(0x03c0, 0x0020, s3_virge_in, NULL, NULL, s3_virge_out, NULL, NULL, virge); - - virge->pci_regs[4] = 3; - virge->pci_regs[5] = 0; - virge->pci_regs[6] = 0; - virge->pci_regs[7] = 2; - virge->pci_regs[0x32] = 0x0c; - virge->pci_regs[0x3d] = 1; - virge->pci_regs[0x3e] = 4; - virge->pci_regs[0x3f] = 0xff; - - virge->virge_id_high = 0x88; - virge->virge_id_low = 0x3d; - virge->virge_rev = 0; - virge->virge_id = 0xe1; - - switch (virge->memory_size) - { - case 2: - virge->svga.crtc[0x36] = 2 | (0 << 2) | (1 << 4) | (4 << 5); - break; - case 4: - default: - virge->svga.crtc[0x36] = 2 | (0 << 2) | (1 << 4) | (0 << 5); - break; - } - - virge->svga.crtc[0x37] = 1; - virge->svga.crtc[0x53] = 1 << 3; - virge->svga.crtc[0x59] = 0x70; - - virge->is_375 = 0; - - if (info->flags & DEVICE_PCI) - { - virge->card = pci_add_card(PCI_ADD_VIDEO, s3_virge_pci_read, s3_virge_pci_write, virge); - } - - virge->wake_render_thread = thread_create_event(); - virge->wake_main_thread = thread_create_event(); - virge->not_full_event = thread_create_event(); - virge->render_thread = thread_create(render_thread, virge); - - virge->wake_fifo_thread = thread_create_event(); - virge->fifo_not_full_event = thread_create_event(); - virge->fifo_thread = thread_create(fifo_thread, virge); - - return virge; -} - -static void *s3_virge_375_init(const device_t *info, wchar_t *romfn) -{ - virge_t *virge = malloc(sizeof(virge_t)); - memset(virge, 0, sizeof(virge_t)); - - virge->bilinear_enabled = device_get_config_int("bilinear"); - virge->dithering_enabled = device_get_config_int("dithering"); - virge->memory_size = device_get_config_int("memory"); - - svga_init(&virge->svga, virge, virge->memory_size << 20, - s3_virge_recalctimings, - s3_virge_in, s3_virge_out, - s3_virge_hwcursor_draw, - s3_virge_overlay_draw); - - virge->pci = !!(info->flags & DEVICE_PCI); - - rom_init(&virge->bios_rom, romfn, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); - if (info->flags & DEVICE_PCI) - mem_mapping_disable(&virge->bios_rom.mapping); - - mem_mapping_add(&virge->mmio_mapping, 0, 0, s3_virge_mmio_read, - s3_virge_mmio_read_w, - s3_virge_mmio_read_l, - s3_virge_mmio_write, - s3_virge_mmio_write_w, - s3_virge_mmio_write_l, - NULL, - 0, - virge); - mem_mapping_add(&virge->new_mmio_mapping, 0, 0, s3_virge_mmio_read, - s3_virge_mmio_read_w, - s3_virge_mmio_read_l, - s3_virge_mmio_write, - s3_virge_mmio_write_w, - s3_virge_mmio_write_l, - NULL, - 0, - virge); - mem_mapping_add(&virge->linear_mapping, 0, 0, svga_read_linear, - svga_readw_linear, - svga_readl_linear, - svga_write_linear, - svga_writew_linear, - svga_writel_linear, - NULL, - 0, - &virge->svga); - - io_sethandler(0x03c0, 0x0020, s3_virge_in, NULL, NULL, s3_virge_out, NULL, NULL, virge); - - virge->pci_regs[4] = 3; - virge->pci_regs[5] = 0; - virge->pci_regs[6] = 0; - virge->pci_regs[7] = 2; - virge->pci_regs[0x32] = 0x0c; - virge->pci_regs[0x3d] = 1; - virge->pci_regs[0x3e] = 4; - virge->pci_regs[0x3f] = 0xff; - - virge->virge_id_high = 0x8a; - virge->virge_id_low = 0x01; - virge->virge_rev = 0; - virge->virge_id = 0xe1; - - switch (virge->memory_size) - { - case 2: - virge->svga.crtc[0x36] = 2 | (0 << 2) | (1 << 4) | (4 << 5); - break; - case 4: - default: - virge->svga.crtc[0x36] = 2 | (0 << 2) | (1 << 4) | (0 << 5); - break; - } - virge->svga.crtc[0x37] = 1; - virge->svga.crtc[0x53] = 1 << 3; - virge->svga.crtc[0x59] = 0x70; - - virge->svga.crtc[0x6c] = 0x01; - - virge->is_375 = 1; - - if (info->flags & DEVICE_PCI) - { - virge->card = pci_add_card(PCI_ADD_VIDEO, s3_virge_pci_read, s3_virge_pci_write, virge); - } + virge->wake_fifo_thread = thread_create_event(); + virge->fifo_not_full_event = thread_create_event(); + virge->fifo_thread = thread_create(fifo_thread, virge); - virge->wake_render_thread = thread_create_event(); - virge->wake_main_thread = thread_create_event(); - virge->not_full_event = thread_create_event(); - virge->render_thread = thread_create(render_thread, virge); - - virge->wake_fifo_thread = thread_create_event(); - virge->fifo_not_full_event = thread_create_event(); - virge->fifo_thread = thread_create(fifo_thread, virge); - - return virge; + return virge; } -static void *s3_virge_375_1_init(const device_t *info) + +static void +s3_virge_close(void *p) { - return s3_virge_375_init(info, L"video/s3/s3virge/86c375_1.bin"); + virge_t *virge = (virge_t *)p; + + thread_kill(virge->render_thread); + thread_destroy_event(virge->not_full_event); + thread_destroy_event(virge->wake_main_thread); + thread_destroy_event(virge->wake_render_thread); + + thread_kill(virge->fifo_thread); + thread_destroy_event(virge->wake_fifo_thread); + thread_destroy_event(virge->fifo_not_full_event); + + svga_close(&virge->svga); + + free(virge); } -static void *s3_virge_375_4_init(const device_t *info) -{ - return s3_virge_375_init(info, L"video/s3/s3virge/86c375_4.bin"); -} - -static void s3_virge_close(void *p) -{ - virge_t *virge = (virge_t *)p; - - thread_kill(virge->render_thread); - thread_destroy_event(virge->not_full_event); - thread_destroy_event(virge->wake_main_thread); - thread_destroy_event(virge->wake_render_thread); - - thread_kill(virge->fifo_thread); - thread_destroy_event(virge->wake_fifo_thread); - thread_destroy_event(virge->fifo_not_full_event); - - svga_close(&virge->svga); - - free(virge); -} static int s3_virge_available(void) { - return rom_present(L"video/s3/s3virge/s3virge.bin"); + return rom_present(ROM_DIAMOND_STEALTH3D_2000); } static int s3_virge_988_available(void) { - return rom_present(L"video/s3/s3virge/diamondstealth3000.vbi"); + return rom_present(ROM_DIAMOND_STEALTH3D_3000); } static int s3_virge_375_1_available(void) { - return rom_present(L"video/s3/s3virge/86c375_1.bin"); + return rom_present(ROM_VIRGE_DX); } static int s3_virge_375_4_available(void) { - return rom_present(L"video/s3/s3virge/86c375_4.bin"); + return rom_present(ROM_VIRGE_DX_VBE20); } + static void s3_virge_speed_changed(void *p) { - virge_t *virge = (virge_t *)p; - - svga_recalctimings(&virge->svga); + virge_t *virge = (virge_t *)p; + + svga_recalctimings(&virge->svga); } static void s3_virge_force_redraw(void *p) { - virge_t *virge = (virge_t *)p; + virge_t *virge = (virge_t *)p; - virge->svga.fullchange = changeframecount; + virge->svga.fullchange = changeframecount; } -static void s3_virge_add_status_info(char *s, int max_len, void *p) -{ - virge_t *virge = (virge_t *)p; - char temps[256]; - uint64_t new_time = plat_timer_read(); - uint64_t status_diff = new_time - status_time; - status_time = new_time; - - if (!status_diff) - status_diff = 1; - - svga_add_status_info(s, max_len, &virge->svga); - sprintf(temps, "%f Mpixels/sec\n%f ktris/sec\n%f%% CPU\n%f%% CPU (real)\n%d writes %i reads\n\n", (double)virge->pixel_count/1000000.0, (double)virge->tri_count/1000.0, ((double)virge_time * 100.0) / timer_freq, ((double)virge_time * 100.0) / status_diff, reg_writes, reg_reads); - strncat(s, temps, max_len); - - virge->pixel_count = virge->tri_count = 0; - virge_time = 0; - reg_reads = 0; - reg_writes = 0; -} static const device_config_t s3_virge_config[] = { @@ -4233,122 +4084,99 @@ static const device_config_t s3_virge_config[] = } }; -const device_t s3_virge_vlb_device = -{ - "Diamond Stealth 3D 2000 (S3 ViRGE) VLB", - DEVICE_VLB, - 0, - s3_virge_init, - s3_virge_close, - NULL, - s3_virge_available, - s3_virge_speed_changed, - s3_virge_force_redraw, - s3_virge_add_status_info, - s3_virge_config + +const device_t s3_virge_vlb_device = { + "Diamond Stealth 3D 2000 (S3 ViRGE)", + DEVICE_VLB, + S3_DIAMOND_STEALTH3D_2000, + s3_virge_init, s3_virge_close, NULL, + s3_virge_available, + s3_virge_speed_changed, + s3_virge_force_redraw, + NULL, + s3_virge_config }; -const device_t s3_virge_pci_device = -{ - "Diamond Stealth 3D 2000 (S3 ViRGE) PCI", - DEVICE_PCI, - 0, - s3_virge_init, - s3_virge_close, - NULL, - s3_virge_available, - s3_virge_speed_changed, - s3_virge_force_redraw, - s3_virge_add_status_info, - s3_virge_config +const device_t s3_virge_pci_device = { + "Diamond Stealth 3D 2000 (S3 ViRGE)", + DEVICE_PCI, + S3_DIAMOND_STEALTH3D_2000, + s3_virge_init, s3_virge_close, NULL, + s3_virge_available, + s3_virge_speed_changed, + s3_virge_force_redraw, + NULL, + s3_virge_config }; -const device_t s3_virge_988_vlb_device = -{ - "Diamond Stealth 3D 3000 (S3 ViRGE/VX) VLB", - DEVICE_VLB, - 0, - s3_virge_988_init, - s3_virge_close, - NULL, - s3_virge_988_available, - s3_virge_speed_changed, - s3_virge_force_redraw, - s3_virge_add_status_info, - s3_virge_config +const device_t s3_virge_988_vlb_device = { + "Diamond Stealth 3D 3000 (S3 ViRGE/VX)", + DEVICE_VLB, + S3_DIAMOND_STEALTH3D_3000, + s3_virge_init, s3_virge_close, NULL, + s3_virge_988_available, + s3_virge_speed_changed, + s3_virge_force_redraw, + NULL, + s3_virge_config }; -const device_t s3_virge_988_pci_device = -{ - "Diamond Stealth 3D 3000 (S3 ViRGE/VX) PCI", - DEVICE_PCI, - 0, - s3_virge_988_init, - s3_virge_close, - NULL, - s3_virge_988_available, - s3_virge_speed_changed, - s3_virge_force_redraw, - s3_virge_add_status_info, - s3_virge_config +const device_t s3_virge_988_pci_device = { + "Diamond Stealth 3D 3000 (S3 ViRGE/VX)", + DEVICE_PCI, + S3_DIAMOND_STEALTH3D_3000, + s3_virge_init, s3_virge_close, NULL, + s3_virge_988_available, + s3_virge_speed_changed, + s3_virge_force_redraw, + NULL, + s3_virge_config }; -const device_t s3_virge_375_vlb_device = -{ - "S3 ViRGE/DX VLB", - DEVICE_VLB, - 0, - s3_virge_375_1_init, - s3_virge_close, - NULL, - s3_virge_375_1_available, - s3_virge_speed_changed, - s3_virge_force_redraw, - s3_virge_add_status_info, - s3_virge_config +const device_t s3_virge_375_vlb_device = { + "S3 ViRGE/DX", + DEVICE_VLB, + S3_VIRGE_DX, + s3_virge_init, s3_virge_close, NULL, + s3_virge_375_1_available, + s3_virge_speed_changed, + s3_virge_force_redraw, + NULL, + s3_virge_config }; -const device_t s3_virge_375_pci_device = -{ - "S3 ViRGE/DX PCI", - DEVICE_PCI, - 0, - s3_virge_375_1_init, - s3_virge_close, - NULL, - s3_virge_375_1_available, - s3_virge_speed_changed, - s3_virge_force_redraw, - s3_virge_add_status_info, - s3_virge_config +const device_t s3_virge_375_pci_device = { + "S3 ViRGE/DX", + DEVICE_PCI, + S3_VIRGE_DX, + s3_virge_init, s3_virge_close, NULL, + s3_virge_375_1_available, + s3_virge_speed_changed, + s3_virge_force_redraw, + NULL, + s3_virge_config }; -const device_t s3_virge_375_4_vlb_device = -{ - "S3 ViRGE/DX (VBE 2.0) VLB", - DEVICE_VLB, - 0, - s3_virge_375_4_init, - s3_virge_close, - NULL, - s3_virge_375_4_available, - s3_virge_speed_changed, - s3_virge_force_redraw, - s3_virge_add_status_info, - s3_virge_config +const device_t s3_virge_375_4_vlb_device = { + "S3 ViRGE/DX (VBE 2.0)", + DEVICE_VLB, + S3_VIRGE_DX_VBE20, + s3_virge_init, s3_virge_close, NULL, + s3_virge_375_4_available, + s3_virge_speed_changed, + s3_virge_force_redraw, + NULL, + s3_virge_config }; -const device_t s3_virge_375_4_pci_device = -{ - "S3 ViRGE/DX (VBE 2.0) PCI", - DEVICE_PCI, - 0, - s3_virge_375_4_init, - s3_virge_close, - NULL, - s3_virge_375_4_available, - s3_virge_speed_changed, - s3_virge_force_redraw, - s3_virge_add_status_info, - s3_virge_config +const device_t s3_virge_375_4_pci_device = { + "S3 ViRGE/DX (VBE 2.0)", + DEVICE_PCI, + S3_VIRGE_DX_VBE20, + s3_virge_init, s3_virge_close, NULL, + s3_virge_375_4_available, + s3_virge_speed_changed, + s3_virge_force_redraw, + NULL, + s3_virge_config }; diff --git a/src/devices/video/vid_sc1502x_ramdac.c b/src/devices/video/vid_sc1502x_ramdac.c index 6ba94ec..5ce55f5 100644 --- a/src/devices/video/vid_sc1502x_ramdac.c +++ b/src/devices/video/vid_sc1502x_ramdac.c @@ -8,9 +8,7 @@ * * Emulation of a Sierra SC1502X RAMDAC. * - * Used by the TLIVESA1 driver for ET4000. - * - * Version: @(#)vid_sc1502x_ramdac.c 1.0.2 2018/05/06 + * Version: @(#)vid_sc1502x_ramdac.c 1.0.3 2018/10/05 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -41,91 +39,137 @@ #include #include #include +#include #include #include "../../emu.h" #include "../../mem.h" +#include "../../device.h" #include "video.h" #include "vid_svga.h" #include "vid_sc1502x_ramdac.h" -void sc1502x_ramdac_out(uint16_t addr, uint8_t val, sc1502x_ramdac_t *ramdac, svga_t *svga) +void +sc1502x_ramdac_out(uint16_t addr, uint8_t val, sc1502x_ramdac_t *dev, svga_t *svga) { - int oldbpp = 0; - switch (addr) - { - case 0x3C6: - if (ramdac->state == 4) - { - ramdac->state = 0; - if (val == 0xFF) break; - ramdac->ctrl = val; - oldbpp = svga->bpp; - switch ((val&1)|((val&0xC0)>>5)) - { - case 0: - svga->bpp = 8; - break; - case 2: case 3: - switch (val & 0x20) - { - case 0x00: svga->bpp = 32; break; - case 0x20: svga->bpp = 24; break; - } - break; - case 4: case 5: - svga->bpp = 15; - break; - case 6: - svga->bpp = 16; - break; - case 7: - switch (val & 4) - { - case 4: - switch (val & 0x20) - { - case 0x00: svga->bpp = 32; break; - case 0x20: svga->bpp = 24; break; - } - break; - case 0: default: - svga->bpp = 16; - break; - } - case 1: default: + int oldbpp = 0; + + switch (addr) { + case 0x3C6: + if (dev->state == 4) { + dev->state = 0; + if (val == 0xFF) break; - } - if (oldbpp != svga->bpp) - { - svga_recalctimings(svga); + dev->ctrl = val; + oldbpp = svga->bpp; + switch ((val & 1) | ((val & 0xc0) >> 5)) { + case 0: + svga->bpp = 8; + break; + case 2: + case 3: + switch (val & 0x20) { + case 0x00: + svga->bpp = 32; + break; + case 0x20: + svga->bpp = 24; + break; + } + break; + case 4: + case 5: + svga->bpp = 15; + break; + case 6: + svga->bpp = 16; + break; + case 7: + if (val & 4) { + switch (val & 0x20) { + case 0x00: + svga->bpp = 32; + break; + case 0x20: + svga->bpp = 24; + break; + } + break; + } else { + svga->bpp = 16; + break; + } + break; } - return; - } - ramdac->state = 0; - break; - case 0x3C7: case 0x3C8: case 0x3C9: - ramdac->state = 0; - break; - } - svga_out(addr, val, svga); + if (oldbpp != svga->bpp) + svga_recalctimings(svga); + return; + } + dev->state = 0; + break; + case 0x3C7: + case 0x3C8: + case 0x3C9: + dev->state = 0; + break; + } + + svga_out(addr, val, svga); } -uint8_t sc1502x_ramdac_in(uint16_t addr, sc1502x_ramdac_t *ramdac, svga_t *svga) + +uint8_t +sc1502x_ramdac_in(uint16_t addr, sc1502x_ramdac_t *dev, svga_t *svga) { - switch (addr) - { - case 0x3C6: - if (ramdac->state == 4) - { - ramdac->state = 0; - return ramdac->ctrl; - } - ramdac->state++; - break; - case 0x3C7: case 0x3C8: case 0x3C9: - ramdac->state = 0; - break; - } - return svga_in(addr, svga); + uint8_t temp; + + temp = svga_in(addr, svga); + + switch (addr) { + case 0x3C6: + if (dev->state == 4) { + dev->state = 0; + temp = dev->ctrl; + break; + } + dev->state++; + break; + case 0x3C7: + case 0x3C8: + case 0x3C9: + dev->state = 0; + break; + } + + return temp; } + + +static void * +sc1502x_init(const device_t *info) +{ + sc1502x_ramdac_t *dev = (sc1502x_ramdac_t *)mem_alloc(sizeof(sc1502x_ramdac_t)); + memset(dev, 0x00, sizeof(sc1502x_ramdac_t)); + + return dev; +} + + +static void +sc1502x_close(void *priv) +{ + sc1502x_ramdac_t *dev = (sc1502x_ramdac_t *)priv; + + if (dev != NULL) + free(dev); +} + + +const device_t sc1502x_ramdac_device = { + "Sierra SC1502x RAMDAC", + 0, + 0, + sc1502x_init, sc1502x_close, NULL, + NULL, NULL, NULL, NULL, + NULL +}; diff --git a/src/devices/video/vid_sc1502x_ramdac.h b/src/devices/video/vid_sc1502x_ramdac.h index b59dd14..6a38afa 100644 --- a/src/devices/video/vid_sc1502x_ramdac.h +++ b/src/devices/video/vid_sc1502x_ramdac.h @@ -8,7 +8,7 @@ * * Definitions for the SC1502X driver. * - * Version: @(#)vid_sc1502x_ramdac_h 1.0.1 2018/02/14 + * Version: @(#)vid_sc1502x_ramdac_h 1.0.2 2018/10/05 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -40,14 +40,17 @@ # define VIDEO_SC1502X_RAMDAC_H -typedef struct unk_ramdac_t -{ - int state; - uint8_t ctrl; +typedef struct { + int state; + uint8_t ctrl; } sc1502x_ramdac_t; -void sc1502x_ramdac_out(uint16_t addr, uint8_t val, sc1502x_ramdac_t *ramdac, svga_t *svga); -uint8_t sc1502x_ramdac_in(uint16_t addr, sc1502x_ramdac_t *ramdac, svga_t *svga); + +extern const device_t sc1502x_ramdac_device; + + +extern void sc1502x_ramdac_out(uint16_t addr, uint8_t val, sc1502x_ramdac_t *dev, svga_t *svga); +extern uint8_t sc1502x_ramdac_in(uint16_t addr, sc1502x_ramdac_t *dev, svga_t *svga); #endif /*VIDEO_SC1502X_RAMDAC_H*/ diff --git a/src/devices/video/vid_sdac_ramdac.c b/src/devices/video/vid_sdac_ramdac.c index f9d112b..5e79f95 100644 --- a/src/devices/video/vid_sdac_ramdac.c +++ b/src/devices/video/vid_sdac_ramdac.c @@ -8,9 +8,7 @@ * * 87C716 'SDAC' true colour RAMDAC emulation. * - * Misidentifies as AT&T 21C504. - * - * Version: @(#)vid_sdac_ramdac.c 1.0.5 2018/09/21 + * Version: @(#)vid_sdac_ramdac.c 1.0.6 2018/10/05 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -41,165 +39,210 @@ #include #include #include +#include #include #include "../../emu.h" #include "../../mem.h" +#include "../../device.h" #include "video.h" #include "vid_svga.h" #include "vid_sdac_ramdac.h" -static void sdac_control_write(sdac_ramdac_t *ramdac, svga_t *svga, uint8_t val) +static void +sdac_control_write(sdac_ramdac_t *dev, svga_t *svga, uint8_t val) { - ramdac->command = val; - switch (val >> 4) - { - case 0x2: case 0x3: case 0xa: svga->bpp = 15; break; - case 0x4: case 0xe: svga->bpp = 24; break; - case 0x5: case 0x6: case 0xc: svga->bpp = 16; break; - case 0x7: svga->bpp = 32; break; + dev->command = val; - case 0: case 1: default: svga->bpp = 8; break; - } + switch (val >> 4) { + case 0x2: + case 0x3: + case 0xa: + svga->bpp = 15; + break; + case 0x4: + case 0xe: + svga->bpp = 24; + break; + case 0x5: + case 0x6: + case 0xc: + svga->bpp = 16; + break; + case 0x7: + svga->bpp = 32; + break; + case 0x0: + case 0x1: + default: + svga->bpp = 8; + break; + } } -static void sdac_reg_write(sdac_ramdac_t *ramdac, int reg, uint8_t val) + +static void +sdac_reg_write(sdac_ramdac_t *dev, int reg, uint8_t val) { - if ((reg >= 2 && reg <= 7) || (reg == 0xa) || (reg == 0xe)) - { - if (!ramdac->reg_ff) - ramdac->regs[reg] = (ramdac->regs[reg] & 0xff00) | val; - else - ramdac->regs[reg] = (ramdac->regs[reg] & 0x00ff) | (val << 8); - } - ramdac->reg_ff = !ramdac->reg_ff; - if (!ramdac->reg_ff) - ramdac->windex++; + if ((reg >= 2 && reg <= 7) || (reg == 0xa) || (reg == 0xe)) { + if (!dev->reg_ff) + dev->regs[reg] = (dev->regs[reg] & 0xff00) | val; + else + dev->regs[reg] = (dev->regs[reg] & 0x00ff) | (val << 8); + } + dev->reg_ff = !dev->reg_ff; + if (!dev->reg_ff) + dev->windex++; } -static uint8_t sdac_reg_read(sdac_ramdac_t *ramdac, int reg) -{ - uint8_t temp; - - if (!ramdac->reg_ff) - temp = ramdac->regs[reg] & 0xff; - else - temp = ramdac->regs[reg] >> 8; - ramdac->reg_ff = !ramdac->reg_ff; - if (!ramdac->reg_ff) - ramdac->rindex++; - return temp; +static uint8_t +sdac_reg_read(sdac_ramdac_t *dev, int reg) +{ + uint8_t temp; + + if (!dev->reg_ff) + temp = dev->regs[reg] & 0xff; + else + temp = dev->regs[reg] >> 8; + dev->reg_ff = !dev->reg_ff; + if (!dev->reg_ff) + dev->rindex++; + + return temp; } -void sdac_ramdac_out(uint16_t addr, uint8_t val, sdac_ramdac_t *ramdac, svga_t *svga) -{ - switch (addr) - { - case 2: - if (ramdac->magic_count == 4) - sdac_control_write(ramdac, svga, val); - ramdac->magic_count = 0; - break; - - case 3: - ramdac->magic_count = 0; - break; - case 0: - ramdac->magic_count = 0; - break; - case 1: - ramdac->magic_count = 0; - break; - case 4: - ramdac->windex = val; - ramdac->reg_ff = 0; - break; - case 5: - sdac_reg_write(ramdac, ramdac->windex & 0xff, val); - break; - case 6: - sdac_control_write(ramdac, svga, val); - break; - case 7: - ramdac->rindex = val; - ramdac->reg_ff = 0; - break; - } - if (!(addr & 4)) - { - if (addr < 2) - svga_out(addr + 0x3c8, val, svga); - else - svga_out(addr + 0x3c4, val, svga); - } +void +sdac_ramdac_out(uint16_t addr, int rs2, uint8_t val, sdac_ramdac_t *dev, svga_t *svga) +{ + uint8_t rs = (addr & 0x03); + rs |= (!!rs2 << 8); + + switch (rs) { + case 0x02: + if (dev->magic_count == 4) + sdac_control_write(dev, svga, val); + /*FALLTHROUGH*/ + case 0x00: + case 0x01: + case 0x03: + dev->magic_count = 0; + break; + case 0x04: + dev->windex = val; + dev->reg_ff = 0; + break; + case 0x05: + sdac_reg_write(dev, dev->windex & 0xff, val); + break; + case 0x06: + sdac_control_write(dev, svga, val); + break; + case 0x07: + dev->rindex = val; + dev->reg_ff = 0; + break; + } + + svga_out(addr, val, svga); } -uint8_t sdac_ramdac_in(uint16_t addr, sdac_ramdac_t *ramdac, svga_t *svga) + +uint8_t +sdac_ramdac_in(uint16_t addr, int rs2, sdac_ramdac_t *dev, svga_t *svga) { - uint8_t temp = 0xff; - switch (addr) - { - case 2: - if (ramdac->magic_count < 5) - ramdac->magic_count++; - if (ramdac->magic_count == 4) - { - temp = 0x70; /*SDAC ID*/ - ramdac->rs2 = 1; - } - if (ramdac->magic_count == 5) - { - temp = ramdac->command; - ramdac->magic_count = 0; - } - return temp; - case 3: - ramdac->magic_count=0; - break; - case 0: - ramdac->magic_count=0; - break; - case 1: - ramdac->magic_count=0; - break; - case 4: - return ramdac->windex; - case 5: - return sdac_reg_read(ramdac, ramdac->rindex & 0xff); - case 6: - return ramdac->command; - case 7: - return ramdac->rindex; - } - if (!(addr & 4)) - { - if (addr < 2) - return svga_in(addr + 0x3c8, svga); - else - return svga_in(addr + 0x3c4, svga); - } - return 0xff; + uint8_t temp = 0xff; + uint8_t rs = (addr & 0x03); + rs |= (!!rs2 << 8); + + switch (rs) { + case 0x02: + if (dev->magic_count < 5) + dev->magic_count++; + if (dev->magic_count == 4) + temp = 0x70; /*SDAC ID*/ + else if (dev->magic_count == 5) { + temp = dev->command; + dev->magic_count = 0; + } else + temp = svga_in(addr, svga); + break; + case 0x00: + case 0x01: + case 0x03: + dev->magic_count=0; + temp = svga_in(addr, svga); + break; + case 0x04: + temp = dev->windex; + break; + case 0x05: + temp = sdac_reg_read(dev, dev->rindex & 0xff); + break; + case 0x06: + temp = dev->command; + break; + case 0x07: + temp = dev->rindex; + break; + } + + return temp; } -float sdac_getclock(int clock, void *p) + +float +sdac_getclock(int clock, void *priv) { - sdac_ramdac_t *ramdac = (sdac_ramdac_t *)p; - float t; - int m, n1, n2; - if (clock == 0) return 25175000.0; - if (clock == 1) return 28322000.0; - clock ^= 1; /*Clocks 2 and 3 seem to be reversed*/ - m = (ramdac->regs[clock] & 0x7f) + 2; - n1 = ((ramdac->regs[clock] >> 8) & 0x1f) + 2; - n2 = ((ramdac->regs[clock] >> 13) & 0x07); - t = (14318184.0f * (float)m / (float)n1) / (float)(1 << n2); - return t; + sdac_ramdac_t *dev = (sdac_ramdac_t *)priv; + float t; + int m, n1, n2; + + if (clock == 0) + return 25175000.0; + if (clock == 1) + return 28322000.0; + + clock ^= 1; /*Clocks 2 and 3 seem to be reversed*/ + m = (dev->regs[clock] & 0x7f) + 2; + n1 = ((dev->regs[clock] >> 8) & 0x1f) + 2; + n2 = ((dev->regs[clock] >> 13) & 0x07); + n2 = (1 << n2); + t = (14318184.0f * (float)m) / (float)(n1 * n2); + + return t; } -void sdac_init(sdac_ramdac_t *ramdac) + +static void * +sdac_init(const device_t *info) { - ramdac->regs[0] = 0x6128; - ramdac->regs[1] = 0x623d; + sdac_ramdac_t *dev = (sdac_ramdac_t *)mem_alloc(sizeof(sdac_ramdac_t)); + memset(dev, 0x00, sizeof(sdac_ramdac_t)); + + dev->regs[0] = 0x6128; + dev->regs[1] = 0x623d; + + return dev; } + + +static void +sdac_close(void *priv) +{ + sdac_ramdac_t *dev = (sdac_ramdac_t *)priv; + + if (dev != NULL) + free(dev); +} + + +const device_t sdac_ramdac_device = { + "S3 SDAC 86c716 RAMDAC", + 0, + 0, + sdac_init, sdac_close, NULL, + NULL, NULL, NULL, NULL, + NULL +}; diff --git a/src/devices/video/vid_sdac_ramdac.h b/src/devices/video/vid_sdac_ramdac.h index d91cc5a..2d15a9a 100644 --- a/src/devices/video/vid_sdac_ramdac.h +++ b/src/devices/video/vid_sdac_ramdac.h @@ -8,7 +8,7 @@ * * Definitions for the SDAC driver. * - * Version: @(#)vid_sdac_ramdac.h 1.0.2 2018/03/21 + * Version: @(#)vid_sdac_ramdac.h 1.0.3 2018/10/05 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -40,22 +40,24 @@ # define VIDEO_SDAC_RAMDAC_H -typedef struct sdac_ramdac_t -{ - int magic_count; - uint8_t command; - int windex, rindex; - uint16_t regs[256]; - int reg_ff; - int rs2; +typedef struct { + uint16_t regs[256]; + int magic_count, + windex, rindex, + reg_ff, rs2; + uint8_t command; } sdac_ramdac_t; -void sdac_ramdac_out(uint16_t addr, uint8_t val, sdac_ramdac_t *ramdac, svga_t *svga); -uint8_t sdac_ramdac_in(uint16_t addr, sdac_ramdac_t *ramdac, svga_t *svga); -float sdac_getclock(int clock, void *p); +extern const device_t sdac_ramdac_device; -void sdac_init(sdac_ramdac_t *ramdac); + +extern void sdac_ramdac_out(uint16_t addr, int rs2, uint8_t val, + sdac_ramdac_t *dev, svga_t *svga); +extern uint8_t sdac_ramdac_in(uint16_t addr, int rs2, + sdac_ramdac_t *dev, svga_t *svga); + +extern float sdac_getclock(int clock, void *p); #endif /*VIDEO_SDAC_RAMDAC_H*/ diff --git a/src/devices/video/vid_stg_ramdac.c b/src/devices/video/vid_stg_ramdac.c index 6190d1e..37df3c0 100644 --- a/src/devices/video/vid_stg_ramdac.c +++ b/src/devices/video/vid_stg_ramdac.c @@ -8,7 +8,7 @@ * * STG1702 true color RAMDAC emulation. * - * Version: @(#)vid_stg_ramdac.c 1.0.3 2018/05/06 + * Version: @(#)vid_stg_ramdac.c 1.0.4 2018/10/05 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -39,163 +39,229 @@ #include #include #include +#include #include #include "../../emu.h" #include "../../mem.h" +#include "../../device.h" #include "video.h" #include "vid_svga.h" #include "vid_stg_ramdac.h" + static int stg_state_read[2][8] = {{1,2,3,4,0,0,0,0}, {1,2,3,4,5,6,7,7}}; static int stg_state_write[8] = {0,0,0,0,0,6,7,7}; -void stg_ramdac_set_bpp(svga_t *svga, stg_ramdac_t *ramdac) +static void +set_bpp(svga_t *svga, stg_ramdac_t *dev) { - if (ramdac->command & 0x8) - { - switch (ramdac->regs[3]) - { - case 0: case 5: case 7: svga->bpp = 8; break; - case 1: case 2: case 8: svga->bpp = 15; break; - case 3: case 6: svga->bpp = 16; break; - case 4: case 9: svga->bpp = 24; break; - default: svga->bpp = 8; break; - } + if (dev->command & 0x8) { + switch (dev->regs[3]) { + case 0: + case 5: + case 7: + default: + svga->bpp = 8; + break; + case 1: + case 2: + case 8: + svga->bpp = 15; + break; + case 3: + case 6: + svga->bpp = 16; + break; + case 4: + case 9: + svga->bpp = 24; + break; } - else - { - switch (ramdac->command >> 5) - { - case 0: svga->bpp = 8; break; - case 5: svga->bpp = 15; break; - case 6: svga->bpp = 16; break; - case 7: svga->bpp = 24; break; - default: svga->bpp = 8; break; - } + } else { + switch (dev->command >> 5) { + case 0: + default: + svga->bpp = 8; + break; + case 5: + svga->bpp = 15; + break; + case 6: + svga->bpp = 16; + break; + case 7: + svga->bpp = 24; + break; } - svga_recalctimings(svga); + } + + svga_recalctimings(svga); } -void stg_ramdac_out(uint16_t addr, uint8_t val, stg_ramdac_t *ramdac, svga_t *svga) + +void +stg_ramdac_out(uint16_t addr, uint8_t val, stg_ramdac_t *dev, svga_t *svga) { - int didwrite, old; - switch (addr) - { - case 0x3c6: - switch (ramdac->magic_count) - { + int didwrite, old; + + switch (addr) { + case 0x3c6: + switch (dev->magic_count) { /* 0 = PEL mask register */ - case 0: case 1: case 2: case 3: - break; - case 4: /* REG06 */ - old = ramdac->command; - ramdac->command = val; - if ((old ^ val) & 8) - { - stg_ramdac_set_bpp(svga, ramdac); - } - else - { - if ((old ^ val) & 0xE0) - { - stg_ramdac_set_bpp(svga, ramdac); - } - } - break; - case 5: - ramdac->index = (ramdac->index & 0xff00) | val; - break; - case 6: - ramdac->index = (ramdac->index & 0xff) | (val << 8); - break; - case 7: - if (ramdac->index < 0x100) - { - ramdac->regs[ramdac->index] = val; - } - if ((ramdac->index == 3) && (ramdac->command & 8)) stg_ramdac_set_bpp(svga, ramdac); - ramdac->index++; - break; - } - didwrite = (ramdac->magic_count >= 4); - ramdac->magic_count = stg_state_write[ramdac->magic_count & 7]; - if (didwrite) return; - break; - case 0x3c7: case 0x3c8: case 0x3c9: - ramdac->magic_count=0; - break; - } - svga_out(addr, val, svga); -} - -uint8_t stg_ramdac_in(uint16_t addr, stg_ramdac_t *ramdac, svga_t *svga) -{ - uint8_t temp = 0xff; - switch (addr) - { - case 0x3c6: - switch (ramdac->magic_count) - { - case 0: case 1: case 2: case 3: - temp = 0xff; - break; - case 4: - temp = ramdac->command; - break; - case 5: - temp = ramdac->index & 0xff; - break; - case 6: - temp = ramdac->index >> 8; - break; - case 7: - switch (ramdac->index) - { - case 0: - temp = 0x44; - break; - case 1: - temp = 0x03; - break; - case 7: - temp = 0x88; + case 0: + case 1: + case 2: + case 3: break; - default: - if (ramdac->index < 0x100) temp = ramdac->regs[ramdac->index]; - else temp = 0xff; - break; - } - ramdac->index++; - break; - } - ramdac->magic_count = stg_state_read[(ramdac->command & 0x10) ? 1 : 0][ramdac->magic_count & 7]; - return temp; - case 0x3c7: case 0x3c8: case 0x3c9: - ramdac->magic_count=0; - break; - } - return svga_in(addr, svga); + case 4: /* REG06 */ + old = dev->command; + dev->command = val; + if ((old ^ val) & 8) + set_bpp(svga, dev); + else { + if ((old ^ val) & 0xE0) + set_bpp(svga, dev); + } + break; + case 5: + dev->index = (dev->index & 0xff00) | val; + break; + case 6: + dev->index = (dev->index & 0xff) | (val << 8); + break; + case 7: + if (dev->index < 0x100) + dev->regs[dev->index] = val; + if ((dev->index == 3) && (dev->command & 8)) + set_bpp(svga, dev); + dev->index++; + break; + } + didwrite = (dev->magic_count >= 4); + dev->magic_count = stg_state_write[dev->magic_count & 7]; + if (didwrite) + return; + break; + case 0x3c7: + case 0x3c8: + case 0x3c9: + dev->magic_count = 0; + break; + } + + svga_out(addr, val, svga); } -float stg_getclock(int clock, void *p) + +uint8_t +stg_ramdac_in(uint16_t addr, stg_ramdac_t *dev, svga_t *svga) { - stg_ramdac_t *ramdac = (stg_ramdac_t *)p; - float t; - int m, n, n2; - float b, n1, d; - uint16_t *c; - if (clock == 0) return 25175000.0; - if (clock == 1) return 28322000.0; - clock ^= 1; /*Clocks 2 and 3 seem to be reversed*/ - c = (uint16_t *) &ramdac->regs[0x20 + (clock << 1)]; - m = (*c & 0xff) + 2; /* B+2 */ - n = ((*c >> 8) & 0x1f) + 2; /* N1+2 */ - n2 = ((*c >> 13) & 0x07); /* D */ - b = (float) m; - n1 = (float) n; - d = (float) (1 << n2); - t = (14318184.0f * b / d) / n1; - return t; + uint8_t temp = 0xff; + + switch (addr) { + case 0x3c6: + switch (dev->magic_count) { + case 0: + case 1: + case 2: + case 3: + temp = 0xff; + break; + case 4: + temp = dev->command; + break; + case 5: + temp = dev->index & 0xff; + break; + case 6: + temp = dev->index >> 8; + break; + case 7: + switch (dev->index) { + case 0: + temp = 0x44; + break; + case 1: + temp = 0x03; + break; + case 7: + temp = 0x88; + break; + default: + if (dev->index < 0x100) + temp = dev->regs[dev->index]; + else + temp = 0xff; + break; + } + dev->index++; + break; + } + dev->magic_count = stg_state_read[(dev->command & 0x10) ? 1 : 0][dev->magic_count & 7]; + return temp; + case 0x3c7: + case 0x3c8: + case 0x3c9: + dev->magic_count=0; + break; + } + + return svga_in(addr, svga); } + + +float +stg_getclock(int clock, void *priv) +{ + stg_ramdac_t *dev = (stg_ramdac_t *)priv; + float t; + int m, n, n2; + uint16_t *c; + + if (clock == 0) + return 25175000.0; + if (clock == 1) + return 28322000.0; + + clock ^= 1; /*Clocks 2 and 3 seem to be reversed*/ + c = (uint16_t *) &dev->regs[0x20 + (clock << 1)]; + m = (*c & 0xff) + 2; /* B+2 */ + n = ((*c >> 8) & 0x1f) + 2; /* N1+2 */ + n2 = ((*c >> 13) & 0x07); /* D */ + n2 = (1 << n2); + t = (14318184.0f * (float)m) / (float)(n * n2); + + return t; +} + + +static void * +stg_init(const device_t *info) +{ + stg_ramdac_t *dev = (stg_ramdac_t *)mem_alloc(sizeof(stg_ramdac_t)); + memset(dev, 0x00, sizeof(stg_ramdac_t)); + + return dev; +} + + +static void +stg_close(void *priv) +{ + stg_ramdac_t *dev = (stg_ramdac_t *)priv; + + if (dev != NULL) + free(dev); +} + + +const device_t stg_ramdac_device = { + "SGS-Thompson STG170x RAMDAC", + 0, + 0, + stg_init, stg_close, NULL, + NULL, NULL, NULL, NULL, + NULL +}; diff --git a/src/devices/video/vid_stg_ramdac.h b/src/devices/video/vid_stg_ramdac.h index 3d16246..a571b90 100644 --- a/src/devices/video/vid_stg_ramdac.h +++ b/src/devices/video/vid_stg_ramdac.h @@ -8,7 +8,7 @@ * * Definitions for the STG RAMDAC driver. * - * Version: @(#)vid_stg_ramdac.h 1.0.1 2018/02/14 + * Version: @(#)vid_stg_ramdac.h 1.0.2 2018/10/05 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -40,17 +40,19 @@ # define VIDEO_STG_RAMDAC_H -typedef struct stg_ramdac_t -{ - int magic_count; - uint8_t command; - int index; - uint8_t regs[256]; +typedef struct { + int magic_count, index; + uint8_t regs[256]; + uint8_t command; } stg_ramdac_t; -void stg_ramdac_out(uint16_t addr, uint8_t val, stg_ramdac_t *ramdac, svga_t *svga); -uint8_t stg_ramdac_in(uint16_t addr, stg_ramdac_t *ramdac, svga_t *svga); -float stg_getclock(int clock, void *p); + +extern const device_t stg_ramdac_device; + + +extern void stg_ramdac_out(uint16_t addr, uint8_t val, stg_ramdac_t *dev, svga_t *svga); +extern uint8_t stg_ramdac_in(uint16_t addr, stg_ramdac_t *dev, svga_t *svga); +extern float stg_getclock(int clock, void *priv); #endif /*VIDEO_STG_RAMDAC_H*/ diff --git a/src/devices/video/vid_svga.c b/src/devices/video/vid_svga.c index 6b78bb6..5d57e5a 100644 --- a/src/devices/video/vid_svga.c +++ b/src/devices/video/vid_svga.c @@ -11,7 +11,7 @@ * This is intended to be used by another SVGA driver, * and not as a card in it's own right. * - * Version: @(#)vid_svga.c 1.0.10 2018/05/06 + * Version: @(#)vid_svga.c 1.0.12 2018/10/05 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -58,1522 +58,1297 @@ #include "vid_svga_render.h" -#define svga_output 0 +extern int cyc_total; +extern uint8_t edatlookup[4][4]; -void svga_doblit(int y1, int y2, int wx, int wy, svga_t *svga); +uint8_t svga_rotate[8][256]; -extern uint8_t edatlookup[4][4]; - -uint8_t svga_rotate[8][256]; +static const uint32_t mask16[16] = { + 0x00000000, 0x000000ff, 0x0000ff00, 0x0000ffff, + 0x00ff0000, 0x00ff00ff, 0x00ffff00, 0x00ffffff, + 0xff000000, 0xff0000ff, 0xff00ff00, 0xff00ffff, + 0xffff0000, 0xffff00ff, 0xffffff00, 0xffffffff +}; /*Primary SVGA device. As multiple video cards are not yet supported this is the only SVGA device.*/ -static svga_t *svga_pri; +static svga_t *svga_pri; -svga_t *svga_get_pri() + +void svga_doblit(int y1, int y2, int wx, int wy, svga_t *svga); + + +svga_t * +svga_get_pri(void) { - return svga_pri; -} -void svga_set_override(svga_t *svga, int val) -{ - if (svga->override && !val) - svga->fullchange = changeframecount; - svga->override = val; + return svga_pri; } -void svga_out(uint16_t addr, uint8_t val, void *p) + +void +svga_set_override(svga_t *svga, int val) { - svga_t *svga = (svga_t *)p; - int c; - uint8_t o; - switch (addr) - { - case 0x3C0: - case 0x3C1: - if (!svga->attrff) - { - svga->attraddr = val & 31; - if ((val & 0x20) != svga->attr_palette_enable) - { - svga->fullchange = 3; - svga->attr_palette_enable = val & 0x20; - svga_recalctimings(svga); - } - } - else - { + if (svga->override && !val) + svga->fullchange = changeframecount; + svga->override = val; +} + + +void +svga_out(uint16_t addr, uint8_t val, void *priv) +{ + svga_t *svga = (svga_t *)priv; + uint8_t indx, o; + int c; + + switch (addr) { + case 0x3c0: + case 0x3c1: + if (!svga->attrff) { + svga->attraddr = val & 31; + if ((val & 0x20) != svga->attr_palette_enable) { + svga->fullchange = 3; + svga->attr_palette_enable = val & 0x20; + svga_recalctimings(svga); + } + } else { + if ((svga->attraddr == 0x13) && (svga->attrregs[0x13] != val)) + svga->fullchange = changeframecount; o = svga->attrregs[svga->attraddr & 31]; - svga->attrregs[svga->attraddr & 31] = val; - if (svga->attraddr < 16) - svga->fullchange = changeframecount; - if (svga->attraddr == 0x10 || svga->attraddr == 0x14 || svga->attraddr < 0x10) - { - for (c = 0; c < 16; c++) - { - if (svga->attrregs[0x10] & 0x80) svga->egapal[c] = (svga->attrregs[c] & 0xf) | ((svga->attrregs[0x14] & 0xf) << 4); - else svga->egapal[c] = (svga->attrregs[c] & 0x3f) | ((svga->attrregs[0x14] & 0xc) << 4); - } - } - /* Recalculate timings on change of attribute register 0x11 (overscan border color) too. */ - if (svga->attraddr == 0x10) - { - if (o != val) - svga_recalctimings(svga); + svga->attrregs[svga->attraddr & 31] = val; + if (svga->attraddr < 16) + svga->fullchange = changeframecount; + if (svga->attraddr == 0x10 || svga->attraddr == 0x14 || svga->attraddr < 0x10) { + for (c = 0; c < 16; c++) { + if (svga->attrregs[0x10] & 0x80) { + svga->egapal[c] = (svga->attrregs[c] & 0xf) | + ((svga->attrregs[0x14] & 0xf) << 4); + } else { + svga->egapal[c] = (svga->attrregs[c] & 0x3f) | + ((svga->attrregs[0x14] & 0xc) << 4); + } + } } - else if (svga->attraddr == 0x11) - { + /* Recalculate timings on change of attribute register 0x11 + (overscan border color) too. */ + if (svga->attraddr == 0x10) { + if (o != val) + svga_recalctimings(svga); + } else if (svga->attraddr == 0x11) { svga->overscan_color = svga->pallook[svga->attrregs[0x11]]; - if (o != val) + if (o != val) svga_recalctimings(svga); + } else if (svga->attraddr == 0x12) { + if ((val & 0xf) != svga->plane_mask) + svga->fullchange = changeframecount; + svga->plane_mask = val & 0xf; } - else if (svga->attraddr == 0x12) - { - if ((val & 0xf) != svga->plane_mask) - svga->fullchange = changeframecount; - svga->plane_mask = val & 0xf; - } - } - svga->attrff ^= 1; - break; - case 0x3C2: - svga->miscout = val; - svga->vidclock = val & 4; - io_removehandler(0x03a0, 0x0020, svga->video_in, NULL, NULL, svga->video_out, NULL, NULL, svga->p); + } + svga->attrff ^= 1; + break; + + case 0x3c2: + svga->miscout = val; + svga->vidclock = val & 4; + io_removehandler(0x03a0, 0x0020, svga->video_in, NULL, NULL, svga->video_out, NULL, NULL, svga->p); if (!(val & 1)) io_sethandler(0x03a0, 0x0020, svga->video_in, NULL, NULL, svga->video_out, NULL, NULL, svga->p); svga_recalctimings(svga); - break; - case 0x3C4: - svga->seqaddr = val; - break; - case 0x3C5: - if (svga->seqaddr > 0xf) return; - o = svga->seqregs[svga->seqaddr & 0xf]; - svga->seqregs[svga->seqaddr & 0xf] = val; - if (o != val && (svga->seqaddr & 0xf) == 1) - svga_recalctimings(svga); - switch (svga->seqaddr & 0xf) - { - case 1: - if (svga->scrblank && !(val & 0x20)) - svga->fullchange = 3; - svga->scrblank = (svga->scrblank & ~0x20) | (val & 0x20); - svga_recalctimings(svga); - break; - case 2: - svga->writemask = val & 0xf; - break; - case 3: - svga->charsetb = (((val >> 2) & 3) * 0x10000) + 2; - svga->charseta = ((val & 3) * 0x10000) + 2; - if (val & 0x10) - svga->charseta += 0x8000; - if (val & 0x20) - svga->charsetb += 0x8000; - break; - case 4: - svga->chain2_write = !(val & 4); - svga->chain4 = val & 8; - svga->fast = (svga->gdcreg[8] == 0xff && !(svga->gdcreg[3] & 0x18) && !svga->gdcreg[1]) && svga->chain4; - break; - } - break; - case 0x3c6: - svga->dac_mask = val; - break; - case 0x3C7: - svga->dac_read = val; - svga->dac_pos = 0; - break; - case 0x3C8: - svga->dac_write = val; - svga->dac_read = val - 1; - svga->dac_pos = 0; - break; - case 0x3C9: - svga->dac_status = 0; - svga->fullchange = changeframecount; - switch (svga->dac_pos) - { - case 0: - svga->dac_r = val; - svga->dac_pos++; - break; - case 1: - svga->dac_g = val; - svga->dac_pos++; - break; - case 2: - svga->vgapal[svga->dac_write].r = svga->dac_r; - svga->vgapal[svga->dac_write].g = svga->dac_g; - svga->vgapal[svga->dac_write].b = val; - if (svga->ramdac_type == RAMDAC_8BIT) - svga->pallook[svga->dac_write] = makecol32(svga->vgapal[svga->dac_write].r, svga->vgapal[svga->dac_write].g, svga->vgapal[svga->dac_write].b); - else - svga->pallook[svga->dac_write] = makecol32(video_6to8[svga->vgapal[svga->dac_write].r & 0x3f], video_6to8[svga->vgapal[svga->dac_write].g & 0x3f], video_6to8[svga->vgapal[svga->dac_write].b & 0x3f]); - svga->dac_pos = 0; - svga->dac_write = (svga->dac_write + 1) & 255; - break; - } - break; - case 0x3CE: - svga->gdcaddr = val; - break; - case 0x3CF: - o = svga->gdcreg[svga->gdcaddr & 15]; - switch (svga->gdcaddr & 15) - { - case 2: svga->colourcompare=val; break; - case 4: svga->readplane=val&3; break; - case 5: - svga->writemode = val & 3; - svga->readmode = val & 8; - svga->chain2_read = val & 0x10; - break; - case 6: - if ((svga->gdcreg[6] & 0xc) != (val & 0xc)) - { - switch (val&0xC) - { - case 0x0: /*128k at A0000*/ - mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x20000); - svga->banked_mask = 0xffff; - break; - case 0x4: /*64k at A0000*/ - mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000); - svga->banked_mask = 0xffff; - break; - case 0x8: /*32k at B0000*/ - mem_mapping_set_addr(&svga->mapping, 0xb0000, 0x08000); - svga->banked_mask = 0x7fff; - break; - case 0xC: /*32k at B8000*/ - mem_mapping_set_addr(&svga->mapping, 0xb8000, 0x08000); - svga->banked_mask = 0x7fff; - break; - } - } - break; - case 7: svga->colournocare=val; break; - } - svga->gdcreg[svga->gdcaddr & 15] = val; - svga->fast = (svga->gdcreg[8] == 0xff && !(svga->gdcreg[3] & 0x18) && !svga->gdcreg[1]) && svga->chain4; - if (((svga->gdcaddr & 15) == 5 && (val ^ o) & 0x70) || ((svga->gdcaddr & 15) == 6 && (val ^ o) & 1)) - svga_recalctimings(svga); - break; - } -} - -uint8_t svga_in(uint16_t addr, void *p) -{ - svga_t *svga = (svga_t *)p; - uint8_t temp; - switch (addr) - { - case 0x3C0: - return svga->attraddr | svga->attr_palette_enable; - case 0x3C1: - return svga->attrregs[svga->attraddr]; - case 0x3c2: - if ((svga->vgapal[0].r + svga->vgapal[0].g + svga->vgapal[0].b) >= 0x4e) - temp = 0; - else - temp = 0x10; - return temp; - case 0x3C4: - return svga->seqaddr; - case 0x3C5: - return svga->seqregs[svga->seqaddr & 0xF]; - case 0x3c6: return svga->dac_mask; - case 0x3c7: return svga->dac_status; - case 0x3c8: return svga->dac_write; - case 0x3c9: - svga->dac_status = 3; - switch (svga->dac_pos) - { - case 0: - svga->dac_pos++; - if (svga->ramdac_type == RAMDAC_8BIT) - return svga->vgapal[svga->dac_read].r; - return svga->vgapal[svga->dac_read].r & 0x3f; - case 1: - svga->dac_pos++; - if (svga->ramdac_type == RAMDAC_8BIT) - return svga->vgapal[svga->dac_read].g; - return svga->vgapal[svga->dac_read].g & 0x3f; - case 2: - svga->dac_pos=0; - svga->dac_read = (svga->dac_read + 1) & 255; - if (svga->ramdac_type == RAMDAC_8BIT) - return svga->vgapal[(svga->dac_read - 1) & 255].b; - return svga->vgapal[(svga->dac_read - 1) & 255].b & 0x3f; - } - break; - case 0x3CC: - return svga->miscout; - case 0x3CE: - return svga->gdcaddr; - case 0x3CF: - /* The spec says GDC addresses 0xF8 to 0xFB return the latch. */ - if (svga->gdcaddr == 0xF8) return svga->la; - if (svga->gdcaddr == 0xF9) return svga->lb; - if (svga->gdcaddr == 0xFA) return svga->lc; - if (svga->gdcaddr == 0xFB) return svga->ld; - return svga->gdcreg[svga->gdcaddr & 0xf]; - case 0x3DA: - svga->attrff = 0; - - if (svga->cgastat & 0x01) - svga->cgastat &= ~0x30; - else - svga->cgastat ^= 0x30; - return svga->cgastat; - } - return 0xFF; -} - -void svga_set_ramdac_type(svga_t *svga, int type) -{ - int c; - - if (svga->ramdac_type != type) - { - svga->ramdac_type = type; - - for (c = 0; c < 256; c++) - { - if (svga->ramdac_type == RAMDAC_8BIT) - svga->pallook[c] = makecol32(svga->vgapal[c].r, svga->vgapal[c].g, svga->vgapal[c].b); - else - svga->pallook[c] = makecol32((svga->vgapal[c].r & 0x3f) * 4, (svga->vgapal[c].g & 0x3f) * 4, (svga->vgapal[c].b & 0x3f) * 4); - } - } -} - -void svga_recalctimings(svga_t *svga) -{ - double crtcconst; - double _dispontime, _dispofftime, disptime; - - svga->vtotal = svga->crtc[6]; - svga->dispend = svga->crtc[0x12]; - svga->vsyncstart = svga->crtc[0x10]; - svga->split = svga->crtc[0x18]; - svga->vblankstart = svga->crtc[0x15]; - - if (svga->crtc[7] & 1) svga->vtotal |= 0x100; - if (svga->crtc[7] & 32) svga->vtotal |= 0x200; - svga->vtotal += 2; - - if (svga->crtc[7] & 2) svga->dispend |= 0x100; - if (svga->crtc[7] & 64) svga->dispend |= 0x200; - svga->dispend++; - - if (svga->crtc[7] & 4) svga->vsyncstart |= 0x100; - if (svga->crtc[7] & 128) svga->vsyncstart |= 0x200; - svga->vsyncstart++; - - if (svga->crtc[7] & 0x10) svga->split|=0x100; - if (svga->crtc[9] & 0x40) svga->split|=0x200; - svga->split++; - - if (svga->crtc[7] & 0x08) svga->vblankstart |= 0x100; - if (svga->crtc[9] & 0x20) svga->vblankstart |= 0x200; - svga->vblankstart++; - - svga->hdisp = svga->crtc[1]; - svga->hdisp++; - - svga->htotal = svga->crtc[0]; - svga->htotal += 6; /*+6 is required for Tyrian*/ - - svga->rowoffset = svga->crtc[0x13]; - - svga->clock = (svga->vidclock) ? VGACONST2 : VGACONST1; - - svga->lowres = svga->attrregs[0x10] & 0x40; - - svga->interlace = 0; - - svga->ma_latch = (svga->crtc[0xc] << 8) | svga->crtc[0xd]; - - svga->hdisp_time = svga->hdisp; - svga->render = svga_render_blank; - if (!svga->scrblank && svga->attr_palette_enable) { - if (!(svga->gdcreg[6] & 1) && !(svga->attrregs[0x10] & 1)) { /*Text mode*/ - if (svga->seqregs[1] & 8) /*40 column*/ { - svga->render = svga_render_text_40; - svga->hdisp *= (svga->seqregs[1] & 1) ? 16 : 18; - } else { - svga->render = svga_render_text_80; - svga->hdisp *= (svga->seqregs[1] & 1) ? 8 : 9; - } - svga->hdisp_old = svga->hdisp; - } else { - svga->hdisp *= (svga->seqregs[1] & 8) ? 16 : 8; - svga->hdisp_old = svga->hdisp; - - switch (svga->gdcreg[5] & 0x60) { - case 0x00: /*16 colours*/ - if (svga->seqregs[1] & 8) /*Low res (320)*/ - svga->render = svga_render_4bpp_lowres; - else - svga->render = svga_render_4bpp_highres; - break; - case 0x20: /*4 colours*/ - if (svga->seqregs[1] & 8) /*Low res (320)*/ - svga->render = svga_render_2bpp_lowres; - else - svga->render = svga_render_2bpp_highres; - break; - case 0x40: case 0x60: /*256+ colours*/ - switch (svga->bpp) { - case 8: - if (svga->lowres) - svga->render = svga_render_8bpp_lowres; - else - svga->render = svga_render_8bpp_highres; - break; - case 15: - if (svga->lowres) - svga->render = svga_render_15bpp_lowres; - else - svga->render = svga_render_15bpp_highres; - break; - case 16: - if (svga->lowres) - svga->render = svga_render_16bpp_lowres; - else - svga->render = svga_render_16bpp_highres; - break; - case 24: - if (svga->lowres) - svga->render = svga_render_24bpp_lowres; - else - svga->render = svga_render_24bpp_highres; - break; - case 32: - if (svga->lowres) - svga->render = svga_render_32bpp_lowres; - else - svga->render = svga_render_32bpp_highres; - break; - } - break; - } - } - } - - svga->linedbl = svga->crtc[9] & 0x80; - svga->rowcount = svga->crtc[9] & 31; - if (enable_overscan) { - overscan_y = (svga->rowcount + 1) << 1; - if (svga->seqregs[1] & 8) /*Low res (320)*/ - overscan_y <<= 1; - if (overscan_y < 16) - overscan_y = 16; - } - if (svga->recalctimings_ex) - svga->recalctimings_ex(svga); - - if (svga->vblankstart < svga->dispend) - svga->dispend = svga->vblankstart; - - crtcconst = (svga->seqregs[1] & 1) ? (svga->clock * 8.0) : (svga->clock * 9.0); - - disptime = svga->htotal; - _dispontime = svga->hdisp_time; - - if (svga->seqregs[1] & 8) { disptime *= 2; _dispontime *= 2; } - _dispofftime = disptime - _dispontime; - _dispontime *= crtcconst; - _dispofftime *= crtcconst; - - svga->dispontime = (int)(_dispontime * (1 << TIMER_SHIFT)); - svga->dispofftime = (int)(_dispofftime * (1 << TIMER_SHIFT)); -} - -extern int cyc_total; -void svga_poll(void *p) -{ - svga_t *svga = (svga_t *)p; - uint32_t x; - - if (!svga->linepos) { - if (svga->displine == svga->hwcursor_latch.y && svga->hwcursor_latch.ena) { - svga->hwcursor_on = 64 - svga->hwcursor_latch.yoff; - svga->hwcursor_oddeven = 0; - } - - if (svga->displine == svga->hwcursor_latch.y+1 && svga->hwcursor_latch.ena && svga->interlace) { - svga->hwcursor_on = 64 - (svga->hwcursor_latch.yoff + 1); - svga->hwcursor_oddeven = 1; - } - - if (svga->displine == svga->overlay_latch.y && svga->overlay_latch.ena) { - svga->overlay_on = svga->overlay_latch.ysize - svga->overlay_latch.yoff; - svga->overlay_oddeven = 0; - } - if (svga->displine == svga->overlay_latch.y+1 && svga->overlay_latch.ena && svga->interlace) { - svga->overlay_on = svga->overlay_latch.ysize - svga->overlay_latch.yoff; - svga->overlay_oddeven = 1; - } - - svga->vidtime += svga->dispofftime; - svga->cgastat |= 1; - svga->linepos = 1; - - if (svga->dispon) { - svga->hdisp_on=1; - - svga->ma &= svga->vram_display_mask; - if (svga->firstline == 2000) { - svga->firstline = svga->displine; - video_wait_for_buffer(); - } - - if (svga->hwcursor_on || svga->overlay_on) - svga->changedvram[svga->ma >> 12] = svga->changedvram[(svga->ma >> 12) + 1] = svga->interlace ? 3 : 2; - - if (!svga->override) - svga->render(svga); - - if (svga->overlay_on) { - if (!svga->override) - svga->overlay_draw(svga, svga->displine); - svga->overlay_on--; - if (svga->overlay_on && svga->interlace) - svga->overlay_on--; - } - - if (svga->hwcursor_on) { - if (!svga->override) - svga->hwcursor_draw(svga, svga->displine); - svga->hwcursor_on--; - if (svga->hwcursor_on && svga->interlace) - svga->hwcursor_on--; - } - - if (svga->lastline < svga->displine) - svga->lastline = svga->displine; - } - - svga->displine++; - if (svga->interlace) - svga->displine++; - if ((svga->cgastat & 8) && ((svga->displine & 15) == (svga->crtc[0x11] & 15)) && svga->vslines) - svga->cgastat &= ~8; - svga->vslines++; - if (svga->displine > 1500) - svga->displine = 0; - } else { - svga->vidtime += svga->dispontime; - - if (svga->dispon) - svga->cgastat &= ~1; - svga->hdisp_on = 0; - - svga->linepos = 0; - if (svga->sc == (svga->crtc[11] & 31)) - svga->con = 0; - if (svga->dispon) { - if (svga->linedbl && !svga->linecountff) { - svga->linecountff = 1; - svga->ma = svga->maback; - } else if (svga->sc == svga->rowcount) { - svga->linecountff = 0; - svga->sc = 0; - - svga->maback += (svga->rowoffset << 3); - if (svga->interlace) - svga->maback += (svga->rowoffset << 3); - svga->maback &= svga->vram_display_mask; - svga->ma = svga->maback; - } else { - svga->linecountff = 0; - svga->sc++; - svga->sc &= 31; - svga->ma = svga->maback; - } - } - svga->vc++; - svga->vc &= 2047; - - if (svga->vc == svga->split) { - svga->ma = svga->maback = 0; - if (svga->attrregs[0x10] & 0x20) - svga->scrollcache = 0; - } - if (svga->vc == svga->dispend) { - if (svga->vblank_start) - svga->vblank_start(svga); - svga->dispon=0; - if (svga->crtc[10] & 0x20) svga->cursoron = 0; - else svga->cursoron = svga->blink & 16; - if (!(svga->gdcreg[6] & 1) && !(svga->blink & 15)) - svga->fullchange = 2; - svga->blink++; - - for (x = 0; x < ((svga->vram_mask+1) >> 12); x++) { - if (svga->changedvram[x]) - svga->changedvram[x]--; - } - if (svga->fullchange) - svga->fullchange--; - } - if (svga->vc == svga->vsyncstart) { - int wx, wy; - svga->dispon=0; - svga->cgastat |= 8; - x = svga->hdisp; - - if (svga->interlace && !svga->oddeven) svga->lastline++; - if (svga->interlace && svga->oddeven) svga->firstline--; - - wx = x; - wy = svga->lastline - svga->firstline; - - if (!svga->override) - svga_doblit(svga->firstline_draw, svga->lastline_draw + 1, wx, wy, svga); - - svga->firstline = 2000; - svga->lastline = 0; - - svga->firstline_draw = 2000; - svga->lastline_draw = 0; - - svga->oddeven ^= 1; - - changeframecount = svga->interlace ? 3 : 2; - svga->vslines = 0; - - if (svga->interlace && svga->oddeven) svga->ma = svga->maback = svga->ma_latch + (svga->rowoffset << 1); - else svga->ma = svga->maback = svga->ma_latch; - svga->ca = (svga->crtc[0xe] << 8) | svga->crtc[0xf]; - - svga->ma <<= 2; - svga->maback <<= 2; - svga->ca <<= 2; - - svga->video_res_x = wx; - svga->video_res_y = wy + 1; - if (!(svga->gdcreg[6] & 1) && !(svga->attrregs[0x10] & 1)) { /*Text mode*/ - svga->video_res_x /= (svga->seqregs[1] & 1) ? 8 : 9; - svga->video_res_y /= (svga->crtc[9] & 31) + 1; - svga->video_bpp = 0; - } else { - if (svga->crtc[9] & 0x80) - svga->video_res_y /= 2; - if (!(svga->crtc[0x17] & 2)) - svga->video_res_y *= 4; - else if (!(svga->crtc[0x17] & 1)) - svga->video_res_y *= 2; - svga->video_res_y /= (svga->crtc[9] & 31) + 1; - if (svga->lowres) - svga->video_res_x /= 2; - - switch (svga->gdcreg[5] & 0x60) { - case 0x00: svga->video_bpp = 4; break; - case 0x20: svga->video_bpp = 2; break; - case 0x40: case 0x60: svga->video_bpp = svga->bpp; break; - } - } - } - if (svga->vc == svga->vtotal) { - svga->vc = 0; - svga->sc = svga->crtc[8] & 0x1f; - svga->dispon = 1; - svga->displine = (svga->interlace && svga->oddeven) ? 1 : 0; - svga->scrollcache = svga->attrregs[0x13] & 7; - svga->linecountff = 0; - - svga->hwcursor_on = 0; - svga->hwcursor_latch = svga->hwcursor; - - svga->overlay_on = 0; - svga->overlay_latch = svga->overlay; - } - if (svga->sc == (svga->crtc[10] & 31)) - svga->con = 1; - } -} - -int svga_init(svga_t *svga, void *p, int memsize, - void (*recalctimings_ex)(struct svga_t *svga), - uint8_t (*video_in) (uint16_t addr, void *p), - void (*video_out)(uint16_t addr, uint8_t val, void *p), - void (*hwcursor_draw)(struct svga_t *svga, int displine), - void (*overlay_draw)(struct svga_t *svga, int displine)) -{ - int c, d, e; - - svga->p = p; - - for (c = 0; c < 256; c++) { - e = c; - for (d = 0; d < 8; d++) { - svga_rotate[d][c] = e; - e = (e >> 1) | ((e & 1) ? 0x80 : 0); - } - } - svga->readmode = 0; - - svga->attrregs[0x11] = 0; - svga->overscan_color = 0x000000; - - overscan_x = 16; - overscan_y = 32; - - svga->crtc[0] = 63; - svga->crtc[6] = 255; - svga->dispontime = 1000 * (1 << TIMER_SHIFT); - svga->dispofftime = 1000 * (1 << TIMER_SHIFT); - svga->bpp = 8; - svga->vram = malloc(memsize); - svga->vram_max = memsize; - svga->vram_display_mask = memsize - 1; - svga->vram_mask = memsize - 1; - svga->decode_mask = 0x7fffff; - svga->changedvram = malloc(/*(memsize >> 12) << 1*/0x800000 >> 12); - svga->recalctimings_ex = recalctimings_ex; - svga->video_in = video_in; - svga->video_out = video_out; - svga->hwcursor_draw = hwcursor_draw; - svga->overlay_draw = overlay_draw; - - mem_mapping_add(&svga->mapping, 0xa0000, 0x20000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel, NULL, MEM_MAPPING_EXTERNAL, svga); - - timer_add(svga_poll, &svga->vidtime, TIMER_ALWAYS_ENABLED, svga); - - svga_pri = svga; - - svga->ramdac_type = RAMDAC_6BIT; - - return 0; -} - -void svga_close(svga_t *svga) -{ - free(svga->changedvram); - free(svga->vram); - - svga_pri = NULL; -} - -void svga_write(uint32_t addr, uint8_t val, void *p) -{ - svga_t *svga = (svga_t *)p; - uint8_t vala, valb, valc, vald, wm = svga->writemask; - int writemask2 = svga->writemask; - - egawrites++; - - cycles -= video_timing_write_b; - cycles_lost += video_timing_write_b; - - if (svga_output) pclog("Writeega %06X ",addr); - addr &= svga->banked_mask; - addr += svga->write_bank; - - if (!(svga->gdcreg[6] & 1)) svga->fullchange=2; - if (svga->chain4 || svga->fb_only) - { - writemask2=1<<(addr&3); - addr&=~3; - } - else if (svga->chain2_write) - { - writemask2 &= ~0xa; - if (addr & 1) - writemask2 <<= 1; - addr &= ~1; - addr <<= 2; - } - else - { - addr<<=2; - } - addr &= svga->decode_mask; - - if (addr >= svga->vram_max) - return; - - addr &= svga->vram_mask; - - if (svga_output) pclog("%08X (%i, %i) %02X %i %i %i %02X\n", addr, addr & 1023, addr >> 10, val, writemask2, svga->writemode, svga->chain4, svga->gdcreg[8]); - svga->changedvram[addr >> 12] = changeframecount; - - switch (svga->writemode) - { - case 1: - if (writemask2 & 1) svga->vram[addr] = svga->la; - if (writemask2 & 2) svga->vram[addr | 0x1] = svga->lb; - if (writemask2 & 4) svga->vram[addr | 0x2] = svga->lc; - if (writemask2 & 8) svga->vram[addr | 0x3] = svga->ld; - break; - case 0: - if (svga->gdcreg[3] & 7) - val = svga_rotate[svga->gdcreg[3] & 7][val]; - if (svga->gdcreg[8] == 0xff && !(svga->gdcreg[3] & 0x18) && (!svga->gdcreg[1] || svga->set_reset_disabled)) - { - if (writemask2 & 1) svga->vram[addr] = val; - if (writemask2 & 2) svga->vram[addr | 0x1] = val; - if (writemask2 & 4) svga->vram[addr | 0x2] = val; - if (writemask2 & 8) svga->vram[addr | 0x3] = val; - } - else - { - if (svga->gdcreg[1] & 1) vala = (svga->gdcreg[0] & 1) ? 0xff : 0; - else vala = val; - if (svga->gdcreg[1] & 2) valb = (svga->gdcreg[0] & 2) ? 0xff : 0; - else valb = val; - if (svga->gdcreg[1] & 4) valc = (svga->gdcreg[0] & 4) ? 0xff : 0; - else valc = val; - if (svga->gdcreg[1] & 8) vald = (svga->gdcreg[0] & 8) ? 0xff : 0; - else vald = val; - - switch (svga->gdcreg[3] & 0x18) - { - case 0: /*Set*/ - if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) | (svga->la & ~svga->gdcreg[8]); - if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) | (svga->lb & ~svga->gdcreg[8]); - if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) | (svga->lc & ~svga->gdcreg[8]); - if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) | (svga->ld & ~svga->gdcreg[8]); - break; - case 8: /*AND*/ - if (writemask2 & 1) svga->vram[addr] = (vala | ~svga->gdcreg[8]) & svga->la; - if (writemask2 & 2) svga->vram[addr | 0x1] = (valb | ~svga->gdcreg[8]) & svga->lb; - if (writemask2 & 4) svga->vram[addr | 0x2] = (valc | ~svga->gdcreg[8]) & svga->lc; - if (writemask2 & 8) svga->vram[addr | 0x3] = (vald | ~svga->gdcreg[8]) & svga->ld; - break; - case 0x10: /*OR*/ - if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) | svga->la; - if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) | svga->lb; - if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) | svga->lc; - if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) | svga->ld; - break; - case 0x18: /*XOR*/ - if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) ^ svga->la; - if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) ^ svga->lb; - if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) ^ svga->lc; - if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) ^ svga->ld; - break; - } -// pclog("- %02X %02X %02X %02X %08X\n",vram[addr],vram[addr|0x1],vram[addr|0x2],vram[addr|0x3],addr); - } - break; - case 2: - if (!(svga->gdcreg[3] & 0x18) && (!svga->gdcreg[1] || svga->set_reset_disabled)) - { - if (writemask2 & 1) svga->vram[addr] = (((val & 1) ? 0xff : 0) & svga->gdcreg[8]) | (svga->la & ~svga->gdcreg[8]); - if (writemask2 & 2) svga->vram[addr | 0x1] = (((val & 2) ? 0xff : 0) & svga->gdcreg[8]) | (svga->lb & ~svga->gdcreg[8]); - if (writemask2 & 4) svga->vram[addr | 0x2] = (((val & 4) ? 0xff : 0) & svga->gdcreg[8]) | (svga->lc & ~svga->gdcreg[8]); - if (writemask2 & 8) svga->vram[addr | 0x3] = (((val & 8) ? 0xff : 0) & svga->gdcreg[8]) | (svga->ld & ~svga->gdcreg[8]); - } - else - { - vala = ((val & 1) ? 0xff : 0); - valb = ((val & 2) ? 0xff : 0); - valc = ((val & 4) ? 0xff : 0); - vald = ((val & 8) ? 0xff : 0); - switch (svga->gdcreg[3] & 0x18) - { - case 0: /*Set*/ - if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) | (svga->la & ~svga->gdcreg[8]); - if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) | (svga->lb & ~svga->gdcreg[8]); - if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) | (svga->lc & ~svga->gdcreg[8]); - if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) | (svga->ld & ~svga->gdcreg[8]); - break; - case 8: /*AND*/ - if (writemask2 & 1) svga->vram[addr] = (vala | ~svga->gdcreg[8]) & svga->la; - if (writemask2 & 2) svga->vram[addr | 0x1] = (valb | ~svga->gdcreg[8]) & svga->lb; - if (writemask2 & 4) svga->vram[addr | 0x2] = (valc | ~svga->gdcreg[8]) & svga->lc; - if (writemask2 & 8) svga->vram[addr | 0x3] = (vald | ~svga->gdcreg[8]) & svga->ld; - break; - case 0x10: /*OR*/ - if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) | svga->la; - if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) | svga->lb; - if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) | svga->lc; - if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) | svga->ld; - break; - case 0x18: /*XOR*/ - if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) ^ svga->la; - if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) ^ svga->lb; - if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) ^ svga->lc; - if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) ^ svga->ld; - break; - } - } - break; - case 3: - if (svga->gdcreg[3] & 7) - val = svga_rotate[svga->gdcreg[3] & 7][val]; - wm = svga->gdcreg[8]; - svga->gdcreg[8] &= val; - - vala = (svga->gdcreg[0] & 1) ? 0xff : 0; - valb = (svga->gdcreg[0] & 2) ? 0xff : 0; - valc = (svga->gdcreg[0] & 4) ? 0xff : 0; - vald = (svga->gdcreg[0] & 8) ? 0xff : 0; - switch (svga->gdcreg[3] & 0x18) - { - case 0: /*Set*/ - if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) | (svga->la & ~svga->gdcreg[8]); - if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) | (svga->lb & ~svga->gdcreg[8]); - if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) | (svga->lc & ~svga->gdcreg[8]); - if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) | (svga->ld & ~svga->gdcreg[8]); - break; - case 8: /*AND*/ - if (writemask2 & 1) svga->vram[addr] = (vala | ~svga->gdcreg[8]) & svga->la; - if (writemask2 & 2) svga->vram[addr | 0x1] = (valb | ~svga->gdcreg[8]) & svga->lb; - if (writemask2 & 4) svga->vram[addr | 0x2] = (valc | ~svga->gdcreg[8]) & svga->lc; - if (writemask2 & 8) svga->vram[addr | 0x3] = (vald | ~svga->gdcreg[8]) & svga->ld; - break; - case 0x10: /*OR*/ - if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) | svga->la; - if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) | svga->lb; - if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) | svga->lc; - if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) | svga->ld; - break; - case 0x18: /*XOR*/ - if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) ^ svga->la; - if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) ^ svga->lb; - if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) ^ svga->lc; - if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) ^ svga->ld; - break; - } - svga->gdcreg[8] = wm; - break; - } -} - -uint8_t svga_read(uint32_t addr, void *p) -{ - svga_t *svga = (svga_t *)p; - uint8_t temp, temp2, temp3, temp4; - uint32_t latch_addr; - int readplane = svga->readplane; - - cycles -= video_timing_read_b; - cycles_lost += video_timing_read_b; - - egareads++; -// pclog("Readega %06X ",addr); - - addr &= svga->banked_mask; - addr += svga->read_bank; - - latch_addr = (addr << 2) & svga->decode_mask; - -// pclog("%05X %i %04X:%04X %02X %02X %i\n",addr,svga->chain4,CS,pc, vram[addr & 0x7fffff], vram[(addr << 2) & 0x7fffff], svga->readmode); -// pclog("%i\n", svga->readmode); - if (svga->chain4 || svga->fb_only) - { - addr &= svga->decode_mask; - if (addr >= svga->vram_max) - return 0xff; - return svga->vram[addr & svga->vram_mask]; - } - else if (svga->chain2_read) - { - readplane = (readplane & 2) | (addr & 1); - addr &= ~1; - addr <<= 2; - } - else - addr<<=2; - - addr &= svga->decode_mask; - - if (latch_addr >= svga->vram_max) - { - svga->la = svga->lb = svga->lc = svga->ld = 0xff; - } - else - { - latch_addr &= svga->vram_mask; - svga->la = svga->vram[latch_addr]; - svga->lb = svga->vram[latch_addr | 0x1]; - svga->lc = svga->vram[latch_addr | 0x2]; - svga->ld = svga->vram[latch_addr | 0x3]; - } - - if (addr >= svga->vram_max) - return 0xff; - - addr &= svga->vram_mask; - - if (svga->readmode) - { - temp = svga->la; - temp ^= (svga->colourcompare & 1) ? 0xff : 0; - temp &= (svga->colournocare & 1) ? 0xff : 0; - temp2 = svga->lb; - temp2 ^= (svga->colourcompare & 2) ? 0xff : 0; - temp2 &= (svga->colournocare & 2) ? 0xff : 0; - temp3 = svga->lc; - temp3 ^= (svga->colourcompare & 4) ? 0xff : 0; - temp3 &= (svga->colournocare & 4) ? 0xff : 0; - temp4 = svga->ld; - temp4 ^= (svga->colourcompare & 8) ? 0xff : 0; - temp4 &= (svga->colournocare & 8) ? 0xff : 0; - return ~(temp | temp2 | temp3 | temp4); - } -//pclog("Read %02X %04X %04X\n",vram[addr|svga->readplane],addr,svga->readplane); - - return svga->vram[addr | readplane]; -} - -void svga_write_linear(uint32_t addr, uint8_t val, void *p) -{ - svga_t *svga = (svga_t *)p; - uint8_t vala, valb, valc, vald, wm = svga->writemask; - int writemask2 = svga->writemask; - - cycles -= video_timing_write_b; - cycles_lost += video_timing_write_b; - - egawrites++; - - if (svga_output) pclog("Write LFB %08X %02X ", addr, val); - if (!(svga->gdcreg[6] & 1)) - svga->fullchange = 2; - if (svga->chain4 || svga->fb_only) - { - writemask2=1<<(addr&3); - addr&=~3; - } - else if (svga->chain2_write) - { - writemask2 &= ~0xa; - if (addr & 1) - writemask2 <<= 1; - addr &= ~1; - addr <<= 2; - } - else - { - addr<<=2; - } - addr &= svga->decode_mask; - if (addr >= svga->vram_max) - return; - addr &= svga->vram_mask; - if (svga_output) pclog("%08X\n", addr); - svga->changedvram[addr >> 12]=changeframecount; - - switch (svga->writemode) - { - case 1: - if (writemask2 & 1) svga->vram[addr] = svga->la; - if (writemask2 & 2) svga->vram[addr | 0x1] = svga->lb; - if (writemask2 & 4) svga->vram[addr | 0x2] = svga->lc; - if (writemask2 & 8) svga->vram[addr | 0x3] = svga->ld; - break; - case 0: - if (svga->gdcreg[3] & 7) - val = svga_rotate[svga->gdcreg[3] & 7][val]; - if (svga->gdcreg[8] == 0xff && !(svga->gdcreg[3] & 0x18) && (!svga->gdcreg[1] || svga->set_reset_disabled)) - { - if (writemask2 & 1) svga->vram[addr] = val; - if (writemask2 & 2) svga->vram[addr | 0x1] = val; - if (writemask2 & 4) svga->vram[addr | 0x2] = val; - if (writemask2 & 8) svga->vram[addr | 0x3] = val; - } - else - { - if (svga->gdcreg[1] & 1) vala = (svga->gdcreg[0] & 1) ? 0xff : 0; - else vala = val; - if (svga->gdcreg[1] & 2) valb = (svga->gdcreg[0] & 2) ? 0xff : 0; - else valb = val; - if (svga->gdcreg[1] & 4) valc = (svga->gdcreg[0] & 4) ? 0xff : 0; - else valc = val; - if (svga->gdcreg[1] & 8) vald = (svga->gdcreg[0] & 8) ? 0xff : 0; - else vald = val; - - switch (svga->gdcreg[3] & 0x18) - { - case 0: /*Set*/ - if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) | (svga->la & ~svga->gdcreg[8]); - if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) | (svga->lb & ~svga->gdcreg[8]); - if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) | (svga->lc & ~svga->gdcreg[8]); - if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) | (svga->ld & ~svga->gdcreg[8]); - break; - case 8: /*AND*/ - if (writemask2 & 1) svga->vram[addr] = (vala | ~svga->gdcreg[8]) & svga->la; - if (writemask2 & 2) svga->vram[addr | 0x1] = (valb | ~svga->gdcreg[8]) & svga->lb; - if (writemask2 & 4) svga->vram[addr | 0x2] = (valc | ~svga->gdcreg[8]) & svga->lc; - if (writemask2 & 8) svga->vram[addr | 0x3] = (vald | ~svga->gdcreg[8]) & svga->ld; - break; - case 0x10: /*OR*/ - if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) | svga->la; - if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) | svga->lb; - if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) | svga->lc; - if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) | svga->ld; - break; - case 0x18: /*XOR*/ - if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) ^ svga->la; - if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) ^ svga->lb; - if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) ^ svga->lc; - if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) ^ svga->ld; - break; - } -// pclog("- %02X %02X %02X %02X %08X\n",vram[addr],vram[addr|0x1],vram[addr|0x2],vram[addr|0x3],addr); - } - break; - case 2: - if (!(svga->gdcreg[3] & 0x18) && (!svga->gdcreg[1] || svga->set_reset_disabled)) - { - if (writemask2 & 1) svga->vram[addr] = (((val & 1) ? 0xff : 0) & svga->gdcreg[8]) | (svga->la & ~svga->gdcreg[8]); - if (writemask2 & 2) svga->vram[addr | 0x1] = (((val & 2) ? 0xff : 0) & svga->gdcreg[8]) | (svga->lb & ~svga->gdcreg[8]); - if (writemask2 & 4) svga->vram[addr | 0x2] = (((val & 4) ? 0xff : 0) & svga->gdcreg[8]) | (svga->lc & ~svga->gdcreg[8]); - if (writemask2 & 8) svga->vram[addr | 0x3] = (((val & 8) ? 0xff : 0) & svga->gdcreg[8]) | (svga->ld & ~svga->gdcreg[8]); - } - else - { - vala = ((val & 1) ? 0xff : 0); - valb = ((val & 2) ? 0xff : 0); - valc = ((val & 4) ? 0xff : 0); - vald = ((val & 8) ? 0xff : 0); - switch (svga->gdcreg[3] & 0x18) - { - case 0: /*Set*/ - if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) | (svga->la & ~svga->gdcreg[8]); - if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) | (svga->lb & ~svga->gdcreg[8]); - if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) | (svga->lc & ~svga->gdcreg[8]); - if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) | (svga->ld & ~svga->gdcreg[8]); - break; - case 8: /*AND*/ - if (writemask2 & 1) svga->vram[addr] = (vala | ~svga->gdcreg[8]) & svga->la; - if (writemask2 & 2) svga->vram[addr | 0x1] = (valb | ~svga->gdcreg[8]) & svga->lb; - if (writemask2 & 4) svga->vram[addr | 0x2] = (valc | ~svga->gdcreg[8]) & svga->lc; - if (writemask2 & 8) svga->vram[addr | 0x3] = (vald | ~svga->gdcreg[8]) & svga->ld; - break; - case 0x10: /*OR*/ - if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) | svga->la; - if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) | svga->lb; - if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) | svga->lc; - if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) | svga->ld; - break; - case 0x18: /*XOR*/ - if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) ^ svga->la; - if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) ^ svga->lb; - if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) ^ svga->lc; - if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) ^ svga->ld; - break; - } - } - break; - case 3: - if (svga->gdcreg[3] & 7) - val = svga_rotate[svga->gdcreg[3] & 7][val]; - wm = svga->gdcreg[8]; - svga->gdcreg[8] &= val; - - vala = (svga->gdcreg[0] & 1) ? 0xff : 0; - valb = (svga->gdcreg[0] & 2) ? 0xff : 0; - valc = (svga->gdcreg[0] & 4) ? 0xff : 0; - vald = (svga->gdcreg[0] & 8) ? 0xff : 0; - switch (svga->gdcreg[3] & 0x18) - { - case 0: /*Set*/ - if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) | (svga->la & ~svga->gdcreg[8]); - if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) | (svga->lb & ~svga->gdcreg[8]); - if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) | (svga->lc & ~svga->gdcreg[8]); - if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) | (svga->ld & ~svga->gdcreg[8]); - break; - case 8: /*AND*/ - if (writemask2 & 1) svga->vram[addr] = (vala | ~svga->gdcreg[8]) & svga->la; - if (writemask2 & 2) svga->vram[addr | 0x1] = (valb | ~svga->gdcreg[8]) & svga->lb; - if (writemask2 & 4) svga->vram[addr | 0x2] = (valc | ~svga->gdcreg[8]) & svga->lc; - if (writemask2 & 8) svga->vram[addr | 0x3] = (vald | ~svga->gdcreg[8]) & svga->ld; - break; - case 0x10: /*OR*/ - if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) | svga->la; - if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) | svga->lb; - if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) | svga->lc; - if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) | svga->ld; - break; - case 0x18: /*XOR*/ - if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) ^ svga->la; - if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) ^ svga->lb; - if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) ^ svga->lc; - if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) ^ svga->ld; - break; - } - svga->gdcreg[8] = wm; - break; - } -} - -uint8_t svga_read_linear(uint32_t addr, void *p) -{ - svga_t *svga = (svga_t *)p; - uint8_t temp, temp2, temp3, temp4; - int readplane = svga->readplane; - - cycles -= video_timing_read_b; - cycles_lost += video_timing_read_b; - - egareads++; - - if (svga->chain4 || svga->fb_only) - { - addr &= svga->decode_mask; - if (addr >= svga->vram_max) - return 0xff; - return svga->vram[addr & svga->vram_mask]; - } - else if (svga->chain2_read) - { - readplane = (readplane & 2) | (addr & 1); - addr &= ~1; - addr <<= 2; - } - else - addr<<=2; - - addr &= svga->decode_mask; - - if (addr >= svga->vram_max) - return 0xff; - - addr &= svga->vram_mask; - - svga->la = svga->vram[addr]; - svga->lb = svga->vram[addr | 0x1]; - svga->lc = svga->vram[addr | 0x2]; - svga->ld = svga->vram[addr | 0x3]; - if (svga->readmode) - { - temp = svga->la; - temp ^= (svga->colourcompare & 1) ? 0xff : 0; - temp &= (svga->colournocare & 1) ? 0xff : 0; - temp2 = svga->lb; - temp2 ^= (svga->colourcompare & 2) ? 0xff : 0; - temp2 &= (svga->colournocare & 2) ? 0xff : 0; - temp3 = svga->lc; - temp3 ^= (svga->colourcompare & 4) ? 0xff : 0; - temp3 &= (svga->colournocare & 4) ? 0xff : 0; - temp4 = svga->ld; - temp4 ^= (svga->colourcompare & 8) ? 0xff : 0; - temp4 &= (svga->colournocare & 8) ? 0xff : 0; - return ~(temp | temp2 | temp3 | temp4); - } - return svga->vram[addr | readplane]; -} - -void svga_doblit(int y1, int y2, int wx, int wy, svga_t *svga) -{ - int y_add = (enable_overscan) ? overscan_y : 0; - int x_add = (enable_overscan) ? 16 : 0; - uint32_t *p; - int i, j; - - svga->frames++; - - if ((xsize > 2032) || (ysize > 2032)) { - x_add = 0; - y_add = 0; - suppress_overscan = 1; - } else - suppress_overscan = 0; - - if (y1 > y2) { - video_blit_memtoscreen(32, 0, 0, 0, xsize + x_add, ysize + y_add); - return; - } - - if ((wx != xsize) || ((wy + 1) != ysize) || video_force_resize_get()) { - /* Screen res has changed.. fix up, and let them know. */ - xsize = wx; - ysize = wy+1; - if (xsize<64) xsize = 640; - if (ysize<32) ysize = 200; - - set_screen_size(xsize+x_add,ysize+y_add); - - if (video_force_resize_get()) - video_force_resize_set(0); - } - - if (enable_overscan && !suppress_overscan) { - if ((wx >= 160) && ((wy + 1) >= 120)) { - /* Draw (overscan_size - scroll size) lines of overscan on top. */ - for (i = 0; i < (y_add >> 1); i++) { - p = &((uint32_t *)buffer32->line[i & 0x7ff])[32]; - - for (j = 0; j < (xsize + x_add); j++) - p[j] = svga_color_transform(svga->overscan_color); - } - - /* Draw (overscan_size + scroll size) lines of overscan on the bottom. */ - for (i = 0; i < (y_add >> 1); i++) { - p = &((uint32_t *)buffer32->line[(ysize + (y_add >> 1) + i) & 0x7ff])[32]; - - for (j = 0; j < (xsize + x_add); j++) - p[j] = svga_color_transform(svga->overscan_color); - } - - for (i = (y_add >> 1); i < (ysize + (y_add >> 1)); i ++) { - p = &((uint32_t *)buffer32->line[i & 0x7ff])[32]; - - for (j = 0; j < 8; j++) { - p[j] = svga->pallook[svga->overscan_color]; - p[xsize + (x_add >> 1) + j] = svga_color_transform(svga->overscan_color); + break; + + case 0x3c4: + svga->seqaddr = val; + break; + + case 0x3c5: + if (svga->seqaddr > 0xf) + return; + o = svga->seqregs[svga->seqaddr & 0xf]; + svga->seqregs[svga->seqaddr & 0xf] = val; + if (o != val && (svga->seqaddr & 0xf) == 1) + svga_recalctimings(svga); + switch (svga->seqaddr & 0xf) { + case 1: + if (svga->scrblank && !(val & 0x20)) + svga->fullchange = 3; + svga->scrblank = (svga->scrblank & ~0x20) | (val & 0x20); + svga_recalctimings(svga); + break; + + case 2: + svga->writemask = val & 0xf; + break; + + case 3: + svga->charsetb = (((val >> 2) & 3) * 0x10000) + 2; + svga->charseta = ((val & 3) * 0x10000) + 2; + if (val & 0x10) + svga->charseta += 0x8000; + if (val & 0x20) + svga->charsetb += 0x8000; + break; + + case 4: + svga->chain2_write = !(val & 4); + svga->chain4 = val & 8; + svga->fast = (svga->gdcreg[8] == 0xff && !(svga->gdcreg[3] & 0x18) && + !svga->gdcreg[1]) && svga->chain4; + break; + } + break; + + case 0x3c6: + svga->dac_mask = val; + break; + + case 0x3c7: + case 0x3c8: + svga->dac_pos = 0; + svga->dac_status = addr & 0x03; + svga->dac_addr = (val + (addr & 0x01)) & 255; + break; + + case 0x3c9: + svga->fullchange = changeframecount; + switch (svga->dac_pos) { + case 0: + svga->dac_r = val; + svga->dac_pos++; + break; + + case 1: + svga->dac_g = val; + svga->dac_pos++; + break; + + case 2: + indx = svga->dac_addr & 255; + svga->vgapal[indx].r = svga->dac_r; + svga->vgapal[indx].g = svga->dac_g; + svga->vgapal[indx].b = val; + if (svga->ramdac_type == RAMDAC_8BIT) + svga->pallook[indx] = makecol32(svga->vgapal[indx].r, svga->vgapal[indx].g, svga->vgapal[indx].b); + else + svga->pallook[indx] = makecol32(video_6to8[svga->vgapal[indx].r & 0x3f], video_6to8[svga->vgapal[indx].g & 0x3f], video_6to8[svga->vgapal[indx].b & 0x3f]); + svga->dac_pos = 0; + svga->dac_addr = (svga->dac_addr + 1) & 255; + break; + } + break; + + case 0x3ce: + svga->gdcaddr = val; + break; + + case 0x3cf: + o = svga->gdcreg[svga->gdcaddr & 15]; + switch (svga->gdcaddr & 15) { + case 2: + svga->colourcompare = val; + break; + + case 4: + svga->readplane = val & 3; + break; + + case 5: + svga->writemode = val & 3; + svga->readmode = val & 8; + svga->chain2_read = val & 0x10; + break; + + case 6: + if ((svga->gdcreg[6] & 0xc) != (val & 0xc)) { + switch (val&0xC) { + case 0x0: /*128k at A0000*/ + mem_map_set_addr(&svga->mapping, 0xa0000, 0x20000); + svga->banked_mask = 0xffff; + break; + + case 0x4: /*64k at A0000*/ + mem_map_set_addr(&svga->mapping, 0xa0000, 0x10000); + svga->banked_mask = 0xffff; + break; + + case 0x8: /*32k at B0000*/ + mem_map_set_addr(&svga->mapping, 0xb0000, 0x08000); + svga->banked_mask = 0x7fff; + break; + + case 0xC: /*32k at B8000*/ + mem_map_set_addr(&svga->mapping, 0xb8000, 0x08000); + svga->banked_mask = 0x7fff; + break; + } } + break; + + case 7: + svga->colournocare=val; + break; + } + svga->gdcreg[svga->gdcaddr & 15] = val; + svga->fast = (svga->gdcreg[8] == 0xff && !(svga->gdcreg[3] & 0x18) && + !svga->gdcreg[1]) && svga->chain4; + if (((svga->gdcaddr & 15) == 5 && (val ^ o) & 0x70) || + ((svga->gdcaddr & 15) == 6 && (val ^ o) & 1)) + svga_recalctimings(svga); + break; + } +} + + +uint8_t +svga_in(uint16_t addr, void *priv) +{ + svga_t *svga = (svga_t *)priv; + uint8_t indx, ret = 0xff; + + switch (addr) { + case 0x3c0: + ret = svga->attraddr | svga->attr_palette_enable; + break; + + case 0x3c1: + ret = svga->attrregs[svga->attraddr]; + break; + + case 0x3c2: + if ((svga->vgapal[0].r + svga->vgapal[0].g + svga->vgapal[0].b) >= 0x4e) + ret = 0; + else + ret = 0x10; + break; + + case 0x3c4: + ret = svga->seqaddr; + break; + + case 0x3c5: + ret = svga->seqregs[svga->seqaddr & 0x0f]; + break; + + case 0x3c6: + ret = svga->dac_mask; + break; + + case 0x3c7: + ret = svga->dac_status; + break; + + case 0x3c8: + ret = svga->dac_addr; + break; + + case 0x3c9: + indx = (svga->dac_addr - 1) & 255; + switch (svga->dac_pos) { + case 0: + svga->dac_pos++; + if (svga->ramdac_type == RAMDAC_8BIT) + ret = svga->vgapal[indx].r; + else + ret = svga->vgapal[indx].r & 0x3f; + break; + + case 1: + svga->dac_pos++; + if (svga->ramdac_type == RAMDAC_8BIT) + ret = svga->vgapal[indx].g; + else + ret = svga->vgapal[indx].g & 0x3f; + break; + + case 2: + svga->dac_pos = 0; + svga->dac_addr = (svga->dac_addr + 1) & 255; + if (svga->ramdac_type == RAMDAC_8BIT) + ret = svga->vgapal[indx].b; + else + ret = svga->vgapal[indx].b & 0x3f; + break; + } + break; + case 0x3cc: + ret = svga->miscout; + break; + case 0x3ce: + ret = svga->gdcaddr; + break; + case 0x3cf: + /* The spec says GDC addresses 0xF8 to 0xFB return the latch. */ + switch(svga->gdcaddr) { + case 0xf8: + ret = (svga->latch & 0xFF); + break; + case 0xf9: + ret = ((svga->latch & 0xFF00) >> 8); + break; + case 0xfa: + ret = ((svga->latch & 0xFF0000) >> 16); + break; + case 0xfb: + ret = ((svga->latch & 0xFF000000) >> 24); + break; + default: + ret = svga->gdcreg[svga->gdcaddr & 0xf]; + break; + } + break; + case 0x3da: + svga->attrff = 0; + svga->attrff = 0; + + if (svga->cgastat & 0x01) + svga->cgastat &= ~0x30; + else + svga->cgastat ^= 0x30; + ret = svga->cgastat; + break; + } + + return(ret); +} + + +void +svga_set_ramdac_type(svga_t *svga, int type) +{ + int c; + + if (svga->ramdac_type != type) { + svga->ramdac_type = type; + + for (c = 0; c < 256; c++) { + if (svga->ramdac_type == RAMDAC_8BIT) + svga->pallook[c] = makecol32(svga->vgapal[c].r, svga->vgapal[c].g, svga->vgapal[c].b); + else + svga->pallook[c] = makecol32((svga->vgapal[c].r & 0x3f) * 4, + (svga->vgapal[c].g & 0x3f) * 4, + (svga->vgapal[c].b & 0x3f) * 4); + } + } +} + + +void +svga_recalctimings(svga_t *svga) +{ + double crtcconst, _dispontime, _dispofftime, disptime; + + svga->vtotal = svga->crtc[6]; + svga->dispend = svga->crtc[0x12]; + svga->vsyncstart = svga->crtc[0x10]; + svga->split = svga->crtc[0x18]; + svga->vblankstart = svga->crtc[0x15]; + + if (svga->crtc[7] & 1) + svga->vtotal |= 0x100; + if (svga->crtc[7] & 32) + svga->vtotal |= 0x200; + svga->vtotal += 2; + + if (svga->crtc[7] & 2) + svga->dispend |= 0x100; + if (svga->crtc[7] & 64) + svga->dispend |= 0x200; + svga->dispend++; + + if (svga->crtc[7] & 4) + svga->vsyncstart |= 0x100; + if (svga->crtc[7] & 128) + svga->vsyncstart |= 0x200; + svga->vsyncstart++; + + if (svga->crtc[7] & 0x10) + svga->split|=0x100; + if (svga->crtc[9] & 0x40) + svga->split|=0x200; + svga->split++; + + if (svga->crtc[7] & 0x08) + svga->vblankstart |= 0x100; + if (svga->crtc[9] & 0x20) + svga->vblankstart |= 0x200; + svga->vblankstart++; + + svga->hdisp = svga->crtc[1]; + svga->hdisp++; + + svga->htotal = svga->crtc[0]; + svga->htotal += 6; /*+6 is required for Tyrian*/ + + svga->rowoffset = svga->crtc[0x13]; + + svga->clock = (svga->vidclock) ? VGACONST2 : VGACONST1; + + svga->lowres = svga->attrregs[0x10] & 0x40; + + svga->interlace = 0; + + svga->ma_latch = (svga->crtc[0xc] << 8) | svga->crtc[0xd]; + + svga->hdisp_time = svga->hdisp; + svga->render = svga_render_blank; + if (!svga->scrblank && svga->attr_palette_enable) { + if (!(svga->gdcreg[6] & 1) && !(svga->attrregs[0x10] & 1)) { /*Text mode*/ + if (svga->seqregs[1] & 8) /*40 column*/ { + svga->render = svga_render_text_40; + svga->hdisp *= (svga->seqregs[1] & 1) ? 16 : 18; + } else { + svga->render = svga_render_text_80; + svga->hdisp *= (svga->seqregs[1] & 1) ? 8 : 9; + } + svga->hdisp_old = svga->hdisp; + } else { + svga->hdisp *= (svga->seqregs[1] & 8) ? 16 : 8; + svga->hdisp_old = svga->hdisp; + + switch (svga->gdcreg[5] & 0x60) { + case 0x00: + if (svga->seqregs[1] & 8) /*Low res (320)*/ + svga->render = svga_render_4bpp_lowres; + else + svga->render = svga_render_4bpp_highres; + break; + case 0x20: /*4 colours*/ + if (svga->seqregs[1] & 8) /*Low res (320)*/ + svga->render = svga_render_2bpp_lowres; + else + svga->render = svga_render_2bpp_highres; + break; + case 0x40: case 0x60: /*256+ colours*/ + switch (svga->bpp) { + case 8: + if (svga->lowres) + svga->render = svga_render_8bpp_lowres; + else + svga->render = svga_render_8bpp_highres; + break; + case 15: + if (svga->lowres) + svga->render = svga_render_15bpp_lowres; + else + svga->render = svga_render_15bpp_highres; + break; + case 16: + if (svga->lowres) + svga->render = svga_render_16bpp_lowres; + else + svga->render = svga_render_16bpp_highres; + break; + case 24: + if (svga->lowres) + svga->render = svga_render_24bpp_lowres; + else + svga->render = svga_render_24bpp_highres; + break; + case 32: + if (svga->lowres) + svga->render = svga_render_32bpp_lowres; + else + svga->render = svga_render_32bpp_highres; + break; + } + break; + } + } + } + + svga->linedbl = svga->crtc[9] & 0x80; + svga->rowcount = svga->crtc[9] & 31; + if (enable_overscan) { + overscan_y = (svga->rowcount + 1) << 1; + if (svga->seqregs[1] & 8) /*Low res (320)*/ + overscan_y <<= 1; + if (overscan_y < 16) + overscan_y = 16; + } + if (svga->recalctimings_ex) + svga->recalctimings_ex(svga); + + if (svga->vblankstart < svga->dispend) + svga->dispend = svga->vblankstart; + + crtcconst = (svga->seqregs[1] & 1) ? (svga->clock * 8.0) : (svga->clock * 9.0); + + disptime = svga->htotal; + _dispontime = svga->hdisp_time; + + if (svga->seqregs[1] & 8) { + disptime *= 2; + _dispontime *= 2; + } + _dispofftime = disptime - _dispontime; + _dispontime *= crtcconst; + _dispofftime *= crtcconst; + + svga->dispontime = (int)(_dispontime * (1 << TIMER_SHIFT)); + svga->dispofftime = (int)(_dispofftime * (1 << TIMER_SHIFT)); +} + + +void +svga_poll(void *p) +{ + svga_t *svga = (svga_t *)p; + uint32_t x; + int wx, wy; + + if (!svga->linepos) { + if (svga->displine == svga->hwcursor_latch.y && svga->hwcursor_latch.ena) { + svga->hwcursor_on = 64 - svga->hwcursor_latch.yoff; + svga->hwcursor_oddeven = 0; + } + + if (svga->displine == (svga->hwcursor_latch.y + 1) && svga->hwcursor_latch.ena && + svga->interlace) { + svga->hwcursor_on = 64 - (svga->hwcursor_latch.yoff + 1); + svga->hwcursor_oddeven = 1; + } + + if (svga->displine == svga->overlay_latch.y && svga->overlay_latch.ena) { + svga->overlay_on = svga->overlay_latch.ysize - svga->overlay_latch.yoff; + svga->overlay_oddeven = 0; + } + + if (svga->displine == svga->overlay_latch.y+1 && svga->overlay_latch.ena && svga->interlace) { + svga->overlay_on = svga->overlay_latch.ysize - svga->overlay_latch.yoff; + svga->overlay_oddeven = 1; + } + + svga->vidtime += svga->dispofftime; + svga->cgastat |= 1; + svga->linepos = 1; + + if (svga->dispon) { + svga->hdisp_on=1; + + svga->ma &= svga->vram_display_mask; + if (svga->firstline == 2000) { + svga->firstline = svga->displine; + video_wait_for_buffer(); + } + + if (svga->hwcursor_on || svga->overlay_on) { + svga->changedvram[svga->ma >> 12] = svga->changedvram[(svga->ma >> 12) + 1] = + svga->interlace ? 3 : 2; + } + + if (!svga->override) + svga->render(svga); + + if (svga->overlay_on) { + if (!svga->override) + svga->overlay_draw(svga, svga->displine); + svga->overlay_on--; + if (svga->overlay_on && svga->interlace) + svga->overlay_on--; + } + + if (svga->hwcursor_on) { + if (!svga->override) + svga->hwcursor_draw(svga, svga->displine); + svga->hwcursor_on--; + if (svga->hwcursor_on && svga->interlace) + svga->hwcursor_on--; + } + + if (svga->lastline < svga->displine) + svga->lastline = svga->displine; + } + + svga->displine++; + if (svga->interlace) + svga->displine++; + if ((svga->cgastat & 8) && ((svga->displine & 15) == (svga->crtc[0x11] & 15)) && svga->vslines) + svga->cgastat &= ~8; + svga->vslines++; + if (svga->displine > 1500) + svga->displine = 0; + } else { + svga->vidtime += svga->dispontime; + + if (svga->dispon) + svga->cgastat &= ~1; + svga->hdisp_on = 0; + + svga->linepos = 0; + if (svga->sc == (svga->crtc[11] & 31)) + svga->con = 0; + if (svga->dispon) { + if (svga->linedbl && !svga->linecountff) { + svga->linecountff = 1; + svga->ma = svga->maback; + } else if (svga->sc == svga->rowcount) { + svga->linecountff = 0; + svga->sc = 0; + + svga->maback += (svga->rowoffset << 3); + if (svga->interlace) + svga->maback += (svga->rowoffset << 3); + svga->maback &= svga->vram_display_mask; + svga->ma = svga->maback; + } else { + svga->linecountff = 0; + svga->sc++; + svga->sc &= 31; + svga->ma = svga->maback; + } + } + svga->vc++; + svga->vc &= 2047; + + if (svga->vc == svga->split) { + svga->ma = svga->maback = 0; + svga->sc = 0; + if (svga->attrregs[0x10] & 0x20) + svga->scrollcache = 0; + } + if (svga->vc == svga->dispend) { + if (svga->vblank_start) + svga->vblank_start(svga); + svga->dispon=0; + if (svga->crtc[10] & 0x20) + svga->cursoron = 0; + else + svga->cursoron = svga->blink & 16; + + if (!(svga->gdcreg[6] & 1) && !(svga->blink & 15)) + svga->fullchange = 2; + svga->blink++; + + for (x = 0; x < ((svga->vram_mask + 1) >> 12); x++) { + if (svga->changedvram[x]) + svga->changedvram[x]--; + } + if (svga->fullchange) + svga->fullchange--; + } + if (svga->vc == svga->vsyncstart) { + svga->dispon = 0; + svga->cgastat |= 8; + x = svga->hdisp; + + if (svga->interlace && !svga->oddeven) + svga->lastline++; + if (svga->interlace && svga->oddeven) + svga->firstline--; + + wx = x; + wy = svga->lastline - svga->firstline; + + if (!svga->override) + svga_doblit(svga->firstline_draw, svga->lastline_draw + 1, wx, wy, svga); + + svga->firstline = 2000; + svga->lastline = 0; + + svga->firstline_draw = 2000; + svga->lastline_draw = 0; + + svga->oddeven ^= 1; + + changeframecount = svga->interlace ? 3 : 2; + svga->vslines = 0; + + if (svga->interlace && svga->oddeven) + svga->ma = svga->maback = svga->ma_latch + (svga->rowoffset << 1); + else + svga->ma = svga->maback = svga->ma_latch; + svga->ca = (svga->crtc[0xe] << 8) | svga->crtc[0xf]; + + svga->ma <<= 2; + svga->maback <<= 2; + svga->ca <<= 2; + + svga->video_res_x = wx; + svga->video_res_y = wy + 1; + if (!(svga->gdcreg[6] & 1) && !(svga->attrregs[0x10] & 1)) { /*Text mode*/ + svga->video_res_x /= (svga->seqregs[1] & 1) ? 8 : 9; + svga->video_res_y /= (svga->crtc[9] & 31) + 1; + svga->video_bpp = 0; + } else { + if (svga->crtc[9] & 0x80) + svga->video_res_y /= 2; + if (!(svga->crtc[0x17] & 2)) + svga->video_res_y *= 4; + else if (!(svga->crtc[0x17] & 1)) + svga->video_res_y *= 2; + svga->video_res_y /= (svga->crtc[9] & 31) + 1; + if (svga->lowres) + svga->video_res_x /= 2; + + svga->video_bpp = svga->bpp; + } + } + if (svga->vc == svga->vtotal) { + svga->vc = 0; + svga->sc = svga->crtc[8] & 0x1f; + svga->dispon = 1; + svga->displine = (svga->interlace && svga->oddeven) ? 1 : 0; + svga->scrollcache = svga->attrregs[0x13] & 7; + svga->linecountff = 0; + + svga->hwcursor_on = 0; + svga->hwcursor_latch = svga->hwcursor; + + svga->overlay_on = 0; + svga->overlay_latch = svga->overlay; + } + if (svga->sc == (svga->crtc[10] & 31)) + svga->con = 1; + } +} + + +int +svga_init(svga_t *svga, void *p, int memsize, + void (*recalctimings_ex)(struct svga_t *svga), + uint8_t (*video_in) (uint16_t addr, void *p), + void (*video_out)(uint16_t addr, uint8_t val, void *p), + void (*hwcursor_draw)(struct svga_t *svga, int displine), + void (*overlay_draw)(struct svga_t *svga, int displine)) +{ + int c, d, e; + + svga->p = p; + + for (c = 0; c < 256; c++) { + e = c; + for (d = 0; d < 8; d++) { + svga_rotate[d][c] = e; + e = (e >> 1) | ((e & 1) ? 0x80 : 0); + } + } + svga->readmode = 0; + + svga->attrregs[0x11] = 0; + svga->overscan_color = 0x000000; + + overscan_x = 16; + overscan_y = 32; + + svga->crtc[0] = 63; + svga->crtc[6] = 255; + svga->dispontime = svga->dispofftime = 1000 * (1 << TIMER_SHIFT); + svga->bpp = 8; + svga->vram = (uint8_t *)mem_alloc(memsize); + svga->vram_max = memsize; + svga->vram_display_mask = svga->vram_mask = memsize - 1; + svga->decode_mask = 0x7fffff; + svga->changedvram = (uint8_t *)mem_alloc(memsize >> 12); + svga->recalctimings_ex = recalctimings_ex; + svga->video_in = video_in; + svga->video_out = video_out; + svga->hwcursor_draw = hwcursor_draw; + svga->overlay_draw = overlay_draw; + + svga->hwcursor.xsize = svga->hwcursor.ysize = 32; + svga->hwcursor.yoff = 32; + + mem_map_add(&svga->mapping, 0xa0000, 0x20000, + svga_read, svga_readw, svga_readl, + svga_write, svga_writew, svga_writel, + NULL, MEM_MAPPING_EXTERNAL, svga); + + timer_add(svga_poll, &svga->vidtime, TIMER_ALWAYS_ENABLED, svga); + + svga_pri = svga; + + svga->ramdac_type = RAMDAC_6BIT; + + return 0; +} + + +void +svga_close(svga_t *svga) +{ + free(svga->changedvram); + free(svga->vram); + + svga_pri = NULL; +} + + +void +svga_write_common(uint32_t addr, uint8_t val, uint8_t linear, void *p) +{ + svga_t *svga = (svga_t *)p; + + int func_select, writemask2 = svga->writemask; + uint32_t write_mask, bit_mask, set_mask, val32 = (uint32_t) val; + + cycles -= video_timing_write_b; + + if (!linear) { + addr &= svga->banked_mask; + addr += svga->write_bank; + } + + if (!(svga->gdcreg[6] & 1)) + svga->fullchange = 2; + + if ((svga->chain4 || svga->fb_only) && (svga->writemode < 4)) { + writemask2 = 1 << (addr & 3); + addr &= ~3; + } else if (svga->chain2_write) { + writemask2 &= ~0xa; + if (addr & 1) + writemask2 <<= 1; + addr &= ~1; + addr <<= 2; + } else + addr <<= 2; + addr &= svga->decode_mask; + + if (addr >= svga->vram_max) + return; + + addr &= svga->vram_mask; + + svga->changedvram[addr >> 12] = changeframecount; + + /* standard VGA latched access */ + func_select = (svga->gdcreg[3] >> 3) & 3; + + switch (svga->writemode) { + case 0: + /* rotate */ + if (svga->gdcreg[3] & 7) + val32 = svga_rotate[svga->gdcreg[3] & 7][val32]; + + /* apply set/reset mask */ + bit_mask = svga->gdcreg[8]; + + val32 |= (val32 << 8); + val32 |= (val32 << 16); + + if (svga->gdcreg[8] == 0xff && !(svga->gdcreg[3] & 0x18) && + (!svga->gdcreg[1] || svga->set_reset_disabled)) { + /* mask data according to sr[2] */ + write_mask = mask16[writemask2 & 0x0f]; + addr >>= 2; + ((uint32_t *)(svga->vram))[addr] &= ~write_mask; + ((uint32_t *)(svga->vram))[addr] |= (val32 & write_mask); + return; + } + + set_mask = mask16[svga->gdcreg[1] & 0x0f]; + val32 = (val32 & ~set_mask) | (mask16[svga->gdcreg[0] & 0x0f] & set_mask); + break; + case 1: + val32 = svga->latch; + + /* mask data according to sr[2] */ + write_mask = mask16[writemask2 & 0x0f]; + addr >>= 2; + ((uint32_t *)(svga->vram))[addr] &= ~write_mask; + ((uint32_t *)(svga->vram))[addr] |= (val32 & write_mask); + return; + case 2: + val32 = mask16[val32 & 0x0f]; + bit_mask = svga->gdcreg[8]; + + if (!(svga->gdcreg[3] & 0x18) && (!svga->gdcreg[1] || svga->set_reset_disabled)) + func_select = 0; + break; + case 3: + /* rotate */ + if (svga->gdcreg[3] & 7) + val32 = svga_rotate[svga->gdcreg[3] & 7][val]; + + bit_mask = svga->gdcreg[8] & val32; + val32 = mask16[svga->gdcreg[0] & 0x0f]; + break; + default: + if (svga->ven_write) + svga->ven_write(svga, val, addr); + return; + } + + /* apply bit mask */ + bit_mask |= bit_mask << 8; + bit_mask |= bit_mask << 16; + + /* apply logical operation */ + switch(func_select) { + case 0: + default: + /* set */ + val32 &= bit_mask; + val32 |= (svga->latch & ~bit_mask); + break; + case 1: + /* and */ + val32 |= ~bit_mask; + val32 &= svga->latch; + break; + case 2: + /* or */ + val32 &= bit_mask; + val32 |= svga->latch; + break; + case 3: + /* xor */ + val32 &= bit_mask; + val32 ^= svga->latch; + break; + } + + /* mask data according to sr[2] */ + write_mask = mask16[writemask2 & 0x0f]; + addr >>= 2; + ((uint32_t *)(svga->vram))[addr] = (((uint32_t *)(svga->vram))[addr] & ~write_mask) | (val32 & write_mask); +} + + +uint8_t +svga_read_common(uint32_t addr, uint8_t linear, void *p) +{ + svga_t *svga = (svga_t *)p; + uint32_t latch_addr = 0, ret; + int readplane = svga->readplane; + uint8_t ret8; + + cycles -= video_timing_read_b; + + if (!linear) { + addr &= svga->banked_mask; + addr += svga->read_bank; + + latch_addr = (addr << 2) & svga->decode_mask; + } + + if (svga->chain4 || svga->fb_only) { + addr &= svga->decode_mask; + if (addr >= svga->vram_max) + return 0xff; + return svga->vram[addr & svga->vram_mask]; + } else if (svga->chain2_read) { + readplane = (readplane & 2) | (addr & 1); + addr &= ~1; + addr <<= 2; + } else + addr <<= 2; + + addr &= svga->decode_mask; + + /* standard VGA latched access */ + if (linear) { + if (addr >= svga->vram_max) + return 0xff; + + addr &= svga->vram_mask; + + svga->latch = ((uint32_t *)(svga->vram))[addr >> 2]; + } else { + if (latch_addr > svga->vram_max) + svga->latch = 0xffffffff; + else { + latch_addr &= svga->vram_mask; + svga->latch = ((uint32_t *)(svga->vram))[latch_addr >> 2]; + } + + if (addr >= svga->vram_max) + return 0xff; + + addr &= svga->vram_mask; + } + + if (!(svga->gdcreg[5] & 8)) { + /* read mode 0 */ + return svga->vram[addr | readplane]; + } else { + /* read mode 1 */ + ret = (svga->latch ^ mask16[svga->colourcompare & 0x0f]) & mask16[svga->colournocare & 0x0f]; + ret8 = (ret & 0xff); + ret8 |= ((ret >> 24) & 0xff); + ret8 |= ((ret >> 16) & 0xff); + ret8 |= ((ret >> 8) & 0xff); + return(~ret8); + } +} + + +void +svga_write(uint32_t addr, uint8_t val, void *p) +{ + svga_write_common(addr, val, 0, p); +} + + +void +svga_write_linear(uint32_t addr, uint8_t val, void *p) +{ + svga_write_common(addr, val, 1, p); +} + + +uint8_t +svga_read(uint32_t addr, void *p) +{ + return svga_read_common(addr, 0, p); +} + + +uint8_t +svga_read_linear(uint32_t addr, void *p) +{ + return svga_read_common(addr, 1, p); +} + + +void +svga_doblit(int y1, int y2, int wx, int wy, svga_t *svga) +{ + int y_add = (enable_overscan) ? overscan_y : 0; + int x_add = (enable_overscan) ? 16 : 0; + uint32_t *p; + int i, j; + + svga->frames++; + + if ((xsize > 2032) || (ysize > 2032)) { + x_add = 0; + y_add = 0; + suppress_overscan = 1; + } else + suppress_overscan = 0; + + if (y1 > y2) { + video_blit_memtoscreen(32, 0, 0, 0, xsize + x_add, ysize + y_add); + return; + } + + if ((wx != xsize) || ((wy + 1) != ysize) || video_force_resize_get()) { + /* Screen res has changed.. fix up, and let them know. */ + xsize = wx; + ysize = wy + 1; + if (xsize < 64) + xsize = 640; + if (ysize < 32) + ysize = 200; + + set_screen_size(xsize+x_add,ysize+y_add); + + if (video_force_resize_get()) + video_force_resize_set(0); + } + + if (enable_overscan && !suppress_overscan) { + if ((wx >= 160) && ((wy + 1) >= 120)) { + /* Draw (overscan_size - scroll size) lines of overscan on top. */ + for (i = 0; i < (y_add >> 1); i++) { + p = &((uint32_t *)buffer32->line[i & 0x7ff])[32]; + + for (j = 0; j < (xsize + x_add); j++) + p[j] = svga->overscan_color; + } + + /* Draw (overscan_size + scroll size) lines of overscan on the bottom. */ + for (i = 0; i < (y_add >> 1); i++) { + p = &((uint32_t *)buffer32->line[(ysize + (y_add >> 1) + i) & 0x7ff])[32]; + + for (j = 0; j < (xsize + x_add); j++) + p[j] = svga->overscan_color; + } + + for (i = (y_add >> 1); i < (ysize + (y_add >> 1)); i ++) { + p = &((uint32_t *)buffer32->line[i & 0x7ff])[32]; + + for (j = 0; j < 8; j++) { + p[j] = svga->pallook[svga->overscan_color]; + p[xsize + (x_add >> 1) + j] = svga->overscan_color; } } } + } - video_blit_memtoscreen(32, 0, y1, y2 + y_add, xsize + x_add, ysize + y_add); + video_blit_memtoscreen(32, 0, y1, y2 + y_add, xsize + x_add, ysize + y_add); } -void svga_writew(uint32_t addr, uint16_t val, void *p) + +void +svga_writeb_linear(uint32_t addr, uint8_t val, void *p) { - svga_t *svga = (svga_t *)p; - if (!svga->fast) - { - svga_write(addr, val & 0xff, p); - svga_write(addr + 1, val >> 8, p); - return; - } + svga_t *svga = (svga_t *)p; - egawrites += 2; + if (!svga->fast) { + svga_write_linear(addr, val, p); + return; + } - cycles -= video_timing_write_w; - cycles_lost += video_timing_write_w; - - if (svga_output) pclog("svga_writew: %05X ", addr); - addr = (addr & svga->banked_mask) + svga->write_bank; - addr &= svga->decode_mask; - if (addr >= svga->vram_max) - return; - addr &= svga->vram_mask; - if (svga_output) pclog("%08X (%i, %i) %04X\n", addr, addr & 1023, addr >> 10, val); - svga->changedvram[addr >> 12] = changeframecount; - *(uint16_t *)&svga->vram[addr] = val; + addr &= svga->decode_mask; + if (addr >= svga->vram_max) + return; + addr &= svga->vram_mask; + svga->changedvram[addr >> 12] = changeframecount; + *(uint8_t *)&svga->vram[addr] = val; } -void svga_writel(uint32_t addr, uint32_t val, void *p) + +void +svga_writew_common(uint32_t addr, uint16_t val, uint8_t linear, void *p) { - svga_t *svga = (svga_t *)p; + svga_t *svga = (svga_t *)p; - if (!svga->fast) - { - svga_write(addr, val, p); - svga_write(addr + 1, val >> 8, p); - svga_write(addr + 2, val >> 16, p); - svga_write(addr + 3, val >> 24, p); - return; - } + if (!svga->fast) { + svga_write_common(addr, val & 0xff, linear, p); + svga_write_common(addr + 1, val >> 8, linear, p); + return; + } - egawrites += 4; + cycles -= video_timing_write_w; - cycles -= video_timing_write_l; - cycles_lost += video_timing_write_l; - - if (svga_output) pclog("svga_writel: %05X ", addr); - addr = (addr & svga->banked_mask) + svga->write_bank; - addr &= svga->decode_mask; - if (addr >= svga->vram_max) - return; - addr &= svga->vram_mask; - if (svga_output) pclog("%08X (%i, %i) %08X\n", addr, addr & 1023, addr >> 10, val); - - svga->changedvram[addr >> 12] = changeframecount; - *(uint32_t *)&svga->vram[addr] = val; + if (!linear) + addr = (addr & svga->banked_mask) + svga->write_bank; + addr &= svga->decode_mask; + if (addr >= svga->vram_max) + return; + addr &= svga->vram_mask; + svga->changedvram[addr >> 12] = changeframecount; + *(uint16_t *)&svga->vram[addr] = val; } -uint16_t svga_readw(uint32_t addr, void *p) + +void +svga_writew(uint32_t addr, uint16_t val, void *p) { - svga_t *svga = (svga_t *)p; - - if (!svga->fast) - return svga_read(addr, p) | (svga_read(addr + 1, p) << 8); - - egareads += 2; - - cycles -= video_timing_read_w; - cycles_lost += video_timing_read_w; - -// pclog("Readw %05X ", addr); - addr = (addr & svga->banked_mask) + svga->read_bank; - addr &= svga->decode_mask; -// pclog("%08X %04X\n", addr, *(uint16_t *)&vram[addr]); - if (addr >= svga->vram_max) - return 0xffff; - - return *(uint16_t *)&svga->vram[addr & svga->vram_mask]; + svga_writew_common(addr, val, 0, p); } -uint32_t svga_readl(uint32_t addr, void *p) + +void +svga_writew_linear(uint32_t addr, uint16_t val, void *p) { - svga_t *svga = (svga_t *)p; - - if (!svga->fast) - return svga_read(addr, p) | (svga_read(addr + 1, p) << 8) | (svga_read(addr + 2, p) << 16) | (svga_read(addr + 3, p) << 24); - - egareads += 4; - - cycles -= video_timing_read_l; - cycles_lost += video_timing_read_l; - -// pclog("Readl %05X ", addr); - addr = (addr & svga->banked_mask) + svga->read_bank; - addr &= svga->decode_mask; -// pclog("%08X %08X\n", addr, *(uint32_t *)&vram[addr]); - if (addr >= svga->vram_max) - return 0xffffffff; - - return *(uint32_t *)&svga->vram[addr & svga->vram_mask]; + svga_writew_common(addr, val, 1, p); } -void svga_writeb_linear(uint32_t addr, uint8_t val, void *p) + +void +svga_writel_common(uint32_t addr, uint32_t val, uint8_t linear, void *p) { - svga_t *svga = (svga_t *)p; + svga_t *svga = (svga_t *)p; - if (!svga->fast) - { - svga_write_linear(addr, val, p); - return; - } + if (!svga->fast) { + svga_write(addr, val, p); + svga_write(addr + 1, val >> 8, p); + svga_write(addr + 2, val >> 16, p); + svga_write(addr + 3, val >> 24, p); + return; + } - egawrites++; + cycles -= video_timing_write_l; - if (svga_output) pclog("Write LFBb %08X %04X\n", addr, val); - addr &= svga->decode_mask; - if (addr >= svga->vram_max) - return; - addr &= svga->vram_mask; - svga->changedvram[addr >> 12] = changeframecount; - *(uint8_t *)&svga->vram[addr] = val; + if (!linear) + addr = (addr & svga->banked_mask) + svga->write_bank; + addr &= svga->decode_mask; + if (addr >= svga->vram_max) + return; + addr &= svga->vram_mask; + + svga->changedvram[addr >> 12] = changeframecount; + *(uint32_t *)&svga->vram[addr] = val; } -void svga_writew_linear(uint32_t addr, uint16_t val, void *p) + +void +svga_writel(uint32_t addr, uint32_t val, void *p) { - svga_t *svga = (svga_t *)p; - - if (!svga->fast) - { - svga_write_linear(addr, val & 0xff, p); - svga_write_linear(addr + 1, val >> 8, p); - return; - } - - egawrites += 2; - - cycles -= video_timing_write_w; - cycles_lost += video_timing_write_w; - - if (svga_output) pclog("Write LFBw %08X %04X\n", addr, val); - addr &= svga->decode_mask; - if (addr >= svga->vram_max) - return; - addr &= svga->vram_mask; - svga->changedvram[addr >> 12] = changeframecount; - *(uint16_t *)&svga->vram[addr] = val; + svga_writel_common(addr, val, 0, p); } -void svga_writel_linear(uint32_t addr, uint32_t val, void *p) + +void +svga_writel_linear(uint32_t addr, uint32_t val, void *p) { - svga_t *svga = (svga_t *)p; - - if (!svga->fast) - { - svga_write_linear(addr, val, p); - svga_write_linear(addr + 1, val >> 8, p); - svga_write_linear(addr + 2, val >> 16, p); - svga_write_linear(addr + 3, val >> 24, p); - return; - } - - egawrites += 4; - - cycles -= video_timing_write_l; - cycles_lost += video_timing_write_l; - - if (svga_output) pclog("Write LFBl %08X %08X\n", addr, val); - addr &= svga->decode_mask; - if (addr >= svga->vram_max) - return; - addr &= svga->vram_mask; - svga->changedvram[addr >> 12] = changeframecount; - *(uint32_t *)&svga->vram[addr] = val; + svga_writel_common(addr, val, 1, p); } -uint8_t svga_readb_linear(uint32_t addr, void *p) + +uint8_t +svga_readb_linear(uint32_t addr, void *p) { - svga_t *svga = (svga_t *)p; + svga_t *svga = (svga_t *)p; - if (!svga->fast) - return svga_read_linear(addr, p); + if (!svga->fast) + return svga_read_linear(addr, p); - egareads++; + addr &= svga->decode_mask; + if (addr >= svga->vram_max) + return 0xff; - addr &= svga->decode_mask; - if (addr >= svga->vram_max) - return 0xff; - - return *(uint8_t *)&svga->vram[addr & svga->vram_mask]; + return *(uint8_t *)&svga->vram[addr & svga->vram_mask]; } -uint16_t svga_readw_linear(uint32_t addr, void *p) + +uint16_t +svga_readw_common(uint32_t addr, uint8_t linear, void *p) { - svga_t *svga = (svga_t *)p; + svga_t *svga = (svga_t *)p; - if (!svga->fast) - return svga_read_linear(addr, p) | (svga_read_linear(addr + 1, p) << 8); + if (!svga->fast) + return svga_read_common(addr, linear, p) | (svga_read_common(addr + 1, linear, p) << 8); - egareads += 2; + cycles -= video_timing_read_w; - cycles -= video_timing_read_w; - cycles_lost += video_timing_read_w; + if (!linear) + addr = (addr & svga->banked_mask) + svga->read_bank; + addr &= svga->decode_mask; + if (addr >= svga->vram_max) + return 0xffff; - addr &= svga->decode_mask; - if (addr >= svga->vram_max) - return 0xffff; - - return *(uint16_t *)&svga->vram[addr & svga->vram_mask]; + return *(uint16_t *)&svga->vram[addr & svga->vram_mask]; } -uint32_t svga_readl_linear(uint32_t addr, void *p) + +uint16_t +svga_readw(uint32_t addr, void *p) { - svga_t *svga = (svga_t *)p; - - if (!svga->fast) - return svga_read_linear(addr, p) | (svga_read_linear(addr + 1, p) << 8) | (svga_read_linear(addr + 2, p) << 16) | (svga_read_linear(addr + 3, p) << 24); - - egareads += 4; - - cycles -= video_timing_read_l; - cycles_lost += video_timing_read_l; - - addr &= svga->decode_mask; - if (addr >= svga->vram_max) - return 0xffffffff; - - return *(uint32_t *)&svga->vram[addr & svga->vram_mask]; + return svga_readw_common(addr, 0, p); } -void svga_add_status_info(char *s, int max_len, void *p) +uint16_t +svga_readw_linear(uint32_t addr, void *p) { - svga_t *svga = (svga_t *)p; - char temps[128]; - - if (svga->chain4) strcpy(temps, "SVGA chained (possibly mode 13h)\n"); - else strcpy(temps, "SVGA unchained (possibly mode-X)\n"); - strncat(s, temps, max_len); - - if (!svga->video_bpp) strcpy(temps, "SVGA in text mode\n"); - else sprintf(temps, "SVGA colour depth : %i bpp\n", svga->video_bpp); - strncat(s, temps, max_len); - - sprintf(temps, "SVGA resolution : %i x %i\n", svga->video_res_x, svga->video_res_y); - strncat(s, temps, max_len); - - sprintf(temps, "SVGA refresh rate : %i Hz\n\n", svga->frames); - svga->frames = 0; - strncat(s, temps, max_len); + return svga_readw_common(addr, 1, p); +} + + +uint32_t +svga_readl_common(uint32_t addr, uint8_t linear, void *p) +{ + svga_t *svga = (svga_t *)p; + + if (!svga->fast) { + return svga_read_common(addr, linear, p) | (svga_read_common(addr + 1, linear, p) << 8) | + (svga_read_common(addr + 2, linear, p) << 16) | (svga_read_common(addr + 3, linear, p) << 24); + } + + cycles -= video_timing_read_l; + + if (!linear) + addr = (addr & svga->banked_mask) + svga->read_bank; + addr &= svga->decode_mask; + if (addr >= svga->vram_max) + return 0xffffffff; + + return *(uint32_t *)&svga->vram[addr & svga->vram_mask]; +} + + +uint32_t +svga_readl(uint32_t addr, void *p) +{ + return svga_readl_common(addr, 0, p); +} + + +uint32_t +svga_readl_linear(uint32_t addr, void *p) +{ + return svga_readl_common(addr, 1, p); } diff --git a/src/devices/video/vid_svga.h b/src/devices/video/vid_svga.h index 7de2c96..32fd67e 100644 --- a/src/devices/video/vid_svga.h +++ b/src/devices/video/vid_svga.h @@ -8,7 +8,7 @@ * * Definitions for the generic SVGA driver. * - * Version: @(#)vid_svga.h 1.0.4 2018/03/26 + * Version: @(#)vid_svga.h 1.0.6 2018/10/05 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -40,230 +40,140 @@ # define VIDEO_SVGA_H +typedef struct { + int ena, + x, y, xoff, yoff, xsize, ysize, + v_acc, h_acc; + + uint32_t addr, pitch; +} hwcursor_t; + + typedef struct svga_t { - mem_mapping_t mapping; + mem_map_t mapping; - int enabled; + int enabled, fast, vidclock, fb_only, + dac_addr, dac_pos, dac_r, dac_g, + ramdac_type, ext_overscan, + readmode, writemode, readplane, extvram, + chain4, chain2_write, chain2_read, + oddeven_page, oddeven_chain, + set_reset_disabled, + vtotal, dispend, vsyncstart, split, vblankstart, + hdisp, hdisp_old, htotal, hdisp_time, rowoffset, + lowres, interlace, linedbl, rowcount, bpp, + dispon, hdisp_on, + vc, sc, linepos, vslines, linecountff, oddeven, + con, cursoron, blink, scrollcache, + firstline, lastline, firstline_draw, lastline_draw, + displine, fullchange, + video_res_x, video_res_y, video_bpp, frames, fps, + vram_display_mask, + hwcursor_on, overlay_on, + hwcursor_oddeven, overlay_oddeven; - uint8_t crtcreg; - uint8_t crtc[128]; - uint8_t gdcreg[64]; - int gdcaddr; - uint8_t attrregs[32]; - int attraddr, attrff; - int attr_palette_enable; - uint8_t seqregs[64]; - int seqaddr; + /*The three variables below allow us to implement memory maps like that seen on a 1MB Trio64 : + 0MB-1MB - VRAM + 1MB-2MB - VRAM mirror + 2MB-4MB - open bus + 4MB-xMB - mirror of above + For the example memory map, decode_mask would be 4MB-1 (4MB address space), vram_max would be 2MB + (present video memory only responds to first 2MB), vram_mask would be 1MB-1 (video memory wraps at 1MB) + */ + uint32_t decode_mask, vram_max, + vram_mask, + charseta, charsetb, + latch, ma_latch, + ma, maback, + write_bank, read_bank, + banked_mask, + ca, overscan_color, + pallook[256]; - uint8_t miscout; - int vidclock; + PALETTE vgapal; - /*The three variables below allow us to implement memory maps like that seen on a 1MB Trio64 : - 0MB-1MB - VRAM - 1MB-2MB - VRAM mirror - 2MB-4MB - open bus - 4MB-xMB - mirror of above + int64_t dispontime, dispofftime, + vidtime; - For the example memory map, decode_mask would be 4MB-1 (4MB address space), vram_max would be 2MB - (present video memory only responds to first 2MB), vram_mask would be 1MB-1 (video memory wraps at 1MB) - */ - uint32_t decode_mask; - uint32_t vram_max; - uint32_t vram_mask; + double clock; - uint8_t la, lb, lc, ld; + hwcursor_t hwcursor, hwcursor_latch, + overlay, overlay_latch; - uint8_t dac_mask, dac_status; - int dac_read, dac_write, dac_pos; - int dac_r, dac_g; + void (*render)(struct svga_t *svga); + void (*recalctimings_ex)(struct svga_t *svga); + void (*video_out)(uint16_t addr, uint8_t val, void *p); + uint8_t (*video_in) (uint16_t addr, void *p); + void (*hwcursor_draw)(struct svga_t *svga, int displine); + void (*overlay_draw)(struct svga_t *svga, int displine); + void (*vblank_start)(struct svga_t *svga); + void (*ven_write)(struct svga_t *svga, uint8_t val, uint32_t addr); + float (*getclock)(int clock, void *p); - uint8_t cgastat; + /*If set then another device is driving the monitor output and the SVGA + card should not attempt to display anything */ + int override; + void *p; - uint8_t plane_mask; + uint8_t crtc[128], gdcreg[64], attrregs[32], seqregs[64], + egapal[16], + *vram, *changedvram; + uint8_t crtcreg, gdcaddr, + attrff, attr_palette_enable, attraddr, seqaddr, + miscout, cgastat, scrblank, + plane_mask, writemask, + colourcompare, colournocare, + dac_mask, dac_status, + ksc5601_sbyte_mask; - int fb_only; - - int fast; - uint8_t colourcompare, colournocare; - int readmode, writemode, readplane; - int chain4, chain2_write, chain2_read; - int oddeven_page, oddeven_chain; - int extvram; - uint8_t writemask; - uint32_t charseta, charsetb; - - int set_reset_disabled; - - uint8_t egapal[16]; - uint32_t pallook[256]; - PALETTE vgapal; - - int ramdac_type; - - int vtotal, dispend, vsyncstart, split, vblankstart; - int hdisp, hdisp_old, htotal, hdisp_time, rowoffset; - int lowres, interlace; - int linedbl, rowcount; - double clock; - uint32_t ma_latch; - int bpp; - - int64_t dispontime, dispofftime; - int64_t vidtime; - - uint8_t scrblank; - - int dispon; - int hdisp_on; - - uint32_t ma, maback, ca; - int vc; - int sc; - int linepos, vslines, linecountff, oddeven; - int con, cursoron, blink; - int scrollcache; - - int firstline, lastline; - int firstline_draw, lastline_draw; - int displine; - - uint8_t *vram; - uint8_t *changedvram; - int vram_display_mask; - uint32_t banked_mask; - - uint32_t write_bank, read_bank; - - int fullchange; - - int video_res_x, video_res_y, video_bpp; - int frames, fps; - - struct - { - int ena; - int x, y; - int xoff, yoff; - int xsize, ysize; - uint32_t addr; - uint32_t pitch; - int v_acc, h_acc; - } hwcursor, hwcursor_latch, overlay, overlay_latch; - - int hwcursor_on; - int overlay_on; - - int hwcursor_oddeven; - int overlay_oddeven; - - /*If set then another device is driving the monitor output and the SVGA - card should not attempt to display anything */ - int override; - void *p; - - uint32_t linear_base; - uint32_t overscan_color; - - void (*render)(struct svga_t *svga); - void (*recalctimings_ex)(struct svga_t *svga); - - void (*video_out)(uint16_t addr, uint8_t val, void *p); - uint8_t (*video_in) (uint16_t addr, void *p); - - void (*hwcursor_draw)(struct svga_t *svga, int displine); - - void (*overlay_draw)(struct svga_t *svga, int displine); - - void (*vblank_start)(struct svga_t *svga); + void *ramdac, *clock_gen; } svga_t; -extern int svga_init(svga_t *svga, void *p, int memsize, - void (*recalctimings_ex)(struct svga_t *svga), - uint8_t (*video_in) (uint16_t addr, void *p), - void (*video_out)(uint16_t addr, uint8_t val, void *p), - void (*hwcursor_draw)(struct svga_t *svga, int displine), - void (*overlay_draw)(struct svga_t *svga, int displine)); -extern void svga_recalctimings(svga_t *svga); -extern void svga_close(svga_t *svga); +extern int svga_init(svga_t *svga, void *p, int memsize, + void (*recalctimings_ex)(struct svga_t *svga), + uint8_t (*video_in) (uint16_t addr, void *p), + void (*video_out)(uint16_t addr, uint8_t val, void *p), + void (*hwcursor_draw)(struct svga_t *svga, int displine), + void (*overlay_draw)(struct svga_t *svga, int displine)); +extern void svga_recalctimings(svga_t *svga); +extern void svga_close(svga_t *svga); +uint8_t svga_read(uint32_t addr, void *p); +uint16_t svga_readw(uint32_t addr, void *p); +uint32_t svga_readl(uint32_t addr, void *p); +void svga_write(uint32_t addr, uint8_t val, void *p); +void svga_writew(uint32_t addr, uint16_t val, void *p); +void svga_writel(uint32_t addr, uint32_t val, void *p); +uint8_t svga_read_linear(uint32_t addr, void *p); +uint8_t svga_readb_linear(uint32_t addr, void *p); +uint16_t svga_readw_linear(uint32_t addr, void *p); +uint32_t svga_readl_linear(uint32_t addr, void *p); +void svga_write_linear(uint32_t addr, uint8_t val, void *p); +void svga_writeb_linear(uint32_t addr, uint8_t val, void *p); +void svga_writew_linear(uint32_t addr, uint16_t val, void *p); +void svga_writel_linear(uint32_t addr, uint32_t val, void *p); -uint8_t svga_read(uint32_t addr, void *p); -uint16_t svga_readw(uint32_t addr, void *p); -uint32_t svga_readl(uint32_t addr, void *p); -void svga_write(uint32_t addr, uint8_t val, void *p); -void svga_writew(uint32_t addr, uint16_t val, void *p); -void svga_writel(uint32_t addr, uint32_t val, void *p); -uint8_t svga_read_linear(uint32_t addr, void *p); -uint8_t svga_readb_linear(uint32_t addr, void *p); -uint16_t svga_readw_linear(uint32_t addr, void *p); -uint32_t svga_readl_linear(uint32_t addr, void *p); -void svga_write_linear(uint32_t addr, uint8_t val, void *p); -void svga_writeb_linear(uint32_t addr, uint8_t val, void *p); -void svga_writew_linear(uint32_t addr, uint16_t val, void *p); -void svga_writel_linear(uint32_t addr, uint32_t val, void *p); +extern uint8_t svga_rotate[8][256]; -void svga_add_status_info(char *s, int max_len, void *p); +extern void svga_out(uint16_t addr, uint8_t val, void *p); +extern uint8_t svga_in(uint16_t addr, void *p); -extern uint8_t svga_rotate[8][256]; +extern svga_t *svga_get_pri(void); +extern void svga_set_override(svga_t *svga, int val); -void svga_out(uint16_t addr, uint8_t val, void *p); -uint8_t svga_in(uint16_t addr, void *p); +extern void svga_set_ramdac_type(svga_t *svga, int type); +extern void svga_close(svga_t *svga); -svga_t *svga_get_pri(); -void svga_set_override(svga_t *svga, int val); +extern uint32_t svga_mask_addr(uint32_t addr, svga_t *svga); +extern uint32_t svga_mask_changedaddr(uint32_t addr, svga_t *svga); -#define RAMDAC_6BIT 0 -#define RAMDAC_8BIT 1 -void svga_set_ramdac_type(svga_t *svga, int type); +extern void svga_doblit(int y1, int y2, int wx, int wy, svga_t *svga); -void svga_close(svga_t *svga); - -uint32_t svga_mask_addr(uint32_t addr, svga_t *svga); -uint32_t svga_mask_changedaddr(uint32_t addr, svga_t *svga); - -extern uint32_t shade[5][256]; - -static __inline uint32_t svga_color_transform(uint32_t color) -{ - uint8_t *clr8 = (uint8_t *) &color; - if (!vid_grayscale && !invert_display) - return color; - if (vid_grayscale) - { - if (vid_graytype) - { - if (vid_graytype == 1) - color = ((54 * (uint32_t)clr8[2]) + (183 * (uint32_t)clr8[1]) + (18 * (uint32_t)clr8[0])) / 255; - else - color = ((uint32_t)clr8[2] + (uint32_t)clr8[1] + (uint32_t)clr8[0]) / 3; - } - else - color = ((76 * (uint32_t)clr8[2]) + (150 * (uint32_t)clr8[1]) + (29 * (uint32_t)clr8[0])) / 255; - switch (vid_grayscale) - { - case 2: - case 3: - case 4: - color = shade[vid_grayscale][color]; - break; - default: - clr8[3] = 0; - clr8[0] = color; - clr8[1] = clr8[2] = clr8[0]; - break; - } - } - if (invert_display) - { - clr8[0] ^= 0xff; - clr8[1] ^= 0xff; - clr8[2] ^= 0xff; - } - return color; -} - -void svga_doblit(int y1, int y2, int wx, int wy, svga_t *svga); +enum { + RAMDAC_6BIT = 0, + RAMDAC_8BIT +}; #endif /*VIDEO_SVGA_H*/ diff --git a/src/devices/video/vid_svga_render.c b/src/devices/video/vid_svga_render.c index b4bb7e5..75eedd1 100644 --- a/src/devices/video/vid_svga_render.c +++ b/src/devices/video/vid_svga_render.c @@ -8,7 +8,7 @@ * * SVGA renderers. * - * Version: @(#)vid_svga_render.c 1.0.10 2018/05/06 + * Version: @(#)vid_svga_render.c 1.0.11 2018/09/19 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -47,66 +47,6 @@ #include "vid_svga_render.h" -uint32_t shade[5][256] = -{ - {0}, // RGB Color (unused) - {0}, // RGB Grayscale (unused) - { // Amber monitor - 0x000000, 0x060000, 0x090000, 0x0d0000, 0x100000, 0x120100, 0x150100, 0x170100, 0x1a0100, 0x1c0100, 0x1e0200, 0x210200, 0x230200, 0x250300, 0x270300, 0x290300, - 0x2b0400, 0x2d0400, 0x2f0400, 0x300500, 0x320500, 0x340500, 0x360600, 0x380600, 0x390700, 0x3b0700, 0x3d0700, 0x3f0800, 0x400800, 0x420900, 0x440900, 0x450a00, - 0x470a00, 0x480b00, 0x4a0b00, 0x4c0c00, 0x4d0c00, 0x4f0d00, 0x500d00, 0x520e00, 0x530e00, 0x550f00, 0x560f00, 0x581000, 0x591000, 0x5b1100, 0x5c1200, 0x5e1200, - 0x5f1300, 0x601300, 0x621400, 0x631500, 0x651500, 0x661600, 0x671600, 0x691700, 0x6a1800, 0x6c1800, 0x6d1900, 0x6e1a00, 0x701a00, 0x711b00, 0x721c00, 0x741c00, - 0x751d00, 0x761e00, 0x781e00, 0x791f00, 0x7a2000, 0x7c2000, 0x7d2100, 0x7e2200, 0x7f2300, 0x812300, 0x822400, 0x832500, 0x842600, 0x862600, 0x872700, 0x882800, - 0x8a2900, 0x8b2900, 0x8c2a00, 0x8d2b00, 0x8e2c00, 0x902c00, 0x912d00, 0x922e00, 0x932f00, 0x953000, 0x963000, 0x973100, 0x983200, 0x993300, 0x9b3400, 0x9c3400, - 0x9d3500, 0x9e3600, 0x9f3700, 0xa03800, 0xa23900, 0xa33a00, 0xa43a00, 0xa53b00, 0xa63c00, 0xa73d00, 0xa93e00, 0xaa3f00, 0xab4000, 0xac4000, 0xad4100, 0xae4200, - 0xaf4300, 0xb14400, 0xb24500, 0xb34600, 0xb44700, 0xb54800, 0xb64900, 0xb74a00, 0xb94a00, 0xba4b00, 0xbb4c00, 0xbc4d00, 0xbd4e00, 0xbe4f00, 0xbf5000, 0xc05100, - 0xc15200, 0xc25300, 0xc45400, 0xc55500, 0xc65600, 0xc75700, 0xc85800, 0xc95900, 0xca5a00, 0xcb5b00, 0xcc5c00, 0xcd5d00, 0xce5e00, 0xcf5f00, 0xd06000, 0xd26101, - 0xd36201, 0xd46301, 0xd56401, 0xd66501, 0xd76601, 0xd86701, 0xd96801, 0xda6901, 0xdb6a01, 0xdc6b01, 0xdd6c01, 0xde6d01, 0xdf6e01, 0xe06f01, 0xe17001, 0xe27201, - 0xe37301, 0xe47401, 0xe57501, 0xe67602, 0xe77702, 0xe87802, 0xe97902, 0xeb7a02, 0xec7b02, 0xed7c02, 0xee7e02, 0xef7f02, 0xf08002, 0xf18103, 0xf28203, 0xf38303, - 0xf48403, 0xf58503, 0xf68703, 0xf78803, 0xf88903, 0xf98a04, 0xfa8b04, 0xfb8c04, 0xfc8d04, 0xfd8f04, 0xfe9005, 0xff9105, 0xff9205, 0xff9305, 0xff9405, 0xff9606, - 0xff9706, 0xff9806, 0xff9906, 0xff9a07, 0xff9b07, 0xff9d07, 0xff9e08, 0xff9f08, 0xffa008, 0xffa109, 0xffa309, 0xffa409, 0xffa50a, 0xffa60a, 0xffa80a, 0xffa90b, - 0xffaa0b, 0xffab0c, 0xffac0c, 0xffae0d, 0xffaf0d, 0xffb00e, 0xffb10e, 0xffb30f, 0xffb40f, 0xffb510, 0xffb610, 0xffb811, 0xffb912, 0xffba12, 0xffbb13, 0xffbd14, - 0xffbe14, 0xffbf15, 0xffc016, 0xffc217, 0xffc317, 0xffc418, 0xffc619, 0xffc71a, 0xffc81b, 0xffca1c, 0xffcb1d, 0xffcc1e, 0xffcd1f, 0xffcf20, 0xffd021, 0xffd122, - 0xffd323, 0xffd424, 0xffd526, 0xffd727, 0xffd828, 0xffd92a, 0xffdb2b, 0xffdc2c, 0xffdd2e, 0xffdf2f, 0xffe031, 0xffe133, 0xffe334, 0xffe436, 0xffe538, 0xffe739 - }, - { // Green monitor - 0x000000, 0x000400, 0x000700, 0x000900, 0x000b00, 0x000d00, 0x000f00, 0x001100, 0x001300, 0x001500, 0x001600, 0x001800, 0x001a00, 0x001b00, 0x001d00, 0x001e00, - 0x002000, 0x002100, 0x002300, 0x002400, 0x002601, 0x002701, 0x002901, 0x002a01, 0x002b01, 0x002d01, 0x002e01, 0x002f01, 0x003101, 0x003201, 0x003301, 0x003401, - 0x003601, 0x003702, 0x003802, 0x003902, 0x003b02, 0x003c02, 0x003d02, 0x003e02, 0x004002, 0x004102, 0x004203, 0x004303, 0x004403, 0x004503, 0x004703, 0x004803, - 0x004903, 0x004a03, 0x004b04, 0x004c04, 0x004d04, 0x004e04, 0x005004, 0x005104, 0x005205, 0x005305, 0x005405, 0x005505, 0x005605, 0x005705, 0x005806, 0x005906, - 0x005a06, 0x005b06, 0x005d06, 0x005e07, 0x005f07, 0x006007, 0x006107, 0x006207, 0x006308, 0x006408, 0x006508, 0x006608, 0x006708, 0x006809, 0x006909, 0x006a09, - 0x006b09, 0x016c0a, 0x016d0a, 0x016e0a, 0x016f0a, 0x01700b, 0x01710b, 0x01720b, 0x01730b, 0x01740c, 0x01750c, 0x01760c, 0x01770c, 0x01780d, 0x01790d, 0x017a0d, - 0x017b0d, 0x017b0e, 0x017c0e, 0x017d0e, 0x017e0f, 0x017f0f, 0x01800f, 0x018110, 0x028210, 0x028310, 0x028410, 0x028511, 0x028611, 0x028711, 0x028812, 0x028912, - 0x028a12, 0x028a13, 0x028b13, 0x028c13, 0x028d14, 0x028e14, 0x038f14, 0x039015, 0x039115, 0x039215, 0x039316, 0x039416, 0x039417, 0x039517, 0x039617, 0x039718, - 0x049818, 0x049918, 0x049a19, 0x049b19, 0x049c19, 0x049c1a, 0x049d1a, 0x049e1b, 0x059f1b, 0x05a01b, 0x05a11c, 0x05a21c, 0x05a31c, 0x05a31d, 0x05a41d, 0x06a51e, - 0x06a61e, 0x06a71f, 0x06a81f, 0x06a920, 0x06aa20, 0x07aa21, 0x07ab21, 0x07ac21, 0x07ad22, 0x07ae22, 0x08af23, 0x08b023, 0x08b024, 0x08b124, 0x08b225, 0x09b325, - 0x09b426, 0x09b526, 0x09b527, 0x0ab627, 0x0ab728, 0x0ab828, 0x0ab929, 0x0bba29, 0x0bba2a, 0x0bbb2a, 0x0bbc2b, 0x0cbd2b, 0x0cbe2c, 0x0cbf2c, 0x0dbf2d, 0x0dc02d, - 0x0dc12e, 0x0ec22e, 0x0ec32f, 0x0ec42f, 0x0fc430, 0x0fc530, 0x0fc631, 0x10c731, 0x10c832, 0x10c932, 0x11c933, 0x11ca33, 0x11cb34, 0x12cc35, 0x12cd35, 0x12cd36, - 0x13ce36, 0x13cf37, 0x13d037, 0x14d138, 0x14d139, 0x14d239, 0x15d33a, 0x15d43a, 0x16d43b, 0x16d53b, 0x17d63c, 0x17d73d, 0x17d83d, 0x18d83e, 0x18d93e, 0x19da3f, - 0x19db40, 0x1adc40, 0x1adc41, 0x1bdd41, 0x1bde42, 0x1cdf43, 0x1ce043, 0x1de044, 0x1ee145, 0x1ee245, 0x1fe346, 0x1fe446, 0x20e447, 0x20e548, 0x21e648, 0x22e749, - 0x22e74a, 0x23e84a, 0x23e94b, 0x24ea4c, 0x25ea4c, 0x25eb4d, 0x26ec4e, 0x27ed4e, 0x27ee4f, 0x28ee50, 0x29ef50, 0x29f051, 0x2af152, 0x2bf153, 0x2cf253, 0x2cf354, - 0x2df455, 0x2ef455, 0x2ff556, 0x2ff657, 0x30f758, 0x31f758, 0x32f859, 0x32f95a, 0x33fa5a, 0x34fa5b, 0x35fb5c, 0x36fc5d, 0x37fd5d, 0x38fd5e, 0x38fe5f, 0x39ff60 - }, - { // White monitor - 0x000000, 0x010102, 0x020203, 0x020304, 0x030406, 0x040507, 0x050608, 0x060709, 0x07080a, 0x08090c, 0x080a0d, 0x090b0e, 0x0a0c0f, 0x0b0d10, 0x0c0e11, 0x0d0f12, - 0x0e1013, 0x0f1115, 0x101216, 0x111317, 0x121418, 0x121519, 0x13161a, 0x14171b, 0x15181c, 0x16191d, 0x171a1e, 0x181b1f, 0x191c20, 0x1a1d21, 0x1b1e22, 0x1c1f23, - 0x1d2024, 0x1e2125, 0x1f2226, 0x202327, 0x212428, 0x222529, 0x22262b, 0x23272c, 0x24282d, 0x25292e, 0x262a2f, 0x272b30, 0x282c30, 0x292d31, 0x2a2e32, 0x2b2f33, - 0x2c3034, 0x2d3035, 0x2e3136, 0x2f3237, 0x303338, 0x313439, 0x32353a, 0x33363b, 0x34373c, 0x35383d, 0x36393e, 0x373a3f, 0x383b40, 0x393c41, 0x3a3d42, 0x3b3e43, - 0x3c3f44, 0x3d4045, 0x3e4146, 0x3f4247, 0x404348, 0x414449, 0x42454a, 0x43464b, 0x44474c, 0x45484d, 0x46494d, 0x474a4e, 0x484b4f, 0x484c50, 0x494d51, 0x4a4e52, - 0x4b4f53, 0x4c5054, 0x4d5155, 0x4e5256, 0x4f5357, 0x505458, 0x515559, 0x52565a, 0x53575b, 0x54585b, 0x55595c, 0x565a5d, 0x575b5e, 0x585c5f, 0x595d60, 0x5a5e61, - 0x5b5f62, 0x5c6063, 0x5d6164, 0x5e6265, 0x5f6366, 0x606466, 0x616567, 0x626668, 0x636769, 0x64686a, 0x65696b, 0x666a6c, 0x676b6d, 0x686c6e, 0x696d6f, 0x6a6e70, - 0x6b6f70, 0x6c7071, 0x6d7172, 0x6f7273, 0x707374, 0x707475, 0x717576, 0x727677, 0x747778, 0x757879, 0x767979, 0x777a7a, 0x787b7b, 0x797c7c, 0x7a7d7d, 0x7b7e7e, - 0x7c7f7f, 0x7d8080, 0x7e8181, 0x7f8281, 0x808382, 0x818483, 0x828584, 0x838685, 0x848786, 0x858887, 0x868988, 0x878a89, 0x888b89, 0x898c8a, 0x8a8d8b, 0x8b8e8c, - 0x8c8f8d, 0x8d8f8e, 0x8e908f, 0x8f9190, 0x909290, 0x919391, 0x929492, 0x939593, 0x949694, 0x959795, 0x969896, 0x979997, 0x989a98, 0x999b98, 0x9a9c99, 0x9b9d9a, - 0x9c9e9b, 0x9d9f9c, 0x9ea09d, 0x9fa19e, 0xa0a29f, 0xa1a39f, 0xa2a4a0, 0xa3a5a1, 0xa4a6a2, 0xa6a7a3, 0xa7a8a4, 0xa8a9a5, 0xa9aaa5, 0xaaaba6, 0xabaca7, 0xacada8, - 0xadaea9, 0xaeafaa, 0xafb0ab, 0xb0b1ac, 0xb1b2ac, 0xb2b3ad, 0xb3b4ae, 0xb4b5af, 0xb5b6b0, 0xb6b7b1, 0xb7b8b2, 0xb8b9b2, 0xb9bab3, 0xbabbb4, 0xbbbcb5, 0xbcbdb6, - 0xbdbeb7, 0xbebfb8, 0xbfc0b8, 0xc0c1b9, 0xc1c2ba, 0xc2c3bb, 0xc3c4bc, 0xc5c5bd, 0xc6c6be, 0xc7c7be, 0xc8c8bf, 0xc9c9c0, 0xcacac1, 0xcbcbc2, 0xccccc3, 0xcdcdc3, - 0xcecec4, 0xcfcfc5, 0xd0d0c6, 0xd1d1c7, 0xd2d2c8, 0xd3d3c9, 0xd4d4c9, 0xd5d5ca, 0xd6d6cb, 0xd7d7cc, 0xd8d8cd, 0xd9d9ce, 0xdadacf, 0xdbdbcf, 0xdcdcd0, 0xdeddd1, - 0xdfded2, 0xe0dfd3, 0xe1e0d4, 0xe2e1d4, 0xe3e2d5, 0xe4e3d6, 0xe5e4d7, 0xe6e5d8, 0xe7e6d9, 0xe8e7d9, 0xe9e8da, 0xeae9db, 0xebeadc, 0xecebdd, 0xedecde, 0xeeeddf, - 0xefeedf, 0xf0efe0, 0xf1f0e1, 0xf2f1e2, 0xf3f2e3, 0xf4f3e3, 0xf6f3e4, 0xf7f4e5, 0xf8f5e6, 0xf9f6e7, 0xfaf7e8, 0xfbf8e9, 0xfcf9e9, 0xfdfaea, 0xfefbeb, 0xfffcec - } -}; - void svga_render_blank(svga_t *svga) { int x, xx; @@ -122,16 +62,16 @@ void svga_render_blank(svga_t *svga) switch (svga->seqregs[1] & 9) { case 0: - for (xx = 0; xx < 9; xx++) ((uint32_t *)buffer32->line[svga->displine + y_add])[(x * 9) + xx + 32 + x_add] = svga_color_transform(0); + for (xx = 0; xx < 9; xx++) ((uint32_t *)buffer32->line[svga->displine + y_add])[(x * 9) + xx + 32 + x_add] = 0; break; case 1: - for (xx = 0; xx < 8; xx++) ((uint32_t *)buffer32->line[svga->displine + y_add])[(x * 8) + xx + 32 + x_add] = svga_color_transform(0); + for (xx = 0; xx < 8; xx++) ((uint32_t *)buffer32->line[svga->displine + y_add])[(x * 8) + xx + 32 + x_add] = 0; break; case 8: - for (xx = 0; xx < 18; xx++) ((uint32_t *)buffer32->line[svga->displine + y_add])[(x * 18) + xx + 32 + x_add] = svga_color_transform(0); + for (xx = 0; xx < 18; xx++) ((uint32_t *)buffer32->line[svga->displine + y_add])[(x * 18) + xx + 32 + x_add] = 0; break; case 9: - for (xx = 0; xx < 16; xx++) ((uint32_t *)buffer32->line[svga->displine + y_add])[(x * 16) + xx + 32 + x_add] = svga_color_transform(0); + for (xx = 0; xx < 16; xx++) ((uint32_t *)buffer32->line[svga->displine + y_add])[(x * 16) + xx + 32 + x_add] = 0; break; } } @@ -181,9 +121,6 @@ void svga_render_text_40(svga_t *svga) } } - fg = svga_color_transform(fg); - bg = svga_color_transform(bg); - dat = svga->vram[charaddr + (svga->sc << 2)]; if (svga->seqregs[1] & 1) { @@ -231,77 +168,10 @@ void svga_render_text_80(svga_t *svga) chr = svga->vram[(svga->ma << 1) & svga->vram_display_mask]; attr = svga->vram[((svga->ma << 1) + 1) & svga->vram_display_mask]; + if (attr & 8) charaddr = svga->charsetb + (chr * 128); else charaddr = svga->charseta + (chr * 128); - if (drawcursor) - { - bg = svga->pallook[svga->egapal[attr & 15]]; - fg = svga->pallook[svga->egapal[attr >> 4]]; - } - else - { - fg = svga->pallook[svga->egapal[attr & 15]]; - bg = svga->pallook[svga->egapal[attr >> 4]]; - if (attr & 0x80 && svga->attrregs[0x10] & 8) - { - bg = svga->pallook[svga->egapal[(attr >> 4) & 7]]; - if (svga->blink & 16) - fg = bg; - } - } - - fg = svga_color_transform(fg); - bg = svga_color_transform(bg); - - dat = svga->vram[charaddr + (svga->sc << 2)]; - if (svga->seqregs[1] & 1) - { - for (xx = 0; xx < 8; xx++) - p[xx] = (dat & (0x80 >> xx)) ? fg : bg; - } - else - { - for (xx = 0; xx < 8; xx++) - p[xx] = (dat & (0x80 >> xx)) ? fg : bg; - if ((chr & ~0x1F) != 0xC0 || !(svga->attrregs[0x10] & 4)) - p[8] = bg; - else - p[8] = (dat & 1) ? fg : bg; - } - svga->ma += 4; - p += xinc; - } - svga->ma &= svga->vram_display_mask; - } -} - -void svga_render_text_80_ksc5601(svga_t *svga) -{ - int y_add = enable_overscan ? (overscan_y >> 1) : 0; - int x_add = enable_overscan ? 8 : 0; - - if (svga->firstline_draw == 2000) - svga->firstline_draw = svga->displine; - svga->lastline_draw = svga->displine; - - if (svga->fullchange) - { - uint32_t *p = &((uint32_t *)buffer32->line[svga->displine + y_add])[32 + x_add]; - int x, xx; - int drawcursor; - uint8_t chr, attr, dat, nextchr; - uint32_t charaddr = 0; - int fg, bg; - int xinc = (svga->seqregs[1] & 1) ? 8 : 9; - - for (x = 0; x < svga->hdisp; x += xinc) - { - drawcursor = ((svga->ma == svga->ca) && svga->con && svga->cursoron); - chr = svga->vram[(svga->ma << 1) & svga->vram_display_mask]; - nextchr = svga->vram[((svga->ma + 4) << 1) & svga->vram_display_mask]; - attr = svga->vram[((svga->ma << 1) + 1) & svga->vram_display_mask]; - if (drawcursor) { bg = svga->pallook[svga->egapal[attr & 15]]; @@ -319,16 +189,80 @@ void svga_render_text_80_ksc5601(svga_t *svga) } } - fg = svga_color_transform(fg); - bg = svga_color_transform(bg); - dat = svga->vram[charaddr + (svga->sc << 2)]; - if(x + xinc < svga->hdisp && (chr & nextchr & 0x80)) + if (svga->seqregs[1] & 1) + { + for (xx = 0; xx < 8; xx++) + p[xx] = (dat & (0x80 >> xx)) ? fg : bg; + } + else + { + for (xx = 0; xx < 8; xx++) + p[xx] = (dat & (0x80 >> xx)) ? fg : bg; + if ((chr & ~0x1F) != 0xC0 || !(svga->attrregs[0x10] & 4)) + p[8] = bg; + else + p[8] = (dat & 1) ? fg : bg; + } + svga->ma += 4; + p += xinc; + } + svga->ma &= svga->vram_display_mask; + } +} + +void svga_render_text_80_ksc5601(svga_t *svga) +{ + int y_add = enable_overscan ? (overscan_y >> 1) : 0; + int x_add = enable_overscan ? 8 : 0; + + if (svga->firstline_draw == 2000) + svga->firstline_draw = svga->displine; + svga->lastline_draw = svga->displine; + + if (svga->fullchange) + { + uint32_t *p = &((uint32_t *)buffer32->line[svga->displine + y_add])[32 + x_add]; + int x, xx; + int drawcursor; + uint8_t chr, attr, dat, nextchr; + uint32_t charaddr; + int fg, bg; + int xinc = (svga->seqregs[1] & 1) ? 8 : 9; + + for (x = 0; x < svga->hdisp; x += xinc) + { + drawcursor = ((svga->ma == svga->ca) && svga->con && svga->cursoron); + chr = svga->vram[(svga->ma << 1) & svga->vram_display_mask]; + nextchr = svga->vram[((svga->ma + 4) << 1) & svga->vram_display_mask]; + attr = svga->vram[((svga->ma << 1) + 1) & svga->vram_display_mask]; + + + if (drawcursor) + { + bg = svga->pallook[svga->egapal[attr & 15]]; + fg = svga->pallook[svga->egapal[attr >> 4]]; + } + else + { + fg = svga->pallook[svga->egapal[attr & 15]]; + bg = svga->pallook[svga->egapal[attr >> 4]]; + if (attr & 0x80 && svga->attrregs[0x10] & 8) + { + bg = svga->pallook[svga->egapal[(attr >> 4) & 7]]; + if (svga->blink & 16) + fg = bg; + } + } + + if(x + xinc < svga->hdisp && (chr & (nextchr | svga->ksc5601_sbyte_mask) & 0x80)) { if((chr == 0xc9 || chr == 0xfe) && (nextchr > 0xa0 && nextchr < 0xff)) dat = fontdatksc5601_user[(chr == 0xfe ? 96 : 0) + (nextchr & 0x7F) - 0x20].chr[svga->sc]; - else + else if(nextchr & 0x80) dat = fontdatksc5601[((chr & 0x7F) << 7) | (nextchr & 0x7F)].chr[svga->sc]; + else + dat = 0xff; } else { @@ -354,7 +288,7 @@ void svga_render_text_80_ksc5601(svga_t *svga) svga->ma += 4; p += xinc; - if(x + xinc < svga->hdisp && (chr & nextchr & 0x80)) + if(x + xinc < svga->hdisp && (chr & (nextchr | svga->ksc5601_sbyte_mask) & 0x80)) { attr = svga->vram[((svga->ma << 1) + 1) & svga->vram_display_mask]; @@ -377,8 +311,10 @@ void svga_render_text_80_ksc5601(svga_t *svga) if((chr == 0xc9 || chr == 0xfe) && (nextchr > 0xa0 && nextchr < 0xff)) dat = fontdatksc5601_user[(chr == 0xfe ? 96 : 0) + (nextchr & 0x7F) - 0x20].chr[svga->sc + 16]; - else + else if(nextchr & 0x80) dat = fontdatksc5601[((chr & 0x7F) << 7) | (nextchr & 0x7F)].chr[svga->sc + 16]; + else + dat = 0xff; if (svga->seqregs[1] & 1) { for (xx = 0; xx < 8; xx++) @@ -431,14 +367,14 @@ void svga_render_2bpp_lowres(svga_t *svga) svga->ma += 4; svga->ma &= svga->vram_display_mask; - p[0] = p[1] = svga_color_transform(svga->pallook[svga->egapal[(dat[0] >> 6) & 3]]); - p[2] = p[3] = svga_color_transform(svga->pallook[svga->egapal[(dat[0] >> 4) & 3]]); - p[4] = p[5] = svga_color_transform(svga->pallook[svga->egapal[(dat[0] >> 2) & 3]]); - p[6] = p[7] = svga_color_transform(svga->pallook[svga->egapal[dat[0] & 3]]); - p[8] = p[9] = svga_color_transform(svga->pallook[svga->egapal[(dat[1] >> 6) & 3]]); - p[10] = p[11] = svga_color_transform(svga->pallook[svga->egapal[(dat[1] >> 4) & 3]]); - p[12] = p[13] = svga_color_transform(svga->pallook[svga->egapal[(dat[1] >> 2) & 3]]); - p[14] = p[15] = svga_color_transform(svga->pallook[svga->egapal[dat[1] & 3]]); + p[0] = p[1] = svga->pallook[svga->egapal[(dat[0] >> 6) & 3]]; + p[2] = p[3] = svga->pallook[svga->egapal[(dat[0] >> 4) & 3]]; + p[4] = p[5] = svga->pallook[svga->egapal[(dat[0] >> 2) & 3]]; + p[6] = p[7] = svga->pallook[svga->egapal[dat[0] & 3]]; + p[8] = p[9] = svga->pallook[svga->egapal[(dat[1] >> 6) & 3]]; + p[10] = p[11] = svga->pallook[svga->egapal[(dat[1] >> 4) & 3]]; + p[12] = p[13] = svga->pallook[svga->egapal[(dat[1] >> 2) & 3]]; + p[14] = p[15] = svga->pallook[svga->egapal[dat[1] & 3]]; p += 16; } @@ -473,14 +409,14 @@ void svga_render_2bpp_highres(svga_t *svga) svga->ma += 4; svga->ma &= svga->vram_display_mask; - p[0] = svga_color_transform(svga->pallook[svga->egapal[(dat[0] >> 6) & 3]]); - p[1] = svga_color_transform(svga->pallook[svga->egapal[(dat[0] >> 4) & 3]]); - p[2] = svga_color_transform(svga->pallook[svga->egapal[(dat[0] >> 2) & 3]]); - p[3] = svga_color_transform(svga->pallook[svga->egapal[dat[0] & 3]]); - p[4] = svga_color_transform(svga->pallook[svga->egapal[(dat[1] >> 6) & 3]]); - p[5] = svga_color_transform(svga->pallook[svga->egapal[(dat[1] >> 4) & 3]]); - p[6] = svga_color_transform(svga->pallook[svga->egapal[(dat[1] >> 2) & 3]]); - p[7] = svga_color_transform(svga->pallook[svga->egapal[dat[1] & 3]]); + p[0] = svga->pallook[svga->egapal[(dat[0] >> 6) & 3]]; + p[1] = svga->pallook[svga->egapal[(dat[0] >> 4) & 3]]; + p[2] = svga->pallook[svga->egapal[(dat[0] >> 2) & 3]]; + p[3] = svga->pallook[svga->egapal[dat[0] & 3]]; + p[4] = svga->pallook[svga->egapal[(dat[1] >> 6) & 3]]; + p[5] = svga->pallook[svga->egapal[(dat[1] >> 4) & 3]]; + p[6] = svga->pallook[svga->egapal[(dat[1] >> 2) & 3]]; + p[7] = svga->pallook[svga->egapal[dat[1] & 3]]; p += 8; } @@ -505,25 +441,25 @@ void svga_render_4bpp_lowres(svga_t *svga) for (x = 0; x <= svga->hdisp; x += 16) { uint8_t edat[4]; - uint32_t *pp = (uint32_t *)edat; uint8_t dat; - *pp = *((uint32_t *)&svga->vram[svga->ma]); + *(uint32_t *)(&edat[0]) = *(uint32_t *)(&svga->vram[svga->ma]); + svga->ma += 4; svga->ma &= svga->vram_display_mask; dat = edatlookup[edat[0] >> 6][edat[1] >> 6] | (edatlookup[edat[2] >> 6][edat[3] >> 6] << 2); - p[0] = p[1] = svga_color_transform(svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]]); - p[2] = p[3] = svga_color_transform(svga->pallook[svga->egapal[dat & svga->plane_mask]]); + p[0] = p[1] = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]]; + p[2] = p[3] = svga->pallook[svga->egapal[dat & svga->plane_mask]]; dat = edatlookup[(edat[0] >> 4) & 3][(edat[1] >> 4) & 3] | (edatlookup[(edat[2] >> 4) & 3][(edat[3] >> 4) & 3] << 2); - p[4] = p[5] = svga_color_transform(svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]]); - p[6] = p[7] = svga_color_transform(svga->pallook[svga->egapal[dat & svga->plane_mask]]); + p[4] = p[5] = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]]; + p[6] = p[7] = svga->pallook[svga->egapal[dat & svga->plane_mask]]; dat = edatlookup[(edat[0] >> 2) & 3][(edat[1] >> 2) & 3] | (edatlookup[(edat[2] >> 2) & 3][(edat[3] >> 2) & 3] << 2); - p[8] = p[9] = svga_color_transform(svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]]); - p[10] = p[11] = svga_color_transform(svga->pallook[svga->egapal[dat & svga->plane_mask]]); + p[8] = p[9] = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]]; + p[10] = p[11] = svga->pallook[svga->egapal[dat & svga->plane_mask]]; dat = edatlookup[edat[0] & 3][edat[1] & 3] | (edatlookup[edat[2] & 3][edat[3] & 3] << 2); - p[12] = p[13] = svga_color_transform(svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]]); - p[14] = p[15] = svga_color_transform(svga->pallook[svga->egapal[dat & svga->plane_mask]]); + p[12] = p[13] = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]]; + p[14] = p[15] = svga->pallook[svga->egapal[dat & svga->plane_mask]]; p += 16; } @@ -552,26 +488,24 @@ void svga_render_4bpp_highres(svga_t *svga) for (x = 0; x <= svga->hdisp; x += 8) { uint8_t edat[4]; - uint32_t *pp = (uint32_t *)edat; uint8_t dat; - *pp = *(uint32_t *)(&svga->vram[svga->ma | ((svga->sc & ~svga->crtc[0x17] & 3)) * 0x8000]); - + *(uint32_t *)(&edat[0]) = *(uint32_t *)(&svga->vram[svga->ma | ((svga->sc & ~svga->crtc[0x17] & 3)) * 0x8000]); svga->ma += 4; svga->ma &= svga->vram_display_mask; dat = edatlookup[edat[0] >> 6][edat[1] >> 6] | (edatlookup[edat[2] >> 6][edat[3] >> 6] << 2); - p[0] = svga_color_transform(svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]]); - p[1] = svga_color_transform(svga->pallook[svga->egapal[dat & svga->plane_mask]]); + p[0] = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]]; + p[1] = svga->pallook[svga->egapal[dat & svga->plane_mask]]; dat = edatlookup[(edat[0] >> 4) & 3][(edat[1] >> 4) & 3] | (edatlookup[(edat[2] >> 4) & 3][(edat[3] >> 4) & 3] << 2); - p[2] = svga_color_transform(svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]]); - p[3] = svga_color_transform(svga->pallook[svga->egapal[dat & svga->plane_mask]]); + p[2] = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]]; + p[3] = svga->pallook[svga->egapal[dat & svga->plane_mask]]; dat = edatlookup[(edat[0] >> 2) & 3][(edat[1] >> 2) & 3] | (edatlookup[(edat[2] >> 2) & 3][(edat[3] >> 2) & 3] << 2); - p[4] = svga_color_transform(svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]]); - p[5] = svga_color_transform(svga->pallook[svga->egapal[dat & svga->plane_mask]]); + p[4] = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]]; + p[5] = svga->pallook[svga->egapal[dat & svga->plane_mask]]; dat = edatlookup[edat[0] & 3][edat[1] & 3] | (edatlookup[edat[2] & 3][edat[3] & 3] << 2); - p[6] = svga_color_transform(svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]]); - p[7] = svga_color_transform(svga->pallook[svga->egapal[dat & svga->plane_mask]]); + p[6] = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]]; + p[7] = svga->pallook[svga->egapal[dat & svga->plane_mask]]; p += 8; } @@ -597,10 +531,10 @@ void svga_render_8bpp_lowres(svga_t *svga) { uint32_t dat = *(uint32_t *)(&svga->vram[svga->ma & svga->vram_display_mask]); - p[0] = p[1] = svga_color_transform(svga->pallook[dat & 0xff]); - p[2] = p[3] = svga_color_transform(svga->pallook[(dat >> 8) & 0xff]); - p[4] = p[5] = svga_color_transform(svga->pallook[(dat >> 16) & 0xff]); - p[6] = p[7] = svga_color_transform(svga->pallook[(dat >> 24) & 0xff]); + p[0] = p[1] = svga->pallook[dat & 0xff]; + p[2] = p[3] = svga->pallook[(dat >> 8) & 0xff]; + p[4] = p[5] = svga->pallook[(dat >> 16) & 0xff]; + p[6] = p[7] = svga->pallook[(dat >> 24) & 0xff]; svga->ma += 4; p += 8; @@ -628,16 +562,16 @@ void svga_render_8bpp_highres(svga_t *svga) { uint32_t dat; dat = *(uint32_t *)(&svga->vram[svga->ma & svga->vram_display_mask]); - p[0] = svga_color_transform(svga->pallook[dat & 0xff]); - p[1] = svga_color_transform(svga->pallook[(dat >> 8) & 0xff]); - p[2] = svga_color_transform(svga->pallook[(dat >> 16) & 0xff]); - p[3] = svga_color_transform(svga->pallook[(dat >> 24) & 0xff]); + p[0] = svga->pallook[dat & 0xff]; + p[1] = svga->pallook[(dat >> 8) & 0xff]; + p[2] = svga->pallook[(dat >> 16) & 0xff]; + p[3] = svga->pallook[(dat >> 24) & 0xff]; dat = *(uint32_t *)(&svga->vram[(svga->ma + 4) & svga->vram_display_mask]); - p[4] = svga_color_transform(svga->pallook[dat & 0xff]); - p[5] = svga_color_transform(svga->pallook[(dat >> 8) & 0xff]); - p[6] = svga_color_transform(svga->pallook[(dat >> 16) & 0xff]); - p[7] = svga_color_transform(svga->pallook[(dat >> 24) & 0xff]); + p[4] = svga->pallook[dat & 0xff]; + p[5] = svga->pallook[(dat >> 8) & 0xff]; + p[6] = svga->pallook[(dat >> 16) & 0xff]; + p[7] = svga->pallook[(dat >> 24) & 0xff]; svga->ma += 8; p += 8; @@ -665,13 +599,13 @@ void svga_render_15bpp_lowres(svga_t *svga) { uint32_t dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1)) & svga->vram_display_mask]); - p[x] = svga_color_transform(video_15to32[dat & 0xffff]); - p[x + 1] = svga_color_transform(video_15to32[dat >> 16]); + p[x] = video_15to32[dat & 0xffff]; + p[x + 1] = video_15to32[dat >> 16]; dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1) + 4) & svga->vram_display_mask]); - p[x] = svga_color_transform(video_15to32[dat & 0xffff]); - p[x + 1] = svga_color_transform(video_15to32[dat >> 16]); + p[x] = video_15to32[dat & 0xffff]; + p[x + 1] = video_15to32[dat >> 16]; } svga->ma += x << 1; svga->ma &= svga->vram_display_mask; @@ -696,20 +630,20 @@ void svga_render_15bpp_highres(svga_t *svga) for (x = 0; x <= svga->hdisp; x += 8) { uint32_t dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1)) & svga->vram_display_mask]); - p[x] = svga_color_transform(video_15to32[dat & 0xffff]); - p[x + 1] = svga_color_transform(video_15to32[dat >> 16]); + p[x] = video_15to32[dat & 0xffff]; + p[x + 1] = video_15to32[dat >> 16]; dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1) + 4) & svga->vram_display_mask]); - p[x + 2] = svga_color_transform(video_15to32[dat & 0xffff]); - p[x + 3] = svga_color_transform(video_15to32[dat >> 16]); + p[x + 2] = video_15to32[dat & 0xffff]; + p[x + 3] = video_15to32[dat >> 16]; dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1) + 8) & svga->vram_display_mask]); - p[x + 4] = svga_color_transform(video_15to32[dat & 0xffff]); - p[x + 5] = svga_color_transform(video_15to32[dat >> 16]); + p[x + 4] = video_15to32[dat & 0xffff]; + p[x + 5] = video_15to32[dat >> 16]; dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1) + 12) & svga->vram_display_mask]); - p[x + 6] = svga_color_transform(video_15to32[dat & 0xffff]); - p[x + 7] = svga_color_transform(video_15to32[dat >> 16]); + p[x + 6] = video_15to32[dat & 0xffff]; + p[x + 7] = video_15to32[dat >> 16]; } svga->ma += x << 1; svga->ma &= svga->vram_display_mask; @@ -735,13 +669,13 @@ void svga_render_16bpp_lowres(svga_t *svga) { uint32_t dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1)) & svga->vram_display_mask]); - p[x] = svga_color_transform(video_16to32[dat & 0xffff]); - p[x + 1] = svga_color_transform(video_16to32[dat >> 16]); + p[x] = video_16to32[dat & 0xffff]; + p[x + 1] = video_16to32[dat >> 16]; dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1) + 4) & svga->vram_display_mask]); - p[x] = svga_color_transform(video_16to32[dat & 0xffff]); - p[x + 1] = svga_color_transform(video_16to32[dat >> 16]); + p[x] = video_16to32[dat & 0xffff]; + p[x + 1] = video_16to32[dat >> 16]; } svga->ma += x << 1; svga->ma &= svga->vram_display_mask; @@ -766,20 +700,20 @@ void svga_render_16bpp_highres(svga_t *svga) for (x = 0; x <= svga->hdisp; x += 8) { uint32_t dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1)) & svga->vram_display_mask]); - p[x] = svga_color_transform(video_16to32[dat & 0xffff]); - p[x + 1] = svga_color_transform(video_16to32[dat >> 16]); + p[x] = video_16to32[dat & 0xffff]; + p[x + 1] = video_16to32[dat >> 16]; dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1) + 4) & svga->vram_display_mask]); - p[x + 2] = svga_color_transform(video_16to32[dat & 0xffff]); - p[x + 3] = svga_color_transform(video_16to32[dat >> 16]); + p[x + 2] = video_16to32[dat & 0xffff]; + p[x + 3] = video_16to32[dat >> 16]; dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1) + 8) & svga->vram_display_mask]); - p[x + 4] = svga_color_transform(video_16to32[dat & 0xffff]); - p[x + 5] = svga_color_transform(video_16to32[dat >> 16]); + p[x + 4] = video_16to32[dat & 0xffff]; + p[x + 5] = video_16to32[dat >> 16]; dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1) + 12) & svga->vram_display_mask]); - p[x + 6] = svga_color_transform(video_16to32[dat & 0xffff]); - p[x + 7] = svga_color_transform(video_16to32[dat >> 16]); + p[x + 6] = video_16to32[dat & 0xffff]; + p[x + 7] = video_16to32[dat >> 16]; } svga->ma += x << 1; svga->ma &= svga->vram_display_mask; @@ -807,7 +741,7 @@ void svga_render_24bpp_lowres(svga_t *svga) fg = svga->vram[svga->ma] | (svga->vram[svga->ma + 1] << 8) | (svga->vram[svga->ma + 2] << 16); svga->ma += 3; svga->ma &= svga->vram_display_mask; - ((uint32_t *)buffer32->line[svga->displine + y_add])[(x << 1) + offset + x_add] = ((uint32_t *)buffer32->line[svga->displine + y_add])[(x << 1) + 1 + offset + x_add] = svga_color_transform(fg); + ((uint32_t *)buffer32->line[svga->displine + y_add])[(x << 1) + offset + x_add] = ((uint32_t *)buffer32->line[svga->displine + y_add])[(x << 1) + 1 + offset + x_add] = fg; } } } @@ -830,16 +764,16 @@ void svga_render_24bpp_highres(svga_t *svga) for (x = 0; x <= svga->hdisp; x += 4) { uint32_t dat = *(uint32_t *)(&svga->vram[svga->ma & svga->vram_display_mask]); - p[x] = svga_color_transform(dat & 0xffffff); + p[x] = dat & 0xffffff; dat = *(uint32_t *)(&svga->vram[(svga->ma + 3) & svga->vram_display_mask]); - p[x + 1] = svga_color_transform(dat & 0xffffff); + p[x + 1] = dat & 0xffffff; dat = *(uint32_t *)(&svga->vram[(svga->ma + 6) & svga->vram_display_mask]); - p[x + 2] = svga_color_transform(dat & 0xffffff); + p[x + 2] = dat & 0xffffff; dat = *(uint32_t *)(&svga->vram[(svga->ma + 9) & svga->vram_display_mask]); - p[x + 3] = svga_color_transform(dat & 0xffffff); + p[x + 3] = dat & 0xffffff; svga->ma += 12; } @@ -868,7 +802,7 @@ void svga_render_32bpp_lowres(svga_t *svga) fg = svga->vram[svga->ma] | (svga->vram[svga->ma + 1] << 8) | (svga->vram[svga->ma + 2] << 16); svga->ma += 4; svga->ma &= svga->vram_display_mask; - ((uint32_t *)buffer32->line[svga->displine + y_add])[(x << 1) + offset + x_add] = ((uint32_t *)buffer32->line[svga->displine + y_add])[(x << 1) + 1 + offset + x_add] = svga_color_transform(fg); + ((uint32_t *)buffer32->line[svga->displine + y_add])[(x << 1) + offset + x_add] = ((uint32_t *)buffer32->line[svga->displine + y_add])[(x << 1) + 1 + offset + x_add] = fg; } } } @@ -893,7 +827,7 @@ void svga_render_32bpp_highres(svga_t *svga) for (x = 0; x <= svga->hdisp; x++) { uint32_t dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 2)) & svga->vram_display_mask]); - p[x] = svga_color_transform(dat & 0xffffff); + p[x] = dat & 0xffffff; } svga->ma += 4; svga->ma &= svga->vram_display_mask; @@ -918,7 +852,7 @@ void svga_render_ABGR8888_highres(svga_t *svga) for (x = 0; x <= svga->hdisp; x++) { uint32_t dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 2)) & svga->vram_display_mask]); - p[x] = svga_color_transform((dat & 0xff0000) >> 16) | (dat & 0x00ff00) | ((dat & 0x0000ff) << 16); + p[x] = ((dat & 0xff0000) >> 16) | (dat & 0x00ff00) | ((dat & 0x0000ff) << 16); } svga->ma += 4; svga->ma &= svga->vram_display_mask; @@ -943,9 +877,9 @@ void svga_render_RGBA8888_highres(svga_t *svga) for (x = 0; x <= svga->hdisp; x++) { uint32_t dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 2)) & svga->vram_display_mask]); - p[x] = svga_color_transform(dat >> 8); + p[x] = dat >> 8; } svga->ma += 4; - svga->ma &= svga->vram_display_mask; +svga->ma &= svga->vram_display_mask; } } diff --git a/src/devices/video/vid_tgui9440.c b/src/devices/video/vid_tgui9440.c index c370576..5bc1719 100644 --- a/src/devices/video/vid_tgui9440.c +++ b/src/devices/video/vid_tgui9440.c @@ -47,7 +47,7 @@ * access size or host data has any affect, but the Windows 3.1 * driver always reads bytes and write words of 0xffff. * - * Version: @(#)vid_tgui9440.c 1.0.8 2018/05/06 + * Version: @(#)vid_tgui9440.c 1.0.9 2018/10/05 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -94,6 +94,10 @@ #include "vid_tkd8001_ramdac.h" +#define ROM_TGUI_9400CXI L"video/trident/tgui9440/9400cxi.vbi" +#define ROM_TGUI_9440 L"video/trident/tgui9440/9440.vbi" + + /*TGUI9400CXi has extended write modes, controlled by extended GDC registers : GDC[0x10] - Control @@ -164,16 +168,14 @@ typedef struct typedef struct tgui_t { - mem_mapping_t linear_mapping; - mem_mapping_t accel_mapping; + mem_map_t linear_mapping; + mem_map_t accel_mapping; rom_t bios_rom; svga_t svga; int pci; - tkd8001_ramdac_t ramdac; /*TGUI9400CXi*/ - int type; struct @@ -230,6 +232,10 @@ typedef struct tgui_t volatile int write_blitter; } tgui_t; + +static const video_timings_t tgui_timing = {VID_BUS,4,8,16,4,8,16}; + + void tgui_recalcmapping(tgui_t *tgui); static void fifo_thread(void *param); @@ -300,7 +306,7 @@ void tgui_out(uint16_t addr, uint8_t val, void *p) case 0x3C6: if (tgui->type == TGUI_9400CXI) { - tkd8001_ramdac_out(addr, val, &tgui->ramdac, svga); + tkd8001_ramdac_out(addr, val, svga->ramdac, svga); return; } if (tgui->ramdac_state == 4) @@ -327,7 +333,7 @@ void tgui_out(uint16_t addr, uint8_t val, void *p) case 0x3C7: case 0x3C8: case 0x3C9: if (tgui->type == TGUI_9400CXI) { - tkd8001_ramdac_out(addr, val, &tgui->ramdac, svga); + tkd8001_ramdac_out(addr, val, svga->ramdac, svga); return; } tgui->ramdac_state = 0; @@ -481,14 +487,14 @@ uint8_t tgui_in(uint16_t addr, void *p) break; case 0x3C6: if (tgui->type == TGUI_9400CXI) - return tkd8001_ramdac_in(addr, &tgui->ramdac, svga); + return tkd8001_ramdac_in(addr, svga->ramdac, svga); if (tgui->ramdac_state == 4) return tgui->ramdac_ctrl; tgui->ramdac_state++; break; case 0x3C7: case 0x3C8: case 0x3C9: if (tgui->type == TGUI_9400CXI) - return tkd8001_ramdac_in(addr, &tgui->ramdac, svga); + return tkd8001_ramdac_in(addr, svga->ramdac, svga); tgui->ramdac_state = 0; break; case 0x3CF: @@ -615,28 +621,28 @@ void tgui_recalcmapping(tgui_t *tgui) { if (tgui->ext_gdc_regs[0] & EXT_CTRL_LATCH_COPY) { - mem_mapping_set_handler(&tgui->linear_mapping, + mem_map_set_handler(&tgui->linear_mapping, tgui_ext_linear_read, NULL, NULL, tgui_ext_linear_write, tgui_ext_linear_writew, tgui_ext_linear_writel); - mem_mapping_set_handler(&svga->mapping, + mem_map_set_handler(&svga->mapping, tgui_ext_read, NULL, NULL, tgui_ext_write, tgui_ext_writew, tgui_ext_writel); } else if (tgui->ext_gdc_regs[0] & EXT_CTRL_MONO_EXPANSION) { - mem_mapping_set_handler(&tgui->linear_mapping, + mem_map_set_handler(&tgui->linear_mapping, svga_read_linear, svga_readw_linear, svga_readl_linear, tgui_ext_linear_write, tgui_ext_linear_writew, tgui_ext_linear_writel); - mem_mapping_set_handler(&svga->mapping, + mem_map_set_handler(&svga->mapping, svga_read, svga_readw, svga_readl, tgui_ext_write, tgui_ext_writew, tgui_ext_writel); } else { - mem_mapping_set_handler(&tgui->linear_mapping, + mem_map_set_handler(&tgui->linear_mapping, svga_read_linear, svga_readw_linear, svga_readl_linear, svga_write_linear, svga_writew_linear, svga_writel_linear); - mem_mapping_set_handler(&svga->mapping, + mem_map_set_handler(&svga->mapping, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel); } @@ -644,31 +650,31 @@ void tgui_recalcmapping(tgui_t *tgui) if (svga->crtc[0x21] & 0x20) { - mem_mapping_disable(&svga->mapping); - mem_mapping_set_addr(&tgui->linear_mapping, tgui->linear_base, tgui->linear_size); + mem_map_disable(&svga->mapping); + mem_map_set_addr(&tgui->linear_mapping, tgui->linear_base, tgui->linear_size); if (tgui->type >= TGUI_9440) { - mem_mapping_enable(&tgui->accel_mapping); - mem_mapping_disable(&svga->mapping); + mem_map_enable(&tgui->accel_mapping); + mem_map_disable(&svga->mapping); } else { switch (svga->gdcreg[6] & 0xC) { case 0x0: /*128k at A0000*/ - mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x20000); + mem_map_set_addr(&svga->mapping, 0xa0000, 0x20000); svga->banked_mask = 0xffff; break; case 0x4: /*64k at A0000*/ - mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000); + mem_map_set_addr(&svga->mapping, 0xa0000, 0x10000); svga->banked_mask = 0xffff; break; case 0x8: /*32k at B0000*/ - mem_mapping_set_addr(&svga->mapping, 0xb0000, 0x08000); + mem_map_set_addr(&svga->mapping, 0xb0000, 0x08000); svga->banked_mask = 0x7fff; break; case 0xC: /*32k at B8000*/ - mem_mapping_set_addr(&svga->mapping, 0xb8000, 0x08000); + mem_map_set_addr(&svga->mapping, 0xb8000, 0x08000); svga->banked_mask = 0x7fff; break; } @@ -676,25 +682,25 @@ void tgui_recalcmapping(tgui_t *tgui) } else { - mem_mapping_disable(&tgui->linear_mapping); - mem_mapping_disable(&tgui->accel_mapping); + mem_map_disable(&tgui->linear_mapping); + mem_map_disable(&tgui->accel_mapping); switch (svga->gdcreg[6] & 0xC) { case 0x0: /*128k at A0000*/ - mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x20000); + mem_map_set_addr(&svga->mapping, 0xa0000, 0x20000); svga->banked_mask = 0xffff; break; case 0x4: /*64k at A0000*/ - mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000); - mem_mapping_enable(&tgui->accel_mapping); + mem_map_set_addr(&svga->mapping, 0xa0000, 0x10000); + mem_map_enable(&tgui->accel_mapping); svga->banked_mask = 0xffff; break; case 0x8: /*32k at B0000*/ - mem_mapping_set_addr(&svga->mapping, 0xb0000, 0x08000); + mem_map_set_addr(&svga->mapping, 0xb0000, 0x08000); svga->banked_mask = 0x7fff; break; case 0xC: /*32k at B8000*/ - mem_mapping_set_addr(&svga->mapping, 0xb8000, 0x08000); + mem_map_set_addr(&svga->mapping, 0xb8000, 0x08000); svga->banked_mask = 0x7fff; break; } @@ -706,6 +712,10 @@ void tgui_hwcursor_draw(svga_t *svga, int disp_line) uint32_t dat[2]; int xx; int offset = svga->hwcursor_latch.x - svga->hwcursor_latch.xoff; + int y_add, x_add; + + y_add = (enable_overscan && !suppress_overscan) ? (overscan_y >> 1) : 0; + x_add = (enable_overscan && !suppress_overscan) ? 8 : 0; if (svga->interlace && svga->hwcursor_oddeven) svga->hwcursor_latch.addr += 8; @@ -717,9 +727,10 @@ void tgui_hwcursor_draw(svga_t *svga, int disp_line) if (offset >= svga->hwcursor_latch.x) { if (!(dat[0] & 0x80000000)) - ((uint32_t *)buffer32->line[disp_line])[offset + 32] = (dat[1] & 0x80000000) ? 0xffffff : 0; + ((uint32_t *)buffer32->line[displine + y_add])[offset + 32 + x_add] = (dat[1] & 0x80000000) ? 0xffffff : 0; else if (dat[1] & 0x80000000) - ((uint32_t *)buffer32->line[disp_line])[offset + 32] ^= 0xffffff; + + ((uint32_t *)buffer32->line[displine + y_add])[offset + 32 + x_add] ^= 0xffffff; } offset++; @@ -791,91 +802,6 @@ void tgui_pci_write(int func, int addr, uint8_t val, void *p) } } -static void *tgui_init(const device_t *info, wchar_t *bios_fn, int type) -{ - tgui_t *tgui = malloc(sizeof(tgui_t)); - memset(tgui, 0, sizeof(tgui_t)); - - tgui->vram_size = device_get_config_int("memory") << 20; - tgui->vram_mask = tgui->vram_size - 1; - - tgui->type = type; - - tgui->pci = !!(info->flags & DEVICE_PCI); - - rom_init(&tgui->bios_rom, bios_fn, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); - - svga_init(&tgui->svga, tgui, tgui->vram_size, - tgui_recalctimings, - tgui_in, tgui_out, - tgui_hwcursor_draw, - NULL); - - mem_mapping_add(&tgui->linear_mapping, 0, 0, svga_read_linear, svga_readw_linear, svga_readl_linear, tgui_accel_write_fb_b, tgui_accel_write_fb_w, tgui_accel_write_fb_l, NULL, 0, &tgui->svga); - mem_mapping_add(&tgui->accel_mapping, 0xbc000, 0x4000, tgui_accel_read, tgui_accel_read_w, tgui_accel_read_l, tgui_accel_write, tgui_accel_write_w, tgui_accel_write_l, NULL, 0, tgui); - mem_mapping_disable(&tgui->accel_mapping); - - io_sethandler(0x03c0, 0x0020, tgui_in, NULL, NULL, tgui_out, NULL, NULL, tgui); - if (tgui->type >= TGUI_9440) - io_sethandler(0x43c8, 0x0002, tgui_in, NULL, NULL, tgui_out, NULL, NULL, tgui); - - if ((info->flags & DEVICE_PCI) && (tgui->type >= TGUI_9440)) - pci_add_card(PCI_ADD_VIDEO, tgui_pci_read, tgui_pci_write, tgui); - - tgui->wake_fifo_thread = thread_create_event(); - tgui->fifo_not_full_event = thread_create_event(); - tgui->fifo_thread = thread_create(fifo_thread, tgui); - - return tgui; -} - -static void *tgui9400cxi_init(const device_t *info) -{ - return tgui_init(info, L"video/trident/tgui9440/9400cxi.vbi", TGUI_9400CXI); -} - -static void *tgui9440_init(const device_t *info) -{ - return tgui_init(info, L"video/trident/tgui9440/9440.vbi", TGUI_9440); -} - -static int tgui9400cxi_available() -{ - return rom_present(L"video/trident/tgui9440/9400cxi.vbi"); -} - -static int tgui9440_available() -{ - return rom_present(L"video/trident/tgui9440/9440.vbi"); -} - -void tgui_close(void *p) -{ - tgui_t *tgui = (tgui_t *)p; - - svga_close(&tgui->svga); - - thread_kill(tgui->fifo_thread); - thread_destroy_event(tgui->wake_fifo_thread); - thread_destroy_event(tgui->fifo_not_full_event); - - free(tgui); -} - -void tgui_speed_changed(void *p) -{ - tgui_t *tgui = (tgui_t *)p; - - svga_recalctimings(&tgui->svga); -} - -void tgui_force_redraw(void *p) -{ - tgui_t *tgui = (tgui_t *)p; - - tgui->svga.fullchange = changeframecount; -} - static uint8_t tgui_ext_linear_read(uint32_t addr, void *p) { @@ -884,7 +810,6 @@ static uint8_t tgui_ext_linear_read(uint32_t addr, void *p) int c; cycles -= video_timing_read_b; - cycles_lost += video_timing_read_b; addr &= svga->decode_mask; if (addr >= svga->vram_max) @@ -916,7 +841,6 @@ static void tgui_ext_linear_write(uint32_t addr, uint8_t val, void *p) uint8_t mask = tgui->ext_gdc_regs[7]; cycles -= video_timing_write_b; - cycles_lost += video_timing_write_b; addr &= svga->decode_mask; if (addr >= svga->vram_max) @@ -986,7 +910,6 @@ static void tgui_ext_linear_writew(uint32_t addr, uint16_t val, void *p) uint16_t mask = (tgui->ext_gdc_regs[7] << 8) | tgui->ext_gdc_regs[8]; cycles -= video_timing_write_w; - cycles_lost += video_timing_write_w; addr &= svga->decode_mask; if (addr >= svga->vram_max) @@ -1749,90 +1672,160 @@ void tgui_accel_write_fb_l(uint32_t addr, uint32_t val, void *p) svga_writel_linear(addr, val, svga); } -void tgui_add_status_info(char *s, int max_len, void *p) + +static void * +tgui_init(const device_t *info) { - tgui_t *tgui = (tgui_t *)p; - char temps[256]; - uint64_t new_time = plat_timer_read(); - uint64_t status_diff = new_time - tgui->status_time; - tgui->status_time = new_time; + const wchar_t *bios_fn; + tgui_t *tgui = (tgui_t *)mem_alloc(sizeof(tgui_t)); + memset(tgui, 0x00, sizeof(tgui_t)); + tgui->type = info->local; + tgui->pci = !!(info->flags & DEVICE_PCI); + + tgui->vram_size = device_get_config_int("memory") << 20; + tgui->vram_mask = tgui->vram_size - 1; - svga_add_status_info(s, max_len, &tgui->svga); + switch(info->local) { + case TGUI_9400CXI: + bios_fn = ROM_TGUI_9400CXI; + break; + case TGUI_9440: + bios_fn = ROM_TGUI_9440; + break; + default: + free(tgui); + return NULL; + } - sprintf(temps, "%f%% CPU\n%f%% CPU (real)\n\n", ((double)tgui->blitter_time * 100.0) / timer_freq, ((double)tgui->blitter_time * 100.0) / status_diff); - strncat(s, temps, max_len); + rom_init(&tgui->bios_rom, (wchar_t *) bios_fn, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); - tgui->blitter_time = 0; + video_inform(VID_TYPE_SPEC, &tgui_timing); + + svga_init(&tgui->svga, tgui, tgui->vram_size, + tgui_recalctimings, + tgui_in, tgui_out, + tgui_hwcursor_draw, + NULL); + + if (tgui->type == TGUI_9400CXI) + tgui->svga.ramdac = device_add(&tkd8001_ramdac_device); + + mem_map_add(&tgui->linear_mapping, 0, 0, svga_read_linear, svga_readw_linear, svga_readl_linear, tgui_accel_write_fb_b, tgui_accel_write_fb_w, tgui_accel_write_fb_l, NULL, 0, &tgui->svga); + mem_map_add(&tgui->accel_mapping, 0xbc000, 0x4000, tgui_accel_read, tgui_accel_read_w, tgui_accel_read_l, tgui_accel_write, tgui_accel_write_w, tgui_accel_write_l, NULL, 0, tgui); + mem_map_disable(&tgui->accel_mapping); + + io_sethandler(0x03c0, 0x0020, tgui_in, NULL, NULL, tgui_out, NULL, NULL, tgui); + + if (tgui->type >= TGUI_9440) + io_sethandler(0x43c8, 0x0002, tgui_in, NULL, NULL, tgui_out, NULL, NULL, tgui); + + if ((info->flags & DEVICE_PCI) && (tgui->type >= TGUI_9440)) + pci_add_card(PCI_ADD_VIDEO, tgui_pci_read, tgui_pci_write, tgui); + tgui->wake_fifo_thread = thread_create_event(); + tgui->fifo_not_full_event = thread_create_event(); + tgui->fifo_thread = thread_create(fifo_thread, tgui); + + return tgui; } + +static void +tgui_close(void *priv) +{ + tgui_t *tgui = (tgui_t *)priv; + + svga_close(&tgui->svga); + + thread_kill(tgui->fifo_thread); + thread_destroy_event(tgui->wake_fifo_thread); + thread_destroy_event(tgui->fifo_not_full_event); + + free(tgui); +} + + +static void +tgui_speed_changed(void *priv) +{ + tgui_t *tgui = (tgui_t *)priv; + + svga_recalctimings(&tgui->svga); +} + + +static void +tgui_force_redraw(void *priv) +{ + tgui_t *tgui = (tgui_t *)priv; + tgui->svga.fullchange = changeframecount; +} + + +static int +tgui9400cxi_available(void) +{ + return rom_present(ROM_TGUI_9400CXI); +} + +static int tgui9440_available(void) +{ + return rom_present(ROM_TGUI_9440); +} + + static const device_config_t tgui9440_config[] = { { - .name = "memory", - .description = "Memory size", - .type = CONFIG_SELECTION, - .selection = + "memory","Memory size",CONFIG_SELECTION,"",2, { { - .description = "1 MB", - .value = 1 + "1 MB",1 }, { - .description = "2 MB", - .value = 2 + "2 MB",2 }, { - .description = "" + "" } }, - .default_int = 2 }, { - .type = -1 + "","",-1 } }; -const device_t tgui9400cxi_device = -{ +const device_t tgui9400cxi_device = { "Trident TGUI 9400CXi", DEVICE_VLB, - 0, - tgui9400cxi_init, - tgui_close, - NULL, + TGUI_9400CXI, + tgui_init, tgui_close, NULL, tgui9400cxi_available, tgui_speed_changed, tgui_force_redraw, - tgui_add_status_info, + NULL, tgui9440_config }; -const device_t tgui9440_vlb_device = -{ +const device_t tgui9440_vlb_device = { "Trident TGUI 9440 VLB", DEVICE_VLB, - 0, - tgui9440_init, - tgui_close, - NULL, + TGUI_9440, + tgui_init, tgui_close, NULL, tgui9440_available, tgui_speed_changed, tgui_force_redraw, - tgui_add_status_info, + NULL, tgui9440_config }; -const device_t tgui9440_pci_device = -{ +const device_t tgui9440_pci_device = { "Trident TGUI 9440 PCI", DEVICE_PCI, - 0, - tgui9440_init, - tgui_close, - NULL, + TGUI_9440, + tgui_init, tgui_close, NULL, tgui9440_available, tgui_speed_changed, tgui_force_redraw, - tgui_add_status_info, + NULL, tgui9440_config }; diff --git a/src/devices/video/vid_ti_cf62011.c b/src/devices/video/vid_ti_cf62011.c index 8a35ef0..4167bb0 100644 --- a/src/devices/video/vid_ti_cf62011.c +++ b/src/devices/video/vid_ti_cf62011.c @@ -42,7 +42,7 @@ * which are the same as the XGA. It supports up to 1MB of VRAM, * but we lock it down to 512K. The PS/1 2122 had 256K. * - * Version: @(#)vid_ti_cf62011.c 1.0.4 2018/05/06 + * Version: @(#)vid_ti_cf62011.c 1.0.6 2018/10/05 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -76,7 +76,6 @@ #include #include #include "../../emu.h" -#include "../../config.h" #include "../../io.h" #include "../../mem.h" #include "../../rom.h" @@ -111,7 +110,6 @@ vid_out(uint16_t addr, uint8_t val, void *priv) if (((addr & 0xfff0) == 0x03d0 || (addr & 0xfff0) == 0x03b0) && !(svga->miscout & 1)) addr ^= 0x60; #endif - // pclog("TISVGA_out(%04x, %02x)\n", addr, val); switch (addr) { case 0x0102: @@ -119,10 +117,12 @@ vid_out(uint16_t addr, uint8_t val, void *priv) return; case 0x03d4: - svga->crtcreg = val & 0x1f; + svga->crtcreg = val & 0x3f; return; case 0x03d5: + if (svga->crtcreg & 0x20) + return; if ((svga->crtcreg < 7) && (svga->crtc[0x11] & 0x80)) return; if ((svga->crtcreg == 7) && (svga->crtc[0x11] & 0x80)) @@ -190,7 +190,10 @@ vid_in(uint16_t addr, void *priv) break; case 0x03d5: - ret = svga->crtc[svga->crtcreg]; + if (svga->crtcreg & 0x20) + ret = 0xff; + else + ret = svga->crtc[svga->crtcreg]; break; case 0x2100: @@ -210,8 +213,6 @@ vid_in(uint16_t addr, void *priv) break; } - // pclog("TISVGA_in(%04x) = %02x\n", addr, ret); - return(ret); } @@ -234,15 +235,6 @@ vid_force_redraw(void *priv) } -static void -vid_add_status_info(char *s, int max_len, void *priv) -{ - tivga_t *ti = (tivga_t *)priv; - - svga_add_status_info(s, max_len, &ti->svga); -} - - static void vid_close(void *priv) { @@ -260,7 +252,7 @@ vid_init(const device_t *info) tivga_t *ti; /* Allocate control block and initialize. */ - ti = (tivga_t *)malloc(sizeof(tivga_t)); + ti = (tivga_t *)mem_alloc(sizeof(tivga_t)); memset(ti, 0x00, sizeof(tivga_t)); /* Set amount of VRAM in KB. */ @@ -269,7 +261,7 @@ vid_init(const device_t *info) else ti->vram_size = info->local; - pclog("VIDEO: initializing %s, %dK VRAM\n", info->name, ti->vram_size); + DEBUG("VIDEO: initializing %s, %dK VRAM\n", info->name, ti->vram_size); svga_init(&ti->svga, ti, ti->vram_size<<10, @@ -314,13 +306,13 @@ static const device_config_t vid_config[] = const device_t ti_cf62011_device = { "TI CF62011 SVGA", - 0, + DEVICE_ISA, 0, vid_init, vid_close, NULL, NULL, vid_speed_changed, vid_force_redraw, - vid_add_status_info, + NULL, vid_config }; #endif @@ -328,12 +320,12 @@ const device_t ti_cf62011_device = { const device_t ibm_ps1_2121_device = { "IBM PS/1 Model 2121 SVGA", - 0, + DEVICE_ISA, 512, vid_init, vid_close, NULL, NULL, vid_speed_changed, vid_force_redraw, - vid_add_status_info, + NULL, NULL }; diff --git a/src/devices/video/vid_tkd8001_ramdac.c b/src/devices/video/vid_tkd8001_ramdac.c index 40d6a13..1f4df6f 100644 --- a/src/devices/video/vid_tkd8001_ramdac.c +++ b/src/devices/video/vid_tkd8001_ramdac.c @@ -8,7 +8,7 @@ * * Trident TKD8001 RAMDAC emulation. * - * Version: @(#)vid_tkd8001_ramdac.c 1.0.2 2018/05/06 + * Version: @(#)vid_tkd8001_ramdac.c 1.0.3 2018/10/05 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -39,62 +39,105 @@ #include #include #include +#include #include #include "../../emu.h" #include "../../mem.h" +#include "../../device.h" #include "video.h" #include "vid_svga.h" #include "vid_tkd8001_ramdac.h" -void tkd8001_ramdac_out(uint16_t addr, uint8_t val, tkd8001_ramdac_t *ramdac, svga_t *svga) +void +tkd8001_ramdac_out(uint16_t addr, uint8_t val, tkd8001_ramdac_t *dev, svga_t *svga) { - switch (addr) - { - case 0x3C6: - if (ramdac->state == 4) - { - ramdac->state = 0; - ramdac->ctrl = val; - switch (val >> 5) - { - case 0: case 1: case 2: case 3: - svga->bpp = 8; - break; - case 5: - svga->bpp = 15; - break; - case 6: - svga->bpp = 24; - break; - case 7: - svga->bpp = 16; - break; - } - return; - } - break; - case 0x3C7: case 0x3C8: case 0x3C9: - ramdac->state = 0; - break; - } - svga_out(addr, val, svga); + switch (addr) { + case 0x3C6: + if (dev->state == 4) { + dev->state = 0; + dev->ctrl = val; + switch (val >> 5) { + case 0: + case 1: + case 2: + case 3: + svga->bpp = 8; + break; + + case 5: + svga->bpp = 15; + break; + + case 6: + svga->bpp = 24; + break; + + case 7: + svga->bpp = 16; + break; + } + return; + } + break; + + case 0x3C7: + case 0x3C8: + case 0x3C9: + dev->state = 0; + break; + } + + svga_out(addr, val, svga); } -uint8_t tkd8001_ramdac_in(uint16_t addr, tkd8001_ramdac_t *ramdac, svga_t *svga) + +uint8_t +tkd8001_ramdac_in(uint16_t addr, tkd8001_ramdac_t *dev, svga_t *svga) { - switch (addr) - { - case 0x3C6: - if (ramdac->state == 4) - { - return ramdac->ctrl; - } - ramdac->state++; - break; - case 0x3C7: case 0x3C8: case 0x3C9: - ramdac->state = 0; - break; - } - return svga_in(addr, svga); + switch (addr) { + case 0x3C6: + if (dev->state == 4) + return dev->ctrl; + dev->state++; + break; + + case 0x3C7: + case 0x3C8: + case 0x3C9: + dev->state = 0; + break; + } + + return svga_in(addr, svga); } + + +static void * +tkd8001_init(const device_t *info) +{ + tkd8001_ramdac_t *dev = (tkd8001_ramdac_t *)mem_alloc(sizeof(tkd8001_ramdac_t)); + memset(dev, 0x00, sizeof(tkd8001_ramdac_t)); + + return dev; +} + + +static void +tkd8001_close(void *priv) +{ + tkd8001_ramdac_t *dev = (tkd8001_ramdac_t *)priv; + + if (dev != NULL) + free(dev); +} + + +const device_t tkd8001_ramdac_device = { + "Trident TKD8001 RAMDAC", + 0, + 0, + tkd8001_init, tkd8001_close, NULL, + NULL, NULL, NULL, NULL, + NULL +}; diff --git a/src/devices/video/vid_tkd8001_ramdac.h b/src/devices/video/vid_tkd8001_ramdac.h index f4b946f..14b3d18 100644 --- a/src/devices/video/vid_tkd8001_ramdac.h +++ b/src/devices/video/vid_tkd8001_ramdac.h @@ -8,7 +8,7 @@ * * Definitions for the TKD8001 driver. * - * Version: @(#)vid_tkd8001_ramdac.h 1.0.1 2018/02/14 + * Version: @(#)vid_tkd8001_ramdac.h 1.0.2 2018/10/05 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -40,14 +40,17 @@ # define VIDEO_TKD8001_RAMDAC_H -typedef struct tkd8001_ramdac_t -{ - int state; - uint8_t ctrl; +typedef struct { + int state; + uint8_t ctrl; } tkd8001_ramdac_t; -void tkd8001_ramdac_out(uint16_t addr, uint8_t val, tkd8001_ramdac_t *ramdac, svga_t *svga); -uint8_t tkd8001_ramdac_in(uint16_t addr, tkd8001_ramdac_t *ramdac, svga_t *svga); + +extern const device_t tkd8001_ramdac_device; + + +extern void tkd8001_ramdac_out(uint16_t addr, uint8_t val, tkd8001_ramdac_t *dev, svga_t *svga); +extern uint8_t tkd8001_ramdac_in(uint16_t addr, tkd8001_ramdac_t *dev, svga_t *svga); #endif /*VIDEO_TKD8001_RAMDAC_H*/ diff --git a/src/devices/video/vid_tvga.c b/src/devices/video/vid_tvga.c index 149745a..9df207c 100644 --- a/src/devices/video/vid_tvga.c +++ b/src/devices/video/vid_tvga.c @@ -8,7 +8,7 @@ * * Trident TVGA (8900D) emulation. * - * Version: @(#)vid_tvga.c 1.0.7 2018/05/06 + * Version: @(#)vid_tvga.c 1.0.8 2018/10/05 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -52,23 +52,24 @@ #include "vid_tkd8001_ramdac.h" -typedef struct tvga_t -{ - mem_mapping_t linear_mapping; - mem_mapping_t accel_mapping; +#define ROM_TVGA_BIOS L"video/trident/tvga/trident.bin" - svga_t svga; - tkd8001_ramdac_t ramdac; - - rom_t bios_rom; - uint8_t tvga_3d8, tvga_3d9; - int oldmode; - uint8_t oldctrl1; - uint8_t oldctrl2, newctrl2; +typedef struct { + mem_map_t linear_mapping; + mem_map_t accel_mapping; + + svga_t svga; - int vram_size; - uint32_t vram_mask; + rom_t bios_rom; + + uint8_t tvga_3d8, tvga_3d9; + int oldmode; + uint8_t oldctrl1; + uint8_t oldctrl2, newctrl2; + + int vram_size; + uint32_t vram_mask; } tvga_t; @@ -87,9 +88,10 @@ static const uint8_t crtc_mask[0x40] = { static void tvga_recalcbanking(tvga_t *tvga); -void tvga_out(uint16_t addr, uint8_t val, void *p) +static void +tvga_out(uint16_t addr, uint8_t val, void *priv) { - tvga_t *tvga = (tvga_t *)p; + tvga_t *tvga = (tvga_t *)priv; svga_t *svga = &tvga->svga; uint8_t old; @@ -131,7 +133,7 @@ void tvga_out(uint16_t addr, uint8_t val, void *p) break; case 0x3C6: case 0x3C7: case 0x3C8: case 0x3C9: - tkd8001_ramdac_out(addr, val, &tvga->ramdac, svga); + tkd8001_ramdac_out(addr, val, svga->ramdac, svga); return; case 0x3CF: @@ -192,9 +194,9 @@ void tvga_out(uint16_t addr, uint8_t val, void *p) svga_out(addr, val, svga); } -uint8_t tvga_in(uint16_t addr, void *p) +static uint8_t tvga_in(uint16_t addr, void *priv) { - tvga_t *tvga = (tvga_t *)p; + tvga_t *tvga = (tvga_t *)priv; svga_t *svga = &tvga->svga; if (((addr&0xFFF0) == 0x3D0 || (addr&0xFFF0) == 0x3B0) && !(svga->miscout & 1)) addr ^= 0x60; @@ -219,7 +221,7 @@ uint8_t tvga_in(uint16_t addr, void *p) } break; case 0x3C6: case 0x3C7: case 0x3C8: case 0x3C9: - return tkd8001_ramdac_in(addr, &tvga->ramdac, svga); + return tkd8001_ramdac_in(addr, svga->ramdac, svga); case 0x3D4: return svga->crtcreg; case 0x3D5: @@ -234,7 +236,9 @@ uint8_t tvga_in(uint16_t addr, void *p) return svga_in(addr, svga); } -static void tvga_recalcbanking(tvga_t *tvga) + +static void +tvga_recalcbanking(tvga_t *tvga) { svga_t *svga = &tvga->svga; @@ -246,7 +250,9 @@ static void tvga_recalcbanking(tvga_t *tvga) svga->read_bank = svga->write_bank; } -void tvga_recalctimings(svga_t *svga) + +static void +tvga_recalctimings(svga_t *svga) { tvga_t *tvga = (tvga_t *)svga->p; if (!svga->rowoffset) svga->rowoffset = 0x100; /*This is the only sensible way I can see this being handled, @@ -314,77 +320,83 @@ void tvga_recalctimings(svga_t *svga) } -static void *tvga8900d_init(const device_t *info) +static void * +tvga_init(const device_t *info) { - tvga_t *tvga = malloc(sizeof(tvga_t)); - memset(tvga, 0, sizeof(tvga_t)); + tvga_t *tvga = (tvga_t *)mem_alloc(sizeof(tvga_t)); + memset(tvga, 0x00, sizeof(tvga_t)); tvga->vram_size = device_get_config_int("memory") << 10; tvga->vram_mask = tvga->vram_size - 1; - rom_init(&tvga->bios_rom, L"video/trident/tvga/trident.bin", 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + rom_init(&tvga->bios_rom, ROM_TVGA_BIOS, + 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); svga_init(&tvga->svga, tvga, tvga->vram_size, tvga_recalctimings, tvga_in, tvga_out, NULL, NULL); - + + tvga->svga.ramdac = device_add(&tkd8001_ramdac_device); + io_sethandler(0x03c0, 0x0020, tvga_in, NULL, NULL, tvga_out, NULL, NULL, tvga); return tvga; } -static int tvga8900d_available(void) -{ - return rom_present(L"video/trident/tvga/trident.bin"); -} -void tvga_close(void *p) +static void +tvga_close(void *priv) { - tvga_t *tvga = (tvga_t *)p; - + tvga_t *tvga = (tvga_t *)priv; + svga_close(&tvga->svga); - + free(tvga); } -void tvga_speed_changed(void *p) + +static void +tvga_speed_changed(void *p) { tvga_t *tvga = (tvga_t *)p; svga_recalctimings(&tvga->svga); } -void tvga_force_redraw(void *p) + +static void +tvga_force_redraw(void *p) { tvga_t *tvga = (tvga_t *)p; tvga->svga.fullchange = changeframecount; } -void tvga_add_status_info(char *s, int max_len, void *p) + +static int +tvga8900d_available(void) { - tvga_t *tvga = (tvga_t *)p; - - svga_add_status_info(s, max_len, &tvga->svga); + return rom_present(ROM_TVGA_BIOS); } + static const device_config_t tvga_config[] = { { "memory", "Memory size", CONFIG_SELECTION, "", 1024, { { - "256 kB", 256 + "256 KB", 256 }, { - "512 kB", 512 + "512 KB", 512 }, { "1 MB", 1024 }, - /*Chip supports 2mb, but drivers are buggy*/ + /*Chip supports 2MB, but drivers are buggy*/ { "" } @@ -395,17 +407,15 @@ static const device_config_t tvga_config[] = } }; -const device_t tvga8900d_device = -{ - "Trident TVGA 8900D", - DEVICE_ISA, - 0, - tvga8900d_init, - tvga_close, - NULL, - tvga8900d_available, - tvga_speed_changed, - tvga_force_redraw, - tvga_add_status_info, - tvga_config + +const device_t tvga8900d_device = { + "Trident TVGA 8900D", + DEVICE_ISA, + 0, + tvga_init, tvga_close, NULL, + tvga8900d_available, + tvga_speed_changed, + tvga_force_redraw, + NULL, + tvga_config }; diff --git a/src/devices/video/vid_vga.c b/src/devices/video/vid_vga.c index ea585cd..d13ee0b 100644 --- a/src/devices/video/vid_vga.c +++ b/src/devices/video/vid_vga.c @@ -8,7 +8,7 @@ * * IBM VGA emulation. * - * Version: @(#)vid_vga.c 1.0.6 2018/05/06 + * Version: @(#)vid_vga.c 1.0.7 2018/09/22 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -50,214 +50,190 @@ #include "vid_svga.h" -typedef struct vga_t -{ - svga_t svga; - - rom_t bios_rom; +#define BIOS_ROM_PATH L"video/ibm/vga/ibm_vga.bin" + + +typedef struct { + svga_t svga; + + rom_t bios_rom; } vga_t; -void vga_out(uint16_t addr, uint8_t val, void *p) + +static void +vga_out(uint16_t port, uint8_t val, void *priv) { - vga_t *vga = (vga_t *)p; - svga_t *svga = &vga->svga; - uint8_t old; + vga_t *dev = (vga_t *)priv; + svga_t *svga = &dev->svga; + uint8_t old; - if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) - addr ^= 0x60; + if (((port & 0xfff0) == 0x3d0 || + (port & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) + port ^= 0x60; - switch (addr) - { - case 0x3D4: - svga->crtcreg = val & 0x1f; - return; - case 0x3D5: - if ((svga->crtcreg < 7) && (svga->crtc[0x11] & 0x80)) - return; - if ((svga->crtcreg == 7) && (svga->crtc[0x11] & 0x80)) - val = (svga->crtc[7] & ~0x10) | (val & 0x10); - old = svga->crtc[svga->crtcreg]; - svga->crtc[svga->crtcreg] = val; - if (old != val) - { - if (svga->crtcreg < 0xe || svga->crtcreg > 0x10) - { - svga->fullchange = changeframecount; - svga_recalctimings(svga); - } - } - break; - } - svga_out(addr, val, svga); -} + switch (port) { + case 0x3d4: + svga->crtcreg = val & 0x3f; + return; -uint8_t vga_in(uint16_t addr, void *p) -{ - vga_t *vga = (vga_t *)p; - svga_t *svga = &vga->svga; - uint8_t temp; + case 0x3d5: + if (svga->crtcreg & 0x20) + return; + if ((svga->crtcreg < 7) && (svga->crtc[0x11] & 0x80)) + return; + if ((svga->crtcreg == 7) && (svga->crtc[0x11] & 0x80)) + val = (svga->crtc[7] & ~0x10) | (val & 0x10); + old = svga->crtc[svga->crtcreg]; + svga->crtc[svga->crtcreg] = val; + if (old != val) { + if (svga->crtcreg < 0xe || svga->crtcreg > 0x10) { + svga->fullchange = changeframecount; + svga_recalctimings(svga); + } + } + break; + } - if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) - addr ^= 0x60; - - switch (addr) - { - case 0x3D4: - temp = svga->crtcreg; - break; - case 0x3D5: - temp = svga->crtc[svga->crtcreg]; - break; - default: - temp = svga_in(addr, svga); - break; - } - return temp; + svga_out(port, val, svga); } -static void *vga_init(const device_t *info) +static uint8_t +vga_in(uint16_t port, void *priv) { - vga_t *vga = malloc(sizeof(vga_t)); - memset(vga, 0, sizeof(vga_t)); + vga_t *dev = (vga_t *)priv; + svga_t *svga = &dev->svga; + uint8_t ret; - rom_init(&vga->bios_rom, L"video/ibm/vga/ibm_vga.bin", 0xc0000, 0x8000, 0x7fff, 0x2000, MEM_MAPPING_EXTERNAL); + if (((port & 0xfff0) == 0x3d0 || + (port & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) + port ^= 0x60; - svga_init(&vga->svga, vga, 1 << 18, /*256kb*/ - NULL, - vga_in, vga_out, - NULL, - NULL); + switch (port) { + case 0x3d4: + ret = svga->crtcreg; + break; - io_sethandler(0x03c0, 0x0020, vga_in, NULL, NULL, vga_out, NULL, NULL, vga); + case 0x3d5: + if (svga->crtcreg & 0x20) + ret = 0xff; + else + ret = svga->crtc[svga->crtcreg]; + break; - vga->svga.bpp = 8; - vga->svga.miscout = 1; - - return vga; + default: + ret = svga_in(port, svga); + break; + } + + return ret; } -#ifdef DEV_BRANCH -static void *trigem_unk_init(const device_t *info) +static void * +vga_init(const device_t *info) { - vga_t *vga = malloc(sizeof(vga_t)); - memset(vga, 0, sizeof(vga_t)); + vga_t *dev; - rom_init(&vga->bios_rom, L"video/ibm/vga/ibm_vga.bin", 0xc0000, 0x8000, 0x7fff, 0x2000, MEM_MAPPING_EXTERNAL); + dev = (vga_t *)mem_alloc(sizeof(vga_t)); + memset(dev, 0x00, sizeof(vga_t)); - svga_init(&vga->svga, vga, 1 << 18, /*256kb*/ - NULL, - vga_in, vga_out, - NULL, - NULL); + switch(info->local) { + case 0: /* IBM VGA */ + rom_init(&dev->bios_rom, BIOS_ROM_PATH, + 0xc0000, 0x8000, 0x7fff, 0x2000, MEM_MAPPING_EXTERNAL); + break; - io_sethandler(0x03c0, 0x0020, vga_in, NULL, NULL, vga_out, NULL, NULL, vga); + case 1: /* IBM PS/1 VGA */ + break; + } - io_sethandler(0x22ca, 0x0002, svga_in, NULL, NULL, vga_out, NULL, NULL, vga); - io_sethandler(0x22ce, 0x0002, svga_in, NULL, NULL, vga_out, NULL, NULL, vga); - io_sethandler(0x32ca, 0x0002, svga_in, NULL, NULL, vga_out, NULL, NULL, vga); + svga_init(&dev->svga, dev, 1 << 18, /*256kb*/ + NULL, vga_in, vga_out, NULL, NULL); - vga->svga.bpp = 8; - vga->svga.miscout = 1; - - return vga; -} -#endif + io_sethandler(0x03c0, 32, + vga_in,NULL,NULL, vga_out,NULL,NULL, dev); -/*PS/1 uses a standard VGA controller, but with no option ROM*/ -void *ps1vga_init(const device_t *info) -{ - vga_t *vga = malloc(sizeof(vga_t)); - memset(vga, 0, sizeof(vga_t)); - - svga_init(&vga->svga, vga, 1 << 18, /*256kb*/ - NULL, - vga_in, vga_out, - NULL, - NULL); + dev->svga.bpp = 8; + dev->svga.miscout = 1; - io_sethandler(0x03c0, 0x0020, vga_in, NULL, NULL, vga_out, NULL, NULL, vga); - - vga->svga.bpp = 8; - vga->svga.miscout = 1; - - return vga; + return dev; } -static int vga_available(void) + +static int +vga_available(void) { - return rom_present(L"video/ibm/vga/ibm_vga.bin"); + return rom_present(BIOS_ROM_PATH); } -void vga_close(void *p) -{ - vga_t *vga = (vga_t *)p; - svga_close(&vga->svga); - - free(vga); +static void +vga_close(void *priv) +{ + vga_t *dev = (vga_t *)priv; + + svga_close(&dev->svga); + + free(dev); } -void vga_speed_changed(void *p) + +static void +speed_changed(void *priv) { - vga_t *vga = (vga_t *)p; - - svga_recalctimings(&vga->svga); + vga_t *dev = (vga_t *)priv; + + svga_recalctimings(&dev->svga); } -void vga_force_redraw(void *p) -{ - vga_t *vga = (vga_t *)p; - vga->svga.fullchange = changeframecount; +static void +force_redraw(void *priv) +{ + vga_t *dev = (vga_t *)priv; + + dev->svga.fullchange = changeframecount; } -void vga_add_status_info(char *s, int max_len, void *p) -{ - vga_t *vga = (vga_t *)p; - - svga_add_status_info(s, max_len, &vga->svga); -} -const device_t vga_device = -{ - "VGA", - DEVICE_ISA, - 0, - vga_init, - vga_close, - NULL, - vga_available, - vga_speed_changed, - vga_force_redraw, - vga_add_status_info +static video_timings_t vga_timing = {VID_ISA, 8,16,32, 8,16,32}; + +const device_t vga_device = { + "VGA", + DEVICE_ISA, + 0, + vga_init, vga_close, NULL, + vga_available, + speed_changed, + force_redraw, + &vga_timing, + NULL }; -#ifdef DEV_BRANCH -const device_t trigem_unk_device = -{ - "VGA", - DEVICE_ISA, - 0, - trigem_unk_init, - vga_close, - NULL, - vga_available, - vga_speed_changed, - vga_force_redraw, - vga_add_status_info + + +static const video_timings_t ps1vga_timing = {VID_ISA,6,8,16,6,8,16}; + +const device_t ps1vga_device = { + "PS/1 VGA", + DEVICE_ISA, + 1, + vga_init, vga_close, NULL, + NULL, + speed_changed, + force_redraw, + &ps1vga_timing, + NULL }; -#endif -const device_t ps1vga_device = -{ - "PS/1 VGA", - 0, - 0, - ps1vga_init, - vga_close, - NULL, - vga_available, - vga_speed_changed, - vga_force_redraw, - vga_add_status_info + +const device_t ps1vga_mca_device = { + "PS/1 VGA", + DEVICE_MCA, + 1, + vga_init, vga_close, NULL, + NULL, + speed_changed, + force_redraw, + &ps1vga_timing, + NULL }; diff --git a/src/devices/video/vid_voodoo.c b/src/devices/video/vid_voodoo.c index efdc9cc..6fbee9a 100644 --- a/src/devices/video/vid_voodoo.c +++ b/src/devices/video/vid_voodoo.c @@ -8,7 +8,7 @@ * * Emulation of the 3DFX Voodoo Graphics controller. * - * Version: @(#)vid_voodoo.c 1.0.10 2018/05/06 + * Version: @(#)vid_voodoo.c 1.0.11 2018/09/23 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -42,15 +42,11 @@ #include #include #include -#include #include -#ifdef _MSC_VER -# include -#endif #include #include -#define HAVE_STDARG_H #include "../../emu.h" +#undef ERROR #include "../../cpu/cpu.h" #include "../../machines/machine.h" #include "../../mem.h" @@ -108,7 +104,6 @@ static const uint32_t texture_offset[LOD_MAX+3] = static int tris = 0; -static uint64_t status_time = 0; typedef union { uint32_t i; @@ -262,7 +257,7 @@ typedef struct texture_t typedef struct voodoo_t { - mem_mapping_t mapping; + mem_map_t mapping; int pci_enable; @@ -473,7 +468,7 @@ typedef struct voodoo_set_t { voodoo_t *voodoos[2]; - mem_mapping_t snoop_mapping; + mem_map_t snoop_mapping; int nr_cards; } voodoo_set_t; @@ -1087,25 +1082,6 @@ enum #define TEXTUREMODE_LOCAL_MASK 0x00643000 #define TEXTUREMODE_LOCAL 0x00241000 -#ifdef ENABLE_VOODOO_LOG -int voodoo_do_log = ENABLE_VOODOO_LOG; -#endif - - -static void -voodoo_log(const char *fmt, ...) -{ -#ifdef ENABLE_VOODOO_LOG - va_list ap; - - if (voodoo_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); - } -#endif -} - static void voodoo_threshold_check(voodoo_t *voodoo); @@ -1223,8 +1199,8 @@ static void voodoo_recalc(voodoo_t *voodoo) voodoo->block_width += 32; voodoo->row_width = voodoo->block_width * 32 * 2; -/* voodoo_log("voodoo_recalc : front_offset %08X back_offset %08X aux_offset %08X draw_offset %08x\n", voodoo->params.front_offset, voodoo->back_offset, voodoo->params.aux_offset, voodoo->params.draw_offset); - voodoo_log(" fb_read_offset %08X fb_write_offset %08X row_width %i %08x %08x\n", voodoo->fb_read_offset, voodoo->fb_write_offset, voodoo->row_width, voodoo->lfbMode, voodoo->params.fbzMode);*/ +/* DEBUG("voodoo_recalc : front_offset %08X back_offset %08X aux_offset %08X draw_offset %08x\n", voodoo->params.front_offset, voodoo->back_offset, voodoo->params.aux_offset, voodoo->params.draw_offset); + DEBUG(" fb_read_offset %08X fb_write_offset %08X row_width %i %08x %08x\n", voodoo->fb_read_offset, voodoo->fb_write_offset, voodoo->row_width, voodoo->lfbMode, voodoo->params.fbzMode);*/ } static void voodoo_recalc_tex(voodoo_t *voodoo, int tmu) @@ -1400,7 +1376,7 @@ static void use_texture(voodoo_t *voodoo, voodoo_params_t *params, int tmu) lod_min = (params->tLOD[tmu] >> 2) & 15; lod_max = (params->tLOD[tmu] >> 8) & 15; -// voodoo_log(" add new texture to %i tformat=%i %08x LOD=%i-%i tmu=%i\n", c, voodoo->params.tformat[tmu], params->texBaseAddr[tmu], lod_min, lod_max, tmu); +// DEBUG(" add new texture to %i tformat=%i %08x LOD=%i-%i tmu=%i\n", c, voodoo->params.tformat[tmu], params->texBaseAddr[tmu], lod_min, lod_max, tmu); lod_min = MIN(lod_min, 8); lod_max = MIN(lod_max, 8); @@ -1412,7 +1388,7 @@ static void use_texture(voodoo_t *voodoo, voodoo_params_t *params, int tmu) int shift = 8 - params->tex_lod[tmu][lod]; rgba_u *pal; - //voodoo_log(" LOD %i : %08x - %08x %i %i,%i\n", lod, params->tex_base[tmu][lod] & voodoo->texture_mask, addr, voodoo->params.tformat[tmu], voodoo->params.tex_w_mask[tmu][lod],voodoo->params.tex_h_mask[tmu][lod]); + //DEBUG(" LOD %i : %08x - %08x %i %i,%i\n", lod, params->tex_base[tmu][lod] & voodoo->texture_mask, addr, voodoo->params.tformat[tmu], voodoo->params.tex_w_mask[tmu][lod],voodoo->params.tex_h_mask[tmu][lod]); switch (params->tformat[tmu]) @@ -1690,7 +1666,7 @@ static void flush_texture_cache(voodoo_t *voodoo, uint32_t dirty_addr, int tmu) int c; memset(voodoo->texture_present[tmu], 0, sizeof(voodoo->texture_present[0])); -// voodoo_log("Evict %08x %i\n", dirty_addr, sizeof(voodoo->texture_present)); +// DEBUG("Evict %08x %i\n", dirty_addr, sizeof(voodoo->texture_present)); for (c = 0; c < TEX_CACHE_MAX; c++) { if (voodoo->texture_cache[tmu][c].base != -1) @@ -1711,7 +1687,7 @@ static void flush_texture_cache(voodoo_t *voodoo, uint32_t dirty_addr, int tmu) addr_end_masked = voodoo->texture_mask+1; if (dirty_addr >= addr_start_masked && dirty_addr < addr_end_masked) { -// voodoo_log(" Evict texture %i %08x\n", c, voodoo->texture_cache[tmu][c].base); +// DEBUG(" Evict texture %i %08x\n", c, voodoo->texture_cache[tmu][c].base); if (voodoo->texture_cache[tmu][c].refcount != voodoo->texture_cache[tmu][c].refcount_r[0] || (voodoo->render_threads == 2 && voodoo->texture_cache[tmu][c].refcount != voodoo->texture_cache[tmu][c].refcount_r[1])) @@ -1860,7 +1836,7 @@ static inline int voodoo_fls(uint16_t val) { int num = 0; -//voodoo_log("fls(%04x) = ", val); +//DEBUG("fls(%04x) = ", val); if (!(val & 0xff00)) { num += 8; @@ -1881,7 +1857,7 @@ static inline int voodoo_fls(uint16_t val) num += 1; val <<= 1; } -//voodoo_log("%i %04x\n", num, val); +//DEBUG("%i %04x\n", num, val); return num; } @@ -2024,7 +2000,7 @@ static inline void voodoo_get_texture(voodoo_t *voodoo, voodoo_params_t *params, t >>= 4; //if (x == 80) //if (voodoo_output) -// voodoo_log("s=%08x t=%08x _ds=%02x _dt=%02x\n", s, t, __ds, dt); +// DEBUG("s=%08x t=%08x _ds=%02x _dt=%02x\n", s, t, __ds, dt); d[0] = (16 - __ds) * (16 - dt); d[1] = __ds * (16 - dt); d[2] = (16 - __ds) * dt; @@ -2702,17 +2678,17 @@ static inline void voodoo_tmu_fetch_and_blend(voodoo_t *voodoo, voodoo_params_t } #ifdef _WIN32 -#if ((defined(i386) || defined(__i386) || defined(__i386__) || defined(_X86_) || defined(_WIN32)) && !(defined(__amd64__)) && (defined(USE_DYNAREC))) -#include "vid_voodoo_codegen_x86.h" -#elif ((defined(__amd64__)) && (defined(USE_DYNAREC))) -#include "vid_voodoo_codegen_x86-64.h" -#else -#define NO_CODEGEN +# if ((defined(i386) || defined(__i386) || defined(__i386__) || defined(_X86_) || defined(_WIN32)) && !(defined(__amd64__)) && (defined(USE_DYNAREC))) +# include "vid_voodoo_codegen_x86.h" +# elif ((defined(__amd64__)) && (defined(USE_DYNAREC))) +# include "vid_voodoo_codegen_x86-64.h" +# else +# define NO_CODEGEN static int voodoo_recomp = 0; -#endif +# endif #else -#define NO_CODEGEN -static int voodoo_recomp = 0; +# define NO_CODEGEN +//static int voodoo_recomp = 0; #endif static void voodoo_half_triangle(voodoo_t *voodoo, voodoo_params_t *params, voodoo_state_t *state, int ystart, int yend, int odd_even) @@ -2760,7 +2736,7 @@ static void voodoo_half_triangle(voodoo_t *voodoo, voodoo_params_t *params, vood state->clamp_s[1] = params->textureMode[1] & TEXTUREMODE_TCLAMPS; state->clamp_t[1] = params->textureMode[1] & TEXTUREMODE_TCLAMPT; // int last_x; -// voodoo_log("voodoo_triangle : bottom-half %X %X %X %X %X %i %i %i %i\n", xstart, xend, dx1, dx2, dx2 * 36, xdir, y, yend, ydir); +// DEBUG("voodoo_triangle : bottom-half %X %X %X %X %X %i %i %i %i\n", xstart, xend, dx1, dx2, dx2 * 36, xdir, y, yend, ydir); for (c = 0; c <= LOD_MAX; c++) { @@ -2839,20 +2815,23 @@ static void voodoo_half_triangle(voodoo_t *voodoo, voodoo_params_t *params, vood } #ifndef NO_CODEGEN if (voodoo->use_recompiler) - voodoo_draw = voodoo_get_block(voodoo, params, state, odd_even); + voodoo_draw = (uint8_t (*)(voodoo_state_t *,voodoo_params_t *,int,int))voodoo_get_block(voodoo, params, state, odd_even); else voodoo_draw = NULL; #endif if (voodoo_output) - voodoo_log("dxAB=%08x dxBC=%08x dxAC=%08x\n", state->dxAB, state->dxBC, state->dxAC); -// voodoo_log("Start %i %i\n", ystart, voodoo->fbzMode & (1 << 17)); + DEBUG("dxAB=%08x dxBC=%08x dxAC=%08x\n", state->dxAB, state->dxBC, state->dxAC); +// DEBUG("Start %i %i\n", ystart, voodoo->fbzMode & (1 << 17)); for (; state->y < yend; state->y += y_diff) { int x, x2; int real_y = (state->y << 4) + 8; - int start_x, start_x2; + int start_x; +#ifdef _LOGGING + int start_x2; +#endif int dx; uint16_t *fb_mem, *aux_mem; @@ -2899,12 +2878,14 @@ static void voodoo_half_triangle(voodoo_t *voodoo, voodoo_params_t *params, vood else x -= (1 << 16); dx = ((x + 0x7000) >> 16) - (((state->vertexAx << 12) + 0x7000) >> 16); +#ifdef _LOGGING start_x2 = x + 0x7000; +#endif x = (x + 0x7000) >> 16; x2 = (x2 + 0x7000) >> 16; if (voodoo_output) - voodoo_log("%03i:%03i : Ax=%08x start_x=%08x dSdX=%016llx dx=%08x s=%08x -> ", x, state->y, state->vertexAx << 8, start_x, params->tmu[0].dTdX, dx, state->tmu0_t); + DEBUG("%03i:%03i : Ax=%08x start_x=%08x dSdX=%016llx dx=%08x s=%08x -> ", x, state->y, state->vertexAx << 8, start_x, params->tmu[0].dTdX, dx, state->tmu0_t); state->ir += (params->dRdX * dx); state->ig += (params->dGdX * dx); @@ -2920,7 +2901,7 @@ static void voodoo_half_triangle(voodoo_t *voodoo, voodoo_params_t *params, vood state->w += (params->dWdX * dx); if (voodoo_output) - voodoo_log("%08llx %lli %lli\n", state->tmu0_t, state->tmu0_t >> (18+state->lod), (state->tmu0_t + (1ULL << (17+state->lod))) >> (18+state->lod)); + DEBUG("%08llx %lli %lli\n", state->tmu0_t, state->tmu0_t >> (18+state->lod), (state->tmu0_t + (1ULL << (17+state->lod))) >> (18+state->lod)); if (params->fbzMode & 1) { @@ -2991,7 +2972,7 @@ static void voodoo_half_triangle(voodoo_t *voodoo, voodoo_params_t *params, vood } if (voodoo_output) - voodoo_log("%03i: x=%08x x2=%08x xstart=%08x xend=%08x dx=%08x start_x2=%08x\n", state->y, x, x2, state->xstart, state->xend, dx, start_x2); + DEBUG("%03i: x=%08x x2=%08x xstart=%08x xend=%08x dx=%08x start_x2=%08x\n", state->y, x, x2, state->xstart, state->xend, dx, start_x2); state->pixel_count = 0; state->texel_count = 0; @@ -3013,7 +2994,7 @@ static void voodoo_half_triangle(voodoo_t *voodoo, voodoo_params_t *params, vood voodoo->fbiPixelsIn++; if (voodoo_output) - voodoo_log(" X=%03i T=%08x\n", x, state->tmu0_t); + DEBUG(" X=%03i T=%08x\n", x, state->tmu0_t); // if (voodoo->fbzMode & FBZ_RGB_WMASK) { int update = 1; @@ -3475,7 +3456,7 @@ static void voodoo_triangle(voodoo_t *voodoo, voodoo_params_t *params, int odd_e if ((params->vertexAy & 0xf) > 8) dy += 16; -/* voodoo_log("voodoo_triangle %i %i %i : vA %f, %f vB %f, %f vC %f, %f f %i,%i %08x %08x %08x,%08x tex=%i,%i fogMode=%08x\n", odd_even, voodoo->params_read_idx[odd_even], voodoo->params_read_idx[odd_even] & PARAM_MASK, (float)params->vertexAx / 16.0, (float)params->vertexAy / 16.0, +/* DEBUG("voodoo_triangle %i %i %i : vA %f, %f vB %f, %f vC %f, %f f %i,%i %08x %08x %08x,%08x tex=%i,%i fogMode=%08x\n", odd_even, voodoo->params_read_idx[odd_even], voodoo->params_read_idx[odd_even] & PARAM_MASK, (float)params->vertexAx / 16.0, (float)params->vertexAy / 16.0, (float)params->vertexBx / 16.0, (float)params->vertexBy / 16.0, (float)params->vertexCx / 16.0, (float)params->vertexCy / 16.0, (params->fbzColorPath & FBZCP_TEXTURE_ENABLED) ? params->tformat[0] : 0, @@ -4062,7 +4043,7 @@ static void blit_start(voodoo_t *voodoo) uint32_t dst_base_addr = (voodoo->bltCommand & BLTCMD_DST_TILED) ? ((voodoo->bltDstBaseAddr & 0x3ff) << 12) : (voodoo->bltDstBaseAddr & 0x3ffff8); int x, y; -/* voodoo_log("blit_start: command=%08x srcX=%i srcY=%i dstX=%i dstY=%i sizeX=%i sizeY=%i color=%04x,%04x\n", +/* DEBUG("blit_start: command=%08x srcX=%i srcY=%i dstX=%i dstY=%i sizeX=%i sizeY=%i color=%04x,%04x\n", voodoo->bltCommand, voodoo->bltSrcX, voodoo->bltSrcY, voodoo->bltDstX, voodoo->bltDstY, voodoo->bltSizeX, voodoo->bltSizeY, voodoo->bltColorFg, voodoo->bltColorBg);*/ wait_for_render_thread_idle(voodoo); @@ -4401,7 +4382,7 @@ static void voodoo_reg_writel(uint32_t addr, uint32_t val, void *priv) chip = 0xf; tempif.i = val; -//voodoo_log("voodoo_reg_write_l: addr=%08x val=%08x(%f) chip=%x\n", addr, val, tempif.f, chip); +//DEBUG("voodoo_reg_write_l: addr=%08x val=%08x(%f) chip=%x\n", addr, val, tempif.f, chip); addr &= 0x3fc; if ((voodoo->fbiInit3 & FBIINIT3_REMAP) && addr < 0x100 && ad21) @@ -4409,7 +4390,7 @@ static void voodoo_reg_writel(uint32_t addr, uint32_t val, void *priv) switch (addr) { case SST_swapbufferCMD: -// voodoo_log(" start swap buffer command\n"); +// DEBUG(" start swap buffer command\n"); if (TRIPLE_BUFFER) { @@ -4425,7 +4406,7 @@ static void voodoo_reg_writel(uint32_t addr, uint32_t val, void *priv) voodoo->params.swapbufferCMD = val; - voodoo_log("Swap buffer %08x %d %p %i\n", val, voodoo->swap_count, &voodoo->swap_count, (voodoo == voodoo->set->voodoos[1]) ? 1 : 0); + DEBUG("Swap buffer %08x %d %p %i\n", val, voodoo->swap_count, &voodoo->swap_count, (voodoo == voodoo->set->voodoos[1]) ? 1 : 0); // voodoo->front_offset = params->front_offset; wait_for_render_thread_idle(voodoo); if (!(val & 1)) @@ -4885,12 +4866,12 @@ static void voodoo_reg_writel(uint32_t addr, uint32_t val, void *priv) case SST_sVx: tempif.i = val; voodoo->verts[3].sVx = tempif.f; -// voodoo_log("sVx[%i]=%f\n", voodoo->vertex_num, tempif.f); +// DEBUG("sVx[%i]=%f\n", voodoo->vertex_num, tempif.f); break; case SST_sVy: tempif.i = val; voodoo->verts[3].sVy = tempif.f; -// voodoo_log("sVy[%i]=%f\n", voodoo->vertex_num, tempif.f); +// DEBUG("sVy[%i]=%f\n", voodoo->vertex_num, tempif.f); break; case SST_sARGB: voodoo->verts[3].sBlue = (float)(val & 0xff); @@ -4948,13 +4929,13 @@ static void voodoo_reg_writel(uint32_t addr, uint32_t val, void *priv) break; case SST_sBeginTriCMD: -// voodoo_log("sBeginTriCMD %i %f\n", voodoo->vertex_num, voodoo->verts[4].sVx); +// DEBUG("sBeginTriCMD %i %f\n", voodoo->vertex_num, voodoo->verts[4].sVx); voodoo->verts[0] = voodoo->verts[3]; voodoo->vertex_num = 1; voodoo->num_verticies = 1; break; case SST_sDrawTriCMD: -// voodoo_log("sDrawTriCMD %i %i %i\n", voodoo->num_verticies, voodoo->vertex_num, voodoo->sSetupMode & SETUPMODE_STRIP_MODE); +// DEBUG("sDrawTriCMD %i %i %i\n", voodoo->num_verticies, voodoo->vertex_num, voodoo->sSetupMode & SETUPMODE_STRIP_MODE); if (voodoo->vertex_num == 3) voodoo->vertex_num = (voodoo->sSetupMode & SETUPMODE_STRIP_MODE) ? 1 : 0; voodoo->verts[voodoo->vertex_num] = voodoo->verts[3]; @@ -4963,7 +4944,7 @@ static void voodoo_reg_writel(uint32_t addr, uint32_t val, void *priv) voodoo->vertex_num++; if (voodoo->num_verticies == 3) { -// voodoo_log("triangle_setup\n"); +// DEBUG("triangle_setup\n"); triangle_setup(voodoo); voodoo->num_verticies = 2; @@ -4976,13 +4957,13 @@ static void voodoo_reg_writel(uint32_t addr, uint32_t val, void *priv) voodoo->bltSrcBaseAddr = val & 0x3fffff; break; case SST_bltDstBaseAddr: -// voodoo_log("Write bltDstBaseAddr %08x\n", val); +// DEBUG("Write bltDstBaseAddr %08x\n", val); voodoo->bltDstBaseAddr = val & 0x3fffff; break; case SST_bltXYStrides: voodoo->bltSrcXYStride = val & 0xfff; voodoo->bltDstXYStride = (val >> 16) & 0xfff; -// voodoo_log("Write bltXYStrides %08x\n", val); +// DEBUG("Write bltXYStrides %08x\n", val); break; case SST_bltSrcChromaRange: voodoo->bltSrcChromaRange = val; @@ -5016,14 +4997,14 @@ static void voodoo_reg_writel(uint32_t addr, uint32_t val, void *priv) voodoo->bltSrcY = (val >> 16) & 0x7ff; break; case SST_bltDstXY: -// voodoo_log("Write bltDstXY %08x\n", val); +// DEBUG("Write bltDstXY %08x\n", val); voodoo->bltDstX = val & 0x7ff; voodoo->bltDstY = (val >> 16) & 0x7ff; if (val & (1 << 31)) blit_start(voodoo); break; case SST_bltSize: -// voodoo_log("Write bltSize %08x\n", val); +// DEBUG("Write bltSize %08x\n", val); voodoo->bltSizeX = val & 0xfff; if (voodoo->bltSizeX & 0x800) voodoo->bltSizeX |= 0xfffff000; @@ -5040,14 +5021,14 @@ static void voodoo_reg_writel(uint32_t addr, uint32_t val, void *priv) voodoo->bltRop[3] = (val >> 12) & 0xf; break; case SST_bltColor: -// voodoo_log("Write bltColor %08x\n", val); +// DEBUG("Write bltColor %08x\n", val); voodoo->bltColorFg = val & 0xffff; voodoo->bltColorBg = (val >> 16) & 0xffff; break; case SST_bltCommand: voodoo->bltCommand = val; -// voodoo_log("Write bltCommand %08x\n", val); +// DEBUG("Write bltCommand %08x\n", val); if (val & (1 << 31)) blit_start(voodoo); break; @@ -5531,7 +5512,7 @@ static uint16_t voodoo_fb_readw(uint32_t addr, void *p) temp = *(uint16_t *)(&voodoo->fb_mem[read_addr & voodoo->fb_mask]); -// voodoo_log("voodoo_fb_readw : %08X %08X %i %i %08X %08X %08x:%08x %i\n", addr, temp, x, y, read_addr, *(uint32_t *)(&voodoo->fb_mem[4]), cs, pc, fb_reads++); +// DEBUG("voodoo_fb_readw : %08X %08X %i %i %08X %08X %08x:%08x %i\n", addr, temp, x, y, read_addr, *(uint32_t *)(&voodoo->fb_mem[4]), cs, pc, fb_reads++); return temp; } static uint32_t voodoo_fb_readl(uint32_t addr, void *p) @@ -5563,7 +5544,7 @@ static uint32_t voodoo_fb_readl(uint32_t addr, void *p) temp = *(uint32_t *)(&voodoo->fb_mem[read_addr & voodoo->fb_mask]); -// voodoo_log("voodoo_fb_readl : %08X %08x %08X x=%i y=%i %08X %08X %08x:%08x %i ro=%08x rw=%i\n", addr, read_addr, temp, x, y, read_addr, *(uint32_t *)(&voodoo->fb_mem[4]), cs, pc, fb_reads++, voodoo->fb_read_offset, voodoo->row_width); +// DEBUG("voodoo_fb_readl : %08X %08x %08X x=%i y=%i %08X %08X %08x:%08x %i ro=%08x rw=%i\n", addr, read_addr, temp, x, y, read_addr, *(uint32_t *)(&voodoo->fb_mem[4]), cs, pc, fb_reads++, voodoo->fb_read_offset, voodoo->row_width); return temp; } @@ -5615,7 +5596,7 @@ static void voodoo_fb_writew(uint32_t addr, uint16_t val, void *p) // while (!RB_EMPTY) // thread_reset_event(voodoo->not_full_event); -// voodoo_log("voodoo_fb_writew : %08X %04X\n", addr, val); +// DEBUG("voodoo_fb_writew : %08X %04X\n", addr, val); switch (voodoo->lfbMode & LFB_FORMAT_MASK) @@ -5662,7 +5643,7 @@ static void voodoo_fb_writew(uint32_t addr, uint16_t val, void *p) write_addr = voodoo->fb_write_offset + x + (y * voodoo->row_width); write_addr_aux = voodoo->params.aux_offset + x + (y * voodoo->row_width); -// voodoo_log("fb_writew %08x %i %i %i %08x\n", addr, x, y, voodoo->row_width, write_addr); +// DEBUG("fb_writew %08x %i %i %i %08x\n", addr, x, y, voodoo->row_width, write_addr); if (voodoo->lfbMode & 0x100) { @@ -5746,7 +5727,7 @@ static void voodoo_fb_writel(uint32_t addr, uint32_t val, void *p) // while (!RB_EMPTY) // thread_reset_event(voodoo->not_full_event); -// voodoo_log("voodoo_fb_writel : %08X %08X\n", addr, val); +// DEBUG("voodoo_fb_writel : %08X %08X\n", addr, val); switch (voodoo->lfbMode & LFB_FORMAT_MASK) { @@ -5808,7 +5789,7 @@ static void voodoo_fb_writel(uint32_t addr, uint32_t val, void *p) write_addr = voodoo->fb_write_offset + x + (y * voodoo->row_width); write_addr_aux = voodoo->params.aux_offset + x + (y * voodoo->row_width); -// voodoo_log("fb_writel %08x x=%i y=%i rw=%i %08x wo=%08x\n", addr, x, y, voodoo->row_width, write_addr, voodoo->fb_write_offset); +// DEBUG("fb_writel %08x x=%i y=%i rw=%i %08x wo=%08x\n", addr, x, y, voodoo->row_width, write_addr, voodoo->fb_write_offset); if (voodoo->lfbMode & 0x100) { @@ -5901,7 +5882,7 @@ static void voodoo_tex_writel(uint32_t addr, uint32_t val, void *p) if (tmu && !voodoo->dual_tmus) return; -// voodoo_log("voodoo_tex_writel : %08X %08X %i\n", addr, val, voodoo->params.tformat); +// DEBUG("voodoo_tex_writel : %08X %08X %i\n", addr, val, voodoo->params.tformat); lod = (addr >> 17) & 0xf; t = (addr >> 9) & 0xff; @@ -5927,7 +5908,7 @@ static void voodoo_tex_writel(uint32_t addr, uint32_t val, void *p) addr = voodoo->params.tex_base[tmu][lod] + s + (t << voodoo->params.tex_shift[tmu][lod]); if (voodoo->texture_present[tmu][(addr & voodoo->texture_mask) >> TEX_DIRTY_SHIFT]) { -// voodoo_log("texture_present at %08x %i\n", addr, (addr & voodoo->texture_mask) >> TEX_DIRTY_SHIFT); +// DEBUG("texture_present at %08x %i\n", addr, (addr & voodoo->texture_mask) >> TEX_DIRTY_SHIFT); flush_texture_cache(voodoo, addr & voodoo->texture_mask, tmu); } *(uint32_t *)(&voodoo->tex_mem[tmu][addr & voodoo->texture_mask]) = val; @@ -6279,7 +6260,7 @@ static void voodoo_pixelclock_update(voodoo_t *voodoo) line_length = (voodoo->hSync & 0xff) + ((voodoo->hSync >> 16) & 0x3ff); -// voodoo_log("Pixel clock %f MHz hsync %08x line_length %d\n", t, voodoo->hSync, line_length); +// DEBUG("Pixel clock %f MHz hsync %08x line_length %d\n", t, voodoo->hSync, line_length); voodoo->pixel_clock = t; @@ -6312,7 +6293,7 @@ static void voodoo_writel(uint32_t addr, uint32_t val, void *p) } else if ((addr & 0x200000) && (voodoo->fbiInit7 & FBIINIT7_CMDFIFO_ENABLE)) { -// voodoo_log("Write CMDFIFO %08x(%08x) %08x %08x\n", addr, voodoo->cmdfifo_base + (addr & 0x3fffc), val, (voodoo->cmdfifo_base + (addr & 0x3fffc)) & voodoo->fb_mask); +// DEBUG("Write CMDFIFO %08x(%08x) %08x %08x\n", addr, voodoo->cmdfifo_base + (addr & 0x3fffc), val, (voodoo->cmdfifo_base + (addr & 0x3fffc)) & voodoo->fb_mask); *(uint32_t *)&voodoo->fb_mem[(voodoo->cmdfifo_base + (addr & 0x3fffc)) & voodoo->fb_mask] = val; voodoo->cmdfifo_depth_wr++; if ((voodoo->cmdfifo_depth_wr - voodoo->cmdfifo_depth_rd) < 20) @@ -6375,7 +6356,7 @@ static void voodoo_writel(uint32_t addr, uint32_t val, void *p) { voodoo->fbiInit4 = val; voodoo->read_time = pci_nonburst_time + pci_burst_time * ((voodoo->fbiInit4 & 1) ? 2 : 1); -// voodoo_log("fbiInit4 write %08x - read_time=%i\n", val, voodoo->read_time); +// DEBUG("fbiInit4 write %08x - read_time=%i\n", val, voodoo->read_time); } break; case SST_backPorch: @@ -6417,7 +6398,7 @@ static void voodoo_writel(uint32_t addr, uint32_t val, void *p) voodoo->fbiInit1 = (val & ~5) | (voodoo->fbiInit1 & 5); voodoo->write_time = pci_nonburst_time + pci_burst_time * ((voodoo->fbiInit1 & 2) ? 1 : 0); voodoo->burst_time = pci_burst_time * ((voodoo->fbiInit1 & 2) ? 2 : 1); -// voodoo_log("fbiInit1 write %08x - write_time=%i burst_time=%i\n", val, voodoo->write_time, voodoo->burst_time); +// DEBUG("fbiInit1 write %08x - write_time=%i burst_time=%i\n", val, voodoo->write_time, voodoo->burst_time); } break; case SST_fbiInit2: @@ -6460,7 +6441,7 @@ static void voodoo_writel(uint32_t addr, uint32_t val, void *p) voodoo->dac_readdata = 0xff; if (val & 0x800) { -// voodoo_log(" dacData read %i %02X\n", voodoo->dac_reg, voodoo->dac_data[7]); +// DEBUG(" dacData read %i %02X\n", voodoo->dac_reg, voodoo->dac_data[7]); if (voodoo->dac_reg == 5) { switch (voodoo->dac_data[7]) @@ -6481,7 +6462,7 @@ static void voodoo_writel(uint32_t addr, uint32_t val, void *p) voodoo->dac_pll_regs[voodoo->dac_data[4] & 0xf] = (voodoo->dac_pll_regs[voodoo->dac_data[4] & 0xf] & 0xff00) | val; else voodoo->dac_pll_regs[voodoo->dac_data[4] & 0xf] = (voodoo->dac_pll_regs[voodoo->dac_data[4] & 0xf] & 0xff) | (val << 8); -// voodoo_log("Write PLL reg %x %04x\n", voodoo->dac_data[4] & 0xf, voodoo->dac_pll_regs[voodoo->dac_data[4] & 0xf]); +// DEBUG("Write PLL reg %x %04x\n", voodoo->dac_data[4] & 0xf, voodoo->dac_pll_regs[voodoo->dac_data[4] & 0xf]); voodoo->dac_reg_ff = !voodoo->dac_reg_ff; if (!voodoo->dac_reg_ff) voodoo->dac_data[4]++; @@ -6505,7 +6486,7 @@ static void voodoo_writel(uint32_t addr, uint32_t val, void *p) if (val < 1) voodoo->scrfilterEnabled = 0; voodoo_threshold_check(voodoo); - voodoo_log("Voodoo Filter: %06x\n", val); + DEBUG("Voodoo Filter: %06x\n", val); } break; @@ -6525,7 +6506,7 @@ static void voodoo_writel(uint32_t addr, uint32_t val, void *p) case SST_cmdFifoBaseAddr: voodoo->cmdfifo_base = (val & 0x3ff) << 12; voodoo->cmdfifo_end = ((val >> 16) & 0x3ff) << 12; -// voodoo_log("CMDFIFO base=%08x end=%08x\n", voodoo->cmdfifo_base, voodoo->cmdfifo_end); +// DEBUG("CMDFIFO base=%08x end=%08x\n", voodoo->cmdfifo_base, voodoo->cmdfifo_end); break; case SST_cmdFifoRdPtr: @@ -6545,7 +6526,7 @@ static void voodoo_writel(uint32_t addr, uint32_t val, void *p) default: if (voodoo->fbiInit7 & FBIINIT7_CMDFIFO_ENABLE) { - voodoo_log("Unknown register write in CMDFIFO mode %08x %08x\n", addr, val); + DEBUG("Unknown register write in CMDFIFO mode %08x %08x\n", addr, val); } else { @@ -6598,7 +6579,7 @@ static uint32_t cmdfifo_get(voodoo_t *voodoo) voodoo->cmdfifo_depth_rd++; voodoo->cmdfifo_rp += 4; -// voodoo_log(" CMDFIFO get %08x\n", val); +// DEBUG(" CMDFIFO get %08x\n", val); return val; } @@ -6684,12 +6665,12 @@ static void fifo_thread(void *param) int num_verticies; int v_num; -// voodoo_log(" CMDFIFO header %08x at %08x\n", header, voodoo->cmdfifo_rp); +// DEBUG(" CMDFIFO header %08x at %08x\n", header, voodoo->cmdfifo_rp); switch (header & 7) { case 0: -// voodoo_log("CMDFIFO0\n"); +// DEBUG("CMDFIFO0\n"); switch ((header >> 3) & 7) { case 0: /*NOP*/ @@ -6697,7 +6678,7 @@ static void fifo_thread(void *param) case 3: /*JMP local frame buffer*/ voodoo->cmdfifo_rp = (header >> 4) & 0xfffffc; -// voodoo_log("JMP to %08x %04x\n", voodoo->cmdfifo_rp, header); +// DEBUG("JMP to %08x %04x\n", voodoo->cmdfifo_rp, header); break; default: @@ -6708,7 +6689,7 @@ static void fifo_thread(void *param) case 1: num = header >> 16; addr = (header & 0x7ff8) >> 1; -// voodoo_log("CMDFIFO1 addr=%08x\n",addr); +// DEBUG("CMDFIFO1 addr=%08x\n",addr); while (num--) { uint32_t val = cmdfifo_get(voodoo); @@ -6732,8 +6713,8 @@ static void fifo_thread(void *param) v_num = 0; if (((header >> 3) & 7) == 2) v_num = 1; -// voodoo_log("CMDFIFO3: num=%i verts=%i mask=%02x\n", num, num_verticies, (header >> 10) & 0xff); -// voodoo_log("CMDFIFO3 %02x %i\n", (header >> 10), (header >> 3) & 7); +// DEBUG("CMDFIFO3: num=%i verts=%i mask=%02x\n", num, num_verticies, (header >> 10) & 0xff); +// DEBUG("CMDFIFO3 %02x %i\n", (header >> 10), (header >> 3) & 7); while (num_verticies--) { @@ -6790,7 +6771,7 @@ static void fifo_thread(void *param) num = (header >> 29) & 7; mask = (header >> 15) & 0x3fff; addr = (header & 0x7ff8) >> 1; -// voodoo_log("CMDFIFO4 addr=%08x\n",addr); +// DEBUG("CMDFIFO4 addr=%08x\n",addr); while (mask) { if (mask & 1) @@ -6815,7 +6796,7 @@ static void fifo_thread(void *param) fatal("CMDFIFO packet 5 has byte disables set %08x\n", header); num = (header >> 3) & 0x7ffff; addr = cmdfifo_get(voodoo) & 0xffffff; -// voodoo_log("CMDFIFO5 addr=%08x num=%i\n", addr, num); +// DEBUG("CMDFIFO5 addr=%08x num=%i\n", addr, num); switch (header >> 30) { case 2: /*Framebuffer*/ @@ -6841,7 +6822,7 @@ static void fifo_thread(void *param) break; default: - voodoo_log("Bad CMDFIFO packet %08x %08x\n", header, voodoo->cmdfifo_rp); + DEBUG("Bad CMDFIFO packet %08x %08x\n", header, voodoo->cmdfifo_rp); } end_time = plat_timer_read(); @@ -6859,40 +6840,40 @@ static void voodoo_recalcmapping(voodoo_set_t *set) { if (set->voodoos[0]->type == VOODOO_2 && set->voodoos[1]->initEnable & (1 << 23)) { - voodoo_log("voodoo_recalcmapping (pri) with snoop : memBaseAddr %08X\n", set->voodoos[0]->memBaseAddr); - mem_mapping_disable(&set->voodoos[0]->mapping); - mem_mapping_set_addr(&set->snoop_mapping, set->voodoos[0]->memBaseAddr, 0x01000000); + DEBUG("voodoo_recalcmapping (pri) with snoop : memBaseAddr %08X\n", set->voodoos[0]->memBaseAddr); + mem_map_disable(&set->voodoos[0]->mapping); + mem_map_set_addr(&set->snoop_mapping, set->voodoos[0]->memBaseAddr, 0x01000000); } else if (set->voodoos[1]->pci_enable && (set->voodoos[0]->memBaseAddr == set->voodoos[1]->memBaseAddr)) { - voodoo_log("voodoo_recalcmapping (pri) (sec) same addr : memBaseAddr %08X\n", set->voodoos[0]->memBaseAddr); - mem_mapping_disable(&set->voodoos[0]->mapping); - mem_mapping_disable(&set->voodoos[1]->mapping); - mem_mapping_set_addr(&set->snoop_mapping, set->voodoos[0]->memBaseAddr, 0x01000000); + DEBUG("voodoo_recalcmapping (pri) (sec) same addr : memBaseAddr %08X\n", set->voodoos[0]->memBaseAddr); + mem_map_disable(&set->voodoos[0]->mapping); + mem_map_disable(&set->voodoos[1]->mapping); + mem_map_set_addr(&set->snoop_mapping, set->voodoos[0]->memBaseAddr, 0x01000000); return; } else { - voodoo_log("voodoo_recalcmapping (pri) : memBaseAddr %08X\n", set->voodoos[0]->memBaseAddr); - mem_mapping_disable(&set->snoop_mapping); - mem_mapping_set_addr(&set->voodoos[0]->mapping, set->voodoos[0]->memBaseAddr, 0x01000000); + DEBUG("voodoo_recalcmapping (pri) : memBaseAddr %08X\n", set->voodoos[0]->memBaseAddr); + mem_map_disable(&set->snoop_mapping); + mem_map_set_addr(&set->voodoos[0]->mapping, set->voodoos[0]->memBaseAddr, 0x01000000); } } else { - voodoo_log("voodoo_recalcmapping (pri) : disabled\n"); - mem_mapping_disable(&set->voodoos[0]->mapping); + DEBUG("voodoo_recalcmapping (pri) : disabled\n"); + mem_map_disable(&set->voodoos[0]->mapping); } if (set->voodoos[1]->pci_enable && set->voodoos[1]->memBaseAddr) { - voodoo_log("voodoo_recalcmapping (sec) : memBaseAddr %08X\n", set->voodoos[1]->memBaseAddr); - mem_mapping_set_addr(&set->voodoos[1]->mapping, set->voodoos[1]->memBaseAddr, 0x01000000); + DEBUG("voodoo_recalcmapping (sec) : memBaseAddr %08X\n", set->voodoos[1]->memBaseAddr); + mem_map_set_addr(&set->voodoos[1]->mapping, set->voodoos[1]->memBaseAddr, 0x01000000); } else { - voodoo_log("voodoo_recalcmapping (sec) : disabled\n"); - mem_mapping_disable(&set->voodoos[1]->mapping); + DEBUG("voodoo_recalcmapping (sec) : disabled\n"); + mem_map_disable(&set->voodoos[1]->mapping); } } else @@ -6901,13 +6882,13 @@ static void voodoo_recalcmapping(voodoo_set_t *set) if (voodoo->pci_enable && voodoo->memBaseAddr) { - voodoo_log("voodoo_recalcmapping : memBaseAddr %08X\n", voodoo->memBaseAddr); - mem_mapping_set_addr(&voodoo->mapping, voodoo->memBaseAddr, 0x01000000); + DEBUG("voodoo_recalcmapping : memBaseAddr %08X\n", voodoo->memBaseAddr); + mem_map_set_addr(&voodoo->mapping, voodoo->memBaseAddr, 0x01000000); } else { - voodoo_log("voodoo_recalcmapping : disabled\n"); - mem_mapping_disable(&voodoo->mapping); + DEBUG("voodoo_recalcmapping : disabled\n"); + mem_map_disable(&voodoo->mapping); } } } @@ -6919,7 +6900,7 @@ uint8_t voodoo_pci_read(int func, int addr, void *p) if (func) return 0; -// voodoo_log("Voodoo PCI read %08X PC=%08x\n", addr, cpu_state.pc); +// DEBUG("Voodoo PCI read %08X PC=%08x\n", addr, cpu_state.pc); switch (addr) { @@ -6966,7 +6947,7 @@ void voodoo_pci_write(int func, int addr, uint8_t val, void *p) if (func) return; -// voodoo_log("Voodoo PCI write %04X %02X PC=%08x\n", addr, val, cpu_state.pc); +// DEBUG("Voodoo PCI write %04X %02X PC=%08x\n", addr, val, cpu_state.pc); switch (addr) { @@ -7198,7 +7179,7 @@ static void voodoo_generate_filter_v2(voodoo_t *voodoo) // debug the ones that don't give us much of a difference //if (difference < FILTCAP) - //voodoo_log("Voodoofilter: %ix%i - %f difference, %f average difference, R=%f, G=%f, B=%f\n", g, h, difference, avgdiff, thiscol, thiscolg, thiscolb); + //DEBUG("Voodoofilter: %ix%i - %f difference, %f average difference, R=%f, G=%f, B=%f\n", g, h, difference, avgdiff, thiscol, thiscolg, thiscolb); } lined = g + 3; @@ -7228,7 +7209,7 @@ static void voodoo_threshold_check(voodoo_t *voodoo) FILTCAPG = g; FILTCAPB = b; - voodoo_log("Voodoo Filter Threshold Check: %06x - RED %i GREEN %i BLUE %i\n", voodoo->scrfilterThreshold, r, g, b); + DEBUG("Voodoo Filter Threshold Check: %06x - RED %i GREEN %i BLUE %i\n", voodoo->scrfilterThreshold, r, g, b); voodoo->scrfilterThresholdOld = voodoo->scrfilterThreshold; @@ -7247,7 +7228,7 @@ static void voodoo_filterline_v1(voodoo_t *voodoo, uint8_t *fil, int column, uin #ifdef _MSC_VER if ((voodoo->h_disp) * 3 > 512 * 1024) { - pclog("voodoo_filterline_v1: possible stack overflow detected. h_disp is %d", voodoo->h_disp); + DEBUG("voodoo_filterline_v1: possible stack overflow detected. h_disp is %d", voodoo->h_disp); return; } uint8_t *fil3 = (uint8_t *)_alloca((voodoo->h_disp) * 3); @@ -7322,7 +7303,7 @@ static void voodoo_filterline_v2(voodoo_t *voodoo, uint8_t *fil, int column, uin #ifdef _MSC_VER if ((voodoo->h_disp) * 3 > 512 * 1024) { - pclog("voodoo_filterline_v2: possible stack overflow detected. h_disp is %d", voodoo->h_disp); + DEBUG("voodoo_filterline_v2: possible stack overflow detected. h_disp is %d", voodoo->h_disp); return; } uint8_t *fil3 = (uint8_t *)_alloca((voodoo->h_disp) * 3); @@ -7440,7 +7421,7 @@ void voodoo_callback(void *priv) #ifdef _MSC_VER if ((voodoo->h_disp) * 3 > 512 * 1024) { - pclog("voodoo_callback: possible stack overflow detected. h_disp is %d", voodoo->h_disp); + DEBUG("voodoo_callback: possible stack overflow detected. h_disp is %d", voodoo->h_disp); return; } uint8_t *fil = (uint8_t *)_alloca((voodoo->h_disp) * 3); @@ -7471,7 +7452,7 @@ void voodoo_callback(void *priv) skip_draw: if (voodoo->line == voodoo->v_disp) { -// voodoo_log("retrace %i %i %08x %i\n", voodoo->retrace_count, voodoo->swap_interval, voodoo->swap_offset, voodoo->swap_pending); +// DEBUG("retrace %i %i %08x %i\n", voodoo->retrace_count, voodoo->swap_interval, voodoo->swap_offset, voodoo->swap_pending); voodoo->retrace_count++; if (SLI_ENABLED && (voodoo->fbiInit2 & FBIINIT2_SWAP_ALGORITHM_MASK) == FBIINIT2_SWAP_ALGORITHM_SLI_SYNC) { @@ -7550,92 +7531,6 @@ skip_draw: voodoo->timer_count += TIMER_USEC * 32; } -static void voodoo_add_status_info(char *s, int max_len, void *p) -{ - voodoo_set_t *voodoo_set = (voodoo_set_t *)p; - voodoo_t *voodoo = voodoo_set->voodoos[0]; - voodoo_t *voodoo_slave = voodoo_set->voodoos[1]; - char temps[512], temps2[256]; - int pixel_count_current[2]; - int pixel_count_total; - int texel_count_current[2]; - int texel_count_total; - int render_time[2]; - uint64_t new_time = plat_timer_read(); - uint64_t status_diff = new_time - status_time; - status_time = new_time; - - if (!status_diff) - status_diff = 1; - - svga_add_status_info(s, max_len, &voodoo->svga); - - pixel_count_current[0] = voodoo->pixel_count[0]; - pixel_count_current[1] = voodoo->pixel_count[1]; - texel_count_current[0] = voodoo->texel_count[0]; - texel_count_current[1] = voodoo->texel_count[1]; - render_time[0] = voodoo->render_time[0]; - render_time[1] = voodoo->render_time[1]; - if (voodoo_set->nr_cards == 2) - { - pixel_count_current[0] += voodoo_slave->pixel_count[0]; - pixel_count_current[1] += voodoo_slave->pixel_count[1]; - texel_count_current[0] += voodoo_slave->texel_count[0]; - texel_count_current[1] += voodoo_slave->texel_count[1]; - render_time[0] = (render_time[0] + voodoo_slave->render_time[0]) / 2; - render_time[1] = (render_time[1] + voodoo_slave->render_time[1]) / 2; - } - pixel_count_total = (pixel_count_current[0] + pixel_count_current[1]) - (voodoo->pixel_count_old[0] + voodoo->pixel_count_old[1]); - texel_count_total = (texel_count_current[0] + texel_count_current[1]) - (voodoo->texel_count_old[0] + voodoo->texel_count_old[1]); - sprintf(temps, "%f Mpixels/sec (%f)\n%f Mtexels/sec (%f)\n%f ktris/sec\n%f%% CPU (%f%% real)\n%d frames/sec (%i)\n%f%% CPU (%f%% real)\n"/*%d reads/sec\n%d write/sec\n%d tex/sec\n*/, - (double)pixel_count_total/1000000.0, - ((double)pixel_count_total/1000000.0) / ((double)render_time[0] / status_diff), - (double)texel_count_total/1000000.0, - ((double)texel_count_total/1000000.0) / ((double)render_time[0] / status_diff), - (double)voodoo->tri_count/1000.0, ((double)voodoo->time * 100.0) / timer_freq, ((double)voodoo->time * 100.0) / status_diff, voodoo->frame_count, voodoo_recomp, - ((double)voodoo->render_time[0] * 100.0) / timer_freq, ((double)voodoo->render_time[0] * 100.0) / status_diff); - if (voodoo->render_threads == 2) - { - sprintf(temps2, "%f%% CPU (%f%% real)\n", - ((double)voodoo->render_time[1] * 100.0) / timer_freq, ((double)voodoo->render_time[1] * 100.0) / status_diff); - strncat(temps, temps2, sizeof(temps)-1); - } - if (voodoo_set->nr_cards == 2) - { - sprintf(temps2, "%f%% CPU (%f%% real)\n", - ((double)voodoo_slave->render_time[0] * 100.0) / timer_freq, ((double)voodoo_slave->render_time[0] * 100.0) / status_diff); - strncat(temps, temps2, sizeof(temps)-1); - - if (voodoo_slave->render_threads == 2) - { - sprintf(temps2, "%f%% CPU (%f%% real)\n", - ((double)voodoo_slave->render_time[1] * 100.0) / timer_freq, ((double)voodoo_slave->render_time[1] * 100.0) / status_diff); - strncat(temps, temps2, sizeof(temps)-1); - } - } - strncat(s, temps, max_len); - - voodoo->pixel_count_old[0] = pixel_count_current[0]; - voodoo->pixel_count_old[1] = pixel_count_current[1]; - voodoo->texel_count_old[0] = texel_count_current[0]; - voodoo->texel_count_old[1] = texel_count_current[1]; - voodoo->tri_count = voodoo->frame_count = 0; - voodoo->rd_count = voodoo->wr_count = voodoo->tex_count = 0; - voodoo->time = 0; - voodoo->render_time[0] = voodoo->render_time[1] = 0; - if (voodoo_set->nr_cards == 2) - { - voodoo_slave->pixel_count_old[0] = pixel_count_current[0]; - voodoo_slave->pixel_count_old[1] = pixel_count_current[1]; - voodoo_slave->texel_count_old[0] = texel_count_current[0]; - voodoo_slave->texel_count_old[1] = texel_count_current[1]; - voodoo_slave->tri_count = voodoo_slave->frame_count = 0; - voodoo_slave->rd_count = voodoo_slave->wr_count = voodoo_slave->tex_count = 0; - voodoo_slave->time = 0; - voodoo_slave->render_time[0] = voodoo_slave->render_time[1] = 0; - } - voodoo_recomp = 0; -} static void voodoo_speed_changed(void *p) { @@ -7652,13 +7547,13 @@ static void voodoo_speed_changed(void *p) voodoo_set->voodoos[1]->write_time = pci_nonburst_time + pci_burst_time * ((voodoo_set->voodoos[1]->fbiInit1 & 2) ? 1 : 0); voodoo_set->voodoos[1]->burst_time = pci_burst_time * ((voodoo_set->voodoos[1]->fbiInit1 & 2) ? 2 : 1); } -// voodoo_log("Voodoo read_time=%i write_time=%i burst_time=%i %08x %08x\n", voodoo->read_time, voodoo->write_time, voodoo->burst_time, voodoo->fbiInit1, voodoo->fbiInit4); +// DEBUG("Voodoo read_time=%i write_time=%i burst_time=%i %08x %08x\n", voodoo->read_time, voodoo->write_time, voodoo->burst_time, voodoo->fbiInit1, voodoo->fbiInit4); } void *voodoo_card_init() { int c; - voodoo_t *voodoo = malloc(sizeof(voodoo_t)); + voodoo_t *voodoo = (voodoo_t *)mem_alloc(sizeof(voodoo_t)); memset(voodoo, 0, sizeof(voodoo_t)); voodoo->bilinear_enabled = device_get_config_int("bilinear"); @@ -7693,23 +7588,23 @@ void *voodoo_card_init() pci_add_card(PCI_ADD_NORMAL, voodoo_pci_read, voodoo_pci_write, voodoo); - mem_mapping_add(&voodoo->mapping, 0, 0, NULL, voodoo_readw, voodoo_readl, NULL, voodoo_writew, voodoo_writel, NULL, MEM_MAPPING_EXTERNAL, voodoo); + mem_map_add(&voodoo->mapping, 0, 0, NULL, voodoo_readw, voodoo_readl, NULL, voodoo_writew, voodoo_writel, NULL, MEM_MAPPING_EXTERNAL, voodoo); - voodoo->fb_mem = malloc(4 * 1024 * 1024); - voodoo->tex_mem[0] = malloc(voodoo->texture_size * 1024 * 1024); + voodoo->fb_mem = (uint8_t *)mem_alloc(4 * 1024 * 1024); + voodoo->tex_mem[0] = (uint8_t *)mem_alloc(voodoo->texture_size * 1024 * 1024); if (voodoo->dual_tmus) - voodoo->tex_mem[1] = malloc(voodoo->texture_size * 1024 * 1024); + voodoo->tex_mem[1] = (uint8_t *)mem_alloc(voodoo->texture_size * 1024 * 1024); voodoo->tex_mem_w[0] = (uint16_t *)voodoo->tex_mem[0]; voodoo->tex_mem_w[1] = (uint16_t *)voodoo->tex_mem[1]; for (c = 0; c < TEX_CACHE_MAX; c++) { - voodoo->texture_cache[0][c].data = malloc((256*256 + 256*256 + 128*128 + 64*64 + 32*32 + 16*16 + 8*8 + 4*4 + 2*2) * 4); + voodoo->texture_cache[0][c].data = (uint32_t *)mem_alloc((256*256 + 256*256 + 128*128 + 64*64 + 32*32 + 16*16 + 8*8 + 4*4 + 2*2) * 4); voodoo->texture_cache[0][c].base = -1; /*invalid*/ voodoo->texture_cache[0][c].refcount = 0; if (voodoo->dual_tmus) { - voodoo->texture_cache[1][c].data = malloc((256*256 + 256*256 + 128*128 + 64*64 + 32*32 + 16*16 + 8*8 + 4*4 + 2*2) * 4); + voodoo->texture_cache[1][c].data = (uint32_t *)mem_alloc((256*256 + 256*256 + 128*128 + 64*64 + 32*32 + 16*16 + 8*8 + 4*4 + 2*2) * 4); voodoo->texture_cache[1][c].base = -1; /*invalid*/ voodoo->texture_cache[1][c].refcount = 0; } @@ -7794,26 +7689,26 @@ void *voodoo_card_init() void *voodoo_init(const device_t *info) { - voodoo_set_t *voodoo_set = malloc(sizeof(voodoo_set_t)); + voodoo_set_t *voodoo_set = (voodoo_set_t *)mem_alloc(sizeof(voodoo_set_t)); uint32_t tmuConfig = 1; int type; memset(voodoo_set, 0, sizeof(voodoo_set_t)); - rgb332 = (rgba8_t *)malloc(sizeof(rgba8_t)*0x100); - ai44 = (rgba8_t *)malloc(sizeof(rgba8_t)*0x100); - rgb565 = (rgba8_t *)malloc(sizeof(rgba8_t)*0x10000); - argb1555 = (rgba8_t *)malloc(sizeof(rgba8_t)*0x10000); - argb4444 = (rgba8_t *)malloc(sizeof(rgba8_t)*0x10000); - ai88 = (rgba8_t *)malloc(sizeof(rgba8_t)*0x10000); + rgb332 = (rgba8_t *)mem_alloc(sizeof(rgba8_t)*0x100); + ai44 = (rgba8_t *)mem_alloc(sizeof(rgba8_t)*0x100); + rgb565 = (rgba8_t *)mem_alloc(sizeof(rgba8_t)*0x10000); + argb1555 = (rgba8_t *)mem_alloc(sizeof(rgba8_t)*0x10000); + argb4444 = (rgba8_t *)mem_alloc(sizeof(rgba8_t)*0x10000); + ai88 = (rgba8_t *)mem_alloc(sizeof(rgba8_t)*0x10000); type = device_get_config_int("type"); voodoo_set->nr_cards = device_get_config_int("sli") ? 2 : 1; - voodoo_set->voodoos[0] = voodoo_card_init(); + voodoo_set->voodoos[0] = (voodoo_t *)voodoo_card_init(); voodoo_set->voodoos[0]->set = voodoo_set; if (voodoo_set->nr_cards == 2) { - voodoo_set->voodoos[1] = voodoo_card_init(); + voodoo_set->voodoos[1] = (voodoo_t *)voodoo_card_init(); voodoo_set->voodoos[1]->set = voodoo_set; @@ -7852,7 +7747,7 @@ void *voodoo_init(const device_t *info) if (voodoo_set->nr_cards == 2) voodoo_set->voodoos[1]->tmuConfig = tmuConfig; - mem_mapping_add(&voodoo_set->snoop_mapping, 0, 0, NULL, voodoo_snoop_readw, voodoo_snoop_readl, NULL, voodoo_snoop_writew, voodoo_snoop_writel, NULL, MEM_MAPPING_EXTERNAL, voodoo_set); + mem_map_add(&voodoo_set->snoop_mapping, 0, 0, NULL, voodoo_snoop_readw, voodoo_snoop_readl, NULL, voodoo_snoop_writew, voodoo_snoop_writel, NULL, MEM_MAPPING_EXTERNAL, voodoo_set); return voodoo_set; } @@ -7931,117 +7826,80 @@ void voodoo_close(void *p) static const device_config_t voodoo_config[] = { { - .name = "type", - .description = "Voodoo type", - .type = CONFIG_SELECTION, - .selection = + "type","Voodoo type",CONFIG_SELECTION,"",VOODOO_1, { { - .description = "Voodoo Graphics", - .value = VOODOO_1 + "Voodoo Graphics",VOODOO_1 }, { - .description = "Obsidian SB50 + Amethyst (2 TMUs)", - .value = VOODOO_SB50 + "Obsidian SB50 + Amethyst (2 TMUs)",VOODOO_SB50 }, { - .description = "Voodoo 2", - .value = VOODOO_2 + "Voodoo 2",VOODOO_2 }, { - .description = "" + "" } }, - .default_int = 0 }, { - .name = "framebuffer_memory", - .description = "Framebuffer memory size", - .type = CONFIG_SELECTION, - .selection = + "framebuffer_memory","Framebuffer memory size",CONFIG_SELECTION,"",2, { { - .description = "2 MB", - .value = 2 + "2 MB",2 }, { - .description = "4 MB", - .value = 4 + "4 MB",4 }, { - .description = "" + "" } }, - .default_int = 2 }, { - .name = "texture_memory", - .description = "Texture memory size", - .type = CONFIG_SELECTION, - .selection = + "texture_memory","Texture memory size",CONFIG_SELECTION,"",2, { { - .description = "2 MB", - .value = 2 + "2 MB",2 }, { - .description = "4 MB", - .value = 4 + "4 MB",4 }, { - .description = "" + "" } }, - .default_int = 2 }, { - .name = "bilinear", - .description = "Bilinear filtering", - .type = CONFIG_BINARY, - .default_int = 1 + "bilinear","Bilinear filtering",CONFIG_BINARY,"",1 }, { - .name = "dacfilter", - .description = "Screen Filter", - .type = CONFIG_BINARY, - .default_int = 0 + "dacfilter","Screen Filter",CONFIG_BINARY,"",0 }, { - .name = "render_threads", - .description = "Render threads", - .type = CONFIG_SELECTION, - .selection = + "render_threads","Render threads",CONFIG_SELECTION,"",2, { { - .description = "1", - .value = 1 + "1",1 }, { - .description = "2", - .value = 2 + "2",2 }, { - .description = "" + "" } }, - .default_int = 2 }, { - .name = "sli", - .description = "SLI", - .type = CONFIG_BINARY, - .default_int = 0 + "sli","SLI",CONFIG_BINARY,"",0 }, #ifndef NO_CODEGEN { - .name = "recompiler", - .description = "Recompiler", - .type = CONFIG_BINARY, - .default_int = 1 + "recompiler","Recompiler",CONFIG_BINARY,"",1 }, #endif { - .type = -1 + "","",-1 } }; @@ -8056,6 +7914,6 @@ const device_t voodoo_device = NULL, voodoo_speed_changed, NULL, - voodoo_add_status_info, + NULL, voodoo_config }; diff --git a/src/devices/video/vid_voodoo_codegen_x86-64.h b/src/devices/video/vid_voodoo_codegen_x86-64.h index 9636baa..38a431a 100644 --- a/src/devices/video/vid_voodoo_codegen_x86-64.h +++ b/src/devices/video/vid_voodoo_codegen_x86-64.h @@ -8,7 +8,7 @@ * * Implementation of the Voodoo Recompiler (64bit.) * - * Version: @(#)vid_voodoo_codegen_x86-64.h 1.0.1 2018/02/14 + * Version: @(#)vid_voodoo_codegen_x86-64.h 1.0.1 2018/09/22 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -3345,7 +3345,7 @@ static void voodoo_codegen_init(voodoo_t *voodoo) #if WIN64 voodoo->codegen_data = VirtualAlloc(NULL, sizeof(voodoo_x86_data_t) * BLOCK_NUM * 2, MEM_COMMIT, PAGE_EXECUTE_READWRITE); #else - voodoo->codegen_data = malloc(sizeof(voodoo_x86_data_t) * BLOCK_NUM * 2); + voodoo->codegen_data = mem_alloc(sizeof(voodoo_x86_data_t) * BLOCK_NUM * 2); #endif #ifdef __linux__ diff --git a/src/devices/video/vid_voodoo_codegen_x86.h b/src/devices/video/vid_voodoo_codegen_x86.h index d7c1810..e01d610 100644 --- a/src/devices/video/vid_voodoo_codegen_x86.h +++ b/src/devices/video/vid_voodoo_codegen_x86.h @@ -8,7 +8,7 @@ * * Implementation of the Voodoo Recompiler (32bit.) * - * Version: @(#)vid_voodoo_codegen_x86.h 1.0.4 2018/05/16 + * Version: @(#)vid_voodoo_codegen_x86.h 1.0.5 2018/09/22 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -3278,7 +3278,7 @@ static inline void *voodoo_get_block(voodoo_t *voodoo, voodoo_params_t *params, int c; int b = last_block[odd_even]; voodoo_x86_data_t *data; - voodoo_x86_data_t *codegen_data = voodoo->codegen_data; + voodoo_x86_data_t *codegen_data = (voodoo_x86_data_t *)voodoo->codegen_data; for (c = 0; c < 8; c++) { @@ -3336,7 +3336,7 @@ static void voodoo_codegen_init(voodoo_t *voodoo) #if defined WIN32 || defined _WIN32 || defined _WIN32 voodoo->codegen_data = VirtualAlloc(NULL, sizeof(voodoo_x86_data_t) * BLOCK_NUM*2, MEM_COMMIT, PAGE_EXECUTE_READWRITE); #else - voodoo->codegen_data = malloc(sizeof(voodoo_x86_data_t) * BLOCK_NUM*2); + voodoo->codegen_data = mem_alloc(sizeof(voodoo_x86_data_t) * BLOCK_NUM*2); #endif #ifdef __linux__ diff --git a/src/devices/video/vid_wy700.c b/src/devices/video/vid_wy700.c index 19b3933..fff7d87 100644 --- a/src/devices/video/vid_wy700.c +++ b/src/devices/video/vid_wy700.c @@ -53,7 +53,7 @@ * What doesn't work, is untested or not well understood: * - Cursor detach (commands 4 and 5) * - * Version: @(#)vid_wy700.c 1.0.4 2018/05/06 + * Version: @(#)vid_wy700.c 1.0.5 2018/09/22 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -89,278 +89,209 @@ #include "../../emu.h" #include "../../io.h" #include "../../mem.h" +#include "../../rom.h" #include "../../timer.h" #include "../../device.h" #include "../system/pit.h" #include "video.h" -#define WY700_XSIZE 1280 -#define WY700_YSIZE 800 +#define WY700_XSIZE 1280 +#define WY700_YSIZE 800 - -//extern void updatewindowsize(int x, int y); +#define BIOS_ROM_PATH L"video/wyse/wyse700/wy700.rom" /* The microcontroller sets up the real CRTC with one of five fixed mode * definitions. As written, this is a fairly simplistic emulation that * doesn't attempt to closely follow the actual working of the CRTC; but I've - * included the definitions here for information. */ - -static uint8_t mode_1280x800[] = -{ - 0x31, /* Horizontal total */ - 0x28, /* Horizontal displayed */ - 0x29, /* Horizontal sync position */ - 0x06, /* Horizontal sync width */ - 0x1b, /* Vertical total */ - 0x00, /* Vertical total adjust */ - 0x19, /* Vertical displayed */ - 0x1a, /* Vsync position */ - 0x03, /* Interlace and skew */ - 0x0f, /* Maximum raster address */ + * included the definitions here for information. + */ +static const uint8_t mode_1280x800[] = { + 0x31, /* Horizontal total */ + 0x28, /* Horizontal displayed */ + 0x29, /* Horizontal sync position */ + 0x06, /* Horizontal sync width */ + 0x1b, /* Vertical total */ + 0x00, /* Vertical total adjust */ + 0x19, /* Vertical displayed */ + 0x1a, /* Vsync position */ + 0x03, /* Interlace and skew */ + 0x0f /* Maximum raster address */ }; -static uint8_t mode_1280x400[] = -{ - 0x31, /* Horizontal total */ - 0x28, /* Horizontal displayed */ - 0x29, /* Horizontal sync position */ - 0x06, /* Horizontal sync width */ - 0x1b, /* Vertical total */ - 0x00, /* Vertical total adjust */ - 0x19, /* Vertical displayed */ - 0x1a, /* Vsync position */ - 0x01, /* Interlace and skew */ - 0x0f, /* Maximum raster address */ +static const uint8_t mode_1280x400[] = { + 0x31, /* Horizontal total */ + 0x28, /* Horizontal displayed */ + 0x29, /* Horizontal sync position */ + 0x06, /* Horizontal sync width */ + 0x1b, /* Vertical total */ + 0x00, /* Vertical total adjust */ + 0x19, /* Vertical displayed */ + 0x1a, /* Vsync position */ + 0x01, /* Interlace and skew */ + 0x0f /* Maximum raster address */ }; -static uint8_t mode_640x400[] = -{ - 0x18, /* Horizontal total */ - 0x14, /* Horizontal displayed */ - 0x14, /* Horizontal sync position */ - 0x03, /* Horizontal sync width */ - 0x1b, /* Vertical total */ - 0x00, /* Vertical total adjust */ - 0x19, /* Vertical displayed */ - 0x1a, /* Vsync position */ - 0x01, /* Interlace and skew */ - 0x0f, /* Maximum raster address */ +static const uint8_t mode_640x400[] = { + 0x18, /* Horizontal total */ + 0x14, /* Horizontal displayed */ + 0x14, /* Horizontal sync position */ + 0x03, /* Horizontal sync width */ + 0x1b, /* Vertical total */ + 0x00, /* Vertical total adjust */ + 0x19, /* Vertical displayed */ + 0x1a, /* Vsync position */ + 0x01, /* Interlace and skew */ + 0x0f /* Maximum raster address */ }; -static uint8_t mode_640x200[] = -{ - 0x18, /* Horizontal total */ - 0x14, /* Horizontal displayed */ - 0x14, /* Horizontal sync position */ - 0xff, /* Horizontal sync width */ - 0x37, /* Vertical total */ - 0x00, /* Vertical total adjust */ - 0x32, /* Vertical displayed */ - 0x34, /* Vsync position */ - 0x03, /* Interlace and skew */ - 0x07, /* Maximum raster address */ +static const uint8_t mode_640x200[] = { + 0x18, /* Horizontal total */ + 0x14, /* Horizontal displayed */ + 0x14, /* Horizontal sync position */ + 0xff, /* Horizontal sync width */ + 0x37, /* Vertical total */ + 0x00, /* Vertical total adjust */ + 0x32, /* Vertical displayed */ + 0x34, /* Vsync position */ + 0x03, /* Interlace and skew */ + 0x07 /* Maximum raster address */ }; -static uint8_t mode_80x24[] = -{ - 0x31, /* Horizontal total */ - 0x28, /* Horizontal displayed */ - 0x2A, /* Horizontal sync position */ - 0xff, /* Horizontal sync width */ - 0x1b, /* Vertical total */ - 0x00, /* Vertical total adjust */ - 0x19, /* Vertical displayed */ - 0x1a, /* Vsync position */ - 0x01, /* Interlace and skew */ - 0x0f, /* Maximum raster address */ +static const uint8_t mode_80x24[] = { + 0x31, /* Horizontal total */ + 0x28, /* Horizontal displayed */ + 0x2A, /* Horizontal sync position */ + 0xff, /* Horizontal sync width */ + 0x1b, /* Vertical total */ + 0x00, /* Vertical total adjust */ + 0x19, /* Vertical displayed */ + 0x1a, /* Vsync position */ + 0x01, /* Interlace and skew */ + 0x0f /* Maximum raster address */ }; -static uint8_t mode_40x24[] = -{ - 0x18, /* Horizontal total */ - 0x14, /* Horizontal displayed */ - 0x15, /* Horizontal sync position */ - 0xff, /* Horizontal sync width */ - 0x1b, /* Vertical total */ - 0x00, /* Vertical total adjust */ - 0x19, /* Vertical displayed */ - 0x1a, /* Vsync position */ - 0x01, /* Interlace and skew */ - 0x0f, /* Maximum raster address */ +static const uint8_t mode_40x24[] = { + 0x18, /* Horizontal total */ + 0x14, /* Horizontal displayed */ + 0x15, /* Horizontal sync position */ + 0xff, /* Horizontal sync width */ + 0x1b, /* Vertical total */ + 0x00, /* Vertical total adjust */ + 0x19, /* Vertical displayed */ + 0x1a, /* Vsync position */ + 0x01, /* Interlace and skew */ + 0x0f /* Maximum raster address */ }; /* Font ROM: Two fonts, each containing 256 characters, 16x16 pixels */ extern uint8_t fontdatw[512][32]; -typedef struct wy700_t -{ - mem_mapping_t mapping; - /* The microcontroller works by watching four ports: - * 0x3D8 / 0x3B8 (mode control register) - * 0x3DD (top scanline address) - * 0x3DF (Wy700 control register) - * CRTC reg 14 (cursor location high) - * - * It will do nothing until one of these registers is touched. When - * one is, it then reconfigures the internal 6845 based on what it - * sees. - */ - uint8_t last_03D8; /* Copies of values written to the listed */ - uint8_t last_03DD; /* I/O ports */ - uint8_t last_03DF; - uint8_t last_crtc_0E; +typedef struct { + mem_map_t mapping; - uint8_t cga_crtc[32]; /* The 'CRTC' as the host PC sees it */ - uint8_t real_crtc[32]; /* The internal CRTC as the microcontroller */ + /* The microcontroller works by watching four ports: + * 0x3D8 / 0x3B8 (mode control register) + * 0x3DD (top scanline address) + * 0x3DF (Wy700 control register) + * CRTC reg 14 (cursor location high) + * + * It will do nothing until one of these registers is touched. When + * one is, it then reconfigures the internal 6845 based on what it + * sees. + */ + uint8_t last_03D8; /* Copies of values written to the listed */ + uint8_t last_03DD; /* I/O ports */ + uint8_t last_03DF; + uint8_t last_crtc_0E; + + uint8_t cga_crtc[32]; /* The 'CRTC' as the host PC sees it */ + uint8_t real_crtc[32]; /* The internal CRTC as the microcontroller */ /* sees it */ - int cga_crtcreg; /* Current CRTC register */ - uint16_t wy700_base; /* Framebuffer base address (native modes) */ - uint8_t wy700_control; /* Native control / command register */ - uint8_t wy700_mode; /* Current mode (see list at top of file) */ - uint8_t cga_ctrl; /* Emulated MDA/CGA control register */ - uint8_t cga_colour; /* Emulated CGA colour register (ignored) */ + int cga_crtcreg; /* Current CRTC register */ + uint16_t wy700_base; /* Framebuffer base address (native modes) */ + uint8_t wy700_control; /* Native control / command register */ + uint8_t wy700_mode; /* Current mode (see list at top of file) */ + uint8_t cga_ctrl; /* Emulated MDA/CGA control register */ + uint8_t cga_colour; /* Emulated CGA colour register (ignored) */ - uint8_t mda_stat; /* MDA status (IN 0x3BA) */ - uint8_t cga_stat; /* CGA status (IN 0x3DA) */ + uint8_t mda_stat; /* MDA status (IN 0x3BA) */ + uint8_t cga_stat; /* CGA status (IN 0x3DA) */ - int font; /* Current font, 0 or 1 */ - int enabled; /* Display enabled, 0 or 1 */ - int detach; /* Detach cursor, 0 or 1 */ + int font; /* Current font, 0 or 1 */ + int enabled; /* Display enabled, 0 or 1 */ + int detach; /* Detach cursor, 0 or 1 */ - int64_t dispontime, dispofftime; - int64_t vidtime; - - int linepos, displine; - int vc; - int dispon, blink; - int64_t vsynctime; + int64_t dispontime, dispofftime; + int64_t vidtime; + + int linepos, displine; + int vc; + int dispon, blink; + int64_t vsynctime; - uint8_t *vram; + /* Mapping of attributes to colours, in CGA emulation... */ + int cgacols[256][2][2]; + + /* ... and MDA emulation. */ + int mdacols[256][2][2]; + + uint8_t *vram; } wy700_t; -/* Mapping of attributes to colours, in CGA emulation... */ -static int cgacols[256][2][2]; -/* ... and MDA emulation. */ -static int mdacols[256][2][2]; -void wy700_recalctimings(wy700_t *wy700); -void wy700_write(uint32_t addr, uint8_t val, void *p); -uint8_t wy700_read(uint32_t addr, void *p); -void wy700_checkchanges(wy700_t *wy700); - - -void wy700_out(uint16_t addr, uint8_t val, void *p) +static void +recalc_timings(wy700_t *dev) { - wy700_t *wy700 = (wy700_t *)p; - switch (addr) - { - /* These three registers are only mapped in the 3Dx range, - * not the 3Bx range. */ - case 0x3DD: /* Base address (low) */ - wy700->wy700_base &= 0xFF00; - wy700->wy700_base |= val; - wy700_checkchanges(wy700); - break; + double disptime; + double _dispontime, _dispofftime; - case 0x3DE: /* Base address (high) */ - wy700->wy700_base &= 0xFF; - wy700->wy700_base |= ((uint16_t)val) << 8; - wy700_checkchanges(wy700); - break; + disptime = dev->real_crtc[0] + 1; + _dispontime = dev->real_crtc[1]; + _dispofftime = disptime - _dispontime; + _dispontime *= MDACONST; + _dispofftime *= MDACONST; - case 0x3DF: /* Command / control register */ - wy700->wy700_control = val; - wy700_checkchanges(wy700); - break; - - /* Emulated CRTC, register select */ - case 0x3b0: case 0x3b2: case 0x3b4: case 0x3b6: - case 0x3d0: case 0x3d2: case 0x3d4: case 0x3d6: - wy700->cga_crtcreg = val & 31; - break; - - /* Emulated CRTC, value */ - case 0x3b1: case 0x3b3: case 0x3b5: case 0x3b7: - case 0x3d1: case 0x3d3: case 0x3d5: case 0x3d7: - wy700->cga_crtc[wy700->cga_crtcreg] = val; - - wy700_checkchanges(wy700); - wy700_recalctimings(wy700); - return; - - /* Emulated MDA / CGA control register */ - case 0x3b8: case 0x3D8: - wy700->cga_ctrl = val; - wy700_checkchanges(wy700); - return; - /* Emulated CGA colour register */ - case 0x3D9: - wy700->cga_colour = val; - return; - } -} - -uint8_t wy700_in(uint16_t addr, void *p) -{ - wy700_t *wy700 = (wy700_t *)p; - switch (addr) - { - case 0x3b0: case 0x3b2: case 0x3b4: case 0x3b6: - case 0x3d0: case 0x3d2: case 0x3d4: case 0x3d6: - return wy700->cga_crtcreg; - case 0x3b1: case 0x3b3: case 0x3b5: case 0x3b7: - case 0x3d1: case 0x3d3: case 0x3d5: case 0x3d7: - return wy700->cga_crtc[wy700->cga_crtcreg]; - case 0x3b8: case 0x3d8: - return wy700->cga_ctrl; - case 0x3d9: - return wy700->cga_colour; - case 0x3ba: - return wy700->mda_stat; - case 0x3da: - return wy700->cga_stat; - } - return 0xff; + dev->dispontime = (int64_t)(_dispontime * (1 << TIMER_SHIFT)); + dev->dispofftime = (int64_t)(_dispofftime * (1 << TIMER_SHIFT)); } /* Check if any of the four key registers has changed. If so, check for a * mode change or cursor size change */ -void wy700_checkchanges(wy700_t *wy700) +static void +check_changes(wy700_t *dev) { - uint8_t curstart, curend; + uint8_t curstart, curend; - if (wy700->last_03D8 == wy700->cga_ctrl && - wy700->last_03DD == (wy700->wy700_base & 0xFF) && - wy700->last_03DF == wy700->wy700_control && - wy700->last_crtc_0E == wy700->cga_crtc[0x0E]) - { + if (dev->last_03D8 == dev->cga_ctrl && + dev->last_03DD == (dev->wy700_base & 0xFF) && + dev->last_03DF == dev->wy700_control && + dev->last_crtc_0E == dev->cga_crtc[0x0E]) { return; /* Nothing changed */ - } - /* Check for control register changes */ - if (wy700->last_03DF != wy700->wy700_control) - { - wy700->last_03DF = wy700->wy700_control; + } - /* Values 1-7 are commands. */ - switch (wy700->wy700_control) - { - case 1: /* Reset */ - wy700->font = 0; - wy700->enabled = 1; - wy700->detach = 0; + /* Check for control register changes */ + if (dev->last_03DF != dev->wy700_control) { + dev->last_03DF = dev->wy700_control; + + /* Values 1-7 are commands. */ + switch (dev->wy700_control) { + case 1: /* Reset */ + dev->font = 0; + dev->enabled = 1; + dev->detach = 0; break; - case 2: /* Font 1 */ - wy700->font = 0; + case 2: /* Font 1 */ + dev->font = 0; break; - case 3: /* Font 2 */ - wy700->font = 1; + case 3: /* Font 2 */ + dev->font = 1; break; /* Even with the microprogram from an original card, I can't really work out @@ -373,667 +304,704 @@ void wy700_checkchanges(wy700_t *wy700) * The card documentation doesn't cover these commands. */ - case 4: /* Detach cursor */ - wy700->detach = 1; + case 4: /* Detach cursor */ + dev->detach = 1; break; - case 5: /* Attach cursor */ - wy700->detach = 0; + case 5: /* Attach cursor */ + dev->detach = 0; break; - case 6: /* Disable display */ - wy700->enabled = 0; + case 6: /* Disable display */ + dev->enabled = 0; break; - case 7: /* Enable display */ - wy700->enabled = 1; + case 7: /* Enable display */ + dev->enabled = 1; break; - } - /* A control write with the top bit set selects graphics mode */ - if (wy700->wy700_control & 0x80) - { - /* Select hi-res graphics mode; map framebuffer at A0000 */ - mem_mapping_set_addr(&wy700->mapping, 0xa0000, 0x20000); - wy700->wy700_mode = wy700->wy700_control; + } - /* Select appropriate preset timings */ - if (wy700->wy700_mode & 0x40) - { - memcpy(wy700->real_crtc, mode_1280x800, - sizeof(mode_1280x800)); - } - else if (wy700->wy700_mode & 0x20) - { - memcpy(wy700->real_crtc, mode_1280x400, - sizeof(mode_1280x400)); - } - else - { - memcpy(wy700->real_crtc, mode_640x400, - sizeof(mode_640x400)); - } - } - } - /* An attempt to program the CGA / MDA selects low-res mode */ - else if (wy700->last_03D8 != wy700->cga_ctrl) - { - wy700->last_03D8 = wy700->cga_ctrl; - /* Set lo-res text or graphics mode. - * (Strictly speaking, when not in hi-res mode the card - * should be mapped at B0000-B3FFF and B8000-BBFFF, leaving - * a 16k hole between the two ranges) */ - mem_mapping_set_addr(&wy700->mapping, 0xb0000, 0x0C000); - if (wy700->cga_ctrl & 2) /* Graphics mode */ - { - wy700->wy700_mode = (wy700->cga_ctrl & 0x10) ? 6 : 4; - memcpy(wy700->real_crtc, mode_640x200, - sizeof(mode_640x200)); - } - else if (wy700->cga_ctrl & 1) /* Text mode 80x24 */ - { - wy700->wy700_mode = 2; - memcpy(wy700->real_crtc, mode_80x24, sizeof(mode_80x24)); - } - else /* Text mode 40x24 */ - { - wy700->wy700_mode = 0; - memcpy(wy700->real_crtc, mode_40x24, sizeof(mode_40x24)); - } - } - /* Convert the cursor sizes from the ones used by the CGA or MDA - * to native */ + /* A control write with the top bit set selects graphics mode */ + if (dev->wy700_control & 0x80) { + /* Select hi-res graphics mode; map framebuffer at A0000 */ + mem_map_set_addr(&dev->mapping, 0xa0000, 0x20000); + dev->wy700_mode = dev->wy700_control; - if (wy700->cga_crtc[9] == 13) /* MDA scaling */ - { - curstart = wy700->cga_crtc[10] & 0x1F; - wy700->real_crtc[10] = ((curstart + 5) >> 3) + curstart; - if (wy700->real_crtc[10] > 31) wy700->real_crtc[10] = 31; - /* And bring 'cursor disabled' flag across */ - if ((wy700->cga_crtc[10] & 0x60) == 0x20) - { - wy700->real_crtc[10] |= 0x20; + /* Select appropriate preset timings */ + if (dev->wy700_mode & 0x40) { + memcpy(dev->real_crtc, mode_1280x800, + sizeof(mode_1280x800)); + } else if (dev->wy700_mode & 0x20) { + memcpy(dev->real_crtc, mode_1280x400, + sizeof(mode_1280x400)); + } else { + memcpy(dev->real_crtc, mode_640x400, + sizeof(mode_640x400)); } - curend = wy700->cga_crtc[11] & 0x1F; - wy700->real_crtc[11] = ((curend + 5) >> 3) + curend; - if (wy700->real_crtc[11] > 31) wy700->real_crtc[11] = 31; } - else /* CGA scaling */ - { - curstart = wy700->cga_crtc[10] & 0x1F; - wy700->real_crtc[10] = curstart << 1; - if (wy700->real_crtc[10] > 31) wy700->real_crtc[10] = 31; - /* And bring 'cursor disabled' flag across */ - if ((wy700->cga_crtc[10] & 0x60) == 0x20) - { - wy700->real_crtc[10] |= 0x20; - } - curend = wy700->cga_crtc[11] & 0x1F; - wy700->real_crtc[11] = curend << 1; - if (wy700->real_crtc[11] > 31) wy700->real_crtc[11] = 31; + } + + /* An attempt to program the CGA / MDA selects low-res mode */ + else if (dev->last_03D8 != dev->cga_ctrl) { + dev->last_03D8 = dev->cga_ctrl; + /* Set lo-res text or graphics mode. + * (Strictly speaking, when not in hi-res mode the card + * should be mapped at B0000-B3FFF and B8000-BBFFF, leaving + * a 16k hole between the two ranges) */ + mem_map_set_addr(&dev->mapping, 0xb0000, 0x0C000); + if (dev->cga_ctrl & 2) /* Graphics mode */ { + dev->wy700_mode = (dev->cga_ctrl & 0x10) ? 6 : 4; + memcpy(dev->real_crtc, mode_640x200, + sizeof(mode_640x200)); + } else if (dev->cga_ctrl & 1) /* Text mode 80x24 */ { + dev->wy700_mode = 2; + memcpy(dev->real_crtc, mode_80x24, sizeof(mode_80x24)); + } else /* Text mode 40x24 */ { + dev->wy700_mode = 0; + memcpy(dev->real_crtc, mode_40x24, sizeof(mode_40x24)); } + } + + /* Convert the cursor sizes from the ones used by the CGA or MDA to native */ + if (dev->cga_crtc[9] == 13) /* MDA scaling */ { + curstart = dev->cga_crtc[10] & 0x1F; + dev->real_crtc[10] = ((curstart + 5) >> 3) + curstart; + if (dev->real_crtc[10] > 31) dev->real_crtc[10] = 31; + /* And bring 'cursor disabled' flag across */ + if ((dev->cga_crtc[10] & 0x60) == 0x20) { + dev->real_crtc[10] |= 0x20; + } + curend = dev->cga_crtc[11] & 0x1F; + dev->real_crtc[11] = ((curend + 5) >> 3) + curend; + if (dev->real_crtc[11] > 31) dev->real_crtc[11] = 31; + } else /* CGA scaling */ { + curstart = dev->cga_crtc[10] & 0x1F; + dev->real_crtc[10] = curstart << 1; + if (dev->real_crtc[10] > 31) dev->real_crtc[10] = 31; + /* And bring 'cursor disabled' flag across */ + if ((dev->cga_crtc[10] & 0x60) == 0x20) { + dev->real_crtc[10] |= 0x20; + } + curend = dev->cga_crtc[11] & 0x1F; + dev->real_crtc[11] = curend << 1; + if (dev->real_crtc[11] > 31) dev->real_crtc[11] = 31; + } } -void wy700_write(uint32_t addr, uint8_t val, void *p) +static void +wy700_out(uint16_t port, uint8_t val, void *priv) { - wy700_t *wy700 = (wy700_t *)p; - egawrites++; + wy700_t *dev = (wy700_t *)priv; - if (wy700->wy700_mode & 0x80) /* High-res mode. */ - { - addr &= 0xFFFF; -/* In 800-line modes, bit 1 of the control register sets the high bit of the - * write address. */ - if ((wy700->wy700_mode & 0x42) == 0x42) - { - addr |= 0x10000; - } - wy700->vram[addr] = val; - } - else - { - wy700->vram[addr & 0x3fff] = val; - } + switch (port) { + /* These three registers are only mapped in the 3Dx range, + * not the 3Bx range. */ + case 0x3dd: /* Base address (low) */ + dev->wy700_base &= 0xFF00; + dev->wy700_base |= val; + check_changes(dev); + break; + + case 0x3de: /* Base address (high) */ + dev->wy700_base &= 0xFF; + dev->wy700_base |= ((uint16_t)val) << 8; + check_changes(dev); + break; + + case 0x3df: /* Command / control register */ + dev->wy700_control = val; + check_changes(dev); + break; + + /* Emulated CRTC, register select */ + case 0x3b0: case 0x3b2: case 0x3b4: case 0x3b6: + case 0x3d0: case 0x3d2: case 0x3d4: case 0x3d6: + dev->cga_crtcreg = val & 31; + break; + + /* Emulated CRTC, value */ + case 0x3b1: case 0x3b3: case 0x3b5: case 0x3b7: + case 0x3d1: case 0x3d3: case 0x3d5: case 0x3d7: + dev->cga_crtc[dev->cga_crtcreg] = val; + + check_changes(dev); + recalc_timings(dev); + return; + + /* Emulated MDA / CGA control register */ + case 0x3b8: + case 0x3d8: + dev->cga_ctrl = val; + check_changes(dev); + return; + + /* Emulated CGA colour register */ + case 0x3d9: + dev->cga_colour = val; + return; + } } - -uint8_t wy700_read(uint32_t addr, void *p) +static uint8_t +wy700_in(uint16_t port, void *priv) { - wy700_t *wy700 = (wy700_t *)p; - egareads++; - if (wy700->wy700_mode & 0x80) /* High-res mode. */ - { - addr &= 0xFFFF; -/* In 800-line modes, bit 0 of the control register sets the high bit of the - * read address. */ - if ((wy700->wy700_mode & 0x41) == 0x41) - { - addr |= 0x10000; - } - return wy700->vram[addr]; - } - else - { - return wy700->vram[addr & 0x3fff]; - } + wy700_t *dev = (wy700_t *)priv; + + switch (port) { + case 0x3b0: case 0x3b2: case 0x3b4: case 0x3b6: + case 0x3d0: case 0x3d2: case 0x3d4: case 0x3d6: + return dev->cga_crtcreg; + + case 0x3b1: case 0x3b3: case 0x3b5: case 0x3b7: + case 0x3d1: case 0x3d3: case 0x3d5: case 0x3d7: + return dev->cga_crtc[dev->cga_crtcreg]; + + case 0x3b8: case 0x3d8: + return dev->cga_ctrl; + + case 0x3d9: + return dev->cga_colour; + + case 0x3ba: + return dev->mda_stat; + + case 0x3da: + return dev->cga_stat; + } + + return 0xff; } - -void wy700_recalctimings(wy700_t *wy700) +static void +wy700_write(uint32_t addr, uint8_t val, void *priv) { - double disptime; - double _dispontime, _dispofftime; + wy700_t *dev = (wy700_t *)priv; - disptime = wy700->real_crtc[0] + 1; - _dispontime = wy700->real_crtc[1]; - _dispofftime = disptime - _dispontime; - _dispontime *= MDACONST; - _dispofftime *= MDACONST; - wy700->dispontime = (int64_t)(_dispontime * (1 << TIMER_SHIFT)); - wy700->dispofftime = (int64_t)(_dispofftime * (1 << TIMER_SHIFT)); + if (dev->wy700_mode & 0x80) { /* High-res mode. */ + addr &= 0xffff; + + /* In 800-line modes, bit 1 of the control register sets + * the high bit of the write address. + */ + if ((dev->wy700_mode & 0x42) == 0x42) { + addr |= 0x10000; + } + dev->vram[addr] = val; + } else { + dev->vram[addr & 0x3fff] = val; + } +} + + +static uint8_t +wy700_read(uint32_t addr, void *priv) +{ + wy700_t *dev = (wy700_t *)priv; + + if (dev->wy700_mode & 0x80) { /* High-res mode. */ + addr &= 0xffff; + + /* In 800-line modes, bit 0 of the control register sets + * the high bit of the read address. + */ + if ((dev->wy700_mode & 0x41) == 0x41) { + addr |= 0x10000; + } + return dev->vram[addr]; + } else { + return dev->vram[addr & 0x3fff]; + } } /* Draw a single line of the screen in either text mode */ -void wy700_textline(wy700_t *wy700) +static void +text_line(wy700_t *dev) { - int x; - int w = (wy700->wy700_mode == 0) ? 40 : 80; - int cw = (wy700->wy700_mode == 0) ? 32 : 16; - uint8_t chr, attr; - uint8_t bitmap[2]; - uint8_t *fontbase = &fontdatw[0][0]; - int blink, c; - int drawcursor, cursorline; - int mda = 0; - uint16_t addr; - uint8_t sc; - uint16_t ma = (wy700->cga_crtc[13] | (wy700->cga_crtc[12] << 8)) & 0x3fff; - uint16_t ca = (wy700->cga_crtc[15] | (wy700->cga_crtc[14] << 8)) & 0x3fff; + uint16_t ma = (dev->cga_crtc[13] | (dev->cga_crtc[12] << 8)) & 0x3fff; + uint16_t ca = (dev->cga_crtc[15] | (dev->cga_crtc[14] << 8)) & 0x3fff; + int x; + int w = (dev->wy700_mode == 0) ? 40 : 80; + int cw = (dev->wy700_mode == 0) ? 32 : 16; + uint8_t chr, attr; + uint8_t bitmap[2]; + uint8_t *fontbase = &fontdatw[0][0]; + int blink, c; + int drawcursor, cursorline; + int mda = 0; + uint16_t addr; + uint8_t sc; -/* The fake CRTC character height register selects whether MDA or CGA - * attributes are used */ - if (wy700->cga_crtc[9] == 0 || wy700->cga_crtc[9] == 13) - { - mda = 1; - } + /* The fake CRTC character height register selects whether MDA or CGA + * attributes are used */ + if (dev->cga_crtc[9] == 0 || dev->cga_crtc[9] == 13) { + mda = 1; + } - if (wy700->font) - { - fontbase += 256*32; - } - addr = ((ma & ~1) + (wy700->displine >> 5) * w) * 2; - sc = (wy700->displine >> 1) & 15; + if (dev->font) { + fontbase += 256*32; + } + addr = ((ma & ~1) + (dev->displine >> 5) * w) * 2; + sc = (dev->displine >> 1) & 15; - ma += ((wy700->displine >> 5) * w); + ma += ((dev->displine >> 5) * w); - if ((wy700->real_crtc[10] & 0x60) == 0x20) - { - cursorline = 0; - } - else - { - cursorline = ((wy700->real_crtc[10] & 0x1F) <= sc) && - ((wy700->real_crtc[11] & 0x1F) >= sc); - } + if ((dev->real_crtc[10] & 0x60) == 0x20) { + cursorline = 0; + } else { + cursorline = ((dev->real_crtc[10] & 0x1F) <= sc) && + ((dev->real_crtc[11] & 0x1F) >= sc); + } - for (x = 0; x < w; x++) - { - chr = wy700->vram[(addr + 2 * x) & 0x3FFF]; - attr = wy700->vram[(addr + 2 * x + 1) & 0x3FFF]; - drawcursor = ((ma == ca) && cursorline && wy700->enabled && - (wy700->cga_ctrl & 8) && (wy700->blink & 16)); - blink = ((wy700->blink & 16) && - (wy700->cga_ctrl & 0x20) && - (attr & 0x80) && !drawcursor); + for (x = 0; x < w; x++) { + chr = dev->vram[(addr + 2 * x) & 0x3FFF]; + attr = dev->vram[(addr + 2 * x + 1) & 0x3FFF]; + drawcursor = ((ma == ca) && cursorline && dev->enabled && + (dev->cga_ctrl & 8) && (dev->blink & 16)); + blink = ((dev->blink & 16) && + (dev->cga_ctrl & 0x20) && + (attr & 0x80) && !drawcursor); - if (wy700->cga_ctrl & 0x20) attr &= 0x7F; - /* MDA underline */ - if (sc == 14 && mda && ((attr & 7) == 1)) - { + if (dev->cga_ctrl & 0x20) attr &= 0x7F; + + /* MDA underline */ + if (sc == 14 && mda && ((attr & 7) == 1)) { + for (c = 0; c < cw; c++) + buffer->line[dev->displine][(x * cw) + c] = + dev->mdacols[attr][blink][1]; + } else { /* Draw 16 pixels of character */ + bitmap[0] = fontbase[chr * 32 + 2 * sc]; + bitmap[1] = fontbase[chr * 32 + 2 * sc + 1]; + for (c = 0; c < 16; c++) { + int col; + if (c < 8) + col = (mda ? dev->mdacols : dev->cgacols)[attr][blink][(bitmap[0] & (1 << (c ^ 7))) ? 1 : 0]; + else col = (mda ? dev->mdacols : dev->cgacols)[attr][blink][(bitmap[1] & (1 << ((c & 7) ^ 7))) ? 1 : 0]; + if (!(dev->enabled) || !(dev->cga_ctrl & 8)) + col = dev->mdacols[0][0][0]; + if (w == 40) { + buffer->line[dev->displine][(x * cw) + 2*c] = col; + buffer->line[dev->displine][(x * cw) + 2*c + 1] = col; + } else + buffer->line[dev->displine][(x * cw) + c] = col; + } + + if (drawcursor) { for (c = 0; c < cw; c++) - buffer->line[wy700->displine][(x * cw) + c] = - mdacols[attr][blink][1]; - } - else /* Draw 16 pixels of character */ - { - bitmap[0] = fontbase[chr * 32 + 2 * sc]; - bitmap[1] = fontbase[chr * 32 + 2 * sc + 1]; - for (c = 0; c < 16; c++) - { - int col; - if (c < 8) - col = (mda ? mdacols : cgacols)[attr][blink][(bitmap[0] & (1 << (c ^ 7))) ? 1 : 0]; - else col = (mda ? mdacols : cgacols)[attr][blink][(bitmap[1] & (1 << ((c & 7) ^ 7))) ? 1 : 0]; - if (!(wy700->enabled) || !(wy700->cga_ctrl & 8)) - col = mdacols[0][0][0]; - if (w == 40) - { - buffer->line[wy700->displine][(x * cw) + 2*c] = col; - buffer->line[wy700->displine][(x * cw) + 2*c + 1] = col; - } - else buffer->line[wy700->displine][(x * cw) + c] = col; - } - - if (drawcursor) - { - for (c = 0; c < cw; c++) - buffer->line[wy700->displine][(x * cw) + c] ^= (mda ? mdacols : cgacols)[attr][0][1]; - } - ++ma; + buffer->line[dev->displine][(x * cw) + c] ^= (mda ? dev->mdacols : dev->cgacols)[attr][0][1]; } + ++ma; } + } } /* Draw a line in either of the CGA graphics modes (320x200 or 640x200) */ -void wy700_cgaline(wy700_t *wy700) +static void +cga_line(wy700_t *dev) { - int x, c; - uint32_t dat; - uint8_t ink = 0; - uint16_t addr; + int x, c; + uint32_t dat; + uint8_t ink = 0; + uint16_t addr; + uint16_t ma = (dev->cga_crtc[13] | (dev->cga_crtc[12] << 8)) & 0x3fff; - uint16_t ma = (wy700->cga_crtc[13] | (wy700->cga_crtc[12] << 8)) & 0x3fff; - addr = ((wy700->displine >> 2) & 1) * 0x2000 + - (wy700->displine >> 3) * 80 + - ((ma & ~1) << 1); + addr = ((dev->displine >> 2) & 1) * 0x2000 + + (dev->displine >> 3) * 80 + ((ma & ~1) << 1); - /* The fixed mode setting here programs the real CRTC with a screen - * width to 20, so draw in 20 fixed chunks of 4 bytes each */ - for (x = 0; x < 20; x++) - { - dat = ((wy700->vram[addr & 0x3FFF] << 24) | - (wy700->vram[(addr+1) & 0x3FFF] << 16) | - (wy700->vram[(addr+2) & 0x3FFF] << 8) | - (wy700->vram[(addr+3) & 0x3FFF])); - addr += 4; + /* The fixed mode setting here programs the real CRTC with a screen + * width to 20, so draw in 20 fixed chunks of 4 bytes each */ + for (x = 0; x < 20; x++) { + dat = ((dev->vram[addr & 0x3FFF] << 24) | + (dev->vram[(addr+1) & 0x3FFF] << 16) | + (dev->vram[(addr+2) & 0x3FFF] << 8) | + (dev->vram[(addr+3) & 0x3FFF])); + addr += 4; - if (wy700->wy700_mode == 6) - { - for (c = 0; c < 32; c++) - { - ink = (dat & 0x80000000) ? 16 + 15: 16 + 0; - if (!(wy700->enabled) || !(wy700->cga_ctrl & 8)) - ink = 16; - buffer->line[wy700->displine][x*64 + 2*c] = - buffer->line[wy700->displine][x*64 + 2*c+1] = - ink; - dat = dat << 1; - } + if (dev->wy700_mode == 6) { + for (c = 0; c < 32; c++) { + ink = (dat & 0x80000000) ? 16 + 15: 16 + 0; + if (!(dev->enabled) || !(dev->cga_ctrl & 8)) + ink = 16; + buffer->line[dev->displine][x*64 + 2*c] = buffer->line[dev->displine][x*64 + 2*c+1] = ink; + dat = dat << 1; } - else - { - for (c = 0; c < 16; c++) - { - switch ((dat >> 30) & 3) - { - case 0: ink = 16 + 0; break; - case 1: ink = 16 + 8; break; - case 2: ink = 16 + 7; break; - case 3: ink = 16 + 15; break; - } - if (!(wy700->enabled) || !(wy700->cga_ctrl & 8)) - ink = 16; - buffer->line[wy700->displine][x*64 + 4*c] = - buffer->line[wy700->displine][x*64 + 4*c+1] = - buffer->line[wy700->displine][x*64 + 4*c+2] = - buffer->line[wy700->displine][x*64 + 4*c+3] = - ink; - dat = dat << 2; + } else { + for (c = 0; c < 16; c++) { + switch ((dat >> 30) & 3) { + case 0: ink = 16 + 0; break; + case 1: ink = 16 + 8; break; + case 2: ink = 16 + 7; break; + case 3: ink = 16 + 15; break; } + if (!(dev->enabled) || !(dev->cga_ctrl & 8)) + ink = 16; + buffer->line[dev->displine][x*64 + 4*c] = buffer->line[dev->displine][x*64 + 4*c+1] = buffer->line[dev->displine][x*64 + 4*c+2] = buffer->line[dev->displine][x*64 + 4*c+3] = ink; + dat = dat << 2; } } + } } + /* Draw a line in the medium-resolution graphics modes (640x400 or 320x400) */ -void wy700_medresline(wy700_t *wy700) +static void +medres_line(wy700_t *dev) { - int x, c; - uint32_t dat; - uint8_t ink = 0; - uint32_t addr; + int x, c; + uint32_t dat; + uint8_t ink = 0; + uint32_t addr; - addr = (wy700->displine >> 1) * 80 + 4 * wy700->wy700_base; + addr = (dev->displine >> 1) * 80 + 4 * dev->wy700_base; - for (x = 0; x < 20; x++) - { - dat = ((wy700->vram[addr & 0x1FFFF] << 24) | - (wy700->vram[(addr+1) & 0x1FFFF] << 16) | - (wy700->vram[(addr+2) & 0x1FFFF] << 8) | - (wy700->vram[(addr+3) & 0x1FFFF])); - addr += 4; + for (x = 0; x < 20; x++) { + dat = ((dev->vram[addr & 0x1FFFF] << 24) | + (dev->vram[(addr+1) & 0x1FFFF] << 16) | + (dev->vram[(addr+2) & 0x1FFFF] << 8) | + (dev->vram[(addr+3) & 0x1FFFF])); + addr += 4; - if (wy700->wy700_mode & 0x10) - { - for (c = 0; c < 16; c++) - { - switch ((dat >> 30) & 3) - { - case 0: ink = 16 + 0; break; - case 1: ink = 16 + 8; break; - case 2: ink = 16 + 7; break; - case 3: ink = 16 + 15; break; - } - /* Display disabled? */ - if (!(wy700->wy700_mode & 8)) ink = 16; - buffer->line[wy700->displine][x*64 + 4*c] = - buffer->line[wy700->displine][x*64 + 4*c+1] = - buffer->line[wy700->displine][x*64 + 4*c+2] = - buffer->line[wy700->displine][x*64 + 4*c+3] = - ink; - dat = dat << 2; + if (dev->wy700_mode & 0x10) { + for (c = 0; c < 16; c++) { + switch ((dat >> 30) & 3) { + case 0: ink = 16 + 0; break; + case 1: ink = 16 + 8; break; + case 2: ink = 16 + 7; break; + case 3: ink = 16 + 15; break; } + + /* Display disabled? */ + if (!(dev->wy700_mode & 8)) ink = 16; + buffer->line[dev->displine][x*64 + 4*c] = buffer->line[dev->displine][x*64 + 4*c+1] = buffer->line[dev->displine][x*64 + 4*c+2] = buffer->line[dev->displine][x*64 + 4*c+3] = ink; + dat = dat << 2; } - else - { - for (c = 0; c < 32; c++) - { - ink = (dat & 0x80000000) ? 16 + 15: 16 + 0; - /* Display disabled? */ - if (!(wy700->wy700_mode & 8)) ink = 16; - buffer->line[wy700->displine][x*64 + 2*c] = - buffer->line[wy700->displine][x*64 + 2*c+1] = - ink; - dat = dat << 1; - } + } else { + for (c = 0; c < 32; c++) { + ink = (dat & 0x80000000) ? 16 + 15: 16 + 0; + + /* Display disabled? */ + if (!(dev->wy700_mode & 8)) ink = 16; + buffer->line[dev->displine][x*64 + 2*c] = buffer->line[dev->displine][x*64 + 2*c+1] = ink; + dat = dat << 1; } } + } } - - /* Draw a line in one of the high-resolution modes */ -void wy700_hiresline(wy700_t *wy700) +static void +hires_line(wy700_t *dev) { - int x, c; - uint32_t dat; - uint8_t ink = 0; - uint32_t addr; + int x, c; + uint32_t dat; + uint8_t ink = 0; + uint32_t addr; - addr = (wy700->displine >> 1) * 160 + 4 * wy700->wy700_base; + addr = (dev->displine >> 1) * 160 + 4 * dev->wy700_base; - if (wy700->wy700_mode & 0x40) /* 800-line interleaved modes */ - { - if (wy700->displine & 1) addr += 0x10000; - } - for (x = 0; x < 40; x++) - { - dat = ((wy700->vram[addr & 0x1FFFF] << 24) | - (wy700->vram[(addr+1) & 0x1FFFF] << 16) | - (wy700->vram[(addr+2) & 0x1FFFF] << 8) | - (wy700->vram[(addr+3) & 0x1FFFF])); - addr += 4; + if (dev->wy700_mode & 0x40) { /* 800-line interleaved modes */ + if (dev->displine & 1) addr += 0x10000; + } - if (wy700->wy700_mode & 0x10) - { - for (c = 0; c < 16; c++) - { - switch ((dat >> 30) & 3) - { - case 0: ink = 16 + 0; break; - case 1: ink = 16 + 8; break; - case 2: ink = 16 + 7; break; - case 3: ink = 16 + 15; break; - } - /* Display disabled? */ - if (!(wy700->wy700_mode & 8)) ink = 16; - buffer->line[wy700->displine][x*32 + 2*c] = - buffer->line[wy700->displine][x*32 + 2*c+1] = - ink; - dat = dat << 2; + for (x = 0; x < 40; x++) { + dat = ((dev->vram[addr & 0x1FFFF] << 24) | + (dev->vram[(addr+1) & 0x1FFFF] << 16) | + (dev->vram[(addr+2) & 0x1FFFF] << 8) | + (dev->vram[(addr+3) & 0x1FFFF])); + addr += 4; + + if (dev->wy700_mode & 0x10) { + for (c = 0; c < 16; c++) { + switch ((dat >> 30) & 3) { + case 0: ink = 16 + 0; break; + case 1: ink = 16 + 8; break; + case 2: ink = 16 + 7; break; + case 3: ink = 16 + 15; break; } + + /* Display disabled? */ + if (!(dev->wy700_mode & 8)) ink = 16; + buffer->line[dev->displine][x*32 + 2*c] = buffer->line[dev->displine][x*32 + 2*c+1] = ink; + dat = dat << 2; } - else - { - for (c = 0; c < 32; c++) - { - ink = (dat & 0x80000000) ? 16 + 15: 16 + 0; - /* Display disabled? */ - if (!(wy700->wy700_mode & 8)) ink = 16; - buffer->line[wy700->displine][x*32 + c] = ink; - dat = dat << 1; - } + } else { + for (c = 0; c < 32; c++) { + ink = (dat & 0x80000000) ? 16 + 15: 16 + 0; + + /* Display disabled? */ + if (!(dev->wy700_mode & 8)) ink = 16; + buffer->line[dev->displine][x*32 + c] = ink; + dat = dat << 1; } } + } } - - -void wy700_poll(void *p) +static void +wy700_poll(void *priv) { - wy700_t *wy700 = (wy700_t *)p; - int mode; + wy700_t *dev = (wy700_t *)priv; + int mode; - if (!wy700->linepos) - { - wy700->vidtime += wy700->dispofftime; - wy700->cga_stat |= 1; - wy700->mda_stat |= 1; - wy700->linepos = 1; - if (wy700->dispon) - { - if (wy700->displine == 0) - { - video_wait_for_buffer(); - } + if (! dev->linepos) { + dev->vidtime += dev->dispofftime; + dev->cga_stat |= 1; + dev->mda_stat |= 1; + dev->linepos = 1; + if (dev->dispon) { + if (dev->displine == 0) + video_wait_for_buffer(); - if (wy700->wy700_mode & 0x80) - mode = wy700->wy700_mode & 0xF0; - else mode = wy700->wy700_mode & 0x0F; + if (dev->wy700_mode & 0x80) + mode = dev->wy700_mode & 0xF0; + else + mode = dev->wy700_mode & 0x0F; - switch (mode) - { - default: - case 0x00: - case 0x02: - wy700_textline(wy700); - break; - case 0x04: - case 0x06: - wy700_cgaline(wy700); - break; - case 0x80: - case 0x90: - wy700_medresline(wy700); - break; - case 0xA0: - case 0xB0: - case 0xC0: - case 0xD0: - case 0xE0: - case 0xF0: - wy700_hiresline(wy700); - break; - } - } - wy700->displine++; - /* Hardcode a fixed refresh rate and VSYNC timing */ - if (wy700->displine == 800) /* Start of VSYNC */ - { - wy700->cga_stat |= 8; - wy700->dispon = 0; - } - if (wy700->displine == 832) /* End of VSYNC */ - { - wy700->displine = 0; - wy700->cga_stat &= ~8; - wy700->dispon = 1; + switch (mode) { + default: + case 0x00: + case 0x02: + text_line(dev); + break; + + case 0x04: + case 0x06: + cga_line(dev); + break; + + case 0x80: + case 0x90: + medres_line(dev); + break; + + case 0xA0: + case 0xB0: + case 0xC0: + case 0xD0: + case 0xE0: + case 0xF0: + hires_line(dev); + break; } - } - else - { - if (wy700->dispon) - { - wy700->cga_stat &= ~1; - wy700->mda_stat &= ~1; + } + dev->displine++; + + /* Hardcode a fixed refresh rate and VSYNC timing */ + if (dev->displine == 800){ + /* Start of VSYNC */ + dev->cga_stat |= 8; + dev->dispon = 0; + } + if (dev->displine == 832) { + /* End of VSYNC */ + dev->displine = 0; + dev->cga_stat &= ~8; + dev->dispon = 1; + } + } else { + if (dev->dispon) { + dev->cga_stat &= ~1; + dev->mda_stat &= ~1; + } + dev->vidtime += dev->dispontime; + dev->linepos = 0; + + if (dev->displine == 800) { + /* Hardcode 1280x800 window size */ + if ((WY700_XSIZE != xsize) || (WY700_YSIZE != ysize) || video_force_resize_get()) { + xsize = WY700_XSIZE; + ysize = WY700_YSIZE; + if (xsize < 64) xsize = 656; + if (ysize < 32) ysize = 200; + set_screen_size(xsize, ysize); + + if (video_force_resize_get()) + video_force_resize_set(0); } - wy700->vidtime += wy700->dispontime; - wy700->linepos = 0; + video_blit_memtoscreen_8(0, 0, 0, ysize, xsize, ysize); - if (wy700->displine == 800) - { -/* Hardcode 1280x800 window size */ - if ((WY700_XSIZE != xsize) || (WY700_YSIZE != ysize) || video_force_resize_get()) - { - xsize = WY700_XSIZE; - ysize = WY700_YSIZE; - if (xsize < 64) xsize = 656; - if (ysize < 32) ysize = 200; - set_screen_size(xsize, ysize); + frames++; - if (video_force_resize_get()) - video_force_resize_set(0); - } - video_blit_memtoscreen_8(0, 0, 0, ysize, xsize, ysize); + /* Fixed 1280x800 resolution */ + video_res_x = WY700_XSIZE; + video_res_y = WY700_YSIZE; + if (dev->wy700_mode & 0x80) - frames++; - /* Fixed 1280x800 resolution */ - video_res_x = WY700_XSIZE; - video_res_y = WY700_YSIZE; - if (wy700->wy700_mode & 0x80) - mode = wy700->wy700_mode & 0xF0; - else mode = wy700->wy700_mode & 0x0F; - switch(mode) - { - case 0x00: - case 0x02: video_bpp = 0; break; - case 0x04: - case 0x90: - case 0xB0: - case 0xD0: - case 0xF0: video_bpp = 2; break; - default: video_bpp = 1; break; - } - wy700->blink++; - } - } + mode = dev->wy700_mode & 0xF0; + else + mode = dev->wy700_mode & 0x0F; + + switch(mode) { + case 0x00: + case 0x02: video_bpp = 0; break; + case 0x04: + case 0x90: + case 0xB0: + case 0xD0: + case 0xF0: video_bpp = 2; break; + default: video_bpp = 1; break; + } + dev->blink++; + } + } } -void *wy700_init(const device_t *info) +static void * +wy700_init(const device_t *info) { - int c; - wy700_t *wy700 = malloc(sizeof(wy700_t)); - memset(wy700, 0, sizeof(wy700_t)); + wy700_t *dev; + int c; - /* 128k video RAM */ - wy700->vram = malloc(0x20000); + dev = (wy700_t *)mem_alloc(sizeof(wy700_t)); + memset(dev, 0x00, sizeof(wy700_t)); - timer_add(wy700_poll, &wy700->vidtime, TIMER_ALWAYS_ENABLED, wy700); + /* 128k video RAM */ + dev->vram = (uint8_t *)mem_alloc(0x20000); - /* Occupy memory between 0xB0000 and 0xBFFFF (moves to 0xA0000 in - * high-resolution modes) */ - mem_mapping_add(&wy700->mapping, 0xb0000, 0x10000, wy700_read, NULL, NULL, wy700_write, NULL, NULL, NULL, MEM_MAPPING_EXTERNAL, wy700); - /* Respond to both MDA and CGA I/O ports */ - io_sethandler(0x03b0, 0x000C, wy700_in, NULL, NULL, wy700_out, NULL, NULL, wy700); - io_sethandler(0x03d0, 0x0010, wy700_in, NULL, NULL, wy700_out, NULL, NULL, wy700); + video_load_font(BIOS_ROM_PATH, 3); - /* Set up the emulated attributes. - * CGA is done in four groups: 00-0F, 10-7F, 80-8F, 90-FF */ - for (c = 0; c < 0x10; c++) - { - cgacols[c][0][0] = cgacols[c][1][0] = cgacols[c][1][1] = 16; - if (c & 8) cgacols[c][0][1] = 15 + 16; - else cgacols[c][0][1] = 7 + 16; - } - for (c = 0x10; c < 0x80; c++) - { - cgacols[c][0][0] = cgacols[c][1][0] = cgacols[c][1][1] = 16 + 7; - if (c & 8) cgacols[c][0][1] = 15 + 16; - else cgacols[c][0][1] = 0 + 16; + timer_add(wy700_poll, &dev->vidtime, TIMER_ALWAYS_ENABLED, dev); - if ((c & 0x0F) == 8) cgacols[c][0][1] = 8 + 16; - } - /* With special cases for 00, 11, 22, ... 77 */ - cgacols[0x00][0][1] = cgacols[0x00][1][1] = 16; - for (c = 0x11; c <= 0x77; c += 0x11) - { - cgacols[c][0][1] = cgacols[c][1][1] = 16 + 7; - } - for (c = 0x80; c < 0x90; c++) - { - cgacols[c][0][0] = 16 + 8; - if (c & 8) cgacols[c][0][1] = 15 + 16; - else cgacols[c][0][1] = 7 + 16; - cgacols[c][1][0] = cgacols[c][1][1] = cgacols[c-0x80][0][0]; - } - for (c = 0x90; c < 0x100; c++) - { - cgacols[c][0][0] = 16 + 15; - if (c & 8) cgacols[c][0][1] = 8 + 16; - else cgacols[c][0][1] = 7 + 16; - if ((c & 0x0F) == 0) cgacols[c][0][1] = 16; - cgacols[c][1][0] = cgacols[c][1][1] = cgacols[c-0x80][0][0]; - } - /* Also special cases for 99, AA, ..., FF */ - for (c = 0x99; c <= 0xFF; c += 0x11) - { - cgacols[c][0][1] = 16 + 15; - } - /* Special cases for 08, 80 and 88 */ - cgacols[0x08][0][1] = 16 + 8; - cgacols[0x80][0][1] = 16; - cgacols[0x88][0][1] = 16 + 8; + /* Occupy memory between 0xB0000 and 0xBFFFF (moves to 0xA0000 in + * high-resolution modes) + */ + mem_map_add(&dev->mapping, 0xb0000, 0x10000, + wy700_read,NULL,NULL, wy700_write,NULL,NULL, + NULL, MEM_MAPPING_EXTERNAL, dev); - /* MDA attributes */ - for (c = 0; c < 256; c++) - { - mdacols[c][0][0] = mdacols[c][1][0] = mdacols[c][1][1] = 16; - if (c & 8) mdacols[c][0][1] = 15 + 16; - else mdacols[c][0][1] = 7 + 16; - } - mdacols[0x70][0][1] = 16; - mdacols[0x70][0][0] = mdacols[0x70][1][0] = mdacols[0x70][1][1] = 16 + 15; - mdacols[0xF0][0][1] = 16; - mdacols[0xF0][0][0] = mdacols[0xF0][1][0] = mdacols[0xF0][1][1] = 16 + 15; - mdacols[0x78][0][1] = 16 + 7; - mdacols[0x78][0][0] = mdacols[0x78][1][0] = mdacols[0x78][1][1] = 16 + 15; - mdacols[0xF8][0][1] = 16 + 7; - mdacols[0xF8][0][0] = mdacols[0xF8][1][0] = mdacols[0xF8][1][1] = 16 + 15; - mdacols[0x00][0][1] = mdacols[0x00][1][1] = 16; - mdacols[0x08][0][1] = mdacols[0x08][1][1] = 16; - mdacols[0x80][0][1] = mdacols[0x80][1][1] = 16; - mdacols[0x88][0][1] = mdacols[0x88][1][1] = 16; + /* Respond to both MDA and CGA I/O ports */ + io_sethandler(0x03b0, 12, + wy700_in,NULL,NULL, wy700_out,NULL,NULL, dev); + io_sethandler(0x03d0, 16, + wy700_in,NULL,NULL, wy700_out,NULL,NULL, dev); -/* Start off in 80x25 text mode */ - wy700->cga_stat = 0xF4; - wy700->wy700_mode = 2; - wy700->enabled = 1; - memcpy(wy700->real_crtc, mode_80x24, sizeof(mode_80x24)); - return wy700; + /* Set up the emulated attributes. + * CGA is done in four groups: 00-0F, 10-7F, 80-8F, 90-FF */ + for (c = 0; c < 0x10; c++) { + dev->cgacols[c][0][0] = dev->cgacols[c][1][0] = dev->cgacols[c][1][1] = 16; + if (c & 8) + dev->cgacols[c][0][1] = 15 + 16; + else + dev->cgacols[c][0][1] = 7 + 16; + } + for (c = 0x10; c < 0x80; c++) { + dev->cgacols[c][0][0] = dev->cgacols[c][1][0] = dev->cgacols[c][1][1] = 16 + 7; + if (c & 8) + dev->cgacols[c][0][1] = 15 + 16; + else + dev->cgacols[c][0][1] = 0 + 16; + if ((c & 0x0F) == 8) + dev->cgacols[c][0][1] = 8 + 16; + } + + /* With special cases for 00, 11, 22, ... 77 */ + dev->cgacols[0x00][0][1] = dev->cgacols[0x00][1][1] = 16; + for (c = 0x11; c <= 0x77; c += 0x11) { + dev->cgacols[c][0][1] = dev->cgacols[c][1][1] = 16 + 7; + } + for (c = 0x80; c < 0x90; c++) { + dev->cgacols[c][0][0] = 16 + 8; + if (c & 8) + dev->cgacols[c][0][1] = 15 + 16; + else + dev->cgacols[c][0][1] = 7 + 16; + dev->cgacols[c][1][0] = dev->cgacols[c][1][1] = dev->cgacols[c-0x80][0][0]; + } + for (c = 0x90; c < 0x100; c++) { + dev->cgacols[c][0][0] = 16 + 15; + if (c & 8) + dev->cgacols[c][0][1] = 8 + 16; + else + dev->cgacols[c][0][1] = 7 + 16; + if ((c & 0x0F) == 0) + dev->cgacols[c][0][1] = 16; + dev->cgacols[c][1][0] = dev->cgacols[c][1][1] = dev->cgacols[c-0x80][0][0]; + } + /* Also special cases for 99, AA, ..., FF */ + for (c = 0x99; c <= 0xFF; c += 0x11) + dev->cgacols[c][0][1] = 16 + 15; + /* Special cases for 08, 80 and 88 */ + dev->cgacols[0x08][0][1] = 16 + 8; + dev->cgacols[0x80][0][1] = 16; + dev->cgacols[0x88][0][1] = 16 + 8; + + /* MDA attributes */ + for (c = 0; c < 256; c++) { + dev->mdacols[c][0][0] = dev->mdacols[c][1][0] = dev->mdacols[c][1][1] = 16; + if (c & 8) + dev->mdacols[c][0][1] = 15 + 16; + else + dev->mdacols[c][0][1] = 7 + 16; + } + dev->mdacols[0x70][0][1] = 16; + dev->mdacols[0x70][0][0] = dev->mdacols[0x70][1][0] = dev->mdacols[0x70][1][1] = 16 + 15; + dev->mdacols[0xF0][0][1] = 16; + dev->mdacols[0xF0][0][0] = dev->mdacols[0xF0][1][0] = dev->mdacols[0xF0][1][1] = 16 + 15; + dev->mdacols[0x78][0][1] = 16 + 7; + dev->mdacols[0x78][0][0] = dev->mdacols[0x78][1][0] = dev->mdacols[0x78][1][1] = 16 + 15; + dev->mdacols[0xF8][0][1] = 16 + 7; + dev->mdacols[0xF8][0][0] = dev->mdacols[0xF8][1][0] = dev->mdacols[0xF8][1][1] = 16 + 15; + dev->mdacols[0x00][0][1] = dev->mdacols[0x00][1][1] = 16; + dev->mdacols[0x08][0][1] = dev->mdacols[0x08][1][1] = 16; + dev->mdacols[0x80][0][1] = dev->mdacols[0x80][1][1] = 16; + dev->mdacols[0x88][0][1] = dev->mdacols[0x88][1][1] = 16; + + /* Start off in 80x25 text mode */ + dev->cga_stat = 0xF4; + dev->wy700_mode = 2; + dev->enabled = 1; + memcpy(dev->real_crtc, mode_80x24, sizeof(mode_80x24)); + + video_inform(VID_TYPE_CGA, info->vid_timing); + + return dev; } -void wy700_close(void *p) -{ - wy700_t *wy700 = (wy700_t *)p; - free(wy700->vram); - free(wy700); +static void +wy700_close(void *priv) +{ + wy700_t *dev = (wy700_t *)priv; + + free(dev->vram); + free(dev); } -void wy700_speed_changed(void *p) + +static int +wy700_available(void) { - wy700_t *wy700 = (wy700_t *)p; - - wy700_recalctimings(wy700); + return rom_present(BIOS_ROM_PATH); } -const device_t wy700_device = + +static void +speed_changed(void *priv) { - "Wyse 700", - DEVICE_ISA, 0, - wy700_init, - wy700_close, - NULL, - NULL, - wy700_speed_changed, - NULL, - NULL, - NULL + wy700_t *dev = (wy700_t *)priv; + + recalc_timings(dev); +} + + +static const video_timings_t wy700_timings = { VID_ISA,8,16,32,8,16,32 }; + +const device_t wy700_device = { + "Wyse 700", + DEVICE_ISA, + 0, + wy700_init, wy700_close, NULL, + wy700_available, + speed_changed, + NULL, + &wy700_timings, + NULL }; diff --git a/src/devices/video/video.c b/src/devices/video/video.c index b3dee88..489c384 100644 --- a/src/devices/video/video.c +++ b/src/devices/video/video.c @@ -40,7 +40,7 @@ * W = 3 bus clocks * L = 4 bus clocks * - * Version: @(#)video.c 1.0.17 2018/08/25 + * Version: @(#)video.c 1.0.18 2018/10/05 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -72,11 +72,13 @@ #include #include #include +#include #include #include +#define HAVE_STDARG_H +#define dbglog video_log #include "../../emu.h" #include "../../cpu/cpu.h" -#include "../../machines/machine.h" #include "../../io.h" #include "../../mem.h" #include "../../rom.h" @@ -86,23 +88,17 @@ #include "vid_svga.h" -enum { - VIDEO_ISA = 0, - VIDEO_MCA, - VIDEO_BUS -}; - - -int vid_present[VID_MAX]; -bitmap_t *screen = NULL, - *buffer = NULL, +#ifdef ENABLE_VIDEO_LOG +int video_do_log = ENABLE_VIDEO_LOG; +#endif +bitmap_t *buffer = NULL, *buffer32 = NULL; uint8_t fontdat[2048][8]; /* IBM CGA font */ uint8_t fontdatm[2048][16]; /* IBM MDA font */ uint8_t fontdatw[512][32]; /* Wyse700 font */ uint8_t fontdat8x12[256][16]; /* MDSI Genius font */ -dbcs_font_t *fontdatksc5601, /* Korean KSC-5601 font */ - *fontdatksc5601_user; /* Korean KSC-5601 user defined font */ +dbcs_font_t *fontdatksc5601 = NULL, /* Korean KSC-5601 font */ + *fontdatksc5601_user = NULL; /* Korean KSC-5601 font (user)*/ uint32_t pal_lookup[256]; int xsize = 1, ysize = 1; @@ -110,9 +106,7 @@ int cga_palette = 0; uint32_t *video_6to8 = NULL, *video_15to32 = NULL, *video_16to32 = NULL; -int egareads = 0, - egawrites = 0, - changeframecount = 2; +int changeframecount = 2; uint8_t rotatevga[8][256]; int frames = 0; int fullchange = 0; @@ -129,15 +123,6 @@ int video_timing_write_b = 0, int video_res_x = 0, video_res_y = 0, video_bpp = 0; -const int video_timing[7][4] = { - { VIDEO_ISA, 8, 16, 32 }, - { VIDEO_ISA, 6, 8, 16 }, - { VIDEO_ISA, 3, 3, 6 }, - { VIDEO_MCA, 4, 5, 10 }, - { VIDEO_BUS, 4, 8, 16 }, - { VIDEO_BUS, 4, 5, 10 }, - { VIDEO_BUS, 3, 3, 4 } -}; PALETTE cgapal = { {0,0,0}, {0,42,0}, {42,0,0}, {42,21,0}, {0,0,0}, {0,42,42}, {42,0,42}, {42,42,42}, @@ -165,42 +150,256 @@ PALETTE cgapal_mono[6] = { {0x01,0x1a,0x06},{0x02,0x28,0x09},{0x02,0x2c,0x0a}, {0x03,0x39,0x0d},{0x03,0x3c,0x0e},{0x00,0x07,0x01}, {0x01,0x13,0x04},{0x01,0x1f,0x07},{0x01,0x23,0x08}, - {0x02,0x31,0x0b},{0x02,0x35,0x0c},{0x05,0x3f,0x11},{0x0d,0x3f,0x17}, + {0x02,0x31,0x0b},{0x02,0x35,0x0c},{0x05,0x3f,0x11}, + {0x0d,0x3f,0x17}, }, { /* 1 - green, 16-color-optimized contrast. */ {0x00,0x00,0x00},{0x00,0x0d,0x03},{0x01,0x15,0x05}, {0x01,0x17,0x05},{0x01,0x21,0x08},{0x01,0x24,0x08}, {0x02,0x2e,0x0b},{0x02,0x31,0x0b},{0x01,0x22,0x08}, {0x02,0x28,0x09},{0x02,0x30,0x0b},{0x02,0x32,0x0c}, - {0x03,0x39,0x0d},{0x03,0x3b,0x0e},{0x09,0x3f,0x14},{0x0d,0x3f,0x17}, + {0x03,0x39,0x0d},{0x03,0x3b,0x0e},{0x09,0x3f,0x14}, + {0x0d,0x3f,0x17}, }, { /* 2 - amber, 4-color-optimized contrast. */ {0x00,0x00,0x00},{0x15,0x05,0x00},{0x20,0x0b,0x00}, {0x24,0x0d,0x00},{0x33,0x18,0x00},{0x37,0x1b,0x00}, {0x3f,0x26,0x01},{0x3f,0x2b,0x06},{0x0b,0x02,0x00}, {0x1b,0x08,0x00},{0x29,0x11,0x00},{0x2e,0x14,0x00}, - {0x3b,0x1e,0x00},{0x3e,0x21,0x00},{0x3f,0x32,0x0a},{0x3f,0x38,0x0d}, + {0x3b,0x1e,0x00},{0x3e,0x21,0x00},{0x3f,0x32,0x0a}, + {0x3f,0x38,0x0d}, }, { /* 3 - amber, 16-color-optimized contrast. */ {0x00,0x00,0x00},{0x15,0x05,0x00},{0x1e,0x09,0x00}, {0x21,0x0b,0x00},{0x2b,0x12,0x00},{0x2f,0x15,0x00}, {0x38,0x1c,0x00},{0x3b,0x1e,0x00},{0x2c,0x13,0x00}, {0x32,0x17,0x00},{0x3a,0x1e,0x00},{0x3c,0x1f,0x00}, - {0x3f,0x27,0x01},{0x3f,0x2a,0x04},{0x3f,0x36,0x0c},{0x3f,0x38,0x0d}, + {0x3f,0x27,0x01},{0x3f,0x2a,0x04},{0x3f,0x36,0x0c}, + {0x3f,0x38,0x0d}, }, { /* 4 - grey, 4-color-optimized contrast. */ {0x00,0x00,0x00},{0x0e,0x0f,0x10},{0x15,0x17,0x18}, {0x18,0x1a,0x1b},{0x24,0x25,0x25},{0x27,0x28,0x28}, {0x33,0x34,0x32},{0x37,0x38,0x35},{0x09,0x0a,0x0b}, {0x11,0x12,0x13},{0x1c,0x1e,0x1e},{0x20,0x22,0x22}, - {0x2c,0x2d,0x2c},{0x2f,0x30,0x2f},{0x3c,0x3c,0x38},{0x3f,0x3f,0x3b}, + {0x2c,0x2d,0x2c},{0x2f,0x30,0x2f},{0x3c,0x3c,0x38}, + {0x3f,0x3f,0x3b}, }, { /* 5 - grey, 16-color-optimized contrast. */ {0x00,0x00,0x00},{0x0e,0x0f,0x10},{0x13,0x14,0x15}, {0x15,0x17,0x18},{0x1e,0x20,0x20},{0x20,0x22,0x22}, {0x29,0x2a,0x2a},{0x2c,0x2d,0x2c},{0x1f,0x21,0x21}, {0x23,0x25,0x25},{0x2b,0x2c,0x2b},{0x2d,0x2e,0x2d}, - {0x34,0x35,0x33},{0x37,0x37,0x34},{0x3e,0x3e,0x3a},{0x3f,0x3f,0x3b}, + {0x34,0x35,0x33},{0x37,0x37,0x34},{0x3e,0x3e,0x3a}, + {0x3f,0x3f,0x3b}, + } +}; + +static const video_timings_t timing_default = { + VID_ISA, 8, 16, 32, 8, 16, 32 +}; +static const video_timings_t *video_timing; +static int video_card_type; +static const uint32_t shade[5][256] = { + {0},/* RGB Color (unused) */ + {0},/* RGB Grayscale (unused) */ + { /* Amber monitor */ + 0x000000, 0x060000, 0x090000, 0x0d0000, + 0x100000, 0x120100, 0x150100, 0x170100, + 0x1a0100, 0x1c0100, 0x1e0200, 0x210200, + 0x230200, 0x250300, 0x270300, 0x290300, + 0x2b0400, 0x2d0400, 0x2f0400, 0x300500, + 0x320500, 0x340500, 0x360600, 0x380600, + 0x390700, 0x3b0700, 0x3d0700, 0x3f0800, + 0x400800, 0x420900, 0x440900, 0x450a00, + 0x470a00, 0x480b00, 0x4a0b00, 0x4c0c00, + 0x4d0c00, 0x4f0d00, 0x500d00, 0x520e00, + 0x530e00, 0x550f00, 0x560f00, 0x581000, + 0x591000, 0x5b1100, 0x5c1200, 0x5e1200, + 0x5f1300, 0x601300, 0x621400, 0x631500, + 0x651500, 0x661600, 0x671600, 0x691700, + 0x6a1800, 0x6c1800, 0x6d1900, 0x6e1a00, + 0x701a00, 0x711b00, 0x721c00, 0x741c00, + 0x751d00, 0x761e00, 0x781e00, 0x791f00, + 0x7a2000, 0x7c2000, 0x7d2100, 0x7e2200, + 0x7f2300, 0x812300, 0x822400, 0x832500, + 0x842600, 0x862600, 0x872700, 0x882800, + 0x8a2900, 0x8b2900, 0x8c2a00, 0x8d2b00, + 0x8e2c00, 0x902c00, 0x912d00, 0x922e00, + 0x932f00, 0x953000, 0x963000, 0x973100, + 0x983200, 0x993300, 0x9b3400, 0x9c3400, + 0x9d3500, 0x9e3600, 0x9f3700, 0xa03800, + 0xa23900, 0xa33a00, 0xa43a00, 0xa53b00, + 0xa63c00, 0xa73d00, 0xa93e00, 0xaa3f00, + 0xab4000, 0xac4000, 0xad4100, 0xae4200, + 0xaf4300, 0xb14400, 0xb24500, 0xb34600, + 0xb44700, 0xb54800, 0xb64900, 0xb74a00, + 0xb94a00, 0xba4b00, 0xbb4c00, 0xbc4d00, + 0xbd4e00, 0xbe4f00, 0xbf5000, 0xc05100, + 0xc15200, 0xc25300, 0xc45400, 0xc55500, + 0xc65600, 0xc75700, 0xc85800, 0xc95900, + 0xca5a00, 0xcb5b00, 0xcc5c00, 0xcd5d00, + 0xce5e00, 0xcf5f00, 0xd06000, 0xd26101, + 0xd36201, 0xd46301, 0xd56401, 0xd66501, + 0xd76601, 0xd86701, 0xd96801, 0xda6901, + 0xdb6a01, 0xdc6b01, 0xdd6c01, 0xde6d01, + 0xdf6e01, 0xe06f01, 0xe17001, 0xe27201, + 0xe37301, 0xe47401, 0xe57501, 0xe67602, + 0xe77702, 0xe87802, 0xe97902, 0xeb7a02, + 0xec7b02, 0xed7c02, 0xee7e02, 0xef7f02, + 0xf08002, 0xf18103, 0xf28203, 0xf38303, + 0xf48403, 0xf58503, 0xf68703, 0xf78803, + 0xf88903, 0xf98a04, 0xfa8b04, 0xfb8c04, + 0xfc8d04, 0xfd8f04, 0xfe9005, 0xff9105, + 0xff9205, 0xff9305, 0xff9405, 0xff9606, + 0xff9706, 0xff9806, 0xff9906, 0xff9a07, + 0xff9b07, 0xff9d07, 0xff9e08, 0xff9f08, + 0xffa008, 0xffa109, 0xffa309, 0xffa409, + 0xffa50a, 0xffa60a, 0xffa80a, 0xffa90b, + 0xffaa0b, 0xffab0c, 0xffac0c, 0xffae0d, + 0xffaf0d, 0xffb00e, 0xffb10e, 0xffb30f, + 0xffb40f, 0xffb510, 0xffb610, 0xffb811, + 0xffb912, 0xffba12, 0xffbb13, 0xffbd14, + 0xffbe14, 0xffbf15, 0xffc016, 0xffc217, + 0xffc317, 0xffc418, 0xffc619, 0xffc71a, + 0xffc81b, 0xffca1c, 0xffcb1d, 0xffcc1e, + 0xffcd1f, 0xffcf20, 0xffd021, 0xffd122, + 0xffd323, 0xffd424, 0xffd526, 0xffd727, + 0xffd828, 0xffd92a, 0xffdb2b, 0xffdc2c, + 0xffdd2e, 0xffdf2f, 0xffe031, 0xffe133, + 0xffe334, 0xffe436, 0xffe538, 0xffe739 + }, + { /* Green monitor. */ + 0x000000, 0x000400, 0x000700, 0x000900, + 0x000b00, 0x000d00, 0x000f00, 0x001100, + 0x001300, 0x001500, 0x001600, 0x001800, + 0x001a00, 0x001b00, 0x001d00, 0x001e00, + 0x002000, 0x002100, 0x002300, 0x002400, + 0x002601, 0x002701, 0x002901, 0x002a01, + 0x002b01, 0x002d01, 0x002e01, 0x002f01, + 0x003101, 0x003201, 0x003301, 0x003401, + 0x003601, 0x003702, 0x003802, 0x003902, + 0x003b02, 0x003c02, 0x003d02, 0x003e02, + 0x004002, 0x004102, 0x004203, 0x004303, + 0x004403, 0x004503, 0x004703, 0x004803, + 0x004903, 0x004a03, 0x004b04, 0x004c04, + 0x004d04, 0x004e04, 0x005004, 0x005104, + 0x005205, 0x005305, 0x005405, 0x005505, + 0x005605, 0x005705, 0x005806, 0x005906, + 0x005a06, 0x005b06, 0x005d06, 0x005e07, + 0x005f07, 0x006007, 0x006107, 0x006207, + 0x006308, 0x006408, 0x006508, 0x006608, + 0x006708, 0x006809, 0x006909, 0x006a09, + 0x006b09, 0x016c0a, 0x016d0a, 0x016e0a, + 0x016f0a, 0x01700b, 0x01710b, 0x01720b, + 0x01730b, 0x01740c, 0x01750c, 0x01760c, + 0x01770c, 0x01780d, 0x01790d, 0x017a0d, + 0x017b0d, 0x017b0e, 0x017c0e, 0x017d0e, + 0x017e0f, 0x017f0f, 0x01800f, 0x018110, + 0x028210, 0x028310, 0x028410, 0x028511, + 0x028611, 0x028711, 0x028812, 0x028912, + 0x028a12, 0x028a13, 0x028b13, 0x028c13, + 0x028d14, 0x028e14, 0x038f14, 0x039015, + 0x039115, 0x039215, 0x039316, 0x039416, + 0x039417, 0x039517, 0x039617, 0x039718, + 0x049818, 0x049918, 0x049a19, 0x049b19, + 0x049c19, 0x049c1a, 0x049d1a, 0x049e1b, + 0x059f1b, 0x05a01b, 0x05a11c, 0x05a21c, + 0x05a31c, 0x05a31d, 0x05a41d, 0x06a51e, + 0x06a61e, 0x06a71f, 0x06a81f, 0x06a920, + 0x06aa20, 0x07aa21, 0x07ab21, 0x07ac21, + 0x07ad22, 0x07ae22, 0x08af23, 0x08b023, + 0x08b024, 0x08b124, 0x08b225, 0x09b325, + 0x09b426, 0x09b526, 0x09b527, 0x0ab627, + 0x0ab728, 0x0ab828, 0x0ab929, 0x0bba29, + 0x0bba2a, 0x0bbb2a, 0x0bbc2b, 0x0cbd2b, + 0x0cbe2c, 0x0cbf2c, 0x0dbf2d, 0x0dc02d, + 0x0dc12e, 0x0ec22e, 0x0ec32f, 0x0ec42f, + 0x0fc430, 0x0fc530, 0x0fc631, 0x10c731, + 0x10c832, 0x10c932, 0x11c933, 0x11ca33, + 0x11cb34, 0x12cc35, 0x12cd35, 0x12cd36, + 0x13ce36, 0x13cf37, 0x13d037, 0x14d138, + 0x14d139, 0x14d239, 0x15d33a, 0x15d43a, + 0x16d43b, 0x16d53b, 0x17d63c, 0x17d73d, + 0x17d83d, 0x18d83e, 0x18d93e, 0x19da3f, + 0x19db40, 0x1adc40, 0x1adc41, 0x1bdd41, + 0x1bde42, 0x1cdf43, 0x1ce043, 0x1de044, + 0x1ee145, 0x1ee245, 0x1fe346, 0x1fe446, + 0x20e447, 0x20e548, 0x21e648, 0x22e749, + 0x22e74a, 0x23e84a, 0x23e94b, 0x24ea4c, + 0x25ea4c, 0x25eb4d, 0x26ec4e, 0x27ed4e, + 0x27ee4f, 0x28ee50, 0x29ef50, 0x29f051, + 0x2af152, 0x2bf153, 0x2cf253, 0x2cf354, + 0x2df455, 0x2ef455, 0x2ff556, 0x2ff657, + 0x30f758, 0x31f758, 0x32f859, 0x32f95a, + 0x33fa5a, 0x34fa5b, 0x35fb5c, 0x36fc5d, + 0x37fd5d, 0x38fd5e, 0x38fe5f, 0x39ff60 + }, + { /* White monitor. */ + 0x000000, 0x010102, 0x020203, 0x020304, + 0x030406, 0x040507, 0x050608, 0x060709, + 0x07080a, 0x08090c, 0x080a0d, 0x090b0e, + 0x0a0c0f, 0x0b0d10, 0x0c0e11, 0x0d0f12, + 0x0e1013, 0x0f1115, 0x101216, 0x111317, + 0x121418, 0x121519, 0x13161a, 0x14171b, + 0x15181c, 0x16191d, 0x171a1e, 0x181b1f, + 0x191c20, 0x1a1d21, 0x1b1e22, 0x1c1f23, + 0x1d2024, 0x1e2125, 0x1f2226, 0x202327, + 0x212428, 0x222529, 0x22262b, 0x23272c, + 0x24282d, 0x25292e, 0x262a2f, 0x272b30, + 0x282c30, 0x292d31, 0x2a2e32, 0x2b2f33, + 0x2c3034, 0x2d3035, 0x2e3136, 0x2f3237, + 0x303338, 0x313439, 0x32353a, 0x33363b, + 0x34373c, 0x35383d, 0x36393e, 0x373a3f, + 0x383b40, 0x393c41, 0x3a3d42, 0x3b3e43, + 0x3c3f44, 0x3d4045, 0x3e4146, 0x3f4247, + 0x404348, 0x414449, 0x42454a, 0x43464b, + 0x44474c, 0x45484d, 0x46494d, 0x474a4e, + 0x484b4f, 0x484c50, 0x494d51, 0x4a4e52, + 0x4b4f53, 0x4c5054, 0x4d5155, 0x4e5256, + 0x4f5357, 0x505458, 0x515559, 0x52565a, + 0x53575b, 0x54585b, 0x55595c, 0x565a5d, + 0x575b5e, 0x585c5f, 0x595d60, 0x5a5e61, + 0x5b5f62, 0x5c6063, 0x5d6164, 0x5e6265, + 0x5f6366, 0x606466, 0x616567, 0x626668, + 0x636769, 0x64686a, 0x65696b, 0x666a6c, + 0x676b6d, 0x686c6e, 0x696d6f, 0x6a6e70, + 0x6b6f70, 0x6c7071, 0x6d7172, 0x6f7273, + 0x707374, 0x707475, 0x717576, 0x727677, + 0x747778, 0x757879, 0x767979, 0x777a7a, + 0x787b7b, 0x797c7c, 0x7a7d7d, 0x7b7e7e, + 0x7c7f7f, 0x7d8080, 0x7e8181, 0x7f8281, + 0x808382, 0x818483, 0x828584, 0x838685, + 0x848786, 0x858887, 0x868988, 0x878a89, + 0x888b89, 0x898c8a, 0x8a8d8b, 0x8b8e8c, + 0x8c8f8d, 0x8d8f8e, 0x8e908f, 0x8f9190, + 0x909290, 0x919391, 0x929492, 0x939593, + 0x949694, 0x959795, 0x969896, 0x979997, + 0x989a98, 0x999b98, 0x9a9c99, 0x9b9d9a, + 0x9c9e9b, 0x9d9f9c, 0x9ea09d, 0x9fa19e, + 0xa0a29f, 0xa1a39f, 0xa2a4a0, 0xa3a5a1, + 0xa4a6a2, 0xa6a7a3, 0xa7a8a4, 0xa8a9a5, + 0xa9aaa5, 0xaaaba6, 0xabaca7, 0xacada8, + 0xadaea9, 0xaeafaa, 0xafb0ab, 0xb0b1ac, + 0xb1b2ac, 0xb2b3ad, 0xb3b4ae, 0xb4b5af, + 0xb5b6b0, 0xb6b7b1, 0xb7b8b2, 0xb8b9b2, + 0xb9bab3, 0xbabbb4, 0xbbbcb5, 0xbcbdb6, + 0xbdbeb7, 0xbebfb8, 0xbfc0b8, 0xc0c1b9, + 0xc1c2ba, 0xc2c3bb, 0xc3c4bc, 0xc5c5bd, + 0xc6c6be, 0xc7c7be, 0xc8c8bf, 0xc9c9c0, + 0xcacac1, 0xcbcbc2, 0xccccc3, 0xcdcdc3, + 0xcecec4, 0xcfcfc5, 0xd0d0c6, 0xd1d1c7, + 0xd2d2c8, 0xd3d3c9, 0xd4d4c9, 0xd5d5ca, + 0xd6d6cb, 0xd7d7cc, 0xd8d8cd, 0xd9d9ce, + 0xdadacf, 0xdbdbcf, 0xdcdcd0, 0xdeddd1, + 0xdfded2, 0xe0dfd3, 0xe1e0d4, 0xe2e1d4, + 0xe3e2d5, 0xe4e3d6, 0xe5e4d7, 0xe6e5d8, + 0xe7e6d9, 0xe8e7d9, 0xe9e8da, 0xeae9db, + 0xebeadc, 0xecebdd, 0xedecde, 0xeeeddf, + 0xefeedf, 0xf0efe0, 0xf1f0e1, 0xf2f1e2, + 0xf3f2e3, 0xf4f3e3, 0xf6f3e4, 0xf7f4e5, + 0xf8f5e6, 0xf9f6e7, 0xfaf7e8, 0xfbf8e9, + 0xfcf9e9, 0xfdfaea, 0xfefbeb, 0xfffcec } }; @@ -216,24 +415,23 @@ static struct { event_t *buffer_not_in_use; } blit_data; static int video_force_resize; +static void (*blit_func)(int x, int y, int y1, int y2, int w, int h); -static void (*blit_func)(int x, int y, int y1, int y2, int w, int h); - - -static -void blit_thread(void *param) +static void +blit_thread(void *param) { while (1) { thread_wait_event(blit_data.wake_blit_thread, -1); thread_reset_event(blit_data.wake_blit_thread); - if (blit_func) + if (blit_func != NULL) blit_func(blit_data.x, blit_data.y, blit_data.y1, blit_data.y2, blit_data.w, blit_data.h); blit_data.busy = 0; + thread_set_event(blit_data.blit_complete); } } @@ -300,10 +498,8 @@ video_blit_memtoscreen_8(int x, int y, int y1, int y2, int w, int h) if (h <= 0) return; - for (yy = 0; yy < h; yy++) - { - if ((y + yy) >= 0 && (y + yy) < buffer->h) - { + for (yy = 0; yy < h; yy++) { + if ((y + yy) >= 0 && (y + yy) < buffer->h) { for (xx = 0; xx < w; xx++) *(uint32_t *) &(buffer32->line[y + yy][(x + xx) << 2]) = pal_lookup[buffer->line[y + yy][x + xx]]; } @@ -321,7 +517,7 @@ cgapal_rebuild(void) /* We cannot do this (yet) if we have not been enabled yet. */ if (video_6to8 == NULL) return; - for (c=0; c<256; c++) { + for (c = 0; c < 256; c++) { pal_lookup[c] = makecol(video_6to8[cgapal[c].r], video_6to8[cgapal[c].g], video_6to8[cgapal[c].b]); @@ -329,7 +525,7 @@ cgapal_rebuild(void) if ((cga_palette > 1) && (cga_palette < 8)) { if (vid_cga_contrast != 0) { - for (c=0; c<16; c++) { + for (c = 0; c < 16; c++) { pal_lookup[c] = makecol(video_6to8[cgapal_mono[cga_palette - 2][c].r], video_6to8[cgapal_mono[cga_palette - 2][c].g], video_6to8[cgapal_mono[cga_palette - 2][c].b]); @@ -344,7 +540,7 @@ cgapal_rebuild(void) video_6to8[cgapal_mono[cga_palette - 2][c].b]); } } else { - for (c=0; c<16; c++) { + for (c = 0; c < 16; c++) { pal_lookup[c] = makecol(video_6to8[cgapal_mono[cga_palette - 1][c].r], video_6to8[cgapal_mono[cga_palette - 1][c].g], video_6to8[cgapal_mono[cga_palette - 1][c].b]); @@ -366,124 +562,7 @@ cgapal_rebuild(void) } -static video_timings_t timing_dram = {VIDEO_BUS, 0,0,0, 0,0,0}; /*No additional waitstates*/ -static video_timings_t timing_pc1512 = {VIDEO_BUS, 0,0,0, 0,0,0}; /*PC1512 video code handles waitstates itself*/ -static video_timings_t timing_pc1640 = {VIDEO_ISA, 8,16,32, 8,16,32}; -static video_timings_t timing_pc200 = {VIDEO_ISA, 8,16,32, 8,16,32}; -static video_timings_t timing_m24 = {VIDEO_ISA, 8,16,32, 8,16,32}; -static video_timings_t timing_t1000 = {VIDEO_ISA, 8,16,32, 8,16,32}; -static video_timings_t timing_pvga1a = {VIDEO_ISA, 6, 8,16, 6, 8,16}; -static video_timings_t timing_wd90c11 = {VIDEO_ISA, 3, 3, 6, 5, 5,10}; -static video_timings_t timing_vga = {VIDEO_ISA, 8,16,32, 8,16,32}; -static video_timings_t timing_ps1_svga = {VIDEO_ISA, 6, 8,16, 6, 8,16}; -static video_timings_t timing_t3100e = {VIDEO_ISA, 8,16,32, 8,16,32}; -static video_timings_t timing_endeavor = {VIDEO_BUS, 3, 2, 4,25,25,40}; - -void -video_update_timing(void) -{ - const video_timings_t *timing; - int new_card; - - if (video_speed == -1) { - new_card = 0; - - /* FIXME: should be in machines[] table. */ - switch(romset) { - case ROM_IBMPCJR: - case ROM_TANDY: - case ROM_TANDY1000HX: - case ROM_TANDY1000SL2: - timing = &timing_dram; - break; - case ROM_PC1512: - timing = &timing_pc1512; - break; - case ROM_PC1640: - timing = &timing_pc1640; - break; - case ROM_PC200: - timing = &timing_pc200; - break; - case ROM_OLIM24: - timing = &timing_m24; - break; - case ROM_T1000: - case ROM_T1200: - timing = &timing_t1000; - break; - case ROM_PC2086: - case ROM_PC3086: - timing = &timing_pvga1a; - break; - case ROM_MEGAPC: - case ROM_MEGAPCDX: - timing = &timing_wd90c11; - break; - case ROM_IBMPS1_2011: - case ROM_IBMPS2_M30_286: - case ROM_IBMPS2_M50: - case ROM_IBMPS2_M55SX: - case ROM_IBMPS2_M80: - timing = &timing_vga; - break; - case ROM_IBMPS1_2121: - case ROM_IBMPS1_2133: - timing = &timing_ps1_svga; - break; - case ROM_T3100E: - timing = &timing_t3100e; - break; - case ROM_ENDEAVOR: - timing = &timing_endeavor; - break; - default: - new_card = video_old_to_new(video_card); - timing = video_card_gettiming(new_card); - break; - } - - if (timing->type == VIDEO_ISA) { - video_timing_read_b = ISA_CYCLES(timing->read_b); - video_timing_read_w = ISA_CYCLES(timing->read_w); - video_timing_read_l = ISA_CYCLES(timing->read_l); - video_timing_write_b = ISA_CYCLES(timing->write_b); - video_timing_write_w = ISA_CYCLES(timing->write_w); - video_timing_write_l = ISA_CYCLES(timing->write_l); - } else { - video_timing_read_b = (int)(bus_timing * timing->read_b); - video_timing_read_w = (int)(bus_timing * timing->read_w); - video_timing_read_l = (int)(bus_timing * timing->read_l); - video_timing_write_b = (int)(bus_timing * timing->write_b); - video_timing_write_w = (int)(bus_timing * timing->write_w); - video_timing_write_l = (int)(bus_timing * timing->write_l); - } - } else { - if (video_timing[video_speed][0] == VIDEO_ISA) { - video_timing_read_b = ISA_CYCLES(video_timing[video_speed][1]); - video_timing_read_w = ISA_CYCLES(video_timing[video_speed][2]); - video_timing_read_l = ISA_CYCLES(video_timing[video_speed][3]); - video_timing_write_b = ISA_CYCLES(video_timing[video_speed][1]); - video_timing_write_w = ISA_CYCLES(video_timing[video_speed][2]); - video_timing_write_l = ISA_CYCLES(video_timing[video_speed][3]); - } else { - video_timing_read_b = (int)(bus_timing * video_timing[video_speed][1]); - video_timing_read_w = (int)(bus_timing * video_timing[video_speed][2]); - video_timing_read_l = (int)(bus_timing * video_timing[video_speed][3]); - video_timing_write_b = (int)(bus_timing * video_timing[video_speed][1]); - video_timing_write_w = (int)(bus_timing * video_timing[video_speed][2]); - video_timing_write_l = (int)(bus_timing * video_timing[video_speed][3]); - } - } - - if (cpu_16bitbus) { - video_timing_read_l = video_timing_read_w * 2; - video_timing_write_l = video_timing_write_w * 2; - } -} - - -int +static int calc_6to8(int c) { int ic, i8; @@ -501,7 +580,7 @@ calc_6to8(int c) } -int +static int calc_15to32(int c) { int b, g, r; @@ -521,7 +600,7 @@ calc_15to32(int c) } -int +static int calc_16to32(int c) { int b, g, r; @@ -541,44 +620,7 @@ calc_16to32(int c) } -void -hline(bitmap_t *b, int x1, int y, int x2, uint32_t col) -{ - if (y < 0 || y >= buffer->h) - return; - - if (b == buffer) - memset(&b->line[y][x1], col, x2 - x1); - else - memset(&((uint32_t *)b->line[y])[x1], col, (x2 - x1) * 4); -} - - -void -blit(bitmap_t *src, bitmap_t *dst, int x1, int y1, int x2, int y2, int xs, int ys) -{ -} - - -void -stretch_blit(bitmap_t *src, bitmap_t *dst, int x1, int y1, int xs1, int ys1, int x2, int y2, int xs2, int ys2) -{ -} - - -void -rectfill(bitmap_t *b, int x1, int y1, int x2, int y2, uint32_t col) -{ -} - - -void -set_palette(PALETTE p) -{ -} - - -void +static void destroy_bitmap(bitmap_t *b) { if (b->dat != NULL) @@ -587,13 +629,13 @@ destroy_bitmap(bitmap_t *b) } -bitmap_t * +static bitmap_t * create_bitmap(int x, int y) { - bitmap_t *b = malloc(sizeof(bitmap_t) + (y * sizeof(uint8_t *))); + bitmap_t *b = (bitmap_t *)mem_alloc(sizeof(bitmap_t) + (y * sizeof(uint8_t *))); int c; - b->dat = malloc(x * y * 4); + b->dat = (uint8_t *)mem_alloc(x * y * 4); for (c = 0; c < y; c++) b->line[c] = b->dat + (c * x * 4); b->w = x; @@ -603,15 +645,33 @@ create_bitmap(int x, int y) } +void +video_log(int level, const char *fmt, ...) +{ +#ifdef ENABLE_VIDEO_LOG + va_list ap; + + if (video_do_log >= level) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +#endif +} + + void video_init(void) { int c, d, e; + /* Initialize video type and timing. */ + video_inform(VID_TYPE_DFLT, NULL); + /* Account for overscan. */ buffer32 = create_bitmap(2048, 2048); - buffer = create_bitmap(2048, 2048); + for (c = 0; c < 64; c++) { cgapal[c + 64].r = (((c & 4) ? 2 : 0) | ((c & 0x10) ? 1 : 0)) * 21; cgapal[c + 64].g = (((c & 2) ? 2 : 0) | ((c & 0x10) ? 1 : 0)) * 21; @@ -642,10 +702,10 @@ video_init(void) } } - video_6to8 = malloc(4 * 256); + video_6to8 = (uint32_t *)mem_alloc(4 * 256); for (c = 0; c < 256; c++) video_6to8[c] = calc_6to8(c); - video_15to32 = malloc(4 * 65536); + video_15to32 = (uint32_t *)mem_alloc(4 * 65536); #if 0 for (c = 0; c < 65536; c++) video_15to32[c] = ((c & 31) << 3) | (((c >> 5) & 31) << 11) | (((c >> 10) & 31) << 19); @@ -653,7 +713,7 @@ video_init(void) for (c = 0; c < 65536; c++) video_15to32[c] = calc_15to32(c); - video_16to32 = malloc(4 * 65536); + video_16to32 = (uint32_t *)mem_alloc(4 * 65536); #if 0 for (c = 0; c < 65536; c++) video_16to32[c] = ((c & 31) << 3) | (((c >> 5) & 63) << 10) | (((c >> 11) & 31) << 19); @@ -683,6 +743,72 @@ video_close(void) destroy_bitmap(buffer); destroy_bitmap(buffer32); + video_reset_font(); +} + + +/* Called by PIT to (re-)set our timings. */ +void +video_update_timing(void) +{ + /* Update the video timing paramaters. */ + if (video_timing->type == VID_ISA) { + video_timing_read_b = ISA_CYCLES(video_timing->read_b); + video_timing_read_w = ISA_CYCLES(video_timing->read_w); + video_timing_read_l = ISA_CYCLES(video_timing->read_l); + video_timing_write_b = ISA_CYCLES(video_timing->write_b); + video_timing_write_w = ISA_CYCLES(video_timing->write_w); + video_timing_write_l = ISA_CYCLES(video_timing->write_l); + } else { + video_timing_read_b = (int)(bus_timing * video_timing->read_b); + video_timing_read_w = (int)(bus_timing * video_timing->read_w); + video_timing_read_l = (int)(bus_timing * video_timing->read_l); + video_timing_write_b = (int)(bus_timing * video_timing->write_b); + video_timing_write_w = (int)(bus_timing * video_timing->write_w); + video_timing_write_l = (int)(bus_timing * video_timing->write_l); + } + + /* Fix up for 16-bit buses. */ + if (cpu_16bitbus) { + video_timing_read_l = video_timing_read_w * 2; + video_timing_write_l = video_timing_write_w * 2; + } +} + + +/* Inform the video module what type a card is, and what its timings are. */ +void +video_inform(int type, const video_timings_t *ptr) +{ + /* Save the video card type. */ + video_card_type = (type == VID_TYPE_DFLT) ? VID_TYPE_SPEC : type; + + /* Save the card's timing parameters. */ + video_timing = (ptr == NULL) ? &timing_default : ptr; + + /* Make sure these are used. */ + video_update_timing(); + + if (type != VID_TYPE_DFLT) + INFO("VIDEO: card type %i, timings {%i: %i,%i,%i %i,%i,%i}\n", + video_card_type, video_timing->type, + video_timing->write_b, video_timing->write_w, video_timing->write_l, + video_timing->read_b, video_timing->read_w, video_timing->read_l); +} + + +/* Return the current video card's type. */ +int +video_type(void) +{ + return(video_card_type); +} + + +/* Zap any font memory allocated previously. */ +void +video_reset_font(void) +{ if (fontdatksc5601 != NULL) { free(fontdatksc5601); fontdatksc5601 = NULL; @@ -695,6 +821,109 @@ video_close(void) } +/* Load a font from its ROM source. */ +void +video_load_font(const wchar_t *s, int format) +{ + FILE *fp; + int c, d; + + fp = plat_fopen(rom_path(s), L"rb"); + if (fp == NULL) { + ERRLOG("VIDEO: cannot load font '%ls', fmt=%d\n", s, format); + return; + } + + switch (format) { + case 0: /* MDA */ + for (c = 0; c < 256; c++) + for (d = 0; d < 8; d++) + fontdatm[c][d] = fgetc(fp); + for (c = 0; c < 256; c++) + for (d = 0; d < 8; d++) + fontdatm[c][d + 8] = fgetc(fp); +#if 0 + (void)fseek(f, 4096+2048, SEEK_SET); + for (c = 0; c < 256; c++) + for (d = 0; d < 8; d++) + fontdat[c][d] = fgetc(fp); +#endif + break; + + case 1: /* PC200 */ + for (c = 0; c < 256; c++) + for (d = 0; d < 8; d++) + fontdatm[c][d] = fgetc(fp); + for (c = 0; c < 256; c++) + for (d = 0; d < 8; d++) + fontdatm[c][d + 8] = fgetc(fp); + (void)fseek(fp, 4096, SEEK_SET); + for (c = 0; c < 256; c++) { + for (d = 0; d < 8; d++) + fontdat[c][d] = fgetc(fp); + for (d = 0; d < 8; d++) (void)fgetc(fp); + } + break; + + case 2: /* CGA, thin font */ + case 8: /* CGA, thick font */ + if (format == 8) { + /* Use the second ("thick") font in the ROM. */ + (void)fseek(fp, 2048, SEEK_SET); + } + for (c = 0; c < 256; c++) + for (d = 0; d < 8; d++) + fontdat[c][d] = fgetc(fp); + break; + + case 3: /* Wyse 700 */ + for (c = 0; c < 512; c++) + for (d = 0; d < 32; d++) + fontdatw[c][d] = fgetc(fp); + break; + + case 4: /* MDSI Genius */ + for (c = 0; c < 256; c++) + for (d = 0; d < 16; d++) + fontdat8x12[c][d] = fgetc(fp); + break; + + case 5: /* Toshiba 3100e */ + for (d = 0; d < 2048; d += 512) { /* Four languages... */ + for (c = d; c < d+256; c++) + fread(&fontdatm[c][8], 1, 8, fp); + for (c = d+256; c < d+512; c++) + fread(&fontdatm[c][8], 1, 8, fp); + for (c = d; c < d+256; c++) + fread(&fontdatm[c][0], 1, 8, fp); + for (c = d+256; c < d+512; c++) + fread(&fontdatm[c][0], 1, 8, fp); + fseek(fp, 4096, SEEK_CUR); /* Skip blank section */ + for (c = d; c < d+256; c++) + fread(&fontdat[c][0], 1, 8, fp); + for (c = d+256; c < d+512; c++) + fread(&fontdat[c][0], 1, 8, fp); + } + break; + + case 6: /* Korean KSC-5601 */ + if (fontdatksc5601 == NULL) + fontdatksc5601 = (dbcs_font_t *)mem_alloc(16384 * sizeof(dbcs_font_t)); + + if (fontdatksc5601_user == NULL) + fontdatksc5601_user = (dbcs_font_t *)mem_alloc(192 * sizeof(dbcs_font_t)); + + for (c = 0; c < 16384; c++) { + for (d = 0; d < 32; d++) + fontdatksc5601[c].chr[d] = fgetc(fp); + } + break; + } + + (void)fclose(fp); +} + + uint8_t video_force_resize_get(void) { @@ -709,103 +938,54 @@ video_force_resize_set(uint8_t res) } -void -loadfont(const wchar_t *s, int format) +uint32_t +video_color_transform(uint32_t color) { - FILE *f; - int c,d; + uint8_t *clr8 = (uint8_t *)&color; - f = plat_fopen(rom_path(s), L"rb"); - if (f == NULL) { - pclog("VIDEO: cannot load font '%ls', fmt=%d\n", s, format); - return; - } - - switch (format) { - case 0: /* MDA */ - for (c=0; c<256; c++) - for (d=0; d<8; d++) - fontdatm[c][d] = fgetc(f); - for (c=0; c<256; c++) - for (d=0; d<8; d++) - fontdatm[c][d+8] = fgetc(f); #if 0 - (void)fseek(f, 4096+2048, SEEK_SET); - for (c=0; c<256; c++) - for (d=0; d<8; d++) - fontdat[c][d] = fgetc(f); + if (!vid_grayscale && !invert_display) return color; #endif - break; - case 1: /* PC200 */ - for (c=0; c<256; c++) - for (d=0; d<8; d++) - fontdatm[c][d] = fgetc(f); - for (c=0; c<256; c++) - for (d=0; d<8; d++) - fontdatm[c][d+8] = fgetc(f); - (void)fseek(f, 4096, SEEK_SET); - for (c=0; c<256; c++) { - for (d=0; d<8; d++) - fontdat[c][d] = fgetc(f); - for (d=0; d<8; d++) (void)fgetc(f); - } - break; + if (vid_grayscale) { + if (vid_graytype) { + if (vid_graytype == 1) + color = ((54 * (uint32_t)clr8[2]) + (183 * (uint32_t)clr8[1]) + (18 * (uint32_t)clr8[0])) / 255; + else + color = ((uint32_t)clr8[2] + (uint32_t)clr8[1] + (uint32_t)clr8[0]) / 3; + } else + color = ((76 * (uint32_t)clr8[2]) + (150 * (uint32_t)clr8[1]) + (29 * (uint32_t)clr8[0])) / 255; - case 2: /* CGA, thin font */ - case 8: /* CGA, thick font */ - if (format == 8) { - /* Use the second ("thick") font in the ROM. */ - (void)fseek(f, 2048, SEEK_SET); - } - for (c=0; c<256; c++) - for (d=0; d<8; d++) - fontdat[c][d] = fgetc(f); - break; + switch (vid_grayscale) { + case 2: + case 3: + case 4: + color = (uint32_t)shade[vid_grayscale][color]; + break; - case 3: /* Wyse 700 */ - for (c=0; c<512; c++) - for (d=0; d<32; d++) - fontdatw[c][d] = fgetc(f); - break; - - case 4: /* MDSI Genius */ - for (c=0; c<256; c++) - for (d=0; d<16; d++) - fontdat8x12[c][d] = fgetc(f); - break; - - case 5: /* Toshiba 3100e */ - for (d = 0; d < 2048; d += 512) { /* Four languages... */ - for (c = d; c < d+256; c++) - fread(&fontdatm[c][8], 1, 8, f); - for (c = d+256; c < d+512; c++) - fread(&fontdatm[c][8], 1, 8, f); - for (c = d; c < d+256; c++) - fread(&fontdatm[c][0], 1, 8, f); - for (c = d+256; c < d+512; c++) - fread(&fontdatm[c][0], 1, 8, f); - fseek(f, 4096, SEEK_CUR); /* Skip blank section */ - for (c = d; c < d+256; c++) - fread(&fontdat[c][0], 1, 8, f); - for (c = d+256; c < d+512; c++) - fread(&fontdat[c][0], 1, 8, f); - } - break; - - case 6: /* Korean KSC-5601 */ - if (fontdatksc5601 == NULL) - fontdatksc5601 = malloc(16384 * sizeof(dbcs_font_t)); - - if (fontdatksc5601_user == NULL) - fontdatksc5601_user = malloc(192 * sizeof(dbcs_font_t)); - - for (c = 0; c < 16384; c++) { - for (d = 0; d < 32; d++) - fontdatksc5601[c].chr[d]=getc(f); - } - break; + default: + clr8[3] = 0; + clr8[0] = color; + clr8[1] = clr8[2] = clr8[0]; + break; + } } - (void)fclose(f); + if (invert_display) + color ^= 0x00ffffff; + + return color; +} + + +void +video_transform_copy(uint32_t *dst, uint32_t *src, int len) +{ + int i; + + for (i = 0; i < len; i++) { + *dst = video_color_transform(*src); + dst++; + src++; + } } diff --git a/src/devices/video/video.h b/src/devices/video/video.h index 2319f7e..1152590 100644 --- a/src/devices/video/video.h +++ b/src/devices/video/video.h @@ -8,7 +8,7 @@ * * Definitions for the video controller module. * - * Version: @(#)video.h 1.0.17 2018/08/25 + * Version: @(#)video.h 1.0.18 2018/09/30 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -40,9 +40,6 @@ # define EMU_VIDEO_H -#define FONT_ATIKOR_PATH L"video/ati/ati28800/ati_ksc5601.rom" - - #define makecol(r, g, b) ((b) | ((g) << 8) | ((r) << 16)) #define makecol32(r, g, b) ((b) | ((g) << 8) | ((r) << 16)) @@ -50,92 +47,25 @@ enum { VID_NONE = 0, VID_INTERNAL, - VID_CGA, - VID_COMPAQ_CGA, /* Compaq CGA */ - VID_COMPAQ_CGA_2, /* Compaq CGA 2 */ - VID_COLORPLUS, /* Plantronics ColorPlus */ - VID_WY700, /* Wyse 700 */ - VID_MDA, - VID_GENIUS, /* MDSI Genius */ - VID_HERCULES, - VID_HERCULESPLUS, - VID_INCOLOR, /* Hercules InColor */ - VID_EGA, /* Using IBM EGA BIOS */ - VID_COMPAQ_EGA, /* Compaq EGA */ - VID_SUPER_EGA, /* Using Chips & Technologies SuperEGA BIOS */ + VID_MDA, /* IBM MDA */ + VID_CGA, /* IBM CGA */ + VID_EGA, /* IBM EGA */ VID_VGA, /* IBM VGA */ - VID_TVGA, /* Using Trident TVGA8900D BIOS */ - VID_ET4000, /* Tseng ET4000 */ - VID_TGKOREANVGA, /* Trigem Korean VGA (ET4000AX) */ - VID_ET4000W32_CARDEX_VLB, /* Tseng ET4000/W32p (Cardex) VLB */ - VID_ET4000W32_CARDEX_PCI, /* Tseng ET4000/W32p (Cardex) PCI */ -#if defined(DEV_BRANCH) && defined(USE_STEALTH32) - VID_ET4000W32_VLB, /* Tseng ET4000/W32p (Diamond Stealth 32) VLB */ - VID_ET4000W32_PCI, /* Tseng ET4000/W32p (Diamond Stealth 32) PCI */ -#endif - VID_BAHAMAS64_VLB, /* S3 Vision864 (Paradise Bahamas 64) VLB */ - VID_BAHAMAS64_PCI, /* S3 Vision864 (Paradise Bahamas 64) PCI */ - VID_N9_9FX_VLB, /* S3 764/Trio64 (Number Nine 9FX) VLB */ - VID_N9_9FX_PCI, /* S3 764/Trio64 (Number Nine 9FX) PCI */ - VID_TGUI9400CXI, /* Trident TGUI9400CXi VLB */ - VID_TGUI9440_VLB, /* Trident TGUI9440AGi VLB */ - VID_TGUI9440_PCI, /* Trident TGUI9440AGi PCI */ - VID_ATIKOREANVGA, /* ATI Korean VGA (28800-5) */ - VID_VGA88, /* ATI VGA-88 (18800-1) */ - VID_VGAEDGE16, /* ATI VGA Edge-16 (18800-1) */ - VID_VGACHARGER, /* ATI VGA Charger (28800-5) */ - VID_VGAWONDER, /* Compaq ATI VGA Wonder (18800) */ - VID_VGAWONDERXL, /* Compaq ATI VGA Wonder XL (28800-5) */ -#if defined(DEV_BRANCH) && defined(USE_XL24) - VID_VGAWONDERXL24, /* Compaq ATI VGA Wonder XL24 (28800-6) */ -#endif - VID_MACH64GX_ISA, /* ATI Graphics Pro Turbo (Mach64) ISA */ - VID_MACH64GX_VLB, /* ATI Graphics Pro Turbo (Mach64) VLB */ - VID_MACH64GX_PCI, /* ATI Graphics Pro Turbo (Mach64) PCI */ - VID_MACH64VT2, /* ATI Mach64 VT2 */ - VID_CL_GD5424_ISA, /* Cirrus Logic GD5424 ISA */ - VID_CL_GD5424_VLB, /* Cirrus Logic GD5424 VLB */ - VID_CL_GD5426_VLB, /* Diamond SpeedStar PRO (Cirrus Logic GD5426) VLB */ - VID_CL_GD5428_ISA, /* Cirrus Logic GD5428 ISA */ - VID_CL_GD5428_VLB, /* Cirrus Logic GD5428 VLB */ - VID_CL_GD5429_ISA, /* Cirrus Logic GD5429 ISA */ - VID_CL_GD5429_VLB, /* Cirrus Logic GD5429 VLB */ - VID_CL_GD5430_VLB, /* Diamond SpeedStar PRO SE (Cirrus Logic GD5430) VLB */ - VID_CL_GD5430_PCI, /* Cirrus Logic GD5430 PCI */ - VID_CL_GD5434_ISA, /* Cirrus Logic GD5434 ISA */ - VID_CL_GD5434_VLB, /* Cirrus Logic GD5434 VLB */ - VID_CL_GD5434_PCI, /* Cirrus Logic GD5434 PCI */ - VID_CL_GD5436_PCI, /* Cirrus Logic GD5436 PCI */ - VID_CL_GD5446_PCI, /* Cirrus Logic GD5446 PCI */ - VID_CL_GD5446_STB_PCI, /* STB Nitro 64V (Cirrus Logic GD5446) PCI */ - VID_CL_GD5480_PCI, /* Cirrus Logic GD5480 PCI */ - VID_OTI037C, /* Oak OTI-037C */ - VID_OTI067, /* Oak OTI-067 */ - VID_OTI077, /* Oak OTI-077 */ - VID_PVGA1A, /* Paradise PVGA1A Standalone */ - VID_WD90C11, /* Paradise WD90C11-LR Standalone */ - VID_WD90C30, /* Paradise WD90C30-LR Standalone */ - VID_PHOENIX_TRIO32_VLB, /* S3 732/Trio32 (Phoenix) VLB */ - VID_PHOENIX_TRIO32_PCI, /* S3 732/Trio32 (Phoenix) PCI */ - VID_PHOENIX_TRIO64_VLB, /* S3 764/Trio64 (Phoenix) VLB */ - VID_PHOENIX_TRIO64_PCI, /* S3 764/Trio64 (Phoenix) PCI */ - VID_VIRGE_VLB, /* S3 Virge VLB */ - VID_VIRGE_PCI, /* S3 Virge PCI */ - VID_VIRGEDX_VLB, /* S3 Virge/DX VLB */ - VID_VIRGEDX_PCI, /* S3 Virge/DX PCI */ - VID_VIRGEDX4_VLB, /* S3 Virge/DX (VBE 2.0) VLB */ - VID_VIRGEDX4_PCI, /* S3 Virge/DX (VBE 2.0) PCI */ - VID_VIRGEVX_VLB, /* S3 Virge/VX VLB */ - VID_VIRGEVX_PCI, /* S3 Virge/VX PCI */ - VID_STEALTH64_VLB, /* S3 Vision864 (Diamond Stealth 64) VLB */ - VID_STEALTH64_PCI, /* S3 Vision864 (Diamond Stealth 64) PCI */ - VID_PHOENIX_VISION864_VLB, /* S3 Vision864 (Phoenix) VLB */ - VID_PHOENIX_VISION864_PCI, /* S3 Vision864 (Phoenix) PCI */ -#if defined(DEV_BRANCH) && defined(USE_TI) - VID_TICF62011, /* TI CF62011 */ -#endif + VID_HERCULES /* Hercules */ +}; - VID_MAX +enum { + VID_TYPE_DFLT = 0, + VID_TYPE_CGA, + VID_TYPE_MDA, + VID_TYPE_SPEC +}; +#define VID_TYPE_MASK 0x03 + +enum { + VID_ISA = 0, + VID_MCA, + VID_BUS }; enum { @@ -152,7 +82,7 @@ extern "C" { #endif -typedef struct { +typedef struct video_timings { int type; int write_b, write_w, write_l; int read_b, read_w, read_l; @@ -161,7 +91,13 @@ typedef struct { typedef struct { int w, h; uint8_t *dat; +#if 1 + /* Most compilers are OK with this, as long as its at end of struct. */ uint8_t *line[]; +#else + /* However, just in case we need it... */ + uint8_t *line[2048]; +#endif } bitmap_t; typedef struct { @@ -175,95 +111,226 @@ typedef struct { typedef rgb_t PALETTE[256]; -extern int vid_present[VID_MAX]; -extern int egareads, - egawrites; -extern int changeframecount; +extern int changeframecount; -extern bitmap_t *screen, - *buffer, - *buffer32; -extern PALETTE cgapal, - cgapal_mono[6]; -extern uint32_t pal_lookup[256]; -extern int fullchange; -extern uint8_t fontdat[2048][8]; -extern uint8_t fontdatm[2048][16]; -extern uint8_t fontdat8x12[256][16]; +extern bitmap_t *buffer, + *buffer32; +extern PALETTE cgapal, + cgapal_mono[6]; +extern uint32_t pal_lookup[256]; +extern uint8_t fontdat[2048][8]; +extern uint8_t fontdatm[2048][16]; +extern uint8_t fontdat8x12[256][16]; extern dbcs_font_t *fontdatksc5601, - *fontdatksc5601_user; -extern uint32_t *video_6to8, - *video_15to32, - *video_16to32; -extern int xsize,ysize; -extern int update_overscan; -extern int overscan_x, - overscan_y; -extern int video_timing_read_b, - video_timing_read_w, - video_timing_read_l; -extern int video_timing_write_b, - video_timing_write_w, - video_timing_write_l; -extern int video_speed; -extern int video_res_x, - video_res_y, - video_bpp; -extern int cga_palette; + *fontdatksc5601_user; +extern uint32_t *video_6to8, + *video_15to32, + *video_16to32; +extern int fullchange; +extern int xsize,ysize; +extern int update_overscan; +extern int overscan_x, + overscan_y; +extern int video_timing_read_b, + video_timing_read_w, + video_timing_read_l; +extern int video_timing_write_b, + video_timing_write_w, + video_timing_write_l; +extern int video_res_x, + video_res_y, + video_bpp; +extern int cga_palette; -extern float cpuclock; -extern int emu_fps, - frames; -extern int readflash; +extern float cpuclock; +extern int frames; -/* Function handler pointers. */ -extern void (*video_recalctimings)(void); +#ifdef EMU_DEVICE_H +/* ATi 18800 series cards. */ +extern const device_t ati18800_wonder_device; +extern const device_t ati18800_vga88_device; +extern const device_t ati18800_device; + +/* ATi 28800 series cards. */ +extern const device_t ati28800_device; +extern const device_t ati28800k_device; +extern const device_t ati28800_compaq_device; +#if defined(DEV_BRANCH) && defined(USE_XL24) +extern const device_t ati28800_wonderxl24_device; +#endif + +/* ATi Mach64 series cards. */ +extern const device_t mach64gx_isa_device; +extern const device_t mach64gx_vlb_device; +extern const device_t mach64gx_pci_device; +extern const device_t mach64vt2_device; + +/* IBM CGA and compatibles. */ +extern const device_t cga_device; + +/* Cirrus Logic GD-series cards. */ +extern const device_t gd5426_vlb_device; +extern const device_t gd5428_isa_device; +extern const device_t gd5428_vlb_device; +extern const device_t gd5429_isa_device; +extern const device_t gd5429_vlb_device; +extern const device_t gd5430_vlb_device; +extern const device_t gd5430_pci_device; +extern const device_t gd5434_isa_device; +extern const device_t gd5434_vlb_device; +extern const device_t gd5434_pci_device; +extern const device_t gd5436_pci_device; +extern const device_t gd5446_pci_device; +extern const device_t gd5440_onboard_pci_device; +extern const device_t gd5440_pci_device; +extern const device_t gd5446_stb_pci_device; +extern const device_t gd5480_pci_device; + +/* COMPAQ CGA-derived cards. */ +extern const device_t cga_compaq_device; +extern const device_t cga_compaq2_device; + +/* IBM EGA and compatibles. */ +extern const device_t ega_device; +extern const device_t ega_compaq_device; +extern const device_t sega_device; + +/* Tseng Labs ET4000 series cards. */ +extern const device_t et4000_isa_device; +extern const device_t et4000_mca_device; +extern const device_t et4000k_isa_device; +extern const device_t et4000k_tg286_isa_device; + +/* Tseng Labs ET4000-W32 series cards. */ +extern const device_t et4000w32p_vlb_device; +extern const device_t et4000w32p_pci_device; +extern const device_t et4000w32p_cardex_vlb_device; +extern const device_t et4000w32p_cardex_pci_device; + +/* MDSI Genius VHR card. */ +extern const device_t genius_device; + +/* Hercules series cards and compatibles. */ +extern const device_t hercules_device; + +/* HerculesPlus series cards and compatibles. */ +extern const device_t herculesplus_device; + +/* Hercules InColor series cards and compatibles. */ +extern const device_t incolor_device; + +/* Hercules ColorPlus series cards and compatibles. */ +extern const device_t colorplus_device; + +/* IBM MDA and compatibles. */ +extern const device_t mda_device; + +/* Oak Technology OTI series cards. */ +extern const device_t oti037c_device; +extern const device_t oti067_device; +extern const device_t oti067_acer386_device; +extern const device_t oti067_onboard_device; +extern const device_t oti077_device; + +/* Paradise PVGA series cards and compatibles. */ +extern const device_t paradise_pvga1a_pc2086_device; +extern const device_t paradise_pvga1a_pc3086_device; +extern const device_t paradise_pvga1a_device; +extern const device_t paradise_wd90c11_megapc_device; +extern const device_t paradise_wd90c11_device; +extern const device_t paradise_wd90c30_device; + +/* S3, Inc standard series cards. */ +extern const device_t s3_bahamas64_vlb_device; +extern const device_t s3_bahamas64_pci_device; +extern const device_t s3_9fx_vlb_device; +extern const device_t s3_9fx_pci_device; +extern const device_t s3_phoenix_trio32_vlb_device; +extern const device_t s3_phoenix_trio32_pci_device; +extern const device_t s3_phoenix_trio64_vlb_device; +extern const device_t s3_phoenix_trio64_pci_device; +extern const device_t s3_phoenix_trio64_onboard_pci_device; +extern const device_t s3_phoenix_vision864_vlb_device; +extern const device_t s3_phoenix_vision864_pci_device; +extern const device_t s3_diamond_stealth64_vlb_device; +extern const device_t s3_diamond_stealth64_pci_device; +extern const device_t s3_diamond_stealth64_964_pci_device; +extern const device_t s3_diamond_stealth64_964_vlb_device; + +/* S3, Inc ViRGE series cards. */ +extern const device_t s3_virge_vlb_device; +extern const device_t s3_virge_pci_device; +extern const device_t s3_virge_988_vlb_device; +extern const device_t s3_virge_988_pci_device; +extern const device_t s3_virge_375_vlb_device; +extern const device_t s3_virge_375_pci_device; +extern const device_t s3_virge_375_4_vlb_device; +extern const device_t s3_virge_375_4_pci_device; + +/* Trident 8900 series cards. */ +extern const device_t tvga8900d_device; + +/* Trident 9400 series cards. */ +extern const device_t tgui9400cxi_device; +extern const device_t tgui9440_vlb_device; +extern const device_t tgui9440_pci_device; + +/* TI-derived cards. */ +#if defined(DEV_BRANCH) && defined(USE_TI) +extern const device_t ti_cf62011_device; +#endif +extern const device_t ibm_ps1_2121_device; + +/* IBM VGA and compatibles. */ +extern const device_t vga_device; +extern const device_t ps1vga_device; +extern const device_t ps1vga_mca_device; + +/* 3Dfx VooDoo-series cards. */ +extern const device_t voodoo_device; + +/* Wyse700 cards. */ +extern const device_t wy700_device; +#endif /* Table functions. */ -extern int video_card_available(int card); -extern int video_detect(void); +extern int video_card_available(int card); extern const char *video_card_getname(int card); +extern const char *video_get_internal_name(int card); +extern int video_get_video_from_internal_name(const char *s); +extern int video_card_has_config(int card); #ifdef EMU_DEVICE_H extern const device_t *video_card_getdevice(int card); #endif -extern int video_card_has_config(int card); -extern const video_timings_t *video_card_gettiming(int card); -extern int video_card_getid(const char *s); -extern int video_old_to_new(int card); -extern int video_new_to_old(int card); -extern const char *video_get_internal_name(int card); -extern int video_get_video_from_internal_name(const char *s); -extern int video_is_mda(void); -extern int video_is_cga(void); -extern int video_is_ega_vga(void); +extern void video_setblit(void(*blit)(int,int,int,int,int,int)); +extern void video_blit_memtoscreen(int x, int y, int y1, int y2, int w, int h); +extern void video_blit_memtoscreen_8(int x, int y, int y1, int y2, int w, int h); +extern void video_blit_complete(void); +extern void video_wait_for_blit(void); +extern void video_wait_for_buffer(void); -extern void video_setblit(void(*blit)(int,int,int,int,int,int)); -extern void video_blit_memtoscreen(int x, int y, int y1, int y2, int w, int h); -extern void video_blit_memtoscreen_8(int x, int y, int y1, int y2, int w, int h); -extern void video_blit_complete(void); -extern void video_wait_for_blit(void); -extern void video_wait_for_buffer(void); +extern void cgapal_rebuild(void); -extern bitmap_t *create_bitmap(int w, int h); -extern void destroy_bitmap(bitmap_t *b); -extern void cgapal_rebuild(void); -extern void hline(bitmap_t *b, int x1, int y, int x2, uint32_t col); -extern void updatewindowsize(int x, int y); +extern void video_log(int level, const char *fmt, ...); +extern void video_init(void); +extern void video_close(void); +extern void video_reset(void); +extern void video_update_timing(void); +extern void video_inform(int type, const video_timings_t *ptr); +extern int video_type(void); +extern void video_reset_font(void); +extern void video_load_font(const wchar_t *s, int format); +extern uint8_t video_force_resize_get(void); +extern void video_force_resize_set(uint8_t res); +extern uint32_t video_color_transform(uint32_t color); +extern void video_transform_copy(uint32_t *dst, uint32_t *src, int len); -extern void video_init(void); -extern void video_close(void); -extern void video_reset(void); -extern uint8_t video_force_resize_get(void); -extern void video_force_resize_set(uint8_t res); -extern void video_update_timing(void); - -extern void loadfont(const wchar_t *s, int format); - -extern int get_actual_size_x(void); -extern int get_actual_size_y(void); +extern void updatewindowsize(int x, int y); +extern int get_actual_size_x(void); +extern int get_actual_size_y(void); #ifdef __cplusplus } diff --git a/src/devices/video/video_dev.c b/src/devices/video/video_dev.c index 75283c0..094a612 100644 --- a/src/devices/video/video_dev.c +++ b/src/devices/video/video_dev.c @@ -8,11 +8,11 @@ * * Define all known video cards. * - * To add a video card to the system, implement it, and put - * an "extern" reference to its device into this file, and - * add an entry for it into the table. + * To add a video card to the system, implement it, add an + * "extern" reference to its device into the video.h file, + * and add an entry for it into the table here. * - * Version: @(#)video_dev.c 1.0.21 2018/09/03 + * Version: @(#)video_dev.c 1.0.22 2018/10/05 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -46,316 +46,144 @@ #include "../../emu.h" #include "../../machines/machine.h" #include "../../mem.h" -#include "../../rom.h" -#include "../../timer.h" #include "../../device.h" #include "../../plat.h" #include "video.h" -#define VIDEO_FLAG_TYPE_CGA 0x00 -#define VIDEO_FLAG_TYPE_MDA 0x01 -#define VIDEO_FLAG_TYPE_SPECIAL 0x02 -#define VIDEO_FLAG_TYPE_MASK 0x03 - - -enum { - VIDEO_ISA = 0, - VIDEO_MCA, - VIDEO_BUS -}; - -typedef struct { - const char *name; - const char *internal_name; +static struct { + const char *internal_name; const device_t *device; - int legacy_id; - int flags; - video_timings_t timing; -} vidcard_t; +} video_cards[] = { + { "none", NULL }, + { "internal", NULL }, + /* Standard video controllers. */ + { "mda", &mda_device }, + { "cga", &cga_device }, + { "ega", &ega_device }, + { "vga", &vga_device }, + { "hercules", &hercules_device }, -/* ATi 18800 series cards. */ -extern const device_t ati18800_wonder_device; -extern const device_t ati18800_vga88_device; -extern const device_t ati18800_device; - -/* ATi 28800 series cards. */ -extern const device_t ati28800_device; -extern const device_t ati28800k_device; -extern const device_t compaq_ati28800_device; -#if defined(DEV_BRANCH) && defined(USE_XL24) -extern const device_t ati28800_wonderxl24_device; -#endif - -/* ATi Mach64 series cards. */ -extern const device_t mach64gx_isa_device; -extern const device_t mach64gx_vlb_device; -extern const device_t mach64gx_pci_device; -extern const device_t mach64vt2_device; - -/* IBM CGA and compatibles. */ -extern const device_t cga_device; - -/* Cirrus Logic GD-series cards. */ -extern const device_t gd5426_vlb_device; -extern const device_t gd5428_isa_device; -extern const device_t gd5428_vlb_device; -extern const device_t gd5429_isa_device; -extern const device_t gd5429_vlb_device; -extern const device_t gd5430_vlb_device; -extern const device_t gd5430_pci_device; -extern const device_t gd5434_isa_device; -extern const device_t gd5434_vlb_device; -extern const device_t gd5434_pci_device; -extern const device_t gd5436_pci_device; -extern const device_t gd5446_pci_device; -extern const device_t gd5446_stb_pci_device; -extern const device_t gd5480_pci_device; - -/* COMPAQ CGA-derived cards. */ -extern const device_t compaq_cga_device; -extern const device_t compaq_cga_2_device; - -/* IBM EGA and compatibles. */ -extern const device_t ega_device; -extern const device_t cpqega_device; -extern const device_t sega_device; - -/* Tseng Labs ET4000 series cards. */ -extern const device_t et4000_isa_device; -extern const device_t et4000_mca_device; -extern const device_t et4000k_isa_device; - -/* Tseng Labs ET4000-W32 series cards. */ -#if defined(DEV_BRANCH) && defined(USE_STEALTH32) -extern const device_t et4000w32p_vlb_device; -extern const device_t et4000w32p_pci_device; -#endif -extern const device_t et4000w32p_cardex_vlb_device; -extern const device_t et4000w32p_cardex_pci_device; - -/* MDSI Genius VHR card. */ -extern const device_t genius_device; - -/* Hercules series cards and compatibles. */ -extern const device_t hercules_device; - -/* HerculesPlus series cards and compatibles. */ -extern const device_t herculesplus_device; - -/* Hercules InColor series cards and compatibles. */ -extern const device_t incolor_device; - -/* Hercules ColorPlus series cards and compatibles. */ -extern const device_t colorplus_device; - -/* IBM MDA and compatibles. */ -extern const device_t mda_device; - -/* Oak Technology OTI series cards. */ -extern const device_t oti037c_device; -extern const device_t oti067_device; -extern const device_t oti067_acer386_device; -extern const device_t oti077_device; - -/* Paradise PVGA series cards and compatibles. */ -extern const device_t paradise_pvga1a_pc2086_device; -extern const device_t paradise_pvga1a_pc3086_device; -extern const device_t paradise_pvga1a_device; -extern const device_t paradise_wd90c11_megapc_device; -extern const device_t paradise_wd90c11_device; -extern const device_t paradise_wd90c30_device; - -/* S3, Inc standard series cards. */ -extern const device_t s3_bahamas64_vlb_device; -extern const device_t s3_bahamas64_pci_device; -extern const device_t s3_9fx_vlb_device; -extern const device_t s3_9fx_pci_device; -extern const device_t s3_phoenix_trio32_vlb_device; -extern const device_t s3_phoenix_trio32_pci_device; -extern const device_t s3_phoenix_trio64_vlb_device; -extern const device_t s3_phoenix_trio64_onboard_pci_device; -extern const device_t s3_phoenix_trio64_pci_device; -extern const device_t s3_phoenix_vision864_pci_device; -extern const device_t s3_phoenix_vision864_vlb_device; -extern const device_t s3_diamond_stealth64_pci_device; -extern const device_t s3_diamond_stealth64_vlb_device; -#if 0 -extern const device_t s3_miro_vision964_device; -#endif - -/* S3, Inc ViRGE series cards. */ -extern const device_t s3_virge_vlb_device; -extern const device_t s3_virge_pci_device; -extern const device_t s3_virge_988_vlb_device; -extern const device_t s3_virge_988_pci_device; -extern const device_t s3_virge_375_vlb_device; -extern const device_t s3_virge_375_pci_device; -extern const device_t s3_virge_375_4_vlb_device; -extern const device_t s3_virge_375_4_pci_device; - -/* Trident 8900 series cards. */ -extern const device_t tvga8900d_device; - -/* Trident 9400 series cards. */ -extern const device_t tgui9400cxi_device; -extern const device_t tgui9440_vlb_device; -extern const device_t tgui9440_pci_device; - -/* TI-derived cards. */ -#if defined(DEV_BRANCH) && defined(USE_TI) -extern const device_t ti_cf62011_device; -#endif -extern const device_t ibm_ps1_2121_device; - -/* IBM VGA and compatibles. */ -extern const device_t vga_device; -extern const device_t trigem_unk_device; -extern const device_t ps1vga_device; - -/* 3Dfx VooDoo-series cards. */ -extern const device_t voodoo_device; - -/* Wyse700 cards. */ -extern const device_t wy700_device; - - -static vidcard_t video_cards[] = { - {"None", "none", NULL, VID_NONE, VIDEO_FLAG_TYPE_SPECIAL, {0, 0, 0, 0, 0, 0, 0}}, - {"Internal", "internal", NULL, VID_INTERNAL, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_ISA, 8, 16, 32, 8, 16, 32}}, - {"[ISA] ATI Graphics Pro Turbo (Mach64 GX)", "mach64gx_isa", &mach64gx_isa_device, VID_MACH64GX_ISA, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_ISA, 3, 3, 6, 5, 5, 10}}, - {"[ISA] ATI Korean VGA (ATI-28800-5)", "ati28800k", &ati28800k_device, VID_ATIKOREANVGA, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_ISA, 3, 3, 6, 5, 5, 10}}, - {"[ISA] ATI VGA-88 (ATI-18800-1)", "ati18800v", &ati18800_vga88_device, VID_VGA88, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_ISA, 8, 16, 32, 8, 16, 32}}, - {"[ISA] ATI VGA Charger (ATI-28800-5)", "ati28800", &ati28800_device, VID_VGACHARGER, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_ISA, 3, 3, 6, 5, 5, 10}}, - {"[ISA] ATI VGA Edge-16 (ATI-18800-5)", "ati18800", &ati18800_device, VID_VGAEDGE16, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_ISA, 8, 16, 32, 8, 16, 32}}, + { "mach64gx_isa", &mach64gx_isa_device }, + { "ati28800k", &ati28800k_device }, + { "ati18800v", &ati18800_vga88_device }, + { "ati28800", &ati28800_device }, + { "ati18800", &ati18800_device }, #if defined(DEV_BRANCH) && defined(USE_WONDER) - {"[ISA] ATI VGA Wonder (ATI-18800)", "ati18800w", &ati18800_wonder_device, VID_VGAWONDER, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_ISA, 8, 16, 32, 8, 16, 32}}, + { "ati18800w", &ati18800_wonder_device }, #endif #if defined(DEV_BRANCH) && defined(USE_XL24) - {"[ISA] ATI VGA Wonder XL24 (ATI-28800-6)", "ati28800w", &ati28800_wonderxl24_device, VID_VGAWONDERXL24, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_ISA, 3, 3, 6, 5, 5, 10}}, + { "ati28800w", &ati28800_wonderxl24_device }, #endif - {"[ISA] CGA", "cga", &cga_device, VID_CGA, VIDEO_FLAG_TYPE_CGA, {VIDEO_ISA, 8, 16, 32, 8, 16, 32}}, - {"[ISA] Chips & Technologies SuperEGA", "superega", &sega_device, VID_SUPER_EGA, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_ISA, 8, 16, 32, 8, 16, 32}}, - {"[ISA] Cirrus Logic GD5428", "cl_gd5428_isa", &gd5428_isa_device, VID_CL_GD5428_ISA, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_ISA, 3, 3, 6, 8, 8, 12}}, - {"[ISA] Cirrus Logic GD5429", "cl_gd5429_isa", &gd5429_isa_device, VID_CL_GD5429_ISA, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_ISA, 3, 3, 6, 8, 8, 12}}, - {"[ISA] Cirrus Logic GD5434", "cl_gd5434_isa", &gd5434_isa_device, VID_CL_GD5434_ISA, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_ISA, 3, 3, 6, 8, 8, 12}}, - {"[ISA] Compaq ATI VGA Wonder XL (ATI-28800-5)", "compaq_ati28800", &compaq_ati28800_device, VID_VGAWONDERXL, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_ISA, 3, 3, 6, 5, 5, 10}}, - {"[ISA] Compaq CGA", "compaq_cga", &compaq_cga_device, VID_COMPAQ_CGA, VIDEO_FLAG_TYPE_CGA, {VIDEO_ISA, 8, 16, 32, 8, 16, 32}}, - {"[ISA] Compaq CGA 2", "compaq_cga_2", &compaq_cga_2_device, VID_COMPAQ_CGA_2, VIDEO_FLAG_TYPE_CGA, {VIDEO_ISA, 8, 16, 32, 8, 16, 32}}, - {"[ISA] Compaq EGA", "compaq_ega", &cpqega_device, VID_COMPAQ_EGA, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_ISA, 8, 16, 32, 8, 16, 32}}, - {"[ISA] EGA", "ega", &ega_device, VID_EGA, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_ISA, 8, 16, 32, 8, 16, 32}}, - {"[ISA] Hercules", "hercules", &hercules_device, VID_HERCULES, VIDEO_FLAG_TYPE_MDA, {VIDEO_ISA, 8, 16, 32, 8, 16, 32}}, - {"[ISA] Hercules Plus", "hercules_plus", &herculesplus_device, VID_HERCULESPLUS, VIDEO_FLAG_TYPE_MDA, {VIDEO_ISA, 8, 16, 32, 8, 16, 32}}, - {"[ISA] Hercules InColor", "incolor", &incolor_device, VID_INCOLOR, VIDEO_FLAG_TYPE_MDA, {VIDEO_ISA, 8, 16, 32, 8, 16, 32}}, - {"[ISA] MDA", "mda", &mda_device, VID_MDA, VIDEO_FLAG_TYPE_MDA, {VIDEO_ISA, 8, 16, 32, 8, 16, 32}}, - {"[ISA] MDSI Genius", "genius", &genius_device, VID_GENIUS, VIDEO_FLAG_TYPE_CGA, {VIDEO_ISA, 8, 16, 32, 8, 16, 32}}, - {"[ISA] OAK OTI-037C", "oti037c", &oti037c_device, VID_OTI037C, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_ISA, 6, 8, 16, 6, 8, 16}}, - {"[ISA] OAK OTI-067", "oti067", &oti067_device, VID_OTI067, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_ISA, 6, 8, 16, 6, 8, 16}}, - {"[ISA] OAK OTI-077", "oti077", &oti077_device, VID_OTI077, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_ISA, 6, 8, 16, 6, 8, 16}}, - {"[ISA] Paradise PVGA1A", "pvga1a", ¶dise_pvga1a_device, VID_PVGA1A, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_ISA, 8, 16, 32, 8, 16, 32}}, - {"[ISA] Paradise WD90C11-LR", "wd90c11", ¶dise_wd90c11_device, VID_WD90C11, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_ISA, 8, 16, 32, 8, 16, 32}}, - {"[ISA] Paradise WD90C30-LR", "wd90c30", ¶dise_wd90c30_device, VID_WD90C30, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_ISA, 6, 8, 16, 6, 8, 16}}, - {"[ISA] Plantronics ColorPlus", "plantronics", &colorplus_device, VID_COLORPLUS, VIDEO_FLAG_TYPE_CGA, {VIDEO_ISA, 8, 16, 32, 8, 16, 32}}, + { "superega", &sega_device }, + { "cl_gd5428_isa", &gd5428_isa_device }, + { "cl_gd5429_isa", &gd5429_isa_device }, + { "cl_gd5434_isa", &gd5434_isa_device }, + { "compaq_ati28800", &ati28800_compaq_device }, + { "compaq_cga", &cga_compaq_device }, + { "compaq_cga_2", &cga_compaq2_device }, + { "compaq_ega", &ega_compaq_device }, + { "hercules_plus", &herculesplus_device }, + { "incolor", &incolor_device }, + { "genius", &genius_device }, + { "oti037c", &oti037c_device }, + { "oti067", &oti067_device }, + { "oti077", &oti077_device }, + { "pvga1a", ¶dise_pvga1a_device }, + { "wd90c11", ¶dise_wd90c11_device }, + { "wd90c30", ¶dise_wd90c30_device }, + { "plantronics", &colorplus_device }, #if defined(DEV_BRANCH) && defined(USE_TI) - {"[ISA] TI CF62011 SVGA", "ti_cf62011", &ti_cf62011_device, VID_TICF62011, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_ISA, 8, 16, 32, 8, 16, 32}}, + { "ti_cf62011", &ti_cf62011_device }, #endif - {"[ISA] Trident TVGA8900D", "tvga8900d", &tvga8900d_device, VID_TVGA, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_ISA, 3, 3, 6, 8, 8, 12}}, - {"[ISA] Tseng ET4000AX", "et4000ax", &et4000_isa_device, VID_ET4000, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_ISA, 3, 3, 6, 5, 5, 10}}, - {"[ISA] Trigem Korean VGA (ET4000AX)", "tgkorvga", &et4000k_isa_device, VID_TGKOREANVGA, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_ISA, 3, 3, 6, 5, 5, 10}}, - {"[ISA] VGA", "vga", &vga_device, VID_VGA, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_ISA, 8, 16, 32, 8, 16, 32}}, - {"[ISA] Wyse 700", "wy700", &wy700_device, VID_WY700, VIDEO_FLAG_TYPE_CGA, {VIDEO_ISA, 8, 16, 32, 8, 16, 32}}, - {"[MCA] Tseng ET4000AX", "et4000ax_mca", &et4000_mca_device, VID_ET4000, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_MCA, 4, 5, 10, 5, 5, 10}}, - {"[PCI] ATI Graphics Pro Turbo (Mach64 GX)", "mach64gx_pci", &mach64gx_pci_device, VID_MACH64GX_PCI, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 2, 2, 1, 20, 20, 21}}, - {"[PCI] ATI Video Xpression (Mach64 VT2)", "mach64vt2", &mach64vt2_device, VID_MACH64VT2, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 2, 2, 1, 20, 20, 21}}, - {"[PCI] Cardex Tseng ET4000/w32p", "et4000w32p_pci", &et4000w32p_cardex_pci_device, VID_ET4000W32_CARDEX_PCI, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 4, 4, 4, 10, 10, 10}}, - {"[PCI] Cirrus Logic GD5430", "cl_gd5430_pci", &gd5430_pci_device, VID_CL_GD5430_PCI, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 4, 4, 8, 10, 10, 20}}, - {"[PCI] Cirrus Logic GD5434", "cl_gd5434_pci", &gd5434_pci_device, VID_CL_GD5434_PCI, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 4, 4, 8, 10, 10, 20}}, - {"[PCI] Cirrus Logic GD5436", "cl_gd5436_pci", &gd5436_pci_device, VID_CL_GD5436_PCI, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 4, 4, 8, 10, 10, 20}}, - {"[PCI] Cirrus Logic GD5446", "cl_gd5446_pci", &gd5446_pci_device, VID_CL_GD5446_PCI, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 4, 4, 8, 10, 10, 20}}, - {"[PCI] Cirrus Logic GD5480", "cl_gd5480_pci", &gd5480_pci_device, VID_CL_GD5480_PCI, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 4, 4, 8, 10, 10, 20}}, -#if defined(DEV_BRANCH) && defined(USE_STEALTH32) - {"[PCI] Diamond Stealth 32 (Tseng ET4000/w32p)", "stealth32_pci", &et4000w32p_pci_device, VID_ET4000W32_PCI, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 4, 4, 4, 10, 10, 10}}, -#endif - {"[PCI] Diamond Stealth 3D 2000 (S3 ViRGE)", "stealth3d_2000_pci", &s3_virge_pci_device, VID_VIRGE_PCI, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 2, 2, 3, 28, 28, 45}}, - {"[PCI] Diamond Stealth 3D 3000 (S3 ViRGE/VX)", "stealth3d_3000_pci", &s3_virge_988_pci_device, VID_VIRGEVX_PCI, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 2, 2, 4, 26, 26, 42}}, - {"[PCI] Diamond Stealth 64 DRAM (S3 Trio64)", "stealth64d_pci", &s3_diamond_stealth64_pci_device, VID_STEALTH64_PCI, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 2, 2, 4, 26, 26, 42}}, - {"[PCI] Number Nine 9FX (S3 Trio64)", "n9_9fx_pci", &s3_9fx_pci_device, VID_N9_9FX_PCI, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 3, 2, 4, 25, 25, 40}}, - {"[PCI] Paradise Bahamas 64 (S3 Vision864)", "bahamas64_pci", &s3_bahamas64_pci_device, VID_BAHAMAS64_PCI, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 4, 4, 5, 20, 20, 35}}, - {"[PCI] Phoenix S3 Vision864", "px_vision864_pci", &s3_phoenix_vision864_pci_device, VID_PHOENIX_VISION864_PCI, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 4, 4, 5, 20, 20, 35}}, - {"[PCI] Phoenix S3 Trio32", "px_trio32_pci", &s3_phoenix_trio32_pci_device, VID_PHOENIX_TRIO32_PCI, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 3, 2, 4, 25, 25, 40}}, - {"[PCI] Phoenix S3 Trio64", "px_trio64_pci", &s3_phoenix_trio64_pci_device, VID_PHOENIX_TRIO64_PCI, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 3, 2, 4, 25, 25, 40}}, - {"[PCI] S3 ViRGE/DX", "virge375_pci", &s3_virge_375_pci_device, VID_VIRGEDX_PCI, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 2, 2, 3, 28, 28, 45}}, - {"[PCI] S3 ViRGE/DX (VBE 2.0)", "virge375_vbe20_pci", &s3_virge_375_4_pci_device, VID_VIRGEDX4_PCI, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 2, 2, 3, 28, 28, 45}}, - {"[PCI] STB Nitro 64V (CL-GD5446)", "cl_gd5446_stb_pci", &gd5446_stb_pci_device, VID_CL_GD5446_STB_PCI, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 4, 4, 8, 10, 10, 20}}, - {"[PCI] Trident TGUI9440", "tgui9440_pci", &tgui9440_pci_device, VID_TGUI9440_PCI, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 4, 8, 16, 4, 8, 16}}, - {"[VLB] ATI Graphics Pro Turbo (Mach64 GX)", "mach64gx_vlb", &mach64gx_vlb_device, VID_MACH64GX_VLB, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 2, 2, 1, 20, 20, 21}}, - {"[VLB] Cardex Tseng ET4000/w32p", "et4000w32p_vlb", &et4000w32p_cardex_vlb_device, VID_ET4000W32_CARDEX_VLB, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 4, 4, 4, 10, 10, 10}}, - {"[VLB] Cirrus Logic GD5429", "cl_gd5429_vlb", &gd5429_vlb_device, VID_CL_GD5429_VLB, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 4, 4, 8, 10, 10, 20}}, - {"[VLB] Cirrus Logic GD5434", "cl_gd5434_vlb", &gd5434_vlb_device, VID_CL_GD5434_VLB, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 4, 4, 8, 10, 10, 20}}, - {"[VLB] Diamond SpeedStar PRO (CL-GD5426)", "cl_gd5426_vlb", &gd5426_vlb_device, VID_CL_GD5426_VLB, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 4, 4, 8, 10, 10, 20}}, - {"[VLB] Diamond SpeedStar PRO SE (CL-GD5430)", "cl_gd5430_vlb", &gd5430_vlb_device, VID_CL_GD5430_VLB, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 4, 4, 8, 10, 10, 20}}, -#if defined(DEV_BRANCH) && defined(USE_STEALTH32) - {"[VLB] Diamond Stealth 32 (Tseng ET4000/w32p)", "stealth32_vlb", &et4000w32p_vlb_device, VID_ET4000W32_VLB, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 4, 4, 4, 10, 10, 10}}, -#endif - {"[VLB] Diamond Stealth 3D 2000 (S3 ViRGE)", "stealth3d_2000_vlb", &s3_virge_vlb_device, VID_VIRGE_VLB, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 2, 2, 3, 28, 28, 45}}, - {"[VLB] Diamond Stealth 3D 3000 (S3 ViRGE/VX)", "stealth3d_3000_vlb", &s3_virge_988_vlb_device, VID_VIRGEVX_VLB, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 2, 2, 4, 26, 26, 42}}, - {"[VLB] Diamond Stealth 64 DRAM (S3 Trio64)", "stealth64d_vlb", &s3_diamond_stealth64_vlb_device, VID_STEALTH64_VLB, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 2, 2, 4, 26, 26, 42}}, - {"[VLB] Number Nine 9FX (S3 Trio64)", "n9_9fx_vlb", &s3_9fx_vlb_device, VID_N9_9FX_VLB, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 3, 2, 4, 25, 25, 40}}, - {"[VLB] Paradise Bahamas 64 (S3 Vision864)", "bahamas64_vlb", &s3_bahamas64_vlb_device, VID_BAHAMAS64_VLB, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 4, 4, 5, 20, 20, 35}}, - {"[VLB] Phoenix S3 Vision864", "px_vision864_vlb", &s3_phoenix_vision864_vlb_device, VID_PHOENIX_VISION864_VLB, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 4, 4, 5, 20, 20, 35}}, - {"[VLB] Phoenix S3 Trio32", "px_trio32_vlb", &s3_phoenix_trio32_vlb_device, VID_PHOENIX_TRIO32_VLB, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 3, 2, 4, 25, 25, 40}}, - {"[VLB] Phoenix S3 Trio64", "px_trio64_vlb", &s3_phoenix_trio64_vlb_device, VID_PHOENIX_TRIO64_VLB, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 3, 2, 4, 25, 25, 40}}, - {"[VLB] S3 ViRGE/DX", "virge375_vlb", &s3_virge_375_vlb_device, VID_VIRGEDX_VLB, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 2, 2, 3, 28, 28, 45}}, - {"[VLB] S3 ViRGE/DX (VBE 2.0)", "virge375_vbe20_vlb", &s3_virge_375_4_vlb_device, VID_VIRGEDX4_VLB, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 2, 2, 3, 28, 28, 45}}, - {"[VLB] Trident TGUI9400CXi", "tgui9400cxi_vlb", &tgui9400cxi_device, VID_TGUI9400CXI, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 4, 8, 16, 4, 8, 16}}, - {"[VLB] Trident TGUI9440", "tgui9440_vlb", &tgui9440_vlb_device, VID_TGUI9440_VLB, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 4, 8, 16, 4, 8, 16}}, - {"", "", NULL, -1, 0, {0, 0, 0, 0, 0, 0, 0}} + { "tvga8900d", &tvga8900d_device }, + { "et4000ax", &et4000_isa_device }, + { "tgkorvga", &et4000k_isa_device }, + { "wy700", &wy700_device }, + + { "et4000ax_mca", &et4000_mca_device }, + + { "mach64gx_pci", &mach64gx_pci_device }, + { "mach64vt2", &mach64vt2_device }, + { "et4000w32p_pci", &et4000w32p_cardex_pci_device }, + { "cl_gd5430_pci", &gd5430_pci_device }, + { "cl_gd5434_pci", &gd5434_pci_device }, + { "cl_gd5436_pci", &gd5436_pci_device }, + { "cl_gd5440_pci", &gd5440_pci_device }, + { "cl_gd5446_pci", &gd5446_pci_device }, + { "cl_gd5480_pci", &gd5480_pci_device }, + { "stealth32_pci", &et4000w32p_pci_device }, + { "stealth3d_2000_pci", &s3_virge_pci_device }, + { "stealth3d_3000_pci", &s3_virge_988_pci_device }, + { "stealth64d_pci", &s3_diamond_stealth64_pci_device}, + { "stealth64v_pci", &s3_diamond_stealth64_964_pci_device}, + { "n9_9fx_pci", &s3_9fx_pci_device }, + { "bahamas64_pci", &s3_bahamas64_pci_device }, + { "px_vision864_pci", &s3_phoenix_vision864_pci_device}, + { "px_trio32_pci", &s3_phoenix_trio32_pci_device }, + { "px_trio64_pci", &s3_phoenix_trio64_pci_device }, + { "virge375_pci", &s3_virge_375_pci_device }, + { "virge375_vbe20_pci", &s3_virge_375_4_pci_device }, + { "cl_gd5446_stb_pci", &gd5446_stb_pci_device }, + { "tgui9440_pci", &tgui9440_pci_device }, + + { "mach64gx_vlb", &mach64gx_vlb_device }, + { "et4000w32p_vlb", &et4000w32p_cardex_vlb_device }, + { "cl_gd5429_vlb", &gd5429_vlb_device }, + { "cl_gd5434_vlb", &gd5434_vlb_device }, + { "stealth32_vlb", &et4000w32p_vlb_device }, + { "cl_gd5426_vlb", &gd5426_vlb_device }, + { "cl_gd5430_vlb", &gd5430_vlb_device }, + { "stealth3d_2000_vlb", &s3_virge_vlb_device }, + { "stealth3d_3000_vlb", &s3_virge_988_vlb_device }, + { "stealth64d_vlb", &s3_diamond_stealth64_vlb_device}, + { "stealth64v_vlb", &s3_diamond_stealth64_964_vlb_device}, + { "n9_9fx_vlb", &s3_9fx_vlb_device }, + { "bahamas64_vlb", &s3_bahamas64_vlb_device }, + { "px_vision864_vlb", &s3_phoenix_vision864_vlb_device}, + { "px_trio32_vlb", &s3_phoenix_trio32_vlb_device }, + { "px_trio64_vlb", &s3_phoenix_trio64_vlb_device }, + { "virge375_vlb", &s3_virge_375_vlb_device }, + { "virge375_vbe20_vlb", &s3_virge_375_4_vlb_device }, + { "tgui9400cxi_vlb", &tgui9400cxi_device }, + { "tgui9440_vlb", &tgui9440_vlb_device }, + + { NULL, NULL } }; -int -video_detect(void) -{ - int c, i; - - /* Make sure we have a usable video card. */ - c = 0; - for (i = 0; i < VID_MAX; i++) { - vid_present[i] = video_card_available(video_old_to_new(i)); - c += vid_present[i]; - } - - return(c); -} - - void video_reset(void) { - pclog("VIDEO: reset (romset=%d, video_card=%d, internal=%d)\n", - romset, video_card, (machines[machine].flags & MACHINE_VIDEO)?1:0); + INFO("VIDEO: reset (video_card=%d, internal=%d)\n", + video_card, (machines[machine].flags & MACHINE_VIDEO) ? 1 : 0); /* Reset the CGA palette. */ cga_palette = 0; cgapal_rebuild(); + /* + * Clear (deallocate) any video font memory. + * + * We have to do this before the machine is reset, as + * that *might* allocate it if that uses an internal + * controller using extended font memory.. + */ + video_reset_font(); + /* Initialize the video font tables. */ - loadfont(L"video/ibm/mda/mda.rom", 0); - loadfont(L"video/wyse/wyse700/wy700.rom", 3); - loadfont(L"video/mdsi/genius/8x12.bin", 4); + video_load_font(L"video/ibm/mda/mda.rom", 0); /* Do not initialize internal cards here. */ if ((video_card == VID_NONE) || \ - (video_card == VID_INTERNAL) || machines[machine].fixed_vidcard) return; + (video_card == VID_INTERNAL) || \ + machines[machine].fixed_vidcard) return; - if (fontdatksc5601 != NULL) { - free(fontdatksc5601); - fontdatksc5601 = NULL; - } + /* Configure default timing parameters for the card. */ + video_inform(VID_TYPE_SPEC, NULL); - /* Initialize the video card. */ - device_add(video_cards[video_old_to_new(video_card)].device); + device_add(video_cards[video_card].device); /* Enable the Voodoo if configured. */ if (voodoo_enabled) @@ -366,7 +194,7 @@ video_reset(void) int video_card_available(int card) { - if (video_cards[card].device) + if (video_cards[card].device != NULL) return(device_available(video_cards[card].device)); return(1); @@ -376,7 +204,10 @@ video_card_available(int card) const char * video_card_getname(int card) { - return(video_cards[card].name); + if (video_cards[card].device != NULL) + return(video_cards[card].device->name); + + return(NULL); } @@ -390,57 +221,13 @@ video_card_getdevice(int card) int video_card_has_config(int card) { - if (video_cards[card].device == NULL) return(0); - - return(video_cards[card].device->config ? 1 : 0); -} - - -const video_timings_t * -video_card_gettiming(int card) -{ - return(&video_cards[card].timing); -} - - -int -video_card_getid(const char *s) -{ - int c = 0; - - while (video_cards[c].legacy_id != -1) { - if (! strcmp(video_cards[c].name, s)) - return(c); - c++; - } - - /* Not found. */ - return(-1); -} - - -int -video_old_to_new(int card) -{ - int c = 0; - - while (video_cards[c].legacy_id != -1) { - if (video_cards[c].legacy_id == card) - return(c); - c++; - } + if (video_cards[card].device != NULL) + return(video_cards[card].device->config ? 1 : 0); return(0); } -int -video_new_to_old(int card) -{ - return(video_cards[card].legacy_id); -} - - const char * video_get_internal_name(int card) { @@ -453,112 +240,12 @@ video_get_video_from_internal_name(const char *s) { int c = 0; - while (video_cards[c].legacy_id != -1) { + while (video_cards[c].internal_name != NULL) { if (! strcmp(video_cards[c].internal_name, s)) - return(video_cards[c].legacy_id); + return(c); c++; } /* Not found. */ return(-1); } - - -int -video_is_mda(void) -{ - switch (romset) { - case ROM_IBMPCJR: - case ROM_TANDY: - case ROM_TANDY1000HX: - case ROM_TANDY1000SL2: - case ROM_PC1512: - case ROM_PC1640: - case ROM_PC200: - case ROM_OLIM24: - case ROM_PC2086: - case ROM_PC3086: - case ROM_MEGAPC: - case ROM_MEGAPCDX: - case ROM_IBMPS1_2011: - case ROM_IBMPS2_M30_286: - case ROM_IBMPS2_M50: - case ROM_IBMPS2_M55SX: - case ROM_IBMPS2_M70_TYPE3: - case ROM_IBMPS2_M70_TYPE4: - case ROM_IBMPS2_M80: - case ROM_IBMPS1_2121: - case ROM_T3100E: - return(0); - } - - return((video_cards[video_old_to_new(video_card)].flags & VIDEO_FLAG_TYPE_MASK) == VIDEO_FLAG_TYPE_MDA); -} - - -int -video_is_cga(void) -{ - switch (romset) { - case ROM_IBMPCJR: - case ROM_TANDY: - case ROM_TANDY1000HX: - case ROM_TANDY1000SL2: - case ROM_PC1512: - case ROM_PC200: - case ROM_OLIM24: - case ROM_T3100E: - return(1); - - case ROM_PC1640: - case ROM_PC2086: - case ROM_PC3086: - case ROM_MEGAPC: - case ROM_MEGAPCDX: - case ROM_IBMPS1_2011: - case ROM_IBMPS2_M30_286: - case ROM_IBMPS2_M50: - case ROM_IBMPS2_M55SX: - case ROM_IBMPS2_M70_TYPE3: - case ROM_IBMPS2_M70_TYPE4: - case ROM_IBMPS2_M80: - case ROM_IBMPS1_2121: - return(0); - } - - return((video_cards[video_old_to_new(video_card)].flags & VIDEO_FLAG_TYPE_MASK) == VIDEO_FLAG_TYPE_CGA); -} - - -int -video_is_ega_vga(void) -{ - switch (romset) { - case ROM_IBMPCJR: - case ROM_TANDY: - case ROM_TANDY1000HX: - case ROM_TANDY1000SL2: - case ROM_PC1512: - case ROM_PC200: - case ROM_OLIM24: - case ROM_T3100E: - return(0); - - case ROM_PC1640: - case ROM_PC2086: - case ROM_PC3086: - case ROM_MEGAPC: - case ROM_MEGAPCDX: - case ROM_IBMPS1_2011: - case ROM_IBMPS2_M30_286: - case ROM_IBMPS2_M50: - case ROM_IBMPS2_M55SX: - case ROM_IBMPS2_M70_TYPE3: - case ROM_IBMPS2_M70_TYPE4: - case ROM_IBMPS2_M80: - case ROM_IBMPS1_2121: - return(1); - } - - return((video_cards[video_old_to_new(video_card)].flags & VIDEO_FLAG_TYPE_MASK) == VIDEO_FLAG_TYPE_SPECIAL); -} diff --git a/src/emu.h b/src/emu.h index 001c08e..894f442 100644 --- a/src/emu.h +++ b/src/emu.h @@ -8,7 +8,7 @@ * * Main include file for the application. * - * Version: @(#)emu.h 1.0.33 2018/10/04 + * Version: @(#)emu.h 1.0.32 2018/10/05 * * Author: Fred N. van Kempen, * @@ -49,8 +49,13 @@ /* Configuration values. */ +#ifdef _WIN32 #define SCREEN_RES_X 640 #define SCREEN_RES_Y 480 +#else +#define SCREEN_RES_X 800 +#define SCREEN_RES_Y 600 +#endif /* Pre-defined directory names. */ #define LANGUAGE_PATH L"lang" @@ -69,6 +74,7 @@ #define BIOS_FILE L"bios.txt" #define CONFIG_FILE L"config.varc" #define CONFIG_FILE_EXT L".varc" +#define NVR_FILE_EXT L".nvr" #define DUMP_FILE_EXT L".dmp" /* Pre-defined URLs to websites. */ @@ -76,8 +82,74 @@ #define URL_PAYPAL L"https://www.paypal.me/VARCem" -#define MIN(a, b) ((a) < (b) ? (a) : (b)) -#define ABS(x) ((x) > 0 ? (x) : -(x)) +/* + * Definitions for the logging system. + * + * First, let us start by defining the varrious logging + * levels in use. Some things must always logged (for + * example, serious errors), while other info is nice + * to have, but not always. + * + * By default, the system starts up in the INFO level, + * so, messages up to and including LOG_INFO will be + * written to the logfile. The --quiet commandline + * option will lower this to LOG_ERROR level, meaning, + * only real errors will be shown. + */ +#define LOG_ALWAYS 0 /* this level always shows */ +#define LOG_ERR LOG_ALWAYS /* errors always logged */ +#define LOG_INFO 1 /* informational logging */ +#define LOG_DEBUG 2 /* debug-level info */ +#define LOG_DETAIL 3 /* more detailed info */ +#define LOG_LOWLEVEL 4 /* pretty verbose stuff */ + +/* + * Now define macros that can be used in the code, + * and which always react the same way. These are + * just shorthands to keep the code clean-ish. + */ +#define ERRLOG(...) pclog(LOG_ERR, __VA_ARGS__) /* always logged */ +#define INFO(...) pclog(LOG_INFO, __VA_ARGS__) /* informational */ + +/* + * Most modules in the program will use the main + * logging facility provided by the pc.c file, but + * a module CAN use its own logging function for + * debugging, for example while it is being worked + * on. Those modules should define the 'dbglog' + * macro to their own function before including the + * main include file, emu.h, to make the logging + * macros use that local function. + * + * By default, if none was defined, we define it + * to be the main logging function. + */ +#ifndef dbglog +# define dbglog pclog +#endif + +/* + * The debug logging macros are also shorthands to + * keep the code reasonably clean from #ifdef and + * other clutter. + * + * Macros for several levels are provided. + */ +#ifdef _LOGGING +# define DBGLOG(x, ...) dbglog(LOG_DEBUG+(x), __VA_ARGS__) +#else +# define DBGLOG(x, ...) do {/*nothing*/} while(0) +#endif +#define DEBUG(...) DBGLOG(0, __VA_ARGS__) /* default-level */ + + +/* For systems that do not provide these. */ +#ifndef MIN +# define MIN(a, b) ((a) < (b) ? (a) : (b)) +#endif +#ifndef ABS +# define ABS(x) ((x) > 0 ? (x) : -(x)) +#endif #ifdef __cplusplus @@ -96,11 +168,11 @@ extern int video_fps; /* (O) render speed in fps */ #endif extern int config_ro; /* (O) dont modify cfg file */ extern int settings_only; /* (O) only the settings dlg */ +extern int log_level; /* (O) global logging level */ extern wchar_t log_path[1024]; /* (O) full path of logfile */ - /* Configuration variables. */ -extern int lang_id; /* (C) language ID */ +extern int language; /* (C) language ID */ extern int window_w, window_h, /* (C) window size and */ window_x, window_y, /* position info */ window_remember; @@ -117,13 +189,11 @@ extern int vid_api, /* (C) video renderer */ scale, /* (C) screen scale factor */ enable_overscan, /* (C) video */ force_43, /* (C) video */ - rctrl_is_lalt, /* (C) set R-CTRL as L-ALT */ - update_icons; /* (C) update statbar icons */ + rctrl_is_lalt; /* (C) set R-CTRL as L-ALT */ extern int video_card, /* (C) graphics/video card */ - video_speed, /* (C) video option */ voodoo_enabled; /* (C) video option */ extern int mouse_type; /* (C) selected mouse type */ -extern int enable_sync; /* (C) enable time sync */ +extern int time_sync; /* (C) enable time sync */ extern int game_enabled, /* (C) enable game port */ serial_enabled[], /* (C) enable serial ports */ parallel_enabled[], /* (C) enable LPT ports */ @@ -140,10 +210,11 @@ extern int sound_card, /* (C) selected sound card */ sound_is_float, /* (C) sound uses FP values */ sound_gain, /* (C) sound volume gain */ mpu401_standalone_enable, /* (C) sound option */ - opl3_type, /* (C) sound option */ + opl_type, /* (C) sound option */ midi_device; /* (C) selected midi device */ extern int joystick_type; /* (C) joystick type */ extern int mem_size; /* (C) memory size */ +extern int machine; /* (C) current machine ID */ extern int cpu_manufacturer, /* (C) cpu manufacturer */ cpu, /* (C) cpu type */ cpu_use_dynarec, /* (C) cpu uses/needs Dyna */ @@ -152,7 +223,6 @@ extern int network_type; /* (C) net provider type */ extern int network_card; /* (C) net interface num */ extern char network_host[512]; /* (C) host network intf */ - /* Global variables. */ extern char emu_title[64]; /* full name of application */ extern char emu_version[32]; /* short version ID string */ @@ -161,20 +231,47 @@ extern wchar_t exe_path[1024]; /* emu executable path */ extern wchar_t emu_path[1024]; /* emu installation path */ extern wchar_t usr_path[1024]; /* path (dir) of user data */ extern wchar_t cfg_path[1024]; /* full path of config file */ -extern FILE *stdlog; /* file to log output to */ +extern int emu_lang_id; /* current language ID */ extern int scrnsz_x, /* current screen size, X */ scrnsz_y; /* current screen size, Y */ -extern int unscaled_size_x, /* current unscaled size X */ - unscaled_size_y, /* current unscaled size Y */ - efscrnsz_y; -extern int config_changed; /* config has changed */ +extern int config_changed, /* config has changed */ + dopause, /* system is paused */ + doresize, /* screen resize requested */ + mouse_capture; /* mouse is captured in app */ + +#ifdef _LOGGING +extern int pci_do_log; +extern int keyboard_do_log; +extern int mouse_do_log; +extern int game_do_log; +extern int parallel_do_log; +extern int serial_do_log; +extern int fdc_do_log; +extern int fdd_do_log; +extern int d86f_do_log; +extern int hdc_do_log; +extern int hdd_do_log; +extern int zip_do_log; +extern int cdrom_do_log; +extern int cdrom_image_do_log; +extern int cdrom_ioctl_do_log; +extern int sound_do_log; +extern int sound_midi_do_log; +extern int sound_dev_do_log; +extern int network_do_log; +extern int network_dev_do_log; +extern int scsi_do_log; +extern int scsi_disk_do_log; +extern int scsi_dev_do_log; +extern int video_do_log; +#endif /* Function prototypes. */ #ifdef HAVE_STDARG_H extern void pclog_ex(const char *fmt, va_list); #endif -extern void pclog(const char *fmt, ...); +extern void pclog(int level, const char *fmt, ...); extern void pclog_repeat(int enabled); extern void pclog_dump(int num); extern void fatal(const char *fmt, ...); @@ -188,20 +285,21 @@ extern void pc_reset_hard_init(void); extern void pc_reset_hard(void); extern void pc_reset(int hard); extern void pc_reload(const wchar_t *fn); +extern void pc_set_speed(void); extern void pc_full_speed(void); extern void pc_speed_changed(void); extern void pc_thread(void *param); -extern void pc_start(void); +extern void pc_pause(int p); extern void pc_onesec(void); extern void set_screen_size(int x, int y); extern void set_screen_size_natural(void); +extern void get_screen_size_natural(int *x, int *y); extern const wchar_t *get_string(int id); extern uint32_t get_val(const char *str); #ifndef USE_STANDARD_MALLOC extern void *mem_alloc(size_t sz); -#define malloc mem_alloc #endif #ifdef __cplusplus diff --git a/src/io.c b/src/io.c index a213b4e..575662b 100644 --- a/src/io.c +++ b/src/io.c @@ -8,7 +8,7 @@ * * Implement I/O ports and their operations. * - * Version: @(#)io.c 1.0.2 2018/05/04 + * Version: @(#)io.c 1.0.3 2018/09/22 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -70,12 +70,12 @@ static io_t *io[NPORTS], #ifdef IO_CATCH -static uint8_t null_inb(uint16_t addr, void *priv) { pclog("IO: read(%04x)\n"); return(0xff); } -static uint16_t null_inw(uint16_t addr, void *priv) { pclog("IO: readw(%04x)\n"); return(0xffff); } -static uint32_t null_inl(uint16_t addr, void *priv) { pclog("IO: readl(%04x)\n"); return(0xffffffff); } -static void null_outb(uint16_t addr, uint8_t val, void *priv) { pclog("IO: write(%04x, %02x)\n", val); } -static void null_outw(uint16_t addr, uint16_t val, void *priv) { pclog("IO: writew(%04x, %04x)\n", val); } -static void null_outl(uint16_t addr, uint32_t val, void *priv) { pclog("IO: writel(%04x, %08lx)\n", val); } +static uint8_t null_inb(uint16_t addr, void *priv) { DEBUG("IO: read(%04x)\n"); return(0xff); } +static uint16_t null_inw(uint16_t addr, void *priv) { DEBUG("IO: readw(%04x)\n"); return(0xffff); } +static uint32_t null_inl(uint16_t addr, void *priv) { DEBUG("IO: readl(%04x)\n"); return(0xffffffff); } +static void null_outb(uint16_t addr, uint8_t val, void *priv) { DEBUG("IO: write(%04x, %02x)\n", val); } +static void null_outw(uint16_t addr, uint16_t val, void *priv) { DEBUG("IO: writew(%04x, %04x)\n", val); } +static void null_outl(uint16_t addr, uint32_t val, void *priv) { DEBUG("IO: writel(%04x, %08lx)\n", val); } #endif @@ -85,14 +85,14 @@ io_init(void) io_t *p, *q; int c; - pclog("IO: initializing\n"); + INFO("IO: initializing\n"); if (! initialized) { - for (c=0; cnext = NULL; @@ -138,9 +138,9 @@ io_sethandler(uint16_t base, int size, io_t *p, *q = NULL; int c; - for (c=0; cnext = q; @@ -175,7 +175,7 @@ io_removehandler(uint16_t base, int size, io_t *p; int c; - for (c=0; cnext = q; @@ -290,7 +290,7 @@ inb(uint16_t port) #ifdef IO_TRACE if (CS == IO_TRACE) - pclog("IOTRACE(%04X): inb(%04x)=%02x\n", IO_TRACE, port, r); + DEBUG("IOTRACE(%04X): inb(%04x)=%02x\n", IO_TRACE, port, r); #endif return(r); @@ -313,7 +313,7 @@ outb(uint16_t port, uint8_t val) #ifdef IO_TRACE if (CS == IO_TRACE) - pclog("IOTRACE(%04X): outb(%04x,%02x)\n", IO_TRACE, port, val); + DEBUG("IOTRACE(%04X): outb(%04x,%02x)\n", IO_TRACE, port, val); #endif } diff --git a/src/machines/m_amstrad.c b/src/machines/m_amstrad.c index d730c99..bfa5d5a 100644 --- a/src/machines/m_amstrad.c +++ b/src/machines/m_amstrad.c @@ -32,7 +32,7 @@ * BIOSES: I need to re-do the bios.txt format so we can load non-BIOS * ROM files for a given machine, such as font roms here.. * - * Version: @(#)m_amstrad.c 1.0.18 2018/05/08 + * Version: @(#)m_amstrad.c 1.0.19 2018/10/05 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -65,6 +65,7 @@ #include #include #include +#define dbglog kbd_log #include "../emu.h" #include "../cpu/cpu.h" #include "../io.h" @@ -135,6 +136,7 @@ typedef struct { typedef struct { /* Machine stuff. */ + int8_t type; uint8_t dead; uint8_t stat1, stat2; @@ -155,21 +157,20 @@ typedef struct { } amstrad_t; -/* Defined in the video module. */ -extern const device_t paradise_pvga1a_pc2086_device; -extern const device_t paradise_pvga1a_pc3086_device; -extern const device_t paradise_wd90c11_megapc_device; - - static uint8_t key_queue[16]; static int key_queue_start = 0, key_queue_end = 0; -static uint8_t crtc_mask[32] = { +static const uint8_t crtc_mask[32] = { 0xff, 0xff, 0xff, 0xff, 0x7f, 0x1f, 0x7f, 0x7f, 0xf3, 0x1f, 0x7f, 0x1f, 0x3f, 0xff, 0x3f, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; +static const video_timings_t pc1512_timing = {VID_BUS,0,0,0,0,0,0}; +static const video_timings_t pc1640_timing = {VID_ISA,8,16,32,8,16,32}; +static const video_timings_t pc200_timing = {VID_ISA,8,16,32,8,16,32}; +static const video_timings_t pvga1a_timing = {VID_ISA,6,8,16,6,8,16}; +static const video_timings_t wd90c11_timing = {VID_ISA,3,3,6,5,5,10}; static void @@ -262,7 +263,6 @@ vid_write_1512(uint32_t addr, uint8_t val, void *priv) { amsvid_t *vid = (amsvid_t *)priv; - egawrites++; cycles -= 12; addr &= 0x3fff; @@ -281,7 +281,6 @@ vid_read_1512(uint32_t addr, void *priv) { amsvid_t *vid = (amsvid_t *)priv; - egareads++; cycles -= 12; addr &= 0x3fff; @@ -425,9 +424,9 @@ vid_poll_1512(void *priv) } else { cols[0] = ((vid->cgamode & 0x12) == 0x12) ? 0 : (vid->cgacol & 15) + 16; if (vid->cgamode & 1) - hline(buffer, 0, vid->displine, (vid->crtc[1] << 3) + 16, cols[0]); + cga_hline(buffer, 0, vid->displine, (vid->crtc[1] << 3) + 16, cols[0]); else - hline(buffer, 0, vid->displine, (vid->crtc[1] << 4) + 16, cols[0]); + cga_hline(buffer, 0, vid->displine, (vid->crtc[1] << 4) + 16, cols[0]); } vid->sc = oldsc; @@ -539,22 +538,24 @@ vid_init_1512(amstrad_t *ams) amsvid_t *vid; /* Allocate a video controller block. */ - vid = (amsvid_t *)malloc(sizeof(amsvid_t)); + vid = (amsvid_t *)mem_alloc(sizeof(amsvid_t)); memset(vid, 0x00, sizeof(amsvid_t)); - vid->vram = malloc(0x10000); + vid->vram = (uint8_t *)mem_alloc(0x10000); vid->cgacol = 7; vid->cgamode = 0x12; timer_add(vid_poll_1512, &vid->vidtime, TIMER_ALWAYS_ENABLED, vid); - mem_mapping_add(&vid->cga.mapping, 0xb8000, 0x08000, - vid_read_1512, NULL, NULL, vid_write_1512, NULL, NULL, - NULL, 0, vid); + mem_map_add(&vid->cga.mapping, 0xb8000, 0x08000, + vid_read_1512, NULL, NULL, vid_write_1512, NULL, NULL, + NULL, 0, vid); io_sethandler(0x03d0, 16, vid_in_1512, NULL, NULL, vid_out_1512, NULL, NULL, vid); overscan_x = overscan_y = 16; + video_inform(VID_TYPE_CGA, &pc1512_timing); + ams->vid = vid; } @@ -565,7 +566,6 @@ vid_close_1512(void *priv) amsvid_t *vid = (amsvid_t *)priv; free(vid->vram); - free(vid); } @@ -581,11 +581,13 @@ vid_speed_change_1512(void *priv) static const device_t vid_1512_device = { "Amstrad PC1512 (video)", - 0, 0, + 0, + 0, NULL, vid_close_1512, NULL, NULL, vid_speed_change_1512, NULL, + &pc1512_timing, NULL }; @@ -619,31 +621,33 @@ vid_out_1640(uint16_t addr, uint8_t val, void *priv) case 0x03db: vid->cga_enabled = val & 0x40; if (vid->cga_enabled) { - mem_mapping_enable(&vid->cga.mapping); - mem_mapping_disable(&vid->ega.mapping); + mem_map_enable(&vid->cga.mapping); + mem_map_disable(&vid->ega.mapping); + video_inform(VID_TYPE_CGA, &pc1640_timing); } else { - mem_mapping_disable(&vid->cga.mapping); + mem_map_disable(&vid->cga.mapping); switch (vid->ega.gdcreg[6] & 0xc) { case 0x0: /*128k at A0000*/ - mem_mapping_set_addr(&vid->ega.mapping, - 0xa0000, 0x20000); + mem_map_set_addr(&vid->ega.mapping, + 0xa0000, 0x20000); break; case 0x4: /*64k at A0000*/ - mem_mapping_set_addr(&vid->ega.mapping, - 0xa0000, 0x10000); + mem_map_set_addr(&vid->ega.mapping, + 0xa0000, 0x10000); break; case 0x8: /*32k at B0000*/ - mem_mapping_set_addr(&vid->ega.mapping, - 0xb0000, 0x08000); + mem_map_set_addr(&vid->ega.mapping, + 0xb0000, 0x08000); break; case 0xC: /*32k at B8000*/ - mem_mapping_set_addr(&vid->ega.mapping, - 0xb8000, 0x08000); + mem_map_set_addr(&vid->ega.mapping, + 0xb8000, 0x08000); break; } + video_inform(VID_TYPE_SPEC, &pc1640_timing); } return; } @@ -660,8 +664,10 @@ vid_in_1640(uint16_t addr, void *priv) { amsvid_t *vid = (amsvid_t *)priv; +#if 0 switch (addr) { } +#endif if (vid->cga_enabled) return(cga_in(addr, &vid->cga)); @@ -697,7 +703,7 @@ vid_init_1640(amstrad_t *ams, wchar_t *fn, int sz) amsvid_t *vid; /* Allocate a video controller block. */ - vid = (amsvid_t *)malloc(sizeof(amsvid_t)); + vid = (amsvid_t *)mem_alloc(sizeof(amsvid_t)); memset(vid, 0x00, sizeof(amsvid_t)); /* Load the BIOS. */ @@ -708,10 +714,10 @@ vid_init_1640(amstrad_t *ams, wchar_t *fn, int sz) vid->cga_enabled = 1; cga_init(&vid->cga); - mem_mapping_add(&vid->cga.mapping, 0xb8000, 0x08000, - cga_read, NULL, NULL, cga_write, NULL, NULL, NULL, 0, &vid->cga); - mem_mapping_add(&vid->ega.mapping, 0, 0, - ega_read, NULL, NULL, ega_write, NULL, NULL, NULL, 0, &vid->ega); + mem_map_add(&vid->cga.mapping, 0xb8000, 0x08000, + cga_read,NULL,NULL, cga_write,NULL,NULL, NULL, 0, &vid->cga); + mem_map_add(&vid->ega.mapping, 0, 0, + ega_read,NULL,NULL, ega_write,NULL,NULL, NULL, 0, &vid->ega); io_sethandler(0x03a0, 64, vid_in_1640, NULL, NULL, vid_out_1640, NULL, NULL, vid); @@ -719,6 +725,8 @@ vid_init_1640(amstrad_t *ams, wchar_t *fn, int sz) overscan_x = overscan_y = 16; + video_inform(VID_TYPE_CGA, &pc1640_timing); + ams->vid = vid; } @@ -729,7 +737,6 @@ vid_close_1640(void *priv) amsvid_t *vid = (amsvid_t *)priv; free(vid->ega.vram); - free(vid); } @@ -745,11 +752,13 @@ vid_speed_changed_1640(void *priv) static const device_t vid_1640_device = { "Amstrad PC1640 (video)", - 0, 0, + 0, + 0, NULL, vid_close_1640, NULL, NULL, vid_speed_changed_1640, NULL, + &pc1640_timing, NULL }; @@ -838,15 +847,15 @@ vid_init_200(amstrad_t *ams) cga_t *cga; /* Allocate a video controller block. */ - vid = (amsvid_t *)malloc(sizeof(amsvid_t)); + vid = (amsvid_t *)mem_alloc(sizeof(amsvid_t)); memset(vid, 0x00, sizeof(amsvid_t)); cga = &vid->cga; - cga->vram = malloc(0x4000); + cga->vram = (uint8_t *)mem_alloc(0x4000); cga_init(cga); - mem_mapping_add(&vid->cga.mapping, 0xb8000, 0x08000, - cga_read, NULL, NULL, cga_write, NULL, NULL, NULL, 0, cga); + mem_map_add(&vid->cga.mapping, 0xb8000, 0x08000, + cga_read,NULL,NULL, cga_write,NULL,NULL, NULL, 0, cga); io_sethandler(0x03d0, 16, vid_in_200, NULL, NULL, vid_out_200, NULL, NULL, vid); @@ -854,6 +863,8 @@ vid_init_200(amstrad_t *ams) overscan_x = overscan_y = 16; + video_inform(VID_TYPE_CGA, &pc200_timing); + ams->vid = vid; } @@ -880,17 +891,19 @@ vid_speed_changed_200(void *priv) static const device_t vid_200_device = { "Amstrad PC200 (video)", - 0, 0, + 0, + 0, NULL, vid_close_200, NULL, NULL, vid_speed_changed_200, NULL, + &pc200_timing, NULL }; static void -ms_write(uint16_t addr, uint8_t val, void *priv) +mse_write(uint16_t addr, uint8_t val, void *priv) { amstrad_t *ams = (amstrad_t *)priv; @@ -902,7 +915,7 @@ ms_write(uint16_t addr, uint8_t val, void *priv) static uint8_t -ms_read(uint16_t addr, void *priv) +mse_read(uint16_t addr, void *priv) { amstrad_t *ams = (amstrad_t *)priv; @@ -914,7 +927,7 @@ ms_read(uint16_t addr, void *priv) static int -ms_poll(int x, int y, int z, int b, void *priv) +mse_poll(int x, int y, int z, int b, void *priv) { amstrad_t *ams = (amstrad_t *)priv; @@ -940,10 +953,7 @@ static void kbd_adddata(uint16_t val) { key_queue[key_queue_end] = (uint8_t)(val&0xff); -#ifdef ENABLE_KEYBOARD_LOG - pclog("keyboard_amstrad : %02X added to key queue at %i\n", - val, key_queue_end); -#endif + DBGLOG(1, "AMSkb: %02X added to key queue at %i\n", val, key_queue_end); key_queue_end = (key_queue_end + 1) & 0xf; } @@ -959,13 +969,8 @@ static void kbd_write(uint16_t port, uint8_t val, void *priv) { amstrad_t *ams = (amstrad_t *)priv; -#ifdef WALTJE - int i = 0; -#endif -#ifdef ENABLE_KEYBOARD_LOG - pclog("keyboard_amstrad : write %04X %02X %02X\n", port, val, ams->pb); -#endif + DBGLOG(2, "AMSkb: write %04X %02X %02X\n", port, val, ams->pb); switch (port) { case 0x61: @@ -983,13 +988,9 @@ kbd_write(uint16_t port, uint8_t val, void *priv) * * This register is controlled by BIOS and/or ROS. */ -#ifdef ENABLE_KEYBOARD_LOG - pclog("AMSkb: write PB %02x (%02x)\n", val, ams->pb); -#endif + DBGLOG(1, "AMSkb: write PB %02x (%02x)\n", val, ams->pb); if (!(ams->pb & 0x40) && (val & 0x40)) { /*Reset keyboard*/ -#ifdef ENABLE_KEYBOARD_LOG - pclog("AMSkb: reset keyboard\n"); -#endif + DEBUG("AMSkb: reset keyboard\n"); kbd_adddata(0xaa); } ams->pb = val; @@ -1015,30 +1016,19 @@ kbd_write(uint16_t port, uint8_t val, void *priv) break; case 0x64: -#ifdef WALTJE - pclog("AMSkb: STAT1 = %02x (%02x)\n", val, ams->stat1); -#endif ams->stat1 = val; break; case 0x65: -#ifdef WALTJE - pclog("AMSkb: STAT2 = %02x (%02x)\n", val, ams->stat2); - i = 512 + (((val & 0x1f) - 0x0e) * 32); - pclog("AMSkb: %d KB RAM installed.\n", i); -#endif ams->stat2 = val; break; case 0x66: -#ifdef WALTJE - pclog("AMSkb: RESET REQUESTED !\n"); -#endif pc_reset(1); break; default: - pclog("AMSkb: bad keyboard write %04X %02X\n", port, val); + ERRLOG("AMSkb: bad keyboard write %04X %02X\n", port, val); } } @@ -1127,7 +1117,7 @@ kbd_read(uint16_t port, void *priv) break; default: - pclog("AMDkb: bad keyboard read %04X\n", port); + ERRLOG("AMDkb: bad keyboard read %04X\n", port); } return(ret); @@ -1145,17 +1135,13 @@ kbd_poll(void *priv) ams->wantirq = 0; ams->pa = ams->key_waiting; picint(2); -#ifdef ENABLE_KEYBOARD_LOG - pclog("keyboard_amstrad : take IRQ\n"); -#endif + DBGLOG(1, "AMSkb: take IRQ\n"); } if (key_queue_start != key_queue_end && !ams->pa) { ams->key_waiting = key_queue[key_queue_start]; -#ifdef ENABLE_KEYBOARD_LOG - pclog("Reading %02X from the key queue at %i\n", - ams->key_waiting, key_queue_start); -#endif + DBGLOG(1, "AMSkb: reading %02X from the key queue at %i\n", + ams->key_waiting, key_queue_start); key_queue_start = (key_queue_start + 1) & 0xf; ams->wantirq = 1; } @@ -1196,12 +1182,12 @@ ams_read(uint16_t port, void *priv) break; case 0x037a: /* printer status */ - switch(romset) { - case ROM_PC1512: + switch(ams->type) { + case 0: ret = 0x20; break; - case ROM_PC200: + case 2: ret = 0x80; break; @@ -1219,14 +1205,15 @@ ams_read(uint16_t port, void *priv) } -void -machine_amstrad_init(const machine_t *model, void *arg) +static void +amstrad_common_init(const machine_t *model, void *arg, int type) { romdef_t *roms = (romdef_t *)arg; amstrad_t *ams; - ams = (amstrad_t *)malloc(sizeof(amstrad_t)); + ams = (amstrad_t *)mem_alloc(sizeof(amstrad_t)); memset(ams, 0x00, sizeof(amstrad_t)); + ams->type = type; machine_common_init(model, arg); @@ -1237,10 +1224,10 @@ machine_amstrad_init(const machine_t *model, void *arg) //FIXME: parallel_remove_amstrad(); io_sethandler(0x0078, 1, - ms_read, NULL, NULL, ms_write, NULL, NULL, ams); + mse_read, NULL, NULL, mse_write, NULL, NULL, ams); io_sethandler(0x007a, 1, - ms_read, NULL, NULL, ms_write, NULL, NULL, ams); + mse_read, NULL, NULL, mse_write, NULL, NULL, ams); io_sethandler(0x0379, 2, ams_read, NULL, NULL, NULL, NULL, NULL, ams); @@ -1248,12 +1235,12 @@ machine_amstrad_init(const machine_t *model, void *arg) io_sethandler(0xdead, 1, ams_read, NULL, NULL, ams_write, NULL, NULL, ams); - switch(model->id) { - case ROM_PC1512: + switch(ams->type) { + case 0: device_add(&fdc_xt_device); if (video_card == VID_INTERNAL) { /* Load the PC1512 CGA Character Set ROM. */ - loadfont(roms->fontfn, roms->fontnum); + video_load_font(roms->fontfn, roms->fontnum); /* Initialize the internal CGA controller. */ vid_init_1512(ams); @@ -1261,7 +1248,7 @@ machine_amstrad_init(const machine_t *model, void *arg) } break; - case ROM_PC1640: + case 1: device_add(&fdc_xt_device); if (video_card == VID_INTERNAL) { /* Load the BIOS for the internal CGA/EGA. */ @@ -1270,35 +1257,38 @@ machine_amstrad_init(const machine_t *model, void *arg) } break; - case ROM_PC200: + case 2: device_add(&fdc_xt_device); if (video_card == VID_INTERNAL) { /* Load the PC200 CGA Character Set ROM. */ - loadfont(roms->fontfn, roms->fontnum); + video_load_font(roms->fontfn, roms->fontnum); vid_init_200(ams); device_add_ex(&vid_200_device, ams->vid); } break; - case ROM_PC2086: + case 3: device_add(&fdc_at_actlow_device); if (video_card == VID_INTERNAL) { device_add(¶dise_pvga1a_pc2086_device); + video_inform(VID_TYPE_SPEC, &pvga1a_timing); } break; - case ROM_PC3086: + case 4: device_add(&fdc_at_actlow_device); if (video_card == VID_INTERNAL) { device_add(¶dise_pvga1a_pc3086_device); + video_inform(VID_TYPE_SPEC, &pvga1a_timing); } break; - case ROM_MEGAPC: + case 5: device_add(&fdc_at_actlow_device); if (video_card == VID_INTERNAL) { device_add(¶dise_wd90c11_megapc_device); + video_inform(VID_TYPE_SPEC, &wd90c11_timing); } break; } @@ -1315,6 +1305,48 @@ machine_amstrad_init(const machine_t *model, void *arg) /* Tell mouse driver about our internal mouse. */ if (mouse_type == MOUSE_INTERNAL) { mouse_reset(); - mouse_set_poll(ms_poll, ams); + mouse_set_poll(mse_poll, ams); } } + + +void +machine_amstrad_1512_init(const machine_t *model, void *arg) +{ + amstrad_common_init(model, arg, 0); +} + + +void +machine_amstrad_1640_init(const machine_t *model, void *arg) +{ + amstrad_common_init(model, arg, 1); +} + + +void +machine_amstrad_200_init(const machine_t *model, void *arg) +{ + amstrad_common_init(model, arg, 2); +} + + +void +machine_amstrad_2086_init(const machine_t *model, void *arg) +{ + amstrad_common_init(model, arg, 3); +} + + +void +machine_amstrad_3086_init(const machine_t *model, void *arg) +{ + amstrad_common_init(model, arg, 4); +} + + +void +machine_amstrad_mega_init(const machine_t *model, void *arg) +{ + amstrad_common_init(model, arg, 5); +} diff --git a/src/machines/m_at_430fx.c b/src/machines/m_at_430fx.c deleted file mode 100644 index f23ca1b..0000000 --- a/src/machines/m_at_430fx.c +++ /dev/null @@ -1,356 +0,0 @@ -/* - * VARCem Virtual ARchaeological Computer EMulator. - * An emulator of (mostly) x86-based PC systems and devices, - * using the ISA,EISA,VLB,MCA and PCI system buses, roughly - * spanning the era between 1981 and 1995. - * - * This file is part of the VARCem Project. - * - * Implementation of the Intel 430FX PCISet chip. - * - * Version: @(#)m_at_430fx.c 1.0.12 2018/05/06 - * - * Authors: Fred N. van Kempen, - * Miran Grca, - * Sarah Walker, - * - * Copyright 2017,2018 Fred N. van Kempen. - * Copyright 2016-2018 Miran Grca. - * Copyright 2008-2018 Sarah Walker. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the: - * - * Free Software Foundation, Inc. - * 59 Temple Place - Suite 330 - * Boston, MA 02111-1307 - * USA. - */ -#include -#include -#include -#include -#include "../emu.h" -#include "../mem.h" -#include "../rom.h" -#include "../device.h" -#include "../devices/system/pci.h" -#include "../devices/system/memregs.h" -#include "../devices/system/intel_piix.h" -#include "../devices/system/intel_flash.h" -#include "../devices/input/keyboard.h" -#include "../devices/sio/sio.h" -#include "../devices/video/video.h" -#include "machine.h" - - -static uint8_t card_i430fx[256]; - - -static void i430fx_map(uint32_t addr, uint32_t size, int state) -{ - switch (state & 3) - { - case 0: - mem_set_mem_state(addr, size, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); - break; - case 1: - mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_EXTERNAL); - break; - case 2: - mem_set_mem_state(addr, size, MEM_READ_EXTERNAL | MEM_WRITE_INTERNAL); - break; - case 3: - mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - break; - } - flushmmucache_nopc(); -} - - -static void i430fx_write(int func, int addr, uint8_t val, void *priv) -{ - if (func) - return; - - if (addr >= 0x10 && addr < 0x4f) - return; - - switch (addr) - { - case 0x00: case 0x01: case 0x02: case 0x03: - case 0x08: case 0x09: case 0x0a: case 0x0b: - case 0x0c: case 0x0e: - return; - - case 0x04: /*Command register*/ - val &= 0x02; - val |= 0x04; - break; - case 0x05: - val = 0; - break; - - case 0x06: /*Status*/ - val = 0; - break; - case 0x07: - val = 0x02; - break; - - case 0x59: /*PAM0*/ - if ((card_i430fx[0x59] ^ val) & 0xf0) - { - i430fx_map(0xf0000, 0x10000, val >> 4); - shadowbios = (val & 0x10); - } - pclog("i430fx_write : PAM0 write %02X\n", val); - break; - case 0x5a: /*PAM1*/ - if ((card_i430fx[0x5a] ^ val) & 0x0f) - i430fx_map(0xc0000, 0x04000, val & 0xf); - if ((card_i430fx[0x5a] ^ val) & 0xf0) - i430fx_map(0xc4000, 0x04000, val >> 4); - break; - case 0x5b: /*PAM2*/ - if ((card_i430fx[0x5b] ^ val) & 0x0f) - i430fx_map(0xc8000, 0x04000, val & 0xf); - if ((card_i430fx[0x5b] ^ val) & 0xf0) - i430fx_map(0xcc000, 0x04000, val >> 4); - break; - case 0x5c: /*PAM3*/ - if ((card_i430fx[0x5c] ^ val) & 0x0f) - i430fx_map(0xd0000, 0x04000, val & 0xf); - if ((card_i430fx[0x5c] ^ val) & 0xf0) - i430fx_map(0xd4000, 0x04000, val >> 4); - break; - case 0x5d: /*PAM4*/ - if ((card_i430fx[0x5d] ^ val) & 0x0f) - i430fx_map(0xd8000, 0x04000, val & 0xf); - if ((card_i430fx[0x5d] ^ val) & 0xf0) - i430fx_map(0xdc000, 0x04000, val >> 4); - break; - case 0x5e: /*PAM5*/ - if ((card_i430fx[0x5e] ^ val) & 0x0f) - i430fx_map(0xe0000, 0x04000, val & 0xf); - if ((card_i430fx[0x5e] ^ val) & 0xf0) - i430fx_map(0xe4000, 0x04000, val >> 4); - pclog("i430fx_write : PAM5 write %02X\n", val); - break; - case 0x5f: /*PAM6*/ - if ((card_i430fx[0x5f] ^ val) & 0x0f) - i430fx_map(0xe8000, 0x04000, val & 0xf); - if ((card_i430fx[0x5f] ^ val) & 0xf0) - i430fx_map(0xec000, 0x04000, val >> 4); - pclog("i430fx_write : PAM6 write %02X\n", val); - break; - case 0x72: /*SMRAM*/ - if ((card_i430fx[0x72] ^ val) & 0x48) - i430fx_map(0xa0000, 0x20000, ((val & 0x48) == 0x48) ? 3 : 0); - break; - } - - card_i430fx[addr] = val; -} - - -static uint8_t i430fx_read(int func, int addr, void *priv) -{ - if (func) - return 0xff; - - return card_i430fx[addr]; -} - - -static void i430fx_reset(void) -{ - memset(card_i430fx, 0, 256); - card_i430fx[0x00] = 0x86; card_i430fx[0x01] = 0x80; /*Intel*/ - card_i430fx[0x02] = 0x2d; card_i430fx[0x03] = 0x16; /*SB82437FX-66*/ - card_i430fx[0x04] = 0x06; card_i430fx[0x05] = 0x00; - card_i430fx[0x06] = 0x00; card_i430fx[0x07] = 0x82; - if (romset == ROM_MB500N) card_i430fx[0x07] = 0x02; - card_i430fx[0x08] = 0x00; /*A0 stepping*/ - card_i430fx[0x09] = 0x00; card_i430fx[0x0a] = 0x00; card_i430fx[0x0b] = 0x06; - card_i430fx[0x52] = 0x40; /*256kb PLB cache*/ - if (romset == ROM_MB500N) - { - card_i430fx[0x52] = 0x42; - card_i430fx[0x53] = 0x14; - card_i430fx[0x56] = 0x52; /*DRAM control*/ - } - card_i430fx[0x57] = 0x01; - card_i430fx[0x60] = card_i430fx[0x61] = card_i430fx[0x62] = card_i430fx[0x63] = card_i430fx[0x64] = 0x02; - if (romset == ROM_MB500N) - { - card_i430fx[0x67] = 0x11; - card_i430fx[0x69] = 0x03; - card_i430fx[0x70] = 0x20; - } - card_i430fx[0x72] = 0x02; - if (romset == ROM_MB500N) - { - card_i430fx[0x74] = 0x0e; - card_i430fx[0x78] = 0x23; - } -} - - -static void i430fx_pci_reset(void) -{ - i430fx_write(0, 0x59, 0x00, NULL); - i430fx_write(0, 0x72, 0x02, NULL); -} - - -static void i430fx_init(void) -{ - pci_add_card(0, i430fx_read, i430fx_write, NULL); - - i430fx_reset(); - - pci_reset_handler.pci_master_reset = i430fx_pci_reset; -} - - -void -machine_at_p54tp4xe_init(const machine_t *model, void *arg) -{ - machine_at_ps2_init(model, arg); - - memregs_init(); - pci_init(PCI_CONFIG_TYPE_1); - pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); - pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x0B, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x0A, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x09, PCI_CARD_NORMAL, 4, 1, 2, 3); - pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); - i430fx_init(); - piix3_init(7); - fdc37c665_init(); - - device_add(&intel_flash_bxt_device); -} - - -void -machine_at_endeavor_init(const machine_t *model, void *arg) -{ - machine_at_common_init(model, arg); - device_add(&keyboard_ps2_ami_device); - - memregs_init(); - pci_init(PCI_CONFIG_TYPE_1); - pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); - pci_register_slot(0x08, PCI_CARD_ONBOARD, 4, 0, 0, 0); - pci_register_slot(0x0D, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x0E, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x0F, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x10, PCI_CARD_NORMAL, 4, 1, 2, 3); - pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); - i430fx_init(); - piix_init(7); - pc87306_init(); - - device_add(&intel_flash_bxt_ami_device); - - if (video_card == VID_INTERNAL) - device_add(&s3_phoenix_trio64_onboard_pci_device); -} - - -void -machine_at_zappa_init(const machine_t *model, void *arg) -{ - machine_at_common_init(model, arg); - device_add(&keyboard_ps2_ami_device); - - memregs_init(); - pci_init(PCI_CONFIG_TYPE_1); - pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); - pci_register_slot(0x0D, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x0E, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x0F, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); - i430fx_init(); - piix_init(7); - pc87306_init(); - - device_add(&intel_flash_bxt_ami_device); -} - - -void -machine_at_mb500n_init(const machine_t *model, void *arg) -{ - machine_at_ps2_init(model, arg); - - pci_init(PCI_CONFIG_TYPE_1); - pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); - pci_register_slot(0x14, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x13, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x12, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x11, PCI_CARD_NORMAL, 4, 1, 2, 3); - pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); - i430fx_init(); - piix_init(7); - fdc37c665_init(); - - device_add(&intel_flash_bxt_device); -} - - -void -machine_at_president_init(const machine_t *model, void *arg) -{ - machine_at_ps2_init(model, arg); - - memregs_init(); - pci_init(PCI_CONFIG_TYPE_1); - pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); - pci_register_slot(0x08, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x09, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x0A, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x0B, PCI_CARD_NORMAL, 4, 1, 2, 3); - pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); - i430fx_init(); - piix_init(7); - w83877f_init(); - - device_add(&intel_flash_bxt_device); -} - - -void -machine_at_thor_init(const machine_t *model, void *arg) -{ - machine_at_common_init(model, arg); - device_add(&keyboard_ps2_ami_device); - - memregs_init(); - pci_init(PCI_CONFIG_TYPE_1); - pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); - pci_register_slot(0x08, PCI_CARD_ONBOARD, 4, 0, 0, 0); - pci_register_slot(0x0D, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x0E, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x0F, PCI_CARD_NORMAL, 3, 4, 2, 1); - pci_register_slot(0x10, PCI_CARD_NORMAL, 4, 3, 2, 1); - pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); - i430fx_init(); - piix_init(7); - pc87306_init(); - - device_add(&intel_flash_bxt_ami_device); -} diff --git a/src/machines/m_at_430hx.c b/src/machines/m_at_430hx.c deleted file mode 100644 index b145923..0000000 --- a/src/machines/m_at_430hx.c +++ /dev/null @@ -1,349 +0,0 @@ -/* - * VARCem Virtual ARchaeological Computer EMulator. - * An emulator of (mostly) x86-based PC systems and devices, - * using the ISA,EISA,VLB,MCA and PCI system buses, roughly - * spanning the era between 1981 and 1995. - * - * This file is part of the VARCem Project. - * - * Implementation of the Intel 430HX PCISet chip. - * - * Version: @(#)m_at_430hx.c 1.0.6 2018/05/06 - * - * Authors: Fred N. van Kempen, - * Miran Grca, - * Sarah Walker, - * - * Copyright 2017,2018 Fred N. van Kempen. - * Copyright 2016-2018 Miran Grca. - * Copyright 2008-2018 Sarah Walker. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the: - * - * Free Software Foundation, Inc. - * 59 Temple Place - Suite 330 - * Boston, MA 02111-1307 - * USA. - */ -#include -#include -#include -#include -#include "../emu.h" -#include "../io.h" -#include "../mem.h" -#include "../device.h" -#include "../devices/system/memregs.h" -#include "../devices/system/pci.h" -#include "../devices/system/intel_piix.h" -#include "../devices/system/intel_flash.h" -#include "../devices/sio/sio.h" -#include "../devices/input/keyboard.h" -#include "machine.h" - - -static uint8_t card_i430hx[256]; - - -static void i430hx_map(uint32_t addr, uint32_t size, int state) -{ - switch (state & 3) - { - case 0: - mem_set_mem_state(addr, size, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); - break; - case 1: - mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_EXTERNAL); - break; - case 2: - mem_set_mem_state(addr, size, MEM_READ_EXTERNAL | MEM_WRITE_INTERNAL); - break; - case 3: - mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - break; - } - flushmmucache_nopc(); -} - - -static void i430hx_write(int func, int addr, uint8_t val, void *priv) -{ - if (func) - return; - - if ((addr >= 0x10) && (addr < 0x4f)) - return; - - switch (addr) - { - case 0x00: case 0x01: case 0x02: case 0x03: - case 0x08: case 0x09: case 0x0a: case 0x0b: - case 0x0c: case 0x0e: - return; - - case 0x04: /*Command register*/ - val &= 0x02; - val |= 0x04; - break; - case 0x05: - val = 0; - break; - - case 0x06: /*Status*/ - val = 0; - break; - case 0x07: - val &= 0x80; - val |= 0x02; - break; - - case 0x59: /*PAM0*/ - if ((card_i430hx[0x59] ^ val) & 0xf0) - { - i430hx_map(0xf0000, 0x10000, val >> 4); - shadowbios = (val & 0x10); - } - break; - case 0x5a: /*PAM1*/ - if ((card_i430hx[0x5a] ^ val) & 0x0f) - i430hx_map(0xc0000, 0x04000, val & 0xf); - if ((card_i430hx[0x5a] ^ val) & 0xf0) - i430hx_map(0xc4000, 0x04000, val >> 4); - break; - case 0x5b: /*PAM2*/ - if ((card_i430hx[0x5b] ^ val) & 0x0f) - i430hx_map(0xc8000, 0x04000, val & 0xf); - if ((card_i430hx[0x5b] ^ val) & 0xf0) - i430hx_map(0xcc000, 0x04000, val >> 4); - break; - case 0x5c: /*PAM3*/ - if ((card_i430hx[0x5c] ^ val) & 0x0f) - i430hx_map(0xd0000, 0x04000, val & 0xf); - if ((card_i430hx[0x5c] ^ val) & 0xf0) - i430hx_map(0xd4000, 0x04000, val >> 4); - break; - case 0x5d: /*PAM4*/ - if ((card_i430hx[0x5d] ^ val) & 0x0f) - i430hx_map(0xd8000, 0x04000, val & 0xf); - if ((card_i430hx[0x5d] ^ val) & 0xf0) - i430hx_map(0xdc000, 0x04000, val >> 4); - break; - case 0x5e: /*PAM5*/ - if ((card_i430hx[0x5e] ^ val) & 0x0f) - i430hx_map(0xe0000, 0x04000, val & 0xf); - if ((card_i430hx[0x5e] ^ val) & 0xf0) - i430hx_map(0xe4000, 0x04000, val >> 4); - break; - case 0x5f: /*PAM6*/ - if ((card_i430hx[0x5f] ^ val) & 0x0f) - i430hx_map(0xe8000, 0x04000, val & 0xf); - if ((card_i430hx[0x5f] ^ val) & 0xf0) - i430hx_map(0xec000, 0x04000, val >> 4); - break; - case 0x72: /*SMRAM*/ - if ((card_i430hx[0x72] ^ val) & 0x48) - i430hx_map(0xa0000, 0x20000, ((val & 0x48) == 0x48) ? 3 : 0); - break; - } - - card_i430hx[addr] = val; -} - - -static uint8_t i430hx_read(int func, int addr, void *priv) -{ - if (func) - return 0xff; - - return card_i430hx[addr]; -} - - -static void i430hx_reset(void) -{ - memset(card_i430hx, 0, 256); - card_i430hx[0x00] = 0x86; card_i430hx[0x01] = 0x80; /*Intel*/ - card_i430hx[0x02] = 0x50; card_i430hx[0x03] = 0x12; /*82439HX*/ - card_i430hx[0x04] = 0x06; card_i430hx[0x05] = 0x00; - card_i430hx[0x06] = 0x00; card_i430hx[0x07] = 0x02; - card_i430hx[0x08] = 0x00; /*A0 stepping*/ - card_i430hx[0x09] = 0x00; card_i430hx[0x0a] = 0x00; card_i430hx[0x0b] = 0x06; - card_i430hx[0x51] = 0x20; - card_i430hx[0x52] = 0xB5; /*512kb cache*/ - - card_i430hx[0x59] = 0x40; - card_i430hx[0x5A] = card_i430hx[0x5B] = card_i430hx[0x5C] = card_i430hx[0x5D] = card_i430hx[0x5E] = card_i430hx[0x5F] = 0x44; - - card_i430hx[0x56] = 0x52; /*DRAM control*/ - card_i430hx[0x57] = 0x01; - card_i430hx[0x60] = card_i430hx[0x61] = card_i430hx[0x62] = card_i430hx[0x63] = card_i430hx[0x64] = card_i430hx[0x65] = card_i430hx[0x66] = card_i430hx[0x67] = 0x02; - card_i430hx[0x68] = 0x11; - card_i430hx[0x72] = 0x02; -} - - -static void i430hx_pci_reset(void) -{ - i430hx_write(0, 0x59, 0x00, NULL); - i430hx_write(0, 0x72, 0x02, NULL); -} - - -static void i430hx_init(void) -{ - pci_add_card(0, i430hx_read, i430hx_write, NULL); - - i430hx_reset(); - - pci_reset_handler.pci_master_reset = i430hx_pci_reset; -} - - -static int acerm3a_index; - - -static void -acerm3a_out(uint16_t port, uint8_t val, void *p) -{ - if (port == 0xea) - acerm3a_index = val; -} - -static uint8_t -acerm3a_in(uint16_t port, void *p) -{ - if (port == 0xeb) - { - switch (acerm3a_index) - { - case 2: - return 0xfd; - } - } - return 0xff; -} - - -void -machine_at_acerm3a_init(const machine_t *model, void *arg) -{ - machine_at_ps2_init(model, arg); - - powermate_memregs_init(); - pci_init(PCI_CONFIG_TYPE_1); - pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); - pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); - pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x0D, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x0E, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x1F, PCI_CARD_NORMAL, 4, 1, 2, 3); - pci_register_slot(0x10, PCI_CARD_ONBOARD, 4, 0, 0, 0); - i430hx_init(); - piix3_init(7); - fdc37c932fr_init(); - io_sethandler(0x00ea, 0x0002, acerm3a_in, NULL, NULL, acerm3a_out, NULL, NULL, NULL); - - device_add(&intel_flash_bxb_device); -} - - -void -machine_at_acerv35n_init(const machine_t *model, void *arg) -{ - machine_at_ps2_init(model, arg); - - powermate_memregs_init(); - pci_init(PCI_CONFIG_TYPE_1); - pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); - pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); - pci_register_slot(0x11, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x12, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x13, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x14, PCI_CARD_NORMAL, 4, 1, 2, 3); - pci_register_slot(0x0D, PCI_CARD_NORMAL, 1, 2, 3, 4); - i430hx_init(); - piix3_init(7); - fdc37c932fr_init(); - io_sethandler(0x00ea, 0x0002, acerm3a_in, NULL, NULL, acerm3a_out, NULL, NULL, NULL); - - device_add(&intel_flash_bxb_device); -} - - -void -machine_at_ap53_init(const machine_t *model, void *arg) -{ - machine_at_common_init(model, arg); - device_add(&keyboard_ps2_ami_device); - - memregs_init(); - powermate_memregs_init(); - pci_init(PCI_CONFIG_TYPE_1); - pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); - pci_register_slot(0x11, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x12, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x13, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x14, PCI_CARD_NORMAL, 4, 1, 2, 3); - pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); - pci_register_slot(0x06, PCI_CARD_ONBOARD, 1, 2, 3, 4); - i430hx_init(); - piix3_init(7); - fdc37c669_init(); - - device_add(&intel_flash_bxt_device); -} - - -void -machine_at_p55t2p4_init(const machine_t *model, void *arg) -{ - machine_at_ps2_init(model, arg); - - memregs_init(); - pci_init(PCI_CONFIG_TYPE_1); - pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); - pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x0B, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x0A, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x09, PCI_CARD_NORMAL, 4, 1, 2, 3); - pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); - i430hx_init(); - piix3_init(7); - w83877f_init(); - - device_add(&intel_flash_bxt_device); -} - - -void -machine_at_p55t2s_init(const machine_t *model, void *arg) -{ - machine_at_common_init(model, arg); - device_add(&keyboard_ps2_ami_device); - - memregs_init(); - powermate_memregs_init(); - pci_init(PCI_CONFIG_TYPE_1); - pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); - pci_register_slot(0x12, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x13, PCI_CARD_NORMAL, 4, 1, 2, 3); - pci_register_slot(0x14, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x11, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); - i430hx_init(); - piix3_init(7); - pc87306_init(); - - device_add(&intel_flash_bxt_device); -} diff --git a/src/machines/m_at_430lx_nx.c b/src/machines/m_at_430lx_nx.c deleted file mode 100644 index 576798c..0000000 --- a/src/machines/m_at_430lx_nx.c +++ /dev/null @@ -1,270 +0,0 @@ -/* - * VARCem Virtual ARchaeological Computer EMulator. - * An emulator of (mostly) x86-based PC systems and devices, - * using the ISA,EISA,VLB,MCA and PCI system buses, roughly - * spanning the era between 1981 and 1995. - * - * This file is part of the VARCem Project. - * - * Implementation of the Intel 430LX and 430NX PCISet chips. - * - * Version: @(#)m_at_430lx_nx.c 1.0.6 2018/05/06 - * - * Authors: Fred N. van Kempen, - * Miran Grca, - * Sarah Walker, - * - * Copyright 2017,2018 Fred N. van Kempen. - * Copyright 2016-2018 Miran Grca. - * Copyright 2008-2018 Sarah Walker. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the: - * - * Free Software Foundation, Inc. - * 59 Temple Place - Suite 330 - * Boston, MA 02111-1307 - * USA. - */ -#include -#include -#include -#include -#include "../emu.h" -#include "../mem.h" -#include "../rom.h" -#include "../device.h" -#include "../devices/system/pci.h" -#include "../devices/system/memregs.h" -#include "../devices/system/intel.h" -#include "../devices/system/intel_flash.h" -#include "../devices/system/intel_sio.h" -#include "../devices/input/keyboard.h" -#include "../devices/sio/sio.h" -#include "machine.h" - - -static uint8_t card_i430_lx_nx[256]; - - -static void i430lx_nx_map(uint32_t addr, uint32_t size, int state) -{ - switch (state & 3) - { - case 0: - mem_set_mem_state(addr, size, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); - break; - case 1: - mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_EXTERNAL); - break; - case 2: - mem_set_mem_state(addr, size, MEM_READ_EXTERNAL | MEM_WRITE_INTERNAL); - break; - case 3: - mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - break; - } - flushmmucache_nopc(); -} - - -static void i430lx_nx_write(int func, int addr, uint8_t val, void *priv) -{ - if (func) - return; - - if ((addr >= 0x10) && (addr < 0x4f)) - return; - - switch (addr) - { - case 0x00: case 0x01: case 0x02: case 0x03: - case 0x08: case 0x09: case 0x0a: case 0x0b: - case 0x0c: case 0x0e: - return; - - case 0x04: /*Command register*/ - val &= 0x42; - val |= 0x04; - break; - case 0x05: - val &= 0x01; - break; - - case 0x06: /*Status*/ - val = 0; - break; - case 0x07: - val = 0x02; - break; - - case 0x59: /*PAM0*/ - if ((card_i430_lx_nx[0x59] ^ val) & 0xf0) - { - i430lx_nx_map(0xf0000, 0x10000, val >> 4); - shadowbios = (val & 0x10); - } - pclog("i430lx_write : PAM0 write %02X\n", val); - break; - case 0x5a: /*PAM1*/ - if ((card_i430_lx_nx[0x5a] ^ val) & 0x0f) - i430lx_nx_map(0xc0000, 0x04000, val & 0xf); - if ((card_i430_lx_nx[0x5a] ^ val) & 0xf0) - i430lx_nx_map(0xc4000, 0x04000, val >> 4); - break; - case 0x5b: /*PAM2*/ - if (romset == ROM_REVENGE) - { - if ((card_i430_lx_nx[0x5b] ^ val) & 0x0f) - i430lx_nx_map(0xc8000, 0x04000, val & 0xf); - if ((card_i430_lx_nx[0x5b] ^ val) & 0xf0) - i430lx_nx_map(0xcc000, 0x04000, val >> 4); - } - break; - case 0x5c: /*PAM3*/ - if ((card_i430_lx_nx[0x5c] ^ val) & 0x0f) - i430lx_nx_map(0xd0000, 0x04000, val & 0xf); - if ((card_i430_lx_nx[0x5c] ^ val) & 0xf0) - i430lx_nx_map(0xd4000, 0x04000, val >> 4); - break; - case 0x5d: /*PAM4*/ - if ((card_i430_lx_nx[0x5d] ^ val) & 0x0f) - i430lx_nx_map(0xd8000, 0x04000, val & 0xf); - if ((card_i430_lx_nx[0x5d] ^ val) & 0xf0) - i430lx_nx_map(0xdc000, 0x04000, val >> 4); - break; - case 0x5e: /*PAM5*/ - if ((card_i430_lx_nx[0x5e] ^ val) & 0x0f) - i430lx_nx_map(0xe0000, 0x04000, val & 0xf); - if ((card_i430_lx_nx[0x5e] ^ val) & 0xf0) - i430lx_nx_map(0xe4000, 0x04000, val >> 4); - pclog("i430lx_write : PAM5 write %02X\n", val); - break; - case 0x5f: /*PAM6*/ - if ((card_i430_lx_nx[0x5f] ^ val) & 0x0f) - i430lx_nx_map(0xe8000, 0x04000, val & 0xf); - if ((card_i430_lx_nx[0x5f] ^ val) & 0xf0) - i430lx_nx_map(0xec000, 0x04000, val >> 4); - pclog("i430lx_write : PAM6 write %02X\n", val); - break; - } - - card_i430_lx_nx[addr] = val; -} - - -static uint8_t i430lx_nx_read(int func, int addr, void *priv) -{ - if (func) - return 0xff; - - return card_i430_lx_nx[addr]; -} - - -static void i430lx_nx_reset_common(void) -{ - memset(card_i430_lx_nx, 0, 256); - card_i430_lx_nx[0x00] = 0x86; card_i430_lx_nx[0x01] = 0x80; /*Intel*/ - card_i430_lx_nx[0x02] = 0xa3; card_i430_lx_nx[0x03] = 0x04; /*82434LX/NX*/ - card_i430_lx_nx[0x04] = 0x06; card_i430_lx_nx[0x05] = 0x00; - card_i430_lx_nx[0x06] = 0x00; card_i430_lx_nx[0x07] = 0x02; - card_i430_lx_nx[0x09] = 0x00; card_i430_lx_nx[0x0a] = 0x00; card_i430_lx_nx[0x0b] = 0x06; - card_i430_lx_nx[0x57] = 0x31; - card_i430_lx_nx[0x60] = card_i430_lx_nx[0x61] = card_i430_lx_nx[0x62] = card_i430_lx_nx[0x63] = card_i430_lx_nx[0x64] = 0x02; -} - - -static void i430lx_reset(void) -{ - i430lx_nx_reset_common(); - card_i430_lx_nx[0x08] = 0x03; /*A3 stepping*/ - card_i430_lx_nx[0x50] = 0x80; - card_i430_lx_nx[0x52] = 0x40; /*256kb PLB cache*/ -} - - -static void i430nx_reset(void) -{ - i430lx_nx_reset_common(); - card_i430_lx_nx[0x08] = 0x10; /*A0 stepping*/ - card_i430_lx_nx[0x50] = 0xA0; - card_i430_lx_nx[0x52] = 0x44; /*256kb PLB cache*/ - card_i430_lx_nx[0x66] = card_i430_lx_nx[0x67] = 0x02; -} - - -static void i430lx_nx_pci_reset(void) -{ - i430lx_nx_write(0, 0x59, 0x00, NULL); -} - - -static void i430lx_init(void) -{ - pci_add_card(0, i430lx_nx_read, i430lx_nx_write, NULL); - - i430lx_reset(); - - pci_reset_handler.pci_master_reset = i430lx_nx_pci_reset; -} - - -static void i430nx_init(void) -{ - pci_add_card(0, i430lx_nx_read, i430lx_nx_write, NULL); - - i430nx_reset(); - - pci_reset_handler.pci_master_reset = i430lx_nx_pci_reset; -} - - -static void -machine_at_premiere_common_init(const machine_t *model, void *arg) -{ - machine_at_common_init(model, arg); - device_add(&keyboard_ps2_ami_device); - - memregs_init(); - pci_init(PCI_CONFIG_TYPE_2); - pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); - pci_register_slot(0x01, PCI_CARD_SPECIAL, 0, 0, 0, 0); - pci_register_slot(0x06, PCI_CARD_NORMAL, 3, 2, 1, 4); - pci_register_slot(0x0E, PCI_CARD_NORMAL, 2, 1, 3, 4); - pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 3, 2, 4); - pci_register_slot(0x02, PCI_CARD_SPECIAL, 0, 0, 0, 0); - sio_init(2); - fdc37c665_init(); - intel_batman_init(); - - device_add(&intel_flash_bxt_ami_device); -} - - -void -machine_at_batman_init(const machine_t *model, void *arg) -{ - machine_at_premiere_common_init(model, arg); - - i430lx_init(); -} - - -void -machine_at_plato_init(const machine_t *model, void *arg) -{ - machine_at_premiere_common_init(model, arg); - - i430nx_init(); -} diff --git a/src/machines/m_at_430vx.c b/src/machines/m_at_430vx.c deleted file mode 100644 index 6f9d348..0000000 --- a/src/machines/m_at_430vx.c +++ /dev/null @@ -1,274 +0,0 @@ -/* - * VARCem Virtual ARchaeological Computer EMulator. - * An emulator of (mostly) x86-based PC systems and devices, - * using the ISA,EISA,VLB,MCA and PCI system buses, roughly - * spanning the era between 1981 and 1995. - * - * This file is part of the VARCem Project. - * - * Implementation of the Intel 430VX PCISet chip. - * - * Version: @(#)m_at_430vx.c 1.0.5 2018/05/06 - * - * Authors: Fred N. van Kempen, - * Miran Grca, - * Sarah Walker, - * - * Copyright 2017,2018 Fred N. van Kempen. - * Copyright 2016-2018 Miran Grca. - * Copyright 2008-2018 Sarah Walker. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the: - * - * Free Software Foundation, Inc. - * 59 Temple Place - Suite 330 - * Boston, MA 02111-1307 - * USA. - */ -#include -#include -#include -#include -#include "../emu.h" -#include "../io.h" -#include "../mem.h" -#include "../device.h" -#include "../devices/system/pci.h" -#include "../devices/system/memregs.h" -#include "../devices/system/intel_piix.h" -#include "../devices/system/intel_flash.h" -#include "../devices/sio/sio.h" -#include "machine.h" - - -static uint8_t card_i430vx[256]; - - -static void i430vx_map(uint32_t addr, uint32_t size, int state) -{ - switch (state & 3) - { - case 0: - mem_set_mem_state(addr, size, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); - break; - case 1: - mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_EXTERNAL); - break; - case 2: - mem_set_mem_state(addr, size, MEM_READ_EXTERNAL | MEM_WRITE_INTERNAL); - break; - case 3: - mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - break; - } - flushmmucache_nopc(); -} - - -static void i430vx_write(int func, int addr, uint8_t val, void *priv) -{ - if (func) - return; - - if ((addr >= 0x10) && (addr < 0x4f)) - return; - - switch (addr) - { - case 0x00: case 0x01: case 0x02: case 0x03: - case 0x08: case 0x09: case 0x0a: case 0x0b: - case 0x0c: case 0x0e: - return; - - case 0x04: /*Command register*/ - val &= 0x02; - val |= 0x04; - break; - case 0x05: - val = 0; - break; - - case 0x06: /*Status*/ - val = 0; - break; - case 0x07: - val &= 0x80; - val |= 0x02; - break; - - case 0x59: /*PAM0*/ - if ((card_i430vx[0x59] ^ val) & 0xf0) - { - i430vx_map(0xf0000, 0x10000, val >> 4); - shadowbios = (val & 0x10); - } - /* pclog("i430vx_write : PAM0 write %02X\n", val); */ - break; - case 0x5a: /*PAM1*/ - if ((card_i430vx[0x5a] ^ val) & 0x0f) - i430vx_map(0xc0000, 0x04000, val & 0xf); - if ((card_i430vx[0x5a] ^ val) & 0xf0) - i430vx_map(0xc4000, 0x04000, val >> 4); - break; - case 0x5b: /*PAM2*/ - if ((card_i430vx[0x5b] ^ val) & 0x0f) - i430vx_map(0xc8000, 0x04000, val & 0xf); - if ((card_i430vx[0x5b] ^ val) & 0xf0) - i430vx_map(0xcc000, 0x04000, val >> 4); - break; - case 0x5c: /*PAM3*/ - if ((card_i430vx[0x5c] ^ val) & 0x0f) - i430vx_map(0xd0000, 0x04000, val & 0xf); - if ((card_i430vx[0x5c] ^ val) & 0xf0) - i430vx_map(0xd4000, 0x04000, val >> 4); - break; - case 0x5d: /*PAM4*/ - if ((card_i430vx[0x5d] ^ val) & 0x0f) - i430vx_map(0xd8000, 0x04000, val & 0xf); - if ((card_i430vx[0x5d] ^ val) & 0xf0) - i430vx_map(0xdc000, 0x04000, val >> 4); - break; - case 0x5e: /*PAM5*/ - if ((card_i430vx[0x5e] ^ val) & 0x0f) - i430vx_map(0xe0000, 0x04000, val & 0xf); - if ((card_i430vx[0x5e] ^ val) & 0xf0) - i430vx_map(0xe4000, 0x04000, val >> 4); - /* pclog("i430vx_write : PAM5 write %02X\n", val); */ - break; - case 0x5f: /*PAM6*/ - if ((card_i430vx[0x5f] ^ val) & 0x0f) - i430vx_map(0xe8000, 0x04000, val & 0xf); - if ((card_i430vx[0x5f] ^ val) & 0xf0) - i430vx_map(0xec000, 0x04000, val >> 4); - /* pclog("i430vx_write : PAM6 write %02X\n", val); */ - break; - case 0x72: /*SMRAM*/ - if ((card_i430vx[0x72] ^ val) & 0x48) - i430vx_map(0xa0000, 0x20000, ((val & 0x48) == 0x48) ? 3 : 0); - break; - } - - card_i430vx[addr] = val; -} - - -static uint8_t i430vx_read(int func, int addr, void *priv) -{ - if (func) - return 0xff; - - return card_i430vx[addr]; -} - - -static void i430vx_reset(void) -{ - memset(card_i430vx, 0, 256); - card_i430vx[0x00] = 0x86; card_i430vx[0x01] = 0x80; /*Intel*/ - card_i430vx[0x02] = 0x30; card_i430vx[0x03] = 0x70; /*82437VX*/ - card_i430vx[0x04] = 0x06; card_i430vx[0x05] = 0x00; - card_i430vx[0x06] = 0x00; card_i430vx[0x07] = 0x02; - card_i430vx[0x08] = 0x00; /*A0 stepping*/ - card_i430vx[0x09] = 0x00; card_i430vx[0x0a] = 0x00; card_i430vx[0x0b] = 0x06; - card_i430vx[0x52] = 0x42; /*256kb PLB cache*/ - card_i430vx[0x53] = 0x14; - card_i430vx[0x56] = 0x52; /*DRAM control*/ - card_i430vx[0x57] = 0x01; - card_i430vx[0x60] = card_i430vx[0x61] = card_i430vx[0x62] = card_i430vx[0x63] = card_i430vx[0x64] = 0x02; - card_i430vx[0x67] = 0x11; - card_i430vx[0x69] = 0x03; - card_i430vx[0x70] = 0x20; - card_i430vx[0x72] = 0x02; - card_i430vx[0x74] = 0x0e; - card_i430vx[0x78] = 0x23; -} - - -static void i430vx_pci_reset(void) -{ - i430vx_write(0, 0x59, 0x00, NULL); - i430vx_write(0, 0x72, 0x02, NULL); -} - - -void i430vx_init(void) -{ - pci_add_card(0, i430vx_read, i430vx_write, NULL); - - i430vx_reset(); - - pci_reset_handler.pci_master_reset = i430vx_pci_reset; -} - - -void -machine_at_p55tvp4_init(const machine_t *model, void *arg) -{ - machine_at_ps2_init(model, arg); - - memregs_init(); - pci_init(PCI_CONFIG_TYPE_1); - pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); - pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x0B, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x0A, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x09, PCI_CARD_NORMAL, 4, 1, 2, 3); - pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); - i430vx_init(); - piix3_init(7); - w83877f_init(); - - device_add(&intel_flash_bxt_device); -} - - -void -machine_at_i430vx_init(const machine_t *model, void *arg) -{ - machine_at_ps2_init(model, arg); - - memregs_init(); - pci_init(PCI_CONFIG_TYPE_1); - pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); - pci_register_slot(0x11, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x12, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x13, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x14, PCI_CARD_NORMAL, 4, 1, 2, 3); - pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); - i430vx_init(); - piix3_init(7); - um8669f_init(); - - device_add(&intel_flash_bxt_device); -} - - -void -machine_at_p55va_init(const machine_t *model, void *arg) -{ - machine_at_ps2_init(model, arg); - - pci_init(PCI_CONFIG_TYPE_1); - pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); - pci_register_slot(0x08, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x09, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x0A, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x0B, PCI_CARD_NORMAL, 4, 1, 2, 3); - pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); - i430vx_init(); - piix3_init(7); - fdc37c932fr_init(); - - device_add(&intel_flash_bxt_device); -} diff --git a/src/machines/m_at_440fx.c b/src/machines/m_at_440fx.c deleted file mode 100644 index 0534f40..0000000 --- a/src/machines/m_at_440fx.c +++ /dev/null @@ -1,259 +0,0 @@ -/* - * VARCem Virtual ARchaeological Computer EMulator. - * An emulator of (mostly) x86-based PC systems and devices, - * using the ISA,EISA,VLB,MCA and PCI system buses, roughly - * spanning the era between 1981 and 1995. - * - * This file is part of the VARCem Project. - * - * Implementation of the Intel 440FX PCISet chip. - * - * Version: @(#)m_at_440fx.c 1.0.6 2018/05/06 - * - * Authors: Fred N. van Kempen, - * Miran Grca, - * Sarah Walker, - * - * Copyright 2017,2018 Fred N. van Kempen. - * Copyright 2016-2018 Miran Grca. - * Copyright 2008-2018 Sarah Walker. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the: - * - * Free Software Foundation, Inc. - * 59 Temple Place - Suite 330 - * Boston, MA 02111-1307 - * USA. - */ -#include -#include -#include -#include -#include "../emu.h" -#include "../io.h" -#include "../mem.h" -#include "../device.h" -#include "../devices/system/pci.h" -#include "../devices/system/memregs.h" -#include "../devices/system/intel_piix.h" -#include "../devices/system/intel_flash.h" -#include "../devices/sio/sio.h" -#include "../devices/input/keyboard.h" -#include "machine.h" - - -static uint8_t card_i440fx[256]; - - -static void i440fx_map(uint32_t addr, uint32_t size, int state) -{ - switch (state & 3) - { - case 0: - mem_set_mem_state(addr, size, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); - break; - case 1: - mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_EXTERNAL); - break; - case 2: - mem_set_mem_state(addr, size, MEM_READ_EXTERNAL | MEM_WRITE_INTERNAL); - break; - case 3: - mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - break; - } - flushmmucache_nopc(); -} - - -static void i440fx_write(int func, int addr, uint8_t val, void *priv) -{ - if (func) - return; - - if ((addr >= 0x10) && (addr < 0x4f)) - return; - - switch (addr) - { - case 0x00: case 0x01: case 0x02: case 0x03: - case 0x08: case 0x09: case 0x0a: case 0x0b: - case 0x0c: case 0x0e: - return; - - case 0x04: /*Command register*/ - val &= 0x02; - val |= 0x04; - break; - case 0x05: - val = 0; - break; - - case 0x06: /*Status*/ - val = 0; - break; - case 0x07: - val &= 0x80; - val |= 0x02; - break; - - case 0x59: /*PAM0*/ - if ((card_i440fx[0x59] ^ val) & 0xf0) - { - i440fx_map(0xf0000, 0x10000, val >> 4); - shadowbios = (val & 0x10); - } - break; - case 0x5a: /*PAM1*/ - if ((card_i440fx[0x5a] ^ val) & 0x0f) - i440fx_map(0xc0000, 0x04000, val & 0xf); - if ((card_i440fx[0x5a] ^ val) & 0xf0) - i440fx_map(0xc4000, 0x04000, val >> 4); - break; - case 0x5b: /*PAM2*/ - if ((card_i440fx[0x5b] ^ val) & 0x0f) - i440fx_map(0xc8000, 0x04000, val & 0xf); - if ((card_i440fx[0x5b] ^ val) & 0xf0) - i440fx_map(0xcc000, 0x04000, val >> 4); - break; - case 0x5c: /*PAM3*/ - if ((card_i440fx[0x5c] ^ val) & 0x0f) - i440fx_map(0xd0000, 0x04000, val & 0xf); - if ((card_i440fx[0x5c] ^ val) & 0xf0) - i440fx_map(0xd4000, 0x04000, val >> 4); - break; - case 0x5d: /*PAM4*/ - if ((card_i440fx[0x5d] ^ val) & 0x0f) - i440fx_map(0xd8000, 0x04000, val & 0xf); - if ((card_i440fx[0x5d] ^ val) & 0xf0) - i440fx_map(0xdc000, 0x04000, val >> 4); - break; - case 0x5e: /*PAM5*/ - if ((card_i440fx[0x5e] ^ val) & 0x0f) - i440fx_map(0xe0000, 0x04000, val & 0xf); - if ((card_i440fx[0x5e] ^ val) & 0xf0) - i440fx_map(0xe4000, 0x04000, val >> 4); - break; - case 0x5f: /*PAM6*/ - if ((card_i440fx[0x5f] ^ val) & 0x0f) - i440fx_map(0xe8000, 0x04000, val & 0xf); - if ((card_i440fx[0x5f] ^ val) & 0xf0) - i440fx_map(0xec000, 0x04000, val >> 4); - break; - case 0x72: /*SMRAM*/ - if ((card_i440fx[0x72] ^ val) & 0x48) - i440fx_map(0xa0000, 0x20000, ((val & 0x48) == 0x48) ? 3 : 0); - break; - } - - card_i440fx[addr] = val; -} - - -static uint8_t i440fx_read(int func, int addr, void *priv) -{ - if (func) - return 0xff; - - return card_i440fx[addr]; -} - - -static void i440fx_reset(void) -{ - memset(card_i440fx, 0, 256); - card_i440fx[0x00] = 0x86; card_i440fx[0x01] = 0x80; /*Intel*/ - card_i440fx[0x02] = 0x37; card_i440fx[0x03] = 0x12; /*82441FX*/ - card_i440fx[0x04] = 0x03; card_i440fx[0x05] = 0x01; - card_i440fx[0x06] = 0x80; card_i440fx[0x07] = 0x00; - card_i440fx[0x08] = 0x02; /*A0 stepping*/ - card_i440fx[0x09] = 0x00; card_i440fx[0x0a] = 0x00; card_i440fx[0x0b] = 0x06; - card_i440fx[0x0d] = 0x00; - card_i440fx[0x0f] = 0x00; - card_i440fx[0x2c] = 0xf4; - card_i440fx[0x2d] = 0x1a; - card_i440fx[0x2e] = 0x00; - card_i440fx[0x2f] = 0x11; - card_i440fx[0x50] = 0x00; - card_i440fx[0x51] = 0x01; - card_i440fx[0x52] = card_i440fx[0x54] = card_i440fx[0x55] = card_i440fx[0x56] = 0x00; - card_i440fx[0x53] = 0x80; - card_i440fx[0x57] = 0x01; - card_i440fx[0x58] = 0x10; - card_i440fx[0x5a] = card_i440fx[0x5b] = card_i440fx[0x5c] = card_i440fx[0x5d] = card_i440fx[0x5e] = 0x11; - card_i440fx[0x5f] = 0x31; - card_i440fx[0x72] = 0x02; -} - - -static void i440fx_pci_reset(void) -{ - i440fx_write(0, 0x59, 0x00, NULL); - i440fx_write(0, 0x72, 0x02, NULL); -} - - -static void i440fx_init(void) -{ - pci_add_card(0, i440fx_read, i440fx_write, NULL); - - i440fx_reset(); - - pci_reset_handler.pci_master_reset = i440fx_pci_reset; -} - - -void -machine_at_i440fx_init(const machine_t *model, void *arg) -{ - machine_at_ps2_init(model, arg); - - memregs_init(); - pci_init(PCI_CONFIG_TYPE_1); - pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); - pci_register_slot(0x0E, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x0D, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x0C, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x0B, PCI_CARD_NORMAL, 4, 1, 2, 3); - pci_register_slot(0x0A, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); - i440fx_init(); - piix3_init(7); - fdc37c665_init(); - - device_add(&intel_flash_bxt_device); -} - - -void -machine_at_s1668_init(const machine_t *model, void *arg) -{ - machine_at_common_init(model, arg); - device_add(&keyboard_ps2_ami_device); - - memregs_init(); - pci_init(PCI_CONFIG_TYPE_1); - pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); - pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); - pci_register_slot(0x0E, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x0D, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x0C, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x0B, PCI_CARD_NORMAL, 4, 1, 2, 3); - pci_register_slot(0x0A, PCI_CARD_NORMAL, 1, 2, 3, 4); - i440fx_init(); - piix3_init(7); - fdc37c665_init(); - - device_add(&intel_flash_bxt_device); -} diff --git a/src/machines/m_at_4x0.c b/src/machines/m_at_4x0.c new file mode 100644 index 0000000..24ce6a3 --- /dev/null +++ b/src/machines/m_at_4x0.c @@ -0,0 +1,1063 @@ +/* + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. + * + * This file is part of the VARCem Project. + * + * Implementation of the Intel 430xx 440xx PCISet chips. + * + * Version: @(#)m_at_4x0.c 1.0.2 2018/09/22 + * + * Authors: Fred N. van Kempen, + * Miran Grca, + * Sarah Walker, + * + * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2016-2018 Miran Grca. + * Copyright 2008-2018 Sarah Walker. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the: + * + * Free Software Foundation, Inc. + * 59 Temple Place - Suite 330 + * Boston, MA 02111-1307 + * USA. + */ +#include +#include +#include +#include +#include +#include "../emu.h" +#include "../io.h" +#include "../mem.h" +#include "../rom.h" +#include "../device.h" +#include "../devices/system/pci.h" +#include "../devices/system/memregs.h" +#include "../devices/system/intel.h" +#include "../devices/system/intel_flash.h" +#include "../devices/system/intel_sio.h" +#include "../devices/system/intel_piix.h" +#include "../devices/input/keyboard.h" +#include "../devices/sio/sio.h" +#include "../devices/disk/hdc.h" +#include "../devices/disk/hdc_ide.h" +#include "../devices/video/video.h" +#include "machine.h" + + +enum { + INTEL_430LX, + INTEL_430NX, + INTEL_430FX, + INTEL_430FX_PB640, + INTEL_430HX, + INTEL_430VX, +#if defined(DEV_BRANCH) && defined(USE_I686) + INTEL_440FX +#endif +}; + +typedef struct { + uint8_t regs[256]; + int type; +} i4x0_t; + +typedef struct { + int index; +} acerm3a_t; + + +static void +i4x0_map(uint32_t addr, uint32_t size, int state) +{ + switch (state & 3) { + case 0: + mem_set_mem_state(addr, size, + MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); + break; + + case 1: + mem_set_mem_state(addr, size, + MEM_READ_INTERNAL | MEM_WRITE_EXTERNAL); + break; + + case 2: + mem_set_mem_state(addr, size, + MEM_READ_EXTERNAL | MEM_WRITE_INTERNAL); + break; + + case 3: + mem_set_mem_state(addr, size, + MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + break; + } + + flushmmucache_nopc(); +} + + +static void +i4x0_write(int func, int addr, uint8_t val, void *priv) +{ + i4x0_t *dev = (i4x0_t *)priv; + + if (func) + return; + + if ((addr >= 0x10) && (addr < 0x4f)) + return; + + switch (addr) { + case 0x00: case 0x01: case 0x02: case 0x03: + case 0x08: case 0x09: case 0x0a: case 0x0b: + case 0x0c: case 0x0e: + return; + + case 0x04: /*Command register*/ + if (dev->type >= INTEL_430FX) { + if (dev->type == INTEL_430FX_PB640) + val &= 0x06; + else + val &= 0x02; + } else + val &= 0x42; + val |= 0x04; + break; + + case 0x05: + if (dev->type >= INTEL_430FX) + val = 0; + else + val &= 0x01; + break; + + case 0x06: /*Status*/ + val = 0; + break; + + case 0x07: + if (dev->type >= INTEL_430HX) { + val &= 0x80; + val |= 0x02; + } else { + val = 0x02; + if (dev->type == INTEL_430FX_PB640) + val |= 0x20; + } + break; + + case 0x59: /*PAM0*/ + if ((dev->regs[0x59] ^ val) & 0xf0) { + i4x0_map(0xf0000, 0x10000, val >> 4); + shadowbios = (val & 0x10); + } + break; + + case 0x5a: /*PAM1*/ + if ((dev->regs[0x5a] ^ val) & 0x0f) + i4x0_map(0xc0000, 0x04000, val & 0xf); + if ((dev->regs[0x5a] ^ val) & 0xf0) + i4x0_map(0xc4000, 0x04000, val >> 4); + break; + + case 0x5b: /*PAM2*/ + if ((dev->regs[0x5b] ^ val) & 0x0f) + i4x0_map(0xc8000, 0x04000, val & 0xf); + if ((dev->regs[0x5b] ^ val) & 0xf0) + i4x0_map(0xcc000, 0x04000, val >> 4); + break; + + case 0x5c: /*PAM3*/ + if ((dev->regs[0x5c] ^ val) & 0x0f) + i4x0_map(0xd0000, 0x04000, val & 0xf); + if ((dev->regs[0x5c] ^ val) & 0xf0) + i4x0_map(0xd4000, 0x04000, val >> 4); + break; + + case 0x5d: /*PAM4*/ + if ((dev->regs[0x5d] ^ val) & 0x0f) + i4x0_map(0xd8000, 0x04000, val & 0xf); + if ((dev->regs[0x5d] ^ val) & 0xf0) + i4x0_map(0xdc000, 0x04000, val >> 4); + break; + + case 0x5e: /*PAM5*/ + if ((dev->regs[0x5e] ^ val) & 0x0f) + i4x0_map(0xe0000, 0x04000, val & 0xf); + if ((dev->regs[0x5e] ^ val) & 0xf0) + i4x0_map(0xe4000, 0x04000, val >> 4); + break; + + case 0x5f: /*PAM6*/ + if ((dev->regs[0x5f] ^ val) & 0x0f) + i4x0_map(0xe8000, 0x04000, val & 0xf); + if ((dev->regs[0x5f] ^ val) & 0xf0) + i4x0_map(0xec000, 0x04000, val >> 4); + break; + + case 0x72: /*SMRAM*/ + if ((dev->type >= INTEL_430FX) && + ((dev->regs[0x72] ^ val) & 0x48)) + i4x0_map(0xa0000, 0x20000, ((val & 0x48) == 0x48) ? 3 : 0); + break; + } + + dev->regs[addr] = val; +} + + +static uint8_t +i4x0_read(int func, int addr, void *priv) +{ + i4x0_t *dev = (i4x0_t *)priv; + + if (func) + return 0xff; + + return dev->regs[addr]; +} + + +static void +i4x0_reset(void *priv) +{ + i4x0_t *dev = (i4x0_t *)priv; + + i4x0_write(0, 0x59, 0x00, priv); + if (dev->type >= INTEL_430FX) + i4x0_write(0, 0x72, 0x02, priv); +} + + +static void +i4x0_close(void *priv) +{ + i4x0_t *dev = (i4x0_t *)priv; + + free(dev); +} + + +static void * +i4x0_init(const device_t *info) +{ + i4x0_t *dev = (i4x0_t *) mem_alloc(sizeof(i4x0_t)); + memset(dev, 0x00, sizeof(i4x0_t)); + dev->type = info->local; + + dev->regs[0x00] = 0x86; dev->regs[0x01] = 0x80; /*Intel*/ + + switch(dev->type) { + case INTEL_430LX: + dev->regs[0x02] = 0xa3; dev->regs[0x03] = 0x04; /*82434LX/NX*/ + dev->regs[0x08] = 0x03; /*A3 stepping*/ + dev->regs[0x50] = 0x80; + dev->regs[0x52] = 0x40; /*256kb PLB cache*/ + break; + + case INTEL_430NX: + dev->regs[0x02] = 0xa3; dev->regs[0x03] = 0x04; /*82434LX/NX*/ + dev->regs[0x08] = 0x10; /*A0 stepping*/ + dev->regs[0x50] = 0xA0; + dev->regs[0x52] = 0x44; /*256kb PLB cache*/ + dev->regs[0x66] = dev->regs[0x67] = 0x02; + break; + + case INTEL_430FX: + case INTEL_430FX_PB640: + dev->regs[0x02] = 0x2d; dev->regs[0x03] = 0x12; /*SB82437FX-66*/ + if (dev->type == INTEL_430FX_PB640) + dev->regs[0x08] = 0x02; /*???? stepping*/ + else + dev->regs[0x08] = 0x00; /*A0 stepping*/ + dev->regs[0x52] = 0x40; /*256kb PLB cache*/ + break; + + case INTEL_430HX: + dev->regs[0x02] = 0x50; dev->regs[0x03] = 0x12; /*82439HX*/ + dev->regs[0x08] = 0x00; /*A0 stepping*/ + dev->regs[0x51] = 0x20; + dev->regs[0x52] = 0xB5; /*512kb cache*/ + dev->regs[0x56] = 0x52; /*DRAM control*/ + dev->regs[0x59] = 0x40; + dev->regs[0x5A] = dev->regs[0x5B] = \ + dev->regs[0x5C] = dev->regs[0x5D] = 0x44; + dev->regs[0x5E] = dev->regs[0x5F] = 0x44; + dev->regs[0x65] = dev->regs[0x66] = dev->regs[0x67] = 0x02; + dev->regs[0x68] = 0x11; + break; + + case INTEL_430VX: + dev->regs[0x02] = 0x30; dev->regs[0x03] = 0x70; /*82437VX*/ + dev->regs[0x08] = 0x00; /*A0 stepping*/ + dev->regs[0x52] = 0x42; /*256kb PLB cache*/ + dev->regs[0x53] = 0x14; + dev->regs[0x56] = 0x52; /*DRAM control*/ + dev->regs[0x67] = 0x11; + dev->regs[0x69] = 0x03; + dev->regs[0x70] = 0x20; + dev->regs[0x74] = 0x0e; + dev->regs[0x78] = 0x23; + break; + +#if defined(DEV_BRANCH) && defined(USE_I686) + case INTEL_440FX: + dev->regs[0x02] = 0x37; dev->regs[0x03] = 0x12; /*82441FX*/ + dev->regs[0x08] = 0x02; /*A0 stepping*/ + dev->regs[0x2c] = 0xf4; + dev->regs[0x2d] = 0x1a; + dev->regs[0x2f] = 0x11; + dev->regs[0x51] = 0x01; + dev->regs[0x53] = 0x80; + dev->regs[0x58] = 0x10; + dev->regs[0x5a] = dev->regs[0x5b] = \ + dev->regs[0x5c] = dev->regs[0x5d] = 0x11; + dev->regs[0x5e] = 0x11; + dev->regs[0x5f] = 0x31; + break; +#endif + } + + dev->regs[0x04] = 0x06; dev->regs[0x05] = 0x00; +#if defined(DEV_BRANCH) && defined(USE_I686) + if (dev->type == INTEL_440FX) + dev->regs[0x06] = 0x80; +#endif + + if (dev->type == INTEL_430FX) + dev->regs[0x07] = 0x82; +#if defined(DEV_BRANCH) && defined(USE_I686) + else if (dev->type != INTEL_440FX) +#else + else +#endif + dev->regs[0x07] = 0x02; + dev->regs[0x0b] = 0x06; + if (dev->type >= INTEL_430FX) + dev->regs[0x57] = 0x01; + else + dev->regs[0x57] = 0x31; + dev->regs[0x60] = dev->regs[0x61] = dev->regs[0x62] = \ + dev->regs[0x63] = 0x02; + dev->regs[0x64] = 0x02; + if (dev->type >= INTEL_430FX) + dev->regs[0x72] = 0x02; + + pci_add_card(0, i4x0_read, i4x0_write, dev); + + return dev; +} + + +static const device_t i430lx_device = { + "Intel 82434LX", + DEVICE_PCI, + INTEL_430LX, + i4x0_init, i4x0_close, i4x0_reset, + NULL, NULL, NULL, NULL, + NULL +}; + +static const device_t i430nx_device = { + "Intel 82434NX", + DEVICE_PCI, + INTEL_430NX, + i4x0_init, i4x0_close, i4x0_reset, + NULL, NULL, NULL, NULL, + NULL +}; + +static const device_t i430fx_device = { + "Intel SB82437FX-66", + DEVICE_PCI, + INTEL_430FX, + i4x0_init, i4x0_close, i4x0_reset, + NULL, NULL, NULL, NULL, + NULL +}; + +const device_t i430fx_pb640_device = { + "Intel SB82437FX-66 (PB640)", + DEVICE_PCI, + INTEL_430FX_PB640, + i4x0_init, i4x0_close, i4x0_reset, + NULL, NULL, NULL, NULL, + NULL +}; + +static const device_t i430hx_device = { + "Intel 82439HX", + DEVICE_PCI, + INTEL_430HX, + i4x0_init, i4x0_close, i4x0_reset, + NULL, NULL, NULL, NULL, + NULL +}; + +static const device_t i430vx_device = { + "Intel 82437VX", + DEVICE_PCI, + INTEL_430VX, + i4x0_init, i4x0_close, i4x0_reset, + NULL, NULL, NULL, NULL, + NULL +}; + +#if defined(DEV_BRANCH) && defined(USE_I686) +static const device_t i440fx_device = { + "Intel 82441FX", + DEVICE_PCI, + INTEL_440FX, + i4x0_init, i4x0_close, i4x0_reset, + NULL, NULL, NULL, NULL, + NULL +}; +#endif + + +static void +machine_at_premiere_common_init(const machine_t *model, void *arg) +{ + machine_at_common_init(model, arg); + + device_add(&keyboard_ps2_ami_pci_device); + + device_add(&ide_pci_2ch_device); + + memregs_init(); + + pci_init(PCI_CONFIG_TYPE_2); + pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x01, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x06, PCI_CARD_NORMAL, 3, 2, 1, 4); + pci_register_slot(0x0E, PCI_CARD_NORMAL, 2, 1, 3, 4); + pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 3, 2, 4); + pci_register_slot(0x02, PCI_CARD_SPECIAL, 0, 0, 0, 0); + + device_add(&sio_device); + + fdc37c665_init(); + + intel_batman_init(); + + device_add(&intel_flash_bxt_ami_device); +} + + +/* Revenge: Intel Premiere/PCI I/430LX/AMI/SMC FDC37C665 */ +void +machine_at_batman_init(const machine_t *model, void *arg) +{ + machine_at_premiere_common_init(model, arg); + + device_add(&i430lx_device); +} + + +/* Plato: Intel Premiere/PCI II/430NX/AMI/SMC FDC37C665 */ +void +machine_at_plato_init(const machine_t *model, void *arg) +{ + machine_at_premiere_common_init(model, arg); + + device_add(&i430nx_device); +} + + +/* P54TP4XE: ASUS P/I-P55TP4XE/430FX/Award/SMC FDC37C665 */ +void +machine_at_p54tp4xe_init(const machine_t *model, void *arg) +{ + machine_at_common_init(model, arg); + + device_add(&keyboard_ps2_pci_device); + + memregs_init(); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0B, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0A, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x09, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); + + device_add(&i430fx_device); + + device_add(&piix_device); + + fdc37c665_init(); + + device_add(&intel_flash_bxt_device); +} + + +/* Endeavor: Intel Advanced_EV/430FX/AMI/NS PC87306 */ +void +machine_at_endeavor_init(const machine_t *model, void *arg) +{ + static video_timings_t endeavor_timing = {VID_BUS,3,2,4,25,25,40}; + + machine_at_common_init(model, arg); + + device_add(&keyboard_ps2_ami_pci_device); + + memregs_init(); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x08, PCI_CARD_ONBOARD, 4, 0, 0, 0); + pci_register_slot(0x0D, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0E, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0F, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x10, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); + + device_add(&i430fx_device); + + device_add(&piix_device); + + pc87306_init(); + + device_add(&intel_flash_bxt_ami_device); + + if (video_card == VID_INTERNAL) { + device_add(&s3_phoenix_trio64_onboard_pci_device); + video_inform(VID_TYPE_SPEC, &endeavor_timing); + } +} + + +/* Zappa: Intel Advanced_ZP/430FX/AMI/NS PC87306 */ +void +machine_at_zappa_init(const machine_t *model, void *arg) +{ + machine_at_common_init(model, arg); + + device_add(&keyboard_ps2_ami_pci_device); + + memregs_init(); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x0D, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0E, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x0F, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); + + device_add(&i430fx_device); + + device_add(&piix_device); + + pc87306_init(); + + device_add(&intel_flash_bxt_ami_device); +} + + +/* MB500N: PC Partner MB500N/430FX/Award/SMC FDC37C665 */ +void +machine_at_mb500n_init(const machine_t *model, void *arg) +{ + machine_at_common_init(model, arg); + + device_add(&keyboard_ps2_pci_device); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x14, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x13, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x12, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x11, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); + + device_add(&i430fx_device); + + device_add(&piix_device); + + fdc37c665_init(); + + device_add(&intel_flash_bxt_device); +} + + +/* President: President Award 430FX PCI/430FX/Award/Unknown SIO */ +void +machine_at_president_init(const machine_t *model, void *arg) +{ + machine_at_common_init(model, arg); + + device_add(&keyboard_ps2_pci_device); + + memregs_init(); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x08, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x09, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0A, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x0B, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); + + device_add(&i430fx_device); + + device_add(&piix_device); + + w83877f_init(1); + + device_add(&intel_flash_bxt_device); +} + + +/* Thor: Intel Advanced_ATX/430FX/AMI/NS PC87306 */ +/* MRthor: Intel Advanced_ATX/430FX/MR.BIOS/NS PC87306 */ +void +machine_at_thor_init(const machine_t *model, void *arg) +{ + machine_at_common_init(model, arg); + + device_add(&keyboard_ps2_ami_pci_device); + + memregs_init(); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x08, PCI_CARD_ONBOARD, 4, 0, 0, 0); + pci_register_slot(0x0D, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0E, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0F, PCI_CARD_NORMAL, 3, 4, 2, 1); + pci_register_slot(0x10, PCI_CARD_NORMAL, 4, 3, 2, 1); + pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); + + device_add(&i430fx_device); + + device_add(&piix_device); + + pc87306_init(); + + device_add(&intel_flash_bxt_ami_device); +} + + +/* PB640: Packard Bell PB640/430FX/AMI/NS PC87306 */ +void +machine_at_pb640_init(const machine_t *model, void *arg) +{ + machine_at_common_init(model, arg); + + device_add(&keyboard_ps2_ami_pci_device); + + memregs_init(); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x08, PCI_CARD_ONBOARD, 4, 0, 0, 0); + pci_register_slot(0x11, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x13, PCI_CARD_NORMAL, 2, 1, 3, 4); + pci_register_slot(0x0B, PCI_CARD_NORMAL, 3, 2, 1, 4); + pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); + + device_add(&i430fx_pb640_device); + + device_add(&piix_pb640_device); + ide_enable_pio_override(); + + pc87306_init(); + + device_add(&intel_flash_bxt_ami_device); + + if (video_card == VID_INTERNAL) { + device_add(&gd5440_onboard_pci_device); + } +} + + +/* AP53: AOpen AP53/430HX/AMI/SMC FDC37C665/669 */ +void +machine_at_ap53_init(const machine_t *model, void *arg) +{ + machine_at_common_init(model, arg); + + device_add(&keyboard_ps2_ami_pci_device); + + memregs_init(); + + powermate_memregs_init(); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x11, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x12, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x13, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x14, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x06, PCI_CARD_ONBOARD, 1, 2, 3, 4); + + device_add(&i430hx_device); + + device_add(&piix3_device); + + fdc37c669_init(); + + device_add(&intel_flash_bxt_device); +} + + +/* P55T2P4: ASUS P/I-P55T2P4/430HX/Award/Winbond W8387F*/ +void +machine_at_p55t2p4_init(const machine_t *model, void *arg) +{ + machine_at_common_init(model, arg); + + device_add(&keyboard_ps2_pci_device); + + memregs_init(); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0B, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0A, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x09, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); + + device_add(&i430hx_device); + + device_add(&piix3_device); + + w83877f_init(0); + + device_add(&intel_flash_bxt_device); +} + + +/* P55T2S: ASUS P/I-P55T2S/430HX/AMI/NS PC87306 */ +void +machine_at_p55t2s_init(const machine_t *model, void *arg) +{ + machine_at_common_init(model, arg); + + device_add(&keyboard_ps2_ami_pci_device); + + memregs_init(); + + powermate_memregs_init(); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x12, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x13, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x14, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x11, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); + + device_add(&i430hx_device); + + device_add(&piix3_device); + + pc87306_init(); + + device_add(&intel_flash_bxt_device); +} + + +/* P55TVP4: ASUS P/I-P55TVP4/430VX/Award/Winbond W8387F*/ +void +machine_at_p55tvp4_init(const machine_t *model, void *arg) +{ + machine_at_common_init(model, arg); + + device_add(&keyboard_ps2_pci_device); + + memregs_init(); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0B, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0A, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x09, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); + + device_add(&i430vx_device); + + device_add(&piix3_device); + + w83877f_init(0); + + device_add(&intel_flash_bxt_device); +} + + +/* 430VX: Award 430VX PCI/430VX/Award/UMC UM8669F*/ +void +machine_at_i430vx_init(const machine_t *model, void *arg) +{ + machine_at_common_init(model, arg); + + device_add(&keyboard_ps2_pci_device); + + memregs_init(); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x11, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x12, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x14, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x13, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); + + device_add(&i430vx_device); + + device_add(&piix3_device); + + um8669f_init(); + + device_add(&intel_flash_bxt_device); +} + + +/* P55VA: Epox P55-VA/430VX/Award/SMC FDC37C932FR*/ +void +machine_at_p55va_init(const machine_t *model, void *arg) +{ + machine_at_common_init(model, arg); + + device_add(&keyboard_ps2_pci_device); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x08, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x09, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0A, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x0B, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); + + device_add(&i430vx_device); + + device_add(&piix3_device); + + fdc37c932fr_init(); + + device_add(&intel_flash_bxt_device); +} + + +/* J656VXD: Jetway J656VXD/430VX/Award/SMC FDC37C669*/ +void +machine_at_j656vxd_init(const machine_t *model, void *arg) +{ + machine_at_common_init(model, arg); + + device_add(&keyboard_ps2_pci_device); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x11, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x12, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x13, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); + + device_add(&i430vx_device); + + device_add(&piix3_device); + + fdc37c669_init(); + + device_add(&intel_flash_bxt_device); +} + + +#if defined(DEV_BRANCH) && defined(USE_I686) +/* 440FX: Tyan Titan-Pro AT/440FX/Award BIOS/SMC FDC37C665 */ +void +machine_at_i440fx_init(const machine_t *model, void *arg) +{ + machine_at_common_init(model, arg); + + device_add(&keyboard_ps2_pci_device); + + memregs_init(); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x0E, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0D, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0C, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x0B, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x0A, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); + + device_add(&i440fx_device); + + device_add(&piix3_device); + + fdc37c665_init(); + + device_add(&intel_flash_bxt_device); +} + + +/* S1668: Tyan Titan-Pro ATX/440FX/AMI/SMC FDC37C669 */ +void +machine_at_s1668_init(const machine_t *model, void *arg) +{ + machine_at_common_init(model, arg); + + device_add(&keyboard_ps2_ami_pci_device); + + memregs_init(); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x0E, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0D, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0C, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x0B, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x0A, PCI_CARD_NORMAL, 1, 2, 3, 4); + + device_add(&i440fx_device); + + device_add(&piix3_device); + + fdc37c665_init(); + + device_add(&intel_flash_bxt_device); +} +#endif + + +static void +acerm3a_out(uint16_t port, uint8_t val, void *priv) +{ + acerm3a_t *dev = (acerm3a_t *)priv; + + if (port == 0xea) + dev->index = val; +} + + +static uint8_t +acerm3a_in(uint16_t port, void *priv) +{ + acerm3a_t *dev = (acerm3a_t *)priv; + + if (port == 0xeb) { + switch (dev->index) { + case 2: + return 0xfd; + } + } + + return(0xff); +} + + +static void +acerm3a_close(void *priv) +{ + acerm3a_t *dev = (acerm3a_t *)priv; + + free(dev); +} + + +static void * +acerm3a_init(const device_t *info) +{ + acerm3a_t *dev = (acerm3a_t *)mem_alloc(sizeof(acerm3a_t)); + memset(dev, 0x00, sizeof(acerm3a_t)); + + io_sethandler(0x00ea, 2, + acerm3a_in,NULL,NULL, acerm3a_out,NULL,NULL, dev); + + return(dev); +} + + +static const device_t acerm3a_device = { + "Acer M3A Register", + 0, + 0, + acerm3a_init, acerm3a_close, NULL, + NULL, NULL, NULL, NULL, + NULL +}; + + +/* ACERM3A: Acer M3A/430HX/Acer/SMC FDC37C932FR */ +void +machine_at_acerm3a_init(const machine_t *model, void *arg) +{ + machine_at_common_init(model, arg); + + device_add(&keyboard_ps2_pci_device); + + powermate_memregs_init(); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0D, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0E, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x1F, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x10, PCI_CARD_ONBOARD, 4, 0, 0, 0); + + device_add(&i430hx_device); + + device_add(&piix3_device); + + fdc37c932fr_init(); + + device_add(&acerm3a_device); + + device_add(&intel_flash_bxb_device); +} + + +/* ACERV35N: Acer V35N/430HX/Acer/SMC FDC37C932FR */ +void +machine_at_acerv35n_init(const machine_t *model, void *arg) +{ + machine_at_common_init(model, arg); + + device_add(&keyboard_ps2_pci_device); + + powermate_memregs_init(); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x11, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x12, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x13, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x14, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x0D, PCI_CARD_NORMAL, 1, 2, 3, 4); + + device_add(&i430hx_device); + + device_add(&piix3_device); + + fdc37c932fr_init(); + + device_add(&acerm3a_device); + + device_add(&intel_flash_bxb_device); +} diff --git a/src/machines/m_at_compaq.c b/src/machines/m_at_compaq.c index bdee6dc..602f74c 100644 --- a/src/machines/m_at_compaq.c +++ b/src/machines/m_at_compaq.c @@ -8,7 +8,7 @@ * * Emulation of various Compaq PC's. * - * Version: @(#)m_at_compaq.c 1.0.7 2018/08/20 + * Version: @(#)m_at_compaq.c 1.0.8 2018/09/15 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -54,7 +54,7 @@ /* Compaq Deskpro 386 remaps RAM from 0xA0000-0xFFFFF to 0xFA0000-0xFFFFFF */ -static mem_mapping_t ram_mapping; +static mem_map_t ram_mapping; static uint8_t @@ -117,8 +117,8 @@ write_raml(uint32_t addr, uint32_t val, void *priv) } -void -machine_at_compaq_init(const machine_t *model, void *arg) +static void +compaq_common_init(const machine_t *model, void *arg, int type) { machine_at_init(model, arg); @@ -126,34 +126,63 @@ machine_at_compaq_init(const machine_t *model, void *arg) device_add(&fdc_at_device); - mem_mapping_add(&ram_mapping, 0xfa0000, 0x60000, - read_ram, read_ramw, read_raml, - write_ram, write_ramw, write_raml, - 0xa0000+ram, MEM_MAPPING_INTERNAL, NULL); + mem_map_add(&ram_mapping, 0xfa0000, 0x60000, + read_ram, read_ramw, read_raml, + write_ram, write_ramw, write_raml, + 0xa0000+ram, MEM_MAPPING_INTERNAL, NULL); - switch(model->id) { - case ROM_PORTABLE: + switch(type) { + case 0: /* Portable 286 */ break; - case ROM_PORTABLEII: + case 2: /* Portable II */ break; #if defined(DEV_BRANCH) && defined(USE_PORTABLE3) - case ROM_PORTABLEIII: + case 3: /* Portable III */ machine_olim24_video_init(); break; - case ROM_PORTABLEIII386: + case 3+386: /* Portable III/386 */ machine_olim24_video_init(); if (hdc_type == 1) device_add(&ide_isa_device); break; #endif + #if defined(DEV_BRANCH) && defined(USE_DESKPRO386) - case ROM_DESKPRO_386: + case 4+386: /* Deskpro 386 */ if (hdc_type == 1) device_add(&ide_isa_device); break; #endif } } + + +void +machine_at_compaq_p1_init(const machine_t *model, void *arg) +{ + compaq_common_init(model, arg, 0); +} + + +void +machine_at_compaq_p2_init(const machine_t *model, void *arg) +{ + compaq_common_init(model, arg, 2); +} + + +void +machine_at_compaq_p3_init(const machine_t *model, void *arg) +{ + compaq_common_init(model, arg, 3); +} + + +void +machine_at_compaq_p3_386_init(const machine_t *model, void *arg) +{ + compaq_common_init(model, arg, 3+386); +} diff --git a/src/machines/m_at_headland.c b/src/machines/m_at_headland.c index 520c628..8b2760c 100644 --- a/src/machines/m_at_headland.c +++ b/src/machines/m_at_headland.c @@ -8,15 +8,17 @@ * * Implementation of the HEADLAND AT286 chipset. * - * Version: @(#)m_at_headland.c 1.0.5 2018/05/06 + * FIXME: fix the mem_map_t stuff in mem_read_b() et al! + * + * Version: @(#)m_at_headland.c 1.0.6 2018/09/22 * * Authors: Fred N. van Kempen, + * Original by GreatPsycho for PCem. * Miran Grca, - * Sarah Walker, * * Copyright 2017,2018 Fred N. van Kempen. - * Copyright 2016-2018 Miran Grca. - * Copyright 2008-2018 Sarah Walker. + * Copyright 2017,2018 Miran Grca. + * Copyright 2017,2018 GreatPsycho. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -39,77 +41,635 @@ #include #include #include +#include #include #include "../emu.h" #include "../cpu/cpu.h" #include "../cpu/x86.h" #include "../io.h" #include "../mem.h" +#include "../rom.h" #include "../device.h" #include "../devices/input/keyboard.h" #include "../devices/floppy/fdd.h" #include "../devices/floppy/fdc.h" +#include "../devices/video/video.h" #include "machine.h" -static int headland_index; -static uint8_t headland_regs[256]; +#define BIOS_67_AMA932J_PATH L"machines/unknown/ama932j/oti067.bin" -static void -headland_write(uint16_t addr, uint8_t val, void *priv) +typedef struct { + uint8_t port_92; + + uint8_t indx; + uint8_t regs[256]; + + uint8_t cri; + uint8_t cr[8]; + + uint8_t ems_mar; + uint16_t ems_mr[64]; + + rom_t vid_bios; + + mem_map_t low_mapping; + mem_map_t ems_mapping[64]; + mem_map_t mid_mapping; + mem_map_t high_mapping; + mem_map_t upper_mapping[24]; +} headland_t; + + +/* TODO - Headland chipset's memory address mapping emulation isn't fully implemented yet, + so memory configuration is hardcoded now. */ +static const int mem_conf_cr0[41] = { + 0x00, 0x00, 0x20, 0x40, 0x60, 0xA0, 0x40, 0xE0, + 0xA0, 0xC0, 0xE0, 0xE0, 0xC0, 0xE0, 0xE0, 0xE0, + 0xE0, 0x20, 0x40, 0x40, 0xA0, 0xC0, 0xE0, 0xE0, + 0xC0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, + 0x20, 0x40, 0x60, 0x60, 0xC0, 0xE0, 0xE0, 0xE0, + 0xE0 +}; +static const int mem_conf_cr1[41] = { + 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, 0x40, 0x40, + 0x00, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, + 0x00, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, + 0x40 +}; +static const video_timings_t oti067_timing = {VID_ISA,6,8,16,6,8,16}; + + +static uint32_t +get_addr(headland_t *dev, uint32_t addr, uint16_t *mr) { - uint8_t old_val; - - if (addr & 1) { - old_val = headland_regs[headland_index]; - - if (headland_index == 0xc1 && !is486) val = 0; - headland_regs[headland_index] = val; - if (headland_index == 0x82) { - shadowbios = val & 0x10; - shadowbios_write = !(val & 0x10); - if (shadowbios) - mem_set_mem_state(0xf0000, 0x10000, MEM_READ_INTERNAL | MEM_WRITE_DISABLED); + if (mr && (dev->cr[0] & 2) && (*mr & 0x200)) { + addr = (addr & 0x3fff) | ((*mr & 0x1F) << 14); + if (dev->cr[1] & 0x40) { + if ((dev->cr[4] & 0x80) && (dev->cr[6] & 1)) { + if (dev->cr[0] & 0x80) { + addr |= (*mr & 0x60) << 14; + if (*mr & 0x100) + addr += ((*mr & 0xC00) << 13) + (((*mr & 0x80) + 0x80) << 15); + else + addr += (*mr & 0x80) << 14; + } else if (*mr & 0x100) + addr += ((*mr & 0xC00) << 13) + (((*mr & 0x80) + 0x20) << 15); + else + addr += (*mr & 0x80) << 12; + } else if (dev->cr[0] & 0x80) + addr |= (*mr & 0x100) ? ((*mr & 0x80) + 0x400) << 12 : (*mr & 0xE0) << 14; else - mem_set_mem_state(0xf0000, 0x10000, MEM_READ_EXTERNAL | MEM_WRITE_INTERNAL); - } else if (headland_index == 0x87) { - if ((val & 1) && !(old_val & 1)) - softresetx86(); + addr |= (*mr & 0x100) ? ((*mr & 0xE0) + 0x40) << 14 : (*mr & 0x80) << 12; + } else { + if ((dev->cr[4] & 0x80) && (dev->cr[6] & 1)) { + if (dev->cr[0] & 0x80) { + addr |= ((*mr & 0x60) << 14); + if (*mr & 0x180) + addr += ((*mr & 0xC00) << 13) + (((*mr & 0x180) - 0x60) << 16); + } else + addr |= ((*mr & 0x60) << 14) | ((*mr & 0x180) << 16) | ((*mr & 0xC00) << 13); + } else if (dev->cr[0] & 0x80) + addr |= (*mr & 0x1E0) << 14; + else + addr |= (*mr & 0x180) << 12; } - } else - headland_index = val; + } else if (mr == NULL && (dev->cr[0] & 4) == 0 && mem_size >= 1024 && addr >= 0x100000) + addr -= 0x60000; + + return addr; +} + + +static void +set_global_EMS_state(headland_t *dev, int state) +{ + uint32_t base_addr, virt_addr; + int i; + + for (i = 0; i < 32; i++) { + base_addr = (i + 16) << 14; + if (i >= 24) + base_addr += 0x20000; + if ((state & 2) && (dev->ems_mr[((state & 1) << 5) | i] & 0x200)) { + virt_addr = get_addr(dev, base_addr, &dev->ems_mr[((state & 1) << 5) | i]); + if (i < 24) + mem_map_disable(&dev->upper_mapping[i]); + mem_map_disable(&dev->ems_mapping[(((state ^ 1) & 1) << 5) | i]); + mem_map_enable(&dev->ems_mapping[((state & 1) << 5) | i]); + if (virt_addr < ((uint32_t)mem_size << 10)) + mem_map_set_exec(&dev->ems_mapping[((state & 1) << 5) | i], ram + virt_addr); + else + mem_map_set_exec(&dev->ems_mapping[((state & 1) << 5) | i], NULL); + } else { + mem_map_set_exec(&dev->ems_mapping[((state & 1) << 5) | i], ram + base_addr); + mem_map_disable(&dev->ems_mapping[(((state ^ 1) & 1) << 5) | i]); + mem_map_disable(&dev->ems_mapping[((state & 1) << 5) | i]); + if (i < 24) + mem_map_enable(&dev->upper_mapping[i]); + } + } + + flushmmucache(); +} + + +static void +memmap_state_update(headland_t *dev) +{ + uint32_t addr; + int i; + + for (i = 0; i < 24; i++) { + addr = get_addr(dev, 0x40000 + (i << 14), NULL); + mem_map_set_exec(&dev->upper_mapping[i], addr < ((uint32_t)mem_size << 10) ? ram + addr : NULL); + } + mem_set_mem_state(0xA0000, 0x40000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); + if (mem_size > 640) { + if ((dev->cr[0] & 4) == 0) { + mem_map_set_addr(&dev->mid_mapping, 0x100000, mem_size > 1024 ? 0x60000 : (mem_size - 640) << 10); + mem_map_set_exec(&dev->mid_mapping, ram + 0xA0000); + if (mem_size > 1024) { + mem_map_set_addr(&dev->high_mapping, 0x160000, (mem_size - 1024) << 10); + mem_map_set_exec(&dev->high_mapping, ram + 0x100000); + } + } else { + mem_map_set_addr(&dev->mid_mapping, 0xA0000, mem_size > 1024 ? 0x60000 : (mem_size - 640) << 10); + mem_map_set_exec(&dev->mid_mapping, ram + 0xA0000); + if (mem_size > 1024) { + mem_map_set_addr(&dev->high_mapping, 0x100000, (mem_size - 1024) << 10); + mem_map_set_exec(&dev->high_mapping, ram + 0x100000); + } + } + } + + set_global_EMS_state(dev, dev->cr[0] & 3); +} + + +static void +hl_write(uint16_t addr, uint8_t val, void *priv) +{ + headland_t *dev = (headland_t *)priv; + uint32_t base_addr, virt_addr; + uint8_t old_val, indx; + + switch(addr) { + case 0x0022: + dev->indx = val; + break; + + case 0x0023: + old_val = dev->regs[dev->indx]; + if ((dev->indx == 0xc1) && !is486) + val = 0; + dev->regs[dev->indx] = val; + if (dev->indx == 0x82) { + shadowbios = val & 0x10; + shadowbios_write = !(val & 0x10); + if (shadowbios) + mem_set_mem_state(0xf0000, 0x10000, MEM_READ_INTERNAL | MEM_WRITE_DISABLED); + else + mem_set_mem_state(0xf0000, 0x10000, MEM_READ_EXTERNAL | MEM_WRITE_INTERNAL); + } else if (dev->indx == 0x87) { + if ((val & 1) && !(old_val & 1)) + softresetx86(); + } + break; + + case 0x0092: + if ((mem_a20_alt ^ val) & 2) { + mem_a20_alt = val & 2; + mem_a20_recalc(); + } + if ((~dev->port_92 & val) & 1) { + softresetx86(); + cpu_set_edx(); + } + dev->port_92 = val | 0xfc; + break; + + case 0x01ec: + dev->ems_mr[dev->ems_mar & 0x3f] = val | 0xff00; + indx = dev->ems_mar & 0x1f; + base_addr = (indx + 16) << 14; + if (indx >= 24) + base_addr += 0x20000; + if ((dev->cr[0] & 2) && ((dev->cr[0] & 1) == ((dev->ems_mar & 0x20) >> 5))) { + virt_addr = get_addr(dev, base_addr, &dev->ems_mr[dev->ems_mar & 0x3F]); + if (indx < 24) + mem_map_disable(&dev->upper_mapping[indx]); + if (virt_addr < ((uint32_t)mem_size << 10)) + mem_map_set_exec(&dev->ems_mapping[dev->ems_mar & 0x3f], ram + virt_addr); + else + mem_map_set_exec(&dev->ems_mapping[dev->ems_mar & 0x3f], NULL); + mem_map_enable(&dev->ems_mapping[dev->ems_mar & 0x3f]); + flushmmucache(); + } + if (dev->ems_mar & 0x80) + dev->ems_mar++; + break; + + case 0x01ed: + dev->cri = val; + break; + + case 0x01ee: + dev->ems_mar = val; + break; + + case 0x01ef: + old_val = dev->cr[dev->cri]; + switch(dev->cri) { + case 0: + dev->cr[0] = (val & 0x1f) | mem_conf_cr0[(mem_size > 640 ? mem_size : mem_size - 128) >> 9]; + mem_set_mem_state(0xe0000, 0x10000, (val & 8 ? MEM_READ_INTERNAL : MEM_READ_EXTERNAL) | MEM_WRITE_DISABLED); + mem_set_mem_state(0xf0000, 0x10000, (val & 0x10 ? MEM_READ_INTERNAL: MEM_READ_EXTERNAL) | MEM_WRITE_DISABLED); + memmap_state_update(dev); + break; + + case 1: + dev->cr[1] = (val & 0xbf) | mem_conf_cr1[(mem_size > 640 ? mem_size : mem_size - 128) >> 9]; + memmap_state_update(dev); + break; + + case 2: + case 3: + case 5: + dev->cr[dev->cri] = val; + memmap_state_update(dev); + break; + + case 4: + dev->cr[4] = (dev->cr[4] & 0xf0) | (val & 0x0f); + if (val & 1) { + mem_map_disable(&bios_mapping[0]); + mem_map_disable(&bios_mapping[1]); + mem_map_disable(&bios_mapping[2]); + mem_map_disable(&bios_mapping[3]); + } else { + mem_map_enable(&bios_mapping[0]); + mem_map_enable(&bios_mapping[1]); + mem_map_enable(&bios_mapping[2]); + mem_map_enable(&bios_mapping[3]); + } + break; + + case 6: + if (dev->cr[4] & 0x80) { + dev->cr[dev->cri] = (val & 0xfe) | (mem_size > 8192 ? 1 : 0); + memmap_state_update(dev); + } + break; + + default: + break; + } + break; + + default: + break; + } +} + + +static void +hl_writew(uint16_t addr, uint16_t val, void *priv) +{ + headland_t *dev = (headland_t *)priv; + uint32_t base_addr, virt_addr; + uint8_t indx; + + switch(addr) { + case 0x01ec: + dev->ems_mr[dev->ems_mar & 0x3f] = val; + indx = dev->ems_mar & 0x1f; + base_addr = (indx + 16) << 14; + if (indx >= 24) + base_addr += 0x20000; + if ((dev->cr[0] & 2) && (dev->cr[0] & 1) == ((dev->ems_mar & 0x20) >> 5)) { + if (val & 0x200) { + virt_addr = get_addr(dev, base_addr, &dev->ems_mr[dev->ems_mar & 0x3f]); + if (indx < 24) + mem_map_disable(&dev->upper_mapping[indx]); + if (virt_addr < ((uint32_t)mem_size << 10)) + mem_map_set_exec(&dev->ems_mapping[dev->ems_mar & 0x3f], ram + virt_addr); + else + mem_map_set_exec(&dev->ems_mapping[dev->ems_mar & 0x3f], NULL); + mem_map_enable(&dev->ems_mapping[dev->ems_mar & 0x3f]); + } else { + mem_map_set_exec(&dev->ems_mapping[dev->ems_mar & 0x3f], ram + base_addr); + mem_map_disable(&dev->ems_mapping[dev->ems_mar & 0x3f]); + if (indx < 24) + mem_map_enable(&dev->upper_mapping[indx]); + } + flushmmucache(); + } + if (dev->ems_mar & 0x80) + dev->ems_mar++; + break; + + default: + break; + } } static uint8_t -headland_read(uint16_t addr, void *priv) +hl_read(uint16_t addr, void *priv) { - if (addr & 1) { - if ((headland_index >= 0xc0 || headland_index == 0x20) && cpu_iscyrix) - return(0xff); /*Don't conflict with Cyrix config registers*/ - return(headland_regs[headland_index]); + headland_t *dev = (headland_t *)priv; + uint8_t ret = 0xff; + + switch(addr) { + case 0x0022: + ret = dev->indx; + break; + + case 0x0023: + if ((dev->indx >= 0xc0 || dev->indx == 0x20) && cpu_iscyrix) + ret = 0xff; /*Don't conflict with Cyrix config registers*/ + else + ret = dev->regs[dev->indx]; + break; + + case 0x0092: + ret = dev->port_92 | 0xfc; + break; + + case 0x01ec: + ret = (uint8_t)dev->ems_mr[dev->ems_mar & 0x3f]; + if (dev->ems_mar & 0x80) + dev->ems_mar++; + break; + + case 0x01ed: + ret = dev->cri; + break; + + case 0x01ee: + ret = dev->ems_mar; + break; + + case 0x01ef: + switch(dev->cri) { + case 0: + ret = (dev->cr[0] & 0x1f) | mem_conf_cr0[(mem_size > 640 ? mem_size : mem_size - 128) >> 9]; + break; + + case 1: + ret = (dev->cr[1] & 0xbf) | mem_conf_cr1[(mem_size > 640 ? mem_size : mem_size - 128) >> 9]; + break; + + case 6: + if (dev->cr[4] & 0x80) + ret = (dev->cr[6] & 0xfe) | (mem_size > 8192 ? 1 : 0); + else + ret = 0; + break; + + default: + ret = dev->cr[dev->cri]; + break; + } + break; + + default: + break; } - return(headland_index); + return ret; +} + + +static uint16_t +hl_readw(uint16_t addr, void *priv) +{ + headland_t *dev = (headland_t *)priv; + uint16_t ret = 0xffff; + + switch(addr) { + case 0x01ec: + ret = dev->ems_mr[dev->ems_mar & 0x3f] | ((dev->cr[4] & 0x80) ? 0xf000 : 0xfc00); + if (dev->ems_mar & 0x80) + dev->ems_mar++; + break; + + default: + break; + } + + return ret; +} + + +static uint8_t +mem_read_b(uint32_t addr, void *priv) +{ + uint16_t *mr = (uint16_t *)priv; + headland_t *dev = NULL; //FIXME: + uint8_t ret = 0xff; + + addr = get_addr(dev, addr, mr); + if (addr < ((uint32_t)mem_size << 10)) + ret = ram[addr]; + + return ret; +} + + +static uint16_t +mem_read_w(uint32_t addr, void *priv) +{ + uint16_t *mr = (uint16_t *)priv; + headland_t *dev = NULL; //FIXME: + uint16_t ret = 0xffff; + + addr = get_addr(dev, addr, mr); + if (addr < ((uint32_t)mem_size << 10)) + ret = *(uint16_t *)&ram[addr]; + + return ret; +} + + +static uint32_t +mem_read_l(uint32_t addr, void *priv) +{ + uint16_t *mr = (uint16_t *)priv; + headland_t *dev = NULL; //FIXME: + uint32_t ret = 0xffffffff; + + addr = get_addr(dev, addr, mr); + if (addr < ((uint32_t)mem_size << 10)) + ret = *(uint32_t *)&ram[addr]; + + return ret; } static void -headland_init(void) +mem_write_b(uint32_t addr, uint8_t val, void *priv) { - io_sethandler(0x0022, 2, - headland_read,NULL,NULL, headland_write,NULL,NULL, NULL); + uint16_t *mr = (uint16_t *)priv; + headland_t *dev = NULL; //FIXME: + + addr = get_addr(dev, addr, mr); + if (addr < ((uint32_t)mem_size << 10)) + ram[addr] = val; +} + + +static void +mem_write_w(uint32_t addr, uint16_t val, void *priv) +{ + uint16_t *mr = (uint16_t *)priv; + headland_t *dev = NULL; //FIXME: + + addr = get_addr(dev, addr, mr); + if (addr < ((uint32_t)mem_size << 10)) + *(uint16_t *)&ram[addr] = val; +} + + +static void +mem_write_l(uint32_t addr, uint32_t val, void *priv) +{ + uint16_t *mr = (uint16_t *)priv; + headland_t *dev = NULL; //FIXME: + + addr = get_addr(dev, addr, mr); + if (addr < ((uint32_t)mem_size << 10)) + *(uint32_t *)&ram[addr] = val; +} + + +static void +headland_init(headland_t *dev, int ht386) +{ + int i; + + dev->port_92 = 0xfc; + + for (i = 0; i < 8; i++) + dev->cr[i] = 0x00; + dev->cr[0] = 0x04; + + if (ht386) { + dev->cr[4] = 0x20; + io_sethandler(0x0092, 1, + hl_read,NULL,NULL, hl_write,NULL,NULL, dev); + } else + dev->cr[4] = 0x00; + + io_sethandler(0x01EC, 1, + hl_read,hl_readw,NULL, hl_write,hl_writew,NULL, dev); + + io_sethandler(0x01ED, 3, hl_read,NULL,NULL, hl_write,NULL,NULL, dev); + + for (i = 0; i < 64; i++) + dev->ems_mr[i] = 0x00; + + /* Turn off mem.c mappings. */ + mem_map_disable(&ram_low_mapping); + mem_map_disable(&ram_mid_mapping); + mem_map_disable(&ram_high_mapping); + + mem_map_add(&dev->low_mapping, 0, 0x40000, + mem_read_b,mem_read_w,mem_read_l, + mem_write_b,mem_write_w,mem_write_l, + ram, MEM_MAPPING_INTERNAL, dev); + + if (mem_size > 640) { + mem_map_add(&dev->mid_mapping, 0xA0000, 0x60000, + mem_read_b,mem_read_w,mem_read_l, + mem_write_b,mem_write_w,mem_write_l, + ram + 0xA0000, MEM_MAPPING_INTERNAL, dev); + mem_map_enable(&dev->mid_mapping); + } + + if (mem_size > 1024) { + mem_map_add(&dev->high_mapping, 0x100000, ((mem_size-1024)*1024), + mem_read_b,mem_read_w,mem_read_l, + mem_write_b,mem_write_w,mem_write_l, + ram + 0x100000, MEM_MAPPING_INTERNAL, dev); + mem_map_enable(&dev->high_mapping); + } + + for (i = 0; i < 24; i++) { + mem_map_add(&dev->upper_mapping[i], + 0x40000 + (i << 14), 0x4000, + mem_read_b,mem_read_w,mem_read_l, + mem_write_b,mem_write_w,mem_write_l, + mem_size > 256 + (i << 4) ? ram + 0x40000 + (i << 14) : NULL, + MEM_MAPPING_INTERNAL, dev); + mem_map_enable(&dev->upper_mapping[i]); + } + + for (i = 0; i < 64; i++) { + dev->ems_mr[i] = 0x00; + mem_map_add(&dev->ems_mapping[i], + ((i & 31) + ((i & 31) >= 24 ? 24 : 16)) << 14, 0x04000, + mem_read_b,mem_read_w,mem_read_l, + mem_write_b,mem_write_w,mem_write_l, + ram + (((i & 31) + ((i & 31) >= 24 ? 24 : 16)) << 14), + 0, &dev->ems_mr[i]); + mem_map_disable(&dev->ems_mapping[i]); + } + + memmap_state_update(dev); +} + + +static headland_t * +headland_common_init(int ht386) +{ + headland_t *dev; + + dev = (headland_t *)mem_alloc(sizeof(headland_t)); + memset(dev, 0x00, sizeof(headland_t)); + + device_add(&keyboard_at_ami_device); + + device_add(&fdc_at_device); + + headland_init(dev, ht386); + + return(dev); } void -machine_at_headland_init(const machine_t *model, void *arg) +machine_at_ama932j_init(const machine_t *model, void *arg) { + headland_t *dev; + machine_at_common_ide_init(model, arg); - device_add(&keyboard_at_ami_device); - device_add(&fdc_at_device); + dev = headland_common_init(1); - headland_init(); + if (video_card == VID_INTERNAL) { + rom_init(&dev->vid_bios, BIOS_67_AMA932J_PATH, + 0xc0000, 0x8000, 0x7fff, + 0, MEM_MAPPING_INTERNAL); + + device_add(&oti067_onboard_device); + } +} + + +void +machine_at_tg286m_init(const machine_t *model, void *arg) +{ + machine_at_common_init(model, arg); + + headland_common_init(0); + + if (video_card == VID_INTERNAL) { + device_add(&et4000k_tg286_isa_device); + video_inform(VID_TYPE_SPEC, &oti067_timing); + } } diff --git a/src/machines/m_at_neat.c b/src/machines/m_at_neat.c index 7553faa..ad17258 100644 --- a/src/machines/m_at_neat.c +++ b/src/machines/m_at_neat.c @@ -13,7 +13,7 @@ * 8MB of DRAM chips', because it works fine with bus-based * memory expansion. * - * Version: @(#)m_at_neat.c 1.0.1 2018/07/22 + * Version: @(#)m_at_neat.c 1.0.2 2018/10/05 * * Author: Fred N. van Kempen, * @@ -64,9 +64,6 @@ #include "machine.h" -#define NEAT_DEBUG 1 - - #define EMS_MAXPAGE 4 #define EMS_PGSIZE 16384 @@ -241,7 +238,7 @@ typedef struct { uint16_t page; /* selected page in EMS block */ uint32_t start; /* start of EMS in RAM */ uint8_t *addr; /* start addr in EMS RAM */ - mem_mapping_t mapping; /* mapping entry for page */ + mem_map_t mapping; /* mapping entry for page */ } emspage_t; typedef struct { @@ -264,7 +261,7 @@ typedef struct { static uint8_t ems_readb(uint32_t addr, void *priv) { - mem_mapping_t *map = (mem_mapping_t *)priv; + mem_map_t *map = (mem_map_t *)priv; neat_t *dev = (neat_t *)map->dev; uint8_t ret = 0xff; int vpage; @@ -283,7 +280,7 @@ ems_readb(uint32_t addr, void *priv) static uint16_t ems_readw(uint32_t addr, void *priv) { - mem_mapping_t *map = (mem_mapping_t *)priv; + mem_map_t *map = (mem_map_t *)priv; neat_t *dev = (neat_t *)map->dev; uint16_t ret = 0xffff; int vpage; @@ -302,7 +299,7 @@ ems_readw(uint32_t addr, void *priv) static void ems_writeb(uint32_t addr, uint8_t val, void *priv) { - mem_mapping_t *map = (mem_mapping_t *)priv; + mem_map_t *map = (mem_map_t *)priv; neat_t *dev = (neat_t *)map->dev; int vpage; @@ -318,7 +315,7 @@ ems_writeb(uint32_t addr, uint8_t val, void *priv) static void ems_writew(uint32_t addr, uint16_t val, void *priv) { - mem_mapping_t *map = (mem_mapping_t *)priv; + mem_map_t *map = (mem_map_t *)priv; neat_t *dev = (neat_t *)map->dev; int vpage; @@ -344,18 +341,16 @@ ems_recalc(neat_t *dev, emspage_t *ems) if (ems->enabled) { /* Update the EMS RAM address for this page. */ - mem_mapping_set_exec(&ems->mapping, ems->addr); + mem_map_set_exec(&ems->mapping, ems->addr); /* Enable this page. */ - mem_mapping_enable(&ems->mapping); + mem_map_enable(&ems->mapping); -#if NEAT_DEBUG > 1 - pclog("NEAT EMS: page %d set to %08lx, %sabled)\n", + DBGLOG(1, "NEAT EMS: page %d set to %08lx, %sabled)\n", ems->page, ems->addr-ram, ems->enabled?"en":"dis"); -#endif } else { /* Disable this page. */ - mem_mapping_disable(&ems->mapping); + mem_map_disable(&ems->mapping); } } @@ -367,9 +362,7 @@ ems_write(uint16_t port, uint8_t val, void *priv) emspage_t *ems; int vpage; -#if NEAT_DEBUG > 1 - pclog("NEAT: ems_write(%04x, %02x)\n", port, val); -#endif + DBGLOG(2, "NEAT: ems_write(%04x, %02x)\n", port, val); /* Get the viewport page number. */ vpage = (port / EMS_PGSIZE); @@ -405,9 +398,7 @@ ems_read(uint16_t port, void *priv) break; } -#if NEAT_DEBUG > 1 - pclog("NEAT: ems_read(%04x) = %02x\n", port, ret); -#endif + DBGLOG(2, "NEAT: ems_read(%04x) = %02x\n", port, ret); return(ret); } @@ -423,14 +414,14 @@ ems_init(neat_t *dev, int en) if (! en) { if (dev->ems_base > 0) for (i = 0; i < EMS_MAXPAGE; i++) { /* Disable for now. */ - mem_mapping_disable(&dev->ems[i].mapping); + mem_map_disable(&dev->ems[i].mapping); /* Remove I/O handler. */ io_removehandler(dev->ems_base + (i * EMS_PGSIZE), 2, ems_read,NULL,NULL, ems_write,NULL,NULL, dev); } - pclog("NEAT: EMS disabled\n"); + DEBUG("NEAT: EMS disabled\n"); return; } @@ -450,16 +441,16 @@ ems_init(neat_t *dev, int en) */ for (i = 0; i < EMS_MAXPAGE; i++) { /* Create and initialize a page mapping. */ - mem_mapping_add(&dev->ems[i].mapping, - dev->ems_frame + (EMS_PGSIZE*i), EMS_PGSIZE, - ems_readb, ems_readw, NULL, - ems_writeb, ems_writew, NULL, - ram, MEM_MAPPING_EXTERNAL, - &dev->ems[i].mapping); - mem_mapping_set_dev(&dev->ems[i].mapping, dev); + mem_map_add(&dev->ems[i].mapping, + dev->ems_frame + (EMS_PGSIZE*i), EMS_PGSIZE, + ems_readb, ems_readw, NULL, + ems_writeb, ems_writew, NULL, + ram, MEM_MAPPING_EXTERNAL, + &dev->ems[i].mapping); + mem_map_set_dev(&dev->ems[i].mapping, dev); /* Disable for now. */ - mem_mapping_disable(&dev->ems[i].mapping); + mem_map_disable(&dev->ems[i].mapping); /* Set up an I/O port handler. */ io_sethandler(dev->ems_base + (i * EMS_PGSIZE), 2, @@ -471,7 +462,7 @@ ems_init(neat_t *dev, int en) */ } - pclog("NEAT: EMS enabled, I/O=%04xH, Frame=%05XH\n", + DEBUG("NEAT: EMS enabled, I/O=%04xH, Frame=%05XH\n", dev->ems_base, dev->ems_frame); } @@ -483,9 +474,7 @@ neat_write(uint16_t port, uint8_t val, void *priv) uint8_t xval, *reg; int i; -#if NEAT_DEBUG > 2 - pclog("NEAT: write(%04x, %02x)\n", port, val); -#endif + DBGLOG(3, "NEAT: write(%04x, %02x)\n", port, val); switch (port) { case 0x22: @@ -500,90 +489,68 @@ neat_write(uint16_t port, uint8_t val, void *priv) val &= RA0_MASK; *reg = (*reg & ~RA0_MASK) | val | \ (RA0_REV_ID << RA0_REV_SH); -#if NEAT_DEBUG > 1 - pclog("NEAT: RA0=%02x(%02x)\n", val, *reg); -#endif + DBGLOG(2, "NEAT: RA0=%02x(%02x)\n", val, *reg); break; case REG_RA1: val &= RA1_MASK; *reg = (*reg & ~RA1_MASK) | val; -#if NEAT_DEBUG > 1 - pclog("NEAT: RA1=%02x(%02x)\n", val, *reg); -#endif + DBGLOG(2, "NEAT: RA1=%02x(%02x)\n", val, *reg); break; case REG_RA2: val &= RA2_MASK; *reg = (*reg & ~RA2_MASK) | val; -#if NEAT_DEBUG > 1 - pclog("NEAT: RA2=%02x(%02x)\n", val, *reg); -#endif + DBGLOG(2, "NEAT: RA2=%02x(%02x)\n", val, *reg); break; case REG_RB0: val &= RB0_MASK; *reg = (*reg & ~RB0_MASK) | val | \ (RB0_REV_ID << RB0_REV_SH); -#if NEAT_DEBUG > 1 - pclog("NEAT: RB0=%02x(%02x)\n", val, *reg); -#endif + DBGLOG(2, "NEAT: RB0=%02x(%02x)\n", val, *reg); break; case REG_RB1: val &= RB1_MASK; *reg = (*reg & ~RB1_MASK) | val; -#if NEAT_DEBUG > 1 - pclog("NEAT: RB1=%02x(%02x)\n", val, *reg); -#endif + DBGLOG(2, "NEAT: RB1=%02x(%02x)\n", val, *reg); break; case REG_RB2: val &= RB2_MASK; *reg = (*reg & ~RB2_MASK) | val; -#if NEAT_DEBUG > 1 - pclog("NEAT: RB2=%02x(%02x)\n", val, *reg); -#endif + DBGLOG(2, "NEAT: RB2=%02x(%02x)\n", val, *reg); break; case REG_RB3: val &= RB3_MASK; *reg = (*reg & ~RB3_MASK) | val; -#if NEAT_DEBUG > 1 - pclog("NEAT: RB3=%02x(%02x)\n", val, *reg); -#endif + DBGLOG(2, "NEAT: RB3=%02x(%02x)\n", val, *reg); break; case REG_RB4: val &= RB4_MASK; *reg = (*reg & ~RB4_MASK) | val; -#if NEAT_DEBUG > 1 - pclog("NEAT: RB4=%02x(%02x)\n", val, *reg); -#endif + DBGLOG(2, "NEAT: RB4=%02x(%02x)\n", val, *reg); break; case REG_RB5: val &= RB5_MASK; *reg = (*reg & ~RB5_MASK) | val; -#if NEAT_DEBUG > 1 - pclog("NEAT: RB5=%02x(%02x)\n", val, *reg); -#endif + DBGLOG(2, "NEAT: RB5=%02x(%02x)\n", val, *reg); break; case REG_RB6: val &= RB6_MASK; *reg = (*reg & ~RB6_MASK) | val; -#if NEAT_DEBUG > 1 - pclog("NEAT: RB6=%02x(%02x)\n", val, *reg); -#endif + DBGLOG(2, "NEAT: RB6=%02x(%02x)\n", val, *reg); break; case REG_RB7: val &= RB7_MASK; *reg = (*reg & ~RB7_MASK) | val; -#if NEAT_DEBUG > 1 - pclog("NEAT: RB7=%02x(%02x)\n", val, *reg); -#endif + DBGLOG(2, "NEAT: RB7=%02x(%02x)\n", val, *reg); if (val & RB7_EMSEN) ems_init(dev, 1); else if (xval & RB7_EMSEN) @@ -600,17 +567,13 @@ neat_write(uint16_t port, uint8_t val, void *priv) case REG_RB8: val &= RB8_MASK; *reg = (*reg & ~RB8_MASK) | val; -#if NEAT_DEBUG > 1 - pclog("NEAT: RB8=%02x(%02x)\n", val, *reg); -#endif + DBGLOG(2, "NEAT: RB8=%02x(%02x)\n", val, *reg); break; case REG_RB9: val &= RB9_MASK; *reg = (*reg & ~RB9_MASK) | val; -#if NEAT_DEBUG > 1 - pclog("NEAT: RB9=%02x(%02x)\n", val, *reg); -#endif + DBGLOG(2, "NEAT: RB9=%02x(%02x)\n", val, *reg); if (dev->regs[REG_RB7] & RB7_EMSEN) { ems_init(dev, 0); ems_init(dev, 1); @@ -620,9 +583,7 @@ neat_write(uint16_t port, uint8_t val, void *priv) case REG_RB10: val &= RB10_MASK; *reg = (*reg & ~RB10_MASK) | val; -#if NEAT_DEBUG > 1 - pclog("NEAT: RB10=%02x(%02x)\n", val, *reg); -#endif + DBGLOG(2, "NEAT: RB10=%02x(%02x)\n", val, *reg); dev->ems[3].start = ((val & RB10_P3EXT) >> RB10_P3EXT_SH) << 21; dev->ems[2].start = ((val & RB10_P2EXT) >> RB10_P2EXT_SH) << 21; @@ -635,9 +596,7 @@ neat_write(uint16_t port, uint8_t val, void *priv) case REG_RB11: val &= RB11_MASK; *reg = (*reg & ~RB11_MASK) | val; -#if NEAT_DEBUG > 1 - pclog("NEAT: RB11=%02x(%02x)\n", val, *reg); -#endif + DBGLOG(2, "NEAT: RB11=%02x(%02x)\n", val, *reg); i = (val & RB11_EMSLEN) >> RB11_EMSLEN_SH; switch(i) { case 0: /* "less than 2MB" */ @@ -656,13 +615,13 @@ neat_write(uint16_t port, uint8_t val, void *priv) } dev->ems_pages = (dev->ems_size << 10) / EMS_PGSIZE; if (dev->regs[REG_RB7] & RB7_EMSEN) - pclog("NEAT: EMS %iKB (%i pages)\n", + DEBUG("NEAT: EMS %iKB (%i pages)\n", dev->ems_size, dev->ems_pages); break; default: - pclog("NEAT: inv write to reg %02x (%02x)\n", - dev->indx, val); + ERRLOG("NEAT: inv write to reg %02x (%02x)\n", + dev->indx, val); break; } break; @@ -689,9 +648,7 @@ neat_read(uint16_t port, void *priv) break; } -#if NEAT_DEBUG > 2 - pclog("NEAT: read(%04x) = %02x\n", port, ret); -#endif + DBGLOG(3, "NEAT: read(%04x) = %02x\n", port, ret); return(ret); } @@ -704,7 +661,7 @@ neat_init(void) int i; /* Create an instance. */ - dev = (neat_t *)malloc(sizeof(neat_t)); + dev = (neat_t *)mem_alloc(sizeof(neat_t)); memset(dev, 0x00, sizeof(neat_t)); /* Initialize some of the registers to specific defaults. */ @@ -842,10 +799,10 @@ neat_init(void) break; default: - pclog("NEAT: **INVALID DRAM SIZE %iKB !**\n", mem_size); + ERRLOG("NEAT: **INVALID DRAM SIZE %iKB !**\n", mem_size); } if (i > 0) - pclog("NEAT: using DRAM mode #%i (mem=%iKB)\n", i, mem_size); + DEBUG("NEAT: using DRAM mode #%i (mem=%iKB)\n", i, mem_size); /* Set up an I/O handler for the chipset. */ io_sethandler(0x0022, 2, diff --git a/src/machines/m_at_opti495.c b/src/machines/m_at_opti495.c index 25d2594..6813a44 100644 --- a/src/machines/m_at_opti495.c +++ b/src/machines/m_at_opti495.c @@ -260,7 +260,7 @@ Note: the block address is forced to be a multiple of the block size by ignoring the appropriate number of the least-significant bits SeeAlso: #P0178,#P0187 * - * Version: @(#)m_at_opti495.c 1.0.6 2018/06/25 + * Version: @(#)m_at_opti495.c 1.0.7 2018/09/06 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -316,9 +316,6 @@ opti495_write(uint16_t addr, uint8_t val, void *p) break; case 0x24: -#if 0 - pclog("OPTI: writing reg %02X %02X\n", optireg, val); -#endif if (optireg >= 0x20 && optireg <= 0x2C) { optiregs[optireg - 0x20] = val; if (optireg == 0x21) { diff --git a/src/machines/m_at_scat.c b/src/machines/m_at_scat.c index 2597e10..deca3a6 100644 --- a/src/machines/m_at_scat.c +++ b/src/machines/m_at_scat.c @@ -8,9 +8,7 @@ * * Implementation of Chips&Technology's SCAT (82C235) chipset. * - * Re-worked version based on the 82C235 datasheet and errata. - * - * Version: @(#)m_at_scat.c 1.0.11 2018/08/31 + * Version: @(#)m_at_scat.c 1.0.12 2018/09/15 * * Authors: Fred N. van Kempen, * Original by GreatPsycho for PCem. @@ -42,10 +40,12 @@ #include #include #include "../emu.h" +#include "../device.h" #include "../cpu/cpu.h" #include "../cpu/x86.h" #include "../io.h" #include "../mem.h" +#include "../rom.h" #include "../device.h" #include "../devices/system/nmi.h" #include "../devices/input/keyboard.h" @@ -54,101 +54,92 @@ #include "machine.h" -#define SCAT_DMA_WAIT_STATE_CONTROL 0x01 -#define SCAT_VERSION 0x40 -#define SCAT_CLOCK_CONTROL 0x41 -#define SCAT_PERIPHERAL_CONTROL 0x44 -#define SCAT_MISCELLANEOUS_STATUS 0x45 -#define SCAT_POWER_MANAGEMENT 0x46 -#define SCAT_ROM_ENABLE 0x48 -#define SCAT_RAM_WRITE_PROTECT 0x49 -#define SCAT_SHADOW_RAM_ENABLE_1 0x4a -#define SCAT_SHADOW_RAM_ENABLE_2 0x4b -#define SCAT_SHADOW_RAM_ENABLE_3 0x4c -#define SCAT_DRAM_CONFIGURATION 0x4d -#define SCAT_EXTENDED_BOUNDARY 0x4e -#define SCAT_EMS_CONTROL 0x4f +#define SCAT_DMA_WAIT_STATE_CONTROL 0x01 +#define SCAT_VERSION 0x40 +#define SCAT_CLOCK_CONTROL 0x41 +#define SCAT_PERIPHERAL_CONTROL 0x44 +#define SCAT_MISCELLANEOUS_STATUS 0x45 +#define SCAT_POWER_MANAGEMENT 0x46 +#define SCAT_ROM_ENABLE 0x48 +#define SCAT_RAM_WRITE_PROTECT 0x49 +#define SCAT_SHADOW_RAM_ENABLE_1 0x4A +#define SCAT_SHADOW_RAM_ENABLE_2 0x4B +#define SCAT_SHADOW_RAM_ENABLE_3 0x4C +#define SCAT_DRAM_CONFIGURATION 0x4D +#define SCAT_EXTENDED_BOUNDARY 0x4E +#define SCAT_EMS_CONTROL 0x4F -#define SCATSX_LAPTOP_FEATURES 0x60 -#define SCATSX_FAST_VIDEO_CONTROL 0x61 -#define SCATSX_FAST_VIDEORAM_ENABLE 0x62 -#define SCATSX_HIGH_PERFORMANCE_REFRESH 0x63 -#define SCATSX_CAS_TIMING_FOR_DMA 0x64 +#define SCATSX_LAPTOP_FEATURES 0x60 +#define SCATSX_FAST_VIDEO_CONTROL 0x61 +#define SCATSX_FAST_VIDEORAM_ENABLE 0x62 +#define SCATSX_HIGH_PERFORMANCE_REFRESH 0x63 +#define SCATSX_CAS_TIMING_FOR_DMA 0x64 - -typedef struct { - uint8_t regs_2x8; - uint8_t regs_2x9; +typedef struct scat_t +{ + uint8_t regs_2x8; + uint8_t regs_2x9; } scat_t; -static uint8_t scat_regs[256]; -static int scat_index; -static uint8_t scat_port_92 = 0; -static uint8_t scat_ems_reg_2xA = 0; -static scat_t scat_stat[32]; -static uint32_t scat_xms_bound; -static mem_mapping_t scat_low_mapping[32]; -static mem_mapping_t scat_ems_mapping[32]; -static mem_mapping_t scat_high_mapping[16]; -static mem_mapping_t scat_remap_mapping[6]; -static mem_mapping_t scat_4000_EFFF_mapping[44]; -static mem_mapping_t scat_low_ROMCS_mapping[8]; +static uint8_t scat_regs[256]; +static int scat_index; +static uint8_t scat_port_92 = 0; +static uint8_t scat_ems_reg_2xA = 0; +static mem_map_t scat_low_mapping[32]; +static mem_map_t scat_ems_mapping[32]; +static mem_map_t scat_high_mapping[16]; +static scat_t scat_stat[32]; +static uint32_t scat_xms_bound; +static mem_map_t scat_remap_mapping[6]; +static mem_map_t scat_4000_EFFF_mapping[44]; +static mem_map_t scat_low_ROMCS_mapping[8]; -static const uint8_t scat_max_map[32] = { - 0, 1, 1, 1, 2, 3, 4, 8, - 4, 8, 12, 16, 20, 24, 28, 32, - 0, 5, 9, 13, 6, 10, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0 -}; - -static const uint8_t scatsx_max_map[32] = { - 0, 1, 2, 1, 3, 4, 6, 10, - 5, 9, 13, 4, 8, 12, 16, 14, - 18, 22, 26, 20, 24, 28, 32, 18, - 20, 32, 0, 0, 0, 0, 0, 0 -}; - -static const uint8_t scatsx_external_is_RAS[33] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1, 0, 0, 1, 1, - 0, 0, 0, 0, 0, 0, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 0 -}; - +static int scat_max_map[32] = { 0, 1, 1, 1, 2, 3, 4, 8, + 4, 8, 12, 16, 20, 24, 28, 32, + 0, 5, 9, 13, 6, 10, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 }; +static int scatsx_max_map[32] = { 0, 1, 2, 1, 3, 4, 6, 10, + 5, 9, 13, 4, 8, 12, 16, 14, + 18, 22, 26, 20, 24, 28, 32, 18, + 20, 32, 0, 0, 0, 0, 0, 0 }; static int external_is_RAS = 0; +static int scatsx_external_is_RAS[33] = { 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 1, 1, + 0, 0, 0, 0, 0, 0, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 0 }; + static uint8_t scat_read(uint16_t port, void *priv); static void scat_write(uint16_t port, uint8_t val, void *priv); static void -romcs_state_update(uint8_t val) +scat_romcs_state_update(uint8_t val) { int i; - - for (i = 0; i < 4; i++) { + for(i = 0; i < 4; i++) { if (val & 1) { - mem_mapping_enable(&scat_low_ROMCS_mapping[i << 1]); - mem_mapping_enable(&scat_low_ROMCS_mapping[(i << 1) + 1]); + mem_map_enable(&scat_low_ROMCS_mapping[i << 1]); + mem_map_enable(&scat_low_ROMCS_mapping[(i << 1) + 1]); } else { - mem_mapping_disable(&scat_low_ROMCS_mapping[i << 1]); - mem_mapping_disable(&scat_low_ROMCS_mapping[(i << 1) + 1]); + mem_map_disable(&scat_low_ROMCS_mapping[i << 1]); + mem_map_disable(&scat_low_ROMCS_mapping[(i << 1) + 1]); } val >>= 1; } - for (i = 0; i < 4; i++) { + for(i = 0; i < 4; i++) { if (val & 1) { - mem_mapping_enable(&bios_mapping[i << 1]); - mem_mapping_enable(&bios_mapping[(i << 1) + 1]); + mem_map_enable(&bios_mapping[i << 1]); + mem_map_enable(&bios_mapping[(i << 1) + 1]); } else { - mem_mapping_disable(&bios_mapping[i << 1]); - mem_mapping_disable(&bios_mapping[(i << 1) + 1]); + mem_map_disable(&bios_mapping[i << 1]); + mem_map_disable(&bios_mapping[(i << 1) + 1]); } val >>= 1; } @@ -156,7 +147,7 @@ romcs_state_update(uint8_t val) static void -shadow_state_update(void) +scat_shadow_state_update() { int i, val; @@ -170,72 +161,56 @@ shadow_state_update(void) static void -set_xms_bound(uint8_t val) +scat_set_xms_bound(uint8_t val) { uint32_t max_xms_size = ((scat_regs[SCAT_VERSION] & 0xF0) != 0 && ((val & 0x10) != 0)) || (scat_regs[SCAT_VERSION] >= 4) ? 0xFE0000 : 0xFC0000; - int i; switch (val & 0x0F) { case 1: scat_xms_bound = 0x100000; break; - case 2: scat_xms_bound = 0x140000; break; - case 3: scat_xms_bound = 0x180000; break; - case 4: scat_xms_bound = 0x200000; break; - case 5: scat_xms_bound = 0x300000; break; - case 6: scat_xms_bound = 0x400000; break; - case 7: scat_xms_bound = (scat_regs[SCAT_VERSION] & 0xF0) == 0 ? 0x600000 : 0x500000; break; - case 8: scat_xms_bound = (scat_regs[SCAT_VERSION] & 0xF0) == 0 ? 0x800000 : 0x700000; break; - case 9: scat_xms_bound = (scat_regs[SCAT_VERSION] & 0xF0) == 0 ? 0xA00000 : 0x800000; break; - case 10: scat_xms_bound = (scat_regs[SCAT_VERSION] & 0xF0) == 0 ? 0xC00000 : 0x900000; break; - case 11: scat_xms_bound = (scat_regs[SCAT_VERSION] & 0xF0) == 0 ? 0xE00000 : 0xA00000; break; - case 12: scat_xms_bound = (scat_regs[SCAT_VERSION] & 0xF0) == 0 ? max_xms_size : 0xB00000; break; - case 13: scat_xms_bound = (scat_regs[SCAT_VERSION] & 0xF0) == 0 ? max_xms_size : 0xC00000; break; - case 14: scat_xms_bound = (scat_regs[SCAT_VERSION] & 0xF0) == 0 ? max_xms_size : 0xD00000; break; - case 15: scat_xms_bound = (scat_regs[SCAT_VERSION] & 0xF0) == 0 ? max_xms_size : 0xF00000; break; - default: scat_xms_bound = max_xms_size; break; @@ -257,13 +232,14 @@ set_xms_bound(uint8_t val) mem_set_mem_state(scat_xms_bound, (mem_size << 10) - scat_xms_bound, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); } - mem_mapping_set_addr(&scat_low_mapping[31], 0xF80000, ((scat_regs[SCAT_VERSION] & 0xF0) != 0 && ((val & 0x10) != 0)) || (scat_regs[SCAT_VERSION] >= 4) ? 0x60000 : 0x40000); - if (scat_regs[SCAT_VERSION] & 0xF0) { - for (i = 0; i < 8; i++) { - if (val & 0x10) - mem_mapping_disable(&scat_high_mapping[i]); + mem_map_set_addr(&scat_low_mapping[31], 0xF80000, ((scat_regs[SCAT_VERSION] & 0xF0) != 0 && ((val & 0x10) != 0)) || (scat_regs[SCAT_VERSION] >= 4) ? 0x60000 : 0x40000); + if(scat_regs[SCAT_VERSION] & 0xF0) { + int i; + for(i=0;i<8;i++) { + if(val & 0x10) + mem_map_disable(&scat_high_mapping[i]); else - mem_mapping_enable(&scat_high_mapping[i]); + mem_map_enable(&scat_high_mapping[i]); } } } @@ -281,78 +257,69 @@ get_scat_addr(uint32_t addr, scat_t *p) switch((scat_regs[SCAT_EXTENDED_BOUNDARY] & ((scat_regs[SCAT_VERSION] & 0x0F) > 3 ? 0x40 : 0)) | (scat_regs[SCAT_DRAM_CONFIGURATION] & 0x0F)) { case 0x41: nbank = addr >> 19; - if (nbank < 4) + if(nbank < 4) nbank = 1; - else if (nbank == 4) + else if(nbank == 4) nbank = 0; else nbank -= 3; break; - case 0x42: nbank = addr >> 19; - if (nbank < 8) + if(nbank < 8) nbank = 1 + (nbank >> 2); - else if (nbank == 8) + else if(nbank == 8) nbank = 0; else nbank -= 6; break; - case 0x43: nbank = addr >> 19; - if (nbank < 12) + if(nbank < 12) nbank = 1 + (nbank >> 2); - else if (nbank == 12) + else if(nbank == 12) nbank = 0; else nbank -= 9; break; - case 0x44: nbank = addr >> 19; - if (nbank < 4) + if(nbank < 4) nbank = 2; - else if (nbank < 6) + else if(nbank < 6) nbank -= 4; else nbank -= 3; break; - case 0x45: nbank = addr >> 19; - if (nbank < 8) + if(nbank < 8) nbank = 2 + (nbank >> 2); - else if (nbank < 10) + else if(nbank < 10) nbank -= 8; else nbank -= 6; break; - default: nbank = addr >> (((scat_regs[SCAT_DRAM_CONFIGURATION] & 0x0F) < 8 && (scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x40) == 0) ? 19 : 21); break; } nbank &= (scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x80) ? 7 : 3; - - if ((scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x40) == 0 && - (scat_regs[SCAT_DRAM_CONFIGURATION] & 0x0F) == 3 && nbank == 2 && - (addr & 0x7FFFF) < 0x60000 && mem_size > 640) { + if ((scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x40) == 0 && (scat_regs[SCAT_DRAM_CONFIGURATION] & 0x0F) == 3 && nbank == 2 && (addr & 0x7FFFF) < 0x60000 && mem_size > 640) { nbank = 1; addr ^= 0x70000; } - if (external_is_RAS && (scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x80) == 0) { - if (nbank == 3) + if(external_is_RAS && (scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x80) == 0) { + if(nbank == 3) nbank = 7; else return 0xFFFFFFFF; - } else if (!external_is_RAS && scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x80) { + } else if(!external_is_RAS && scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x80) { switch(nbank) { case 7: nbank = 3; break; - /* Note - In the following cases, the chipset accesses multiple memory banks at the same time, so it's impossible to predict which memory bank is actually accessed. */ @@ -360,33 +327,29 @@ get_scat_addr(uint32_t addr, scat_t *p) case 1: nbank = 1; break; - case 3: nbank = 2; break; - default: nbank = 0; break; } } - if ((scat_regs[SCAT_VERSION] & 0x0F) > 3 && - (mem_size > 2048) && (mem_size & 1536)) { - if ((mem_size & 1536) == 512) { - if (nbank == 0) + if((scat_regs[SCAT_VERSION] & 0x0F) > 3 && (mem_size > 2048) && (mem_size & 1536)) { + if((mem_size & 1536) == 512) { + if(nbank == 0) addr &= 0x7FFFF; else addr = 0x80000 + ((addr & 0x1FFFFF) | ((nbank - 1) << 21)); } else { - if (nbank < 2) + if(nbank < 2) addr = (addr & 0x7FFFF) | (nbank << 19); else addr = 0x100000 + ((addr & 0x1FFFFF) | ((nbank - 2) << 21)); } } else { int nbanks_2048k, nbanks_512k; - if (mem_size <= ((scat_regs[SCAT_VERSION] & 0x0F) > 3 ? 2048 : 4096) && (((scat_regs[SCAT_DRAM_CONFIGURATION] & 0x0F) < 8) || external_is_RAS)) { nbanks_2048k = 0; nbanks_512k = mem_size >> 9; @@ -394,11 +357,10 @@ get_scat_addr(uint32_t addr, scat_t *p) nbanks_2048k = mem_size >> 11; nbanks_512k = (mem_size & 1536) >> 9; } - - if (nbank < nbanks_2048k || (nbanks_2048k > 0 && nbank >= nbanks_2048k + nbanks_512k + ((mem_size & 511) >> 7))) { + if(nbank < nbanks_2048k || (nbanks_2048k > 0 && nbank >= nbanks_2048k + nbanks_512k + ((mem_size & 511) >> 7))) { addr &= 0x1FFFFF; addr |= (nbank << 21); - } else if (nbank < nbanks_2048k + nbanks_512k || nbank >= nbanks_2048k + nbanks_512k + ((mem_size & 511) >> 7)) { + } else if(nbank < nbanks_2048k + nbanks_512k || nbank >= nbanks_2048k + nbanks_512k + ((mem_size & 511) >> 7)) { addr &= 0x7FFFF; addr |= (nbanks_2048k << 21) | ((nbank - nbanks_2048k) << 19); } else { @@ -408,43 +370,39 @@ get_scat_addr(uint32_t addr, scat_t *p) } } else { uint32_t addr2; - - switch (scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F) { + switch(scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F) { case 2: case 4: nbank = addr >> 19; - if ((nbank & (scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x80 ? 7 : 3)) < 2) { + if((nbank & (scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x80 ? 7 : 3)) < 2) { nbank = (addr >> 10) & 1; addr2 = addr >> 11; } else addr2 = addr >> 10; break; - case 3: nbank = addr >> 19; - if ((nbank & (scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x80 ? 7 : 3)) < 2) { + if((nbank & (scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x80 ? 7 : 3)) < 2) { nbank = (addr >> 10) & 1; addr2 = addr >> 11; - } else if ((nbank & (scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x80 ? 7 : 3)) == 2 && (addr & 0x7FFFF) < 0x60000) { + } else if((nbank & (scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x80 ? 7 : 3)) == 2 && (addr & 0x7FFFF) < 0x60000) { addr ^= 0x1F0000; nbank = (addr >> 10) & 1; addr2 = addr >> 11; } else addr2 = addr >> 10; break; - case 5: nbank = addr >> 19; - if ((nbank & (scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x80 ? 7 : 3)) < 4) { + if((nbank & (scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x80 ? 7 : 3)) < 4) { nbank = (addr >> 10) & 3; addr2 = addr >> 12; } else addr2 = addr >> 10; break; - case 6: nbank = addr >> 19; - if (nbank < 2) { + if(nbank < 2) { nbank = (addr >> 10) & 1; addr2 = addr >> 11; } else { @@ -452,14 +410,13 @@ get_scat_addr(uint32_t addr, scat_t *p) addr2 = (addr - 0x100000) >> 11; } break; - case 7: case 0x0F: nbank = addr >> 19; - if (nbank < 2) { + if(nbank < 2) { nbank = (addr >> 10) & 1; addr2 = addr >> 11; - } else if (nbank < 10) { + } else if(nbank < 10) { nbank = 2 + (((addr - 0x100000) >> 11) & 1); addr2 = (addr - 0x100000) >> 12; } else { @@ -467,13 +424,12 @@ get_scat_addr(uint32_t addr, scat_t *p) addr2 = (addr - 0x500000) >> 11; } break; - case 8: nbank = addr >> 19; - if (nbank < 4) { + if(nbank < 4) { nbank = 1; addr2 = addr >> 11; - } else if (nbank == 4) { + } else if(nbank == 4) { nbank = 0; addr2 = addr >> 10; } else { @@ -483,10 +439,10 @@ get_scat_addr(uint32_t addr, scat_t *p) break; case 9: nbank = addr >> 19; - if (nbank < 8) { + if(nbank < 8) { nbank = 1 + ((addr >> 11) & 1); addr2 = addr >> 12; - } else if (nbank == 8) { + } else if(nbank == 8) { nbank = 0; addr2 = addr >> 10; } else { @@ -494,16 +450,15 @@ get_scat_addr(uint32_t addr, scat_t *p) addr2 = addr >> 10; } break; - case 0x0A: nbank = addr >> 19; - if (nbank < 8) { + if(nbank < 8) { nbank = 1 + ((addr >> 11) & 1); addr2 = addr >> 12; - } else if (nbank < 12) { + } else if(nbank < 12) { nbank = 3; addr2 = addr >> 11; - } else if (nbank == 12) { + } else if(nbank == 12) { nbank = 0; addr2 = addr >> 10; } else { @@ -511,42 +466,38 @@ get_scat_addr(uint32_t addr, scat_t *p) addr2 = addr >> 10; } break; - case 0x0B: nbank = addr >> 21; addr2 = addr >> 11; break; - case 0x0C: case 0x0D: nbank = addr >> 21; - if ((nbank & (scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x80 ? 7 : 3)) < 2) { + if((nbank & (scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x80 ? 7 : 3)) < 2) { nbank = (addr >> 11) & 1; addr2 = addr >> 12; } else addr2 = addr >> 11; break; - case 0x0E: case 0x13: nbank = addr >> 21; - if ((nbank & (scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x80 ? 7 : 3)) < 4) { + if((nbank & (scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x80 ? 7 : 3)) < 4) { nbank = (addr >> 11) & 3; addr2 = addr >> 13; } else addr2 = addr >> 11; break; - case 0x10: case 0x11: nbank = addr >> 19; - if (nbank < 2) { + if(nbank < 2) { nbank = (addr >> 10) & 1; addr2 = addr >> 11; - } else if (nbank < 10) { + } else if(nbank < 10) { nbank = 2 + (((addr - 0x100000) >> 11) & 1); addr2 = (addr - 0x100000) >> 12; - } else if (nbank < 18) { + } else if(nbank < 18) { nbank = 4 + (((addr - 0x500000) >> 11) & 1); addr2 = (addr - 0x500000) >> 12; } else { @@ -554,13 +505,12 @@ get_scat_addr(uint32_t addr, scat_t *p) addr2 = (addr - 0x900000) >> 11; } break; - case 0x12: nbank = addr >> 19; - if (nbank < 2) { + if(nbank < 2) { nbank = (addr >> 10) & 1; addr2 = addr >> 11; - } else if (nbank < 10) { + } else if(nbank < 10) { nbank = 2 + (((addr - 0x100000) >> 11) & 1); addr2 = (addr - 0x100000) >> 12; } else { @@ -568,14 +518,13 @@ get_scat_addr(uint32_t addr, scat_t *p) addr2 = (addr - 0x500000) >> 13; } break; - case 0x14: case 0x15: nbank = addr >> 21; - if ((nbank & 7) < 4) { + if((nbank & 7) < 4) { nbank = (addr >> 11) & 3; addr2 = addr >> 13; - } else if ((nbank & 7) < 6) { + } else if((nbank & 7) < 6) { nbank = 4 + (((addr - 0x800000) >> 11) & 1); addr2 = (addr - 0x800000) >> 12; } else { @@ -583,17 +532,15 @@ get_scat_addr(uint32_t addr, scat_t *p) addr2 = (addr - 0xC00000) >> 13; } break; - case 0x16: nbank = ((addr >> 21) & 4) | ((addr >> 11) & 3); addr2 = addr >> 13; break; - case 0x17: - if (external_is_RAS && (addr & 0x800) == 0) + if(external_is_RAS && (addr & 0x800) == 0) return 0xFFFFFFFF; nbank = addr >> 19; - if (nbank < 2) { + if(nbank < 2) { nbank = (addr >> 10) & 1; addr2 = addr >> 11; } else { @@ -601,15 +548,14 @@ get_scat_addr(uint32_t addr, scat_t *p) addr2 = (addr - 0x100000) >> 12; } break; - case 0x18: - if (external_is_RAS && (addr & 0x800) == 0) + if(external_is_RAS && (addr & 0x800) == 0) return 0xFFFFFFFF; nbank = addr >> 21; - if (nbank < 4) { + if(nbank < 4) { nbank = 1; addr2 = addr >> 12; - } else if (nbank == 4) { + } else if(nbank == 4) { nbank = 0; addr2 = addr >> 11; } else { @@ -617,23 +563,21 @@ get_scat_addr(uint32_t addr, scat_t *p) addr2 = addr >> 11; } break; - case 0x19: - if (external_is_RAS && (addr & 0x800) == 0) + if(external_is_RAS && (addr & 0x800) == 0) return 0xFFFFFFFF; nbank = addr >> 23; - if ((nbank & 3) < 2) { + if((nbank & 3) < 2) { nbank = (addr >> 12) & 1; addr2 = addr >> 13; } else addr2 = addr >> 12; break; - default: - if ((scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F) < 6) { + if((scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F) < 6) { nbank = addr >> 19; addr2 = (addr >> 10) & 0x1FF; - } else if ((scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F) < 0x17) { + } else if((scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F) < 0x17) { nbank = addr >> 21; addr2 = (addr >> 11) & 0x3FF; } else { @@ -647,17 +591,16 @@ get_scat_addr(uint32_t addr, scat_t *p) if ((scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F) > 0x16 && nbank == 3) return 0xFFFFFFFF; - if (external_is_RAS && (scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x80) == 0) { - if (nbank == 3) + if(external_is_RAS && (scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x80) == 0) { + if(nbank == 3) nbank = 7; else return 0xFFFFFFFF; - } else if (!external_is_RAS && scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x80) { + } else if(!external_is_RAS && scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x80) { switch(nbank) { case 7: nbank = 3; break; - /* Note - In the following cases, the chipset accesses multiple memory banks at the same time, so it's impossible to predict which memory bank is actually accessed. */ @@ -665,11 +608,9 @@ get_scat_addr(uint32_t addr, scat_t *p) case 1: nbank = 1; break; - case 3: nbank = 2; break; - default: nbank = 0; break; @@ -680,16 +621,15 @@ get_scat_addr(uint32_t addr, scat_t *p) case 1024: case 1536: addr &= 0x3FF; - if (nbank < 2) + if(nbank < 2) addr |= (nbank << 10) | ((addr2 & 0x1FF) << 11); else addr |= ((addr2 & 0x1FF) << 10) | (nbank << 19); break; - case 2048: - if ((scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F) == 5) { + if((scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F) == 5) { addr &= 0x3FF; - if (nbank < 4) + if(nbank < 4) addr |= (nbank << 10) | ((addr2 & 0x1FF) << 12); else addr |= ((addr2 & 0x1FF) << 10) | (nbank << 19); @@ -698,9 +638,8 @@ get_scat_addr(uint32_t addr, scat_t *p) addr |= ((addr2 & 0x3FF) << 11) | (nbank << 21); } break; - case 2560: - if (nbank == 0) + if(nbank == 0) addr = (addr & 0x3FF) | ((addr2 & 0x1FF) << 10); else { addr &= 0x7FF; @@ -708,32 +647,29 @@ get_scat_addr(uint32_t addr, scat_t *p) addr = addr + 0x80000 + ((addr2 << 11) | ((nbank - 1) << 21)); } break; - case 3072: - if (nbank < 2) + if(nbank < 2) addr = (addr & 0x3FF) | (nbank << 10) | ((addr2 & 0x1FF) << 11); else addr = 0x100000 + ((addr & 0x7FF) | ((addr2 & 0x3FF) << 11) | ((nbank - 2) << 21)); break; - case 4096: case 6144: addr &= 0x7FF; - if (nbank < 2) + if(nbank < 2) addr |= (nbank << 11) | ((addr2 & 0x3FF) << 12); else addr |= ((addr2 & 0x3FF) << 11) | (nbank << 21); break; - case 4608: - if (((scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F) >= 8 && (scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F) <= 0x0A) || ((scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F) == 0x18)) { - if (nbank == 0) + if(((scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F) >= 8 && (scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F) <= 0x0A) || ((scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F) == 0x18)) { + if(nbank == 0) addr = (addr & 0x3FF) | ((addr2 & 0x1FF) << 10); - else if (nbank < 3) + else if(nbank < 3) addr = 0x80000 + ((addr & 0x7FF) | ((nbank - 1) << 11) | ((addr2 & 0x3FF) << 12)); else addr = 0x480000 + ((addr & 0x3FF) | ((addr2 & 0x1FF) << 10) | ((nbank - 3) << 19)); - } else if (nbank == 0) + } else if(nbank == 0) addr = (addr & 0x3FF) | ((addr2 & 0x1FF) << 10); else { addr &= 0x7FF; @@ -741,7 +677,6 @@ get_scat_addr(uint32_t addr, scat_t *p) addr = addr + 0x80000 + ((addr2 << 11) | ((nbank - 1) << 21)); } break; - case 5120: case 7168: if(nbank < 2) @@ -883,108 +818,106 @@ get_scat_addr(uint32_t addr, scat_t *p) static void -set_global_EMS_state(int state) +scat_set_global_EMS_state(int state) { - uint32_t base_addr, virt_addr; int i; + uint32_t base_addr, virt_addr; - for (i=((scat_regs[SCAT_VERSION] & 0xF0) == 0) ? 0 : 24; i<32; i++) { + for(i=((scat_regs[SCAT_VERSION] & 0xF0) == 0) ? 0 : 24; i<32; i++) { base_addr = (i + 16) << 14; if(i >= 24) base_addr += 0x30000; if(state && (scat_stat[i].regs_2x9 & 0x80)) { virt_addr = get_scat_addr(base_addr, &scat_stat[i]); - if(i < 24) mem_mapping_disable(&scat_4000_EFFF_mapping[i]); - else mem_mapping_disable(&scat_4000_EFFF_mapping[i + 12]); - mem_mapping_enable(&scat_ems_mapping[i]); - if(virt_addr < ((uint32_t)mem_size << 10)) mem_mapping_set_exec(&scat_ems_mapping[i], ram + virt_addr); - else mem_mapping_set_exec(&scat_ems_mapping[i], NULL); + if(i < 24) mem_map_disable(&scat_4000_EFFF_mapping[i]); + else mem_map_disable(&scat_4000_EFFF_mapping[i + 12]); + mem_map_enable(&scat_ems_mapping[i]); + if(virt_addr < ((uint32_t)mem_size << 10)) mem_map_set_exec(&scat_ems_mapping[i], ram + virt_addr); + else mem_map_set_exec(&scat_ems_mapping[i], NULL); } else { - mem_mapping_set_exec(&scat_ems_mapping[i], ram + base_addr); - mem_mapping_disable(&scat_ems_mapping[i]); + mem_map_set_exec(&scat_ems_mapping[i], ram + base_addr); + mem_map_disable(&scat_ems_mapping[i]); int conf = (scat_regs[SCAT_VERSION] & 0xF0) ? (scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F) : (scat_regs[SCAT_DRAM_CONFIGURATION] & 0xF) | ((scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x40) >> 2); if(i < 24) { if(conf > 1 || (conf == 1 && i < 16)) - mem_mapping_enable(&scat_4000_EFFF_mapping[i]); + mem_map_enable(&scat_4000_EFFF_mapping[i]); else - mem_mapping_disable(&scat_4000_EFFF_mapping[i]); + mem_map_disable(&scat_4000_EFFF_mapping[i]); } else if(conf > 3 || ((scat_regs[SCAT_VERSION] & 0xF0) != 0 && conf == 2)) - mem_mapping_enable(&scat_4000_EFFF_mapping[i + 12]); + mem_map_enable(&scat_4000_EFFF_mapping[i + 12]); else - mem_mapping_disable(&scat_4000_EFFF_mapping[i + 12]); + mem_map_disable(&scat_4000_EFFF_mapping[i + 12]); } } - flushmmucache(); } static void -memmap_state_update(void) +scat_memmap_state_update() { - uint32_t addr; int i; + uint32_t addr; - for (i= (((scat_regs[SCAT_VERSION] & 0xF0) == 0) ? 0 : 16);i<44;i++) { + for(i=(((scat_regs[SCAT_VERSION] & 0xF0) == 0) ? 0 : 16);i<44;i++) { addr = get_scat_addr(0x40000 + (i << 14), NULL); - mem_mapping_set_exec(&scat_4000_EFFF_mapping[i], addr < ((uint32_t)mem_size << 10) ? ram + addr : NULL); + mem_map_set_exec(&scat_4000_EFFF_mapping[i], addr < ((uint32_t)mem_size << 10) ? ram + addr : NULL); } addr = get_scat_addr(0, NULL); - mem_mapping_set_exec(&scat_low_mapping[0], addr < ((uint32_t)mem_size << 10) ? ram + addr : NULL); + mem_map_set_exec(&scat_low_mapping[0], addr < ((uint32_t)mem_size << 10) ? ram + addr : NULL); addr = get_scat_addr(0xF0000, NULL); - mem_mapping_set_exec(&scat_low_mapping[1], addr < ((uint32_t)mem_size << 10) ? ram + addr : NULL); - - for (i = 2; i < 32; i++) { + mem_map_set_exec(&scat_low_mapping[1], addr < ((uint32_t)mem_size << 10) ? ram + addr : NULL); + for(i=2;i<32;i++) { addr = get_scat_addr(i << 19, NULL); - mem_mapping_set_exec(&scat_low_mapping[i], addr < ((uint32_t)mem_size << 10) ? ram + addr : NULL); + mem_map_set_exec(&scat_low_mapping[i], addr < ((uint32_t)mem_size << 10) ? ram + addr : NULL); } if((scat_regs[SCAT_VERSION] & 0xF0) == 0) { for(i=0;i < scat_max_map[(scat_regs[SCAT_DRAM_CONFIGURATION] & 0xF) | ((scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x40) >> 2)];i++) - mem_mapping_enable(&scat_low_mapping[i]); - for(;i<32;i++) mem_mapping_disable(&scat_low_mapping[i]); + mem_map_enable(&scat_low_mapping[i]); + for(;i<32;i++) mem_map_disable(&scat_low_mapping[i]); for(i=24;i<36;i++) { if(((scat_regs[SCAT_DRAM_CONFIGURATION] & 0xF) | (scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x40)) < 4) - mem_mapping_disable(&scat_4000_EFFF_mapping[i]); + mem_map_disable(&scat_4000_EFFF_mapping[i]); else - mem_mapping_enable(&scat_4000_EFFF_mapping[i]); + mem_map_enable(&scat_4000_EFFF_mapping[i]); } } else { for(i=0;i < scatsx_max_map[scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F];i++) - mem_mapping_enable(&scat_low_mapping[i]); - for(;i<32;i++) mem_mapping_disable(&scat_low_mapping[i]); + mem_map_enable(&scat_low_mapping[i]); + for(;i<32;i++) mem_map_disable(&scat_low_mapping[i]); for(i=24;i<36;i++) { if((scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F) < 2 || (scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F) == 3) - mem_mapping_disable(&scat_4000_EFFF_mapping[i]); + mem_map_disable(&scat_4000_EFFF_mapping[i]); else - mem_mapping_enable(&scat_4000_EFFF_mapping[i]); + mem_map_enable(&scat_4000_EFFF_mapping[i]); } } if((((scat_regs[SCAT_VERSION] & 0xF0) == 0) && (scat_regs[SCAT_EXTENDED_BOUNDARY] & 0x40) == 0) || ((scat_regs[SCAT_VERSION] & 0xF0) != 0)) { if((((scat_regs[SCAT_VERSION] & 0xF0) == 0) && (scat_regs[SCAT_DRAM_CONFIGURATION] & 0x0F) == 3) || (((scat_regs[SCAT_VERSION] & 0xF0) != 0) && (scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F) == 3)) { - mem_mapping_disable(&scat_low_mapping[2]); + mem_map_disable(&scat_low_mapping[2]); for(i=0;i<6;i++) { addr = get_scat_addr(0x100000 + (i << 16), NULL); - mem_mapping_set_exec(&scat_remap_mapping[i], addr < ((uint32_t)mem_size << 10) ? ram + addr : NULL); - mem_mapping_enable(&scat_remap_mapping[i]); + mem_map_set_exec(&scat_remap_mapping[i], addr < ((uint32_t)mem_size << 10) ? ram + addr : NULL); + mem_map_enable(&scat_remap_mapping[i]); } } else { for(i=0;i<6;i++) - mem_mapping_disable(&scat_remap_mapping[i]); + mem_map_disable(&scat_remap_mapping[i]); if((((scat_regs[SCAT_VERSION] & 0xF0) == 0) && (scat_regs[SCAT_DRAM_CONFIGURATION] & 0x0F) > 4) || (((scat_regs[SCAT_VERSION] & 0xF0) != 0) && (scat_regs[SCAT_DRAM_CONFIGURATION] & 0x1F) > 3)) - mem_mapping_enable(&scat_low_mapping[2]); + mem_map_enable(&scat_low_mapping[2]); } } else { for(i=0;i<6;i++) - mem_mapping_disable(&scat_remap_mapping[i]); - mem_mapping_enable(&scat_low_mapping[2]); + mem_map_disable(&scat_remap_mapping[i]); + mem_map_enable(&scat_low_mapping[2]); } - set_global_EMS_state(scat_regs[SCAT_EMS_CONTROL] & 0x80); + scat_set_global_EMS_state(scat_regs[SCAT_EMS_CONTROL] & 0x80); } @@ -1019,7 +952,7 @@ scat_write(uint16_t port, uint8_t val, void *priv) io_removehandler(0x0208, 0x0003, scat_read, NULL, NULL, scat_write, NULL, NULL, NULL); io_removehandler(0x0218, 0x0003, scat_read, NULL, NULL, scat_write, NULL, NULL, NULL); } - set_global_EMS_state(val & 0x80); + scat_set_global_EMS_state(val & 0x80); scat_reg_valid = 1; break; case SCAT_POWER_MANAGEMENT: @@ -1042,20 +975,20 @@ scat_write(uint16_t port, uint8_t val, void *priv) if((scat_regs[SCAT_VERSION] & 0xF0) == 0) { if(scat_regs[SCAT_VERSION] < 4) { val &= 0xBF; - set_xms_bound(val & 0x0f); + scat_set_xms_bound(val & 0x0f); } else { val = (val & 0x7F) | 0x80; - set_xms_bound(val & 0x4f); + scat_set_xms_bound(val & 0x4f); } } else - set_xms_bound(val & 0x1f); + scat_set_xms_bound(val & 0x1f); mem_set_mem_state(0x40000, 0x60000, (val & 0x20) ? MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL : MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); if((val ^ scat_regs[SCAT_EXTENDED_BOUNDARY]) & 0xC0) scat_map_update = 1; scat_reg_valid = 1; break; case SCAT_ROM_ENABLE: scat_reg_valid = 1; - romcs_state_update(val); + scat_romcs_state_update(val); break; case SCAT_RAM_WRITE_PROTECT: scat_reg_valid = 1; @@ -1085,9 +1018,9 @@ scat_write(uint16_t port, uint8_t val, void *priv) if (scat_reg_valid) scat_regs[scat_index] = val; if (scat_shadow_update) - shadow_state_update(); + scat_shadow_state_update(); if (scat_map_update) - memmap_state_update(); + scat_memmap_state_update(); break; case 0x92: @@ -1114,8 +1047,8 @@ scat_write(uint16_t port, uint8_t val, void *priv) if((scat_regs[SCAT_EMS_CONTROL] & 0x80) && (scat_stat[index].regs_2x9 & 0x80)) { virt_addr = get_scat_addr(base_addr, &scat_stat[index]); - if(virt_addr < ((uint32_t)mem_size << 10)) mem_mapping_set_exec(&scat_ems_mapping[index], ram + virt_addr); - else mem_mapping_set_exec(&scat_ems_mapping[index], NULL); + if(virt_addr < ((uint32_t)mem_size << 10)) mem_map_set_exec(&scat_ems_mapping[index], ram + virt_addr); + else mem_map_set_exec(&scat_ems_mapping[index], NULL); flushmmucache(); } } @@ -1133,16 +1066,16 @@ scat_write(uint16_t port, uint8_t val, void *priv) if (scat_regs[SCAT_EMS_CONTROL] & 0x80) { if (val & 0x80) { virt_addr = get_scat_addr(base_addr, &scat_stat[index]); - if(index < 24) mem_mapping_disable(&scat_4000_EFFF_mapping[index]); - else mem_mapping_disable(&scat_4000_EFFF_mapping[index + 12]); - if(virt_addr < ((uint32_t)mem_size << 10)) mem_mapping_set_exec(&scat_ems_mapping[index], ram + virt_addr); - else mem_mapping_set_exec(&scat_ems_mapping[index], NULL); - mem_mapping_enable(&scat_ems_mapping[index]); + if(index < 24) mem_map_disable(&scat_4000_EFFF_mapping[index]); + else mem_map_disable(&scat_4000_EFFF_mapping[index + 12]); + if(virt_addr < ((uint32_t)mem_size << 10)) mem_map_set_exec(&scat_ems_mapping[index], ram + virt_addr); + else mem_map_set_exec(&scat_ems_mapping[index], NULL); + mem_map_enable(&scat_ems_mapping[index]); } else { - mem_mapping_set_exec(&scat_ems_mapping[index], ram + base_addr); - mem_mapping_disable(&scat_ems_mapping[index]); - if(index < 24) mem_mapping_enable(&scat_4000_EFFF_mapping[index]); - else mem_mapping_enable(&scat_4000_EFFF_mapping[index + 12]); + mem_map_set_exec(&scat_ems_mapping[index], ram + base_addr); + mem_map_disable(&scat_ems_mapping[index]); + if(index < 24) mem_map_enable(&scat_4000_EFFF_mapping[index]); + else mem_map_enable(&scat_4000_EFFF_mapping[index + 12]); } flushmmucache(); } @@ -1310,22 +1243,20 @@ mem_write_scatl(uint32_t addr, uint32_t val, void *priv) static void -scat_init(void) +scat_common_init(int type) { int i; - io_sethandler(0x0022, 2, - scat_read, NULL, NULL, scat_write, NULL, NULL, NULL); - io_sethandler(0x0092, 1, - scat_read, NULL, NULL, scat_write, NULL, NULL, NULL); + io_sethandler(0x0022, 0x0002, scat_read, NULL, NULL, scat_write, NULL, NULL, NULL); + io_sethandler(0x0092, 0x0001, scat_read, NULL, NULL, scat_write, NULL, NULL, NULL); for (i = 0; i < 256; i++) scat_regs[i] = 0xff; scat_regs[SCAT_DMA_WAIT_STATE_CONTROL] = 0; - switch(romset) { - case ROM_GW286CT: - case ROM_SPC4216P: + switch(type) { + case 1: + case 2: scat_regs[SCAT_VERSION] = 4; break; @@ -1333,7 +1264,6 @@ scat_init(void) scat_regs[SCAT_VERSION] = 1; break; } - scat_regs[SCAT_CLOCK_CONTROL] = 2; scat_regs[SCAT_PERIPHERAL_CONTROL] = 0x80; scat_regs[SCAT_MISCELLANEOUS_STATUS] = 0x37; @@ -1348,54 +1278,85 @@ scat_init(void) scat_regs[SCAT_EMS_CONTROL] = 0; scat_port_92 = 0; - mem_mapping_disable(&ram_low_mapping); - mem_mapping_disable(&ram_high_mapping); + mem_map_disable(&ram_low_mapping); + mem_map_disable(&ram_mid_mapping); + mem_map_disable(&ram_high_mapping); for (i = 0; i < 4; i++) - mem_mapping_disable(&bios_mapping[i]); - mem_mapping_add(&scat_low_mapping[0], 0, 0x40000, mem_read_scatb, mem_read_scatw, mem_read_scatl, mem_write_scatb, mem_write_scatw, mem_write_scatl, ram, MEM_MAPPING_INTERNAL, NULL); - mem_mapping_add(&scat_low_mapping[1], 0xF0000, 0x10000, mem_read_scatb, mem_read_scatw, mem_read_scatl, mem_write_scatb, mem_write_scatw, mem_write_scatl, ram + 0xF0000, MEM_MAPPING_INTERNAL, NULL); + mem_map_disable(&bios_mapping[i]); + mem_map_add(&scat_low_mapping[0], 0, 0x40000, mem_read_scatb, mem_read_scatw, mem_read_scatl, mem_write_scatb, mem_write_scatw, mem_write_scatl, ram, MEM_MAPPING_INTERNAL, NULL); + mem_map_add(&scat_low_mapping[1], 0xF0000, 0x10000, mem_read_scatb, mem_read_scatw, mem_read_scatl, mem_write_scatb, mem_write_scatw, mem_write_scatl, ram + 0xF0000, MEM_MAPPING_INTERNAL, NULL); for(i=2;i<32;i++) - mem_mapping_add(&scat_low_mapping[i], (i << 19), 0x80000, mem_read_scatb, mem_read_scatw, mem_read_scatl, mem_write_scatb, mem_write_scatw, mem_write_scatl, ram + (i << 19), MEM_MAPPING_INTERNAL, NULL); - mem_mapping_set_addr(&scat_low_mapping[31], 0xF80000, scat_regs[SCAT_VERSION] < 4 ? 0x40000 : 0x60000); + mem_map_add(&scat_low_mapping[i], (i << 19), 0x80000, mem_read_scatb, mem_read_scatw, mem_read_scatl, mem_write_scatb, mem_write_scatw, mem_write_scatl, ram + (i << 19), MEM_MAPPING_INTERNAL, NULL); + mem_map_set_addr(&scat_low_mapping[31], 0xF80000, scat_regs[SCAT_VERSION] < 4 ? 0x40000 : 0x60000); for (i = 0; i < 44; i++) - mem_mapping_add(&scat_4000_EFFF_mapping[i], 0x40000 + (i << 14), 0x4000, mem_read_scatb, mem_read_scatw, mem_read_scatl, mem_write_scatb, mem_write_scatw, mem_write_scatl, mem_size > 256 + (i << 4) ? ram + 0x40000 + (i << 14) : NULL, MEM_MAPPING_INTERNAL, NULL); + mem_map_add(&scat_4000_EFFF_mapping[i], 0x40000 + (i << 14), 0x4000, mem_read_scatb, mem_read_scatw, mem_read_scatl, mem_write_scatb, mem_write_scatw, mem_write_scatl, mem_size > 256 + (i << 4) ? ram + 0x40000 + (i << 14) : NULL, MEM_MAPPING_INTERNAL, NULL); for (i = 0; i < 8; i++) { - mem_mapping_add(&scat_low_ROMCS_mapping[i], 0xC0000 + (i << 14), 0x4000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + ((i << 14) & biosmask), MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROM, NULL); - mem_mapping_disable(&scat_low_ROMCS_mapping[i]); + mem_map_add(&scat_low_ROMCS_mapping[i], 0xC0000 + (i << 14), 0x4000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + ((i << 14) & biosmask), MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROM, NULL); + mem_map_disable(&scat_low_ROMCS_mapping[i]); } for (i = 0; i < 32; i++) { scat_stat[i].regs_2x8 = 0xff; scat_stat[i].regs_2x9 = 0x03; - mem_mapping_add(&scat_ems_mapping[i], (i + (i >= 24 ? 28 : 16)) << 14, 0x04000, mem_read_scatb, mem_read_scatw, mem_read_scatl, mem_write_scatb, mem_write_scatw, mem_write_scatl, ram + ((i + (i >= 24 ? 28 : 16)) << 14), 0, &scat_stat[i]); + mem_map_add(&scat_ems_mapping[i], (i + (i >= 24 ? 28 : 16)) << 14, 0x04000, mem_read_scatb, mem_read_scatw, mem_read_scatl, mem_write_scatb, mem_write_scatw, mem_write_scatl, ram + ((i + (i >= 24 ? 28 : 16)) << 14), 0, &scat_stat[i]); } for (i = (scat_regs[SCAT_VERSION] < 4 ? 0 : 8); i < 16; i++) { - mem_mapping_add(&scat_high_mapping[i], (i << 14) + 0xFC0000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + ((i << 14) & biosmask), 0, NULL); - mem_mapping_enable(&scat_high_mapping[i]); + mem_map_add(&scat_high_mapping[i], (i << 14) + 0xFC0000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + ((i << 14) & biosmask), 0, NULL); + mem_map_enable(&scat_high_mapping[i]); } for(i=0;i<6;i++) - mem_mapping_add(&scat_remap_mapping[i], 0x100000 + (i << 16), 0x10000, mem_read_scatb, mem_read_scatw, mem_read_scatl, mem_write_scatb, mem_write_scatw, mem_write_scatl, mem_size >= 1024 ? ram + get_scat_addr(0x100000 + (i << 16), NULL) : NULL, MEM_MAPPING_INTERNAL, NULL); + mem_map_add(&scat_remap_mapping[i], 0x100000 + (i << 16), 0x10000, mem_read_scatb, mem_read_scatw, mem_read_scatl, mem_write_scatb, mem_write_scatw, mem_write_scatl, mem_size >= 1024 ? ram + get_scat_addr(0x100000 + (i << 16), NULL) : NULL, MEM_MAPPING_INTERNAL, NULL); external_is_RAS = (scat_regs[SCAT_VERSION] > 3) || (((mem_size & ~2047) >> 11) + ((mem_size & 1536) >> 9) + ((mem_size & 511) >> 7)) > 4; - set_xms_bound(0); - memmap_state_update(); - shadow_state_update(); + scat_set_xms_bound(0); + scat_memmap_state_update(); + scat_shadow_state_update(); +} + + +void +machine_at_scat_init(const machine_t *model, void *arg) +{ + machine_at_init(model, arg); + device_add(&fdc_at_device); + + scat_common_init(0); +} + + +void +machine_at_scat_gw286ct_init(const machine_t *model, void *arg) +{ + machine_at_init(model, arg); + + device_add(&fdc_at_device); + + scat_common_init(1); +} + + +void +machine_at_scat_spc4216p_init(const machine_t *model, void *arg) +{ + machine_at_init(model, arg); + + device_add(&fdc_at_device); + + scat_common_init(2); } static void -scatsx_init(void) +scatsx_common_init(void) { int i; - io_sethandler(0x0022, 2, - scat_read, NULL, NULL, scat_write, NULL, NULL, NULL); - io_sethandler(0x0092, 1, - scat_read, NULL, NULL, scat_write, NULL, NULL, NULL); + io_sethandler(0x0022, 0x0002, scat_read, NULL, NULL, scat_write, NULL, NULL, NULL); + io_sethandler(0x0092, 0x0001, scat_read, NULL, NULL, scat_write, NULL, NULL, NULL); for (i = 0; i < 256; i++) scat_regs[i] = 0xff; @@ -1421,55 +1382,46 @@ scatsx_init(void) scat_regs[SCATSX_CAS_TIMING_FOR_DMA] = 3; scat_port_92 = 0; - mem_mapping_disable(&ram_low_mapping); - mem_mapping_disable(&ram_high_mapping); + mem_map_disable(&ram_low_mapping); + mem_map_disable(&ram_mid_mapping); + mem_map_disable(&ram_high_mapping); for (i = 0; i < 4; i++) - mem_mapping_disable(&bios_mapping[i]); - mem_mapping_add(&scat_low_mapping[0], 0, 0x80000, mem_read_scatb, mem_read_scatw, mem_read_scatl, mem_write_scatb, mem_write_scatw, mem_write_scatl, ram, MEM_MAPPING_INTERNAL, NULL); - mem_mapping_add(&scat_low_mapping[1], 0xF0000, 0x10000, mem_read_scatb, mem_read_scatw, mem_read_scatl, mem_write_scatb, mem_write_scatw, mem_write_scatl, ram + 0xF0000, MEM_MAPPING_INTERNAL, NULL); + mem_map_disable(&bios_mapping[i]); + mem_map_add(&scat_low_mapping[0], 0, 0x80000, mem_read_scatb, mem_read_scatw, mem_read_scatl, mem_write_scatb, mem_write_scatw, mem_write_scatl, ram, MEM_MAPPING_INTERNAL, NULL); + mem_map_add(&scat_low_mapping[1], 0xF0000, 0x10000, mem_read_scatb, mem_read_scatw, mem_read_scatl, mem_write_scatb, mem_write_scatw, mem_write_scatl, ram + 0xF0000, MEM_MAPPING_INTERNAL, NULL); for(i=2;i<32;i++) - mem_mapping_add(&scat_low_mapping[i], (i << 19), 0x80000, mem_read_scatb, mem_read_scatw, mem_read_scatl, mem_write_scatb, mem_write_scatw, mem_write_scatl, ram + (i << 19), MEM_MAPPING_INTERNAL, NULL); - mem_mapping_set_addr(&scat_low_mapping[31], 0xF80000, 0x40000); + mem_map_add(&scat_low_mapping[i], (i << 19), 0x80000, mem_read_scatb, mem_read_scatw, mem_read_scatl, mem_write_scatb, mem_write_scatw, mem_write_scatl, ram + (i << 19), MEM_MAPPING_INTERNAL, NULL); + mem_map_set_addr(&scat_low_mapping[31], 0xF80000, 0x40000); for (i = 16; i < 44; i++) { - mem_mapping_add(&scat_4000_EFFF_mapping[i], 0x40000 + (i << 14), 0x4000, mem_read_scatb, mem_read_scatw, mem_read_scatl, mem_write_scatb, mem_write_scatw, mem_write_scatl, mem_size > 256 + (i << 4) ? ram + 0x40000 + (i << 14) : NULL, MEM_MAPPING_INTERNAL, NULL); - mem_mapping_enable(&scat_4000_EFFF_mapping[i]); + mem_map_add(&scat_4000_EFFF_mapping[i], 0x40000 + (i << 14), 0x4000, mem_read_scatb, mem_read_scatw, mem_read_scatl, mem_write_scatb, mem_write_scatw, mem_write_scatl, mem_size > 256 + (i << 4) ? ram + 0x40000 + (i << 14) : NULL, MEM_MAPPING_INTERNAL, NULL); + mem_map_enable(&scat_4000_EFFF_mapping[i]); } for (i = 0; i < 8; i++) { - mem_mapping_add(&scat_low_ROMCS_mapping[i], 0xC0000 + (i << 14), 0x4000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + ((i << 14) & biosmask), MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROM, NULL); - mem_mapping_disable(&scat_low_ROMCS_mapping[i]); + mem_map_add(&scat_low_ROMCS_mapping[i], 0xC0000 + (i << 14), 0x4000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + ((i << 14) & biosmask), MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROM, NULL); + mem_map_disable(&scat_low_ROMCS_mapping[i]); } for (i = 24; i < 32; i++) { scat_stat[i].regs_2x8 = 0xff; scat_stat[i].regs_2x9 = 0x03; - mem_mapping_add(&scat_ems_mapping[i], (i + 28) << 14, 0x04000, mem_read_scatb, mem_read_scatw, mem_read_scatl, mem_write_scatb, mem_write_scatw, mem_write_scatl, ram + ((i + 28) << 14), 0, &scat_stat[i]); - mem_mapping_disable(&scat_ems_mapping[i]); + mem_map_add(&scat_ems_mapping[i], (i + 28) << 14, 0x04000, mem_read_scatb, mem_read_scatw, mem_read_scatl, mem_write_scatb, mem_write_scatw, mem_write_scatl, ram + ((i + 28) << 14), 0, &scat_stat[i]); + mem_map_disable(&scat_ems_mapping[i]); } for (i = 0; i < 16; i++) { - mem_mapping_add(&scat_high_mapping[i], (i << 14) + 0xFC0000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + ((i << 14) & biosmask), 0, NULL); - mem_mapping_enable(&scat_high_mapping[i]); + mem_map_add(&scat_high_mapping[i], (i << 14) + 0xFC0000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + ((i << 14) & biosmask), 0, NULL); + mem_map_enable(&scat_high_mapping[i]); } for(i=0;i<6;i++) - mem_mapping_add(&scat_remap_mapping[i], 0x100000 + (i << 16), 0x10000, mem_read_scatb, mem_read_scatw, mem_read_scatl, mem_write_scatb, mem_write_scatw, mem_write_scatl, mem_size >= 1024 ? ram + get_scat_addr(0x100000 + (i << 16), NULL) : NULL, MEM_MAPPING_INTERNAL, NULL); + mem_map_add(&scat_remap_mapping[i], 0x100000 + (i << 16), 0x10000, mem_read_scatb, mem_read_scatw, mem_read_scatl, mem_write_scatb, mem_write_scatw, mem_write_scatl, mem_size >= 1024 ? ram + get_scat_addr(0x100000 + (i << 16), NULL) : NULL, MEM_MAPPING_INTERNAL, NULL); external_is_RAS = scatsx_external_is_RAS[mem_size >> 9]; - set_xms_bound(0); - memmap_state_update(); - shadow_state_update(); -} - - -void -machine_at_scat_init(const machine_t *model, void *arg) -{ - machine_at_init(model, arg); - device_add(&fdc_at_device); - - scat_init(); + scat_set_xms_bound(0); + scat_memmap_state_update(); + scat_shadow_state_update(); } @@ -1481,5 +1433,5 @@ machine_at_scatsx_init(const machine_t *model, void *arg) device_add(&keyboard_at_ami_device); device_add(&fdc_at_device); - scatsx_init(); + scatsx_common_init(); } diff --git a/src/machines/m_at_sis_85c496.c b/src/machines/m_at_sis_85c496.c index c19f810..6767acb 100644 --- a/src/machines/m_at_sis_85c496.c +++ b/src/machines/m_at_sis_85c496.c @@ -8,7 +8,7 @@ * * Implementation of the SiS 85C496 chipset. * - * Version: @(#)m_at_sis_85c496.c 1.0.5 2018/05/06 + * Version: @(#)m_at_sis_85c496.c 1.0.6 2018/10/05 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -42,7 +42,6 @@ #include #include #include "../emu.h" -#include "../cpu/cpu.h" #include "../io.h" #include "../device.h" #include "../mem.h" @@ -50,178 +49,179 @@ #include "../devices/system/memregs.h" #include "../devices/sio/sio.h" #include "../devices/disk/hdc.h" +#include "../devices/input/keyboard.h" #include "machine.h" -typedef struct { +typedef struct sis_85c496_t { uint8_t pci_conf[256]; } sis_85c496_t; -sis_85c496_t sis496; - - static void -recalc_mapping(void) +sis_85c496_recalcmapping(sis_85c496_t *dev) { uint32_t base; int c; for (c = 0; c < 8; c++) { base = 0xc0000 + (c << 15); - - if (sis496.pci_conf[0x44] & (1 << c)) { - switch (sis496.pci_conf[0x45] & 3) { + if (dev->pci_conf[0x44] & (1 << c)) { + switch (dev->pci_conf[0x45] & 3) { case 0: - mem_set_mem_state(base, 0x8000, - MEM_READ_EXTERNAL | MEM_WRITE_INTERNAL); + mem_set_mem_state(base, 0x8000, MEM_READ_EXTERNAL | MEM_WRITE_INTERNAL); break; - case 1: - mem_set_mem_state(base, 0x8000, - MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); + mem_set_mem_state(base, 0x8000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); break; - case 2: - mem_set_mem_state(base, 0x8000, - MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + mem_set_mem_state(base, 0x8000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); break; - case 3: - mem_set_mem_state(base, 0x8000, - MEM_READ_INTERNAL | MEM_WRITE_EXTERNAL); + mem_set_mem_state(base, 0x8000, MEM_READ_INTERNAL | MEM_WRITE_EXTERNAL); break; } - } else { - mem_set_mem_state(base, 0x8000, - MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); - } + } else + mem_set_mem_state(base, 0x8000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); } flushmmucache(); - - shadowbios = (sis496.pci_conf[0x44] & 0xf0); + shadowbios = (dev->pci_conf[0x44] & 0xf0); } static void -sis_write(int func, int addr, uint8_t val, void *p) +sis_85c496_write(int func, int addr, uint8_t val, void *priv) { + sis_85c496_t *dev = (sis_85c496_t *)priv; + switch (addr) { case 0x44: /*Shadow configure*/ - if ((sis496.pci_conf[0x44] & val) ^ 0xf0) { - sis496.pci_conf[0x44] = val; - recalc_mapping(); + if ((dev->pci_conf[0x44] & val) ^ 0xf0) { + dev->pci_conf[0x44] = val; + sis_85c496_recalcmapping(dev); } break; case 0x45: /*Shadow configure*/ - if ((sis496.pci_conf[0x45] & val) ^ 0x01) { - sis496.pci_conf[0x45] = val; - recalc_mapping(); + if ((dev->pci_conf[0x45] & val) ^ 0x01) { + dev->pci_conf[0x45] = val; + sis_85c496_recalcmapping(dev); } break; case 0xc0: if (val & 0x80) pci_set_irq_routing(PCI_INTA, val & 0xf); - else + else pci_set_irq_routing(PCI_INTA, PCI_IRQ_DISABLED); break; case 0xc1: if (val & 0x80) pci_set_irq_routing(PCI_INTB, val & 0xf); - else + else pci_set_irq_routing(PCI_INTB, PCI_IRQ_DISABLED); break; case 0xc2: if (val & 0x80) pci_set_irq_routing(PCI_INTC, val & 0xf); - else + else pci_set_irq_routing(PCI_INTC, PCI_IRQ_DISABLED); break; - case 0xc3:// pclog("IRQ routing %02x %02x\n", addr, val); + case 0xc3: if (val & 0x80) pci_set_irq_routing(PCI_INTD, val & 0xf); - else + else pci_set_irq_routing(PCI_INTD, PCI_IRQ_DISABLED); break; } - + if ((addr >= 4 && addr < 8) || addr >= 0x40) - sis496.pci_conf[addr] = val; + dev->pci_conf[addr] = val; } static uint8_t -sis_read(int func, int addr, void *p) +sis_85c496_read(int func, int addr, void *priv) { - return sis496.pci_conf[addr]; + sis_85c496_t *dev = (sis_85c496_t *)priv; + + return dev->pci_conf[addr]; } static void -sis_reset(void) -{ - memset(&sis496, 0, sizeof(sis_85c496_t)); - - sis496.pci_conf[0x00] = 0x39; /*SiS*/ - sis496.pci_conf[0x01] = 0x10; - sis496.pci_conf[0x02] = 0x96; /*496/497*/ - sis496.pci_conf[0x03] = 0x04; - - sis496.pci_conf[0x04] = 7; - sis496.pci_conf[0x05] = 0; - - sis496.pci_conf[0x06] = 0x80; - sis496.pci_conf[0x07] = 0x02; - - sis496.pci_conf[0x08] = 2; /*Device revision*/ - - sis496.pci_conf[0x09] = 0x00; /*Device class (PCI bridge)*/ - sis496.pci_conf[0x0a] = 0x00; - sis496.pci_conf[0x0b] = 0x06; - - sis496.pci_conf[0x0e] = 0x00; /*Single function device*/ -} - - -static void -sis_pci_reset(void) +sis_85c496_reset(void *priv) { uint8_t val = 0; - /* Read current value of 0x44. */ - val = sis_read(0, 0x44, NULL); - - /* Turn off shadow BIOS but keep the lower 4 bits. */ - sis_write(0, 0x44, val & 0xf, NULL); + val = sis_85c496_read(0, 0x44, priv); /* Read current value of 0x44. */ + sis_85c496_write(0, 0x44, val & 0xf, priv); /* Turn off shadow BIOS but keep the lower 4 bits. */ } static void -sis_init(void) +sis_85c496_close(void *priv) { - pci_add_card(5, sis_read, sis_write, NULL); + sis_85c496_t *dev = (sis_85c496_t *)priv; - sis_reset(); - - pci_reset_handler.pci_master_reset = sis_pci_reset; + free(dev); } +static void * +sis_85c496_init(const device_t *info) +{ + sis_85c496_t *dev = (sis_85c496_t *)mem_alloc(sizeof(sis_85c496_t)); + memset(dev, 0, sizeof(sis_85c496_t)); + + dev->pci_conf[0x00] = 0x39; /*SiS*/ + dev->pci_conf[0x01] = 0x10; + dev->pci_conf[0x02] = 0x96; /*496/497*/ + dev->pci_conf[0x03] = 0x04; + + dev->pci_conf[0x04] = 7; + dev->pci_conf[0x05] = 0; + + dev->pci_conf[0x06] = 0x80; + dev->pci_conf[0x07] = 0x02; + + dev->pci_conf[0x08] = 2; /*Device revision*/ + + dev->pci_conf[0x09] = 0x00; /*Device class (PCI bridge)*/ + dev->pci_conf[0x0a] = 0x00; + dev->pci_conf[0x0b] = 0x06; + + dev->pci_conf[0x0e] = 0x00; /*Single function device*/ + + pci_add_card(5, sis_85c496_read, sis_85c496_write, dev); + + return dev; +} + + +const device_t sis_85c496_device = { + "SiS 85c496/85c497", + DEVICE_PCI, + 0, + sis_85c496_init, sis_85c496_close, sis_85c496_reset, + NULL, NULL, NULL, NULL, + NULL +}; + + static void machine_at_sis_85c496_common_init(const machine_t *model, void *arg) { - machine_at_ps2_init(model, arg); + machine_at_common_init(model, arg); + device_add(&keyboard_ps2_pci_device); device_add(&ide_pci_device); memregs_init(); - pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x05, PCI_CARD_SPECIAL, 0, 0, 0, 0); pci_register_slot(0x0B, PCI_CARD_NORMAL, 1, 2, 3, 4); @@ -229,14 +229,19 @@ machine_at_sis_85c496_common_init(const machine_t *model, void *arg) pci_register_slot(0x0F, PCI_CARD_NORMAL, 3, 4, 1, 2); pci_register_slot(0x07, PCI_CARD_NORMAL, 4, 1, 2, 3); - sis_init(); + pci_set_irq_routing(PCI_INTA, PCI_IRQ_DISABLED); + pci_set_irq_routing(PCI_INTB, PCI_IRQ_DISABLED); + pci_set_irq_routing(PCI_INTC, PCI_IRQ_DISABLED); + pci_set_irq_routing(PCI_INTD, PCI_IRQ_DISABLED); + + device_add(&sis_85c496_device); } void machine_at_r418_init(const machine_t *model, void *arg) { - machine_at_sis_85c496_common_init(model, arg); + machine_at_sis_85c496_common_init(model, arg); - fdc37c665_init(); + fdc37c665_init(); } diff --git a/src/machines/m_at_sis_85c50x.c b/src/machines/m_at_sis_85c50x.c index f488180..a3910c9 100644 --- a/src/machines/m_at_sis_85c50x.c +++ b/src/machines/m_at_sis_85c50x.c @@ -8,7 +8,7 @@ * * Emulation of the SiS 85C50x PCI chips. * - * Version: @(#)m_at_sis_85c50x.c 1.0.3 2018/05/06 + * Version: @(#)m_at_sis_85c50x.c 1.0.4 2018/09/13 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -109,7 +109,6 @@ static void sis_85c501_recalcmapping(void) static void sis_85c501_write(int func, int addr, uint8_t val, void *p) { - /* pclog("sis_85c501_write : addr=%02x val=%02x\n", addr, val); */ if (func) return; @@ -153,8 +152,6 @@ static void sis_85c501_write(int func, int addr, uint8_t val, void *p) static void sis_85c503_write(int func, int addr, uint8_t val, void *p) { - /* pclog("sis_85c503_write : addr=%02x val=%02x\n", addr, val); */ - if (func > 0) return; @@ -184,28 +181,28 @@ static void sis_85c503_write(int func, int addr, uint8_t val, void *p) break; case 0x41: - pclog("Set IRQ routing: INT A -> %02X\n", val); + DEBUG("Set IRQ routing: INT A -> %02X\n", val); if (val & 0x80) pci_set_irq_routing(PCI_INTA, PCI_IRQ_DISABLED); else pci_set_irq_routing(PCI_INTA, val & 0xf); break; case 0x42: - pclog("Set IRQ routing: INT B -> %02X\n", val); + DEBUG("Set IRQ routing: INT B -> %02X\n", val); if (val & 0x80) pci_set_irq_routing(PCI_INTC, PCI_IRQ_DISABLED); else pci_set_irq_routing(PCI_INTC, val & 0xf); break; case 0x43: - pclog("Set IRQ routing: INT C -> %02X\n", val); + DEBUG("Set IRQ routing: INT C -> %02X\n", val); if (val & 0x80) pci_set_irq_routing(PCI_INTB, PCI_IRQ_DISABLED); else pci_set_irq_routing(PCI_INTB, val & 0xf); break; case 0x44: - pclog("Set IRQ routing: INT D -> %02X\n", val); + DEBUG("Set IRQ routing: INT D -> %02X\n", val); if (val & 0x80) pci_set_irq_routing(PCI_INTD, PCI_IRQ_DISABLED); else diff --git a/src/machines/m_at_t3100e.c b/src/machines/m_at_t3100e.c index ca35242..6a11364 100644 --- a/src/machines/m_at_t3100e.c +++ b/src/machines/m_at_t3100e.c @@ -70,6 +70,10 @@ * OUT 0x218, 0x80 will page in the 129th 16k page at 0xD0000. * etc. * + * The T3100e motherboard can (and does) dynamically reassign RAM + * between conventional, XMS and EMS. This translates to monkeying + * with the mappings. + * * To use EMS from DOS, you will need the Toshiba EMS driver * (TOSHEMM.ZIP). This supports the above system, plus further * ranges of ports at 0x_2A8, 0x_2B8, 0x_2C8. @@ -117,7 +121,7 @@ * bit 2 set for single-pixel LCD font * bits 0,1 for display font * - * Version: @(#)m_at_t3100e.c 1.0.8 2018/05/06 + * Version: @(#)m_at_t3100e.c 1.0.9 2018/09/13 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -155,6 +159,7 @@ #include "../io.h" #include "../mem.h" #include "../device.h" +#include "../devices/video/video.h" #include "../devices/input/keyboard.h" #include "../devices/input/mouse.h" #include "../devices/floppy/fdd.h" @@ -163,18 +168,7 @@ #include "m_at_t3100e.h" -/* The T3100e motherboard can (and does) dynamically reassign RAM between - * conventional, XMS and EMS. This translates to monkeying with the mappings. - */ - -extern mem_mapping_t base_mapping; -extern mem_mapping_t ram_low_mapping; /* This is to switch conventional RAM - * between 512k and 640k */ -extern mem_mapping_t ram_mid_mapping; /* This will not be used */ -extern mem_mapping_t ram_high_mapping; /* This is RAM beyond 1Mb if any */ - - -static unsigned t3100e_ems_page_reg[] = { +static const unsigned ems_page_reg[] = { 0x0208, 0x4208, 0x8208, 0xc208, /* The first four map the first 2Mb */ /* of RAM into the page frame */ 0x0218, 0x4218, 0x8218, 0xc218, /* The next four map the next 2Mb */ @@ -184,19 +178,22 @@ static unsigned t3100e_ems_page_reg[] = { }; -struct t3100e_ems_regs { +typedef struct { uint8_t page[16]; - mem_mapping_t mapping[4]; + mem_map_t mapping[4]; uint32_t page_exec[4]; /* Physical location of memory pages */ uint32_t upper_base; /* Start of upper RAM */ uint8_t upper_pages; /* Pages of EMS available from upper RAM */ uint8_t upper_is_ems; /* Upper RAM is EMS? */ - mem_mapping_t upper_mapping; + mem_map_t upper_mapping; uint8_t notify; /* Notification from keyboard controller */ uint8_t turbo; /* 0 for 6MHz, else full speed */ uint8_t mono; /* Emulates PC/AT 'mono' motherboard switch */ /* Bit 0 is 0 for colour, 1 for mono */ -} t3100e_ems; +} t3100e_t; + + +static t3100e_t t3100e; static void t3100e_ems_out(uint16_t addr, uint8_t val, void *p); @@ -224,9 +221,8 @@ page_to_addr(int pg) /* Given an EMS page ID, return its physical address in RAM. */ -uint32_t -t3100e_ems_execaddr(struct t3100e_ems_regs *regs, - int pg, uint16_t val) +static uint32_t +ems_execaddr(t3100e_t *dev, int pg, uint16_t val) { uint32_t addr; @@ -238,17 +234,17 @@ t3100e_ems_execaddr(struct t3100e_ems_regs *regs, /* to 8Mb of EMS to be accessed */ /* Is it in the upper memory range? */ - if (regs->upper_is_ems) { - if (val < regs->upper_pages) { - addr = regs->upper_base + 0x4000 * val; + if (dev->upper_is_ems) { + if (val < dev->upper_pages) { + addr = dev->upper_base + 0x4000 * val; return addr; } - val -= regs->upper_pages; + val -= dev->upper_pages; } /* Otherwise work down from the top of high RAM (so, the more EMS, * the less XMS) */ - if ((val * 0x4000) + 0x100000 >= (mem_size * 1024)) + if (((val * 0x4000) + 0x100000) >= (mem_size * 1024)) return 0; /* Not enough high RAM for this page */ /* High RAM found */ @@ -285,14 +281,12 @@ port_to_page(uint16_t addr) } -#if 0 /*NOT_USED*/ /* Used to dump the memory mapping table, for debugging. */ static void dump_mappings(void) { - mem_mapping_t *mm = base_mapping.next; - - if (!t3100e_log) return; +#if 0 /*NOT_USED*/ + mem_map_t *mm = base_mapping.next; while (mm) { const char *name = ""; @@ -301,109 +295,100 @@ dump_mappings(void) if (mm == &ram_low_mapping ) name = "LOW "; if (mm == &ram_mid_mapping ) name = "MID "; if (mm == &ram_high_mapping) name = "HIGH"; - if (mm == &t3100e_ems.upper_mapping) name = "UPPR"; - if (mm == &t3100e_ems.mapping[0]) { + if (mm == &t3100e.upper_mapping) name = "UPPR"; + if (mm == &t3100e.mapping[0]) { name = "EMS0"; - offset = t3100e_ems.page_exec[0]; + offset = t3100e.page_exec[0]; } - if (mm == &t3100e_ems.mapping[1]) { + if (mm == &t3100e.mapping[1]) { name = "EMS1"; - offset = t3100e_ems.page_exec[1]; + offset = t3100e.page_exec[1]; } - if (mm == &t3100e_ems.mapping[2]) { + if (mm == &t3100e.mapping[2]) { name = "EMS2"; - offset = t3100e_ems.page_exec[2]; + offset = t3100e.page_exec[2]; } - if (mm == &t3100e_ems.mapping[3]) { + if (mm == &t3100e.mapping[3]) { name = "EMS3"; - offset = t3100e_ems.page_exec[3]; + offset = t3100e.page_exec[3]; } - pclog(" %p | base=%05x size=%05x %c @ %06x %s\n", mm, + DEBUG(" %p | base=%05x size=%05x %c @ %06x %s\n", mm, mm->base, mm->size, mm->enable ? 'Y' : 'N', offset, name); mm = mm->next; } -} #endif +} static void -t3100e_map_ram(uint8_t val) +map_ram(t3100e_t *dev, uint8_t val) { int32_t upper_len; int n; #if 0 /*NOT_USED*/ - if (t3100e_log) { - pclog("OUT 0x8084, %02x [ set memory mapping :", val | 0x40); - if (val & 1) pclog("ENABLE_EMS "); - if (val & 2) pclog("ENABLE_XMS "); - if (val & 4) pclog("640K "); - if (val & 8) pclog("X8X "); - if (val & 16) pclog("UPPER_IS_XMS "); - pclog("\n"); - } + DEBUG("OUT 0x8084, %02x [ set memory mapping :", val | 0x40); + if (val & 1) DEBUG("ENABLE_EMS "); + if (val & 2) DEBUG("ENABLE_XMS "); + if (val & 4) DEBUG("640K "); + if (val & 8) DEBUG("X8X "); + if (val & 16) DEBUG("UPPER_IS_XMS "); + DEBUG("\n"); #endif /* Bit 2 controls size of conventional memory */ if (val & 4) { - t3100e_ems.upper_base = 0xA0000; - t3100e_ems.upper_pages = 24; + dev->upper_base = 0xA0000; + dev->upper_pages = 24; } else { - t3100e_ems.upper_base = 0x80000; - t3100e_ems.upper_pages = 32; + dev->upper_base = 0x80000; + dev->upper_pages = 32; } - upper_len = t3100e_ems.upper_pages * 16384; + upper_len = dev->upper_pages * 16384; - mem_mapping_set_addr(&ram_low_mapping, 0, t3100e_ems.upper_base); + mem_map_set_addr(&ram_low_mapping, 0, dev->upper_base); /* Bit 0 set if upper RAM is EMS */ - t3100e_ems.upper_is_ems = (val & 1); + dev->upper_is_ems = (val & 1); /* Bit 1 set if high RAM is enabled */ if (val & 2) - mem_mapping_enable(&ram_high_mapping); + mem_map_enable(&ram_high_mapping); else - mem_mapping_disable(&ram_high_mapping); + mem_map_disable(&ram_high_mapping); /* Bit 4 set if upper RAM is mapped to high memory * (and bit 1 set if XMS enabled) */ if ((val & 0x12) == 0x12) { - mem_mapping_set_addr(&t3100e_ems.upper_mapping, - mem_size * 1024, - upper_len); - mem_mapping_enable(&t3100e_ems.upper_mapping); - mem_mapping_set_exec(&t3100e_ems.upper_mapping, ram + t3100e_ems.upper_base); + mem_map_set_addr(&dev->upper_mapping, mem_size * 1024, upper_len); + mem_map_enable(&dev->upper_mapping); + mem_map_set_exec(&dev->upper_mapping, ram + dev->upper_base); } else { - mem_mapping_disable(&t3100e_ems.upper_mapping); + mem_map_disable(&dev->upper_mapping); } /* Recalculate EMS mappings */ for (n = 0; n < 4; n++) - t3100e_ems_out(t3100e_ems_page_reg[n], t3100e_ems.page[n], - &t3100e_ems); + t3100e_ems_out(ems_page_reg[n], dev->page[n], dev); -#if 0 /*NOT_USED*/ dump_mappings(); -#endif } static uint8_t t3100e_sys_in(uint16_t addr, void *p) { - struct t3100e_ems_regs *regs = (struct t3100e_ems_regs *)p; + t3100e_t *dev = (t3100e_t *)p; /* The low 4 bits always seem to be 0x0C. The high 4 are a * notification sent by the keyboard controller when it detects * an [Fn] key combination */ -#if 0 /*NOT_USED*/ - if (t3100e_log) pclog("IN 0x8084\n"); -#endif + DEBUG("IN 0x8084\n"); - return 0x0C | (regs->notify << 4); + return 0x0C | (dev->notify << 4); } @@ -411,18 +396,15 @@ t3100e_sys_in(uint16_t addr, void *p) static void t3100e_sys_out(uint16_t addr, uint8_t val, void *p) { -// struct t3100e_ems_regs *regs = (struct t3100e_ems_regs *)p; + t3100e_t *dev = (t3100e_t *)p; switch (val & 0xE0) { case 0x00: /* Set serial port IRQs. Not implemented */ -#if 0 /*NOT_USED*/ - if (t3100e_log) - pclog("OUT 0x8084, %02x [ set serial port IRQs]\n", val); -#endif + DEBUG("OUT 0x8084, %02x [ set serial port IRQs]\n", val); break; case 0x40: /* Set RAM mappings. */ - t3100e_map_ram(val & 0x1F); + map_ram(dev, val & 0x1F); break; case 0x80: /* Set video options. */ @@ -430,9 +412,7 @@ t3100e_sys_out(uint16_t addr, uint8_t val, void *p) break; default: /* Other options not implemented. */ -#if 0 /*NOT_USED*/ - if (t3100e_log) pclog("OUT 0x8084, %02x\n", val); -#endif + DEBUG("OUT 0x8084, %02x\n", val); break; } } @@ -442,9 +422,9 @@ t3100e_sys_out(uint16_t addr, uint8_t val, void *p) static uint8_t t3100e_ems_in(uint16_t addr, void *p) { - struct t3100e_ems_regs *regs = (struct t3100e_ems_regs *)p; + t3100e_t *dev = (t3100e_t *)p; - return regs->page[port_to_page(addr)]; + return dev->page[port_to_page(addr)]; } @@ -453,31 +433,23 @@ t3100e_ems_in(uint16_t addr, void *p) static void t3100e_ems_out(uint16_t addr, uint8_t val, void *p) { - struct t3100e_ems_regs *regs = (struct t3100e_ems_regs *)p; + t3100e_t *dev = (t3100e_t *)p; int pg = port_to_page(addr); - regs->page_exec[pg & 3] = t3100e_ems_execaddr(regs, pg, val); -#if 0 /*NOT_USED*/ - if (t3100e_log) pclog("EMS: page %d %02x -> %02x [%06x]\n", - pg, regs->page[pg], val, regs->page_exec[pg & 3]); -#endif - regs->page[pg] = val; + dev->page_exec[pg & 3] = ems_execaddr(dev, pg, val); + DEBUG("EMS: page %d %02x -> %02x [%06x]\n", + pg, dev->page[pg], val, dev->page_exec[pg & 3]); + dev->page[pg] = val; /* Bit 7 set if page is enabled, reset if page is disabled */ pg &= 3; - if (regs->page_exec[pg]) { -#if 0 /*NOT_USED*/ - if (t3100e_log) pclog("Enabling EMS RAM at %05x\n", - page_to_addr(pg)); -#endif - mem_mapping_enable(®s->mapping[pg]); - mem_mapping_set_exec(®s->mapping[pg], ram + regs->page_exec[pg]); + if (dev->page_exec[pg]) { + DEBUG("Enabling EMS RAM at %05x\n", page_to_addr(pg)); + mem_map_enable(&dev->mapping[pg]); + mem_map_set_exec(&dev->mapping[pg], ram + dev->page_exec[pg]); } else { -#if 0 /*NOT_USED*/ - if (t3100e_log) pclog("Disabling EMS RAM at %05x\n", - page_to_addr(pg)); -#endif - mem_mapping_disable(®s->mapping[pg]); + DEBUG("Disabling EMS RAM at %05x\n", page_to_addr(pg)); + mem_map_disable(&dev->mapping[pg]); } } @@ -486,11 +458,12 @@ t3100e_ems_out(uint16_t addr, uint8_t val, void *p) static uint8_t ems_read_ram(uint32_t addr, void *priv) { - struct t3100e_ems_regs *regs = (struct t3100e_ems_regs *)priv; + t3100e_t *dev = (t3100e_t *)priv; int pg = addr_to_page(addr); if (pg < 0) return 0xFF; - addr = regs->page_exec[pg] + (addr & 0x3FFF); + addr = dev->page_exec[pg] + (addr & 0x3FFF); + return ram[addr]; } @@ -498,13 +471,15 @@ ems_read_ram(uint32_t addr, void *priv) static uint16_t ems_read_ramw(uint32_t addr, void *priv) { - struct t3100e_ems_regs *regs = (struct t3100e_ems_regs *)priv; + t3100e_t *dev = (t3100e_t *)priv; int pg = addr_to_page(addr); if (pg < 0) return 0xFF; -//pclog("ems_read_ramw addr=%05x ", addr); - addr = regs->page_exec[pg] + (addr & 0x3FFF); -//pclog("-> %06x val=%04x\n", addr, *(uint16_t *)&ram[addr]); + + DBGLOG(1, "ems_read_ramw addr=%05x ", addr); + addr = dev->page_exec[pg] + (addr & 0x3FFF); + DBGLOG(1, "-> %06x val=%04x\n", addr, *(uint16_t *)&ram[addr]); + return *(uint16_t *)&ram[addr]; } @@ -512,11 +487,11 @@ ems_read_ramw(uint32_t addr, void *priv) static uint32_t ems_read_raml(uint32_t addr, void *priv) { - struct t3100e_ems_regs *regs = (struct t3100e_ems_regs *)priv; + t3100e_t *dev = (t3100e_t *)priv; int pg = addr_to_page(addr); if (pg < 0) return 0xFF; - addr = regs->page_exec[pg] + (addr & 0x3FFF); + addr = dev->page_exec[pg] + (addr & 0x3FFF); return *(uint32_t *)&ram[addr]; } @@ -526,11 +501,11 @@ ems_read_raml(uint32_t addr, void *priv) static void ems_write_ram(uint32_t addr, uint8_t val, void *priv) { - struct t3100e_ems_regs *regs = (struct t3100e_ems_regs *)priv; + t3100e_t *dev = (t3100e_t *)priv; int pg = addr_to_page(addr); if (pg < 0) return; - addr = regs->page_exec[pg] + (addr & 0x3FFF); + addr = dev->page_exec[pg] + (addr & 0x3FFF); ram[addr] = val; } @@ -538,13 +513,13 @@ ems_write_ram(uint32_t addr, uint8_t val, void *priv) static void ems_write_ramw(uint32_t addr, uint16_t val, void *priv) { - struct t3100e_ems_regs *regs = (struct t3100e_ems_regs *)priv; + t3100e_t *dev = (t3100e_t *)priv; int pg = addr_to_page(addr); if (pg < 0) return; -//pclog("ems_write_ramw addr=%05x ", addr); - addr = regs->page_exec[pg] + (addr & 0x3FFF); -//pclog("-> %06x val=%04x\n", addr, val); + DBGLOG(1, "ems_write_ramw addr=%05x ", addr); + addr = dev->page_exec[pg] + (addr & 0x3FFF); + DBGLOG(1, "-> %06x val=%04x\n", addr, val); *(uint16_t *)&ram[addr] = val; } @@ -553,11 +528,11 @@ ems_write_ramw(uint32_t addr, uint16_t val, void *priv) static void ems_write_raml(uint32_t addr, uint32_t val, void *priv) { - struct t3100e_ems_regs *regs = (struct t3100e_ems_regs *)priv; + t3100e_t *dev = (t3100e_t *)priv; int pg = addr_to_page(addr); if (pg < 0) return; - addr = regs->page_exec[pg] + (addr & 0x3FFF); + addr = dev->page_exec[pg] + (addr & 0x3FFF); *(uint32_t *)&ram[addr] = val; } @@ -567,9 +542,10 @@ ems_write_raml(uint32_t addr, uint32_t val, void *priv) static uint8_t upper_read_ram(uint32_t addr, void *priv) { - struct t3100e_ems_regs *regs = (struct t3100e_ems_regs *)priv; + t3100e_t *dev = (t3100e_t *)priv; + + addr = (addr - (1024 * mem_size)) + dev->upper_base; - addr = (addr - (1024 * mem_size)) + regs->upper_base; return ram[addr]; } @@ -577,18 +553,21 @@ upper_read_ram(uint32_t addr, void *priv) static uint16_t upper_read_ramw(uint32_t addr, void *priv) { - struct t3100e_ems_regs *regs = (struct t3100e_ems_regs *)priv; + t3100e_t *dev = (t3100e_t *)priv; + + addr = (addr - (1024 * mem_size)) + dev->upper_base; - addr = (addr - (1024 * mem_size)) + regs->upper_base; return *(uint16_t *)&ram[addr]; } + static uint32_t upper_read_raml(uint32_t addr, void *priv) { - struct t3100e_ems_regs *regs = (struct t3100e_ems_regs *)priv; + t3100e_t *dev = (t3100e_t *)priv; + + addr = (addr - (1024 * mem_size)) + dev->upper_base; - addr = (addr - (1024 * mem_size)) + regs->upper_base; return *(uint32_t *)&ram[addr]; } @@ -596,9 +575,9 @@ upper_read_raml(uint32_t addr, void *priv) static void upper_write_ram(uint32_t addr, uint8_t val, void *priv) { - struct t3100e_ems_regs *regs = (struct t3100e_ems_regs *)priv; + t3100e_t *dev = (t3100e_t *)priv; - addr = (addr - (1024 * mem_size)) + regs->upper_base; + addr = (addr - (1024 * mem_size)) + dev->upper_base; ram[addr] = val; } @@ -606,9 +585,9 @@ upper_write_ram(uint32_t addr, uint8_t val, void *priv) static void upper_write_ramw(uint32_t addr, uint16_t val, void *priv) { - struct t3100e_ems_regs *regs = (struct t3100e_ems_regs *)priv; + t3100e_t *dev = (t3100e_t *)priv; - addr = (addr - (1024 * mem_size)) + regs->upper_base; + addr = (addr - (1024 * mem_size)) + dev->upper_base; *(uint16_t *)&ram[addr] = val; } @@ -616,9 +595,9 @@ upper_write_ramw(uint32_t addr, uint16_t val, void *priv) static void upper_write_raml(uint32_t addr, uint32_t val, void *priv) { - struct t3100e_ems_regs *regs = (struct t3100e_ems_regs *)priv; + t3100e_t *dev = (t3100e_t *)priv; - addr = (addr - (1024 * mem_size)) + regs->upper_base; + addr = (addr - (1024 * mem_size)) + dev->upper_base; *(uint32_t *)&ram[addr] = val; } @@ -628,7 +607,7 @@ machine_at_t3100e_init(const machine_t *model, void *arg) { int pg; - memset(&t3100e_ems, 0x00, sizeof(t3100e_ems)); + memset(&t3100e, 0x00, sizeof(t3100e_t)); machine_at_common_ide_init(model, arg); @@ -638,38 +617,36 @@ machine_at_t3100e_init(const machine_t *model, void *arg) /* Hook up system control port */ io_sethandler(0x8084, 1, - t3100e_sys_in,NULL,NULL, t3100e_sys_out,NULL,NULL, &t3100e_ems); + t3100e_sys_in,NULL,NULL, t3100e_sys_out,NULL,NULL, &t3100e); /* Start monitoring all 16 EMS registers */ for (pg = 0; pg < 16; pg++) { - io_sethandler(t3100e_ems_page_reg[pg], 0x0001, + io_sethandler(ems_page_reg[pg], 1, t3100e_ems_in, NULL, NULL, - t3100e_ems_out, NULL, NULL, &t3100e_ems); + t3100e_ems_out, NULL, NULL, &t3100e); } /* Map the EMS page frame */ for (pg = 0; pg < 4; pg++) { -#if 0 /*NOT_USED*/ - if (t3100e_log) pclog("Adding memory map at %x for page %d\n", page_to_addr(pg), pg); -#endif - mem_mapping_add(&t3100e_ems.mapping[pg], - page_to_addr(pg), 16384, - ems_read_ram, ems_read_ramw, ems_read_raml, - ems_write_ram, ems_write_ramw, ems_write_raml, - NULL, MEM_MAPPING_EXTERNAL, - &t3100e_ems); + DBGLOG(1, "Adding memory map at %x for page %d\n",page_to_addr(pg),pg); + mem_map_add(&t3100e.mapping[pg], + page_to_addr(pg), 16384, + ems_read_ram, ems_read_ramw, ems_read_raml, + ems_write_ram, ems_write_ramw, ems_write_raml, + NULL, MEM_MAPPING_EXTERNAL, + &t3100e); /* Start them all off disabled */ - mem_mapping_disable(&t3100e_ems.mapping[pg]); + mem_map_disable(&t3100e.mapping[pg]); } /* Mapping for upper RAM when in use as XMS*/ - mem_mapping_add(&t3100e_ems.upper_mapping, mem_size * 1024, 384 * 1024, - upper_read_ram, upper_read_ramw, upper_read_raml, - upper_write_ram, upper_write_ramw, upper_write_raml, - NULL, MEM_MAPPING_INTERNAL, &t3100e_ems); + mem_map_add(&t3100e.upper_mapping, mem_size * 1024, 384 * 1024, + upper_read_ram, upper_read_ramw, upper_read_raml, + upper_write_ram, upper_write_ramw, upper_write_raml, + NULL, MEM_MAPPING_INTERNAL, &t3100e); - mem_mapping_disable(&t3100e_ems.upper_mapping); + mem_map_disable(&t3100e.upper_mapping); device_add(&t3100e_device); } @@ -697,7 +674,7 @@ t3100e_config_get(void) /* Get display setting */ if (t3100e_display_get()) value |= 0x80; - if (! t3100e_ems.turbo) value |= 0x40; + if (! t3100e.turbo) value |= 0x40; /* Try to determine the floppy types.*/ prt_switch = (type_b ? 2 : 0); @@ -755,31 +732,32 @@ t3100e_config_get(void) void -t3100e_notify_set(uint8_t value) +t3100e_notify_set(uint8_t val) { - t3100e_ems.notify = value; + t3100e.notify = val; } void -t3100e_mono_set(uint8_t value) +t3100e_mono_set(uint8_t val) { - t3100e_ems.mono = value; + t3100e.mono = val; } uint8_t t3100e_mono_get(void) { - return t3100e_ems.mono; + return t3100e.mono; } void -t3100e_turbo_set(uint8_t value) +t3100e_turbo_set(uint8_t val) { - t3100e_ems.turbo = value; - if (! value) + t3100e.turbo = val; + + if (! val) cpu_dynamic_switch(0); /* 286/6 */ else cpu_dynamic_switch(cpu); diff --git a/src/machines/m_at_t3100e_vid.c b/src/machines/m_at_t3100e_vid.c index 3a6434a..707a06e 100644 --- a/src/machines/m_at_t3100e_vid.c +++ b/src/machines/m_at_t3100e_vid.c @@ -22,7 +22,7 @@ * 61 50 52 0F 19 06 19 19 02 0D 0B 0C MONO * 2D 28 22 0A 67 00 64 67 02 03 06 07 640x400 * - * Version: @(#)m_at_t3100e_vid.c 1.0.5 2018/05/06 + * Version: @(#)m_at_t3100e_vid.c 1.0.6 2018/09/22 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -86,678 +86,653 @@ static uint32_t normcols[256][2]; static uint8_t st_video_options; static int8_t st_display_internal = -1; -void t3100e_video_options_set(uint8_t options) -{ - st_video_options = options; -} -void t3100e_display_set(uint8_t internal) -{ - st_display_internal = internal; -} +typedef struct { + mem_map_t mapping; -uint8_t t3100e_display_get() -{ - return st_display_internal; -} - - -typedef struct t3100e_t -{ - mem_mapping_t mapping; - - cga_t cga; /* The CGA is used for the external + cga_t cga; /* The CGA is used for the external * display; most of its registers are * ignored by the plasma display. */ - int font; /* Current font, 0-3 */ - int enabled; /* Hardware enabled, 0 or 1 */ - int internal; /* Using internal display? */ - uint8_t attrmap; /* Attribute mapping register */ + int font; /* Current font, 0-3 */ + int enabled; /* Hardware enabled, 0 or 1 */ + int internal; /* Using internal display? */ + uint8_t attrmap; /* Attribute mapping register */ - int dispontime, dispofftime; - - int linepos, displine; - int vc; - int dispon; - int vsynctime; - uint8_t video_options; + int dispontime, dispofftime; - uint8_t *vram; + int linepos, displine; + int vc; + int dispon; + int vsynctime; + uint8_t video_options; + + uint8_t *vram; } t3100e_t; -void t3100e_recalctimings(t3100e_t *t3100e); -void t3100e_write(uint32_t addr, uint8_t val, void *p); -uint8_t t3100e_read(uint32_t addr, void *p); -void t3100e_recalcattrs(t3100e_t *t3100e); - - -void t3100e_out(uint16_t addr, uint8_t val, void *p) +static void +recalc_timings(t3100e_t *dev) { - t3100e_t *t3100e = (t3100e_t *)p; - switch (addr) - { - /* Emulated CRTC, register select */ - case 0x3d0: case 0x3d2: case 0x3d4: case 0x3d6: - cga_out(addr, val, &t3100e->cga); - break; + double disptime; + double _dispontime, _dispofftime; - /* Emulated CRTC, value */ - case 0x3d1: case 0x3d3: case 0x3d5: case 0x3d7: - /* Register 0x12 controls the attribute mappings for the - * plasma screen. */ - if (t3100e->cga.crtcreg == 0x12) - { - t3100e->attrmap = val; - t3100e_recalcattrs(t3100e); - return; - } - cga_out(addr, val, &t3100e->cga); + if (! dev->internal) { + cga_recalctimings(&dev->cga); + return; + } - t3100e_recalctimings(t3100e); - return; + disptime = 651; + _dispontime = 640; + _dispofftime = disptime - _dispontime; - /* CGA control register */ - case 0x3D8: - cga_out(addr, val, &t3100e->cga); - return; - /* CGA colour register */ - case 0x3D9: - cga_out(addr, val, &t3100e->cga); - return; - } -} - -uint8_t t3100e_in(uint16_t addr, void *p) -{ - t3100e_t *t3100e = (t3100e_t *)p; - uint8_t val; - - switch (addr) - { - case 0x3d1: case 0x3d3: case 0x3d5: case 0x3d7: - if (t3100e->cga.crtcreg == 0x12) - { - val = t3100e->attrmap & 0x0F; - if (t3100e->internal) val |= 0x30; /* Plasma / CRT */ - return val; - } - } - - return cga_in(addr, &t3100e->cga); + dev->dispontime = (int)(_dispontime * (1 << TIMER_SHIFT)); + dev->dispofftime = (int)(_dispofftime * (1 << TIMER_SHIFT)); } - - -void t3100e_write(uint32_t addr, uint8_t val, void *p) +static void +recalc_attrs(t3100e_t *dev) { - t3100e_t *t3100e = (t3100e_t *)p; - egawrites++; + int n; -// pclog("CGA_WRITE %04X %02X\n", addr, val); - t3100e->vram[addr & 0x7fff] = val; - cycles -= 4; -} - + /* val behaves as follows: + * Bit 0: Attributes 01-06, 08-0E are inverse video + * Bit 1: Attributes 01-06, 08-0E are bold + * Bit 2: Attributes 11-16, 18-1F, 21-26, 28-2F ... F1-F6, F8-FF + * are inverse video + * Bit 3: Attributes 11-16, 18-1F, 21-26, 28-2F ... F1-F6, F8-FF + * are bold + */ + /* Set up colors. */ + amber = makecol(0xf7, 0x7C, 0x34); + black = makecol(0x17, 0x0C, 0x00); -uint8_t t3100e_read(uint32_t addr, void *p) -{ - t3100e_t *t3100e = (t3100e_t *)p; - egareads++; - cycles -= 4; + /* Initialize the attribute mapping. Start by defaulting + * everything to black on amber, and with bold set by bit 3. + */ + for (n = 0; n < 256; n++) { + boldcols[n] = (n & 8) != 0; + blinkcols[n][0] = normcols[n][0] = amber; + blinkcols[n][1] = normcols[n][1] = black; + } -// pclog("CGA_READ %04X\n", addr); - return t3100e->vram[addr & 0x7fff]; -} + /* Colors 0x11-0xFF are controlled by bits 2 and 3 of the + * passed value. Exclude x0 and x8, which are always black + * on amber. + */ + for (n = 0x11; n <= 0xFF; n++) { + if ((n & 7) == 0) continue; - - -void t3100e_recalctimings(t3100e_t *t3100e) -{ - double disptime; - double _dispontime, _dispofftime; - - if (!t3100e->internal) - { - cga_recalctimings(&t3100e->cga); - return; - } - disptime = 651; - _dispontime = 640; - _dispofftime = disptime - _dispontime; - t3100e->dispontime = (int)(_dispontime * (1 << TIMER_SHIFT)); - t3100e->dispofftime = (int)(_dispofftime * (1 << TIMER_SHIFT)); -} - - -/* Draw a row of text in 80-column mode */ -void t3100e_text_row80(t3100e_t *t3100e) -{ - uint32_t cols[2]; - int x, c; - uint8_t chr, attr; - int drawcursor; - int cursorline; - int bold; - int blink; - uint16_t addr; - uint8_t sc; - uint16_t ma = (t3100e->cga.crtc[13] | (t3100e->cga.crtc[12] << 8)) & 0x7fff; - uint16_t ca = (t3100e->cga.crtc[15] | (t3100e->cga.crtc[14] << 8)) & 0x7fff; - - sc = (t3100e->displine) & 15; - addr = ((ma & ~1) + (t3100e->displine >> 4) * 80) * 2; - ma += (t3100e->displine >> 4) * 80; - - if ((t3100e->cga.crtc[10] & 0x60) == 0x20) - { - cursorline = 0; - } - else - { - cursorline = ((t3100e->cga.crtc[10] & 0x0F)*2 <= sc) && - ((t3100e->cga.crtc[11] & 0x0F)*2 >= sc); - } - for (x = 0; x < 80; x++) - { - chr = t3100e->vram[(addr + 2 * x) & 0x7FFF]; - attr = t3100e->vram[(addr + 2 * x + 1) & 0x7FFF]; - drawcursor = ((ma == ca) && cursorline && - (t3100e->cga.cgamode & 8) && (t3100e->cga.cgablink & 16)); - - blink = ((t3100e->cga.cgablink & 16) && (t3100e->cga.cgamode & 0x20) && - (attr & 0x80) && !drawcursor); - - if (t3100e->video_options & 4) - bold = boldcols[attr] ? chr + 256 : chr; - else - bold = boldcols[attr] ? chr : chr + 256; - bold += 512 * (t3100e->video_options & 3); - - if (t3100e->cga.cgamode & 0x20) /* Blink */ - { - cols[1] = blinkcols[attr][1]; - cols[0] = blinkcols[attr][0]; - if (blink) cols[1] = cols[0]; - } - else - { - cols[1] = normcols[attr][1]; - cols[0] = normcols[attr][0]; - } - if (drawcursor) - { - for (c = 0; c < 8; c++) - { - ((uint32_t *)buffer32->line[t3100e->displine])[(x << 3) + c] = cols[(fontdatm[bold][sc] & (1 << (c ^ 7))) ? 1 : 0] ^ (amber ^ black); - } - } - else - { - for (c = 0; c < 8; c++) - ((uint32_t *)buffer32->line[t3100e->displine])[(x << 3) + c] = cols[(fontdatm[bold][sc] & (1 << (c ^ 7))) ? 1 : 0]; - } - ++ma; - } -} - -/* Draw a row of text in 40-column mode */ -void t3100e_text_row40(t3100e_t *t3100e) -{ - uint32_t cols[2]; - int x, c; - uint8_t chr, attr; - int drawcursor; - int cursorline; - int bold; - int blink; - uint16_t addr; - uint8_t sc; - uint16_t ma = (t3100e->cga.crtc[13] | (t3100e->cga.crtc[12] << 8)) & 0x7fff; - uint16_t ca = (t3100e->cga.crtc[15] | (t3100e->cga.crtc[14] << 8)) & 0x7fff; - - sc = (t3100e->displine) & 15; - addr = ((ma & ~1) + (t3100e->displine >> 4) * 40) * 2; - ma += (t3100e->displine >> 4) * 40; - - if ((t3100e->cga.crtc[10] & 0x60) == 0x20) - { - cursorline = 0; - } - else - { - cursorline = ((t3100e->cga.crtc[10] & 0x0F)*2 <= sc) && - ((t3100e->cga.crtc[11] & 0x0F)*2 >= sc); - } - for (x = 0; x < 40; x++) - { - chr = t3100e->vram[(addr + 2 * x) & 0x7FFF]; - attr = t3100e->vram[(addr + 2 * x + 1) & 0x7FFF]; - drawcursor = ((ma == ca) && cursorline && - (t3100e->cga.cgamode & 8) && (t3100e->cga.cgablink & 16)); - - blink = ((t3100e->cga.cgablink & 16) && (t3100e->cga.cgamode & 0x20) && - (attr & 0x80) && !drawcursor); - - if (t3100e->video_options & 4) - bold = boldcols[attr] ? chr + 256 : chr; - else bold = boldcols[attr] ? chr : chr + 256; - bold += 512 * (t3100e->video_options & 3); - - if (t3100e->cga.cgamode & 0x20) /* Blink */ - { - cols[1] = blinkcols[attr][1]; - cols[0] = blinkcols[attr][0]; - if (blink) cols[1] = cols[0]; - } - else - { - cols[1] = normcols[attr][1]; - cols[0] = normcols[attr][0]; - } - if (drawcursor) - { - for (c = 0; c < 8; c++) - { - ((uint32_t *)buffer32->line[t3100e->displine])[(x << 4) + c*2] = - ((uint32_t *)buffer32->line[t3100e->displine])[(x << 4) + c*2 + 1] = cols[(fontdatm[bold][sc] & (1 << (c ^ 7))) ? 1 : 0] ^ (amber ^ black); - } - } - else - { - for (c = 0; c < 8; c++) - { - ((uint32_t *)buffer32->line[t3100e->displine])[(x << 4) + c*2] = - ((uint32_t *)buffer32->line[t3100e->displine])[(x << 4) + c*2+1] = cols[(fontdatm[bold][sc] & (1 << (c ^ 7))) ? 1 : 0]; - } - } - ++ma; - } -} - - - - -/* Draw a line in CGA 640x200 or T3100e 640x400 mode */ -void t3100e_cgaline6(t3100e_t *t3100e) -{ - int x, c; - uint8_t dat; - uint32_t ink = 0; - uint16_t addr; - uint32_t fg = (t3100e->cga.cgacol & 0x0F) ? amber : black; - uint32_t bg = black; - - uint16_t ma = (t3100e->cga.crtc[13] | (t3100e->cga.crtc[12] << 8)) & 0x7fff; - - if (t3100e->cga.crtc[9] == 3) /* 640*400 */ - { - addr = ((t3100e->displine) & 1) * 0x2000 + - ((t3100e->displine >> 1) & 1) * 0x4000 + - (t3100e->displine >> 2) * 80 + - ((ma & ~1) << 1); - } - else - { - addr = ((t3100e->displine >> 1) & 1) * 0x2000 + - (t3100e->displine >> 2) * 80 + - ((ma & ~1) << 1); - } - for (x = 0; x < 80; x++) - { - dat = t3100e->vram[addr & 0x7FFF]; - addr++; - - for (c = 0; c < 8; c++) - { - ink = (dat & 0x80) ? fg : bg; - if (!(t3100e->cga.cgamode & 8)) ink = black; - ((uint32_t *)buffer32->line[t3100e->displine])[x*8+c] = ink; - dat = dat << 1; - } - } -} - - -/* Draw a line in CGA 320x200 mode. Here the CGA colours are converted to - * dither patterns: colour 1 to 25% grey, colour 2 to 50% grey */ -void t3100e_cgaline4(t3100e_t *t3100e) -{ - int x, c; - uint8_t dat, pattern; - uint32_t ink0 = 0, ink1 = 0; - uint16_t addr; - - uint16_t ma = (t3100e->cga.crtc[13] | (t3100e->cga.crtc[12] << 8)) & 0x7fff; - if (t3100e->cga.crtc[9] == 3) /* 320*400 undocumented */ - { - addr = ((t3100e->displine) & 1) * 0x2000 + - ((t3100e->displine >> 1) & 1) * 0x4000 + - (t3100e->displine >> 2) * 80 + - ((ma & ~1) << 1); - } - else /* 320*200 */ - { - addr = ((t3100e->displine >> 1) & 1) * 0x2000 + - (t3100e->displine >> 2) * 80 + - ((ma & ~1) << 1); - } - for (x = 0; x < 80; x++) - { - dat = t3100e->vram[addr & 0x7FFF]; - addr++; - - for (c = 0; c < 4; c++) - { - pattern = (dat & 0xC0) >> 6; - if (!(t3100e->cga.cgamode & 8)) pattern = 0; - - switch (pattern & 3) - { - case 0: ink0 = ink1 = black; break; - case 1: if (t3100e->displine & 1) - { - ink0 = black; ink1 = black; - } - else - { - ink0 = amber; ink1 = black; - } - break; - case 2: if (t3100e->displine & 1) - { - ink0 = black; ink1 = amber; - } - else - { - ink0 = amber; ink1 = black; - } - break; - case 3: ink0 = ink1 = amber; break; - - } - ((uint32_t *)buffer32->line[t3100e->displine])[x*8+2*c] = ink0; - ((uint32_t *)buffer32->line[t3100e->displine])[x*8+2*c+1] = ink1; - dat = dat << 2; - } - } -} - - - - - - -void t3100e_poll(void *p) -{ - t3100e_t *t3100e = (t3100e_t *)p; - - if (t3100e->video_options != st_video_options) - { - t3100e->video_options = st_video_options; - - if (t3100e->video_options & 8) /* Disable internal CGA */ - mem_mapping_disable(&t3100e->mapping); - else mem_mapping_enable(&t3100e->mapping); - - /* Set the font used for the external display */ - t3100e->cga.fontbase = (512 * (t3100e->video_options & 3)) - + ((t3100e->video_options & 4) ? 256 : 0); - - } - /* Switch between internal plasma and external CRT display. */ - if (st_display_internal != -1 && st_display_internal != t3100e->internal) - { - t3100e->internal = st_display_internal; - t3100e_recalctimings(t3100e); - } - if (!t3100e->internal) - { - cga_poll(&t3100e->cga); - return; - } - - - if (!t3100e->linepos) - { - t3100e->cga.vidtime += t3100e->dispofftime; - t3100e->cga.cgastat |= 1; - t3100e->linepos = 1; - if (t3100e->dispon) - { - if (t3100e->displine == 0) - { - video_wait_for_buffer(); - } - - /* Graphics */ - if (t3100e->cga.cgamode & 0x02) - { - if (t3100e->cga.cgamode & 0x10) - t3100e_cgaline6(t3100e); - else t3100e_cgaline4(t3100e); - } - else - if (t3100e->cga.cgamode & 0x01) /* High-res text */ - { - t3100e_text_row80(t3100e); - } - else - { - t3100e_text_row40(t3100e); - } - } - t3100e->displine++; - /* Hardcode a fixed refresh rate and VSYNC timing */ - if (t3100e->displine == 400) /* Start of VSYNC */ - { - t3100e->cga.cgastat |= 8; - t3100e->dispon = 0; - } - if (t3100e->displine == 416) /* End of VSYNC */ - { - t3100e->displine = 0; - t3100e->cga.cgastat &= ~8; - t3100e->dispon = 1; - } - } - else - { - if (t3100e->dispon) - { - t3100e->cga.cgastat &= ~1; - } - t3100e->cga.vidtime += t3100e->dispontime; - t3100e->linepos = 0; - - if (t3100e->displine == 400) - { -/* Hardcode 640x400 window size */ - if (T3100E_XSIZE != xsize || T3100E_YSIZE != ysize) - { - xsize = T3100E_XSIZE; - ysize = T3100E_YSIZE; - if (xsize < 64) xsize = 656; - if (ysize < 32) ysize = 200; - set_screen_size(xsize, ysize); - } - video_blit_memtoscreen(0, 0, 0, ysize, xsize, ysize); - - frames++; - /* Fixed 640x400 resolution */ - video_res_x = T3100E_XSIZE; - video_res_y = T3100E_YSIZE; - - if (t3100e->cga.cgamode & 0x02) - { - if (t3100e->cga.cgamode & 0x10) - video_bpp = 1; - else video_bpp = 2; - - } - else video_bpp = 0; - t3100e->cga.cgablink++; - } - } -} - - - -void t3100e_recalcattrs(t3100e_t *t3100e) -{ - int n; - - /* val behaves as follows: - * Bit 0: Attributes 01-06, 08-0E are inverse video - * Bit 1: Attributes 01-06, 08-0E are bold - * Bit 2: Attributes 11-16, 18-1F, 21-26, 28-2F ... F1-F6, F8-FF - * are inverse video - * Bit 3: Attributes 11-16, 18-1F, 21-26, 28-2F ... F1-F6, F8-FF - * are bold */ - - /* Set up colours */ - amber = makecol(0xf7, 0x7C, 0x34); - black = makecol(0x17, 0x0C, 0x00); - - /* Initialise the attribute mapping. Start by defaulting everything - * to black on amber, and with bold set by bit 3 */ - for (n = 0; n < 256; n++) - { - boldcols[n] = (n & 8) != 0; - blinkcols[n][0] = normcols[n][0] = amber; + if (dev->attrmap & 4) { /* Inverse */ + blinkcols[n][0] = normcols[n][0] = amber; blinkcols[n][1] = normcols[n][1] = black; + } else { /* Normal */ + blinkcols[n][0] = normcols[n][0] = black; + blinkcols[n][1] = normcols[n][1] = amber; } + if (dev->attrmap & 8) + boldcols[n] = 1; /* Bold */ + } - /* Colours 0x11-0xFF are controlled by bits 2 and 3 of the - * passed value. Exclude x0 and x8, which are always black on - * amber. */ - for (n = 0x11; n <= 0xFF; n++) - { - if ((n & 7) == 0) continue; - if (t3100e->attrmap & 4) /* Inverse */ - { - blinkcols[n][0] = normcols[n][0] = amber; - blinkcols[n][1] = normcols[n][1] = black; - } - else /* Normal */ - { - blinkcols[n][0] = normcols[n][0] = black; - blinkcols[n][1] = normcols[n][1] = amber; - } - if (t3100e->attrmap & 8) boldcols[n] = 1; /* Bold */ - } - /* Set up the 01-0E range, controlled by bits 0 and 1 of the - * passed value. When blinking is enabled this also affects 81-8E. */ - for (n = 0x01; n <= 0x0E; n++) - { - if (n == 7) continue; - if (t3100e->attrmap & 1) - { - blinkcols[n][0] = normcols[n][0] = amber; - blinkcols[n][1] = normcols[n][1] = black; - blinkcols[n+128][0] = amber; - blinkcols[n+128][1] = black; - } - else - { - blinkcols[n][0] = normcols[n][0] = black; - blinkcols[n][1] = normcols[n][1] = amber; - blinkcols[n+128][0] = black; - blinkcols[n+128][1] = amber; - } - if (t3100e->attrmap & 2) boldcols[n] = 1; - } - /* Colours 07 and 0F are always amber on black. If blinking is - * enabled so are 87 and 8F. */ - for (n = 0x07; n <= 0x0F; n += 8) - { + /* Set up the 01-0E range, controlled by bits 0 and 1 of the + * passed value. When blinking is enabled this also affects + * 81-8E. + */ + for (n = 0x01; n <= 0x0E; n++) { + if (n == 7) continue; + + if (dev->attrmap & 1) { + blinkcols[n][0] = normcols[n][0] = amber; + blinkcols[n][1] = normcols[n][1] = black; + blinkcols[n+128][0] = amber; + blinkcols[n+128][1] = black; + } else { blinkcols[n][0] = normcols[n][0] = black; blinkcols[n][1] = normcols[n][1] = amber; blinkcols[n+128][0] = black; blinkcols[n+128][1] = amber; } - /* When not blinking, colours 81-8F are always amber on black. */ - for (n = 0x81; n <= 0x8F; n ++) - { - normcols[n][0] = black; - normcols[n][1] = amber; - boldcols[n] = (n & 0x08) != 0; + if (dev->attrmap & 2) + boldcols[n] = 1; + } + + /* Colors 07 and 0F are always amber on black. If + * blinking is enabled so are 87 and 8F. + */ + for (n = 0x07; n <= 0x0F; n += 8) { + blinkcols[n][0] = normcols[n][0] = black; + blinkcols[n][1] = normcols[n][1] = amber; + blinkcols[n+128][0] = black; + blinkcols[n+128][1] = amber; + } + + /* When not blinking, colors 81-8F are always amber on black. */ + for (n = 0x81; n <= 0x8F; n ++) { + normcols[n][0] = black; + normcols[n][1] = amber; + boldcols[n] = (n & 0x08) != 0; + } + + /* Finally do the ones which are solid black. These + * differ between the normal and blinking mappings. + */ + for (n = 0; n <= 0xFF; n += 0x11) + normcols[n][0] = normcols[n][1] = black; + + /* In the blinking range, 00 11 22 .. 77 and 80 91 A2 .. F7 are black */ + for (n = 0; n <= 0x77; n += 0x11) { + blinkcols[n][0] = blinkcols[n][1] = black; + blinkcols[n+128][0] = blinkcols[n+128][1] = black; + } +} + + +static void +t3100e_out(uint16_t port, uint8_t val, void *priv) +{ + t3100e_t *dev = (t3100e_t *)priv; + + switch (port) { + /* Emulated CRTC, register select */ + case 0x3d0: case 0x3d2: case 0x3d4: case 0x3d6: + cga_out(port, val, &dev->cga); + break; + + /* Emulated CRTC, value */ + case 0x3d1: case 0x3d3: case 0x3d5: case 0x3d7: + /* Register 0x12 controls the attribute mappings for the + * plasma screen. */ + if (dev->cga.crtcreg == 0x12) { + dev->attrmap = val; + recalc_attrs(dev); + return; + } + cga_out(port, val, &dev->cga); + + recalc_timings(dev); + return; + + /* CGA control register */ + case 0x3D8: + cga_out(port, val, &dev->cga); + return; + + /* CGA colour register */ + case 0x3D9: + cga_out(port, val, &dev->cga); + return; + } +} + + +static uint8_t +t3100e_in(uint16_t port, void *priv) +{ + t3100e_t *dev = (t3100e_t *)priv; + uint8_t ret; + + switch (port) { + case 0x3d1: case 0x3d3: case 0x3d5: case 0x3d7: + if (dev->cga.crtcreg == 0x12) { + ret = dev->attrmap & 0x0F; + if (dev->internal) + ret |= 0x30; /* Plasma / CRT */ + return ret; + } + break; + } + + return cga_in(port, &dev->cga); +} + + +static void +t3100e_write(uint32_t addr, uint8_t val, void *priv) +{ + t3100e_t *dev = (t3100e_t *)priv; + + dev->vram[addr & 0x7fff] = val; + + cycles -= 4; +} + + +static uint8_t +t3100e_read(uint32_t addr, void *priv) +{ + t3100e_t *dev = (t3100e_t *)priv; + + cycles -= 4; + + return dev->vram[addr & 0x7fff]; +} + + +/* Draw a row of text in 80-column mode */ +static void +text_row80(t3100e_t *dev) +{ + uint16_t ma = (dev->cga.crtc[13] | (dev->cga.crtc[12] << 8)) & 0x7fff; + uint16_t ca = (dev->cga.crtc[15] | (dev->cga.crtc[14] << 8)) & 0x7fff; + uint32_t cols[2]; + int x, c; + uint8_t chr, attr; + int drawcursor; + int cursorline; + int bold; + int blink; + uint16_t addr; + uint8_t sc; + + sc = (dev->displine) & 15; + addr = ((ma & ~1) + (dev->displine >> 4) * 80) * 2; + ma += (dev->displine >> 4) * 80; + + if ((dev->cga.crtc[10] & 0x60) == 0x20) { + cursorline = 0; + } else { + cursorline = ((dev->cga.crtc[10] & 0x0F)*2 <= sc) && + ((dev->cga.crtc[11] & 0x0F)*2 >= sc); + } + + for (x = 0; x < 80; x++) { + chr = dev->vram[(addr + 2 * x) & 0x7FFF]; + attr = dev->vram[(addr + 2 * x + 1) & 0x7FFF]; + drawcursor = ((ma == ca) && cursorline && + (dev->cga.cgamode & 8) && (dev->cga.cgablink & 16)); + + blink = ((dev->cga.cgablink & 16) && (dev->cga.cgamode & 0x20) && + (attr & 0x80) && !drawcursor); + + if (dev->video_options & 4) + bold = boldcols[attr] ? chr + 256 : chr; + else + bold = boldcols[attr] ? chr : chr + 256; + bold += 512 * (dev->video_options & 3); + + if (dev->cga.cgamode & 0x20) { /* Blink */ + cols[1] = blinkcols[attr][1]; + cols[0] = blinkcols[attr][0]; + if (blink) cols[1] = cols[0]; + } else { + cols[1] = normcols[attr][1]; + cols[0] = normcols[attr][0]; } - - /* Finally do the ones which are solid black. These differ between - * the normal and blinking mappings */ - for (n = 0; n <= 0xFF; n += 0x11) - { - normcols[n][0] = normcols[n][1] = black; + if (drawcursor) { + for (c = 0; c < 8; c++) { + ((uint32_t *)buffer32->line[dev->displine])[(x << 3) + c] = cols[(fontdatm[bold][sc] & (1 << (c ^ 7))) ? 1 : 0] ^ (amber ^ black); + } + } else { + for (c = 0; c < 8; c++) + ((uint32_t *)buffer32->line[dev->displine])[(x << 3) + c] = cols[(fontdatm[bold][sc] & (1 << (c ^ 7))) ? 1 : 0]; } - /* In the blinking range, 00 11 22 .. 77 and 80 91 A2 .. F7 are black */ - for (n = 0; n <= 0x77; n += 0x11) - { - blinkcols[n][0] = blinkcols[n][1] = black; - blinkcols[n+128][0] = blinkcols[n+128][1] = black; + ++ma; + } +} + + +/* Draw a row of text in 40-column mode */ +static void +text_row40(t3100e_t *dev) +{ + uint16_t ma = (dev->cga.crtc[13] | (dev->cga.crtc[12] << 8)) & 0x7fff; + uint16_t ca = (dev->cga.crtc[15] | (dev->cga.crtc[14] << 8)) & 0x7fff; + uint32_t cols[2]; + int x, c; + uint8_t chr, attr; + int drawcursor; + int cursorline; + int bold; + int blink; + uint16_t addr; + uint8_t sc; + + sc = (dev->displine) & 15; + addr = ((ma & ~1) + (dev->displine >> 4) * 40) * 2; + ma += (dev->displine >> 4) * 40; + + if ((dev->cga.crtc[10] & 0x60) == 0x20) { + cursorline = 0; + } else { + cursorline = ((dev->cga.crtc[10] & 0x0F)*2 <= sc) && + ((dev->cga.crtc[11] & 0x0F)*2 >= sc); + } + + for (x = 0; x < 40; x++) { + chr = dev->vram[(addr + 2 * x) & 0x7FFF]; + attr = dev->vram[(addr + 2 * x + 1) & 0x7FFF]; + drawcursor = ((ma == ca) && cursorline && + (dev->cga.cgamode & 8) && (dev->cga.cgablink & 16)); + + blink = ((dev->cga.cgablink & 16) && (dev->cga.cgamode & 0x20) && + (attr & 0x80) && !drawcursor); + + if (dev->video_options & 4) + bold = boldcols[attr] ? chr + 256 : chr; + else + bold = boldcols[attr] ? chr : chr + 256; + bold += 512 * (dev->video_options & 3); + + if (dev->cga.cgamode & 0x20) { /* Blink */ + cols[1] = blinkcols[attr][1]; + cols[0] = blinkcols[attr][0]; + if (blink) cols[1] = cols[0]; + } else { + cols[1] = normcols[attr][1]; + cols[0] = normcols[attr][0]; } + + if (drawcursor) { + for (c = 0; c < 8; c++) { + ((uint32_t *)buffer32->line[dev->displine])[(x << 4) + c*2] = ((uint32_t *)buffer32->line[dev->displine])[(x << 4) + c*2 + 1] = cols[(fontdatm[bold][sc] & (1 << (c ^ 7))) ? 1 : 0] ^ (amber ^ black); + } + } else { + for (c = 0; c < 8; c++) { + ((uint32_t *)buffer32->line[dev->displine])[(x << 4) + c*2] = ((uint32_t *)buffer32->line[dev->displine])[(x << 4) + c*2+1] = cols[(fontdatm[bold][sc] & (1 << (c ^ 7))) ? 1 : 0]; + } + } + ++ma; + } } -void *t3100e_init(const device_t *info) +/* Draw a line in CGA 640x200 or T3100e 640x400 mode */ +static void +cga_line6(t3100e_t *dev) { - t3100e_t *t3100e = malloc(sizeof(t3100e_t)); - memset(t3100e, 0, sizeof(t3100e_t)); - cga_init(&t3100e->cga); + uint16_t ma = (dev->cga.crtc[13] | (dev->cga.crtc[12] << 8)) & 0x7fff; + uint32_t fg = (dev->cga.cgacol & 0x0F) ? amber : black; + uint32_t bg = black; + uint8_t dat; + uint32_t ink = 0; + uint16_t addr; + int x, c; - t3100e->internal = 1; + if (dev->cga.crtc[9] == 3) { /* 640*400 */ + addr = ((dev->displine) & 1) * 0x2000 + + ((dev->displine >> 1) & 1) * 0x4000 + + (dev->displine >> 2) * 80 + + ((ma & ~1) << 1); + } else { + addr = ((dev->displine >> 1) & 1) * 0x2000 + + (dev->displine >> 2) * 80 + + ((ma & ~1) << 1); + } - /* 32k video RAM */ - t3100e->vram = malloc(0x8000); + for (x = 0; x < 80; x++) { + dat = dev->vram[addr & 0x7FFF]; + addr++; - timer_add(t3100e_poll, &t3100e->cga.vidtime, TIMER_ALWAYS_ENABLED, t3100e); - - /* Occupy memory between 0xB8000 and 0xBFFFF */ - mem_mapping_add(&t3100e->mapping, 0xb8000, 0x8000, t3100e_read, NULL, NULL, t3100e_write, NULL, NULL, NULL, 0, t3100e); - /* Respond to CGA I/O ports */ - io_sethandler(0x03d0, 0x000c, t3100e_in, NULL, NULL, t3100e_out, NULL, NULL, t3100e); - - /* Default attribute mapping is 4 */ - t3100e->attrmap = 4; - t3100e_recalcattrs(t3100e); - -/* Start off in 80x25 text mode */ - t3100e->cga.cgastat = 0xF4; - t3100e->cga.vram = t3100e->vram; - t3100e->enabled = 1; - t3100e->video_options = 0xFF; - return t3100e; + for (c = 0; c < 8; c++) { + ink = (dat & 0x80) ? fg : bg; + if (!(dev->cga.cgamode & 8)) + ink = black; + ((uint32_t *)buffer32->line[dev->displine])[x*8+c] = ink; + dat = dat << 1; + } + } } -void t3100e_close(void *p) -{ - t3100e_t *t3100e = (t3100e_t *)p; - free(t3100e->vram); - free(t3100e); +/* Draw a line in CGA 320x200 mode. Here the CGA colors are + * converted to dither patterns: color 1 to 25% grey, color + * 2 to 50% grey. + */ +static void +cga_line4(t3100e_t *dev) +{ + uint16_t ma = (dev->cga.crtc[13] | (dev->cga.crtc[12] << 8)) & 0x7fff; + uint8_t dat, pattern; + uint32_t ink0 = 0, ink1 = 0; + uint16_t addr; + int x, c; + + if (dev->cga.crtc[9] == 3) { /* 320*400 undocumented */ + addr = ((dev->displine) & 1) * 0x2000 + + ((dev->displine >> 1) & 1) * 0x4000 + + (dev->displine >> 2) * 80 + + ((ma & ~1) << 1); + } else { /* 320*200 */ + addr = ((dev->displine >> 1) & 1) * 0x2000 + + (dev->displine >> 2) * 80 + + ((ma & ~1) << 1); + } + + for (x = 0; x < 80; x++) { + dat = dev->vram[addr & 0x7FFF]; + addr++; + + for (c = 0; c < 4; c++) { + pattern = (dat & 0xC0) >> 6; + if (!(dev->cga.cgamode & 8)) pattern = 0; + + switch (pattern & 3) { + case 0: + ink0 = ink1 = black; break; + + case 1: + if (dev->displine & 1) { + ink0 = black; ink1 = black; + } else { + ink0 = amber; ink1 = black; + } + break; + + case 2: + if (dev->displine & 1) { + ink0 = black; ink1 = amber; + } else { + ink0 = amber; ink1 = black; + } + break; + + case 3: + ink0 = ink1 = amber; break; + + } + + ((uint32_t *)buffer32->line[dev->displine])[x*8+2*c] = ink0; + ((uint32_t *)buffer32->line[dev->displine])[x*8+2*c+1] = ink1; + dat = dat << 2; + } + } } -void t3100e_speed_changed(void *p) + +static void +t3100e_poll(void *priv) { - t3100e_t *t3100e = (t3100e_t *)p; - - t3100e_recalctimings(t3100e); + t3100e_t *dev = (t3100e_t *)priv; + + if (dev->video_options != st_video_options) { + dev->video_options = st_video_options; + + if (dev->video_options & 8) /* Disable internal CGA */ + mem_map_disable(&dev->mapping); + else + mem_map_enable(&dev->mapping); + + /* Set the font used for the external display */ + dev->cga.fontbase = (512 * (dev->video_options & 3)) + + ((dev->video_options & 4) ? 256 : 0); + + } + + /* Switch between internal plasma and external CRT display. */ + if (st_display_internal != -1 && st_display_internal != dev->internal) { + dev->internal = st_display_internal; + recalc_timings(dev); + } + + if (! dev->internal) { + cga_poll(&dev->cga); + return; + } + + if (! dev->linepos) { + dev->cga.vidtime += dev->dispofftime; + dev->cga.cgastat |= 1; + dev->linepos = 1; + if (dev->dispon) { + if (dev->displine == 0) + video_wait_for_buffer(); + + /* Graphics */ + if (dev->cga.cgamode & 0x02) { + if (dev->cga.cgamode & 0x10) + cga_line6(dev); + else + cga_line4(dev); + } else if (dev->cga.cgamode & 0x01) { /* High-res text */ + text_row80(dev); + } else { + text_row40(dev); + } + } + dev->displine++; + + /* Hardcode a fixed refresh rate and VSYNC timing */ + if (dev->displine == 400) { /* Start of VSYNC */ + dev->cga.cgastat |= 8; + dev->dispon = 0; + } + + if (dev->displine == 416) { /* End of VSYNC */ + dev->displine = 0; + dev->cga.cgastat &= ~8; + dev->dispon = 1; + } + } else { + if (dev->dispon) + dev->cga.cgastat &= ~1; + dev->cga.vidtime += dev->dispontime; + dev->linepos = 0; + + if (dev->displine == 400) { + /* Hardcode 640x400 window size */ + if (T3100E_XSIZE != xsize || T3100E_YSIZE != ysize) { + xsize = T3100E_XSIZE; + ysize = T3100E_YSIZE; + if (xsize < 64) xsize = 656; + if (ysize < 32) ysize = 200; + set_screen_size(xsize, ysize); + } + video_blit_memtoscreen(0, 0, 0, ysize, xsize, ysize); + frames++; + + /* Fixed 640x400 resolution */ + video_res_x = T3100E_XSIZE; + video_res_y = T3100E_YSIZE; + + if (dev->cga.cgamode & 0x02) { + if (dev->cga.cgamode & 0x10) + video_bpp = 1; + else + video_bpp = 2; + } else + video_bpp = 0; + dev->cga.cgablink++; + } + } } -const device_t t3100e_device = + +static void * +t3100e_init(const device_t *info) { - "Toshiba T3100e", - 0, - 0, - t3100e_init, - t3100e_close, - NULL, - NULL, - t3100e_speed_changed, - NULL, - NULL + t3100e_t *dev; + + dev = (t3100e_t *)mem_alloc(sizeof(t3100e_t)); + memset(dev, 0x00, sizeof(t3100e_t)); + + cga_init(&dev->cga); + + dev->internal = 1; + + /* 32K video RAM */ + dev->vram = (uint8_t *)mem_alloc(0x8000); + + timer_add(t3100e_poll, &dev->cga.vidtime, TIMER_ALWAYS_ENABLED, dev); + + /* Occupy memory between 0xB8000 and 0xBFFFF */ + mem_map_add(&dev->mapping, 0xb8000, 0x8000, + t3100e_read,NULL,NULL, t3100e_write,NULL,NULL, + NULL, 0, dev); + + /* Respond to CGA I/O ports */ + io_sethandler(0x03d0, 12, + t3100e_in,NULL,NULL, t3100e_out,NULL,NULL, dev); + + /* Default attribute mapping is 4 */ + dev->attrmap = 4; + recalc_attrs(dev); + + /* Start off in 80x25 text mode */ + dev->cga.cgastat = 0xf4; + dev->cga.vram = dev->vram; + dev->enabled = 1; + dev->video_options = 0xff; + + video_inform(VID_TYPE_CGA, + (const video_timings_t *)info->vid_timing); + + return dev; +} + + +static void +t3100e_close(void *priv) +{ + t3100e_t *dev = (t3100e_t *)priv; + + free(dev->vram); + free(dev); +} + + +static void +speed_changed(void *priv) +{ + t3100e_t *dev = (t3100e_t *)priv; + + recalc_timings(dev); +} + + +static video_timings_t t3100e_timing = { VID_ISA, 8,16,32, 8,16,32 }; + +const device_t t3100e_device = { + "Toshiba T3100e", + 0, + 0, + t3100e_init, t3100e_close, NULL, + NULL, + speed_changed, + NULL, + &t3100e_timing, + NULL }; + + +void +t3100e_video_options_set(uint8_t options) +{ + st_video_options = options; +} + + +void +t3100e_display_set(uint8_t internal) +{ + st_display_internal = internal; +} + + +uint8_t +t3100e_display_get(void) +{ + return st_display_internal; +} diff --git a/src/machines/m_at_wd76c10.c b/src/machines/m_at_wd76c10.c index 04f1f9e..2e39513 100644 --- a/src/machines/m_at_wd76c10.c +++ b/src/machines/m_at_wd76c10.c @@ -8,7 +8,7 @@ * * Implementation of the WD76C10 system controller. * - * Version: @(#)m_at_wd76c10.c 1.0.8 2018/05/06 + * Version: @(#)m_at_wd76c10.c 1.0.9 2018/09/19 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -88,8 +88,6 @@ wd76c10_read(uint16_t port, void *priv) static void wd76c10_write(uint16_t port, uint16_t val, void *priv) { - pclog("WD76C10 write %04X %04X\n", port, val); - switch (port) { case 0x0092: wd76c10_0092 = val; @@ -196,7 +194,7 @@ machine_at_wd76c10_init(const machine_t *model, void *arg) machine_at_common_ide_init(model, arg); device_add(&keyboard_ps2_quadtel_device); - wd76c10_fdc = device_add(&fdc_at_device); + wd76c10_fdc = (fdc_t *)device_add(&fdc_at_device); wd76c10_init(); diff --git a/src/machines/m_europc.c b/src/machines/m_europc.c index 088aed2..d2c167c 100644 --- a/src/machines/m_europc.c +++ b/src/machines/m_europc.c @@ -66,7 +66,10 @@ * bit 1: b8000 memory available * 0000:046a: 00 jim 250 01 jim 350 * - * Version: @(#)m_europc.c 1.0.16 2018/08/27 + * FIXME: Find a new way to handle the switching of color/mono on + * external cards. New video_get_type(int card) function? + * + * Version: @(#)m_europc.c 1.0.17 2018/10/05 * * Author: Fred N. van Kempen, * @@ -109,16 +112,16 @@ */ #include #include -#include #include +#include #include #include #include "../emu.h" #include "../io.h" #include "../mem.h" #include "../rom.h" -#include "../nvr.h" #include "../device.h" +#include "../nvr.h" #include "../devices/system/nmi.h" #include "../devices/ports/parallel.h" #include "../devices/input/keyboard.h" @@ -130,9 +133,6 @@ #include "machine.h" -#define EUROPC_DEBUG 0 /* current debugging level */ - - /* M3002 RTC chip registers. */ #define MRTC_SECONDS 0x00 /* BCD, 00-59 */ #define MRTC_MINUTES 0x01 /* BCD, 00-59 */ @@ -151,6 +151,7 @@ #define MRTC_CHECK_HI 0x0e /* Checksum, high byte */ #define MRTC_CTRLSTAT 0x0f /* RTC control/status, binary */ + typedef struct { uint16_t jim; /* JIM base address */ @@ -178,7 +179,7 @@ static europc_t europc; * FIXME: should we mark NVR as dirty? */ static void -rtc_tick(nvr_t *nvr) +rtc_ticker(nvr_t *nvr) { uint8_t *regs; int mon, yr; @@ -225,7 +226,7 @@ rtc_time_get(uint8_t *regs, struct tm *tm) tm->tm_mday = RTC_DCB(regs[MRTC_DAYS]); tm->tm_mon = (RTC_DCB(regs[MRTC_MONTHS]) - 1); tm->tm_year = RTC_DCB(regs[MRTC_YEARS]); -#if 0 /*USE_Y2K*/ +#ifdef MRTC_CENTURY tm->tm_year += (RTC_DCB(regs[MRTC_CENTURY]) * 100) - 1900; #endif } @@ -243,7 +244,7 @@ rtc_time_set(uint8_t *regs, struct tm *tm) regs[MRTC_DAYS] = RTC_BCD(tm->tm_mday); regs[MRTC_MONTHS] = RTC_BCD(tm->tm_mon + 1); regs[MRTC_YEARS] = RTC_BCD(tm->tm_year % 100); -#if 0 /*USE_Y2K*/ +#ifdef MRTC_CENTURY regs[MRTC_CENTURY] = RTC_BCD((tm->tm_year+1900) / 100); #endif } @@ -255,7 +256,7 @@ rtc_start(nvr_t *nvr) struct tm tm; /* Initialize the internal and chip times. */ - if (enable_sync) { + if (time_sync != TIME_SYNC_DISABLED) { /* Use the internal clock's time. */ nvr_time_get(&tm); rtc_time_set(nvr->regs, &tm); @@ -367,8 +368,8 @@ jim_set(europc_t *sys, uint8_t reg, uint8_t val) { switch(reg) { case 0: /* MISC control (WO) */ - // bit0: enable MOUSE - // bit1: enable joystick + /* bit0: enable MOUSE */ + /* bit1: enable joystick */ break; case 2: /* AGA control */ @@ -380,27 +381,27 @@ jim_set(europc_t *sys, uint8_t reg, uint8_t val) switch (val) { case 0x1f: /* 0001 1111 */ case 0x0b: /* 0000 1011 */ - //europc_jim.mode=AGA_MONO; - pclog("EuroPC: AGA Monochrome mode!\n"); + /*europc_jim.mode=AGA_MONO; */ + DEBUG("EuroPC: AGA Monochrome mode!\n"); break; case 0x18: /* 0001 1000 */ case 0x1a: /* 0001 1010 */ - //europc_jim.mode=AGA_COLOR; + /*europc_jim.mode=AGA_COLOR; */ break; case 0x0e: /* 0000 1100 */ /*80 columns? */ - pclog("EuroPC: AGA 80-column mode!\n"); + DEBUG("EuroPC: AGA 80-column mode!\n"); break; case 0x0d: /* 0000 1011 */ /*40 columns? */ - pclog("EuroPC: AGA 40-column mode!\n"); + DEBUG("EuroPC: AGA 40-column mode!\n"); break; default: - //europc_jim.mode=AGA_OFF; + /*europc_jim.mode=AGA_OFF; */ break; } break; @@ -408,15 +409,15 @@ jim_set(europc_t *sys, uint8_t reg, uint8_t val) case 4: /* CPU Speed control */ switch(val & 0xc0) { case 0x00: /* 4.77 MHz */ -// cpu_set_clockscale(0, 1.0/2); +/*FIXME: cpu_set_clockscale(0, 1.0/2); */ break; case 0x40: /* 7.16 MHz */ -// cpu_set_clockscale(0, 3.0/4); +/*FIXME: cpu_set_clockscale(0, 3.0/4); */ break; default: /* 9.54 MHz */ -// cpu_set_clockscale(0, 1);break; +/*FIXME: cpu_set_clockscale(0, 1);break; */ break; } break; @@ -436,9 +437,7 @@ jim_write(uint16_t addr, uint8_t val, void *priv) europc_t *sys = (europc_t *)priv; uint8_t b; -#if EUROPC_DEBUG > 1 - pclog("EuroPC: jim_wr(%04x, %02x)\n", addr, val); -#endif + DBGLOG(2, "EuroPC: jim_wr(%04x, %02x)\n", addr, val); switch (addr & 0x000f) { case 0x00: /* JIM internal registers (WRONLY) */ @@ -478,7 +477,7 @@ jim_write(uint16_t addr, uint8_t val, void *priv) break; default: - pclog("EuroPC: invalid JIM write %02x, val %02x\n", addr, val); + ERRLOG("EuroPC: invalid JIM write %02x, val %02x\n", addr, val); break; } } @@ -525,13 +524,11 @@ jim_read(uint16_t addr, void *priv) break; default: - pclog("EuroPC: invalid JIM read %02x\n", addr); + ERRLOG("EuroPC: invalid JIM read %02x\n", addr); break; } -#if EUROPC_DEBUG > 1 - pclog("EuroPC: jim_rd(%04x): %02x\n", addr, r); -#endif + DBGLOG(2, "EuroPC: jim_rd(%04x): %02x\n", addr, r); return(r); } @@ -543,16 +540,28 @@ europc_boot(const device_t *info) { europc_t *sys = &europc; uint8_t b; + int vid; -#if EUROPC_DEBUG - pclog("EuroPC: booting mainboard..\n"); -#endif + DEBUG("EuroPC: booting mainboard..\n"); - pclog("EuroPC: NVR=[ %02x %02x %02x %02x %02x ] %sVALID\n", - sys->nvr.regs[MRTC_CONF_A], sys->nvr.regs[MRTC_CONF_B], - sys->nvr.regs[MRTC_CONF_C], sys->nvr.regs[MRTC_CONF_D], - sys->nvr.regs[MRTC_CONF_E], - (sys->nvr.regs[MRTC_CHECK_LO]!=rtc_checksum(sys->nvr.regs))?"IN":""); + /* + * This is not quite correct, but it works. + * + * The EuroPC has an onboard CGA-class video controller + * (AGA) which is normally used. We currently do not yet + * support it. To keep the NVRAM valid, however, we act + * like we have it configured. + */ + if (video_card == VID_INTERNAL) { + INFO("EuroPC: enabling CGA in place of AGA!\n"); + device_add(&cga_device); + } + + DEBUG("EuroPC: NVR=[ %02x %02x %02x %02x %02x ] %sVALID\n", + sys->nvr.regs[MRTC_CONF_A], sys->nvr.regs[MRTC_CONF_B], + sys->nvr.regs[MRTC_CONF_C], sys->nvr.regs[MRTC_CONF_D], + sys->nvr.regs[MRTC_CONF_E], + (sys->nvr.regs[MRTC_CHECK_LO]!=rtc_checksum(sys->nvr.regs))?"IN":""); /* * Now that we have initialized the NVR (either from file, @@ -560,21 +569,48 @@ europc_boot(const device_t *info) * with values set by the user. */ b = (sys->nvr.regs[MRTC_CONF_D] & ~0x17); - switch(video_card) { - case VID_CGA: /* Color, CGA */ - case VID_COLORPLUS: /* Color, Hercules ColorPlus */ - b |= 0x12; /* external video, CGA80 */ - break; + if (video_card != VID_INTERNAL) { + /* + * OK, this is not exactly correct, either. + * + * If we use an external video card, that will not be + * installed until after we boot the mainboard, so we + * do not know about it yet. Therefore, we just peek + * at the configured video card type, and perform an + * "educated guess" as to its type.. + */ + switch(video_card) { + case VID_MDA: /* MDA */ + case VID_HERCULES: /* Hercules */ + b |= 0x03; /* external video, mono */ + break; - case VID_MDA: /* Monochrome, MDA */ - case VID_HERCULES: /* Monochrome, Hercules */ - case VID_INCOLOR: /* Color, ? */ - b |= 0x03; /* external video, mono */ - break; + case VID_CGA: /* Color, CGA */ + b |= 0x12; /* external video, CGA80 */ + break; - default: /* EGA, VGA etc */ - b |= 0x10; /* external video, special */ + default: /* all others */ + b |= 0x10; /* external video, special */ + } + } else { + vid = video_type(); + switch(vid) { + case VID_TYPE_MDA: /* Monochrome, MDA, Hercules */ + b |= 0x03; /* external video, mono */ + break; + case VID_TYPE_CGA: /* Color, CGA */ + b |= 0x12; /* external video, CGA80 */ + break; + + case VID_TYPE_SPEC: /* EGA, VGA etc */ + b |= 0x10; /* external video, special */ + break; + + default: + ERRLOG("EuroPC: unknown video type %d !\n", vid); + break; + } } sys->nvr.regs[MRTC_CONF_D] = b; @@ -639,7 +675,7 @@ europc_boot(const device_t *info) else b |= 0x02; /* 3.5" DD */ } else - pclog("EuroPC: unsupported HD type for floppy drive 0\n"); + ERRLOG("EuroPC: unsupported HD type for floppy drive 0\n"); } if (fdd_get_type(1) != 0) { /* We have floppy B: */ @@ -650,7 +686,7 @@ europc_boot(const device_t *info) else b |= 0x10; /* 3.5" DD */ } else - pclog("EuroPC: unsupported HD type for floppy drive 1\n"); + ERRLOG("EuroPC: unsupported HD type for floppy drive 1\n"); } sys->nvr.regs[MRTC_CONF_B] = b; @@ -680,7 +716,7 @@ europc_boot(const device_t *info) * * We only do this if we have not configured another one. */ - if (hdc_type == 1) + if (hdc_type == HDC_INTERNAL) (void)device_add(&xta_hd20_device); return(sys); @@ -722,7 +758,8 @@ static const device_config_t europc_config[] = { const device_t europc_device = { "EuroPC System Board", - 0, 0, + 0, + 0, europc_boot, europc_close, NULL, NULL, NULL, NULL, NULL, europc_config @@ -755,7 +792,7 @@ machine_europc_init(const machine_t *model, void *arg) /* Set up any local handlers here. */ europc.nvr.reset = rtc_reset; europc.nvr.start = rtc_start; - europc.nvr.tick = rtc_tick; + europc.nvr.tick = rtc_ticker; /* Initialize the actual NVR. */ nvr_init(&europc.nvr); diff --git a/src/machines/m_olivetti_m24.c b/src/machines/m_olivetti_m24.c index 48e4273..0b17f7f 100644 --- a/src/machines/m_olivetti_m24.c +++ b/src/machines/m_olivetti_m24.c @@ -8,7 +8,7 @@ * * Emulation of the Olivetti M24. * - * Version: @(#)m_olivetti_m24.c 1.0.11 2018/05/06 + * Version: @(#)m_olivetti_m24.c 1.0.12 2018/10/05 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -38,10 +38,11 @@ */ #include #include -#include #include +#include #include #include +#define dbglog kbd_log #include "../emu.h" #include "../io.h" #include "../mem.h" @@ -59,6 +60,7 @@ #include "../devices/sound/sound.h" #include "../devices/sound/snd_speaker.h" #include "../devices/video/video.h" +#include "../devices/video/vid_cga.h" #include "machine.h" @@ -74,7 +76,7 @@ typedef struct { /* Video stuff. */ - mem_mapping_t mapping; + mem_map_t mapping; uint8_t crtc[32]; int crtcreg; uint8_t monitor_type, @@ -114,7 +116,7 @@ typedef struct { } olim24_t; -static uint8_t crtcmask[32] = { +static const uint8_t crtcmask[32] = { 0xff, 0xff, 0xff, 0xff, 0x7f, 0x1f, 0x7f, 0x7f, 0xf3, 0x1f, 0x7f, 0x1f, 0x3f, 0xff, 0x3f, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -126,67 +128,67 @@ static int key_queue_start = 0, static void -recalc_timings(olim24_t *m24) +recalc_timings(olim24_t *dev) { double _dispontime, _dispofftime, disptime; - if (m24->cgamode & 1) { - disptime = m24->crtc[0] + 1; - _dispontime = m24->crtc[1]; + if (dev->cgamode & 1) { + disptime = dev->crtc[0] + 1; + _dispontime = dev->crtc[1]; } else { - disptime = (m24->crtc[0] + 1) << 1; - _dispontime = m24->crtc[1] << 1; + disptime = (dev->crtc[0] + 1) << 1; + _dispontime = dev->crtc[1] << 1; } _dispofftime = disptime - _dispontime; _dispontime *= CGACONST / 2; _dispofftime *= CGACONST / 2; - m24->dispontime = (int64_t)(_dispontime * (1 << TIMER_SHIFT)); - m24->dispofftime = (int64_t)(_dispofftime * (1 << TIMER_SHIFT)); + dev->dispontime = (int64_t)(_dispontime * (1 << TIMER_SHIFT)); + dev->dispofftime = (int64_t)(_dispofftime * (1 << TIMER_SHIFT)); } static void vid_out(uint16_t addr, uint8_t val, void *priv) { - olim24_t *m24 = (olim24_t *)priv; + olim24_t *dev = (olim24_t *)priv; uint8_t old; switch (addr) { case 0x03d4: - m24->crtcreg = val & 31; + dev->crtcreg = val & 31; break; case 0x03d5: - old = m24->crtc[m24->crtcreg]; - m24->crtc[m24->crtcreg] = val & crtcmask[m24->crtcreg]; + old = dev->crtc[dev->crtcreg]; + dev->crtc[dev->crtcreg] = val & crtcmask[dev->crtcreg]; if (old != val) { - if (m24->crtcreg < 0xe || m24->crtcreg > 0x10) { + if (dev->crtcreg < 0xe || dev->crtcreg > 0x10) { fullchange = changeframecount; - recalc_timings(m24); + recalc_timings(dev); } } break; case 0x03d8: - m24->cgamode = val; + dev->cgamode = val; break; case 0x03d9: - m24->cgacol = val; + dev->cgacol = val; break; case 0x03de: - m24->ctrl = val; - m24->base = (val & 0x08) ? 0x4000 : 0; + dev->ctrl = val; + dev->base = (val & 0x08) ? 0x4000 : 0; break; case 0x13c6: - m24->monitor_type = val; + dev->monitor_type = val; break; case 0x23c6: - m24->port_23c6 = val; + dev->port_23c6 = val; break; } } @@ -195,28 +197,28 @@ vid_out(uint16_t addr, uint8_t val, void *priv) static uint8_t vid_in(uint16_t addr, void *priv) { - olim24_t *m24 = (olim24_t *)priv; + olim24_t *dev = (olim24_t *)priv; uint8_t ret = 0xff; switch (addr) { case 0x03d4: - ret = m24->crtcreg; + ret = dev->crtcreg; break; case 0x03d5: - ret = m24->crtc[m24->crtcreg]; + ret = dev->crtc[dev->crtcreg]; break; case 0x03da: - ret = m24->stat; + ret = dev->stat; break; case 0x13c6: - ret = m24->monitor_type; + ret = dev->monitor_type; break; case 0x23c6: - ret = m24->port_23c6; + ret = dev->port_23c6; break; } @@ -227,28 +229,28 @@ vid_in(uint16_t addr, void *priv) static void vid_write(uint32_t addr, uint8_t val, void *priv) { - olim24_t *m24 = (olim24_t *)priv; + olim24_t *dev = (olim24_t *)priv; - m24->vram[addr & 0x7fff] = val; - m24->charbuffer[ ((int)(((m24->dispontime - m24->vidtime) * 2) / (CGACONST / 2))) & 0xfc] = val; - m24->charbuffer[(((int)(((m24->dispontime - m24->vidtime) * 2) / (CGACONST / 2))) & 0xfc) | 1] = val; + dev->vram[addr & 0x7fff] = val; + dev->charbuffer[ ((int)(((dev->dispontime - dev->vidtime) * 2) / (CGACONST / 2))) & 0xfc] = val; + dev->charbuffer[(((int)(((dev->dispontime - dev->vidtime) * 2) / (CGACONST / 2))) & 0xfc) | 1] = val; } static uint8_t vid_read(uint32_t addr, void *priv) { - olim24_t *m24 = (olim24_t *)priv; + olim24_t *dev = (olim24_t *)priv; - return(m24->vram[addr & 0x7fff]); + return(dev->vram[addr & 0x7fff]); } static void vid_poll(void *priv) { - olim24_t *m24 = (olim24_t *)priv; - uint16_t ca = (m24->crtc[15] | (m24->crtc[14] << 8)) & 0x3fff; + olim24_t *dev = (olim24_t *)priv; + uint16_t ca = (dev->crtc[15] | (dev->crtc[14] << 8)) & 0x3fff; int drawcursor; int x, c; int oldvc; @@ -258,42 +260,42 @@ vid_poll(void *priv) int col; int oldsc; - if (!m24->linepos) { - m24->vidtime += m24->dispofftime; - m24->stat |= 1; - m24->linepos = 1; - oldsc = m24->sc; - if ((m24->crtc[8] & 3) == 3) - m24->sc = (m24->sc << 1) & 7; - if (m24->dispon) { - if (m24->displine < m24->firstline) { - m24->firstline = m24->displine; + if (!dev->linepos) { + dev->vidtime += dev->dispofftime; + dev->stat |= 1; + dev->linepos = 1; + oldsc = dev->sc; + if ((dev->crtc[8] & 3) == 3) + dev->sc = (dev->sc << 1) & 7; + if (dev->dispon) { + if (dev->displine < dev->firstline) { + dev->firstline = dev->displine; } - m24->lastline = m24->displine; + dev->lastline = dev->displine; for (c = 0; c < 8; c++) { - if ((m24->cgamode & 0x12) == 0x12) { - buffer->line[m24->displine][c] = 0; - if (m24->cgamode & 1) - buffer->line[m24->displine][c + (m24->crtc[1] << 3) + 8] = 0; + if ((dev->cgamode & 0x12) == 0x12) { + buffer->line[dev->displine][c] = 0; + if (dev->cgamode & 1) + buffer->line[dev->displine][c + (dev->crtc[1] << 3) + 8] = 0; else - buffer->line[m24->displine][c + (m24->crtc[1] << 4) + 8] = 0; + buffer->line[dev->displine][c + (dev->crtc[1] << 4) + 8] = 0; } else { - buffer->line[m24->displine][c] = (m24->cgacol & 15) + 16; - if (m24->cgamode & 1) - buffer->line[m24->displine][c + (m24->crtc[1] << 3) + 8] = (m24->cgacol & 15) + 16; + buffer->line[dev->displine][c] = (dev->cgacol & 15) + 16; + if (dev->cgamode & 1) + buffer->line[dev->displine][c + (dev->crtc[1] << 3) + 8] = (dev->cgacol & 15) + 16; else - buffer->line[m24->displine][c + (m24->crtc[1] << 4) + 8] = (m24->cgacol & 15) + 16; + buffer->line[dev->displine][c + (dev->crtc[1] << 4) + 8] = (dev->cgacol & 15) + 16; } } - if (m24->cgamode & 1) { - for (x = 0; x < m24->crtc[1]; x++) { - chr = m24->charbuffer[ x << 1]; - attr = m24->charbuffer[(x << 1) + 1]; - drawcursor = ((m24->ma == ca) && m24->con && m24->cursoron); - if (m24->cgamode & 0x20) { + if (dev->cgamode & 1) { + for (x = 0; x < dev->crtc[1]; x++) { + chr = dev->charbuffer[ x << 1]; + attr = dev->charbuffer[(x << 1) + 1]; + drawcursor = ((dev->ma == ca) && dev->con && dev->cursoron); + if (dev->cgamode & 0x20) { cols[1] = (attr & 15) + 16; cols[0] = ((attr >> 4) & 7) + 16; - if ((m24->blink & 16) && (attr & 0x80) && !drawcursor) + if ((dev->blink & 16) && (attr & 0x80) && !drawcursor) cols[1] = cols[0]; } else { cols[1] = (attr & 15) + 16; @@ -301,46 +303,46 @@ vid_poll(void *priv) } if (drawcursor) { for (c = 0; c < 8; c++) - buffer->line[m24->displine][(x << 3) + c + 8] = cols[(fontdatm[chr][((m24->sc & 7) << 1) | m24->lineff] & (1 << (c ^ 7))) ? 1 : 0] ^ 15; + buffer->line[dev->displine][(x << 3) + c + 8] = cols[(fontdatm[chr][((dev->sc & 7) << 1) | dev->lineff] & (1 << (c ^ 7))) ? 1 : 0] ^ 15; } else { for (c = 0; c < 8; c++) - buffer->line[m24->displine][(x << 3) + c + 8] = cols[(fontdatm[chr][((m24->sc & 7) << 1) | m24->lineff] & (1 << (c ^ 7))) ? 1 : 0]; + buffer->line[dev->displine][(x << 3) + c + 8] = cols[(fontdatm[chr][((dev->sc & 7) << 1) | dev->lineff] & (1 << (c ^ 7))) ? 1 : 0]; } - m24->ma++; + dev->ma++; } - } else if (!(m24->cgamode & 2)) { - for (x = 0; x < m24->crtc[1]; x++) { - chr = m24->vram[((m24->ma << 1) & 0x3fff) + m24->base]; - attr = m24->vram[(((m24->ma << 1) + 1) & 0x3fff) + m24->base]; - drawcursor = ((m24->ma == ca) && m24->con && m24->cursoron); - if (m24->cgamode & 0x20) { + } else if (!(dev->cgamode & 2)) { + for (x = 0; x < dev->crtc[1]; x++) { + chr = dev->vram[((dev->ma << 1) & 0x3fff) + dev->base]; + attr = dev->vram[(((dev->ma << 1) + 1) & 0x3fff) + dev->base]; + drawcursor = ((dev->ma == ca) && dev->con && dev->cursoron); + if (dev->cgamode & 0x20) { cols[1] = (attr & 15) + 16; cols[0] = ((attr >> 4) & 7) + 16; - if ((m24->blink & 16) && (attr & 0x80)) + if ((dev->blink & 16) && (attr & 0x80)) cols[1] = cols[0]; } else { cols[1] = (attr & 15) + 16; cols[0] = (attr >> 4) + 16; } - m24->ma++; + dev->ma++; if (drawcursor) { for (c = 0; c < 8; c++) - buffer->line[m24->displine][(x << 4) + (c << 1) + 8] = - buffer->line[m24->displine][(x << 4) + (c << 1) + 1 + 8] = cols[(fontdatm[chr][((m24->sc & 7) << 1) | m24->lineff] & (1 << (c ^ 7))) ? 1 : 0] ^ 15; + buffer->line[dev->displine][(x << 4) + (c << 1) + 8] = + buffer->line[dev->displine][(x << 4) + (c << 1) + 1 + 8] = cols[(fontdatm[chr][((dev->sc & 7) << 1) | dev->lineff] & (1 << (c ^ 7))) ? 1 : 0] ^ 15; } else { for (c = 0; c < 8; c++) - buffer->line[m24->displine][(x << 4) + (c << 1) + 8] = - buffer->line[m24->displine][(x << 4) + (c << 1) + 1 + 8] = cols[(fontdatm[chr][((m24->sc & 7) << 1) | m24->lineff] & (1 << (c ^ 7))) ? 1 : 0]; + buffer->line[dev->displine][(x << 4) + (c << 1) + 8] = + buffer->line[dev->displine][(x << 4) + (c << 1) + 1 + 8] = cols[(fontdatm[chr][((dev->sc & 7) << 1) | dev->lineff] & (1 << (c ^ 7))) ? 1 : 0]; } } - } else if (! (m24->cgamode & 16)) { - cols[0] = (m24->cgacol & 15) | 16; - col = (m24->cgacol & 16) ? 24 : 16; - if (m24->cgamode & 4) { + } else if (! (dev->cgamode & 16)) { + cols[0] = (dev->cgacol & 15) | 16; + col = (dev->cgacol & 16) ? 24 : 16; + if (dev->cgamode & 4) { cols[1] = col | 3; cols[2] = col | 4; cols[3] = col | 7; - } else if (m24->cgacol & 32) { + } else if (dev->cgacol & 32) { cols[1] = col | 3; cols[2] = col | 5; cols[3] = col | 7; @@ -349,114 +351,116 @@ vid_poll(void *priv) cols[2] = col | 4; cols[3] = col | 6; } - for (x = 0; x < m24->crtc[1]; x++) { - dat = (m24->vram[((m24->ma << 1) & 0x1fff) + ((m24->sc & 1) * 0x2000) + m24->base] << 8) | - m24->vram[((m24->ma << 1) & 0x1fff) + ((m24->sc & 1) * 0x2000) + 1 + m24->base]; - m24->ma++; + for (x = 0; x < dev->crtc[1]; x++) { + dat = (dev->vram[((dev->ma << 1) & 0x1fff) + ((dev->sc & 1) * 0x2000) + dev->base] << 8) | + dev->vram[((dev->ma << 1) & 0x1fff) + ((dev->sc & 1) * 0x2000) + 1 + dev->base]; + dev->ma++; for (c = 0; c < 8; c++) { - buffer->line[m24->displine][(x << 4) + (c << 1) + 8] = - buffer->line[m24->displine][(x << 4) + (c << 1) + 1 + 8] = cols[dat >> 14]; + buffer->line[dev->displine][(x << 4) + (c << 1) + 8] = + buffer->line[dev->displine][(x << 4) + (c << 1) + 1 + 8] = cols[dat >> 14]; dat <<= 2; } } } else { - if (m24->ctrl & 1 || ((m24->monitor_type & 8) && (m24->port_23c6 & 1))) { - dat2 = ((m24->sc & 1) * 0x4000) | (m24->lineff * 0x2000); - cols[0] = 0; cols[1] = /*(m24->cgacol & 15)*/15 + 16; + if (dev->ctrl & 1 || ((dev->monitor_type & 8) && (dev->port_23c6 & 1))) { + dat2 = ((dev->sc & 1) * 0x4000) | (dev->lineff * 0x2000); + cols[0] = 0; cols[1] = /*(dev->cgacol & 15)*/15 + 16; } else { - dat2 = (m24->sc & 1) * 0x2000; - cols[0] = 0; cols[1] = (m24->cgacol & 15) + 16; + dat2 = (dev->sc & 1) * 0x2000; + cols[0] = 0; cols[1] = (dev->cgacol & 15) + 16; } - for (x = 0; x < m24->crtc[1]; x++) { - dat = (m24->vram[((m24->ma << 1) & 0x1fff) + dat2] << 8) | m24->vram[((m24->ma << 1) & 0x1fff) + dat2 + 1]; - m24->ma++; + for (x = 0; x < dev->crtc[1]; x++) { + dat = (dev->vram[((dev->ma << 1) & 0x1fff) + dat2] << 8) | dev->vram[((dev->ma << 1) & 0x1fff) + dat2 + 1]; + dev->ma++; for (c = 0; c < 16; c++) { - buffer->line[m24->displine][(x << 4) + c + 8] = cols[dat >> 15]; + buffer->line[dev->displine][(x << 4) + c + 8] = cols[dat >> 15]; dat <<= 1; } } } } else { - cols[0] = ((m24->cgamode & 0x12) == 0x12) ? 0 : (m24->cgacol & 15) + 16; - if (m24->cgamode & 1) hline(buffer, 0, m24->displine, (m24->crtc[1] << 3) + 16, cols[0]); - else hline(buffer, 0, m24->displine, (m24->crtc[1] << 4) + 16, cols[0]); + cols[0] = ((dev->cgamode & 0x12) == 0x12) ? 0 : (dev->cgacol & 15) + 16; + if (dev->cgamode & 1) + cga_hline(buffer, 0, dev->displine, (dev->crtc[1] << 3) + 16, cols[0]); + else + cga_hline(buffer, 0, dev->displine, (dev->crtc[1] << 4) + 16, cols[0]); } - if (m24->cgamode & 1) - x = (m24->crtc[1] << 3) + 16; + if (dev->cgamode & 1) + x = (dev->crtc[1] << 3) + 16; else - x = (m24->crtc[1] << 4) + 16; + x = (dev->crtc[1] << 4) + 16; - m24->sc = oldsc; - if (m24->vc == m24->crtc[7] && !m24->sc) - m24->stat |= 8; - m24->displine++; - if (m24->displine >= 720) - m24->displine = 0; + dev->sc = oldsc; + if (dev->vc == dev->crtc[7] && !dev->sc) + dev->stat |= 8; + dev->displine++; + if (dev->displine >= 720) + dev->displine = 0; } else { - m24->vidtime += m24->dispontime; - if (m24->dispon) m24->stat &= ~1; - m24->linepos = 0; - m24->lineff ^= 1; - if (m24->lineff) { - m24->ma = m24->maback; + dev->vidtime += dev->dispontime; + if (dev->dispon) dev->stat &= ~1; + dev->linepos = 0; + dev->lineff ^= 1; + if (dev->lineff) { + dev->ma = dev->maback; } else { - if (m24->vsynctime) { - m24->vsynctime--; - if (! m24->vsynctime) - m24->stat &= ~8; + if (dev->vsynctime) { + dev->vsynctime--; + if (! dev->vsynctime) + dev->stat &= ~8; } - if (m24->sc == (m24->crtc[11] & 31) || ((m24->crtc[8] & 3) == 3 && m24->sc == ((m24->crtc[11] & 31) >> 1))) { - m24->con = 0; - m24->coff = 1; + if (dev->sc == (dev->crtc[11] & 31) || ((dev->crtc[8] & 3) == 3 && dev->sc == ((dev->crtc[11] & 31) >> 1))) { + dev->con = 0; + dev->coff = 1; } - if (m24->vadj) { - m24->sc++; - m24->sc &= 31; - m24->ma = m24->maback; - m24->vadj--; - if (! m24->vadj) { - m24->dispon = 1; - m24->ma = m24->maback = (m24->crtc[13] | (m24->crtc[12] << 8)) & 0x3fff; - m24->sc = 0; + if (dev->vadj) { + dev->sc++; + dev->sc &= 31; + dev->ma = dev->maback; + dev->vadj--; + if (! dev->vadj) { + dev->dispon = 1; + dev->ma = dev->maback = (dev->crtc[13] | (dev->crtc[12] << 8)) & 0x3fff; + dev->sc = 0; } - } else if (m24->sc == m24->crtc[9] || ((m24->crtc[8] & 3) == 3 && m24->sc == (m24->crtc[9] >> 1))) { - m24->maback = m24->ma; - m24->sc = 0; - oldvc = m24->vc; - m24->vc++; - m24->vc &= 127; + } else if (dev->sc == dev->crtc[9] || ((dev->crtc[8] & 3) == 3 && dev->sc == (dev->crtc[9] >> 1))) { + dev->maback = dev->ma; + dev->sc = 0; + oldvc = dev->vc; + dev->vc++; + dev->vc &= 127; - if (m24->vc == m24->crtc[6]) - m24->dispon=0; + if (dev->vc == dev->crtc[6]) + dev->dispon=0; - if (oldvc == m24->crtc[4]) { - m24->vc = 0; - m24->vadj = m24->crtc[5]; - if (! m24->vadj) - m24->dispon = 1; - if (! m24->vadj) - m24->ma = m24->maback = (m24->crtc[13] | (m24->crtc[12] << 8)) & 0x3fff; - if ((m24->crtc[10] & 0x60) == 0x20) - m24->cursoron = 0; + if (oldvc == dev->crtc[4]) { + dev->vc = 0; + dev->vadj = dev->crtc[5]; + if (! dev->vadj) + dev->dispon = 1; + if (! dev->vadj) + dev->ma = dev->maback = (dev->crtc[13] | (dev->crtc[12] << 8)) & 0x3fff; + if ((dev->crtc[10] & 0x60) == 0x20) + dev->cursoron = 0; else - m24->cursoron = m24->blink & 16; + dev->cursoron = dev->blink & 16; } - if (m24->vc == m24->crtc[7]) { - m24->dispon = 0; - m24->displine = 0; - m24->vsynctime = (m24->crtc[3] >> 4) + 1; - if (m24->crtc[7]) { - if (m24->cgamode & 1) - x = (m24->crtc[1] << 3) + 16; + if (dev->vc == dev->crtc[7]) { + dev->dispon = 0; + dev->displine = 0; + dev->vsynctime = (dev->crtc[3] >> 4) + 1; + if (dev->crtc[7]) { + if (dev->cgamode & 1) + x = (dev->crtc[1] << 3) + 16; else - x = (m24->crtc[1] << 4) + 16; - m24->lastline++; - if ((x != xsize) || ((m24->lastline - m24->firstline) != ysize) || video_force_resize_get()) { + x = (dev->crtc[1] << 4) + 16; + dev->lastline++; + if ((x != xsize) || ((dev->lastline - dev->firstline) != ysize) || video_force_resize_get()) { xsize = x; - ysize = m24->lastline - m24->firstline; + ysize = dev->lastline - dev->firstline; if (xsize < 64) xsize = 656; if (ysize < 32) ysize = 200; set_screen_size(xsize, ysize + 16); @@ -465,43 +469,43 @@ vid_poll(void *priv) video_force_resize_set(0); } - video_blit_memtoscreen_8(0, m24->firstline - 8, 0, (m24->lastline - m24->firstline) + 16, xsize, (m24->lastline - m24->firstline) + 16); + video_blit_memtoscreen_8(0, dev->firstline - 8, 0, (dev->lastline - dev->firstline) + 16, xsize, (dev->lastline - dev->firstline) + 16); frames++; video_res_x = xsize - 16; video_res_y = ysize; - if (m24->cgamode & 1) { + if (dev->cgamode & 1) { video_res_x /= 8; - video_res_y /= (m24->crtc[9] + 1) * 2; + video_res_y /= (dev->crtc[9] + 1) * 2; video_bpp = 0; - } else if (! (m24->cgamode & 2)) { + } else if (! (dev->cgamode & 2)) { video_res_x /= 16; - video_res_y /= (m24->crtc[9] + 1) * 2; + video_res_y /= (dev->crtc[9] + 1) * 2; video_bpp = 0; - } else if (! (m24->cgamode & 16)) { + } else if (! (dev->cgamode & 16)) { video_res_x /= 2; video_res_y /= 2; video_bpp = 2; - } else if (! (m24->ctrl & 1)) { + } else if (! (dev->ctrl & 1)) { video_res_y /= 2; video_bpp = 1; } } - m24->firstline = 1000; - m24->lastline = 0; - m24->blink++; + dev->firstline = 1000; + dev->lastline = 0; + dev->blink++; } } else { - m24->sc++; - m24->sc &= 31; - m24->ma = m24->maback; + dev->sc++; + dev->sc &= 31; + dev->ma = dev->maback; } - if ((m24->sc == (m24->crtc[10] & 31) || ((m24->crtc[8] & 3) == 3 && m24->sc == ((m24->crtc[10] & 31) >> 1)))) - m24->con = 1; + if ((dev->sc == (dev->crtc[10] & 31) || ((dev->crtc[8] & 3) == 3 && dev->sc == ((dev->crtc[10] & 31) >> 1)))) + dev->con = 1; } - if (m24->dispon && (m24->cgamode & 1)) { - for (x = 0; x < (m24->crtc[1] << 1); x++) - m24->charbuffer[x] = m24->vram[(((m24->ma << 1) + x) & 0x3fff) + m24->base]; + if (dev->dispon && (dev->cgamode & 1)) { + for (x = 0; x < (dev->crtc[1] << 1); x++) + dev->charbuffer[x] = dev->vram[(((dev->ma << 1) + x) & 0x3fff) + dev->base]; } } } @@ -510,36 +514,32 @@ vid_poll(void *priv) static void speed_changed(void *priv) { - olim24_t *m24 = (olim24_t *)priv; + olim24_t *dev = (olim24_t *)priv; - recalc_timings(m24); + recalc_timings(dev); } static void kbd_poll(void *priv) { - olim24_t *m24 = (olim24_t *)priv; + olim24_t *dev = (olim24_t *)priv; keyboard_delay += (1000LL * TIMER_USEC); - if (m24->wantirq) { - m24->wantirq = 0; + if (dev->wantirq) { + dev->wantirq = 0; picint(2); -#ifdef ENABLE_KEYBOARD_LOG - kbd_log("M24: take IRQ\n"); -#endif + DBGLOG(1, "M24: take IRQ\n"); } - if (!(m24->status & STAT_OFULL) && key_queue_start != key_queue_end) { -#ifdef ENABLE_KEYBOARD_LOG - kbd_log("M24: reading %02X from the key queue at %i\n", - m24->out, key_queue_start); -#endif - m24->out = key_queue[key_queue_start]; + if (!(dev->status & STAT_OFULL) && key_queue_start != key_queue_end) { + DBGLOG(1, "M24: reading %02X from the key queue at %i\n", + dev->out, key_queue_start); + dev->out = key_queue[key_queue_start]; key_queue_start = (key_queue_start + 1) & 0xf; - m24->status |= STAT_OFULL; - m24->status &= ~STAT_IFULL; - m24->wantirq = 1; + dev->status |= STAT_OFULL; + dev->status &= ~STAT_IFULL; + dev->wantirq = 1; } } @@ -562,45 +562,41 @@ kbd_adddata_ex(uint16_t val) static void kbd_write(uint16_t port, uint8_t val, void *priv) { - olim24_t *m24 = (olim24_t *)priv; + olim24_t *dev = (olim24_t *)priv; -#ifdef ENABLE_KEYBOARD_LOG - kbd_log("M24: write %04X %02X\n", port, val); -#endif + DBGLOG(2, "M24: write %04X %02X\n", port, val); switch (port) { case 0x60: - if (m24->param != m24->param_total) { - m24->params[m24->param++] = val; - if (m24->param == m24->param_total) { - switch (m24->command) { + if (dev->param != dev->param_total) { + dev->params[dev->param++] = val; + if (dev->param == dev->param_total) { + switch (dev->command) { case 0x11: - m24->mouse_mode = 0; - m24->scan[0] = m24->params[0]; - m24->scan[1] = m24->params[1]; - m24->scan[2] = m24->params[2]; - m24->scan[3] = m24->params[3]; - m24->scan[4] = m24->params[4]; - m24->scan[5] = m24->params[5]; - m24->scan[6] = m24->params[6]; + dev->mouse_mode = 0; + dev->scan[0] = dev->params[0]; + dev->scan[1] = dev->params[1]; + dev->scan[2] = dev->params[2]; + dev->scan[3] = dev->params[3]; + dev->scan[4] = dev->params[4]; + dev->scan[5] = dev->params[5]; + dev->scan[6] = dev->params[6]; break; case 0x12: - m24->mouse_mode = 1; - m24->scan[0] = m24->params[0]; - m24->scan[1] = m24->params[1]; - m24->scan[2] = m24->params[2]; + dev->mouse_mode = 1; + dev->scan[0] = dev->params[0]; + dev->scan[1] = dev->params[1]; + dev->scan[2] = dev->params[2]; break; default: -#ifdef ENABLE_KEYBOARD_LOG - kbd_log("M24: bad keyboard command complete %02X\n", m24->command); -#endif + DEBUG("M24: bad keyboard command complete %02X\n", dev->command); break; } } } else { - m24->command = val; + dev->command = val; switch (val) { case 0x01: /*Self-test*/ break; @@ -610,19 +606,17 @@ kbd_write(uint16_t port, uint8_t val, void *priv) break; case 0x11: - m24->param = 0; - m24->param_total = 9; + dev->param = 0; + dev->param_total = 9; break; case 0x12: - m24->param = 0; - m24->param_total = 4; + dev->param = 0; + dev->param_total = 4; break; default: -#ifdef ENABLE_KEYBOARD_LOG - kbd_log("M24: bad keyboard command %02X\n", val); -#endif + ERRLOG("M24: bad keyboard command %02X\n", val); break; } } @@ -648,21 +642,21 @@ kbd_write(uint16_t port, uint8_t val, void *priv) static uint8_t kbd_read(uint16_t port, void *priv) { - olim24_t *m24 = (olim24_t *)priv; + olim24_t *dev = (olim24_t *)priv; uint8_t ret = 0xff; switch (port) { case 0x60: - ret = m24->out; + ret = dev->out; if (key_queue_start == key_queue_end) { - m24->status &= ~STAT_OFULL; - m24->wantirq = 0; + dev->status &= ~STAT_OFULL; + dev->wantirq = 0; } else { - m24->out = key_queue[key_queue_start]; + dev->out = key_queue[key_queue_start]; key_queue_start = (key_queue_start + 1) & 0xf; - m24->status |= STAT_OFULL; - m24->status &= ~STAT_IFULL; - m24->wantirq = 1; + dev->status |= STAT_OFULL; + dev->status &= ~STAT_IFULL; + dev->wantirq = 1; } break; @@ -671,14 +665,12 @@ kbd_read(uint16_t port, void *priv) break; case 0x64: - ret = m24->status; - m24->status &= ~(STAT_RTIMEOUT | STAT_TTIMEOUT); + ret = dev->status; + dev->status &= ~(STAT_RTIMEOUT | STAT_TTIMEOUT); break; default: -#ifdef ENABLE_KEYBOARD_LOG - kbd_log("\nBad M24 keyboard read %04X\n", port); -#endif + ERRLOG("\nBad M24 keyboard read %04X\n", port); break; } @@ -687,81 +679,81 @@ kbd_read(uint16_t port, void *priv) static int -ms_poll(int x, int y, int z, int b, void *priv) +mse_poll(int x, int y, int z, int b, void *priv) { - olim24_t *m24 = (olim24_t *)priv; + olim24_t *dev = (olim24_t *)priv; - m24->x += x; - m24->y += y; + dev->x += x; + dev->y += y; if (((key_queue_end - key_queue_start) & 0xf) > 14) return(0xff); - if ((b & 1) && !(m24->b & 1)) - kbd_adddata(m24->scan[0]); - if (!(b & 1) && (m24->b & 1)) - kbd_adddata(m24->scan[0] | 0x80); - m24->b = (m24->b & ~1) | (b & 1); + if ((b & 1) && !(dev->b & 1)) + kbd_adddata(dev->scan[0]); + if (!(b & 1) && (dev->b & 1)) + kbd_adddata(dev->scan[0] | 0x80); + dev->b = (dev->b & ~1) | (b & 1); if (((key_queue_end - key_queue_start) & 0xf) > 14) return(0xff); - if ((b & 2) && !(m24->b & 2)) - kbd_adddata(m24->scan[2]); - if (!(b & 2) && (m24->b & 2)) - kbd_adddata(m24->scan[2] | 0x80); - m24->b = (m24->b & ~2) | (b & 2); + if ((b & 2) && !(dev->b & 2)) + kbd_adddata(dev->scan[2]); + if (!(b & 2) && (dev->b & 2)) + kbd_adddata(dev->scan[2] | 0x80); + dev->b = (dev->b & ~2) | (b & 2); if (((key_queue_end - key_queue_start) & 0xf) > 14) return(0xff); - if ((b & 4) && !(m24->b & 4)) - kbd_adddata(m24->scan[1]); - if (!(b & 4) && (m24->b & 4)) - kbd_adddata(m24->scan[1] | 0x80); - m24->b = (m24->b & ~4) | (b & 4); + if ((b & 4) && !(dev->b & 4)) + kbd_adddata(dev->scan[1]); + if (!(b & 4) && (dev->b & 4)) + kbd_adddata(dev->scan[1] | 0x80); + dev->b = (dev->b & ~4) | (b & 4); - if (m24->mouse_mode) { + if (dev->mouse_mode) { if (((key_queue_end - key_queue_start) & 0xf) > 12) return(0xff); - if (!m24->x && !m24->y) return(0xff); + if (!dev->x && !dev->y) return(0xff); - m24->y = -m24->y; + dev->y = -dev->y; - if (m24->x < -127) m24->x = -127; - if (m24->x > 127) m24->x = 127; - if (m24->x < -127) m24->x = 0x80 | ((-m24->x) & 0x7f); + if (dev->x < -127) dev->x = -127; + if (dev->x > 127) dev->x = 127; + if (dev->x < -127) dev->x = 0x80 | ((-dev->x) & 0x7f); - if (m24->y < -127) m24->y = -127; - if (m24->y > 127) m24->y = 127; - if (m24->y < -127) m24->y = 0x80 | ((-m24->y) & 0x7f); + if (dev->y < -127) dev->y = -127; + if (dev->y > 127) dev->y = 127; + if (dev->y < -127) dev->y = 0x80 | ((-dev->y) & 0x7f); kbd_adddata(0xfe); - kbd_adddata(m24->x); - kbd_adddata(m24->y); + kbd_adddata(dev->x); + kbd_adddata(dev->y); - m24->x = m24->y = 0; + dev->x = dev->y = 0; } else { - while (m24->x < -4) { + while (dev->x < -4) { if (((key_queue_end - key_queue_start) & 0xf) > 14) return(0xff); - m24->x += 4; - kbd_adddata(m24->scan[3]); + dev->x += 4; + kbd_adddata(dev->scan[3]); } - while (m24->x > 4) { + while (dev->x > 4) { if (((key_queue_end - key_queue_start) & 0xf) > 14) return(0xff); - m24->x -= 4; - kbd_adddata(m24->scan[4]); + dev->x -= 4; + kbd_adddata(dev->scan[4]); } - while (m24->y < -4) { + while (dev->y < -4) { if (((key_queue_end - key_queue_start) & 0xf) > 14) return(0xff); - m24->y += 4; - kbd_adddata(m24->scan[5]); + dev->y += 4; + kbd_adddata(dev->scan[5]); } - while (m24->y > 4) { + while (dev->y > 4) { if (((key_queue_end - key_queue_start) & 0xf) > 14) return(0xff); - m24->y -= 4; - kbd_adddata(m24->scan[6]); + dev->y -= 4; + kbd_adddata(dev->scan[6]); } } @@ -787,21 +779,23 @@ m24_read(uint16_t port, void *priv) static void vid_close(void *priv) { - olim24_t *m24 = (olim24_t *)priv; + olim24_t *dev = (olim24_t *)priv; - free(m24->vram); - - free(m24); + free(dev->vram); + free(dev); } +static video_timings_t m24_timing = {VID_ISA, 8,16,32, 8,16,32}; + const device_t m24_device = { "Olivetti M24 Video", 0, 0, NULL, vid_close, NULL, NULL, speed_changed, - NULL, NULL, + NULL, + &m24_timing, NULL }; @@ -809,48 +803,49 @@ const device_t m24_device = { void machine_olim24_init(const machine_t *model, void *arg) { - olim24_t *m24; + olim24_t *dev; - m24 = (olim24_t *)malloc(sizeof(olim24_t)); - memset(m24, 0x00, sizeof(olim24_t)); + dev = (olim24_t *)mem_alloc(sizeof(olim24_t)); + memset(dev, 0x00, sizeof(olim24_t)); machine_common_init(model, arg); io_sethandler(0x0066, 2, - m24_read,NULL,NULL, NULL,NULL,NULL, m24); + m24_read,NULL,NULL, NULL,NULL,NULL, dev); /* Initialize the video adapter. */ - m24->vram = malloc(0x8000); + dev->vram = (uint8_t *)mem_alloc(0x8000); overscan_x = overscan_y = 16; - mem_mapping_add(&m24->mapping, 0xb8000, 0x08000, - vid_read,NULL,NULL, - vid_write,NULL,NULL, NULL, 0, m24); + mem_map_add(&dev->mapping, 0xb8000, 0x08000, + vid_read,NULL,NULL, vid_write,NULL,NULL, NULL, 0, dev); io_sethandler(0x03d0, 16, - vid_in,NULL,NULL, vid_out,NULL,NULL, m24); - timer_add(vid_poll, &m24->vidtime, TIMER_ALWAYS_ENABLED, m24); - device_add_ex(&m24_device, m24); + vid_in,NULL,NULL, vid_out,NULL,NULL, dev); + timer_add(vid_poll, &dev->vidtime, TIMER_ALWAYS_ENABLED, dev); + device_add_ex(&m24_device, dev); + video_inform(VID_TYPE_CGA, + (const video_timings_t *)&m24_device.vid_timing); /* Initialize the keyboard. */ - m24->status = STAT_LOCK | STAT_CD; - m24->scan[0] = 0x1c; - m24->scan[1] = 0x53; - m24->scan[2] = 0x01; - m24->scan[3] = 0x4b; - m24->scan[4] = 0x4d; - m24->scan[5] = 0x48; - m24->scan[6] = 0x50; + dev->status = STAT_LOCK | STAT_CD; + dev->scan[0] = 0x1c; + dev->scan[1] = 0x53; + dev->scan[2] = 0x01; + dev->scan[3] = 0x4b; + dev->scan[4] = 0x4d; + dev->scan[5] = 0x48; + dev->scan[6] = 0x50; io_sethandler(0x0060, 2, - kbd_read,NULL,NULL, kbd_write,NULL,NULL, m24); + kbd_read,NULL,NULL, kbd_write,NULL,NULL, dev); io_sethandler(0x0064, 1, - kbd_read,NULL,NULL, kbd_write,NULL,NULL, m24); + kbd_read,NULL,NULL, kbd_write,NULL,NULL, dev); keyboard_set_table(scancode_xt); keyboard_send = kbd_adddata_ex; keyboard_scan = 1; - timer_add(kbd_poll, &keyboard_delay, TIMER_ALWAYS_ENABLED, m24); + timer_add(kbd_poll, &keyboard_delay, TIMER_ALWAYS_ENABLED, dev); /* Tell mouse driver about our internal mouse. */ mouse_reset(); - mouse_set_poll(ms_poll, m24); + mouse_set_poll(mse_poll, dev); /* FIXME: make sure this is correct?? */ device_add(&at_nvr_device); @@ -866,24 +861,25 @@ machine_olim24_init(const machine_t *model, void *arg) void machine_olim24_video_init(void) { - olim24_t *m24; + olim24_t *dev; - m24 = (olim24_t *)malloc(sizeof(olim24_t)); - memset(m24, 0x00, sizeof(olim24_t)); + dev = (olim24_t *)mem_alloc(sizeof(olim24_t)); + memset(dev, 0x00, sizeof(olim24_t)); /* Initialize the video adapter. */ - m24->vram = malloc(0x8000); + dev->vram = (uint8_t *)mem_alloc(0x8000); overscan_x = overscan_y = 16; - mem_mapping_add(&m24->mapping, 0xb8000, 0x08000, - vid_read,NULL,NULL, - vid_write,NULL,NULL, NULL, 0, m24); + mem_map_add(&dev->mapping, 0xb8000, 0x08000, + vid_read,NULL,NULL, vid_write,NULL,NULL, NULL, 0, dev); io_sethandler(0x03d0, 16, - vid_in,NULL,NULL, vid_out,NULL,NULL, m24); + vid_in,NULL,NULL, vid_out,NULL,NULL, dev); io_sethandler(0x13c6, 1, - vid_in,NULL,NULL, vid_out,NULL,NULL, m24); + vid_in,NULL,NULL, vid_out,NULL,NULL, dev); io_sethandler(0x23c6, 1, - vid_in,NULL,NULL, vid_out,NULL,NULL, m24); - timer_add(vid_poll, &m24->vidtime, TIMER_ALWAYS_ENABLED, m24); - device_add_ex(&m24_device, m24); + vid_in,NULL,NULL, vid_out,NULL,NULL, dev); + timer_add(vid_poll, &dev->vidtime, TIMER_ALWAYS_ENABLED, dev); + device_add_ex(&m24_device, dev); + video_inform(VID_TYPE_CGA, + (const video_timings_t *)&m24_device.vid_timing); } #endif diff --git a/src/machines/m_pcjr.c b/src/machines/m_pcjr.c index 8696c77..4d7dc6b 100644 --- a/src/machines/m_pcjr.c +++ b/src/machines/m_pcjr.c @@ -8,7 +8,7 @@ * * Emulation of the IBM PCjr. * - * Version: @(#)m_pcjr.c 1.0.8 2018/05/06 + * Version: @(#)m_pcjr.c 1.0.9 2018/10/05 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -50,6 +50,7 @@ #include "../devices/system/nmi.h" #include "../devices/system/pic.h" #include "../devices/system/pit.h" +#include "../devices/system/ppi.h" #include "../devices/ports/serial.h" #include "../devices/input/keyboard.h" #include "../devices/floppy/fdd.h" @@ -58,6 +59,7 @@ #include "../devices/sound/snd_speaker.h" #include "../devices/sound/snd_sn76489.h" #include "../devices/video/video.h" +#include "../devices/video/vid_cga.h" #include "../devices/video/vid_cga_comp.h" #include "../plat.h" #include "machine.h" @@ -78,7 +80,7 @@ typedef struct { /* Video Controller stuff. */ - mem_mapping_t mapping; + mem_map_t mapping; uint8_t crtc[32]; int crtcreg; int array_index; @@ -110,7 +112,7 @@ typedef struct { } pcjr_t; -static uint8_t crtcmask[32] = { +static const uint8_t crtcmask[32] = { 0xff, 0xff, 0xff, 0xff, 0x7f, 0x1f, 0x7f, 0x7f, 0xf3, 0x1f, 0x7f, 0x1f, 0x3f, 0xff, 0x3f, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -232,7 +234,6 @@ vid_write(uint32_t addr, uint8_t val, void *p) if (pcjr->memctrl == -1) return; - egawrites++; pcjr->b8000[addr & 0x3fff] = val; } @@ -244,7 +245,6 @@ vid_read(uint32_t addr, void *p) if (pcjr->memctrl == -1) return(0xff); - egareads++; return(pcjr->b8000[addr & 0x3fff]); } @@ -441,12 +441,16 @@ vid_poll(void *p) } } else { if (pcjr->array[3] & 4) { - if (pcjr->array[0] & 1) hline(buffer, 0, pcjr->displine, (pcjr->crtc[1] << 3) + 16, (pcjr->array[2] & 0xf) + 16); - else hline(buffer, 0, pcjr->displine, (pcjr->crtc[1] << 4) + 16, (pcjr->array[2] & 0xf) + 16); + if (pcjr->array[0] & 1) + cga_hline(buffer, 0, pcjr->displine, (pcjr->crtc[1] << 3) + 16, (pcjr->array[2] & 0xf) + 16); + else + cga_hline(buffer, 0, pcjr->displine, (pcjr->crtc[1] << 4) + 16, (pcjr->array[2] & 0xf) + 16); } else { cols[0] = pcjr->array[0 + 16] + 16; - if (pcjr->array[0] & 1) hline(buffer, 0, pcjr->displine, (pcjr->crtc[1] << 3) + 16, cols[0]); - else hline(buffer, 0, pcjr->displine, (pcjr->crtc[1] << 4) + 16, cols[0]); + if (pcjr->array[0] & 1) + cga_hline(buffer, 0, pcjr->displine, (pcjr->crtc[1] << 3) + 16, cols[0]); + else + cga_hline(buffer, 0, pcjr->displine, (pcjr->crtc[1] << 4) + 16, cols[0]); } } if (pcjr->array[0] & 1) x = (pcjr->crtc[1] << 3) + 16; @@ -624,7 +628,7 @@ kbd_read(uint16_t port, void *priv) break; default: - pclog("\nBad PCjr keyboard read %04X\n", port); + ERRLOG("PCjr: bad keyboard read %04X\n", port); } return(ret); @@ -731,6 +735,8 @@ static const device_config_t pcjr_config[] = { }; +static const video_timings_t pcjr_timings = { VID_BUS,0,0,0,0,0,0 }; + const device_t m_pcjr_device = { "IBM PCjr", 0, 0, @@ -738,7 +744,7 @@ const device_t m_pcjr_device = { NULL, speed_changed, NULL, - NULL, + &pcjr_timings, pcjr_config }; @@ -749,7 +755,7 @@ machine_pcjr_init(const machine_t *model, UNUSED(void *arg)) int display_type; pcjr_t *pcjr; - pcjr = malloc(sizeof(pcjr_t)); + pcjr = (pcjr_t *)mem_alloc(sizeof(pcjr_t)); memset(pcjr, 0x00, sizeof(pcjr_t)); pcjr->memctrl = -1; display_type = machine_get_config_int("display_type"); @@ -759,17 +765,21 @@ machine_pcjr_init(const machine_t *model, UNUSED(void *arg)) pit_init(); pit_set_out_func(&pit, 0, pit_irq0_timer_pcjr); - if (serial_enabled[0]) + if (serial_enabled[0]) { serial_setup(1, 0x2f8, 3); + device_add(&serial_1_pcjr_device); + } /* Initialize the video controller. */ - mem_mapping_add(&pcjr->mapping, 0xb8000, 0x08000, - vid_read, NULL, NULL, - vid_write, NULL, NULL, NULL, 0, pcjr); + mem_map_add(&pcjr->mapping, 0xb8000, 0x08000, + vid_read, NULL, NULL, + vid_write, NULL, NULL, NULL, 0, pcjr); io_sethandler(0x03d0, 16, vid_in, NULL, NULL, vid_out, NULL, NULL, pcjr); timer_add(vid_poll, &pcjr->vidtime, TIMER_ALWAYS_ENABLED, pcjr); device_add_ex(&m_pcjr_device, pcjr); + video_inform(VID_TYPE_CGA, + (const video_timings_t *)&m_pcjr_device.vid_timing); /* Initialize the keyboard. */ key_queue_start = key_queue_end = 0; diff --git a/src/machines/m_ps1.c b/src/machines/m_ps1.c index d9e03f0..9280755 100644 --- a/src/machines/m_ps1.c +++ b/src/machines/m_ps1.c @@ -22,7 +22,7 @@ * The reserved 384K is remapped to the top of extended memory. * If this is not done then you get an error on startup. * - * Version: @(#)m_ps1.c 1.0.20 2018/08/20 + * Version: @(#)m_ps1.c 1.0.21 2018/10/05 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -99,6 +99,8 @@ typedef struct { int model; rom_t high_rom; + mem_map_t romext_mapping; + uint8_t romext[32768]; uint8_t ps1_91, ps1_92, @@ -253,7 +255,7 @@ snd_init(const device_t *info) { ps1snd_t *snd; - snd = malloc(sizeof(ps1snd_t)); + snd = (ps1snd_t *)mem_alloc(sizeof(ps1snd_t)); memset(snd, 0x00, sizeof(ps1snd_t)); sn76489_init(&snd->sn76489, 0x0205, 0x0001, SN76496, 4000000); @@ -289,18 +291,47 @@ static const device_t snd_device = { }; +static uint8_t +ps1_read_romext(uint32_t addr, void *priv) +{ + ps1_t *dev = (ps1_t *)priv; + + return dev->romext[addr & 0x7fff]; +} + + +static uint16_t +ps1_read_romextw(uint32_t addr, void *priv) +{ + ps1_t *dev = (ps1_t *)priv; + uint16_t *p = (uint16_t *)&dev->romext[addr & 0x7fff]; + + return *p; +} + + +static uint32_t +ps1_read_romextl(uint32_t addr, void *priv) +{ + ps1_t *dev = (ps1_t *)priv; + uint32_t *p = (uint32_t *)&dev->romext[addr & 0x7fff]; + + return *p; +} + + static void -recalc_memory(ps1_t *ps) +recalc_memory(ps1_t *dev) { /* Enable first 512K */ mem_set_mem_state(0x00000, 0x80000, - (ps->ps1_e0_regs[0] & 0x01) ? + (dev->ps1_e0_regs[0] & 0x01) ? (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL) : (MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL)); /* Enable 512-640K */ mem_set_mem_state(0x80000, 0x20000, - (ps->ps1_e0_regs[1] & 0x01) ? + (dev->ps1_e0_regs[1] & 0x01) ? (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL) : (MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL)); } @@ -309,73 +340,78 @@ recalc_memory(ps1_t *ps) static void ps1_write(uint16_t port, uint8_t val, void *priv) { - ps1_t *ps = (ps1_t *)priv; + ps1_t *dev = (ps1_t *)priv; switch (port) { case 0x0092: - if (ps->model != 2011) { + if (dev->model != 2011) { if (val & 1) { softresetx86(); cpu_set_edx(); } - ps->ps1_92 = val & ~1; + dev->ps1_92 = val & ~1; } else { - ps->ps1_92 = val; + dev->ps1_92 = val; } mem_a20_alt = val & 2; mem_a20_recalc(); break; case 0x0094: - ps->ps1_94 = val; + dev->ps1_94 = val; break; case 0x00e0: - if (ps->model != 2011) { - ps->ps1_e0_addr = val; - } + if (dev->model != 2011) + dev->ps1_e0_addr = val; break; case 0x00e1: - if (ps->model != 2011) { - ps->ps1_e0_regs[ps->ps1_e0_addr] = val; - recalc_memory(ps); + if (dev->model != 2011) { + dev->ps1_e0_regs[dev->ps1_e0_addr] = val; + recalc_memory(dev); } break; case 0x0102: if (val & 0x04) serial_setup(1, SERIAL1_ADDR, SERIAL1_IRQ); +#if 0 + else + serial_remove(1); +#endif if (val & 0x10) { switch ((val >> 5) & 3) { case 0: parallel_setup(1, 0x03bc); break; + case 1: parallel_setup(1, 0x0378); break; + case 2: parallel_setup(1, 0x0278); break; } } - ps->ps1_102 = val; + dev->ps1_102 = val; break; case 0x0103: - ps->ps1_103 = val; + dev->ps1_103 = val; break; case 0x0104: - ps->ps1_104 = val; + dev->ps1_104 = val; break; case 0x0105: - ps->ps1_105 = val; + dev->ps1_105 = val; break; case 0x0190: - ps->ps1_190 = val; + dev->ps1_190 = val; break; } } @@ -384,53 +420,52 @@ ps1_write(uint16_t port, uint8_t val, void *priv) static uint8_t ps1_read(uint16_t port, void *priv) { - ps1_t *ps = (ps1_t *)priv; + ps1_t *dev = (ps1_t *)priv; uint8_t ret = 0xff; switch (port) { case 0x0091: /* Card Select Feedback register */ - ret = ps->ps1_91; - ps->ps1_91 = 0; + ret = dev->ps1_91; + dev->ps1_91 = 0; break; case 0x0092: - ret = ps->ps1_92; + ret = dev->ps1_92; break; case 0x0094: - ret = ps->ps1_94; + ret = dev->ps1_94; break; case 0x00e1: - if (ps->model != 2011) { - ret = ps->ps1_e0_regs[ps->ps1_e0_addr]; - } + if (dev->model != 2011) + ret = dev->ps1_e0_regs[dev->ps1_e0_addr]; break; case 0x0102: - if (ps->model == 2011) - ret = ps->ps1_102 | 0x08; + if (dev->model == 2011) + ret = dev->ps1_102 | 0x08; else - ret = ps->ps1_102; + ret = dev->ps1_102; break; case 0x0103: - ret = ps->ps1_103; + ret = dev->ps1_103; break; case 0x0104: - ret = ps->ps1_104; + ret = dev->ps1_104; break; case 0x0105: - if (ps->model == 2011) - ret = ps->ps1_105; + if (dev->model == 2011) + ret = dev->ps1_105; else - ret = ps->ps1_105 | 0x80; + ret = dev->ps1_105 | 0x80; break; case 0x0190: - ret = ps->ps1_190; + ret = dev->ps1_190; break; default: @@ -444,23 +479,23 @@ ps1_read(uint16_t port, void *priv) static void ps1_setup(int model, romdef_t *bios) { - ps1_t *ps; void *priv; + ps1_t *dev; - ps = (ps1_t *)malloc(sizeof(ps1_t)); - memset(ps, 0x00, sizeof(ps1_t)); - ps->model = model; + dev = (ps1_t *)mem_alloc(sizeof(ps1_t)); + memset(dev, 0x00, sizeof(ps1_t)); + dev->model = model; io_sethandler(0x0091, 1, - ps1_read, NULL, NULL, ps1_write, NULL, NULL, ps); + ps1_read, NULL, NULL, ps1_write, NULL, NULL, dev); io_sethandler(0x0092, 1, - ps1_read, NULL, NULL, ps1_write, NULL, NULL, ps); + ps1_read, NULL, NULL, ps1_write, NULL, NULL, dev); io_sethandler(0x0094, 1, - ps1_read, NULL, NULL, ps1_write, NULL, NULL, ps); + ps1_read, NULL, NULL, ps1_write, NULL, NULL, dev); io_sethandler(0x0102, 4, - ps1_read, NULL, NULL, ps1_write, NULL, NULL, ps); + ps1_read, NULL, NULL, ps1_write, NULL, NULL, dev); io_sethandler(0x0190, 1, - ps1_read, NULL, NULL, ps1_write, NULL, NULL, ps); + ps1_read, NULL, NULL, ps1_write, NULL, NULL, dev); /* Set up the parallel port. */ parallel_setup(1, 0x03bc); @@ -470,11 +505,15 @@ ps1_setup(int model, romdef_t *bios) video_card = VID_INTERNAL; mouse_type = MOUSE_PS2; + mem_map_add(&dev->romext_mapping, 0xc8000, 0x08000, + ps1_read_romext,ps1_read_romextw,ps1_read_romextl, + NULL,NULL, NULL, dev->romext, 0, dev); + if (machine_get_config_int("rom_shell")) { - if (! rom_init(&ps->high_rom, + if (! rom_init(&dev->high_rom, L"machines/ibm/ps1_2011/fc0000_105775_us.bin", 0xfc0000, 0x20000, 0x01ffff, 0, MEM_MAPPING_EXTERNAL)) { - pclog("PS1: unable to load ROM Shell !\n"); + ERRLOG("PS1: unable to load ROM Shell !\n"); } } @@ -496,7 +535,7 @@ ps1_setup(int model, romdef_t *bios) * This is nasty, we will have to generalize this * at some point for all PS/1 and/or PS/2 machines. */ - ps1_hdc_inform(priv, ps); + ps1_hdc_inform(priv, dev); } } @@ -506,14 +545,14 @@ ps1_setup(int model, romdef_t *bios) mouse_type = MOUSE_PS2; io_sethandler(0x00e0, 2, - ps1_read, NULL, NULL, ps1_write, NULL, NULL, ps); + ps1_read, NULL, NULL, ps1_write, NULL, NULL, dev); if (machine_get_config_int("rom_shell")) { - pclog("PS1: loading ROM Shell..\n"); - if (! rom_init(&ps->high_rom, + DEBUG("PS1: loading ROM Shell..\n"); + if (! rom_init(&dev->high_rom, L"machines/ibm/ps1_2121/fc0000_92f9674.bin", 0xfc0000, 0x20000, 0x1ffff, 0, MEM_MAPPING_EXTERNAL)) { - pclog("PS1: unable to load ROM Shell !\n"); + ERRLOG("PS1: unable to load ROM Shell !\n"); } } @@ -609,9 +648,9 @@ const device_t m_ps1_device = { void ps1_set_feedback(void *priv) { - ps1_t *ps = (ps1_t *)priv; + ps1_t *dev = (ps1_t *)priv; - ps->ps1_91 |= 0x01; + dev->ps1_91 |= 0x01; } diff --git a/src/machines/m_ps1_hdc.c b/src/machines/m_ps1_hdc.c index 5dbdcff..430f032 100644 --- a/src/machines/m_ps1_hdc.c +++ b/src/machines/m_ps1_hdc.c @@ -43,7 +43,7 @@ * Type table with the main code, so the user can only select * items from that list... * - * Version: @(#)m_ps1_hdc.c 1.0.7 2018/05/06 + * Version: @(#)m_ps1_hdc.c 1.0.8 2018/10/05 * * Author: Fred N. van Kempen, * @@ -90,6 +90,7 @@ #include #include #include +#define dbglog hdc_log #include "../emu.h" #include "../io.h" #include "../timer.h" @@ -507,20 +508,20 @@ static int get_sector(hdc_t *dev, drive_t *drive, off64_t *addr) { if (drive->cur_cyl != dev->track) { - hdc_log("HDC: get_sector: wrong cylinder %d/%d\n", - drive->cur_cyl, dev->track); + DEBUG("HDC: get_sector: wrong cylinder %d/%d\n", + drive->cur_cyl, dev->track); dev->ssb.wrong_cyl = 1; return(1); } if (dev->head >= drive->hpc) { - hdc_log("HDC: get_sector: past end of heads\n"); + DEBUG("HDC: get_sector: past end of heads\n"); dev->ssb.cylinder_err = 1; return(1); } if (dev->sector > drive->spt) { - hdc_log("HDC: get_sector: past end of sectors\n"); + DEBUG("HDC: get_sector: past end of sectors\n"); dev->ssb.mark_not_found = 1; return(1); } @@ -595,7 +596,7 @@ dump_ssb(ssb_t *ssb) sprintf(sp, " Misc : Syndrome=%02X DRIVE_TYPE=%d\n", ssb->cmd_syndrome, ssb->drive_type); - hdc_log("HDC: %s\n", temp); + DBGLOG(1, "HDC: %s\n", temp); } @@ -613,7 +614,7 @@ dump_ccb(hdc_t *dev, ccb_t *ccb) sprintf(sp, " CYL=%d HEAD=%d SECTOR=%d COUNT=%d\n", ((ccb->cyl_high<<8)|ccb->cyl_low), ccb->head, ccb->sector, ccb->count); - hdc_log("HDC: %s\n", temp); + DBGLOG(1, "HDC: %s\n", temp); }; @@ -635,7 +636,7 @@ dump_fcb(fcb_t *fcb, int count) fcb++; } - hdc_log("HDC: %s\n", temp); + DBGLOG(1, "HDC: %s\n", temp); } #endif @@ -714,7 +715,7 @@ do_format(hdc_t *dev, drive_t *drive, ccb_t *ccb) while (dev->buf_idx < dev->buf_len) { val = dma_channel_read(dev->dma); if (val == DMA_NODATA) { - hdc_log("HDC: CMD_FORMAT out of data (idx=%d, len=%d)!\n", dev->buf_idx, dev->buf_len); + ERRLOG("HDC: CMD_FORMAT out of data (idx=%d, len=%d)!\n", dev->buf_idx, dev->buf_len); dev->intstat |= ISR_EQUIP_CHECK; dev->ssb.need_reset = 1; intr = 1; @@ -742,13 +743,13 @@ do_format(hdc_t *dev, drive_t *drive, ccb_t *ccb) case STATE_FINIT: do_fmt: #ifdef ENABLE_HDC_LOG - hdc_log("HDC: format_%s(%d) %d,%d\n", - (ccb->cmd==CMD_FORMAT_DRIVE)?"drive":"track", - drive->id, dev->track, dev->head); + DEBUG("HDC: format_%s(%d) %d,%d\n", + (ccb->cmd==CMD_FORMAT_DRIVE)?"drive":"track", + drive->id, dev->track, dev->head); #endif /* Activate the status icon. */ - ui_sb_icon_update(SB_HDD|HDD_BUS_IDE, 1); + hdd_active(drive->hdd_num, 1); /* Seek to cylinder. */ if (do_seek(dev, drive, start_cyl)) { @@ -787,7 +788,7 @@ do_fmt: } /* De-activate the status icon. */ - ui_sb_icon_update(SB_HDD|HDD_BUS_IDE, 0); + hdd_active(SB_DISK|drive->hdd_num, 0); /* This saves us a LOT of code. */ dev->state = STATE_FINIT; @@ -797,7 +798,7 @@ do_fmt: /* If we errored out, go back idle. */ if (intr) { /* De-activate the status icon. */ - ui_sb_icon_update(SB_HDD|HDD_BUS_IDE, 0); + hdd_active(drive->hdd_num, 0); do_finish(dev); } @@ -872,11 +873,11 @@ hdc_callback(void *priv) case STATE_SEND: /* Activate the status icon. */ - ui_sb_icon_update(SB_HDD|HDD_BUS_IDE, 1); + hdd_active(drive->hdd_num, 1); do_send: #ifdef ENABLE_HDC_LOG - hdc_log("HDC: read_%s(%d: %d,%d,%d) cnt=%d\n", + DEBUG("HDC: read_%s(%d: %d,%d,%d) cnt=%d\n", (no_data)?"verify":"sector", drive->id, dev->track, dev->head, dev->sector, dev->count); @@ -885,7 +886,7 @@ do_send: /* Get address of sector to load. */ if (get_sector(dev, drive, &addr)) { /* De-activate the status icon. */ - ui_sb_icon_update(SB_HDD|HDD_BUS_IDE, 0); + hdd_active(drive->hdd_num, 0); do_finish(dev); return; } @@ -925,10 +926,10 @@ do_send: val = dma_channel_write(dev->dma, *dev->buf_ptr++); if (val == DMA_NODATA) { - hdc_log("HDC: CMD_READ_SECTORS out of data (idx=%d, len=%d)!\n", dev->buf_idx, dev->buf_len); + ERRLOG("HDC: CMD_READ_SECTORS out of data (idx=%d, len=%d)!\n", dev->buf_idx, dev->buf_len); /* De-activate the status icon. */ - ui_sb_icon_update(SB_HDD|HDD_BUS_IDE, 0); + hdd_active(drive->hdd_num, 0); dev->intstat |= ISR_EQUIP_CHECK; dev->ssb.need_reset = 1; @@ -946,12 +947,12 @@ do_send: dev->buf_idx = 0; if (--dev->count == 0) { #ifdef ENABLE_HDC_LOG - hdc_log("HDC: read_%s(%d) DONE\n", + DEBUG("HDC: read_%s(%d) DONE\n", (no_data)?"verify":"sector", drive->id); #endif /* De-activate the status icon. */ - ui_sb_icon_update(SB_HDD|HDD_BUS_IDE, 0); + hdd_active(drive->hdd_num, 0); if (! (dev->ctrl & ACR_DMA_EN)) dev->status &= ~(ASR_DATA_REQ|ASR_DIR); @@ -989,7 +990,7 @@ do_send: dump_ccb(dev, ccb); #endif #ifdef ENABLE_HDC_LOG - hdc_log("HDC: recalibrate(%d) ready=%d\n", + DEBUG("HDC: recalibrate(%d) ready=%d\n", drive->id, drive->present); #endif if (drive->present) { @@ -1038,10 +1039,10 @@ do_send: case STATE_RECV: /* Activate the status icon. */ - ui_sb_icon_update(SB_HDD|HDD_BUS_IDE, 1); + hdd_active(drive->hdd_num, 1); do_recv: #ifdef ENABLE_HDC_LOG - hdc_log("HDC write_%s(%d: %d,%d,%d) cnt=%d\n", + DEBUG("HDC write_%s(%d: %d,%d,%d) cnt=%d\n", (no_data)?"verify":"sector", drive->id, dev->track, dev->head, dev->sector, dev->count); @@ -1071,10 +1072,10 @@ do_recv: while (dev->buf_idx < dev->buf_len) { val = dma_channel_read(dev->dma); if (val == DMA_NODATA) { - hdc_log("HDC: CMD_WRITE_SECTORS out of data (idx=%d, len=%d)!\n", dev->buf_idx, dev->buf_len); + ERRLOG("HDC: CMD_WRITE_SECTORS out of data (idx=%d, len=%d)!\n", dev->buf_idx, dev->buf_len); /* De-activate the status icon. */ - ui_sb_icon_update(SB_HDD|HDD_BUS_IDE, 0); + hdd_active(drive->hdd_num, 0); dev->intstat |= ISR_EQUIP_CHECK; dev->ssb.need_reset = 1; @@ -1099,7 +1100,7 @@ do_recv: /* Get address of sector to write. */ if (get_sector(dev, drive, &addr)) { /* De-activate the status icon. */ - ui_sb_icon_update(SB_HDD|HDD_BUS_IDE, 0); + hdd_active(drive->hdd_num, 0); do_finish(dev); return; @@ -1112,12 +1113,12 @@ do_recv: dev->buf_idx = 0; if (--dev->count == 0) { #ifdef ENABLE_HDC_LOG - hdc_log("HDC: write_%s(%d) DONE\n", + DEBUG("HDC: write_%s(%d) DONE\n", (no_data)?"verify":"sector", drive->id); #endif /* De-activate the status icon. */ - ui_sb_icon_update(SB_HDD|HDD_BUS_IDE, 0); + hdd_active(drive->hdd_num, 0); if (! (dev->ctrl & ACR_DMA_EN)) dev->status &= ~ASR_DATA_REQ; @@ -1162,9 +1163,9 @@ do_recv: (ccb->cyl_low|(ccb->cyl_high<<8))); } #ifdef ENABLE_HDC_LOG - hdc_log("HDC: %s(%d) cyl=%d, err=%d\n", - (ccb->ec_p)?"park":"seek", - drive->id, drive->cur_cyl, val); + DEBUG("HDC: %s(%d) cyl=%d, err=%d\n", + (ccb->ec_p)?"park":"seek", + drive->id, drive->cur_cyl, val); #endif if (! val) dev->ssb.seek_end = 1; @@ -1172,11 +1173,9 @@ do_recv: break; default: -#ifdef ENABLE_HDC_LOG - hdc_log("HDC: unknown command - %02x\n", ccb->cmd); -# ifdef _DEBUG + ERRLOG("HDC: unknown command - %02x\n", ccb->cmd); +#if defined(ENABLE_HDC_LOG) && defined(_DEBUG) dump_ccb(dev, ccb); -# endif #endif dev->intstat |= ISR_INVALID_CMD; do_finish(dev); @@ -1243,7 +1242,7 @@ hdc_read(uint16_t port, void *priv) case 0: /* DATA register */ if (dev->state == STATE_SDATA) { if (dev->buf_idx > dev->buf_len) { - hdc_log("HDC: read with empty buffer!\n"); + ERRLOG("HDC: read with empty buffer!\n"); dev->state = STATE_IDLE; dev->intstat |= ISR_INVALID_CMD; dev->status &= (ASR_TX_EN|ASR_DATA_REQ|ASR_DIR); @@ -1287,7 +1286,7 @@ hdc_write(uint16_t port, uint8_t val, void *priv) case 0: /* DATA register */ if (dev->state == STATE_RDATA) { if (dev->buf_idx >= dev->buf_len) { - hdc_log("HDC: write with full buffer!\n"); + ERRLOG("HDC: write with full buffer!\n"); dev->intstat |= ISR_INVALID_CMD; dev->status &= ~ASR_DATA_REQ; set_intr(dev, 1); @@ -1388,7 +1387,7 @@ ps1_hdc_init(const device_t *info) int c, i; /* Allocate and initialize device block. */ - dev = malloc(sizeof(hdc_t)); + dev = (hdc_t *)mem_alloc(sizeof(hdc_t)); memset(dev, 0x00, sizeof(hdc_t)); /* Set up controller parameters for PS/1 2011. */ @@ -1396,7 +1395,7 @@ ps1_hdc_init(const device_t *info) dev->irq = 14; dev->dma = 3; - pclog("HDC: initializing (I/O=%04X, IRQ=%d, DMA=%d)\n", + DEBUG("HDC: initializing (I/O=%04X, IRQ=%d, DMA=%d)\n", dev->base, dev->irq, dev->dma); /* Load any disks for this device class. */ @@ -1425,9 +1424,9 @@ ps1_hdc_init(const device_t *info) drive->hdd_num = i; drive->present = 1; - pclog("HDC: drive%d (type %d: cyl=%d,hd=%d,spt=%d), disk %d\n", - hdd[i].id.ide_channel, drive->type, - drive->tracks, drive->hpc, drive->spt, i); + INFO("HDC: drive%d (type %d: cyl=%d,hd=%d,spt=%d), disk %d\n", + hdd[i].id.ide_channel, drive->type, + drive->tracks, drive->hpc, drive->spt, i); if (++c > PS1_HDD_NUM) break; } diff --git a/src/machines/m_ps2_isa.c b/src/machines/m_ps2_isa.c index 11253cf..3532787 100644 --- a/src/machines/m_ps2_isa.c +++ b/src/machines/m_ps2_isa.c @@ -8,7 +8,7 @@ * * Implementation of ISA-based PS/2 machines. * - * Version: @(#)m_ps2_isa.c 1.0.12 2018/05/06 + * Version: @(#)m_ps2_isa.c 1.0.13 2018/09/04 * * Authors: Fred N. van Kempen, * Miran Grca, diff --git a/src/machines/m_ps2_mca.c b/src/machines/m_ps2_mca.c index 5f1e01a..ca1d8f8 100644 --- a/src/machines/m_ps2_mca.c +++ b/src/machines/m_ps2_mca.c @@ -8,7 +8,7 @@ * * Implementation of MCA-based PS/2 machines. * - * Version: @(#)m_ps2_mca.c 1.0.17 2018/08/20 + * Version: @(#)m_ps2_mca.c 1.0.18 2018/09/19 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -60,6 +60,7 @@ #include "../devices/input/mouse.h" #include "../devices/floppy/fdd.h" #include "../devices/floppy/fdc.h" +#include "../devices/video/video.h" #include "machine.h" @@ -80,10 +81,10 @@ static struct uint8_t io_id; - mem_mapping_t shadow_mapping; - mem_mapping_t split_mapping; - mem_mapping_t expansion_mapping; - mem_mapping_t cache_mapping; + mem_map_t shadow_mapping; + mem_map_t split_mapping; + mem_map_t expansion_mapping; + mem_map_t cache_mapping; uint8_t (*planar_read)(uint16_t port); void (*planar_write)(uint16_t port, uint8_t val); @@ -138,7 +139,7 @@ static int ps2_cache_valid[65536/8]; static uint8_t ps2_read_cache_ram(uint32_t addr, void *priv) { -// pclog("ps2_read_cache_ram: addr=%08x %i %04x:%04x\n", addr, ps2_cache_valid[addr >> 3], CS,cpu_state.pc); + DBGLOG(1, "ps2_read_cache_ram: addr=%08x %i %04x:%04x\n", addr, ps2_cache_valid[addr >> 3], CS,cpu_state.pc); if (!ps2_cache_valid[addr >> 3]) { ps2_cache_valid[addr >> 3] = 1; @@ -151,7 +152,7 @@ static uint8_t ps2_read_cache_ram(uint32_t addr, void *priv) } static uint16_t ps2_read_cache_ramw(uint32_t addr, void *priv) { -// pclog("ps2_read_cache_ramw: addr=%08x %i %04x:%04x\n", addr, ps2_cache_valid[addr >> 3], CS,cpu_state.pc); + DBGLOG(1, "ps2_read_cache_ramw: addr=%08x %i %04x:%04x\n", addr, ps2_cache_valid[addr >> 3], CS,cpu_state.pc); if (!ps2_cache_valid[addr >> 3]) { ps2_cache_valid[addr >> 3] = 1; @@ -160,11 +161,11 @@ static uint16_t ps2_read_cache_ramw(uint32_t addr, void *priv) else ps2.pending_cache_miss = 0; - return *(uint16_t *)&ps2_cache[addr]; + return *((uint16_t *)(ps2_cache+addr)); } static uint32_t ps2_read_cache_raml(uint32_t addr, void *priv) { -// pclog("ps2_read_cache_raml: addr=%08x %i %04x:%04x\n", addr, ps2_cache_valid[addr >> 3], CS,cpu_state.pc); + DBGLOG(1, "ps2_read_cache_raml: addr=%08x %i %04x:%04x\n", addr, ps2_cache_valid[addr >> 3], CS,cpu_state.pc); if (!ps2_cache_valid[addr >> 3]) { ps2_cache_valid[addr >> 3] = 1; @@ -173,11 +174,11 @@ static uint32_t ps2_read_cache_raml(uint32_t addr, void *priv) else ps2.pending_cache_miss = 0; - return *(uint32_t *)&ps2_cache[addr]; + return *((uint32_t *)ps2_cache+addr); } static void ps2_write_cache_ram(uint32_t addr, uint8_t val, void *priv) { -// pclog("ps2_write_cache_ram: addr=%08x val=%02x %04x:%04x %i\n", addr, val, CS,cpu_state.pc, ins); + DBGLOG(1, "ps2_write_cache_ram: addr=%08x val=%02x %04x:%04x %i\n", addr, val, CS,cpu_state.pc, ins); ps2_cache[addr] = val; } @@ -456,10 +457,11 @@ static void model_55sx_write(uint16_t port, uint8_t val) case 0x104: ps2.memory_bank[ps2.option[3] & 7] &= ~0xf; ps2.memory_bank[ps2.option[3] & 7] |= (val & 0xf); - /* pclog("Write memory bank %i %02x\n", ps2.option[3] & 7, val); */ + + DBGLOG(1, "Write memory bank %i %02x\n", ps2.option[3] & 7, val); break; case 0x105: - /* pclog("Write POS3 %02x\n", val); */ + DBGLOG(1, "Write POS3 %02x\n", val); ps2.option[3] = val; shadowbios = !(val & 0x10); shadowbios_write = val & 0x10; @@ -467,12 +469,12 @@ static void model_55sx_write(uint16_t port, uint8_t val) if (shadowbios) { mem_set_mem_state(0xe0000, 0x20000, MEM_READ_INTERNAL | MEM_WRITE_DISABLED); - mem_mapping_disable(&ps2.shadow_mapping); + mem_map_disable(&ps2.shadow_mapping); } else { mem_set_mem_state(0xe0000, 0x20000, MEM_READ_EXTERNAL | MEM_WRITE_INTERNAL); - mem_mapping_enable(&ps2.shadow_mapping); + mem_map_enable(&ps2.shadow_mapping); } if ((ps2.option[1] & 1) && !(ps2.option[3] & 0x20)) @@ -690,14 +692,14 @@ uint8_t ps2_mca_read(uint16_t port, void *p) break; } - /* pclog("ps2_read: port=%04x temp=%02x\n", port, temp); */ + DBGLOG(2, "ps2_read: port=%04x temp=%02x\n", port, temp); return temp; } static void ps2_mca_write(uint16_t port, uint8_t val, void *p) { - /* pclog("ps2_write: port=%04x val=%02x %04x:%04x\n", port, val, CS,cpu_state.pc); */ + DBGLOG(2, "ps2_write: port=%04x val=%02x %04x:%04x\n", port, val, CS,cpu_state.pc); switch (port) { @@ -790,9 +792,9 @@ static void ps2_mem_expansion_write(int port, uint8_t val, void *p) ps2.mem_pos_regs[port & 7] = val; if (ps2.mem_pos_regs[2] & 1) - mem_mapping_enable(&ps2.expansion_mapping); + mem_map_enable(&ps2.expansion_mapping); else - mem_mapping_disable(&ps2.expansion_mapping); + mem_map_disable(&ps2.expansion_mapping); } @@ -808,7 +810,7 @@ static void ps2_mca_mem_fffc_init(int start_mb) expansion_start = start_mb << 20; } - mem_mapping_set_addr(&ram_high_mapping, 0x100000, planar_size); + mem_map_set_addr(&ram_high_mapping, 0x100000, planar_size); ps2.mem_pos_regs[0] = 0xff; ps2.mem_pos_regs[1] = 0xfc; @@ -842,7 +844,7 @@ static void ps2_mca_mem_fffc_init(int start_mb) } mca_add(ps2_mem_expansion_read, ps2_mem_expansion_write, NULL); - mem_mapping_add(&ps2.expansion_mapping, + mem_map_add(&ps2.expansion_mapping, expansion_start, (mem_size - (start_mb << 10)) << 10, mem_read_ram, @@ -854,7 +856,7 @@ static void ps2_mca_mem_fffc_init(int start_mb) &ram[expansion_start], MEM_MAPPING_INTERNAL, NULL); - mem_mapping_disable(&ps2.expansion_mapping); + mem_map_disable(&ps2.expansion_mapping); } static void ps2_mca_board_model_50_init() @@ -874,14 +876,15 @@ static void ps2_mca_board_model_50_init() ps2_mca_mem_fffc_init(2); } - device_add(&ps1vga_device); + if (video_card == VID_INTERNAL) + device_add(&ps1vga_device); } static void ps2_mca_board_model_55sx_init() { ps2_mca_board_common_init(); - mem_mapping_add(&ps2.shadow_mapping, + mem_map_add(&ps2.shadow_mapping, (mem_size+256) * 1024, 128*1024, ps2_read_shadow_ram, @@ -937,29 +940,30 @@ static void ps2_mca_board_model_55sx_init() ps2.planar_read = model_55sx_read; ps2.planar_write = model_55sx_write; - device_add(&ps1vga_device); + if (video_card == VID_INTERNAL) + device_add(&ps1vga_device); } static void mem_encoding_update() { - mem_mapping_disable(&ps2.split_mapping); + mem_map_disable(&ps2.split_mapping); ps2.split_addr = ((uint32_t) (ps2.mem_regs[0] & 0xf)) << 20; if (ps2.mem_regs[1] & 2) { mem_set_mem_state(0xe0000, 0x20000, MEM_READ_EXTERNAL | MEM_WRITE_INTERNAL); - /* pclog("PS/2 Model 80-111: ROM space enabled\n"); */ + DEBUG("PS/2 Model 80-111: ROM space enabled\n"); } else { mem_set_mem_state(0xe0000, 0x20000, MEM_READ_INTERNAL | MEM_WRITE_DISABLED); - /* pclog("PS/2 Model 80-111: ROM space disabled\n"); */ + DEBUG("PS/2 Model 80-111: ROM space disabled\n"); } if (ps2.mem_regs[1] & 4) { - mem_mapping_set_addr(&ram_low_mapping, 0x00000, 0x80000); - /* pclog("PS/2 Model 80-111: 00080000- 0009FFFF disabled\n"); */ + mem_map_set_addr(&ram_low_mapping, 0x00000, 0x80000); + DEBUG("PS/2 Model 80-111: 00080000- 0009FFFF disabled\n"); } else { - mem_mapping_set_addr(&ram_low_mapping, 0x00000, 0xa0000); - /* pclog("PS/2 Model 80-111: 00080000- 0009FFFF enabled\n"); */ + mem_map_set_addr(&ram_low_mapping, 0x00000, 0xa0000); + DEBUG("PS/2 Model 80-111: 00080000- 0009FFFF enabled\n"); } if (!(ps2.mem_regs[1] & 8)) @@ -972,13 +976,13 @@ static void mem_encoding_update() ps2.split_phys = 0xa0000; } - mem_mapping_set_exec(&ps2.split_mapping, &ram[ps2.split_phys]); - mem_mapping_set_addr(&ps2.split_mapping, ps2.split_addr, ps2.split_size << 10); + mem_map_set_exec(&ps2.split_mapping, &ram[ps2.split_phys]); + mem_map_set_addr(&ps2.split_mapping, ps2.split_addr, ps2.split_size << 10); - /* pclog("PS/2 Model 80-111: Split memory block enabled at %08X\n", ps2.split_addr); */ - } /* else { - pclog("PS/2 Model 80-111: Split memory block disabled\n"); - } */ + DEBUG("PS/2 Model 80-111: Split memory block enabled at %08X\n", ps2.split_addr); + } else { + DEBUG("PS/2 Model 80-111: Split memory block disabled\n"); + } } static uint8_t mem_encoding_read(uint16_t addr, void *p) @@ -1037,7 +1041,7 @@ static void mem_encoding_write_cached(uint16_t addr, uint8_t val, void *p) ps2.mem_regs[2] = (ps2.mem_regs[2] & 0x80) | (val & ~0x88); if (val & 2) { -// pclog("Clear latch - %i\n", ps2.pending_cache_miss); + DBGLOG(1, "Clear latch - %i\n", ps2.pending_cache_miss); if (ps2.pending_cache_miss) ps2.mem_regs[2] |= 0x80; else @@ -1058,18 +1062,18 @@ static void mem_encoding_write_cached(uint16_t addr, uint8_t val, void *p) #endif break; } -// pclog("mem_encoding_write: addr=%02x val=%02x %04x:%04x %02x %02x\n", addr, val, CS,cpu_state.pc, ps2.mem_regs[1],ps2.mem_regs[2]); + DBGLOG(1, "mem_encoding_write: addr=%02x val=%02x %04x:%04x %02x %02x\n", addr, val, CS,cpu_state.pc, ps2.mem_regs[1],ps2.mem_regs[2]); mem_encoding_update(); if ((ps2.mem_regs[1] & 0x10) && (ps2.mem_regs[2] & 0x21) == 0x20) { - mem_mapping_disable(&ram_low_mapping); - mem_mapping_enable(&ps2.cache_mapping); + mem_map_disable(&ram_low_mapping); + mem_map_enable(&ps2.cache_mapping); flushmmucache(); } else { - mem_mapping_disable(&ps2.cache_mapping); - mem_mapping_enable(&ram_low_mapping); + mem_map_disable(&ps2.cache_mapping); + mem_map_enable(&ram_low_mapping); flushmmucache(); } } @@ -1114,7 +1118,7 @@ static void ps2_mca_board_model_70_type34_init(int is_type4) if (is_type4) ps2.option[2] |= 0x04; /*486 CPU*/ - mem_mapping_add(&ps2.split_mapping, + mem_map_add(&ps2.split_mapping, (mem_size+256) * 1024, 256*1024, ps2_read_split_ram, @@ -1126,9 +1130,9 @@ static void ps2_mca_board_model_70_type34_init(int is_type4) &ram[0xa0000], MEM_MAPPING_INTERNAL, NULL); - mem_mapping_disable(&ps2.split_mapping); + mem_map_disable(&ps2.split_mapping); - mem_mapping_add(&ps2.cache_mapping, + mem_map_add(&ps2.cache_mapping, 0, is_type4 ? (8 * 1024) : (64 * 1024), ps2_read_cache_ram, @@ -1140,7 +1144,7 @@ static void ps2_mca_board_model_70_type34_init(int is_type4) ps2_cache, MEM_MAPPING_INTERNAL, NULL); - mem_mapping_disable(&ps2.cache_mapping); + mem_map_disable(&ps2.cache_mapping); if (mem_size > 8192) { @@ -1148,7 +1152,8 @@ static void ps2_mca_board_model_70_type34_init(int is_type4) ps2_mca_mem_fffc_init(8); } - device_add(&ps1vga_device); + if (video_card == VID_INTERNAL) + device_add(&ps1vga_device); } static void ps2_mca_board_model_80_type2_init(int is_486) @@ -1197,7 +1202,7 @@ static void ps2_mca_board_model_80_type2_init(int is_486) ps2.mem_regs[0] |= ((mem_size/1024) & 0x0f); - mem_mapping_add(&ps2.split_mapping, + mem_map_add(&ps2.split_mapping, (mem_size+256) * 1024, 256*1024, ps2_read_split_ram, @@ -1209,7 +1214,7 @@ static void ps2_mca_board_model_80_type2_init(int is_486) &ram[0xa0000], MEM_MAPPING_INTERNAL, NULL); - mem_mapping_disable(&ps2.split_mapping); + mem_map_disable(&ps2.split_mapping); if ((mem_size > 4096) && !is_486) { @@ -1217,7 +1222,8 @@ static void ps2_mca_board_model_80_type2_init(int is_486) ps2_mca_mem_fffc_init(4); } - device_add(&ps1vga_device); + if (video_card == VID_INTERNAL) + device_add(&ps1vga_device); } diff --git a/src/machines/m_tandy.c b/src/machines/m_tandy.c index bb5e05c..cd15d45 100644 --- a/src/machines/m_tandy.c +++ b/src/machines/m_tandy.c @@ -8,7 +8,10 @@ * * Emulation of Tandy models 1000, 1000HX and 1000SL2. * - * Version: @(#)m_tandy.c 1.0.12 2018/05/06 + * NOTE: It might be better (after all..) to split off the video + * driver from the main code, to keep it a little cleaner. + * + * Version: @(#)m_tandy.c 1.0.13 2018/10/05 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -59,6 +62,7 @@ #include "../devices/sound/sound.h" #include "../devices/sound/snd_sn76489.h" #include "../devices/video/video.h" +#include "../devices/video/vid_cga.h" #include "../devices/video/vid_cga_comp.h" #include "../plat.h" #include "machine.h" @@ -77,41 +81,41 @@ enum { typedef struct { - mem_mapping_t mapping; - mem_mapping_t vram_mapping; + mem_map_t mapping; + mem_map_t vram_mapping; - uint8_t crtc[32]; - int crtcreg; + uint8_t crtc[32]; + int crtcreg; - int array_index; - uint8_t array[32]; - int memctrl; - uint8_t mode, col; - uint8_t stat; + int array_index; + uint8_t array[32]; + int memctrl; + uint8_t mode, col; + uint8_t stat; - uint8_t *vram, *b8000; - uint32_t b8000_mask; - uint32_t b8000_limit; - uint8_t planar_ctrl; + uint8_t *vram, *b8000; + uint32_t b8000_mask; + uint32_t b8000_limit; + uint8_t planar_ctrl; - int linepos, - displine; - int sc, vc; - int dispon; - int con, coff, - cursoron, - blink; - int64_t vsynctime; - int vadj; - uint16_t ma, maback; + int linepos, + displine; + int sc, vc; + int dispon; + int con, coff, + cursoron, + blink; + int64_t vsynctime; + int vadj; + uint16_t ma, maback; - int64_t dispontime, - dispofftime, - vidtime; - int firstline, - lastline; + int64_t dispontime, + dispofftime, + vidtime; + int firstline, + lastline; - int composite; + int composite; } t1kvid_t; typedef struct { @@ -135,32 +139,31 @@ typedef struct { } t1ksnd_t; typedef struct { - int romset; - wchar_t *path; + wchar_t *fn; - int state; - int count; - int addr; - int clk; - uint16_t data; - uint16_t store[64]; + int state; + int count; + int addr; + int clk; + uint16_t data; + uint16_t store[64]; } t1keep_t; typedef struct { - mem_mapping_t ram_mapping; - mem_mapping_t rom_mapping; /* SL2 */ + mem_map_t ram_mapping; + mem_map_t rom_mapping; /* SL2 */ - uint8_t *rom; /* SL2 */ - uint8_t ram_bank; - uint8_t rom_bank; /* SL2 */ - int rom_offset; /* SL2 */ + uint8_t *rom; /* SL2 */ + uint8_t ram_bank; + uint8_t rom_bank; /* SL2 */ + int rom_offset; /* SL2 */ - uint32_t base; - int is_sl2; + uint32_t base; + int type; - t1ksnd_t *snd; + t1ksnd_t *snd; - t1kvid_t *vid; + t1kvid_t *vid; } tandy_t; @@ -445,16 +448,16 @@ recalc_mapping(tandy_t *dev) { t1kvid_t *vid = dev->vid; - mem_mapping_disable(&vid->mapping); + mem_map_disable(&vid->mapping); io_removehandler(0x03d0, 16, vid_in, NULL, NULL, vid_out, NULL, NULL, dev); if (vid->planar_ctrl & 4) { - mem_mapping_enable(&vid->mapping); + mem_map_enable(&vid->mapping); if (vid->array[5] & 1) - mem_mapping_set_addr(&vid->mapping, 0xa0000, 0x10000); + mem_map_set_addr(&vid->mapping, 0xa0000, 0x10000); else - mem_mapping_set_addr(&vid->mapping, 0xb8000, 0x8000); + mem_map_set_addr(&vid->mapping, 0xb8000, 0x8000); io_sethandler(0x03d0, 16, vid_in,NULL,NULL, vid_out,NULL,NULL, dev); } } @@ -536,7 +539,7 @@ vid_out(uint16_t addr, uint8_t val, void *priv) case 0x03d5: old = vid->crtc[vid->crtcreg]; - if (dev->is_sl2) + if (dev->type == 2) vid->crtc[vid->crtcreg] = val & crtcmask_sl[vid->crtcreg]; else vid->crtc[vid->crtcreg] = val & crtcmask[vid->crtcreg]; @@ -550,7 +553,7 @@ vid_out(uint16_t addr, uint8_t val, void *priv) case 0x03d8: vid->mode = val; - if (! dev->is_sl2) + if (dev->type != 2) update_cga16_color(vid->mode); break; @@ -566,7 +569,7 @@ vid_out(uint16_t addr, uint8_t val, void *priv) if (vid->array_index & 16) val &= 0xf; vid->array[vid->array_index & 0x1f] = val; - if (dev->is_sl2) { + if (dev->type == 2) { if ((vid->array_index & 0x1f) == 5) { recalc_mapping(dev); recalc_address_sl(dev); @@ -576,7 +579,7 @@ vid_out(uint16_t addr, uint8_t val, void *priv) case 0x03df: vid->memctrl = val; - if (dev->is_sl2) + if (dev->type == 2) recalc_address_sl(dev); else recalc_address(dev); @@ -624,8 +627,7 @@ vid_write(uint32_t addr, uint8_t val, void *priv) if (vid->memctrl == -1) return; - egawrites++; - if (dev->is_sl2) { + if (dev->type == 2) { if (vid->array[5] & 1) vid->b8000[addr & 0xffff] = val; else { @@ -643,20 +645,19 @@ vid_read(uint32_t addr, void *priv) { tandy_t *dev = (tandy_t *)priv; t1kvid_t *vid = dev->vid; + uint8_t ret = 0xff; - if (vid->memctrl == -1) return(0xff); + if (vid->memctrl == -1) return(ret); - egareads++; - if (dev->is_sl2) { + if (dev->type == 2) { if (vid->array[5] & 1) - return(vid->b8000[addr & 0xffff]); + ret = vid->b8000[addr & 0xffff]; if ((addr & 0x7fff) < vid->b8000_limit) - return(vid->b8000[addr & 0x7fff]); - else - return(0xff); - } else { - return(vid->b8000[addr & vid->b8000_mask]); - } + ret = vid->b8000[addr & 0x7fff]; + } else + ret = vid->b8000[addr & vid->b8000_mask]; + + return(ret); } @@ -858,15 +859,15 @@ vid_poll(void *priv) } else { if (vid->array[3] & 4) { if (vid->mode & 1) - hline(buffer, 0, vid->displine, (vid->crtc[1] << 3) + 16, (vid->array[2] & 0xf) + 16); + cga_hline(buffer, 0, vid->displine, (vid->crtc[1] << 3) + 16, (vid->array[2] & 0xf) + 16); else - hline(buffer, 0, vid->displine, (vid->crtc[1] << 4) + 16, (vid->array[2] & 0xf) + 16); + cga_hline(buffer, 0, vid->displine, (vid->crtc[1] << 4) + 16, (vid->array[2] & 0xf) + 16); } else { cols[0] = ((vid->mode & 0x12) == 0x12) ? 0 : (vid->col & 0xf) + 16; if (vid->mode & 1) - hline(buffer, 0, vid->displine, (vid->crtc[1] << 3) + 16, cols[0]); + cga_hline(buffer, 0, vid->displine, (vid->crtc[1] << 3) + 16, cols[0]); else - hline(buffer, 0, vid->displine, (vid->crtc[1] << 4) + 16, cols[0]); + cga_hline(buffer, 0, vid->displine, (vid->crtc[1] << 4) + 16, cols[0]); } } @@ -1203,15 +1204,15 @@ vid_poll_sl(void *priv) } else { if (vid->array[3] & 4) { if (vid->mode & 1) - hline(buffer, 0, vid->displine, (vid->crtc[1] << 3) + 16, (vid->array[2] & 0xf) + 16); + cga_hline(buffer, 0, vid->displine, (vid->crtc[1] << 3) + 16, (vid->array[2] & 0xf) + 16); else - hline(buffer, 0, vid->displine, (vid->crtc[1] << 4) + 16, (vid->array[2] & 0xf) + 16); + cga_hline(buffer, 0, vid->displine, (vid->crtc[1] << 4) + 16, (vid->array[2] & 0xf) + 16); } else { cols[0] = ((vid->mode & 0x12) == 0x12) ? 0 : (vid->col & 0xf) + 16; if (vid->mode & 1) - hline(buffer, 0, vid->displine, (vid->crtc[1] << 3) + 16, cols[0]); + cga_hline(buffer, 0, vid->displine, (vid->crtc[1] << 3) + 16, cols[0]); else - hline(buffer, 0, vid->displine, (vid->crtc[1] << 4) + 16, cols[0]); + cga_hline(buffer, 0, vid->displine, (vid->crtc[1] << 4) + 16, cols[0]); } } @@ -1366,7 +1367,7 @@ vid_init(tandy_t *dev) int display_type; t1kvid_t *vid; - vid = malloc(sizeof(t1kvid_t)); + vid = (t1kvid_t *)mem_alloc(sizeof(t1kvid_t)); memset(vid, 0x00, sizeof(t1kvid_t)); vid->memctrl = -1; dev->vid = vid; @@ -1376,7 +1377,7 @@ vid_init(tandy_t *dev) cga_comp_init(1); - if (dev->is_sl2) { + if (dev->type == 2) { vid->b8000_limit = 0x8000; vid->planar_ctrl = 4; overscan_x = overscan_y = 16; @@ -1389,8 +1390,10 @@ vid_init(tandy_t *dev) timer_add(vid_poll, &vid->vidtime, TIMER_ALWAYS_ENABLED, dev); } - mem_mapping_add(&vid->mapping, 0xb8000, 0x08000, - vid_read,NULL,NULL, vid_write,NULL,NULL, NULL, 0, dev); + + mem_map_add(&vid->mapping, 0xb8000, 0x08000, + vid_read,NULL,NULL, vid_write,NULL,NULL, NULL, 0, dev); + io_sethandler(0x03d0, 16, vid_in,NULL,NULL, vid_out,NULL,NULL, dev); } @@ -1574,7 +1577,7 @@ snd_init(const device_t *info) { t1ksnd_t *dev; - dev = (t1ksnd_t *)malloc(sizeof(t1ksnd_t)); + dev = (t1ksnd_t *)mem_alloc(sizeof(t1ksnd_t)); memset(dev, 0x00, sizeof(t1ksnd_t)); sn76489_init(&dev->sn76489, 0x00c0, 0x0004, PSSJ, 3579545); @@ -1689,27 +1692,24 @@ eep_write(uint16_t addr, uint8_t val, void *priv) static void * eep_init(const device_t *info) { + char temp[128]; t1keep_t *eep; - FILE *f = NULL; + FILE *fp = NULL; + int i; - eep = (t1keep_t *)malloc(sizeof(t1keep_t)); + eep = (t1keep_t *)mem_alloc(sizeof(t1keep_t)); memset(eep, 0x00, sizeof(t1keep_t)); - eep->romset = romset; - switch (romset) { - case ROM_TANDY1000HX: - eep->path = L"tandy1000hx.bin"; - break; - case ROM_TANDY1000SL2: - eep->path = L"tandy1000sl2.bin"; - break; - - } - - f = plat_fopen(nvr_path(eep->path), L"rb"); - if (f != NULL) { - fread(eep->store, 128, 1, f); - (void)fclose(f); + /* Set up the EEPROM's file name. */ + sprintf(temp, "%s.bin", machine_get_internal_name()); + i = strlen(temp) + 1; + eep->fn = (wchar_t *)mem_alloc(i * sizeof(wchar_t)); + mbstowcs(eep->fn, temp, i); + + fp = plat_fopen(nvr_path(eep->fn), L"rb"); + if (fp != NULL) { + fread(eep->store, 128, 1, fp); + (void)fclose(fp); } io_sethandler(0x037c, 1, NULL,NULL,NULL, eep_write,NULL,NULL, eep); @@ -1722,14 +1722,15 @@ static void eep_close(void *priv) { t1keep_t *eep = (t1keep_t *)priv; - FILE *f = NULL; + FILE *fp; - f = plat_fopen(nvr_path(eep->path), L"rb"); - if (f != NULL) { - (void)fwrite(eep->store, 128, 1, f); - (void)fclose(f); + fp = plat_fopen(nvr_path(eep->fn), L"rb"); + if (fp != NULL) { + (void)fwrite(eep->store, 128, 1, fp); + (void)fclose(fp); } + free(eep->fn); free(eep); } @@ -1750,18 +1751,17 @@ tandy_write(uint16_t addr, uint8_t val, void *priv) switch (addr) { case 0x00a0: - mem_mapping_set_addr(&dev->ram_mapping, - ((val >> 1) & 7) * 128 * 1024, 0x20000); + mem_map_set_addr(&dev->ram_mapping, + ((val >> 1) & 7) * 128 * 1024, 0x20000); dev->ram_bank = val; break; case 0xffe8: if ((val & 0xe) == 0xe) - mem_mapping_disable(&dev->ram_mapping); + mem_map_disable(&dev->ram_mapping); else - mem_mapping_set_addr(&dev->ram_mapping, - ((val >> 1) & 7) * 128 * 1024, - 0x20000); + mem_map_set_addr(&dev->ram_mapping, + ((val >> 1) & 7) * 128 * 1024, 0x20000); recalc_address_sl(dev); dev->ram_bank = val; break; @@ -1769,8 +1769,8 @@ tandy_write(uint16_t addr, uint8_t val, void *priv) case 0xffea: dev->rom_bank = val; dev->rom_offset = ((val ^ 4) & 7) * 0x10000; - mem_mapping_set_exec(&dev->rom_mapping, - &dev->rom[dev->rom_offset]); + mem_map_set_exec(&dev->rom_mapping, + &dev->rom[dev->rom_offset]); } } @@ -1849,20 +1849,20 @@ read_roml(uint32_t addr, void *priv) static void init_rom(tandy_t *dev) { - dev->rom = (uint8_t *)malloc(0x80000); + dev->rom = (uint8_t *)mem_alloc(0x80000); if (! rom_load_interleaved(L"machines/tandy1000sl2/8079047.hu1", L"machines/tandy1000sl2/8079048.hu2", 0x000000, 0x80000, 0, dev->rom)) { - pclog("TANDY: unable to load BIOS for 1000/SL2 !\n"); + ERRLOG("TANDY: unable to load BIOS for 1000/SL2 !\n"); free(dev->rom); dev->rom = NULL; return; } - mem_mapping_add(&dev->rom_mapping, 0xe0000, 0x10000, - read_rom, read_romw, read_roml, NULL, NULL, NULL, - dev->rom, MEM_MAPPING_EXTERNAL, dev); + mem_map_add(&dev->rom_mapping, 0xe0000, 0x10000, + read_rom, read_romw, read_roml, NULL, NULL, NULL, + dev->rom, MEM_MAPPING_EXTERNAL, dev); } @@ -1886,6 +1886,7 @@ static const device_config_t vid_config[] = { } }; +static const video_timings_t tandy_timing = { VID_BUS,1,2,4,1,2,4 }; const device_t m_tandy1k_device = { "Tandy 1000", @@ -1921,13 +1922,14 @@ const device_t m_tandy1k_sl2_device = { }; -void -machine_tandy1k_init(const machine_t *model, void *arg) +static void +tandy1k_common_init(const machine_t *model, void *arg, int type) { tandy_t *dev; - dev = malloc(sizeof(tandy_t)); + dev = (tandy_t *)mem_alloc(sizeof(tandy_t)); memset(dev, 0x00, sizeof(tandy_t)); + dev->type = type; machine_common_init(model, arg); @@ -1938,40 +1940,48 @@ machine_tandy1k_init(const machine_t *model, void *arg) * 0xFFE8 (SL2), so we remove it from the main mapping. */ dev->base = (mem_size - 128) * 1024; - mem_mapping_add(&dev->ram_mapping, 0x80000, 0x20000, - read_ram,NULL,NULL, write_ram,NULL,NULL, NULL, 0, dev); - mem_mapping_set_addr(&ram_low_mapping, 0, dev->base); + mem_map_add(&dev->ram_mapping, 0x80000, 0x20000, + read_ram,NULL,NULL, write_ram,NULL,NULL, NULL, 0, dev); + mem_map_set_addr(&ram_low_mapping, 0, dev->base); device_add(&keyboard_tandy_device); keyboard_set_table(scancode_tandy); device_add(&fdc_xt_device); - switch(romset) { - case ROM_TANDY: + switch(dev->type) { + case 0: io_sethandler(0x00a0, 1, tandy_read,NULL,NULL,tandy_write,NULL,NULL,dev); vid_init(dev); device_add_ex(&m_tandy1k_device, dev); + + video_inform(VID_TYPE_CGA, &tandy_timing); + device_add(&sn76489_device); break; - case ROM_TANDY1000HX: + case 1: io_sethandler(0x00a0, 1, tandy_read,NULL,NULL,tandy_write,NULL,NULL,dev); vid_init(dev); device_add_ex(&m_tandy1k_hx_device, dev); + + video_inform(VID_TYPE_CGA, &tandy_timing); + device_add(&ncr8496_device); device_add(&eep_device); break; - case ROM_TANDY1000SL2: - dev->is_sl2 = 1; + case 2: init_rom(dev); io_sethandler(0xffe8, 8, tandy_read,NULL,NULL,tandy_write,NULL,NULL,dev); vid_init(dev); device_add_ex(&m_tandy1k_sl2_device, dev); + + video_inform(VID_TYPE_CGA, &tandy_timing); + device_add(&snd_device); device_add(&eep_device); } @@ -1980,6 +1990,27 @@ machine_tandy1k_init(const machine_t *model, void *arg) } +void +machine_tandy1k_init(const machine_t *model, void *arg) +{ + tandy1k_common_init(model, arg, 0); +} + + +void +machine_tandy1k_hx_init(const machine_t *model, void *arg) +{ + tandy1k_common_init(model, arg, 1); +} + + +void +machine_tandy1k_sl2_init(const machine_t *model, void *arg) +{ + tandy1k_common_init(model, arg, 2); +} + + int tandy1k_eeprom_read(void) { diff --git a/src/machines/m_xt.c b/src/machines/m_xt.c index 48401c6..dd3cf49 100644 --- a/src/machines/m_xt.c +++ b/src/machines/m_xt.c @@ -8,7 +8,7 @@ * * Implementation of standard IBM PC/XT class machine. * - * Version: @(#)m_xt.c 1.0.10 2018/05/06 + * Version: @(#)m_xt.c 1.0.11 2018/09/15 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -54,7 +54,7 @@ static int rom_basic = 0; /* is ROM BASIC enabled? */ -static const device_config_t xt_config[] = { +static const device_config_t pcxt_config[] = { { "rom_basic", "ROM BASIC", CONFIG_SELECTION, "", 0, { @@ -75,6 +75,29 @@ static const device_config_t xt_config[] = { }; +void +machine_pc_init(const machine_t *model, void *arg) +{ + machine_common_init(model, arg); + + /* Check if we support a BASIC ROM. */ + if (model->device != NULL) { + DEBUG("This (%s) machine supports a BASIC ROM.\n", model->name); + + rom_basic = machine_get_config_int("rom_basic"); + DEBUG("ROM BASIC is currently %sabled.\n", (rom_basic)?"en":"dis"); + } + + pit_set_out_func(&pit, 1, pit_refresh_timer_xt); + + device_add(&keyboard_pc_device); + + device_add(&fdc_xt_device); + + nmi_init(); +} + + void machine_xt_init(const machine_t *model, void *arg) { @@ -82,10 +105,10 @@ machine_xt_init(const machine_t *model, void *arg) /* Check if we support a BASIC ROM. */ if (model->device != NULL) { - pclog("This (%s) machine supports a BASIC ROM.\n", model->name); + DEBUG("This (%s) machine supports a BASIC ROM.\n", model->name); rom_basic = machine_get_config_int("rom_basic"); - pclog("ROM BASIC is currently %sabled.\n", (rom_basic)?"en":"dis"); + DEBUG("ROM BASIC is currently %sabled.\n", (rom_basic)?"en":"dis"); } pit_set_out_func(&pit, 1, pit_refresh_timer_xt); @@ -98,10 +121,18 @@ machine_xt_init(const machine_t *model, void *arg) } +const device_t m_pc_device = { + "IBM PC", + 0, 0, + NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + pcxt_config +}; + const device_t m_xt_device = { "PC/XT", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - xt_config + pcxt_config }; diff --git a/src/machines/m_xt_compaq.c b/src/machines/m_xt_compaq.c index 18d0d8b..c271fa8 100644 --- a/src/machines/m_xt_compaq.c +++ b/src/machines/m_xt_compaq.c @@ -6,13 +6,12 @@ * * This file is part of the VARCem Project. * - * Emulation of various Compaq XT-class PC's. + * Emulation of the Compaq XT-class PC's. * - * Version: @(#)m_xt_compaq.c 1.0.11 2018/05/06 + * Version: @(#)m_xt_compaq.c 1.0.12 2018/09/15 * * Authors: Fred N. van Kempen, * Miran Grca, - * TheCollector1995, * Sarah Walker, * * Copyright 2017,2018 Fred N. van Kempen. @@ -56,7 +55,7 @@ void -machine_xt_compaq_init(const machine_t *model, void *arg) +machine_xt_compaq_p1_init(const machine_t *model, void *arg) { machine_common_init(model, arg); @@ -68,9 +67,5 @@ machine_xt_compaq_init(const machine_t *model, void *arg) nmi_init(); - switch(model->id) { - case ROM_PORTABLE: - parallel_setup(1, 0x03bc); - break; - } + parallel_setup(1, 0x03bc); } diff --git a/src/machines/m_xt_laserxt.c b/src/machines/m_xt_laserxt.c index 9b1249a..f47c141 100644 --- a/src/machines/m_xt_laserxt.c +++ b/src/machines/m_xt_laserxt.c @@ -8,7 +8,7 @@ * * Emulation of the Laser XT series of machines. * - * Version: @(#)m_xt_laserxt.c 1.0.6 2018/05/06 + * Version: @(#)m_xt_laserxt.c 1.0.7 2018/09/19 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -45,6 +45,12 @@ #include "../io.h" #include "../mem.h" #include "../rom.h" +#include "../device.h" +#include "../devices/system/nmi.h" +#include "../devices/system/pit.h" +#include "../devices/input/keyboard.h" +#include "../devices/floppy/fdd.h" +#include "../devices/floppy/fdc.h" #include "machine.h" @@ -53,15 +59,16 @@ static int ems_page[4]; static int ems_control[4]; -static mem_mapping_t ems_mapping[4]; +static mem_map_t ems_mapping[4]; static int ems_baseaddr_index = 0; +static int is_lxt3 = 0; static uint32_t get_ems_addr(uint32_t addr) { if (ems_page[(addr >> 14) & 3] & 0x80) { - addr = (romset == ROM_LTXT ? 0x70000 + (((mem_size + 64) & 255) << 10) : 0x30000 + (((mem_size + 320) & 511) << 10)) + ((ems_page[(addr >> 14) & 3] & 0x0F) << 14) + ((ems_page[(addr >> 14) & 3] & 0x40) << 12) + (addr & 0x3FFF); + addr = (!is_lxt3 ? 0x70000 + (((mem_size + 64) & 255) << 10) : 0x30000 + (((mem_size + 320) & 511) << 10)) + ((ems_page[(addr >> 14) & 3] & 0x0F) << 14) + ((ems_page[(addr >> 14) & 3] & 0x40) << 12) + (addr & 0x3FFF); } return addr; @@ -82,11 +89,11 @@ do_write(uint16_t port, uint8_t val, void *priv) ems_page[port >> 14] = val; paddr = 0xC0000 + (port & 0xC000) + (((ems_baseaddr_index + (4 - (port >> 14))) & 0x0C) << 14); if (val & 0x80) { - mem_mapping_enable(&ems_mapping[port >> 14]); + mem_map_enable(&ems_mapping[port >> 14]); vaddr = get_ems_addr(paddr); - mem_mapping_set_exec(&ems_mapping[port >> 14], ram + vaddr); + mem_map_set_exec(&ems_mapping[port >> 14], ram + vaddr); } else { - mem_mapping_disable(&ems_mapping[port >> 14]); + mem_map_disable(&ems_mapping[port >> 14]); } flushmmucache(); break; @@ -100,15 +107,11 @@ do_write(uint16_t port, uint8_t val, void *priv) for (i = 0; i < 4; i++) { ems_baseaddr_index |= (ems_control[i] & 0x80) >> (7 - i); } - if (ems_baseaddr_index < 3) - mem_mapping_disable(&romext_mapping); - else - mem_mapping_enable(&romext_mapping); - mem_mapping_set_addr(&ems_mapping[0], 0xC0000 + (((ems_baseaddr_index + 4) & 0x0C) << 14), 0x4000); - mem_mapping_set_addr(&ems_mapping[1], 0xC4000 + (((ems_baseaddr_index + 3) & 0x0C) << 14), 0x4000); - mem_mapping_set_addr(&ems_mapping[2], 0xC8000 + (((ems_baseaddr_index + 2) & 0x0C) << 14), 0x4000); - mem_mapping_set_addr(&ems_mapping[3], 0xCC000 + (((ems_baseaddr_index + 1) & 0x0C) << 14), 0x4000); + mem_map_set_addr(&ems_mapping[0], 0xC0000 + (((ems_baseaddr_index + 4) & 0x0C) << 14), 0x4000); + mem_map_set_addr(&ems_mapping[1], 0xC4000 + (((ems_baseaddr_index + 3) & 0x0C) << 14), 0x4000); + mem_map_set_addr(&ems_mapping[2], 0xC8000 + (((ems_baseaddr_index + 2) & 0x0C) << 14), 0x4000); + mem_map_set_addr(&ems_mapping[3], 0xCC000 + (((ems_baseaddr_index + 1) & 0x0C) << 14), 0x4000); flushmmucache(); break; } @@ -161,11 +164,13 @@ mem_read_ems(uint32_t addr, void *priv) static void -laserxt_init(void) +laserxt_init(int lxt3) { int i; - if(mem_size > 640) { + is_lxt3 = lxt3; + + if (mem_size > 640) { io_sethandler(0x0208, 2, do_read,NULL,NULL, do_write,NULL,NULL, NULL); io_sethandler(0x4208, 2, @@ -175,18 +180,18 @@ laserxt_init(void) io_sethandler(0xc208, 2, do_read,NULL,NULL, do_write,NULL,NULL, NULL); - mem_mapping_set_addr(&ram_low_mapping, 0, romset == ROM_LTXT ? 0x70000 + (((mem_size + 64) & 255) << 10) : 0x30000 + (((mem_size + 320) & 511) << 10)); + mem_map_set_addr(&ram_low_mapping, 0, !is_lxt3 ? 0x70000 + (((mem_size + 64) & 255) << 10) : 0x30000 + (((mem_size + 320) & 511) << 10)); } for (i = 0; i < 4; i++) { ems_page[i] = 0x7F; ems_control[i] = (i == 3) ? 0x00 : 0x80; - mem_mapping_add(&ems_mapping[i], 0xE0000 + (i << 14), 0x4000, + mem_map_add(&ems_mapping[i], 0xE0000 + (i << 14), 0x4000, mem_read_ems,NULL,NULL, mem_write_ems,NULL,NULL, ram + 0xA0000 + (i << 14), 0, NULL); - mem_mapping_disable(&ems_mapping[i]); + mem_map_disable(&ems_mapping[i]); } mem_set_mem_state(0x0c0000, 0x40000, @@ -197,11 +202,27 @@ laserxt_init(void) void machine_xt_laserxt_init(const machine_t *model, void *arg) { - machine_xt_init(model, arg); + machine_xt_init(model, arg); - laserxt_init(); + laserxt_init(0); } +void +machine_xt_lxt3_init(const machine_t *model, void *arg) +{ + machine_common_init(model, arg); + + pit_set_out_func(&pit, 1, pit_refresh_timer_xt); + + device_add(&keyboard_xt_lxt3_device); + + device_add(&fdc_xt_device); + + nmi_init(); + + laserxt_init(1); +} + #endif /*defined(DEV_BRANCH) && defined(USE_LASERXT)*/ diff --git a/src/machines/m_xt_t1000.c b/src/machines/m_xt_t1000.c index 8a73b90..bc9f6b4 100644 --- a/src/machines/m_xt_t1000.c +++ b/src/machines/m_xt_t1000.c @@ -36,21 +36,67 @@ * * The T1200 is a slightly upgraded version with a turbo mode * (double CPU clock, 9.54MHz) and an optional hard drive. - * The interface for this is proprietary both at the physical - * and programming level. + * + * The hard drive is a JVC JD-3824R00-1 (20MB, 615/2/34) RLL + * 3.5" drive with custom 26-pin interface. This is what is + * known about the drive: + * + * JD-3824G is a 20MB hard disk drive that JVC made as one + * of OEM products. This HDD was shipped to Laptop PC + * manufactures. + * + * This HDD was discontinued about 10 years ago and JVC + * America does not have detail information because of the + * OEM product. + * + * This is the information that I have. + * [JD-3824G] + * 1. 3.5" 20MB Hard Disk Drive + * 2. JVC original interface (26 pin) + * This is not the IDE interface. This drive was made long + * before IDE standard. It required special controller board. + * This interface is not compatible with any other disk + * interface. + * + * Pin 1 GND Pin 2 -Read Data + * Pin 3 GND Pin 4 -Write data + * Pin 5 GND Pin 6 Reserved + * Pin 7 -Drive Select/+Power Save Pin 8 -Ship Ready + * Pin 9 GND Pin 10 +Read/-Write control + * Pin 11 -Motor On Pin 12 Head Select(+Head 0/ - Head1) + * Pin 13 -Direction In Pin 14 -Step + * Pin 15 -Write Fault Pin 16 -Seek Complete + * Pin 17 -Servo Gate Pin 18 -Index + * Pin 19 -Track 000 Pin 20 -Drive Ready + * Pin 21 GND Pin 22 +5V + * Pin 23 GND Pin 24 +5V + * Pin 25 GND Pin 26 +12V + * + * 3. Parameters( 2 heads, 34 sectors, 615 cylinders) + * 4. 2-7 RLL coding + * 5. Spindle Rotation: 2597 rpm + * 6. Data Transfer: 7.5M bps + * 7. Average Access: 78ms + * 8. Power Voltage: 5V and 12V + * + * (from Jeff Kishida, JVC Americas, Corp. + * Tel: 714-827-6267 Fax: 714-827-8740 + * Email: Jeff.Kishida@worldnet.att.net) + * + * The controller is on a separate PCB, and contains a T7518, + * DC2090P166A and a 27256 EPROM (label "036A") with BIOS. The + * interface for this is proprietary at the rogramming level. * * 01F2h: If hard drive is present, low 4 bits are 0Ch [20Mb] * or 0Dh [10Mb]. * - * The hard drive is a 20MB (615/2/26) RLL 3.5" drive. - * * The TC8521 is a 4-bit RTC, so each memory location can only * hold a single BCD digit. Hence everything has 'ones' and * 'tens' digits. * * FIXME: The ROM drive should be re-done using the "option file". * - * Version: @(#)m_xt_t1000.c 1.0.14 2018/09/21 + * Version: @(#)m_xt_t1000.c 1.0.14 2018/09/22 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -89,14 +135,15 @@ #include "../io.h" #include "../mem.h" #include "../rom.h" -#include "../nvr.h" #include "../device.h" +#include "../nvr.h" #include "../devices/system/nmi.h" #include "../devices/system/pit.h" #include "../devices/ports/parallel.h" #include "../devices/input/keyboard.h" #include "../devices/floppy/fdd.h" #include "../devices/floppy/fdc.h" +#include "../devices/disk/hdc.h" #include "../devices/video/video.h" #include "../plat.h" #include "machine.h" @@ -134,11 +181,13 @@ enum TC8521_ADDR { typedef struct { /* ROM drive */ - int rom_dos; - uint8_t *romdrive; + int8_t rom_dos, + is_t1200; + uint8_t rom_ctl; uint32_t rom_offset; - mem_mapping_t rom_mapping; + uint8_t *romdrive; + mem_map_t rom_mapping; /* CONFIG.SYS drive. */ wchar_t cfgsys_fn[128]; @@ -155,11 +204,11 @@ typedef struct { uint8_t nvr_tick; int nvr_addr; uint8_t nvr_active; - mem_mapping_t nvr_mapping; /* T1200 NVRAM mapping */ + mem_map_t nvr_mapping; /* T1200 NVRAM mapping */ /* EMS data */ uint8_t ems_reg[4]; - mem_mapping_t mapping[4]; + mem_map_t mapping[4]; uint32_t page_exec[4]; uint8_t ems_port_index; uint16_t ems_port; @@ -167,7 +216,7 @@ typedef struct { uint32_t ems_base; int32_t ems_pages; - fdc_t *fdc; + fdc_t *fdc; nvr_t nvr; } t1000_t; @@ -225,7 +274,7 @@ tc8521_time_get(uint8_t *regs, struct tm *tm) static void tc8521_tick(nvr_t *nvr) { - pclog("TC8521: ping\n"); + DEBUG("TC8521: ping\n"); } @@ -235,7 +284,7 @@ tc8521_start(nvr_t *nvr) struct tm tm; /* Initialize the internal and chip times. */ - if (enable_sync) { + if (time_sync != TIME_SYNC_DISABLED) { /* Use the internal clock's time. */ nvr_time_get(&tm); tc8521_time_set(nvr->regs, &tm); @@ -335,9 +384,7 @@ ems_execaddr(t1000_t *sys, int pg, uint16_t val) * HardRAM or conventional RAM */ val &= 0x7f; -#if 0 - pclog("Select EMS page: %d of %d\n", val, sys->ems_pages); -#endif + DBGLOG(1, "Select EMS page: %d of %d\n", val, sys->ems_pages); if (val < sys->ems_pages) { /* EMS is any memory above 512k, with ems_base giving the start address */ @@ -352,11 +399,12 @@ static uint8_t ems_in(uint16_t addr, void *priv) { t1000_t *sys = (t1000_t *)priv; + uint8_t ret; -#if 0 - pclog("ems_in(%04x)=%02x\n", addr, sys->ems_reg[(addr >> 14) & 3]); -#endif - return(sys->ems_reg[(addr >> 14) & 3]); + ret = sys->ems_reg[(addr >> 14) & 3]; + DBGLOG(1, "ems_in(%04x)=%02x\n", addr, ret); + + return(ret); } @@ -366,17 +414,16 @@ ems_out(uint16_t addr, uint8_t val, void *priv) t1000_t *sys = (t1000_t *)priv; int pg = (addr >> 14) & 3; -#if 0 - pclog("ems_out(%04x, %02x) pg=%d\n", addr, val, pg); -#endif + DBGLOG(1, "ems_out(%04x, %02x) pg=%d\n", addr, val, pg); + sys->ems_reg[pg] = val; sys->page_exec[pg] = ems_execaddr(sys, pg, val); if (sys->page_exec[pg]) { /* Page present */ - mem_mapping_enable(&sys->mapping[pg]); - mem_mapping_set_exec(&sys->mapping[pg], ram + sys->page_exec[pg]); + mem_map_enable(&sys->mapping[pg]); + mem_map_set_exec(&sys->mapping[pg], ram + sys->page_exec[pg]); } else { - mem_mapping_disable(&sys->mapping[pg]); + mem_map_disable(&sys->mapping[pg]); } } @@ -393,10 +440,8 @@ ems_set_hardram(t1000_t *sys, uint8_t val) else sys->ems_base = 0; -#if 0 - pclog("EMS base set to %02x\n", val); -#endif - sys->ems_pages = 48 - 4 * sys->ems_base; + DEBUG("EMS base set to %02x\n", val); + sys->ems_pages = ((mem_size - 512) / 16) - 4 * sys->ems_base; if (sys->ems_pages < 0) sys->ems_pages = 0; /* Recalculate EMS mappings */ @@ -409,10 +454,10 @@ static void ems_set_640k(t1000_t *sys, uint8_t val) { if (val && mem_size >= 640) { - mem_mapping_set_addr(&ram_low_mapping, 0, 640 * 1024); + mem_map_set_addr(&ram_low_mapping, 0, 640 * 1024); sys->is_640k = 1; } else { - mem_mapping_set_addr(&ram_low_mapping, 0, 512 * 1024); + mem_map_set_addr(&ram_low_mapping, 0, 512 * 1024); sys->is_640k = 0; } } @@ -423,9 +468,7 @@ ems_set_port(t1000_t *sys, uint8_t val) { int n; -#if 0 - pclog("ems_set_port(%d)", val & 0x0f); -#endif + DBGLOG(1, "ems_set_port(%d)", val & 0x0f); if (sys->ems_port) { for (n = 0; n <= 0xc000; n += 0x4000) { io_removehandler(sys->ems_port+n, 1, @@ -448,9 +491,7 @@ ems_set_port(t1000_t *sys, uint8_t val) sys->ems_port = 0; } -#if 0 - pclog(" -> %04x\n", sys->ems_port); -#endif + DBGLOG(1, " -> %04x\n", sys->ems_port); } @@ -483,14 +524,9 @@ ems_read_ramw(uint32_t addr, void *priv) if (pg < 0) return(0xff); -#if 0 - pclog("ems_read_ramw addr=%05x ", addr); -#endif + DBGLOG(1, "ems_read_ramw addr=%05x ", addr); addr = sys->page_exec[pg] + (addr & 0x3FFF); - -#if 0 - pclog("-> %06x val=%04x\n", addr, *(uint16_t *)&ram[addr]); -#endif + DBGLOG(1, "-> %06x val=%04x\n", addr, *(uint16_t *)&ram[addr]); return(*(uint16_t *)&ram[addr]); } @@ -533,14 +569,9 @@ ems_write_ramw(uint32_t addr, uint16_t val, void *priv) if (pg < 0) return; -#if 0 - pclog("ems_write_ramw addr=%05x ", addr); -#endif + DBGLOG(1, "ems_write_ramw addr=%05x ", addr); addr = sys->page_exec[pg] + (addr & 0x3fff); - -#if 0 - pclog("-> %06x val=%04x\n", addr, val); -#endif + DBGLOG(1, "-> %06x val=%04x\n", addr, val); if (*(uint16_t *)&ram[addr] != val) nvr_dosave = 1; @@ -616,11 +647,11 @@ cfgsys_load(t1000_t *dev) memset(dev->cfgsys, 0x1a, dev->cfgsys_len); f = plat_fopen(nvr_path(dev->cfgsys_fn), L"rb"); if (f != NULL) { - pclog("NVR: loaded CONFIG.SYS from '%ls'\n", dev->cfgsys_fn); + INFO("NVR: loaded CONFIG.SYS from '%ls'\n", dev->cfgsys_fn); (void)fread(dev->cfgsys, dev->cfgsys_len, 1, f); fclose(f); - } - else pclog("NVR: initialized CONFIG.SYS for '%ls'\n", dev->cfgsys_fn); + } else + INFO("NVR: initialized CONFIG.SYS for '%ls'\n", dev->cfgsys_fn); } @@ -635,7 +666,7 @@ cfgsys_save(t1000_t *dev) f = plat_fopen(nvr_path(dev->cfgsys_fn), L"wb"); if (f != NULL) { - pclog("NVR: saved CONFIG.SYS to '%ls'\n", dev->cfgsys_fn); + INFO("NVR: saved CONFIG.SYS to '%ls'\n", dev->cfgsys_fn); (void)fwrite(dev->cfgsys, dev->cfgsys_len, 1, f); fclose(f); } @@ -699,11 +730,21 @@ write_ctl(uint16_t addr, uint8_t val, void *priv) if (sys->sys_ctl[3] == 0x5A) { t1000_video_options_set((val & 0x20) ? 1 : 0); t1000_display_set((val & 0x40) ? 0 : 1); - if (romset == ROM_T1200) + if (sys->is_t1200) t1200_turbo_set((val & 0x80) ? 1 : 0); } break; + /* + * It looks as if the T1200, like the T3100, can disable + * its builtin video chipset if it detects the presence of + * another video card. + */ + case 6: + if (sys->is_t1200) + t1000_video_enable(val & 0x01 ? 0 : 1); + break; + case 0x0f: /* EMS control */ switch (sys->sys_ctl[0x0e]) { case 0x50: @@ -793,7 +834,8 @@ t1000_write_nvram(uint16_t addr, uint8_t val, void *priv) * at -1. */ sys->nvr_active = val; - if (val == 0x80) sys->nvr_addr = -1; + if (val == 0x80) + sys->nvr_addr = -1; break; } } @@ -818,11 +860,11 @@ t1000_write_rom_ctl(uint16_t addr, uint8_t val, void *priv) if (sys->romdrive && (val & 0x80)) { /* Enable */ sys->rom_offset = ((val & 0x7f) * 0x10000) % T1000_ROMDOS_SIZE; - mem_mapping_set_addr(&sys->rom_mapping, 0xa0000, 0x10000); - mem_mapping_set_exec(&sys->rom_mapping, sys->romdrive + sys->rom_offset); - mem_mapping_enable(&sys->rom_mapping); + mem_map_set_addr(&sys->rom_mapping, 0xa0000, 0x10000); + mem_map_set_exec(&sys->rom_mapping, sys->romdrive + sys->rom_offset); + mem_map_enable(&sys->rom_mapping); } else { - mem_mapping_disable(&sys->rom_mapping); + mem_map_disable(&sys->rom_mapping); } } @@ -903,9 +945,6 @@ machine_xt_t1000_init(const machine_t *model, void *arg) t1000.turbo = 0xff; t1000.ems_port_index = 7; /* EMS disabled */ - /* Load the T1000 CGA Font ROM. */ - loadfont(L"machines/toshiba/t1000/t1000font.rom", 2); - /* * The ROM drive is optional. * @@ -916,33 +955,33 @@ machine_xt_t1000_init(const machine_t *model, void *arg) if (t1000.rom_dos) { f = plat_fopen(rom_path(T1000_ROMDOS_PATH), L"rb"); if (f != NULL) { - t1000.romdrive = malloc(T1000_ROMDOS_SIZE); + t1000.romdrive = (uint8_t *)mem_alloc(T1000_ROMDOS_SIZE); if (t1000.romdrive) { memset(t1000.romdrive, 0xff, T1000_ROMDOS_SIZE); fread(t1000.romdrive, T1000_ROMDOS_SIZE, 1, f); } fclose(f); } - mem_mapping_add(&t1000.rom_mapping, 0xa0000, 0x10000, - t1000_read_rom,t1000_read_romw,t1000_read_roml, - NULL,NULL,NULL, NULL, MEM_MAPPING_INTERNAL, &t1000); - mem_mapping_disable(&t1000.rom_mapping); + mem_map_add(&t1000.rom_mapping, 0xa0000, 0x10000, + t1000_read_rom,t1000_read_romw,t1000_read_roml, + NULL,NULL,NULL, NULL, MEM_MAPPING_INTERNAL, &t1000); + mem_map_disable(&t1000.rom_mapping); } /* Map the EMS page frame */ for (pg = 0; pg < 4; pg++) { - mem_mapping_add(&t1000.mapping[pg], 0xd0000 + (0x4000 * pg), 16384, - ems_read_ram,ems_read_ramw,ems_read_raml, - ems_write_ram,ems_write_ramw,ems_write_raml, - NULL, MEM_MAPPING_EXTERNAL, &t1000); + mem_map_add(&t1000.mapping[pg], 0xd0000 + (0x4000 * pg), 16384, + ems_read_ram,ems_read_ramw,ems_read_raml, + ems_write_ram,ems_write_ramw,ems_write_raml, + NULL, MEM_MAPPING_EXTERNAL, &t1000); /* Start them all off disabled */ - mem_mapping_disable(&t1000.mapping[pg]); + mem_map_disable(&t1000.mapping[pg]); } /* Non-volatile RAM for CONFIG.SYS */ t1000.cfgsys_len = 160; - t1000.cfgsys = (uint8_t *)malloc(t1000.cfgsys_len); + t1000.cfgsys = (uint8_t *)mem_alloc(t1000.cfgsys_len); io_sethandler(0xc0, 4, t1000_read_nvram,NULL,NULL, t1000_write_nvram,NULL,NULL, &t1000); @@ -961,17 +1000,22 @@ machine_xt_t1000_init(const machine_t *model, void *arg) pit_set_out_func(&pit, 1, pit_refresh_timer_xt); device_add(&keyboard_xt_device); - t1000.fdc = device_add(&fdc_xt_device); + t1000.fdc = (fdc_t *)device_add(&fdc_xt_device); nmi_init(); tc8521_init(&t1000.nvr, model->nvrsz); - device_add(&t1000_video_device); + if (video_card == VID_INTERNAL) { + /* Load the T1000 CGA Font ROM. */ + video_load_font(L"machines/toshiba/t1000/t1000font.rom", 2); + + device_add(&t1000_video_device); + } } -static -uint8_t t1200_nvram_read(uint32_t addr, void *priv) +static uint8_t +t1200_nvram_read(uint32_t addr, void *priv) { t1000_t *sys = (t1000_t *)priv; @@ -980,14 +1024,14 @@ uint8_t t1200_nvram_read(uint32_t addr, void *priv) static void -t1200_nvram_write(uint32_t addr, uint8_t value, void *priv) +t1200_nvram_write(uint32_t addr, uint8_t val, void *priv) { t1000_t *sys = (t1000_t *)priv; - if (sys->cfgsys[addr & 0x7ff] != value) + if (sys->cfgsys[addr & 0x7ff] != val) nvr_dosave = 1; - sys->cfgsys[addr & 0x7ff] = value; + sys->cfgsys[addr & 0x7ff] = val; } @@ -998,20 +1042,18 @@ machine_xt_t1200_init(const machine_t *model, void *arg) memset(&t1000, 0x00, sizeof(t1000)); t1000.ems_port_index = 7; /* EMS disabled */ - - /* Load the T1200 CGA Font ROM. */ - loadfont(L"machines/toshiba/t1200/t1000font.bin", 2); + t1000.is_t1200 = 1; /* Map the EMS page frame */ for (pg = 0; pg < 4; pg++) { - mem_mapping_add(&t1000.mapping[pg], - 0xd0000 + (0x4000 * pg), 16384, - ems_read_ram,ems_read_ramw,ems_read_raml, - ems_write_ram,ems_write_ramw,ems_write_raml, - NULL, MEM_MAPPING_EXTERNAL, &t1000); + mem_map_add(&t1000.mapping[pg], + 0xd0000 + (0x4000 * pg), 16384, + ems_read_ram,ems_read_ramw,ems_read_raml, + ems_write_ram,ems_write_ramw,ems_write_raml, + NULL, MEM_MAPPING_EXTERNAL, &t1000); /* Start them all off disabled */ - mem_mapping_disable(&t1000.mapping[pg]); + mem_map_disable(&t1000.mapping[pg]); } /* System control functions, and add-on memory board */ @@ -1022,22 +1064,30 @@ machine_xt_t1200_init(const machine_t *model, void *arg) /* Non-volatile RAM for CONFIG.SYS */ t1000.cfgsys_len = 2048; - t1000.cfgsys = (uint8_t *)malloc(t1000.cfgsys_len); - mem_mapping_add(&t1000.nvr_mapping, - 0x000f0000, t1000.cfgsys_len, - t1200_nvram_read,NULL,NULL, - t1200_nvram_write,NULL,NULL, - NULL, 0, &t1000); + t1000.cfgsys = (uint8_t *)mem_alloc(t1000.cfgsys_len); + mem_map_add(&t1000.nvr_mapping, + 0x000f0000, t1000.cfgsys_len, + t1200_nvram_read,NULL,NULL, + t1200_nvram_write,NULL,NULL, + NULL, 0, &t1000); cfgsys_load(&t1000); pit_set_out_func(&pit, 1, pit_refresh_timer_xt); device_add(&keyboard_xt_device); - t1000.fdc = device_add(&fdc_xt_toshiba_device); + t1000.fdc = (fdc_t *)device_add(&fdc_toshiba_device); nmi_init(); tc8521_init(&t1000.nvr, model->nvrsz); - device_add(&t1200_video_device); + if (video_card == VID_INTERNAL) { + /* Load the T1200 CGA Font ROM. */ + video_load_font(L"machines/toshiba/t1200/t1000font.bin", 2); + + device_add(&t1200_video_device); + } + + if (hdc_type == HDC_INTERNAL) + (void)device_add(&xta_t1200_device); } diff --git a/src/machines/m_xt_t1000.h b/src/machines/m_xt_t1000.h index 8fe2419..543a232 100644 --- a/src/machines/m_xt_t1000.h +++ b/src/machines/m_xt_t1000.h @@ -8,15 +8,11 @@ * * Definitions for the Toshiba T1000/T1200 machines. * - * Version: @(#)m_xt_t1000.h 1.0.4 2018/04/03 + * Version: @(#)m_xt_t1000.h 1.0.5 2018/09/09 * - * Authors: Fred N. van Kempen, - * Miran Grca, - * Sarah Walker, + * Author: Fred N. van Kempen, * * Copyright 2017,2018 Fred N. van Kempen. - * Copyright 2016-2018 Miran Grca. - * Copyright 2008-2018 Sarah Walker. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -47,6 +43,7 @@ extern const device_t t1200_video_device; extern void t1000_video_options_set(uint8_t options); +extern void t1000_video_enable(uint8_t enabled); extern void t1000_display_set(uint8_t internal); extern void t1000_syskey(uint8_t amask, uint8_t omask, uint8_t xmask); diff --git a/src/machines/m_xt_t1000_vid.c b/src/machines/m_xt_t1000_vid.c index ab7e1cb..871fef2 100644 --- a/src/machines/m_xt_t1000_vid.c +++ b/src/machines/m_xt_t1000_vid.c @@ -9,15 +9,15 @@ * Implementation of the Toshiba T1000 plasma display, which * has a fixed resolution of 640x200 pixels. * - * Version: @(#)m_xt_t1000_vid.c 1.0.6 2018/05/06 + * Version: @(#)m_xt_t1000_vid.c 1.0.7 2018/09/24 * * Authors: Fred N. van Kempen, * Miran Grca, - * Sarah Walker, + * John Elliott, * * Copyright 2018 Fred N. van Kempen. - * Copyright 2018 Miran Grca. - * Copyright 2018 Sarah Walker. + * Copyright 2017,2018 Miran Grca. + * Copyright 2017,2018 John Elliott. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -62,7 +62,7 @@ static uint32_t blue, grey; static uint8_t boldcols[256]; /* Which attributes use the bold font */ static uint32_t blinkcols[256][2]; static uint32_t normcols[256][2]; -static uint8_t language; +static uint8_t langid; /* Video options set by the motherboard; they will be picked up by the card @@ -72,6 +72,7 @@ static uint8_t language; * Bit 0: Thin font */ static uint8_t st_video_options; +static uint8_t st_enabled = 1; static int8_t st_display_internal = -1; @@ -79,7 +80,13 @@ void t1000_video_options_set(uint8_t options) { st_video_options = options & 1; - st_video_options |= language; + st_video_options |= langid; +} + + +void t1000_video_enable(uint8_t enabled) +{ + st_enabled = enabled; } @@ -98,7 +105,7 @@ t1000_display_get(void) typedef struct t1000_t { - mem_mapping_t mapping; + mem_map_t mapping; cga_t cga; /* The CGA is used for the external * display; most of its registers are @@ -190,9 +197,7 @@ static void t1000_write(uint32_t addr, uint8_t val, void *p) { t1000_t *t1000 = (t1000_t *)p; - egawrites++; -// pclog("CGA_WRITE %04X %02X\n", addr, val); t1000->vram[addr & 0x3fff] = val; cycles -= 4; } @@ -202,10 +207,9 @@ static uint8_t t1000_read(uint32_t addr, void *p) { t1000_t *t1000 = (t1000_t *)p; - egareads++; + cycles -= 4; -// pclog("CGA_READ %04X\n", addr); return t1000->vram[addr & 0x3fff]; } @@ -478,12 +482,20 @@ t1000_poll(void *p) { t1000_t *t1000 = (t1000_t *)p; - if (t1000->video_options != st_video_options) + if (t1000->video_options != st_video_options || + t1000->enabled != st_enabled) { t1000->video_options = st_video_options; + t1000->enabled = st_enabled; /* Set the font used for the external display */ t1000->cga.fontbase = ((t1000->video_options & 3) * 256); + + /* Enable or disable internal chipset. */ + if (t1000->enabled) + mem_map_enable(&t1000->mapping); + else + mem_map_disable(&t1000->mapping); } /* Switch between internal plasma and external CRT display. */ if (st_display_internal != -1 && st_display_internal != t1000->internal) @@ -682,19 +694,19 @@ t1000_recalcattrs(t1000_t *t1000) static void * t1000_init(const device_t *info) { - t1000_t *t1000 = malloc(sizeof(t1000_t)); + t1000_t *t1000 = (t1000_t *)mem_alloc(sizeof(t1000_t)); memset(t1000, 0, sizeof(t1000_t)); cga_init(&t1000->cga); t1000->internal = 1; /* 16k video RAM */ - t1000->vram = malloc(0x4000); + t1000->vram = (uint8_t *)mem_alloc(0x4000); timer_add(t1000_poll, &t1000->cga.vidtime, TIMER_ALWAYS_ENABLED, t1000); /* Occupy memory between 0xB8000 and 0xBFFFF */ - mem_mapping_add(&t1000->mapping, 0xb8000, 0x8000, t1000_read, NULL, NULL, t1000_write, NULL, NULL, NULL, 0, t1000); + mem_map_add(&t1000->mapping, 0xb8000, 0x8000, t1000_read, NULL, NULL, t1000_write, NULL, NULL, NULL, 0, t1000); /* Respond to CGA I/O ports */ io_sethandler(0x03d0, 0x000c, t1000_in, NULL, NULL, t1000_out, NULL, NULL, t1000); @@ -707,7 +719,11 @@ t1000_init(const device_t *info) t1000->cga.vram = t1000->vram; t1000->enabled = 1; t1000->video_options = 0x01; - language = device_get_config_int("display_language") ? 2 : 0; + langid = device_get_config_int("display_language") ? 2 : 0; + + video_inform(VID_TYPE_CGA, + (const video_timings_t *)info->vid_timing); + return t1000; } @@ -731,30 +747,27 @@ t1000_speed_changed(void *p) } -static const device_config_t t1000_config[] = -{ +static const device_config_t t1000_config[] = { + { + "display_language","Language",CONFIG_SELECTION,"",0, { - .name = "display_language", - .description = "Language", - .type = CONFIG_SELECTION, - .selection = - { - { - .description = "USA", - .value = 0 - }, - { - .description = "Danish", - .value = 1 - } + { + "USA",0 }, - .default_int = 0 - }, - { - .type = -1 + { + "Danish",1 + }, + { + "" + } } + }, + { + "", "", -1 + } }; +static video_timings_t timing_t1000 = {VID_ISA, 8,16,32, 8,16,32}; const device_t t1000_video_device = { "Toshiba T1000 Video", @@ -763,7 +776,7 @@ const device_t t1000_video_device = { NULL, t1000_speed_changed, NULL, - NULL, + &timing_t1000, t1000_config }; @@ -774,6 +787,6 @@ const device_t t1200_video_device = { NULL, t1000_speed_changed, NULL, - NULL, + &timing_t1000, t1000_config }; diff --git a/src/machines/m_xt_xi8088.c b/src/machines/m_xt_xi8088.c index 385030a..a969f40 100644 --- a/src/machines/m_xt_xi8088.c +++ b/src/machines/m_xt_xi8088.c @@ -8,7 +8,7 @@ * * Implementation of the Xi8088 open-source machine. * - * Version: @(#)m_xt_xi8088.c 1.0.10 2018/05/06 + * Version: @(#)m_xt_xi8088.c 1.0.11 2018/09/19 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -79,17 +79,19 @@ xi8088_turbo_get(void) void xi8088_turbo_set(uint8_t value) { + int c; + if (! xi8088.turbo_setting) return; xi8088.turbo = value; if (! value) { - pclog("Xi8088 turbo off\n"); - int c = cpu; + DEBUG("Xi8088 turbo off\n"); + c = cpu; cpu = 0; /* 8088/4.77 */ cpu_set(); cpu = c; } else { - pclog("Xi8088 turbo on\n"); + DEBUG("Xi8088 turbo on\n"); cpu_set(); } } @@ -109,28 +111,24 @@ xi8088_bios_128kb(void) } -static const device_config_t xi8088_config[] = -{ +static const device_config_t xi8088_config[] = { + { + "turbo_setting","Turbo",CONFIG_SELECTION,"",0, { - .name = "turbo_setting", - .description = "Turbo", - .type = CONFIG_SELECTION, - .selection = { - { - .description = "Always at selected speed", - .value = 0 - }, - { - .description = "Hotkeys (starts off)", - .value = 1 - } + "Always at selected speed",0 }, - .default_int = 0 - }, - { - .type = -1 + { + "Hotkeys (starts off)",1 + }, + { + "" + } } + }, + { + "","",-1 + } }; @@ -138,10 +136,7 @@ const device_t m_xi8088_device = { "Xi8088", 0, 0, NULL, NULL, NULL, - NULL, - NULL, - NULL, - NULL, + NULL, NULL, NULL, NULL, xi8088_config }; @@ -157,6 +152,9 @@ machine_xt_xi8088_init(const machine_t *model, void *arg) else xi8088_bios_128kb_set(1); + if (xi8088_bios_128kb()) + mem_add_upper_bios(); + /* * Get the selected Turbo Speed setting. * Even though the bios by default turns the turbo off when @@ -177,7 +175,7 @@ machine_xt_xi8088_init(const machine_t *model, void *arg) device_add(&at_nvr_device); - device_add(&keyboard_ps2_device); + device_add(&keyboard_ps2_xi8088_device); device_add(&fdc_xt_device); } diff --git a/src/machines/machine.c b/src/machines/machine.c index 259d86a..dcf3216 100644 --- a/src/machines/machine.c +++ b/src/machines/machine.c @@ -8,7 +8,7 @@ * * Handling of the emulated machines. * - * Version: @(#)machine.c 1.0.15 2018/05/06 + * Version: @(#)machine.c 1.0.16 2018/09/22 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -41,6 +41,7 @@ #include #include #include "../emu.h" +#include "../cpu/cpu.h" #include "../mem.h" #include "../rom.h" #include "../device.h" @@ -50,29 +51,26 @@ #include "../devices/ports/game.h" #include "../devices/ports/serial.h" #include "../devices/ports/parallel.h" -#include "../devices/disk/hdc.h" -#include "../devices/disk/hdc_ide.h" +#include "../devices/video/video.h" #include "../plat.h" #include "machine.h" -int romset; -int machine; -int AT, PCI; -int romspresent[ROM_MAX]; +int AT, MCA, PCI; void -machine_init(void) +machine_reset(void) { wchar_t temp[1024]; romdef_t r; - pclog("Initializing as \"%s\"\n", machine_getname()); + INFO("Initializing as \"%s\"\n", machine_getname()); /* Set up the architecture flags. */ AT = IS_ARCH(machine, MACHINE_AT); PCI = IS_ARCH(machine, MACHINE_PCI); + MCA = IS_ARCH(machine, MACHINE_MCA); /* Reset memory and the MMU. */ mem_reset(); @@ -86,11 +84,24 @@ machine_init(void) /* Activate the ROM BIOS. */ mem_add_bios(); - /* Reset the IDE bus master pointers. */ - ide_set_bus_master(NULL, NULL, NULL); + /* + * If this is not a PCI or MCA machine, reset the video + * card before initializing the machine, to please the + * EuroPC and other systems that need this. + */ + if (!PCI && !MCA) + video_reset(); /* All good, boot the machine! */ machines[machine].init(&machines[machine], &r); + + /* + * If this is a PCI or MCA machine, reset the video + * card after initializing the machine, so the bus + * slots work correctly. + */ + if (PCI || MCA) + video_reset(); } @@ -103,6 +114,18 @@ machine_close(void) } +/* Return the (maximum) speed at which this machine will run. */ +uint32_t +machine_speed(void) +{ + uint32_t k; + + k = machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].rspeed; + + return(k); +} + + /* Check if the machine's ROM files are present. */ int machine_available(int id) @@ -120,32 +143,6 @@ machine_available(int id) } -/* Check for the availability of all the defined machines. */ -int -machine_detect(void) -{ - int c, i; - - pclog("Scanning for ROM images:\n"); - - c = 0; - for (i=0; i= CPU_286) + setrtcconst((float)machine_speed()); + else + setrtcconst(14318184.0); + if (game_enabled) device_add(&game_device); diff --git a/src/machines/machine.h b/src/machines/machine.h index de7d0df..d934221 100644 --- a/src/machines/machine.h +++ b/src/machines/machine.h @@ -8,7 +8,7 @@ * * Handling of the emulated machines. * - * Version: @(#)machine.h 1.0.23 2018/08/26 + * Version: @(#)machine.h 1.0.24 2018/09/21 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -40,139 +40,11 @@ # define EMU_MACHINE_H -/* FIXME: replace these with machine flags! */ -#define PCJR (romset==ROM_IBMPCJR) -#define AMIBIOS (romset==ROM_AMI386SX || \ - romset==ROM_AMI486 || \ - romset==ROM_WIN486) - - -/* FIXME: try to get rid of these... */ -enum { - ROM_IBMPC = 0, /* 301 keyboard error, 131 cassette (!!!) error */ - ROM_AMIXT, /* XT Clone with AMI BIOS */ - ROM_AWDXT, /* XT Clone with Award BIOS */ - ROM_DTKXT, - ROM_IBMXT, /* 301 keyboard error */ - ROM_GENXT, /* 'Generic XT BIOS' */ - ROM_JUKOPC, - ROM_PORTABLE, - ROM_PXXT, -#if defined(DEV_BRANCH) && defined(USE_LASERXT) - ROM_LTXT, - ROM_LXT3, -#endif - ROM_T1000, - ROM_T1200, - ROM_XI8088, - ROM_IBMPCJR, - ROM_TANDY, - ROM_TANDY1000HX, - ROM_EUROPC, - ROM_PC1512, - ROM_PC1640, - ROM_PC200, - ROM_PC2086, - ROM_PC3086, - ROM_OLIM24, - ROM_TANDY1000SL2, - ROM_T3100E, - - ROM_AMI286, - ROM_AWARD286, - ROM_CMDPC30, - ROM_PORTABLEII, -#if defined(DEV_BRANCH) && defined(USE_PORTABLE3) - ROM_PORTABLEIII, -#endif - ROM_GW286CT, - ROM_SUPER286TR, /* Hyundai Super-286TR/SCAT/Award */ - ROM_IBMAT, - ROM_IBMPS1_2011, - ROM_IBMPS2_M30_286, - ROM_IBMXT286, - ROM_SPC4200P, /* Samsung SPC-4200P/SCAT/Phoenix */ - ROM_SPC4216P, /* Samsung SPC-4216P/SCAT */ - - ROM_IBMPS2_M50, - - ROM_AMI386SX, - ROM_KMXC02, - ROM_MEGAPC, - ROM_AWARD386SX_OPTI495, -#if defined(DEV_BRANCH) && defined(USE_DESKPRO386) - ROM_DESKPRO_386, -#endif - ROM_DTK386, - ROM_IBMPS1_2121, - ROM_IBMPS1_2121_ISA,/* IBM PS/1 Model 2121 with ISA expansion bus */ -#if defined(DEV_BRANCH) && defined(USE_PORTABLE3) - ROM_PORTABLEIII386, -#endif - - ROM_IBMPS2_M55SX, - - ROM_AMI386DX_OPTI495, - ROM_MEGAPCDX, /* 386DX mdl - Note: documentation (in German) clearly says such a model exists */ - ROM_AWARD386DX_OPTI495, - ROM_MR386DX_OPTI495, - - ROM_IBMPS2_M80, - - ROM_AMI486, - ROM_WIN486, -#ifdef UNIMPLEMENTED_MACHINES - ROM_VLI486SV2G, /* ASUS VL/I-486SV2G/SiS 471/Award/SiS 85C471 */ /* 51 */ -#endif - ROM_AWARD486_OPTI495, - ROM_DTK486, /* DTK PKM-0038S E-2/SiS 471/Award/SiS 85C471 */ - - ROM_IBMPS1_2133, - - ROM_IBMPS2_M70_TYPE3, - ROM_IBMPS2_M70_TYPE4, - - ROM_R418, /* Rise Computer R418/SiS 496/497/Award/SMC FDC37C665 */ - - ROM_REVENGE, /* Intel Premiere/PCI I/430LX/AMI/SMC FDC37C665 */ - - ROM_PLATO, /* Intel Premiere/PCI II/430NX/AMI/SMC FDC37C665 */ - - ROM_P54TP4XE, /* ASUS P/I-P55TP4XE/430FX/Award/SMC FDC37C665 */ - ROM_ENDEAVOR, /* Intel Advanced_EV/430FX/AMI/NS PC87306 */ - ROM_ZAPPA, /* Intel Advanced_ZP/430FX/AMI/NS PC87306 */ -#ifdef UNIMPLEMENTED_MACHINES - ROM_POWERMATE_V, /* NEC PowerMate V/430FX/Phoenix/SMC FDC37C66 5*/ -#endif - ROM_MB500N, /* PC Partner MB500N/430FX/Award/SMC FDC37C665 */ - ROM_PRESIDENT, /* President Award 430FX PCI/430FX/Award/Unknown SIO */ - - ROM_THOR, /* Intel Advanced_ATX/430FX/AMI/NS PC87306 */ - ROM_MRTHOR, /* Intel Advanced_ATX/430FX/MR.BIOS/NS PC87306 */ - - ROM_ACERM3A, /* Acer M3A/430HX/Acer/SMC FDC37C932FR */ - ROM_ACERV35N, /* Acer V35N/430HX/Acer/SMC FDC37C932FR */ - ROM_AP53, /* AOpen AP53/430HX/AMI/SMC FDC37C665/669 */ - ROM_P55T2P4, /* ASUS P/I-P55T2P4/430HX/Award/Winbond W8387F*/ - ROM_P55T2S, /* ASUS P/I-P55T2S/430HX/AMI/NS PC87306 */ - - ROM_P55TVP4, /* ASUS P/I-P55TVP4/430HX/Award/Winbond W8387F*/ - ROM_430VX, /* Award 430VX PCI/430VX/Award/UMC UM8669F*/ - ROM_P55VA, /* Epox P55-VA/430VX/Award/SMC FDC37C932FR*/ - -#if defined(DEV_BRANCH) && defined(USE_I686) - ROM_440FX, /* Tyan Titan-Pro AT/440FX/Award BIOS/SMC FDC37C665 */ - ROM_S1668, /* Tyan Titan-Pro ATX/440FX/AMI/SMC FDC37C669 */ -#endif - - ROM_MAX -}; - - /* Machine feature flags. */ #define MACHINE_PC 0x000000 /* PC architecture */ #define MACHINE_AT 0x000001 /* PC/AT architecture */ #define MACHINE_PS2 0x000002 /* PS/2 architecture */ +#define MACHINE_NONMI 0x000004 /* sys does not have NMI's */ #define MACHINE_ISA 0x000010 /* sys has ISA bus */ #define MACHINE_CBUS 0x000020 /* sys has C-BUS bus */ #define MACHINE_EISA 0x000040 /* sys has EISA bus */ @@ -180,9 +52,9 @@ enum { #define MACHINE_MCA 0x000100 /* sys has MCA bus */ #define MACHINE_PCI 0x000200 /* sys has PCI bus */ #define MACHINE_AGP 0x000400 /* sys has AGP bus */ -#define MACHINE_HDC 0x011000 /* sys has int HDC */ -#define MACHINE_HDC_PS2 0x022000 /* sys has int PS/2 HDC */ -#define MACHINE_MOUSE 0x044000 /* sys has int mouse */ +#define MACHINE_HDC 0x010000 /* sys has int HDC */ +#define MACHINE_HDC_PS2 0x020000 /* sys has int PS/2 HDC */ +#define MACHINE_MOUSE 0x040000 /* sys has int mouse */ #define MACHINE_SOUND 0x080000 /* sys has int sound */ #define MACHINE_VIDEO 0x100000 /* sys has int video */ @@ -191,7 +63,6 @@ enum { typedef struct _machine_ { const char *name; - int id; const char *internal_name; const wchar_t *bios_path; struct { @@ -204,7 +75,8 @@ typedef struct _machine_ { } cpu[5]; int fixed_vidcard; /* FIXME: change to "fixed_flags" */ int flags; - int min_ram, max_ram; + uint32_t min_ram, + max_ram; int ram_granularity; int nvrsz; void (*init)(const struct _machine_ *, void *); @@ -219,28 +91,22 @@ typedef struct _machine_ { /* Global variables. */ extern const machine_t machines[]; -extern int machine; -extern int romset; extern int AT, PCI; -extern int romspresent[ROM_MAX]; /* Core functions. */ -extern int machine_count(void); -extern int machine_getromset(void); -extern int machine_getmachine(int romset); extern const char *machine_getname(void); +extern const char *machine_getname_ex(int id); extern const char *machine_get_internal_name(void); -extern int machine_get_machine_from_internal_name(const char *s); +extern const char *machine_get_internal_name_ex(int m); +extern int machine_get_from_internal_name(const char *s); extern int machine_available(int id); -extern int machine_detect(void); -extern void machine_init(void); +extern void machine_reset(void); extern void machine_close(void); +extern uint32_t machine_speed(void); #ifdef EMU_DEVICE_H extern const device_t *machine_getdevice(int machine); #endif -extern int machine_getromset_ex(int m); -extern const char *machine_get_internal_name_ex(int m); extern int machine_get_config_int(const char *s); extern const char *machine_get_config_string(const char *s); @@ -260,13 +126,11 @@ extern void machine_at_t3100e_init(const machine_t *, void *); extern void machine_at_p54tp4xe_init(const machine_t *, void *); extern void machine_at_endeavor_init(const machine_t *, void *); -#ifdef EMU_DEVICE_H -extern const device_t s3_phoenix_trio64_onboard_pci_device; -#endif extern void machine_at_zappa_init(const machine_t *, void *); extern void machine_at_mb500n_init(const machine_t *, void *); extern void machine_at_president_init(const machine_t *, void *); extern void machine_at_thor_init(const machine_t *, void *); +extern void machine_at_pb640_init(const machine_t *, void *); extern void machine_at_acerm3a_init(const machine_t *, void *); extern void machine_at_acerv35n_init(const machine_t *, void *); @@ -280,6 +144,7 @@ extern void machine_at_plato_init(const machine_t *, void *); extern void machine_at_p55tvp4_init(const machine_t *, void *); extern void machine_at_i430vx_init(const machine_t *, void *); extern void machine_at_p55va_init(const machine_t *, void *); +extern void machine_at_j656vxd_init(const machine_t *, void *); #if defined(DEV_BRANCH) && defined(USE_I686) extern void machine_at_i440fx_init(const machine_t *, void *); @@ -288,16 +153,27 @@ extern void machine_at_s1668_init(const machine_t *, void *); extern void machine_at_ali1429_init(const machine_t *, void *); extern void machine_at_cmdpc_init(const machine_t *, void *); -extern void machine_at_headland_init(const machine_t *, void *); +extern void machine_at_tg286m_init(const machine_t *, void *); +extern void machine_at_ama932j_init(const machine_t *, void *); extern void machine_at_neat_init(const machine_t *, void *); extern void machine_at_neat_ami_init(const machine_t *, void *); + extern void machine_at_opti495_init(const machine_t *, void *); extern void machine_at_opti495_ami_init(const machine_t *, void *); -extern void machine_at_scat_init(const machine_t *, void *); -extern void machine_at_scatsx_init(const machine_t *, void *); -extern void machine_at_compaq_init(const machine_t *, void *); + +extern void machine_at_scat_init(const machine_t*, void*); +extern void machine_at_scat_gw286ct_init(const machine_t*, void*); +extern void machine_at_scat_spc4216p_init(const machine_t*, void*); + +extern void machine_at_scatsx_init(const machine_t*, void*); + +extern void machine_at_compaq_p1_init(const machine_t*, void*); +extern void machine_at_compaq_p2_init(const machine_t*, void*); +extern void machine_at_compaq_p3_init(const machine_t*, void*); +extern void machine_at_compaq_p3_386_init(const machine_t*, void*); extern void machine_at_dtk486_init(const machine_t *, void *); + extern void machine_at_r418_init(const machine_t *, void *); extern void machine_at_wd76c10_init(const machine_t *, void *); @@ -324,7 +200,12 @@ extern void machine_ps2_model_70_type3_init(const machine_t *, void *); extern void machine_ps2_model_70_type4_init(const machine_t *, void *); extern void machine_ps2_model_80_init(const machine_t *, void *); -extern void machine_amstrad_init(const machine_t *, void *); +extern void machine_amstrad_1512_init(const machine_t *, void *); +extern void machine_amstrad_1640_init(const machine_t *, void *); +extern void machine_amstrad_200_init(const machine_t *, void *); +extern void machine_amstrad_2086_init(const machine_t *, void *); +extern void machine_amstrad_3086_init(const machine_t *, void *); +extern void machine_amstrad_mega_init(const machine_t *, void *); extern void machine_europc_init(const machine_t *, void *); #ifdef EMU_DEVICE_H @@ -335,6 +216,8 @@ extern void machine_olim24_init(const machine_t *, void *); extern void machine_olim24_video_init(void); extern void machine_tandy1k_init(const machine_t *, void *); +extern void machine_tandy1k_hx_init(const machine_t *, void *); +extern void machine_tandy1k_sl2_init(const machine_t *, void *); #ifdef EMU_DEVICE_H extern const device_t m_tandy1k_device; extern const device_t m_tandy1k_hx_device; @@ -342,19 +225,25 @@ extern const device_t m_tandy1k_sl2_device; #endif extern int tandy1k_eeprom_read(void); +extern void machine_pc_init(const machine_t *, void *); extern void machine_xt_init(const machine_t *, void *); #ifdef EMU_DEVICE_H +extern const device_t m_pc_device; extern const device_t m_xt_device; #endif -extern void machine_xt_compaq_init(const machine_t *, void *); +extern void machine_xt_compaq_p1_init(const machine_t *, void *); + #if defined(DEV_BRANCH) && defined(USE_LASERXT) extern void machine_xt_laserxt_init(const machine_t *, void *); +extern void machine_xt_lxt3_init(const machine_t *, void *); #endif extern void machine_xt_t1000_init(const machine_t *, void *); #ifdef EMU_DEVICE_H extern const device_t m_xt_t1000_device; +extern const device_t t1000_video_device; +extern const device_t t1200_video_device; #endif extern void machine_xt_t1200_init(const machine_t *, void *); extern void machine_xt_t1x00_close(void); diff --git a/src/machines/machine_table.c b/src/machines/machine_table.c index d3ac697..15dad50 100644 --- a/src/machines/machine_table.c +++ b/src/machines/machine_table.c @@ -8,9 +8,6 @@ * * Handling of the emulated machines. * - * NOTES: OpenAT wip for 286-class machine with open BIOS. - * PS2_M80-486 wip, pending receipt of TRM's for machine. - * * Version: @(#)machine_table.c 1.0.26 2018/09/28 * * Authors: Fred N. van Kempen, @@ -50,181 +47,152 @@ #include "../nvr.h" #include "../rom.h" #include "../device.h" +#include "../devices/video/video.h" #include "machine.h" const machine_t machines[] = { - { "[8088] IBM PC", ROM_IBMPC, "ibm_pc", L"ibm/pc", {{"", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 64, 640, 32, 0, machine_xt_init, &m_xt_device, NULL }, - { "[8088] IBM PCjr", ROM_IBMPCJR, "ibm_pcjr", L"ibm/pcjr", {{"", cpus_pcjr}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_VIDEO, 128, 640, 128, 0, machine_pcjr_init, &m_pcjr_device, NULL }, - { "[8088] IBM XT", ROM_IBMXT, "ibm_xt", L"ibm/xt", {{"", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 64, 640, 64, 0, machine_xt_init, &m_xt_device, NULL }, - { "[8088] OpenXT Generic Clone", ROM_GENXT, "open_xt", L"generic/open_xt", {{"", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 64, 640, 64, 0, machine_xt_init, &m_xt_device, NULL }, - { "[8088] AMI XT clone", ROM_AMIXT, "ami_xt", L"generic/ami/xt", {{"", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 64, 640, 64, 0, machine_xt_init, &m_xt_device, NULL }, - { "[8088] Award XT clone", ROM_AWDXT, "awd_xt", L"generic/award/xt", {{"", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 64, 640, 64, 0, machine_xt_init, &m_xt_device, NULL }, - { "[8088] Compaq Portable", ROM_PORTABLE, "compaq_portable", L"compaq/portable", {{"", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_VIDEO, 128, 640, 128, 0, machine_xt_compaq_init, NULL, NULL }, - { "[8088] DTK XT clone", ROM_DTKXT, "dtk_xt", L"dtk/xt", {{"", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 64, 640, 64, 0, machine_xt_init, &m_xt_device, NULL }, - { "[8088] Juko XT clone", ROM_JUKOPC, "juko_pc", L"juko/pc", {{"", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 64, 640, 64, 0, machine_xt_init, NULL, NULL }, - { "[8088] Phoenix XT clone", ROM_PXXT, "phoenix_xt", L"generic/phoenix/xt", {{"", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 64, 640, 64, 0, machine_xt_init, NULL, NULL }, - { "[8088] Schneider EuroPC", ROM_EUROPC, "schneider_europc", L"schneider/europc", {{"Siemens", cpus_europc}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_HDC | MACHINE_VIDEO | MACHINE_MOUSE, 512, 640, 128, 16, machine_europc_init, NULL, NULL }, - { "[8088] Tandy 1000", ROM_TANDY, "tandy_1000", L"tandy/t1000", {{"", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA, 128, 640, 128, 0, machine_tandy1k_init, &m_tandy1k_device, NULL }, - { "[8088] Tandy 1000 HX", ROM_TANDY1000HX, "tandy_1000hx", L"tandy/t1000hx", {{"", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA, 256, 640, 128, 0, machine_tandy1k_init, &m_tandy1k_hx_device, NULL }, - { "[8088] Toshiba 1000", ROM_T1000, "toshiba_t1000", L"toshiba/t1000", {{"", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_VIDEO, 512, 1280, 768, 64, machine_xt_t1000_init, &m_xt_t1000_device, machine_xt_t1x00_close }, + { "[8088] IBM PC", "ibm_pc", L"ibm/pc", {{"Intel", cpus_8088}, {"NEC", cpus_nec}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 64, 640, 32, 0, machine_pc_init, &m_pc_device, NULL }, + { "[8088] IBM PCjr", "ibm_pcjr", L"ibm/pcjr", {{"Intel", cpus_pcjr}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_VIDEO, 128, 640, 128, 0, machine_pcjr_init, &m_pcjr_device, NULL }, + { "[8088] IBM XT", "ibm_xt", L"ibm/xt", {{"Intel", cpus_8088}, {"NEC", cpus_nec}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 64, 640, 64, 0, machine_xt_init, &m_xt_device, NULL }, + { "[8088] OpenXT Generic Clone", "open_xt", L"generic/open_xt", {{"Intel", cpus_8088}, {"NEC", cpus_nec}, {"Intel", cpus_186}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 64, 640, 64, 0, machine_xt_init, &m_xt_device, NULL }, + { "[8088] AMI XT clone", "ami_xt", L"generic/ami/xt", {{"Intel", cpus_8088}, {"NEC", cpus_nec}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 64, 640, 64, 0, machine_xt_init, &m_xt_device, NULL }, + { "[8088] Award XT clone", "awd_xt", L"generic/award/xt", {{"Intel", cpus_8088}, {"NEC", cpus_nec}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 64, 640, 64, 0, machine_xt_init, &m_xt_device, NULL }, + { "[8088] Compaq Portable", "compaq_portable", L"compaq/portable", {{"Intel", cpus_8088}, {"NEC", cpus_nec}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_VIDEO, 128, 640, 128, 0, machine_xt_compaq_p1_init, NULL, NULL }, + { "[8088] DTK XT clone", "dtk_xt", L"dtk/xt", {{"Intel", cpus_8088}, {"NEC", cpus_nec}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 64, 640, 64, 0, machine_xt_init, &m_xt_device, NULL }, + { "[8088] Juko XT clone", "juko_pc", L"juko/pc", {{"Intel", cpus_8088}, {"NEC", cpus_nec}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 64, 640, 64, 0, machine_xt_init, NULL, NULL }, + { "[8088] Phoenix XT clone", "phoenix_xt", L"generic/phoenix/xt", {{"Intel", cpus_8088}, {"NEC", cpus_nec}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 64, 640, 64, 0, machine_xt_init, NULL, NULL }, + { "[8088] Schneider EuroPC", "schneider_europc", L"schneider/europc", {{"Siemens", cpus_europc}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_HDC | MACHINE_VIDEO | MACHINE_MOUSE, 512, 640, 128, 16, machine_europc_init, NULL, NULL }, + { "[8088] Tandy 1000", "tandy_1000", L"tandy/t1000", {{"Intel", cpus_8088}, {"NEC", cpus_nec}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_VIDEO, 128, 640, 128, 0, machine_tandy1k_init, &m_tandy1k_device, NULL }, + { "[8088] Tandy 1000 HX", "tandy_1000hx", L"tandy/t1000hx", {{"Intel", cpus_8088}, {"NEC", cpus_nec}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_VIDEO, 256, 640, 128, 0, machine_tandy1k_hx_init, &m_tandy1k_hx_device, NULL }, + { "[8088] Toshiba T1000", "toshiba_t1000", L"toshiba/t1000", {{"Intel", cpus_8088}, {"NEC", cpus_nec}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_VIDEO, 512, 1280, 768, 64, machine_xt_t1000_init, &m_xt_t1000_device, machine_xt_t1x00_close }, #if defined(DEV_BRANCH) && defined(USE_LASERXT) - { "[8088] VTech Laser Turbo XT", ROM_LTXT, "vtech_ltxt", L"vtech/ltxt", {{"", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 512, 512, 256, 0, machine_xt_laserxt_init, NULL, NULL }, + { "[8088] VTech Laser Turbo XT", "vtech_ltxt", L"vtech/ltxt", {{"Intel", cpus_8088}, {"NEC", cpus_nec}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 512, 512, 256, 0, machine_xt_laserxt_init, NULL, NULL }, #endif - { "[8088] Xi8088", ROM_XI8088, "malinov_xi8088", L"malinov/xi8088", {{"", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA /*| MACDHINE_AT*/ | MACHINE_PS2, 64, 1024, 128, 128, machine_xt_xi8088_init, NULL, NULL }, + { "[8088] Xi8088", "malinov_xi8088", L"malinov/xi8088", {{"Intel", cpus_8088}, {"NEC", cpus_nec}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA /*| MACDHINE_AT*/ | MACHINE_PS2, 64, 1024, 128, 128, machine_xt_xi8088_init, NULL, NULL }, - { "[8086] Amstrad PC1512", ROM_PC1512, "amstrad_pc1512", L"amstrad/pc1512", {{"", cpus_pc1512}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_VIDEO | MACHINE_MOUSE, 512, 640, 128, 64, machine_amstrad_init, NULL, NULL }, - { "[8086] Amstrad PC1640", ROM_PC1640, "amstrad_pc1640", L"amstrad/pc1640", {{"", cpus_8086}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_VIDEO | MACHINE_MOUSE, 640, 640, 0, 64, machine_amstrad_init, NULL, NULL }, - { "[8086] Amstrad PC2086", ROM_PC2086, "amstrad_pc2086", L"amstrad/pc2086", {{"", cpus_8086}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_VIDEO | MACHINE_MOUSE, 640, 640, 0, 64, machine_amstrad_init, NULL, NULL }, - { "[8086] Amstrad PC3086", ROM_PC3086, "amstrad_pc3086", L"amstrad/pc3086", {{"", cpus_8086}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_VIDEO | MACHINE_MOUSE, 640, 640, 0, 64, machine_amstrad_init, NULL, NULL }, - { "[8086] Amstrad PC20(0)", ROM_PC200, "amstrad_pc200", L"amstrad/pc200", {{"", cpus_8086}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_VIDEO | MACHINE_MOUSE, 512, 640, 128, 64, machine_amstrad_init, NULL, NULL }, - { "[8086] Olivetti M24", ROM_OLIM24, "olivetti_m24", L"olivetti/m24", {{"", cpus_8086}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_VIDEO | MACHINE_MOUSE, 128, 640, 128, 0, machine_olim24_init, NULL, NULL }, - { "[8086] Tandy 1000 SL/2", ROM_TANDY1000SL2, "tandy_1000sl2", L"tandy/t1000sl2", {{"", cpus_8086}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA, 512, 768, 128, 0, machine_tandy1k_init, &m_tandy1k_sl2_device, NULL }, - { "[8086] Toshiba 1200", ROM_T1200, "toshiba_t1200", L"toshiba/t1200", {{"", cpus_8086}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_VIDEO, 1024, 2048,1024, 64, machine_xt_t1200_init, NULL, machine_xt_t1x00_close }, + { "[8086] Amstrad PC1512", "amstrad_pc1512", L"amstrad/pc1512", {{"Intel", cpus_pc1512}, {"NEC", cpus_nec}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_VIDEO | MACHINE_MOUSE, 512, 640, 128, 64, machine_amstrad_1512_init, NULL, NULL }, + { "[8086] Amstrad PC1640", "amstrad_pc1640", L"amstrad/pc1640", {{"Intel", cpus_8086}, {"NEC", cpus_nec}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_VIDEO | MACHINE_MOUSE, 640, 640, 0, 64, machine_amstrad_1640_init, NULL, NULL }, + { "[8086] Amstrad PC2086", "amstrad_pc2086", L"amstrad/pc2086", {{"Intel", cpus_8086}, {"NEC", cpus_nec}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_VIDEO | MACHINE_MOUSE, 640, 640, 0, 64, machine_amstrad_2086_init, NULL, NULL }, + { "[8086] Amstrad PC3086", "amstrad_pc3086", L"amstrad/pc3086", {{"Intel", cpus_8086}, {"NEC", cpus_nec}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_VIDEO | MACHINE_MOUSE, 640, 640, 0, 64, machine_amstrad_3086_init, NULL, NULL }, + { "[8086] Amstrad PC20(0)", "amstrad_pc200", L"amstrad/pc200", {{"Intel", cpus_8086}, {"NEC", cpus_nec}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_VIDEO | MACHINE_MOUSE, 512, 640, 128, 64, machine_amstrad_200_init, NULL, NULL }, + { "[8086] Olivetti M24", "olivetti_m24", L"olivetti/m24", {{"Intel", cpus_8086}, {"NEC", cpus_nec}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_VIDEO | MACHINE_MOUSE, 128, 640, 128, 0, machine_olim24_init, NULL, NULL }, + { "[8086] Tandy 1000 SL/2", "tandy_1000sl2", L"tandy/t1000sl2", {{"Intel", cpus_8086}, {"NEC", cpus_nec}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA, 512, 768, 128, 0, machine_tandy1k_sl2_init, &m_tandy1k_sl2_device, NULL }, + { "[8086] Toshiba T1200", "toshiba_t1200", L"toshiba/t1200", {{"Intel", cpus_8086}, {"NEC", cpus_nec}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_VIDEO | MACHINE_HDC, 1024, 2048,1024, 64, machine_xt_t1200_init, &t1200_video_device, machine_xt_t1x00_close }, #if defined(DEV_BRANCH) && defined(USE_LASERXT) - { "[8086] VTech Laser XT3", ROM_LXT3, "vtech_lxt3", L"vtech/lxt3", {{"", cpus_8086}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 256, 512, 256, 0, machine_xt_laserxt_init, NULL, NULL }, + { "[8086] VTech Laser XT3", "vtech_lxt3", L"vtech/lxt3", {{"Intel", cpus_8086}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA, 256, 512, 256, 0, machine_xt_lxt3_init, NULL, NULL }, #endif - { "[286 ISA] AMI 286 clone", ROM_AMI286, "ami_286", L"generic/ami/286", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT, 512, 8192, 128, 128, machine_at_neat_ami_init, NULL, NULL }, - { "[286 ISA] Award 286 clone", ROM_AWARD286, "award_286", L"generic/award/286", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT, 512,16384, 128, 128, machine_at_scat_init, NULL, NULL }, - { "[286 ISA] Commodore PC 30 III", ROM_CMDPC30, "commodore_pc30", L"commodore/pc30", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT, 640,16384, 128, 128, machine_at_cmdpc_init, NULL, NULL }, - { "[286 ISA] Compaq Portable II", ROM_PORTABLEII, "compaq_portable2", L"compaq/portable2", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT, 640,16384, 128, 128, machine_at_compaq_init, NULL, NULL }, + { "[286 ISA] AMI 286 clone", "ami_286", L"generic/ami/286", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT, 512, 8192, 128, 128, machine_at_neat_ami_init, NULL, NULL }, + { "[286 ISA] Award 286 clone", "award_286", L"generic/award/286", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT, 512,16384, 128, 128, machine_at_scat_init, NULL, NULL }, + { "[286 ISA] Commodore PC 30 III", "commodore_pc30", L"commodore/pc30", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT, 640,16384, 128, 128, machine_at_cmdpc_init, NULL, NULL }, + { "[286 ISA] Compaq Portable II", "compaq_portable2", L"compaq/portable2", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT, 640,16384, 128, 128, machine_at_compaq_p2_init, NULL, NULL }, #if defined(DEV_BRANCH) && defined(USE_PORTABLE3) - { "[286 ISA] Compaq Portable III", ROM_PORTABLEIII, "compaq_portable3", L"compaq/portable3", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_AT | MACHINE_VIDEO, 640,16384, 128, 128, machine_at_compaq_init, NULL, NULL }, + { "[286 ISA] Compaq Portable III", "compaq_portable3", L"compaq/portable3", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_AT | MACHINE_VIDEO, 640,16384, 128, 128, machine_at_compaq_p3_init, NULL, NULL }, #endif - { "[286 ISA] GW-286CT GEAR", ROM_GW286CT, "gw286ct", L"unknown/gw286ct", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT, 512,16384, 128, 128, machine_at_scat_init, NULL, NULL }, - { "[286 ISA] Hyundai Super-286TR", ROM_SUPER286TR, "hyundai_super286tr", L"hyundai/super286tr", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT, 512,16384, 128, 128, machine_at_scat_init, NULL, NULL }, - { "[286 ISA] IBM AT", ROM_IBMAT, "ibm_at", L"ibm/at", {{"", cpus_ibmat}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT, 256,15872, 128, 64, machine_at_ibm_init, NULL, NULL }, - { "[286 ISA] IBM PS/1 model 2011", ROM_IBMPS1_2011, "ibm_ps1_2011", L"ibm/ps1_2011", {{"", cpus_ps1_m2011}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_VIDEO | MACHINE_HDC, 512, 6144, 512, 64, machine_ps1_m2011_init, &m_ps1_device, NULL }, - { "[286 ISA] IBM PS/2 model 30-286", ROM_IBMPS2_M30_286, "ibm_ps2_m30_286", L"ibm/ps2_m30_286", {{"", cpus_ps2_m30_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC_PS2, 1, 16, 1, 64, machine_ps2_m30_286_init, NULL, NULL }, - { "[286 ISA] IBM XT Model 286", ROM_IBMXT286, "ibm_xt286", L"ibm/xt286", {{"", cpus_ibmxt286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT, 256,15872, 128, 128, machine_at_ibm_init, NULL, NULL }, - { "[286 ISA] Samsung SPC-4200P", ROM_SPC4200P, "samsung_spc4200p", L"samsung/spc4200p", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT | MACHINE_PS2, 512, 2048, 128, 128, machine_at_scat_init, NULL, NULL }, - { "[286 ISA] Samsung SPC-4216P", ROM_SPC4216P, "samsung_spc4216p", L"samsung/spc4216p", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT | MACHINE_PS2, 1, 5, 1, 128, machine_at_scat_init, NULL, NULL }, - { "[286 ISA] Toshiba 3100e", ROM_T3100E, "toshiba_t3100e", L"toshiba/t3100e", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_AT | MACHINE_HDC, 1024, 5120, 256, 64, machine_at_t3100e_init, NULL, NULL }, + { "[286 ISA] GW-286CT GEAR", "gw286ct", L"unknown/gw286ct", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT, 512,16384, 128, 128, machine_at_scat_gw286ct_init, NULL, NULL }, + { "[286 ISA] Hyundai Super-286TR", "hyundai_super286tr", L"hyundai/super286tr", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT, 512,16384, 128, 128, machine_at_scat_init, NULL, NULL }, + { "[286 ISA] IBM AT", "ibm_at", L"ibm/at", {{"", cpus_ibmat}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT, 256,15872, 128, 64, machine_at_ibm_init, NULL, NULL }, + { "[286 ISA] IBM PS/1 model 2011", "ibm_ps1_2011", L"ibm/ps1_2011", {{"", cpus_ps1_m2011}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_VIDEO | MACHINE_HDC, 512, 6144, 512, 64, machine_ps1_m2011_init, &m_ps1_device, NULL }, + { "[286 ISA] IBM PS/2 model 30-286", "ibm_ps2_m30_286", L"ibm/ps2_m30_286", {{"", cpus_ps2_m30_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC_PS2, 1, 16, 1, 64, machine_ps2_m30_286_init, NULL, NULL }, + { "[286 ISA] IBM XT Model 286", "ibm_xt286", L"ibm/xt286", {{"", cpus_ibmxt286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT, 256,15872, 128, 128, machine_at_ibm_init, NULL, NULL }, + { "[286 ISA] Samsung SPC-4200P", "samsung_spc4200p", L"samsung/spc4200p", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT | MACHINE_PS2, 512, 2048, 128, 128, machine_at_scat_init, NULL, NULL }, + { "[286 ISA] Samsung SPC-4216P", "samsung_spc4216p", L"samsung/spc4216p", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT | MACHINE_PS2, 1, 5, 1, 128, machine_at_scat_spc4216p_init, NULL, NULL }, + { "[286 ISA] Toshiba T3100e", "toshiba_t3100e", L"toshiba/t3100e", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_AT | MACHINE_HDC, 1024, 5120, 256, 64, machine_at_t3100e_init, NULL, NULL }, + { "[286 ISA] Trigem 286M", "tg286m", L"trigem/tg286m", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT | MACHINE_VIDEO, 512, 8192, 128, 128, machine_at_tg286m_init, &et4000k_tg286_isa_device,NULL }, + + { "[286 MCA] IBM PS/2 model 50", "ibm_ps2_m50", L"ibm/ps2_m50", {{"", cpus_ps2_m30_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_MCA | MACHINE_AT | MACHINE_PS2 | MACHINE_VIDEO | MACHINE_HDC_PS2, 1, 10, 1, 64, machine_ps2_model_50_init, NULL, NULL }, - { "[286 MCA] IBM PS/2 model 50", ROM_IBMPS2_M50, "ibm_ps2_m50", L"ibm/ps2_m50", {{"", cpus_ps2_m30_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_MCA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC_PS2, 1, 10, 1, 64, machine_ps2_model_50_init, NULL, NULL }, + { "[386SX ISA] AMI 386SX clone", "ami_386", L"generic/ami/386", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT | MACHINE_HDC, 512,16384, 128, 128, machine_at_ama932j_init, NULL, NULL }, + { "[386SX ISA] Amstrad MegaPC", "amstrad_megapc", L"amstrad/megapc", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_VIDEO | MACHINE_HDC, 1, 16, 1, 128, machine_at_wd76c10_init, NULL, NULL }, + { "[386SX ISA] Award 386SX clone", "award_386sx", L"generic/award/opti495", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 16, 1, 128, machine_at_opti495_init, NULL, NULL }, + { "[386SX ISA] DTK 386SX clone", "dtk_386", L"dtk/386", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT | MACHINE_HDC, 512, 8192, 128, 128, machine_at_neat_init, NULL, NULL }, + { "[386SX ISA] IBM PS/1 model 2121", "ibm_ps1_2121", L"ibm/ps1_2121", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC | MACHINE_VIDEO, 1, 6, 1, 64, machine_ps1_m2121_init, &m_ps1_device, NULL }, + { "[386SX ISA] IBM PS/1 m.2121+ISA", "ibm_ps1_2121_isa", L"ibm/ps1_2121", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC | MACHINE_VIDEO, 1, 6, 1, 64, machine_ps1_m2121_init, &m_ps1_device, NULL }, - { "[386SX ISA] AMI 386SX clone", ROM_AMI386SX, "ami_386", L"generic/ami/386", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT | MACHINE_HDC, 512,16384, 128, 128, machine_at_headland_init, NULL, NULL }, - { "[386SX ISA] Amstrad MegaPC", ROM_MEGAPC, "amstrad_megapc", L"amstrad/megapc", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_VIDEO | MACHINE_HDC, 1, 16, 1, 128, machine_at_wd76c10_init, NULL, NULL }, - { "[386SX ISA] Award 386SX clone", ROM_AWARD386SX_OPTI495, "award_386sx", L"generic/award/opti495", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT | MACHINE_HDC, 1, 16, 1, 128, machine_at_opti495_init, NULL, NULL }, - { "[386SX ISA] DTK 386SX clone", ROM_DTK386, "dtk_386", L"dtk/386", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT | MACHINE_HDC, 512, 8192, 128, 128, machine_at_neat_init, NULL, NULL }, - { "[386SX ISA] IBM PS/1 model 2121", ROM_IBMPS1_2121, "ibm_ps1_2121", L"ibm/ps1_2121", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC | MACHINE_VIDEO, 1, 6, 1, 64, machine_ps1_m2121_init, &m_ps1_device, NULL }, - { "[386SX ISA] IBM PS/1 m.2121+ISA", ROM_IBMPS1_2121_ISA, "ibm_ps1_2121_isa", L"ibm/ps1_2121", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC | MACHINE_VIDEO, 1, 6, 1, 64, machine_ps1_m2121_init, &m_ps1_device, NULL }, + { "[386SX ISA] KMX-C-02", "kmxc02", L"unknown/kmxc02", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT, 512,16384, 512, 128, machine_at_scatsx_init, NULL, NULL }, + { "[386SX ISA] AMA-932J", "ama932j", L"unknown/ama932j", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT | MACHINE_HDC | MACHINE_VIDEO, 512, 8192, 128, 128, machine_at_ama932j_init, &oti067_onboard_device, NULL }, - { "[386SX MCA] IBM PS/2 model 55SX", ROM_IBMPS2_M55SX, "ibm_ps2_m55sx", L"ibm/ps2_m55sx", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, 1, MACHINE_MCA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC_PS2, 1, 8, 1, 64, machine_ps2_model_55sx_init, NULL, NULL }, - { "[386SX ISA] KMX-C-02", ROM_KMXC02, "kmxc02", L"unknown/kmxc02", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT, 512,16384, 512, 128, machine_at_scatsx_init, NULL, NULL }, + { "[386SX MCA] IBM PS/2 model 55SX", "ibm_ps2_m55sx", L"ibm/ps2_m55sx", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, 0, MACHINE_MCA | MACHINE_AT | MACHINE_PS2 | MACHINE_VIDEO | MACHINE_HDC_PS2, 1, 8, 1, 64, machine_ps2_model_55sx_init, NULL, NULL }, - { "[386DX ISA] AMI 386DX clone", ROM_AMI386DX_OPTI495, "ami_386dx", L"generic/ami/386dx", {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT | MACHINE_HDC, 1, 64, 1, 128, machine_at_opti495_ami_init, NULL, NULL }, - { "[386DX ISA] Amstrad MegaPC 386DX", ROM_MEGAPCDX, "amstrad_megapc_dx", L"amstrad/megapc", {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC | MACHINE_VIDEO, 1, 32, 1, 128, machine_at_wd76c10_init, NULL, NULL }, - { "[386DX ISA] Award 386DX clone", ROM_AWARD386DX_OPTI495, "award_386dx", L"generic/award/opti495", {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT | MACHINE_HDC, 1, 64, 1, 128, machine_at_opti495_init, NULL, NULL }, - { "[386DX ISA] MR 386DX clone", ROM_MR386DX_OPTI495, "microid_mr386dx", L"microid/mr386dx", {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT | MACHINE_HDC, 1, 64, 1, 128, machine_at_opti495_ami_init, NULL, NULL }, + { "[386DX ISA] AMI 386DX clone", "ami_386dx", L"generic/ami/386dx", {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT | MACHINE_HDC, 1, 64, 1, 128, machine_at_opti495_ami_init, NULL, NULL }, + { "[386DX ISA] Amstrad MegaPC 386DX", "amstrad_megapc_dx", L"amstrad/megapc", {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC | MACHINE_VIDEO, 1, 32, 1, 128, machine_at_wd76c10_init, NULL, NULL }, + { "[386DX ISA] Award 386DX clone", "award_386dx", L"generic/award/opti495", {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 64, 1, 128, machine_at_opti495_init, NULL, NULL }, + { "[386DX ISA] MR 386DX clone", "microid_mr386dx", L"microid/mr386dx", {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT | MACHINE_HDC, 1, 64, 1, 128, machine_at_opti495_ami_init, NULL, NULL }, #if defined(DEV_BRANCH) && defined(USE_PORTABLE3) - { "[386DX ISA] Compaq Portable III (386)", ROM_PORTABLEIII386, "portable3_386", L"compaq/deskpro386", {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_AT | MACHINE_HDC | MACHINE_VIDEO, 1, 14, 1, 128, machine_at_compaq_init, NULL, NULL }, + { "[386DX ISA] Compaq Portable III (386)", "portable3_386", L"compaq/deskpro386", {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_AT | MACHINE_HDC | MACHINE_VIDEO, 1, 14, 1, 128, machine_at_compaq_p3_386_init, NULL, NULL }, #endif - { "[386DX MCA] IBM PS/2 model 70 (type 3)", ROM_IBMPS2_M70_TYPE3, "ibm_ps2_m70_type3", L"ibm/ps2_m70_type3", {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"", NULL}, {"", NULL}}, 1, MACHINE_MCA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC_PS2, 2, 16, 2, 64, machine_ps2_model_70_type3_init, NULL, NULL }, - { "[386DX MCA] IBM PS/2 model 80", ROM_IBMPS2_M80, "ibm_ps2_m80", L"ibm/ps2_m80", {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"", NULL}, {"", NULL}}, 1, MACHINE_MCA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC_PS2, 1, 12, 1, 64, machine_ps2_model_80_init, NULL, NULL }, + { "[386DX MCA] IBM PS/2 model 70 (type 3)", "ibm_ps2_m70_type3", L"ibm/ps2_m70_type3", {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"", NULL}, {"", NULL}}, 0, MACHINE_MCA | MACHINE_AT | MACHINE_PS2 | MACHINE_VIDEO | MACHINE_HDC_PS2, 2, 16, 2, 64, machine_ps2_model_70_type3_init, NULL, NULL }, + { "[386DX MCA] IBM PS/2 model 80", "ibm_ps2_m80", L"ibm/ps2_m80", {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"", NULL}, {"", NULL}}, 0, MACHINE_MCA | MACHINE_AT | MACHINE_PS2 | MACHINE_VIDEO | MACHINE_HDC_PS2, 1, 12, 1, 64, machine_ps2_model_80_init, NULL, NULL }, - { "[486 ISA] AMI 486 clone", ROM_AMI486, "ami_486", L"generic/ami/486", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 64, 1, 128, machine_at_ali1429_init, NULL, NULL }, - { "[486 ISA] AMI WinBIOS 486", ROM_WIN486, "ami_win486", L"generic/ami/win486", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 64, 1, 128, machine_at_ali1429_init, NULL, NULL }, - { "[486 ISA] Award 486 clone", ROM_AWARD486_OPTI495, "award_486", L"generic/award/opti495", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 64, 1, 128, machine_at_opti495_init, NULL, NULL }, - { "[486 ISA] DTK PKM-0038S E-2", ROM_DTK486, "dtk_486", L"dtk/486", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 128, 1, 128, machine_at_dtk486_init, NULL, NULL }, - { "[486 ISA] IBM PS/1 model 2133", ROM_IBMPS1_2133, "ibm_ps1_2133", L"ibm/ps1_2133", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 1, 64, 1, 128, machine_ps1_m2133_init, NULL, NULL }, - { "[486 MCA] IBM PS/2 model 70 (type 4)", ROM_IBMPS2_M70_TYPE4, "ibm_ps2_m70_type4", L"ibm/ps2_m70_type4", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, 1, MACHINE_MCA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC_PS2, 2, 16, 2, 64, machine_ps2_model_70_type4_init, NULL, NULL }, + { "[486 ISA] AMI 486 clone", "ami_486", L"generic/ami/486", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 64, 1, 128, machine_at_ali1429_init, NULL, NULL }, + { "[486 ISA] AMI WinBIOS 486", "ami_win486", L"generic/ami/win486", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 64, 1, 128, machine_at_ali1429_init, NULL, NULL }, + { "[486 ISA] Award 486 clone", "award_486", L"generic/award/opti495", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 64, 1, 128, machine_at_opti495_init, NULL, NULL }, + { "[486 ISA] DTK PKM-0038S E-2", "dtk_486", L"dtk/486", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 128, 1, 128, machine_at_dtk486_init, NULL, NULL }, + { "[486 ISA] IBM PS/1 model 2133", "ibm_ps1_2133", L"ibm/ps1_2133", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC | MACHINE_NONMI, 1, 64, 1, 128, machine_ps1_m2133_init, NULL, NULL }, + { "[486 MCA] IBM PS/2 model 70 (type 4)", "ibm_ps2_m70_type4", L"ibm/ps2_m70_type4", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, 1, MACHINE_MCA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC_PS2, 2, 16, 2, 64, machine_ps2_model_70_type4_init, NULL, NULL }, - { "[486 PCI] Rise Computer R418", ROM_R418, "rise_r418", L"rise/r418", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 255, 1, 128, machine_at_r418_init, NULL, NULL }, + { "[486 PCI] Rise Computer R418", "rise_r418", L"rise/r418", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 255, 1, 128, machine_at_r418_init, NULL, NULL }, - { "[Socket 4 LX] Intel Premiere/PCI", ROM_REVENGE, "intel_revenge", L"intel/revenge", {{"Intel", cpus_Pentium5V}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 2, 128, 2, 128, machine_at_batman_init, NULL, NULL }, + { "[Socket 4 LX] Intel Premiere/PCI", "intel_revenge", L"intel/revenge", {{"Intel", cpus_Pentium5V}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 2, 128, 2, 128, machine_at_batman_init, NULL, NULL }, #if defined(DEV_BRANCH) && defined(USE_AMD_K) - { "[Socket 5 NX] Intel Premiere/PCI II", ROM_PLATO, "intel_plato", L"intel/plato", {{"Intel", cpus_PentiumS5}, {"IDT", cpus_WinChip}, {"AMD", cpus_K5}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 2, 128, 2, 128, machine_at_plato_init, NULL, NULL }, + { "[Socket 5 NX] Intel Premiere/PCI II", "intel_plato", L"intel/plato", {{"Intel", cpus_PentiumS5}, {"IDT", cpus_WinChip}, {"AMD", cpus_K5}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 2, 128, 2, 128, machine_at_plato_init, NULL, NULL }, - { "[Socket 5 FX] ASUS P/I-P54TP4XE", ROM_P54TP4XE, "asus_p54tp4xe", L"asus/p54tp4xe", {{"Intel", cpus_PentiumS5}, {"IDT", cpus_WinChip}, {"AMD", cpus_K5}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 8, 128, 8, 128, machine_at_p54tp4xe_init, NULL, NULL }, - { "[Socket 5 FX] Intel Advanced/EV", ROM_ENDEAVOR, "intel_endeavor", L"intel/endeavor", {{"Intel", cpus_PentiumS5}, {"IDT", cpus_WinChip}, {"AMD", cpus_K5}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC | MACHINE_VIDEO, 8, 128, 8, 128, machine_at_endeavor_init, &s3_phoenix_trio64_onboard_pci_device, NULL }, - { "[Socket 5 FX] Intel Advanced/ZP", ROM_ZAPPA, "intel_zappa", L"intel/zappa", {{"Intel", cpus_PentiumS5}, {"IDT", cpus_WinChip}, {"AMD", cpus_K5}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 128, machine_at_zappa_init, NULL, NULL }, - { "[Socket 5 FX] PC Partner MB500N", ROM_MB500N, "pcpartner_mb500n", L"pcpartner/mb500n", {{"Intel", cpus_PentiumS5}, {"IDT", cpus_WinChip}, {"AMD", cpus_K5}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 8, 128, 8, 128, machine_at_mb500n_init, NULL, NULL }, - { "[Socket 5 FX] President Award 430FX PCI",ROM_PRESIDENT, "president", L"president/president", {{"Intel", cpus_PentiumS5}, {"IDT", cpus_WinChip}, {"AMD", cpus_K5}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 8, 128, 8, 128, machine_at_president_init, NULL, NULL }, + { "[Socket 5 FX] ASUS P/I-P54TP4XE", "asus_p54tp4xe", L"asus/p54tp4xe", {{"Intel", cpus_PentiumS5}, {"IDT", cpus_WinChip}, {"AMD", cpus_K5}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 8, 128, 8, 128, machine_at_p54tp4xe_init, NULL, NULL }, + { "[Socket 5 FX] Intel Advanced/ZP", "intel_zappa", L"intel/zappa", {{"Intel", cpus_PentiumS5}, {"IDT", cpus_WinChip}, {"AMD", cpus_K5}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 128, machine_at_zappa_init, NULL, NULL }, + { "[Socket 5 FX] PC Partner MB500N", "pcpartner_mb500n", L"pcpartner/mb500n", {{"Intel", cpus_PentiumS5}, {"IDT", cpus_WinChip}, {"AMD", cpus_K5}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 8, 128, 8, 128, machine_at_mb500n_init, NULL, NULL }, + { "[Socket 5 FX] President Award 430FX PCI","president", L"president/president", {{"Intel", cpus_PentiumS5}, {"IDT", cpus_WinChip}, {"AMD", cpus_K5}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 8, 128, 8, 128, machine_at_president_init, NULL, NULL }, - { "[Socket 7 FX] Intel Advanced/ATX", ROM_THOR, "intel_thor", L"intel/thor", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"AMD", cpus_K56}, {"Cyrix", cpus_6x86}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 128, machine_at_thor_init, NULL, NULL }, - { "[Socket 7 FX] MR Intel Advanced/ATX", ROM_MRTHOR, "intel_mrthor", L"intel/mrthor", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"AMD", cpus_K56}, {"Cyrix", cpus_6x86}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 128, machine_at_thor_init, NULL, NULL }, + { "[Socket 7 FX] Intel Advanced/ATX", "intel_thor", L"intel/thor", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"AMD", cpus_K56}, {"Cyrix", cpus_6x86}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 128, machine_at_thor_init, NULL, NULL }, + { "[Socket 7 FX] MR Intel Advanced/ATX", "intel_mrthor", L"intel/mrthor", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"AMD", cpus_K56}, {"Cyrix", cpus_6x86}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 128, machine_at_thor_init, NULL, NULL }, + { "[Socket 7 FX] Intel Advanced/EV", "intel_endeavor", L"intel/endeavor", {{"Intel", cpus_PentiumS5}, {"IDT", cpus_WinChip}, {"AMD", cpus_K5}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC | MACHINE_VIDEO, 8, 128, 8, 128, machine_at_endeavor_init, &s3_phoenix_trio64_onboard_pci_device, NULL }, + { "[Socket 7 FX] Packard Bell PB640", "pbell_pb640", L"pbell/pb640", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"AMD", cpus_K56}, {"Cyrix", cpus_6x86}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC | MACHINE_VIDEO, 8, 128, 8, 128, machine_at_pb640_init, &gd5440_onboard_pci_device, NULL }, - { "[Socket 7 HX] Acer M3a", ROM_ACERM3A, "acer_m3a", L"acer/m3a", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"AMD", cpus_K56}, {"Cyrix", cpus_6x86}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 192, 8, 128, machine_at_acerm3a_init, NULL, NULL }, - { "[Socket 7 HX] Acer V35n", ROM_ACERV35N, "acer_v35n", L"acer/v35n", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"AMD", cpus_K56}, {"Cyrix", cpus_6x86}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 192, 8, 128, machine_at_acerv35n_init, NULL, NULL }, - { "[Socket 7 HX] AOpen AP53", ROM_AP53, "aopen_ap53", L"aopen/ap53", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"AMD", cpus_K56}, {"Cyrix", cpus_6x86}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 512, 8, 128, machine_at_ap53_init, NULL, NULL }, - { "[Socket 7 HX] ASUS P/I-P55T2P4", ROM_P55T2P4, "asus_p55t2p4", L"asus/p55t2p4", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"AMD", cpus_K56}, {"Cyrix", cpus_6x86}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 512, 8, 128, machine_at_p55t2p4_init, NULL, NULL }, - { "[Socket 7 HX] SuperMicro Super P55T2S", ROM_P55T2S, "supermicro_p55t2s", L"supermicro/p55t2s", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"AMD", cpus_K56}, {"Cyrix", cpus_6x86}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 768, 8, 128, machine_at_p55t2s_init, NULL, NULL }, + { "[Socket 7 HX] Acer M3a", "acer_m3a", L"acer/m3a", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"AMD", cpus_K56}, {"Cyrix", cpus_6x86}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 192, 8, 128, machine_at_acerm3a_init, NULL, NULL }, + { "[Socket 7 HX] Acer V35n", "acer_v35n", L"acer/v35n", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"AMD", cpus_K56}, {"Cyrix", cpus_6x86}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 192, 8, 128, machine_at_acerv35n_init, NULL, NULL }, + { "[Socket 7 HX] AOpen AP53", "aopen_ap53", L"aopen/ap53", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"AMD", cpus_K56}, {"Cyrix", cpus_6x86}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 512, 8, 128, machine_at_ap53_init, NULL, NULL }, + { "[Socket 7 HX] ASUS P/I-P55T2P4", "asus_p55t2p4", L"asus/p55t2p4", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"AMD", cpus_K56}, {"Cyrix", cpus_6x86}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 512, 8, 128, machine_at_p55t2p4_init, NULL, NULL }, + { "[Socket 7 HX] SuperMicro Super P55T2S", "supermicro_p55t2s", L"supermicro/p55t2s", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"AMD", cpus_K56}, {"Cyrix", cpus_6x86}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 768, 8, 128, machine_at_p55t2s_init, NULL, NULL }, - { "[Socket 7 VX] ASUS P/I-P55TVP4", ROM_P55TVP4, "asus_p55tvp4", L"asus/p55tvp4", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"AMD", cpus_K56}, {"Cyrix", cpus_6x86}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 128, machine_at_p55tvp4_init, NULL, NULL }, - { "[Socket 7 VX] Award 430VX PCI", ROM_430VX, "award_430vx", L"generic/award/430vx", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"AMD", cpus_K56}, {"Cyrix", cpus_6x86}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 128, machine_at_i430vx_init, NULL, NULL }, - { "[Socket 7 VX] Epox P55-VA", ROM_P55VA, "epox_p55va", L"epox/p55va", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"AMD", cpus_K56}, {"Cyrix", cpus_6x86}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 128, machine_at_p55va_init, NULL, NULL }, + { "[Socket 7 VX] ASUS P/I-P55TVP4", "asus_p55tvp4", L"asus/p55tvp4", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"AMD", cpus_K56}, {"Cyrix", cpus_6x86}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 128, machine_at_p55tvp4_init, NULL, NULL }, + { "[Socket 7 VX] Award 430VX PCI", "award_430vx", L"generic/award/430vx", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"AMD", cpus_K56}, {"Cyrix", cpus_6x86}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 128, machine_at_i430vx_init, NULL, NULL }, + { "[Socket 7 VX] Epox P55-VA", "epox_p55va", L"epox/p55va", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"AMD", cpus_K56}, {"Cyrix", cpus_6x86}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 128, machine_at_p55va_init, NULL, NULL }, + { "[Socket 7 VX] Jetway J656VXD", "jetway_j656vxd", L"jetway/j656vxd", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"AMD", cpus_K56}, {"Cyrix", cpus_6x86}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 128, machine_at_j656vxd_init, NULL, NULL }, #else - { "[Socket 5 NX] Intel Premiere/PCI II", ROM_PLATO, "intel_plato", L"intel/plato", {{"Intel", cpus_PentiumS5}, {"IDT", cpus_WinChip}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 2, 128, 2, 128, machine_at_plato_init, NULL, NULL }, + { "[Socket 5 NX] Intel Premiere/PCI II", "intel_plato", L"intel/plato", {{"Intel", cpus_PentiumS5}, {"IDT", cpus_WinChip}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 2, 128, 2, 128, machine_at_plato_init, NULL, NULL }, - { "[Socket 5 FX] ASUS P/I-P54TP4XE", ROM_P54TP4XE, "asus_p54tp4xe", L"asus/p54tp4xe", {{"Intel", cpus_PentiumS5}, {"IDT", cpus_WinChip}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 8, 128, 8, 128, machine_at_p54tp4xe_init, NULL, NULL }, - { "[Socket 5 FX] Intel Advanced/EV", ROM_ENDEAVOR, "intel_endeavor", L"intel/endeavor", {{"Intel", cpus_PentiumS5}, {"IDT", cpus_WinChip}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC | MACHINE_VIDEO, 8, 128, 8, 128, machine_at_endeavor_init, &s3_phoenix_trio64_onboard_pci_device, NULL }, - { "[Socket 5 FX] Intel Advanced/ZP", ROM_ZAPPA, "intel_zappa", L"intel/zappa", {{"Intel", cpus_PentiumS5}, {"IDT", cpus_WinChip}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 128, machine_at_zappa_init, NULL, NULL }, - { "[Socket 5 FX] PC Partner MB500N", ROM_MB500N, "pcpartner_mb500n", L"pcpartner/mb500n", {{"Intel", cpus_PentiumS5}, {"IDT", cpus_WinChip}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 8, 128, 8, 128, machine_at_mb500n_init, NULL, NULL }, - { "[Socket 5 FX] President Award 430FX PCI",ROM_PRESIDENT, "president", L"president/president", {{"Intel", cpus_PentiumS5}, {"IDT", cpus_WinChip}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 8, 128, 8, 128, machine_at_president_init, NULL, NULL }, + { "[Socket 5 FX] ASUS P/I-P54TP4XE", "asus_p54tp4xe", L"asus/p54tp4xe", {{"Intel", cpus_PentiumS5}, {"IDT", cpus_WinChip}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 8, 128, 8, 128, machine_at_p54tp4xe_init, NULL, NULL }, + { "[Socket 5 FX] Intel Advanced/ZP", "intel_zappa", L"intel/zappa", {{"Intel", cpus_PentiumS5}, {"IDT", cpus_WinChip}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 128, machine_at_zappa_init, NULL, NULL }, + { "[Socket 5 FX] PC Partner MB500N", "pcpartner_mb500n", L"pcpartner/mb500n", {{"Intel", cpus_PentiumS5}, {"IDT", cpus_WinChip}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 8, 128, 8, 128, machine_at_mb500n_init, NULL, NULL }, + { "[Socket 5 FX] President Award 430FX PCI","president", L"president/president", {{"Intel", cpus_PentiumS5}, {"IDT", cpus_WinChip}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 8, 128, 8, 128, machine_at_president_init, NULL, NULL }, - { "[Socket 7 FX] Intel Advanced/ATX", ROM_THOR, "intel_thor", L"intel/thor", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"Cyrix", cpus_6x86}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 128, machine_at_thor_init, NULL, NULL }, - { "[Socket 7 FX] MR Intel Advanced/ATX", ROM_MRTHOR, "intel_mrthor", L"intel/mrthor", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"Cyrix", cpus_6x86}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 128, machine_at_thor_init, NULL, NULL }, + { "[Socket 7 FX] Intel Advanced/ATX", "intel_thor", L"intel/thor", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"Cyrix", cpus_6x86}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 128, machine_at_thor_init, NULL, NULL }, + { "[Socket 7 FX] MR Intel Advanced/ATX", "intel_mrthor", L"intel/mrthor", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"Cyrix", cpus_6x86}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 128, machine_at_thor_init, NULL, NULL }, + { "[Socket 7 FX] Intel Advanced/EV", "intel_endeavor", L"intel/endeavor", {{"Intel", cpus_PentiumS5}, {"IDT", cpus_WinChip}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC | MACHINE_VIDEO, 8, 128, 8, 128, machine_at_endeavor_init, &s3_phoenix_trio64_onboard_pci_device, NULL }, + { "[Socket 7 FX] Packard Bell PB640", "pbell_pb640", L"pbell/pb640", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"AMD", cpus_K56}, {"Cyrix", cpus_6x86}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC | MACHINE_VIDEO, 8, 128, 8, 128, machine_at_pb640_init, &gd5440_onboard_pci_device, NULL }, - { "[Socket 7 HX] Acer M3a", ROM_ACERM3A, "acer_m3a", L"acer/m3a", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"Cyrix", cpus_6x86}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 192, 8, 128, machine_at_acerm3a_init, NULL, NULL }, - { "[Socket 7 HX] Acer V35n", ROM_ACERV35N, "acer_v35n", L"acer/v35n", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"Cyrix", cpus_6x86}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 192, 8, 128, machine_at_acerv35n_init, NULL, NULL }, - { "[Socket 7 HX] AOpen AP53", ROM_AP53, "aopen_ap53", L"aopen/ap53", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"Cyrix", cpus_6x86}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 512, 8, 128, machine_at_ap53_init, NULL, NULL }, - { "[Socket 7 HX] ASUS P/I-P55T2P4", ROM_P55T2P4, "asus_p55t2p4", L"asus/p55t2p4", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"Cyrix", cpus_6x86}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 512, 8, 128, machine_at_p55t2p4_init, NULL, NULL }, - { "[Socket 7 HX] SuperMicro Super P55T2S", ROM_P55T2S, "supermicro_p55t2s", L"supermicro/p55t2s", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"Cyrix", cpus_6x86}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 768, 8, 128, machine_at_p55t2s_init, NULL, NULL }, + { "[Socket 7 HX] Acer M3a", "acer_m3a", L"acer/m3a", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"Cyrix", cpus_6x86}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 192, 8, 128, machine_at_acerm3a_init, NULL, NULL }, + { "[Socket 7 HX] Acer V35n", "acer_v35n", L"acer/v35n", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"Cyrix", cpus_6x86}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 192, 8, 128, machine_at_acerv35n_init, NULL, NULL }, + { "[Socket 7 HX] AOpen AP53", "aopen_ap53", L"aopen/ap53", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"Cyrix", cpus_6x86}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 512, 8, 128, machine_at_ap53_init, NULL, NULL }, + { "[Socket 7 HX] ASUS P/I-P55T2P4", "asus_p55t2p4", L"asus/p55t2p4", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"Cyrix", cpus_6x86}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 512, 8, 128, machine_at_p55t2p4_init, NULL, NULL }, + { "[Socket 7 HX] SuperMicro Super P55T2S", "supermicro_p55t2s", L"supermicro/p55t2s", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"Cyrix", cpus_6x86}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 768, 8, 128, machine_at_p55t2s_init, NULL, NULL }, - { "[Socket 7 VX] ASUS P/I-P55TVP4", ROM_P55TVP4, "asus_p55tvp4", L"asus/p55tvp4", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"Cyrix", cpus_6x86}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 128, machine_at_p55tvp4_init, NULL, NULL }, - { "[Socket 7 VX] Award 430VX PCI", ROM_430VX, "award_430vx", L"generic/award/430vx", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"Cyrix", cpus_6x86}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 128, machine_at_i430vx_init, NULL, NULL }, - { "[Socket 7 VX] Epox P55-VA", ROM_P55VA, "epox_p55va", L"epox/p55va", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"Cyrix", cpus_6x86}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 128, machine_at_p55va_init, NULL, NULL }, + { "[Socket 7 VX] ASUS P/I-P55TVP4", "asus_p55tvp4", L"asus/p55tvp4", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"Cyrix", cpus_6x86}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 128, machine_at_p55tvp4_init, NULL, NULL }, + { "[Socket 7 VX] Award 430VX PCI", "award_430vx", L"generic/award/430vx", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"Cyrix", cpus_6x86}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 128, machine_at_i430vx_init, NULL, NULL }, + { "[Socket 7 VX] Epox P55-VA", "epox_p55va", L"epox/p55va", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"Cyrix", cpus_6x86}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 128, machine_at_p55va_init, NULL, NULL }, + { "[Socket 7 VX] Jetway J656VXD", "jetway_j656vxd", L"jetway/j656vxd", {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"AMD", cpus_K56}, {"Cyrix", cpus_6x86}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 128, machine_at_j656vxd_init, NULL, NULL }, #endif #if defined(DEV_BRANCH) && defined(USE_I686) - { "[Socket 8 FX] Tyan Titan-Pro AT", ROM_440FX, "tyan_440fx", L"tyan/440fx", {{"Intel", cpus_PentiumPro}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 1024, 8, 128, machine_at_i440fx_init, NULL, NULL }, - { "[Socket 8 FX] Tyan Titan-Pro ATX", ROM_S1668, "tyan_tpatx", L"tyan/tpatx", {{"Intel", cpus_PentiumPro}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 1024, 8, 128, machine_at_s1668_init, NULL, NULL }, + { "[Socket 8 FX] Tyan Titan-Pro AT", "tyan_440fx", L"tyan/440fx", {{"Intel", cpus_PentiumPro}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 1024, 8, 128, machine_at_i440fx_init, NULL, NULL }, + { "[Socket 8 FX] Tyan Titan-Pro ATX", "tyan_tpatx", L"tyan/tpatx", {{"Intel", cpus_PentiumPro}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 1024, 8, 128, machine_at_s1668_init, NULL, NULL }, #endif - { NULL, -1, NULL, NULL, {{"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } + { NULL, NULL, NULL, {{"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } }; -int -machine_count(void) -{ - return((sizeof(machines) / sizeof(machine_t)) - 1); -} - - -int -machine_getromset(void) -{ - return(machines[machine].id); -} - - -int -machine_getromset_ex(int m) -{ - return(machines[m].id); -} - - -int -machine_getmachine(int rs) -{ - int c = 0; - - while (machines[c].id != -1) { - if (machines[c].id == romset) - return(c); - c++; - } - - /* Not found. */ - return(-1); -} - - const char * machine_getname(void) { @@ -232,10 +200,10 @@ machine_getname(void) } -const device_t * -machine_getdevice(int m) +const char * +machine_getname_ex(int m) { - return(machines[m].device); + return(machines[m].name); } @@ -254,12 +222,12 @@ machine_get_internal_name_ex(int m) int -machine_get_machine_from_internal_name(const char *s) +machine_get_from_internal_name(const char *s) { int c = 0; - while (machines[c].id != -1) { - if (!strcmp(machines[c].internal_name, s)) + while (machines[c].internal_name != NULL) { + if (! strcmp(machines[c].internal_name, s)) return(c); c++; } @@ -269,6 +237,13 @@ machine_get_machine_from_internal_name(const char *s) } +const device_t * +machine_getdevice(int m) +{ + return(machines[m].device); +} + + int machine_get_config_int(const char *s) { diff --git a/src/mem.c b/src/mem.c index 2e14b36..7fc35ff 100644 --- a/src/mem.c +++ b/src/mem.c @@ -8,11 +8,7 @@ * * Memory handling and MMU. * - * NOTE: Experimenting with dynamically allocated lookup tables; - * the DYNAMIC_TABLES=1 enables this. Will eventually go - * away, either way... - * - * Version: @(#)mem.c 1.0.21 2018/09/19 + * Version: @(#)mem.c 1.0.21 2018/10/05 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -65,63 +61,54 @@ #endif -#define DYNAMIC_TABLES 0 /* experimental */ +mem_map_t base_mapping, + ram_low_mapping, /* 0..640K mapping */ + ram_mid_mapping, + ram_remapped_mapping, /* 640..1024K mapping */ + ram_high_mapping, /* 1024K+ mapping */ + bios_mapping[8], + bios_high_mapping[8]; +page_t *pages, /* RAM page table */ + **page_lookup; /* pagetable lookup */ +uint32_t pages_sz = 0; /* #pages in table */ -mem_mapping_t base_mapping, - ram_low_mapping, /* 0..640K mapping */ -#if 1 - ram_mid_mapping, -#endif - ram_remapped_mapping, /* 640..1024K mapping */ - ram_high_mapping, /* 1024K+ mapping */ - bios_mapping[8], - bios_high_mapping[8], - romext_mapping; +uint8_t *ram; /* the virtual RAM */ +uint32_t rammask; -page_t *pages, /* RAM page table */ - **page_lookup; /* pagetable lookup */ -uint32_t pages_sz = 0; /* #pages in table */ +uint8_t *rom; /* the virtual ROM */ +uint32_t biosmask; -uint8_t *ram; /* the virtual RAM */ -uint32_t rammask; +uint32_t pccache; +uint8_t *pccache2; -uint8_t *rom; /* the virtual ROM */ -uint8_t romext[32768]; -uint32_t biosmask; +int readlnext; +int readlookup[256], + readlookupp[256]; +uintptr_t *readlookup2; +int writelnext; +int writelookup[256], + writelookupp[256]; +uintptr_t *writelookup2; -uint32_t pccache; -uint8_t *pccache2; +uint32_t mem_logical_addr; -int readlnext; -int readlookup[256], - readlookupp[256]; -uintptr_t *readlookup2; -int writelnext; -int writelookup[256], - writelookupp[256]; -uintptr_t *writelookup2; +int shadowbios = 0, + shadowbios_write; +int pctrans = 0; +int cachesize = 256; -uint32_t mem_logical_addr; +uint32_t ram_mapped_addr[64]; -int shadowbios = 0, - shadowbios_write; -int readlnum = 0, - writelnum = 0; -int pctrans = 0; -int cachesize = 256; +uint32_t get_phys_virt, + get_phys_phys; -uint32_t ram_mapped_addr[64]; +int mem_a20_key = 0, + mem_a20_alt = 0, + mem_a20_state = 0; -uint32_t get_phys_virt, - get_phys_phys; - -int mem_a20_key = 0, - mem_a20_alt = 0, - mem_a20_state = 0; - -int mmuflush = 0; -int mmu_perm = 4; +int mmuflush = 0; +int mmu_perm = 4; /* FIXME: re-do this with a 'mem_ops' struct. */ @@ -134,8 +121,8 @@ static void (*_mem_write_l[0x40000])(uint32_t addr, uint32_t val, void *priv); static uint8_t *_mem_exec[0x40000]; static void *_mem_priv_r[0x40000]; static void *_mem_priv_w[0x40000]; -static mem_mapping_t *_mem_mapping_r[0x40000]; -static mem_mapping_t *_mem_mapping_w[0x40000]; +static mem_map_t *_mem_map_r[0x40000]; +static mem_map_t *_mem_map_w[0x40000]; static int _mem_state[0x40000]; static uint8_t ff_pccache[4] = { 0xff, 0xff, 0xff, 0xff }; @@ -148,17 +135,8 @@ resetreadlookup(void) { int c; - /* This is NULL after app startup, when mem_init() has not yet run. */ -#if DYNAMIC_TABLES -pclog("MEM: reset_lookup: pages=%08lx, lookup=%08lx, pages_sz=%i\n", pages, page_lookup, pages_sz); -#endif - /* Initialize the page lookup table. */ -#if DYNAMIC_TABLES - memset(page_lookup, 0x00, pages_sz*sizeof(page_t *)); -#else memset(page_lookup, 0x00, (1<<20)*sizeof(page_t *)); -#endif /* Initialize the tables for lower (<= 1024K) RAM. */ for (c = 0; c < 256; c++) { @@ -167,13 +145,8 @@ pclog("MEM: reset_lookup: pages=%08lx, lookup=%08lx, pages_sz=%i\n", pages, page } /* Initialize the tables for high (> 1024K) RAM. */ -#if DYNAMIC_TABLES - memset(readlookup2, 0xff, pages_sz*sizeof(uintptr_t)); - memset(writelookup2, 0xff, pages_sz*sizeof(uintptr_t)); -#else memset(readlookup2, 0xff, (1<<20)*sizeof(uintptr_t)); memset(writelookup2, 0xff, (1<<20)*sizeof(uintptr_t)); -#endif readlnext = 0; writelnext = 0; @@ -187,11 +160,11 @@ flushmmucache(void) int c; for (c = 0; c < 256; c++) { - if (readlookup[c] != 0xffffffff) { + if (readlookup[c] != (int)0xffffffff) { readlookup2[readlookup[c]] = -1; readlookup[c] = 0xffffffff; } - if (writelookup[c] != 0xffffffff) { + if (writelookup[c] != (int)0xffffffff) { page_lookup[writelookup[c]] = NULL; writelookup2[writelookup[c]] = -1; writelookup[c] = 0xffffffff; @@ -214,11 +187,11 @@ flushmmucache_nopc(void) int c; for (c = 0; c < 256; c++) { - if (readlookup[c] != 0xffffffff) { + if (readlookup[c] != (int)0xffffffff) { readlookup2[readlookup[c]] = -1; readlookup[c] = 0xffffffff; } - if (writelookup[c] != 0xffffffff) { + if (writelookup[c] != (int)0xffffffff) { page_lookup[writelookup[c]] = NULL; writelookup2[writelookup[c]] = -1; writelookup[c] = 0xffffffff; @@ -233,11 +206,11 @@ flushmmucache_cr3(void) int c; for (c = 0; c < 256; c++) { - if (readlookup[c] != 0xffffffff) { + if (readlookup[c] != (int)0xffffffff) { readlookup2[readlookup[c]] = -1; readlookup[c] = 0xffffffff; } - if (writelookup[c] != 0xffffffff) { + if (writelookup[c] != (int)0xffffffff) { page_lookup[writelookup[c]] = NULL; writelookup2[writelookup[c]] = -1; writelookup[c] = 0xffffffff; @@ -253,7 +226,7 @@ mem_flush_write_page(uint32_t addr, uint32_t virt) int c; for (c = 0; c < 256; c++) { - if (writelookup[c] != 0xffffffff) { + if (writelookup[c] != (int)0xffffffff) { uintptr_t target = (uintptr_t)&ram[(uintptr_t)(addr & ~0xfff) - (virt & ~0xfff)]; if (writelookup2[writelookup[c]] == target || page_lookup[writelookup[c]] == page_target) { @@ -397,9 +370,9 @@ addreadlookup(uint32_t virt, uint32_t phys) { if (virt == 0xffffffff) return; - if (readlookup2[virt>>12] != -1) return; + if (readlookup2[virt>>12] != (uintptr_t)-1) return; - if (readlookup[readlnext] != 0xffffffff) + if (readlookup[readlnext] != (int)0xffffffff) readlookup2[readlookup[readlnext]] = -1; readlookup2[virt>>12] = (uintptr_t)&ram[(uintptr_t)(phys & ~0xFFF) - (uintptr_t)(virt & ~0xfff)]; @@ -465,7 +438,7 @@ getpccache(uint32_t a) a &= rammask; if (_mem_exec[a >> 14]) { - if (_mem_mapping_r[a >> 14]->flags & MEM_MAPPING_ROM) + if (_mem_map_r[a >> 14]->flags & MEM_MAPPING_ROM) cpu_prefetch_cycles = cpu_rom_prefetch_cycles; else cpu_prefetch_cycles = cpu_mem_prefetch_cycles; @@ -473,7 +446,7 @@ getpccache(uint32_t a) return &_mem_exec[a >> 14][(uintptr_t)(a & 0x3000) - (uintptr_t)(a2 & ~0xfff)]; } - pclog("Bad getpccache %08X\n", a); + ERRLOG("Bad getpccache %08X\n", a); return (uint8_t *)&ff_pccache; } @@ -535,10 +508,10 @@ writemembl(uint32_t addr, uint8_t val) uint8_t readmemb386l(uint32_t seg, uint32_t addr) { - if (seg == -1) { + if (seg == (uint32_t)-1) { x86gpf("NULL segment", 0); - return -1; + return 0xff; } mem_logical_addr = addr = addr + seg; @@ -567,7 +540,7 @@ readmemb386l(uint32_t seg, uint32_t addr) void writememb386l(uint32_t seg, uint32_t addr, uint8_t val) { - if (seg == -1) { + if (seg == (uint32_t)-1) { x86gpf("NULL segment", 0); return; } @@ -603,9 +576,9 @@ readmemwl(uint32_t seg, uint32_t addr) { uint32_t addr2 = mem_logical_addr = seg + addr; - if (seg == -1) { + if (seg == (uint32_t)-1) { x86gpf("NULL segment", 0); - return -1; + return 0xffff; } if (addr2 & 1) { @@ -616,10 +589,10 @@ readmemwl(uint32_t seg, uint32_t addr) if (mmutranslate_read(addr2) == 0xffffffff) return 0xffff; if (mmutranslate_read(addr2+1) == 0xffffffff) return 0xffff; } - if (is386) return readmemb386l(seg,addr)|(readmemb386l(seg,addr+1)<<8); - else return readmembl(seg+addr)|(readmembl(seg+addr+1)<<8); + if (is386) return readmemb386l(seg,addr)|((uint16_t)(readmemb386l(seg,addr+1))<<8); + else return readmembl(seg+addr)|((uint16_t)(readmembl(seg+addr+1))<<8); } - else if (readlookup2[addr2 >> 12] != -1) + else if (readlookup2[addr2 >> 12] != (uintptr_t)-1) return *(uint16_t *)(readlookup2[addr2 >> 12] + addr2); } @@ -643,9 +616,11 @@ readmemwl(uint32_t seg, uint32_t addr) if (_mem_read_b[addr2 >> 14]) { if (AT) - return _mem_read_b[addr2 >> 14](addr2, _mem_priv_r[addr2 >> 14]) | (_mem_read_b[(addr2 + 1) >> 14](addr2 + 1, _mem_priv_r[addr2 >> 14]) << 8); + return _mem_read_b[addr2 >> 14](addr2, _mem_priv_r[addr2 >> 14]) | + ((uint16_t)(_mem_read_b[(addr2 + 1) >> 14](addr2 + 1, _mem_priv_r[addr2 >> 14])) << 8); else - return _mem_read_b[addr2 >> 14](addr2, _mem_priv_r[addr2 >> 14]) | (_mem_read_b[(seg + ((addr + 1) & 0xffff)) >> 14](seg + ((addr + 1) & 0xffff), _mem_priv_r[addr2 >> 14]) << 8); + return _mem_read_b[addr2 >> 14](addr2, _mem_priv_r[addr2 >> 14]) | + ((uint16_t)(_mem_read_b[(seg + ((addr + 1) & 0xffff)) >> 14](seg + ((addr + 1) & 0xffff), _mem_priv_r[addr2 >> 14])) << 8); } return 0xffff; @@ -657,7 +632,7 @@ writememwl(uint32_t seg, uint32_t addr, uint16_t val) { uint32_t addr2 = mem_logical_addr = seg + addr; - if (seg == -1) { + if (seg == (uint32_t)-1) { x86gpf("NULL segment", 0); return; } @@ -685,7 +660,7 @@ writememwl(uint32_t seg, uint32_t addr, uint16_t val) writemembl(seg+addr+1,(uint8_t)(val>>8)); } return; - } else if (writelookup2[addr2 >> 12] != -1) { + } else if (writelookup2[addr2 >> 12] != (uintptr_t)-1) { *(uint16_t *)(writelookup2[addr2 >> 12] + addr2) = val; return; } @@ -703,11 +678,6 @@ writememwl(uint32_t seg, uint32_t addr, uint16_t val) addr2 &= rammask; -#if 0 - if (addr2 >= 0xa0000 && addr2 < 0xc0000) - pclog("writememwl %08X %02X\n", addr2, val); -#endif - if (_mem_write_w[addr2 >> 14]) { _mem_write_w[addr2 >> 14](addr2, val, _mem_priv_w[addr2 >> 14]); return; @@ -726,7 +696,7 @@ readmemll(uint32_t seg, uint32_t addr) { uint32_t addr2 = mem_logical_addr = seg + addr; - if (seg == -1) { + if (seg == (uint32_t)-1) { x86gpf("NULL segment", 0); return -1; } @@ -747,7 +717,7 @@ readmemll(uint32_t seg, uint32_t addr) if (mmutranslate_read(addr2+3) == 0xffffffff) return 0xffffffff; } return readmemwl(seg,addr)|(readmemwl(seg,addr+2)<<16); - } else if (readlookup2[addr2 >> 12] != -1) + } else if (readlookup2[addr2 >> 12] != (uintptr_t)-1) return *(uint32_t *)(readlookup2[addr2 >> 12] + addr2); } @@ -763,10 +733,14 @@ readmemll(uint32_t seg, uint32_t addr) return _mem_read_l[addr2 >> 14](addr2, _mem_priv_r[addr2 >> 14]); if (_mem_read_w[addr2 >> 14]) - return _mem_read_w[addr2 >> 14](addr2, _mem_priv_r[addr2 >> 14]) | (_mem_read_w[addr2 >> 14](addr2 + 2, _mem_priv_r[addr2 >> 14]) << 16); + return _mem_read_w[addr2 >> 14](addr2, _mem_priv_r[addr2 >> 14]) | + ((uint32_t)(_mem_read_w[addr2 >> 14](addr2 + 2, _mem_priv_r[addr2 >> 14])) << 16); if (_mem_read_b[addr2 >> 14]) - return _mem_read_b[addr2 >> 14](addr2, _mem_priv_r[addr2 >> 14]) | (_mem_read_b[addr2 >> 14](addr2 + 1, _mem_priv_r[addr2 >> 14]) << 8) | (_mem_read_b[addr2 >> 14](addr2 + 2, _mem_priv_r[addr2 >> 14]) << 16) | (_mem_read_b[addr2 >> 14](addr2 + 3, _mem_priv_r[addr2 >> 14]) << 24); + return _mem_read_b[addr2 >> 14](addr2, _mem_priv_r[addr2 >> 14]) | + ((uint32_t)(_mem_read_b[addr2 >> 14](addr2 + 1, _mem_priv_r[addr2 >> 14])) << 8) | + ((uint32_t)(_mem_read_b[addr2 >> 14](addr2 + 2, _mem_priv_r[addr2 >> 14]) << 16)) | + ((uint32_t)(_mem_read_b[addr2 >> 14](addr2 + 3, _mem_priv_r[addr2 >> 14])) << 24); return 0xffffffff; } @@ -777,7 +751,7 @@ writememll(uint32_t seg, uint32_t addr, uint32_t val) { uint32_t addr2 = mem_logical_addr = seg + addr; - if (seg == -1) { + if (seg == (uint32_t)-1) { x86gpf("NULL segment", 0); return; } @@ -800,7 +774,7 @@ writememll(uint32_t seg, uint32_t addr, uint32_t val) writememwl(seg,addr,val); writememwl(seg,addr+2,val>>16); return; - } else if (writelookup2[addr2 >> 12] != -1) { + } else if (writelookup2[addr2 >> 12] != (uintptr_t)-1) { *(uint32_t *)(writelookup2[addr2 >> 12] + addr2) = val; return; } @@ -819,19 +793,19 @@ writememll(uint32_t seg, uint32_t addr, uint32_t val) addr2 &= rammask; if (_mem_write_l[addr2 >> 14]) { - _mem_write_l[addr2 >> 14](addr2, val, _mem_priv_w[addr2 >> 14]); + _mem_write_l[addr2 >> 14](addr2, val, _mem_priv_w[addr2 >> 14]); return; } if (_mem_write_w[addr2 >> 14]) { - _mem_write_w[addr2 >> 14](addr2, val, _mem_priv_w[addr2 >> 14]); - _mem_write_w[addr2 >> 14](addr2 + 2, val >> 16, _mem_priv_w[addr2 >> 14]); + _mem_write_w[addr2 >> 14](addr2, val, _mem_priv_w[addr2 >> 14]); + _mem_write_w[addr2 >> 14](addr2+2, val >> 16, _mem_priv_w[addr2 >> 14]); return; } if (_mem_write_b[addr2 >> 14]) { - _mem_write_b[addr2 >> 14](addr2, val, _mem_priv_w[addr2 >> 14]); - _mem_write_b[addr2 >> 14](addr2 + 1, val >> 8, _mem_priv_w[addr2 >> 14]); - _mem_write_b[addr2 >> 14](addr2 + 2, val >> 16, _mem_priv_w[addr2 >> 14]); - _mem_write_b[addr2 >> 14](addr2 + 3, val >> 24, _mem_priv_w[addr2 >> 14]); + _mem_write_b[addr2 >> 14](addr2, val, _mem_priv_w[addr2 >> 14]); + _mem_write_b[addr2 >> 14](addr2+1, val >> 8, _mem_priv_w[addr2 >> 14]); + _mem_write_b[addr2 >> 14](addr2+2, val >> 16, _mem_priv_w[addr2 >> 14]); + _mem_write_b[addr2 >> 14](addr2+3, val >> 24, _mem_priv_w[addr2 >> 14]); return; } } @@ -842,7 +816,7 @@ readmemql(uint32_t seg, uint32_t addr) { uint32_t addr2 = mem_logical_addr = seg + addr; - if (seg == -1) { + if (seg == (uint32_t)-1) { x86gpf("NULL segment", 0); return -1; } @@ -862,7 +836,7 @@ readmemql(uint32_t seg, uint32_t addr) if (mmutranslate_read(addr2+7) == 0xffffffff) return 0xffffffff; } return readmemll(seg,addr)|((uint64_t)readmemll(seg,addr+4)<<32); - } else if (readlookup2[addr2 >> 12] != -1) + } else if (readlookup2[addr2 >> 12] != (uintptr_t)-1) return *(uint64_t *)(readlookup2[addr2 >> 12] + addr2); } @@ -876,7 +850,7 @@ readmemql(uint32_t seg, uint32_t addr) if (_mem_read_l[addr2 >> 14]) return _mem_read_l[addr2 >> 14](addr2, _mem_priv_r[addr2 >> 14]) | - ((uint64_t)_mem_read_l[addr2 >> 14](addr2 + 4, _mem_priv_r[addr2 >> 14]) << 32); + ((uint64_t)_mem_read_l[addr2 >> 14](addr2 + 4, _mem_priv_r[addr2 >> 14]) << 32); return readmemll(seg,addr) | ((uint64_t)readmemll(seg,addr+4)<<32); } @@ -887,7 +861,7 @@ writememql(uint32_t seg, uint32_t addr, uint64_t val) { uint32_t addr2 = mem_logical_addr = seg + addr; - if (seg == -1) { + if (seg == (uint32_t)-1) { x86gpf("NULL segment", 0); return; } @@ -909,7 +883,7 @@ writememql(uint32_t seg, uint32_t addr, uint64_t val) writememll(seg, addr, (uint32_t)(val&0xffffffff)); writememll(seg, addr+4, (uint32_t)(val>>32)); return; - } else if (writelookup2[addr2 >> 12] != -1) { + } else if (writelookup2[addr2 >> 12] != (uintptr_t)-1) { *(uint64_t *)(writelookup2[addr2 >> 12] + addr2) = val; return; } @@ -973,10 +947,6 @@ mem_readb_phys(uint32_t addr) uint8_t mem_readb_phys_dma(uint32_t addr) { -#if 0 - mem_logical_addr = 0xffffffff; -#endif - if (_mem_exec[addr >> 14]) return _mem_exec[addr >> 14][addr & 0x3fff]; else if (_mem_read_b[addr >> 14]) @@ -1015,10 +985,6 @@ mem_writeb_phys(uint32_t addr, uint8_t val) void mem_writeb_phys_dma(uint32_t addr, uint8_t val) { -#if 0 - mem_logical_addr = 0xffffffff; -#endif - if (_mem_exec[addr >> 14]) _mem_exec[addr >> 14][addr & 0x3fff] = val; else if (_mem_write_b[addr >> 14]) @@ -1226,31 +1192,6 @@ mem_read_biosl(uint32_t addr, void *priv) } -uint8_t -mem_read_romext(uint32_t addr, void *priv) -{ - return romext[addr & 0x7fff]; -} - - -uint16_t -mem_read_romextw(uint32_t addr, void *priv) -{ - uint16_t *p = (uint16_t *)&romext[addr & 0x7fff]; - - return *p; -} - - -uint32_t -mem_read_romextl(uint32_t addr, void *priv) -{ - uint32_t *p = (uint32_t *)&romext[addr & 0x7fff]; - - return *p; -} - - void mem_write_null(uint32_t addr, uint8_t val, void *p) { @@ -1284,7 +1225,7 @@ mem_invalidate_range(uint32_t start_addr, uint32_t end_addr) static __inline int -mem_mapping_read_allowed(uint32_t fl, int state) +mem_map_read_allowed(uint32_t fl, int state) { switch (state & MEM_READ_MASK) { case MEM_READ_ANY: @@ -1305,7 +1246,7 @@ mem_mapping_read_allowed(uint32_t fl, int state) static __inline int -mem_mapping_write_allowed(uint32_t fl, int state) +mem_map_write_allowed(uint32_t fl, int state) { switch (state & MEM_WRITE_MASK) { case MEM_WRITE_DISABLED: @@ -1325,9 +1266,9 @@ mem_mapping_write_allowed(uint32_t fl, int state) static void -mem_mapping_recalc(uint64_t base, uint64_t size) +mem_map_recalc(uint64_t base, uint64_t size) { - mem_mapping_t *map = base_mapping.next; + mem_map_t *map = base_mapping.next; uint64_t c; if (! size) return; @@ -1339,12 +1280,12 @@ mem_mapping_recalc(uint64_t base, uint64_t size) _mem_read_l[c >> 14] = NULL; _mem_exec[c >> 14] = NULL; _mem_priv_r[c >> 14] = NULL; - _mem_mapping_r[c >> 14] = NULL; + _mem_map_r[c >> 14] = NULL; _mem_write_b[c >> 14] = NULL; _mem_write_w[c >> 14] = NULL; _mem_write_l[c >> 14] = NULL; _mem_priv_w[c >> 14] = NULL; - _mem_mapping_w[c >> 14] = NULL; + _mem_map_w[c >> 14] = NULL; } /* Walk mapping list. */ @@ -1358,7 +1299,7 @@ mem_mapping_recalc(uint64_t base, uint64_t size) for (c = start; c < end; c += 0x4000) { if ((map->read_b || map->read_w || map->read_l) && - mem_mapping_read_allowed(map->flags, _mem_state[c >> 14])) { + mem_map_read_allowed(map->flags, _mem_state[c >> 14])) { _mem_read_b[c >> 14] = map->read_b; _mem_read_w[c >> 14] = map->read_w; _mem_read_l[c >> 14] = map->read_l; @@ -1367,15 +1308,15 @@ mem_mapping_recalc(uint64_t base, uint64_t size) else _mem_exec[c >> 14] = NULL; _mem_priv_r[c >> 14] = map->p; - _mem_mapping_r[c >> 14] = map; + _mem_map_r[c >> 14] = map; } if ((map->write_b || map->write_w || map->write_l) && - mem_mapping_write_allowed(map->flags, _mem_state[c >> 14])) { + mem_map_write_allowed(map->flags, _mem_state[c >> 14])) { _mem_write_b[c >> 14] = map->write_b; _mem_write_w[c >> 14] = map->write_w; _mem_write_l[c >> 14] = map->write_l; _mem_priv_w[c >> 14] = map->p; - _mem_mapping_w[c >> 14] = map; + _mem_map_w[c >> 14] = map; } } } @@ -1387,12 +1328,12 @@ mem_mapping_recalc(uint64_t base, uint64_t size) void -mem_mapping_del(mem_mapping_t *map) +mem_map_del(mem_map_t *map) { - mem_mapping_t *ptr; + mem_map_t *ptr; /* Disable the entry. */ - mem_mapping_disable(map); + mem_map_disable(map); /* Zap it from the list. */ for (ptr = &base_mapping; ptr->next != NULL; ptr = ptr->next) { @@ -1405,20 +1346,16 @@ mem_mapping_del(mem_mapping_t *map) void -mem_mapping_add(mem_mapping_t *map, - uint32_t base, - uint32_t size, - uint8_t (*read_b)(uint32_t addr, void *p), - uint16_t (*read_w)(uint32_t addr, void *p), - uint32_t (*read_l)(uint32_t addr, void *p), - void (*write_b)(uint32_t addr, uint8_t val, void *p), - void (*write_w)(uint32_t addr, uint16_t val, void *p), - void (*write_l)(uint32_t addr, uint32_t val, void *p), - uint8_t *exec, - uint32_t fl, - void *p) +mem_map_add(mem_map_t *map, uint32_t base, uint32_t size, + uint8_t (*read_b)(uint32_t addr, void *p), + uint16_t (*read_w)(uint32_t addr, void *p), + uint32_t (*read_l)(uint32_t addr, void *p), + void (*write_b)(uint32_t addr, uint8_t val, void *p), + void (*write_w)(uint32_t addr, uint16_t val, void *p), + void (*write_l)(uint32_t addr, uint32_t val, void *p), + uint8_t *exec, uint32_t fl, void *p) { - mem_mapping_t *dest = &base_mapping; + mem_map_t *dest = &base_mapping; /* Add mapping to the end of the list.*/ while (dest->next) @@ -1444,18 +1381,18 @@ mem_mapping_add(mem_mapping_t *map, map->dev = NULL; map->next = NULL; - mem_mapping_recalc(map->base, map->size); + mem_map_recalc(map->base, map->size); } void -mem_mapping_set_handler(mem_mapping_t *map, - uint8_t (*read_b)(uint32_t addr, void *p), - uint16_t (*read_w)(uint32_t addr, void *p), - uint32_t (*read_l)(uint32_t addr, void *p), - void (*write_b)(uint32_t addr, uint8_t val, void *p), - void (*write_w)(uint32_t addr, uint16_t val, void *p), - void (*write_l)(uint32_t addr, uint32_t val, void *p)) +mem_map_set_handler(mem_map_t *map, + uint8_t (*read_b)(uint32_t addr, void *p), + uint16_t (*read_w)(uint32_t addr, void *p), + uint32_t (*read_l)(uint32_t addr, void *p), + void (*write_b)(uint32_t addr, uint8_t val, void *p), + void (*write_w)(uint32_t addr, uint16_t val, void *p), + void (*write_l)(uint32_t addr, uint32_t val, void *p)) { map->read_b = read_b; map->read_w = read_w; @@ -1464,64 +1401,64 @@ mem_mapping_set_handler(mem_mapping_t *map, map->write_w = write_w; map->write_l = write_l; - mem_mapping_recalc(map->base, map->size); + mem_map_recalc(map->base, map->size); } void -mem_mapping_set_addr(mem_mapping_t *map, uint32_t base, uint32_t size) +mem_map_set_addr(mem_map_t *map, uint32_t base, uint32_t size) { /* Remove old mapping. */ map->enable = 0; - mem_mapping_recalc(map->base, map->size); + mem_map_recalc(map->base, map->size); /* Set new mapping. */ map->enable = 1; map->base = base; map->size = size; - mem_mapping_recalc(map->base, map->size); + mem_map_recalc(map->base, map->size); } void -mem_mapping_set_exec(mem_mapping_t *map, uint8_t *exec) +mem_map_set_exec(mem_map_t *map, uint8_t *exec) { map->exec = exec; - mem_mapping_recalc(map->base, map->size); + mem_map_recalc(map->base, map->size); } void -mem_mapping_set_p(mem_mapping_t *map, void *p) +mem_map_set_p(mem_map_t *map, void *p) { map->p = p; } void -mem_mapping_set_dev(mem_mapping_t *map, void *p) +mem_map_set_dev(mem_map_t *map, void *p) { map->dev = p; } void -mem_mapping_disable(mem_mapping_t *map) +mem_map_disable(mem_map_t *map) { map->enable = 0; - mem_mapping_recalc(map->base, map->size); + mem_map_recalc(map->base, map->size); } void -mem_mapping_enable(mem_mapping_t *map) +mem_map_enable(mem_map_t *map) { map->enable = 1; - mem_mapping_recalc(map->base, map->size); + mem_map_recalc(map->base, map->size); } @@ -1533,96 +1470,115 @@ mem_set_mem_state(uint32_t base, uint32_t size, int state) for (c = 0; c < size; c += 0x4000) _mem_state[(c + base) >> 14] = state; - mem_mapping_recalc(base, size); + mem_map_recalc(base, size); +} + + +void +mem_add_upper_bios(void) +{ + mem_map_add(&bios_mapping[0], 0xe0000, 0x04000, + mem_read_bios,mem_read_biosw,mem_read_biosl, + mem_write_null,mem_write_nullw,mem_write_nulll, + rom,MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROM, 0); + + mem_map_add(&bios_mapping[1], 0xe4000, 0x04000, + mem_read_bios,mem_read_biosw,mem_read_biosl, + mem_write_null,mem_write_nullw,mem_write_nulll, + rom + (0x4000 & biosmask), + MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROM, 0); + + mem_map_add(&bios_mapping[2], 0xe8000, 0x04000, + mem_read_bios,mem_read_biosw,mem_read_biosl, + mem_write_null,mem_write_nullw,mem_write_nulll, + rom + (0x8000 & biosmask), + MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROM, 0); + + mem_map_add(&bios_mapping[3], 0xec000, 0x04000, + mem_read_bios,mem_read_biosw,mem_read_biosl, + mem_write_null,mem_write_nullw,mem_write_nulll, + rom + (0xc000 & biosmask), + MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROM, 0); } void mem_add_bios(void) { - if (AT || (romset == ROM_XI8088 && xi8088_bios_128kb())) { - mem_mapping_add(&bios_mapping[0], 0xe0000, 0x04000, - mem_read_bios,mem_read_biosw,mem_read_biosl, - mem_write_null,mem_write_nullw,mem_write_nulll, - rom,MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROM, 0); - mem_mapping_add(&bios_mapping[1], 0xe4000, 0x04000, - mem_read_bios,mem_read_biosw,mem_read_biosl, - mem_write_null,mem_write_nullw,mem_write_nulll, - rom + (0x4000 & biosmask), - MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROM, 0); - mem_mapping_add(&bios_mapping[2], 0xe8000, 0x04000, - mem_read_bios,mem_read_biosw,mem_read_biosl, - mem_write_null,mem_write_nullw,mem_write_nulll, - rom + (0x8000 & biosmask), - MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROM, 0); - mem_mapping_add(&bios_mapping[3], 0xec000, 0x04000, - mem_read_bios,mem_read_biosw,mem_read_biosl, - mem_write_null,mem_write_nullw,mem_write_nulll, - rom + (0xc000 & biosmask), - MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROM, 0); - } + if (AT) + mem_add_upper_bios(); - mem_mapping_add(&bios_mapping[4], 0xf0000, 0x04000, - mem_read_bios,mem_read_biosw,mem_read_biosl, - mem_write_null,mem_write_nullw,mem_write_nulll, - rom + (0x10000 & biosmask), - MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROM, 0); - mem_mapping_add(&bios_mapping[5], 0xf4000, 0x04000, - mem_read_bios,mem_read_biosw,mem_read_biosl, - mem_write_null,mem_write_nullw,mem_write_nulll, - rom + (0x14000 & biosmask), - MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROM, 0); - mem_mapping_add(&bios_mapping[6], 0xf8000, 0x04000, - mem_read_bios,mem_read_biosw,mem_read_biosl, - mem_write_null,mem_write_nullw,mem_write_nulll, - rom + (0x18000 & biosmask), - MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROM, 0); - mem_mapping_add(&bios_mapping[7], 0xfc000, 0x04000, - mem_read_bios,mem_read_biosw,mem_read_biosl, - mem_write_null,mem_write_nullw,mem_write_nulll, - rom + (0x1c000 & biosmask), - MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROM, 0); + mem_map_add(&bios_mapping[4], 0xf0000, 0x04000, + mem_read_bios,mem_read_biosw,mem_read_biosl, + mem_write_null,mem_write_nullw,mem_write_nulll, + rom + (0x10000 & biosmask), + MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROM, 0); - mem_mapping_add(&bios_high_mapping[0], - (AT && cpu_16bitbus) ? 0xfe0000 : 0xfffe0000, 0x04000, - mem_read_bios,mem_read_biosw,mem_read_biosl, - mem_write_null,mem_write_nullw,mem_write_nulll, - rom, MEM_MAPPING_ROM, 0); - mem_mapping_add(&bios_high_mapping[1], - (AT && cpu_16bitbus) ? 0xfe4000 : 0xfffe4000, 0x04000, - mem_read_bios,mem_read_biosw,mem_read_biosl, - mem_write_null,mem_write_nullw,mem_write_nulll, - rom + (0x4000 & biosmask), MEM_MAPPING_ROM, 0); - mem_mapping_add(&bios_high_mapping[2], - (AT && cpu_16bitbus) ? 0xfe8000 : 0xfffe8000, 0x04000, - mem_read_bios,mem_read_biosw,mem_read_biosl, - mem_write_null,mem_write_nullw,mem_write_nulll, - rom + (0x8000 & biosmask), MEM_MAPPING_ROM, 0); - mem_mapping_add(&bios_high_mapping[3], - (AT && cpu_16bitbus) ? 0xfec000 : 0xfffec000, 0x04000, - mem_read_bios,mem_read_biosw,mem_read_biosl, - mem_write_null,mem_write_nullw,mem_write_nulll, - rom + (0xc000 & biosmask), MEM_MAPPING_ROM, 0); - mem_mapping_add(&bios_high_mapping[4], - (AT && cpu_16bitbus) ? 0xff0000 : 0xffff0000, 0x04000, - mem_read_bios,mem_read_biosw,mem_read_biosl, - mem_write_null,mem_write_nullw,mem_write_nulll, - rom + (0x10000 & biosmask), MEM_MAPPING_ROM, 0); - mem_mapping_add(&bios_high_mapping[5], - (AT && cpu_16bitbus) ? 0xff4000 : 0xffff4000, 0x04000, - mem_read_bios,mem_read_biosw,mem_read_biosl, - mem_write_null,mem_write_nullw,mem_write_nulll, - rom + (0x14000 & biosmask), MEM_MAPPING_ROM, 0); - mem_mapping_add(&bios_high_mapping[6], - (AT && cpu_16bitbus) ? 0xff8000 : 0xffff8000, 0x04000, - mem_read_bios,mem_read_biosw,mem_read_biosl, - mem_write_null,mem_write_nullw,mem_write_nulll, - rom + (0x18000 & biosmask), MEM_MAPPING_ROM, 0); - mem_mapping_add(&bios_high_mapping[7], - (AT && cpu_16bitbus) ? 0xffc000 : 0xffffc000, 0x04000, - mem_read_bios,mem_read_biosw,mem_read_biosl, - mem_write_null,mem_write_nullw,mem_write_nulll, - rom + (0x1c000 & biosmask), MEM_MAPPING_ROM, 0); + mem_map_add(&bios_mapping[5], 0xf4000, 0x04000, + mem_read_bios,mem_read_biosw,mem_read_biosl, + mem_write_null,mem_write_nullw,mem_write_nulll, + rom + (0x14000 & biosmask), + MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROM, 0); + + mem_map_add(&bios_mapping[6], 0xf8000, 0x04000, + mem_read_bios,mem_read_biosw,mem_read_biosl, + mem_write_null,mem_write_nullw,mem_write_nulll, + rom + (0x18000 & biosmask), + MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROM, 0); + + mem_map_add(&bios_mapping[7], 0xfc000, 0x04000, + mem_read_bios,mem_read_biosw,mem_read_biosl, + mem_write_null,mem_write_nullw,mem_write_nulll, + rom + (0x1c000 & biosmask), + MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROM, 0); + + mem_map_add(&bios_high_mapping[0], + (AT && cpu_16bitbus) ? 0xfe0000 : 0xfffe0000, 0x04000, + mem_read_bios,mem_read_biosw,mem_read_biosl, + mem_write_null,mem_write_nullw,mem_write_nulll, + rom, MEM_MAPPING_ROM, 0); + + mem_map_add(&bios_high_mapping[1], + (AT && cpu_16bitbus) ? 0xfe4000 : 0xfffe4000, 0x04000, + mem_read_bios,mem_read_biosw,mem_read_biosl, + mem_write_null,mem_write_nullw,mem_write_nulll, + rom + (0x4000 & biosmask), MEM_MAPPING_ROM, 0); + + mem_map_add(&bios_high_mapping[2], + (AT && cpu_16bitbus) ? 0xfe8000 : 0xfffe8000, 0x04000, + mem_read_bios,mem_read_biosw,mem_read_biosl, + mem_write_null,mem_write_nullw,mem_write_nulll, + rom + (0x8000 & biosmask), MEM_MAPPING_ROM, 0); + + mem_map_add(&bios_high_mapping[3], + (AT && cpu_16bitbus) ? 0xfec000 : 0xfffec000, 0x04000, + mem_read_bios,mem_read_biosw,mem_read_biosl, + mem_write_null,mem_write_nullw,mem_write_nulll, + rom + (0xc000 & biosmask), MEM_MAPPING_ROM, 0); + + mem_map_add(&bios_high_mapping[4], + (AT && cpu_16bitbus) ? 0xff0000 : 0xffff0000, 0x04000, + mem_read_bios,mem_read_biosw,mem_read_biosl, + mem_write_null,mem_write_nullw,mem_write_nulll, + rom + (0x10000 & biosmask), MEM_MAPPING_ROM, 0); + + mem_map_add(&bios_high_mapping[5], + (AT && cpu_16bitbus) ? 0xff4000 : 0xffff4000, 0x04000, + mem_read_bios,mem_read_biosw,mem_read_biosl, + mem_write_null,mem_write_nullw,mem_write_nulll, + rom + (0x14000 & biosmask), MEM_MAPPING_ROM, 0); + + mem_map_add(&bios_high_mapping[6], + (AT && cpu_16bitbus) ? 0xff8000 : 0xffff8000, 0x04000, + mem_read_bios,mem_read_biosw,mem_read_biosl, + mem_write_null,mem_write_nullw,mem_write_nulll, + rom + (0x18000 & biosmask), MEM_MAPPING_ROM, 0); + + mem_map_add(&bios_high_mapping[7], + (AT && cpu_16bitbus) ? 0xffc000 : 0xffffc000, 0x04000, + mem_read_bios,mem_read_biosw,mem_read_biosl, + mem_write_null,mem_write_nullw,mem_write_nulll, + rom + (0x1c000 & biosmask), MEM_MAPPING_ROM, 0); } @@ -1664,21 +1620,14 @@ mem_reset(void) if (AT) c <<= 10; /* make KB */ if (m > c) { - pclog("MEM: %luKB exceeds machine limit (%luKB), adjusted!\n", m, c); + INFO("MEM: %luKB exceeds machine limit (%luKB), adjusted!\n", m, c); mem_size = c; } - /* - * Always allocate the full 16 MB memory space if memory size - * is smaller, we'll need this for stupid things like the PS/2 - * split mapping. - */ - if (mem_size < 16384) - m = 1024UL * 16384; - else - m = 1024UL * mem_size; - if (ram != NULL) free(ram); - ram = (uint8_t *)malloc(m); /* allocate and clear the RAM block */ + m = 1024UL * mem_size; + if (ram != NULL) + free(ram); + ram = (uint8_t *)mem_alloc(m); /* allocate and clear the RAM block */ memset(ram, 0x00, m); /* @@ -1707,27 +1656,11 @@ mem_reset(void) * Allocate and initialize the (new) page table. * We only do this if the size of the page table has changed. */ -#if DYNAMIC_TABLES -pclog("MEM: reset: previous pages=%08lx, pages_sz=%i\n", pages, pages_sz); -#endif if (pages_sz != m || pages_sz == 0) { pages_sz = m; free(pages); - pages = (page_t *)malloc(m*sizeof(page_t)); + pages = (page_t *)mem_alloc(m*sizeof(page_t)); memset(pages, 0x00, m*sizeof(page_t)); -#if DYNAMIC_TABLES -pclog("MEM: reset: new pages=%08lx, pages_sz=%i\n", pages, pages_sz); - - /* Allocate the (new) lookup tables. */ - if (page_lookup != NULL) free(page_lookup); - page_lookup = (page_t **)malloc(pages_sz*sizeof(page_t *)); - - if (readlookup2 != NULL) free(readlookup2); - readlookup2 = malloc(pages_sz*sizeof(uintptr_t)); - - if (writelookup2 != NULL) free(writelookup2); - writelookup2 = malloc(pages_sz*sizeof(uintptr_t)); -#endif } /* Initialize the page table. */ @@ -1738,15 +1671,6 @@ pclog("MEM: reset: new pages=%08lx, pages_sz=%i\n", pages, pages_sz); pages[c].write_l = mem_write_raml_page; } - if (pages_sz > 256) { - for (c = ((1024UL * mem_size) >> 12); c < ((1024UL * (mem_size + 256)) >> 12); c++) { - pages[c].mem = &ram[0xA0000 + ((c - ((mem_size * 1024) >> 12)) << 12)]; - pages[c].write_b = mem_write_ramb_page; - pages[c].write_w = mem_write_ramw_page; - pages[c].write_l = mem_write_raml_page; - } - } - /* Initialize the tables. */ resetreadlookup(); @@ -1767,48 +1691,43 @@ pclog("MEM: reset: new pages=%08lx, pages_sz=%i\n", pages, pages_sz); mem_set_mem_state(0x0c0000, 0x40000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); - mem_mapping_add(&ram_low_mapping, 0x00000, - (mem_size > 640) ? 0xa0000 : mem_size * 1024, - mem_read_ram,mem_read_ramw,mem_read_raml, - mem_write_ram,mem_write_ramw,mem_write_raml, - ram, MEM_MAPPING_INTERNAL, NULL); + mem_map_add(&ram_low_mapping, 0x00000, + (mem_size > 640) ? 0xa0000 : mem_size * 1024, + mem_read_ram,mem_read_ramw,mem_read_raml, + mem_write_ram,mem_write_ramw,mem_write_raml, + ram, MEM_MAPPING_INTERNAL, NULL); if (mem_size > 1024) { if (cpu_16bitbus && mem_size > 16256) { mem_set_mem_state(0x100000, (16256 - 1024) * 1024, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - mem_mapping_add(&ram_high_mapping, 0x100000, - ((16256 - 1024) * 1024), - mem_read_ram,mem_read_ramw,mem_read_raml, - mem_write_ram,mem_write_ramw,mem_write_raml, - ram + 0x100000, MEM_MAPPING_INTERNAL, NULL); + mem_map_add(&ram_high_mapping, 0x100000, + ((16256 - 1024) * 1024), + mem_read_ram,mem_read_ramw,mem_read_raml, + mem_write_ram,mem_write_ramw,mem_write_raml, + ram + 0x100000, MEM_MAPPING_INTERNAL, NULL); } else { mem_set_mem_state(0x100000, (mem_size - 1024) * 1024, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - mem_mapping_add(&ram_high_mapping, 0x100000, - ((mem_size - 1024) * 1024), - mem_read_ram,mem_read_ramw,mem_read_raml, - mem_write_ram,mem_write_ramw,mem_write_raml, - ram + 0x100000, MEM_MAPPING_INTERNAL, NULL); + mem_map_add(&ram_high_mapping, 0x100000, + ((mem_size - 1024) * 1024), + mem_read_ram,mem_read_ramw,mem_read_raml, + mem_write_ram,mem_write_ramw,mem_write_raml, + ram + 0x100000, MEM_MAPPING_INTERNAL, NULL); } } if (mem_size > 768) - mem_mapping_add(&ram_mid_mapping, 0xc0000, 0x40000, - mem_read_ram,mem_read_ramw,mem_read_raml, - mem_write_ram,mem_write_ramw,mem_write_raml, - ram + 0xc0000, MEM_MAPPING_INTERNAL, NULL); + mem_map_add(&ram_mid_mapping, 0xc0000, 0x40000, + mem_read_ram,mem_read_ramw,mem_read_raml, + mem_write_ram,mem_write_ramw,mem_write_raml, + ram + 0xc0000, MEM_MAPPING_INTERNAL, NULL); - if (romset == ROM_IBMPS1_2011) - mem_mapping_add(&romext_mapping, 0xc8000, 0x08000, - mem_read_romext,mem_read_romextw,mem_read_romextl, - NULL,NULL, NULL, romext, 0, NULL); - - mem_mapping_add(&ram_remapped_mapping, mem_size * 1024, 256 * 1024, - mem_read_remapped,mem_read_remappedw,mem_read_remappedl, - mem_write_remapped,mem_write_remappedw,mem_write_remappedl, - ram + 0xa0000, MEM_MAPPING_INTERNAL, NULL); - mem_mapping_disable(&ram_remapped_mapping); + mem_map_add(&ram_remapped_mapping, mem_size * 1024, 256 * 1024, + mem_read_remapped,mem_read_remappedw,mem_read_remappedl, + mem_write_remapped,mem_write_remappedw,mem_write_remappedl, + ram + 0xa0000, MEM_MAPPING_INTERNAL, NULL); + mem_map_disable(&ram_remapped_mapping); mem_a20_init(); } @@ -1822,19 +1741,13 @@ mem_init(void) ram = rom = NULL; pages = NULL; pages_sz = 0; -#if DYNAMIC_TABLES - page_lookup = NULL; - readlookup2 = NULL; - writelookup2 = NULL; -#else /* Allocate the lookup tables. */ - page_lookup = (page_t **)malloc((1<<20)*sizeof(page_t *)); + page_lookup = (page_t **)mem_alloc((1<<20)*sizeof(page_t *)); - readlookup2 = malloc((1<<20)*sizeof(uintptr_t)); + readlookup2 = (uintptr_t *)mem_alloc((1<<20)*sizeof(uintptr_t)); - writelookup2 = malloc((1<<20)*sizeof(uintptr_t)); -#endif + writelookup2 = (uintptr_t *)mem_alloc((1<<20)*sizeof(uintptr_t)); memset(ram_mapped_addr, 0x00, 64 * sizeof(uint32_t)); } @@ -1845,14 +1758,15 @@ mem_remap_top(int kb) { uint32_t start = (mem_size >= 1024) ? mem_size : 1024; int size = mem_size - 640; + uint32_t i; - pclog("MEM: remapping top %iKB (mem=%i)\n", kb, mem_size); + INFO("MEM: remapping top %iKB (mem=%i)\n", kb, mem_size); if (mem_size <= 640) return; if (kb == 0) { /* Called to disable the mapping. */ - mem_mapping_disable(&ram_remapped_mapping); + mem_map_disable(&ram_remapped_mapping); return; } @@ -1860,10 +1774,17 @@ mem_remap_top(int kb) if (size > kb) size = kb; + for (i = ((start * 1024) >> 12); i < (((start + size) * 1024) >> 12); i++) { + pages[i].mem = &ram[0xA0000 + ((i - ((start * 1024) >> 12)) << 12)]; + pages[i].write_b = mem_write_ramb_page; + pages[i].write_w = mem_write_ramw_page; + pages[i].write_l = mem_write_raml_page; + } + mem_set_mem_state(start * 1024, size * 1024, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - mem_mapping_set_addr(&ram_remapped_mapping, start * 1024, size * 1024); - mem_mapping_set_exec(&ram_remapped_mapping, ram + (start * 1024)); + mem_map_set_addr(&ram_remapped_mapping, start * 1024, size * 1024); + mem_map_set_exec(&ram_remapped_mapping, ram + (start * 1024)); flushmmucache(); } diff --git a/src/mem.h b/src/mem.h index 0370843..0f11437 100644 --- a/src/mem.h +++ b/src/mem.h @@ -8,7 +8,7 @@ * * Definitions for the memory interface. * - * Version: @(#)mem.h 1.0.9 2018/08/20 + * Version: @(#)mem.h 1.0.10 2018/09/18 * * Authors: Fred N. van Kempen, * Sarah Walker, @@ -58,8 +58,8 @@ #define MEM_WRITE_MASK 0x0f -typedef struct _mem_mapping_ { - struct _mem_mapping_ *prev, *next; +typedef struct _memmap_ { + struct _memmap_ *prev, *next; int enable; @@ -80,7 +80,7 @@ typedef struct _mem_mapping_ { void *p; /* backpointer to mapping or device */ void *dev; /* backpointer to memory device */ -} mem_mapping_t; +} mem_map_t; typedef struct _page_ { void (*write_b)(uint32_t addr, uint8_t val, struct _page_ *p); @@ -103,7 +103,6 @@ extern uint8_t *ram; extern uint32_t rammask; extern uint8_t *rom; -extern uint8_t romext[32768]; extern uint32_t biosmask; extern int readlookup[256], @@ -116,11 +115,9 @@ extern uintptr_t *writelookup2; extern int writelnext; extern uint32_t ram_mapped_addr[64]; -mem_mapping_t base_mapping, +extern mem_map_t base_mapping, ram_low_mapping, -#if 1 ram_mid_mapping, -#endif ram_remapped_mapping, ram_high_mapping, bios_mapping[8], @@ -136,8 +133,6 @@ extern uint32_t get_phys_virt,get_phys_phys; extern int shadowbios, shadowbios_write; -extern int readlnum, - writelnum; extern int nopageerrors; extern int memspeed[11]; @@ -180,9 +175,9 @@ extern void addreadlookup(uint32_t virt, uint32_t phys); extern void addwritelookup(uint32_t virt, uint32_t phys); -extern void mem_mapping_del(mem_mapping_t *); +extern void mem_map_del(mem_map_t *); -extern void mem_mapping_add(mem_mapping_t *, +extern void mem_map_add(mem_map_t *, uint32_t base, uint32_t size, uint8_t (*read_b)(uint32_t addr, void *p), @@ -195,7 +190,7 @@ extern void mem_mapping_add(mem_mapping_t *, uint32_t flags, void *p); -extern void mem_mapping_set_handler(mem_mapping_t *, +extern void mem_map_set_handler(mem_map_t *, uint8_t (*read_b)(uint32_t addr, void *p), uint16_t (*read_w)(uint32_t addr, void *p), uint32_t (*read_l)(uint32_t addr, void *p), @@ -203,15 +198,14 @@ extern void mem_mapping_set_handler(mem_mapping_t *, void (*write_w)(uint32_t addr, uint16_t val, void *p), void (*write_l)(uint32_t addr, uint32_t val, void *p)); -extern void mem_mapping_set_p(mem_mapping_t *, void *p); +extern void mem_map_set_p(mem_map_t *, void *p); -extern void mem_mapping_set_dev(mem_mapping_t *, void *dev); +extern void mem_map_set_dev(mem_map_t *, void *dev); -extern void mem_mapping_set_addr(mem_mapping_t *, - uint32_t base, uint32_t size); -extern void mem_mapping_set_exec(mem_mapping_t *, uint8_t *exec); -extern void mem_mapping_disable(mem_mapping_t *); -extern void mem_mapping_enable(mem_mapping_t *); +extern void mem_map_set_addr(mem_map_t *, uint32_t base, uint32_t size); +extern void mem_map_set_exec(mem_map_t *, uint8_t *exec); +extern void mem_map_disable(mem_map_t *); +extern void mem_map_enable(mem_map_t *); extern void mem_set_mem_state(uint32_t base, uint32_t size, int state); @@ -256,6 +250,7 @@ extern void mmu_invalidate(uint32_t addr); extern void mem_a20_recalc(void); extern void mem_add_bios(void); +extern void mem_add_upper_bios(void); extern void mem_init(void); extern void mem_reset(void); diff --git a/src/misc.c b/src/misc.c index 0562929..ea52a8a 100644 --- a/src/misc.c +++ b/src/misc.c @@ -8,7 +8,7 @@ * * Misc functions that do not fit anywhere else. * - * Version: @(#)misc.c 1.0.3 2018/10/04 + * Version: @(#)misc.c 1.0.3 2018/10/05 * * Author: Fred N. van Kempen, * @@ -55,26 +55,6 @@ #include "ui/ui.h" -const wchar_t * -get_string(int id) -{ - const wchar_t *str = NULL; - const string_t *tbl; - - tbl = plat_strings; - while(tbl->str != NULL) { - if (tbl->id == id) { - str = tbl->str; - break; - } - - tbl++; - } - - return(str); -} - - /* Grab the value from a string. */ uint32_t get_val(const char *str) @@ -100,9 +80,8 @@ mem_alloc(size_t sz) ui_msgbox(MBX_ERROR|MBX_FATAL, (wchar_t *)IDS_ERR_NOMEM); /* Try to write to the logfile. This may not work anymore. */ - pclog("FATAL: system out of memory!\n"); - fflush(stdlog); - fclose(stdlog); + ERRLOG("FATAL: system out of memory!\n"); + pclog(-1, NULL); /* Now exit - this will (hopefully..) not return. */ exit(-1); diff --git a/src/nvr.c b/src/nvr.c index dd78521..4934a23 100644 --- a/src/nvr.c +++ b/src/nvr.c @@ -8,7 +8,7 @@ * * Implement a generic NVRAM/CMOS/RTC device. * - * Version: @(#)nvr.c 1.0.11 2018/08/27 + * Version: @(#)nvr.c 1.0.12 2018/10/05 * * Author: Fred N. van Kempen, * @@ -52,8 +52,6 @@ #include #include "emu.h" #include "machines/machine.h" -#include "devices/system/pic.h" -#include "devices/system/pit.h" #include "timer.h" #include "plat.h" #include "nvr.h" @@ -108,7 +106,7 @@ rtc_tick(void) if (++intclk.tm_mon == 13) { intclk.tm_mon = 1; intclk.tm_year++; - } + } } } } @@ -152,18 +150,22 @@ nvr_init(nvr_t *nvr) strcpy(temp, (const char *)nvr->fn); else strcpy(temp, machine_get_internal_name()); - strcat(temp, ".nvr"); c = strlen(temp) + 1; - sp = (wchar_t *)malloc(c*sizeof(wchar_t)); + sp = (wchar_t *)mem_alloc((c+10) * sizeof(wchar_t)); mbstowcs(sp, temp, c); + wcscat(sp, NVR_FILE_EXT); nvr->fn = (const wchar_t *)sp; /* Initialize the internal clock as needed. */ memset(&intclk, 0x00, sizeof(intclk)); - if (enable_sync) { + if (time_sync != TIME_SYNC_DISABLED) { /* Get the current time of day, and convert to local time. */ (void)time(&now); - tm = localtime(&now); + + if (time_sync == TIME_SYNC_ENABLED_UTC) + tm = gmtime(&now); + else + tm = localtime(&now); /* Set the internal clock. */ nvr_time_set(tm); @@ -242,7 +244,7 @@ nvr_load(void) /* Load the (relevant) part of the NVR contents. */ if (saved_nvr->size != 0) { path = nvr_path(saved_nvr->fn); - pclog("NVR: loading from '%ls'\n", path); + INFO("NVR: loading from '%ls'\n", path); fp = plat_fopen(path, L"rb"); if (fp != NULL) { /* Read NVR contents from file. */ @@ -271,7 +273,7 @@ nvr_save(void) if (saved_nvr->size != 0) { path = nvr_path(saved_nvr->fn); - pclog("NVR: saving to '%ls'\n", path); + INFO("NVR: saving to '%ls'\n", path); fp = plat_fopen(path, L"wb"); if (fp != NULL) { /* Save NVR contents to file. */ @@ -287,6 +289,17 @@ nvr_save(void) } +void +nvr_period_recalc(void) +{ + /* Make sure we have been initialized. */ + if (saved_nvr == NULL) return; + + if (saved_nvr->size != 0) + saved_nvr->recalc(saved_nvr); +} + + /* Get current time from internal clock. */ void nvr_time_get(struct tm *tm) diff --git a/src/nvr.h b/src/nvr.h index 31e9cda..308517a 100644 --- a/src/nvr.h +++ b/src/nvr.h @@ -8,7 +8,7 @@ * * Definitions for the generic NVRAM/CMOS driver. * - * Version: @(#)nvr.h 1.0.7 2018/08/27 + * Version: @(#)nvr.h 1.0.8 2018/09/09 * * Author: Fred N. van Kempen, * @@ -56,6 +56,14 @@ #define RTC_BCDINC(x,y) RTC_BCD(RTC_DCB(x) + y) +/* Time sync options. */ +enum { + TIME_SYNC_DISABLED = 0, + TIME_SYNC_ENABLED, + TIME_SYNC_ENABLED_UTC +}; + + /* Define a generic RTC/NVRAM device. */ typedef struct _nvr_ { const wchar_t *fn; /* pathname of image file */ @@ -71,6 +79,7 @@ typedef struct _nvr_ { void (*reset)(struct _nvr_ *); void (*start)(struct _nvr_ *); void (*tick)(struct _nvr_ *); + void (*recalc)(struct _nvr_ *); uint8_t regs[NVR_MAXSIZE]; /* these are the registers */ } nvr_t; @@ -78,6 +87,8 @@ typedef struct _nvr_ { extern int nvr_dosave; #ifdef EMU_DEVICE_H + +extern const device_t at_nvr_old_device; extern const device_t at_nvr_device; extern const device_t ps_nvr_device; extern const device_t amstrad_nvr_device; @@ -88,6 +99,7 @@ extern void nvr_init(nvr_t *); extern wchar_t *nvr_path(const wchar_t *fn); extern int nvr_load(void); extern int nvr_save(void); +extern void nvr_period_recalc(void); extern int nvr_is_leap(int year); extern int nvr_get_days(int month, int year); diff --git a/src/pc.c b/src/pc.c index dd33226..8317af3 100644 --- a/src/pc.c +++ b/src/pc.c @@ -8,7 +8,7 @@ * * Main emulator module where most things are controlled. * - * Version: @(#)pc.c 1.0.55 2018/09/28 + * Version: @(#)pc.c 1.0.54 2018/10/05 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -36,7 +36,6 @@ * Boston, MA 02111-1307 * USA. */ -#include #include #include #include @@ -50,13 +49,11 @@ #include "config.h" #include "cpu/cpu.h" #ifdef USE_DYNAREC +# include "cpu/x86.h" # include "cpu/codegen.h" #endif -#include "cpu/x86_ops.h" #include "machines/machine.h" #include "io.h" -#include "mem.h" -#include "rom.h" #include "devices/system/dma.h" #include "devices/system/pic.h" #include "devices/system/pit.h" @@ -74,15 +71,13 @@ #include "devices/floppy/fdd_common.h" #include "devices/disk/hdd.h" #include "devices/disk/hdc.h" -#include "devices/disk/hdc_ide.h" +#include "devices/scsi/scsi.h" +#include "devices/scsi/scsi_device.h" +#include "devices/scsi/scsi_disk.h" #include "devices/disk/zip.h" #include "devices/cdrom/cdrom.h" -#include "devices/cdrom/cdrom_image.h" -#include "devices/cdrom/cdrom_null.h" -#include "devices/scsi/scsi.h" #include "devices/network/network.h" #include "devices/sound/sound.h" -#include "devices/sound/snd_speaker.h" #include "devices/video/video.h" #include "devices/misc/bugger.h" #include "devices/misc/isamem.h" @@ -106,10 +101,11 @@ int video_fps = RENDER_FPS; /* (O) render speed in fps */ #endif int settings_only = 0; /* (O) only the settings dlg */ int config_ro = 0; /* (O) dont modify cfg file */ +int log_level = LOG_INFO; /* (O) global logging level */ wchar_t log_path[1024] = { L'\0'}; /* (O) full path of logfile */ /* Configuration values. */ -int lang_id = 0x0409; /* (C) language ID */ +int language = 0x0000; /* (C) language ID */ int window_w, window_h, /* (C) window size and */ window_x, window_y, /* position info */ window_remember; @@ -126,13 +122,11 @@ int vid_api = 0, /* (C) video renderer */ scale = 0, /* (C) screen scale factor */ enable_overscan = 0, /* (C) video */ force_43 = 0, /* (C) video */ - rctrl_is_lalt, /* (C) set R-CTRL as L-ALT */ - update_icons = 1; /* (C) update statbar icons */ + rctrl_is_lalt; /* (C) set R-CTRL as L-ALT */ int video_card = 0, /* (C) graphics/video card */ - video_speed = 0, /* (C) video */ voodoo_enabled = 0; /* (C) video option */ int mouse_type = 0; /* (C) selected mouse type */ -int enable_sync = 0; /* (C) enable time sync */ +int time_sync = 0; /* (C) enable time sync */ int game_enabled = 0, /* (C) enable game port */ serial_enabled[] = {0,0}, /* (C) enable serial ports */ parallel_enabled[] = {0,0,0}, /* (C) enable LPT ports */ @@ -149,10 +143,11 @@ int sound_card = 0, /* (C) selected sound card */ sound_is_float = 1, /* (C) sound uses FP values */ sound_gain = 0, /* (C) sound volume gain */ mpu401_standalone_enable = 0, /* (C) sound option */ - opl3_type = 0, /* (C) sound option */ + opl_type = 0, /* (C) sound option */ midi_device; /* (C) selected midi device */ int joystick_type = 0; /* (C) joystick type */ int mem_size = 0; /* (C) memory size */ +int machine = -1; /* (C) current machine ID */ int cpu_manufacturer = 0, /* (C) cpu manufacturer */ cpu_use_dynarec = 0, /* (C) cpu uses/needs Dyna */ cpu = 3, /* (C) cpu type */ @@ -161,29 +156,7 @@ int network_type; /* (C) net provider type */ int network_card; /* (C) net interface num */ char network_host[512]; /* (C) host network intf */ - -/* Statistics. */ -extern int - mmuflush, - readlnum, - writelnum; - -int sndcount = 0; -int sreadlnum, - swritelnum, - segareads, - segawrites, - scycles_lost; -float mips, flops; -int cycles_lost = 0; /* video */ -int insc = 0; /* cpu */ -int emu_fps = 0, fps; /* video */ -int framecount; - -int atfullspeed; -int cpuspeed2; -int clockrate; - +/* Global variables. */ char emu_title[64]; /* full name of application */ char emu_version[32]; /* short version ID string */ char emu_fullversion[128]; /* full version ID string */ @@ -191,16 +164,24 @@ wchar_t exe_path[1024]; /* emu executable path */ wchar_t emu_path[1024]; /* emu installation path */ wchar_t usr_path[1024]; /* path (dir) of user data */ wchar_t cfg_path[1024]; /* full path of config file */ -FILE *stdlog = NULL; /* file to log output to */ +int emu_lang_id; /* current language ID */ int scrnsz_x = SCREEN_RES_X, /* current screen size, X */ scrnsz_y = SCREEN_RES_Y; /* current screen size, Y */ -int unscaled_size_x = SCREEN_RES_X, /* current unscaled size X */ - unscaled_size_y = SCREEN_RES_Y, /* current unscaled size Y */ - efscrnsz_y = SCREEN_RES_Y; -int config_changed; /* config has changed */ -int romset; /* current machine ID */ -int title_update; -int64_t main_time; +int config_changed, /* config has changed */ + dopause = 0, /* system is paused */ + doresize = 0, /* screen resize requested */ + mouse_capture = 0; /* mouse is captured in app */ + +/* Local variables. */ +static int fps, /* statistics */ + framecount, + title_update, /* we want title updated */ + atfullspeed, + cpuspeed2; +static int unscaled_size_x = SCREEN_RES_X, /* current unscaled size X */ + unscaled_size_y = SCREEN_RES_Y, /* current unscaled size Y */ + efscrnsz_y = SCREEN_RES_Y; +static FILE *stdlog = NULL; /* file to log output to */ /* @@ -217,7 +198,6 @@ int64_t main_time; void pclog_ex(const char *fmt, va_list ap) { -#ifndef RELEASE_BUILD static char buff[PCLOG_BUFF_SIZE]; static int seen = 0; static int detect = 1; @@ -261,21 +241,26 @@ pclog_ex(const char *fmt, va_list ap) } fflush(stdlog); -#endif } /* Log something. We only do this in non-release builds. */ void -pclog(const char *fmt, ...) +pclog(int level, const char *fmt, ...) { -#ifndef RELEASE_BUILD va_list ap; - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); -#endif + if (fmt == NULL) { + fflush(stdlog); + fclose(stdlog); + return; + } + + if (log_level >= level) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } } @@ -318,14 +303,12 @@ pclog_dump(int num) sp += strlen(sp); if ((i % 16) == 0) { - strcat(sp, "\n"); - pclog(buff); + DBGLOG(2, "%s\n", buff); sp = NULL; } } if (sp != NULL) { - strcat(sp, "\n"); - pclog(buff); + DBGLOG(2, "%s\n", buff); } /* Re-enable the repeat-detection. */ @@ -475,61 +458,66 @@ pc_path(wchar_t *dst, int sz, const wchar_t *src) /* * Perform initial setup of the PC. * - * This is the platform-indepenent part of the startup, - * where we check commandline arguments and load a - * configuration file. + * This is the platform-indepenent part of the startup, where we + * check commandline arguments and load a configuration file. */ int pc_setup(int argc, wchar_t *argv[]) { - wchar_t path[1024]; + wchar_t temp[1024]; + char tempA[128]; wchar_t *cfg = NULL, *p; - char temp[128]; struct tm *info; time_t now; int c, ret = 0; - /* Grab the executable's full path. */ - plat_get_exe_name(emu_path, sizeof_w(emu_path)); - if ((p = plat_get_basename(emu_path)) != NULL) - *p = L'\0'; - wcscpy(exe_path, emu_path); - plat_append_slash(exe_path); - - /* - * See if we are perhaps in a "bin/" subfolder of - * the installation path, in which case the real - * root of the installation is one level up. We - * can test this by looking for the 'roms' folder. - */ - wcscpy(path, emu_path); - plat_append_slash(path); - wcscat(path, ROMS_PATH); - if (! plat_dir_check(path)) { - /* No 'roms' folder found, so go up one level. */ - wcscpy(path, emu_path); - if ((p = plat_get_basename(path)) != NULL) + /* Are we doing first initialization? */ + if (argc == 0) { + /* Grab the executable's full path. */ + plat_get_exe_name(emu_path, sizeof_w(emu_path)); + if ((p = plat_get_basename(emu_path)) != NULL) *p = L'\0'; - plat_append_slash(path); - wcscat(path, ROMS_PATH); - if (plat_dir_check(path)) { - if (p != NULL) - *p = L'\0'; - wcscpy(emu_path, path); - } - } - plat_append_slash(emu_path); + wcscpy(exe_path, emu_path); + plat_append_slash(exe_path); - /* - * Get the current working directory. - * - * This is normally the directory from where the - * program was run. If we have been started via - * a shortcut (desktop icon), however, the CWD - * could have been set to something else. - */ - plat_getcwd(usr_path, sizeof_w(usr_path)); - memset(path, 0x00, sizeof(path)); + /* + * See if we are perhaps in a "bin/" subfolder of the + * installation path, in which case the real root of + * the installation is one level up. We can test this + * by looking for the 'roms' folder. + */ + wcscpy(temp, emu_path); + plat_append_slash(temp); + wcscat(temp, ROMS_PATH); + if (! plat_dir_check(temp)) { + /* No 'roms' folder found, so go up one level. */ + wcscpy(temp, emu_path); + if ((p = plat_get_basename(temp)) != NULL) + *p = L'\0'; + plat_append_slash(temp); + wcscat(temp, ROMS_PATH); + if (plat_dir_check(temp)) { + if (p != NULL) + *p = L'\0'; + wcscpy(emu_path, temp); + } + } + plat_append_slash(emu_path); + + /* + * Get the current working directory. + * + * This is normally the directory from where the + * program was run. If we have been started via + * a shortcut (desktop icon), however, the CWD + * could have been set to something else. + */ + plat_getcwd(usr_path, sizeof_w(usr_path)); + + return(0); + } + + memset(temp, 0x00, sizeof(temp)); for (c = 1; c < argc; c++) { if (argv[c][0] != L'-') break; @@ -544,12 +532,11 @@ usage: printf("Valid options are:\n\n"); printf(" -? or --help - show this information\n"); printf(" -C or --dumpcfg - dump config file after loading\n"); -#ifdef _WIN32 - printf(" -D or --debug - force debug output logging\n"); -#endif + printf(" -D or --debug - force debug logging\n"); printf(" -F or --fullscreen - start in fullscreen mode\n"); printf(" -L or --logfile path - set 'path' to be the logfile\n"); printf(" -P or --vmpath path - set 'path' to be root for vm\n"); + printf(" -q or --quiet - set logging level to QUIET\n"); #ifdef USE_WX printf(" -R or --fps num - set render speed to 'num' fps\n"); #endif @@ -560,11 +547,12 @@ usage: } else if (!wcscasecmp(argv[c], L"--dumpcfg") || !wcscasecmp(argv[c], L"-C")) { do_dump_config = 1; -#ifdef _WIN32 } else if (!wcscasecmp(argv[c], L"--debug") || !wcscasecmp(argv[c], L"-D")) { +#ifdef _WIN32 force_debug = 1; #endif + log_level++; } else if (!wcscasecmp(argv[c], L"--fullscreen") || !wcscasecmp(argv[c], L"-F")) { start_in_fullscreen = 1; @@ -581,7 +569,10 @@ usage: ret = -1; goto usage; } - wcscpy(path, argv[++c]); + wcsncpy(temp, argv[++c], sizeof_w(temp)); + } else if (!wcscasecmp(argv[c], L"--quiet") || + !wcscasecmp(argv[c], L"-q")) { + log_level = LOG_DEBUG; #ifdef USE_WX } else if (!wcscasecmp(argv[c], L"--fps") || !wcscasecmp(argv[c], L"-R")) { @@ -622,8 +613,8 @@ usage: * make sure that if that was a relative path, we * make it absolute. */ - if (path[0] != L'\0') { - if (! plat_path_abs(path)) { + if (temp[0] != L'\0') { + if (! plat_path_abs(temp)) { /* * This looks like a relative path. * @@ -631,13 +622,13 @@ usage: * to convert it (back) to an absolute path. */ plat_append_slash(usr_path); - wcscat(usr_path, path); + wcscat(usr_path, temp); } else { /* * The user-provided path seems like an * absolute path, so just use that. */ - wcscpy(usr_path, path); + wcscpy(usr_path, temp); } } @@ -704,12 +695,12 @@ usage: #endif (void)time(&now); info = localtime(&now); - strftime(temp, sizeof(temp), "%Y/%m/%d %H:%M:%S", info); - pclog("#\n# %s %s\n#\n# Logfile created %s\n#\n", - emu_title, emu_fullversion, temp); - pclog("# Emulator path: %ls\n", emu_path); - pclog("# Userfiles path: %ls\n", usr_path); - pclog("# Configuration file: %ls\n#\n\n", cfg_path); + strftime(tempA, sizeof(temp), "%Y/%m/%d %H:%M:%S", info); + INFO("#\n# %s %s\n#\n# Logfile created %s\n#\n", + emu_title, emu_fullversion, tempA); + INFO("# Emulator path: %ls\n", emu_path); + INFO("# Userfiles path: %ls\n", usr_path); + INFO("# Configuration file: %ls\n#\n\n", cfg_path); /* * We are about to read the configuration file, which MAY @@ -721,6 +712,8 @@ usage: hdd_init(); cdrom_global_init(); zip_global_init(); + scsi_disk_global_init(); + network_init(); /* Load the configuration file. */ @@ -731,29 +724,37 @@ usage: } +void +pc_set_speed(void) +{ + if (machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].cpu_type >= CPU_286) + setpitclock((float)machine_speed()); + else + setpitclock(14318184.0); +} + + void pc_full_speed(void) { cpuspeed2 = cpuspeed; if (! atfullspeed) { - pclog("Set fullspeed - %i %i %i\n", is386, AT, cpuspeed2); - if (AT) - setpitclock((float)machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].rspeed); - else - setpitclock(14318184.0); + DEBUG("Set fullspeed - %i\n", cpuspeed2); + pc_set_speed(); + atfullspeed = 1; } - atfullspeed = 1; + + nvr_period_recalc(); } void pc_speed_changed(void) { - if (AT) - setpitclock((float)machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].rspeed); - else - setpitclock(14318184.0); + pc_set_speed(); + + nvr_period_recalc(); } @@ -762,16 +763,11 @@ pc_speed_changed(void) void pc_reload(const wchar_t *fn) { - int i; - config_write(cfg_path); floppy_close(); - for (i=0; iexit(i); - cdrom_close(i); - } + cdrom_close(); pc_reset_hard_close(); @@ -779,27 +775,11 @@ pc_reload(const wchar_t *fn) config_load(); - for (i=0; i= 'A') && (cdrom_drives[i].host_drive <= 'Z')) - ioctl_open(i, cdrom_drives[i].host_drive); - else -#endif - cdrom_null_open(i, cdrom_drives[i].host_drive); - } + zip_hard_reset(); - for (i=0; i= CPU_286) ? 2 : 1; atfullspeed = 0; random_init(); @@ -890,22 +874,24 @@ pc_init(void) joystick_init(); video_init(); - ide_init_first(); - device_init(); timer_reset(); sound_init(); - floppy_init(); +#if 0 + fdd_init(); +#else + floppy_init(); //FIXME: fdd_init() now? +#endif /* FIXME: should be disk_init() */ cdrom_hard_reset(); zip_hard_reset(); - ide_reset_hard(); /* FIXME: should be scsi_init() */ + scsi_disk_hard_reset(); scsi_card_init(); pc_full_speed(); @@ -919,8 +905,6 @@ pc_init(void) void pc_close(thread_t *ptr) { - int i; - /* Wait a while so things can shut down. */ plat_delay_ms(200); @@ -941,15 +925,13 @@ pc_close(thread_t *ptr) config_save(); - plat_mouse_capture(-1); + ui_mouse_capture(0); - for (i = 0; i < ZIP_NUM; i++) - zip_close(i); + zip_close(); - for (i = 0; i < CDROM_NUM; i++) - cdrom_drives[i].handler->exit(i); + scsi_disk_close(); - floppy_close(); +// floppy_close(); if (dump_on_exit) dumppic(); @@ -963,9 +945,7 @@ pc_close(thread_t *ptr) sound_close(); - ide_destroy_buffers(); - - cdrom_destroy_drives(); + cdrom_close(); } @@ -980,6 +960,12 @@ pc_reset_hard_close(void) mouse_close(); + cdrom_close(); + +#if 0 + sound_close(); +#endif + device_close_all(); } @@ -1002,22 +988,18 @@ pc_reset_hard_init(void) parallel_reset(); serial_reset(); - sound_reset(); - speaker_init(); + /* FIXME: these, should be in disk_reset(). */ + cdrom_hard_reset(); + zip_hard_reset(); - /* Initialize the actual machine and its basic modules. */ - machine_init(); - - /* FIXME: move elsewhere? */ - shadowbios = 0; - - /* Reset any ISA memory cards. */ - isamem_reset(); - - /* Reset any ISA RTC cards. */ - isartc_reset(); - - fdd_reset(); + /* + * Reset the actual machine and its basic modules. + * + * Note that on PCI-based machines, this will also reset + * the PCI bus state, so, we MUST reset PCI devices after + * the machine! + */ + machine_reset(); /* * Once the machine has been initialized, all that remains @@ -1027,16 +1009,26 @@ pc_reset_hard_init(void) * For now, we will call their reset functions here, but * that will be a call to device_reset_all() later ! */ +#if 0 + /* FIXME: move elsewhere? */ + shadowbios = 0; +#endif + + /* Reset any ISA memory cards. */ + isamem_reset(); + + /* Reset any ISA RTC cards. */ + isartc_reset(); /* Reset some basic devices. */ mouse_reset(); - video_reset(); + keyboard_reset(); - /* FIXME: these, and hdc_reset, should be in disk_reset(). */ - cdrom_hard_reset(); - zip_hard_reset(); + /* Reset sound system. This MAY add a game port, so before joystick! */ + sound_reset(); - /* Reset the Hard Disk Controller module. */ + /* Reset the Floppy and Hard Disk modules. */ + fdd_reset(); hdc_reset(); /* Reset and reconfigure the SCSI layer. */ @@ -1050,7 +1042,7 @@ pc_reset_hard_init(void) game_update_joystick_type(); if (config_changed) { - ui_sb_update(); + ui_sb_reset(); config_save(); @@ -1062,19 +1054,13 @@ pc_reset_hard_init(void) device_add(&bugger_device); /* Needs the status bar initialized. */ - plat_mouse_capture(-1); + ui_mouse_capture(-1); /* Reset the CPU module. */ - cpu_set(); resetx86(); dma_reset(); pic_reset(); - cpu_cache_int_enabled = cpu_cache_ext_enabled = 0; - - if (AT) - setpitclock((float)machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].rspeed); - else - setpitclock(14318184.0); + pc_set_speed(); } @@ -1090,7 +1076,7 @@ pc_reset_hard(void) void pc_reset(int hard) { - plat_pause(1); + pc_pause(1); plat_delay_ms(100); @@ -1103,9 +1089,9 @@ pc_reset(int hard) if (hard) pc_reset_hard(); else - keyboard_send_cad(); + keyboard_cad(); - plat_pause(0); + pc_pause(0); } @@ -1121,26 +1107,19 @@ pc_thread(void *param) { wchar_t temp[200]; uint64_t start_time, end_time; + int64_t main_time; uint32_t old_time, new_time; - int status_update_needed; + uint32_t clockrate; int done, drawits, frm; int *quitp = (int *)param; - int framecountx; - pclog("PC: starting main thread...\n"); + INFO("PC: starting main thread...\n"); main_time = 0; - framecountx = 0; - status_update_needed = title_update = 1; + title_update = 1; old_time = plat_get_ticks(); done = drawits = frm = 0; while (! *quitp) { - /* Update the Stat(u)s window with the current info. */ - if (status_update_needed) { - dlg_status_update(); - status_update_needed = 0; - } - /* See if it is time to run a frame of code. */ new_time = plat_get_ticks(); drawits += (new_time - old_time); @@ -1154,9 +1133,8 @@ pc_thread(void *param) /* Run a block of code. */ plat_startblit(); - clockrate = machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].rspeed; + clockrate = machine_speed(); -pclog("PC: clockrate=%lu cpuspeed=%lu\n", clockrate, cpuspeed); if (is386) { #ifdef USE_DYNAREC if (cpu_use_dynarec) @@ -1164,7 +1142,7 @@ pclog("PC: clockrate=%lu cpuspeed=%lu\n", clockrate, cpuspeed); else #endif exec386(clockrate/100); - } else if (AT) { + } else if (machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].cpu_type >= CPU_286) { exec386(clockrate/100); } else { execx86(clockrate/100); @@ -1176,64 +1154,9 @@ pclog("PC: clockrate=%lu cpuspeed=%lu\n", clockrate, cpuspeed); plat_endblit(); - /* Done with this frame, update statistics. */ - framecount++; - if (++framecountx >= 100) { - framecountx = 0; - - /* FIXME: all this should go into a "stats" struct! */ - mips = (float)insc/1000000.0f; - insc = 0; - flops = (float)fpucount/1000000.0f; - fpucount = 0; - sreadlnum = readlnum; - swritelnum = writelnum; - segareads = egareads; - segawrites = egawrites; - scycles_lost = cycles_lost; - -#ifdef USE_DYNAREC - cpu_recomp_blocks_latched = cpu_recomp_blocks; - cpu_recomp_ins_latched = cpu_state.cpu_recomp_ins; - cpu_recomp_full_ins_latched = cpu_recomp_full_ins; - cpu_new_blocks_latched = cpu_new_blocks; - cpu_recomp_flushes_latched = cpu_recomp_flushes; - cpu_recomp_evicted_latched = cpu_recomp_evicted; - cpu_recomp_reuse_latched = cpu_recomp_reuse; - cpu_recomp_removed_latched = cpu_recomp_removed; - cpu_reps_latched = cpu_reps; - cpu_notreps_latched = cpu_notreps; - - cpu_recomp_blocks = 0; - cpu_state.cpu_recomp_ins = 0; - cpu_recomp_full_ins = 0; - cpu_new_blocks = 0; - cpu_recomp_flushes = 0; - cpu_recomp_evicted = 0; - cpu_recomp_reuse = 0; - cpu_recomp_removed = 0; - cpu_reps = 0; - cpu_notreps = 0; -#endif - - readlnum = writelnum = 0; - egareads = egawrites = 0; - cycles_lost = 0; - mmuflush = 0; - emu_fps = frm; - frm = 0; - - /* We need a Status window update now. */ - status_update_needed = 1; - } - if (title_update) { swprintf(temp, sizeof_w(temp), -#ifdef _WIN32 - L"%S %S - %i%% - %S - %S", -#else L"%s %s - %i%% - %s - %s", -#endif EMU_NAME,emu_version,fps,machine_getname(), machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].name); ui_window_title(temp); @@ -1242,6 +1165,7 @@ pclog("PC: clockrate=%lu cpuspeed=%lu\n", clockrate, cpuspeed); } /* One more frame done! */ + framecount++; done++; /* Every 200 frames we save the machine status. */ @@ -1266,7 +1190,7 @@ pclog("PC: clockrate=%lu cpuspeed=%lu\n", clockrate, cpuspeed); } } - pclog("PC: main thread done.\n"); + INFO("PC: main thread done.\n"); } @@ -1281,6 +1205,36 @@ pc_onesec(void) } +/* Pause or unpause the emulator. */ +void +pc_pause(int p) +{ + static wchar_t oldtitle[512]; + wchar_t title[512]; + + /* If un-pausing, ask the renderer if that's OK. */ + if (p == 0) + p = vidapi_pause(); + + /* If already so, done. */ + if (dopause == p) return; + + if (p) { + wcscpy(oldtitle, ui_window_title(NULL)); + wcscpy(title, oldtitle); + wcscat(title, L" - PAUSED -"); + ui_window_title(title); + } else { + ui_window_title(oldtitle); + } + + dopause = p; + + /* Update the actual menu item. */ + menu_set_item(IDM_PAUSE, dopause); +} + + void set_screen_size(int x, int y) { @@ -1289,11 +1243,11 @@ set_screen_size(int x, int y) int temp_overscan_x = overscan_x; int temp_overscan_y = overscan_y; double dx, dy, dtx, dty; + int vid; + + DEBUG("SetScreenSize(%d, %d) resize=%d\n", x, y, vid_resize); /* Make sure we keep usable values. */ -#if 0 - pclog("SetScreenSize(%d, %d) resize=%d\n", x, y, vid_resize); -#endif if (x < 320) x = 320; if (y < 200) y = 200; if (x > 2048) x = 2048; @@ -1314,10 +1268,11 @@ set_screen_size(int x, int y) dty = (double)temp_overscan_y; /* Account for possible overscan. */ - if (!(video_is_ega_vga()) && (temp_overscan_y == 16)) { + vid = video_type(); + if ((vid == VID_TYPE_CGA) && (temp_overscan_y == 16)) { /* CGA */ dy = (((dx - dtx) / 4.0) * 3.0) + dty; - } else if (!(video_is_ega_vga()) && (temp_overscan_y < 16)) { + } else if ((vid == VID_MDA) && (temp_overscan_y < 16)) { /* MDA/Hercules */ dy = (x / 4.0) * 3.0; } else { @@ -1371,15 +1326,11 @@ set_screen_size_natural(void) } -int -get_actual_size_x(void) +void +get_screen_size_natural(int *x, int *y) { - return(unscaled_size_x); -} - - -int -get_actual_size_y(void) -{ - return(efscrnsz_y); + if (x != NULL) + *x = unscaled_size_x; + if (y != NULL) + *y = efscrnsz_y; } diff --git a/src/plat.h b/src/plat.h index c1a7aa8..f816b23 100644 --- a/src/plat.h +++ b/src/plat.h @@ -8,7 +8,7 @@ * * Define the various platform support functions. * - * Version: @(#)plat.h 1.0.17 2018/08/31 + * Version: @(#)plat.h 1.0.18 2018/09/29 * * Author: Fred N. van Kempen, * @@ -47,13 +47,13 @@ #ifndef EMU_PLAT_H # define EMU_PLAT_H -#ifndef GLOBAL -# define GLOBAL extern -#endif - /* The Win32 API uses _wcsicmp and _stricmp. */ #ifdef _WIN32 +# ifndef _MSC_VER +# undef swprintf +# define swprintf __swprintf +# endif # define wcsncasecmp _wcsnicmp # define wcscasecmp _wcsicmp # define strncasecmp _strnicmp @@ -85,16 +85,35 @@ #define sizeof_w(x) (sizeof((x)) / sizeof(wchar_t)) +#if defined(_WIN32) && !defined(_MSC_VER) +/* + * MinGW uses the very old Visual Studio 6.0 C runtime (and even ises + * it..) for licensing reasons. All this means, that it has the old + * Microsoft-style string specifiers for wide strings, which predate + * (and are incompatible with) the ISO ones. The (inlined) function + * below, and the #undef above, are to redirect "swprintf" used in + * the code the inlined one, which basically redirects to the ISO + * variant MinGW also provides. Yum! --FvK + */ +static __inline int +__swprintf(wchar_t *__dst, UNUSED(size_t __cnt), const wchar_t *__fmt, ...) \ +{ \ + register int __retval; \ + __builtin_va_list __local_argv; \ + \ + __builtin_va_start( __local_argv, __fmt ); \ + __retval = __mingw_vswprintf( __dst, __fmt, __local_argv ); \ + __builtin_va_end( __local_argv ); \ + \ + return __retval; \ +} +#endif + + #ifdef __cplusplus extern "C" { #endif -/* Define an entry in the strings table. */ -typedef struct { - int id; - const wchar_t *str; -} string_t; - /* Define a "vidapi", or, rather, a Renderer API. */ typedef struct { const char *name; @@ -105,26 +124,19 @@ typedef struct { void (*resize)(int x, int y); int (*pause)(void); void (*screenshot)(const wchar_t *fn); - int (*available)(void); + int (*is_available)(void); } vidapi_t; /* Global variables residing in the platform module. */ -GLOBAL int dopause, /* system is paused */ - doresize, /* screen resize requested */ - quited, /* system exit requested */ - mouse_capture; /* mouse is captured in app */ -GLOBAL uint64_t timer_freq; -GLOBAL int infocus; -GLOBAL const vidapi_t *plat_vidapis[]; -extern const string_t *plat_strings; +extern int quited; /* system exit requested */ +extern const vidapi_t *plat_vidapis[]; /* System-related functions. */ #ifdef _WIN32 extern void plat_console(int on); #endif -extern int plat_set_language(int id); extern wchar_t *fix_emu_path(const wchar_t *str); extern FILE *plat_fopen(const wchar_t *path, const wchar_t *mode); extern void plat_remove(const wchar_t *path); @@ -143,10 +155,14 @@ extern int plat_dir_create(const wchar_t *path); extern uint64_t plat_timer_read(void); extern uint32_t plat_get_ticks(void); extern void plat_delay_ms(uint32_t count); -extern void plat_pause(int p); extern void plat_mouse_capture(int on); -extern void plat_setfullscreen(int on); -extern int plat_fdd_icon(int); +extern int plat_kbd_state(void); +extern void plat_fullscreen(int on); +#ifdef EMU_UI_H +extern const string_t *plat_lang_load(lang_t *ptr); +#endif +extern void plat_lang_scan(void); +extern void plat_lang_set(int id); /* Dynamic Module Loader interface. */ @@ -169,23 +185,19 @@ extern void plat_stop(void); extern uint8_t host_cdrom_drive_available[26]; extern uint8_t host_cdrom_drive_available_num; +#ifdef USE_IOCTL extern void cdrom_init_host_drives(void); -extern void cdrom_eject(uint8_t id); -extern void cdrom_reload(uint8_t id); -extern void zip_eject(uint8_t id); -extern void zip_reload(uint8_t id); -extern void removable_disk_unload(uint8_t id); -extern void removable_disk_eject(uint8_t id); -extern void removable_disk_reload(uint8_t id); extern int ioctl_open(uint8_t id, char d); extern void ioctl_reset(uint8_t id); extern void ioctl_close(uint8_t id); +#endif extern void plat_midi_init(void); extern void plat_midi_close(void); -extern void plat_midi_play_msg(uint8_t *val); -extern void plat_midi_play_sysex(uint8_t *data, unsigned int len); +extern void plat_midi_play_msg(uint8_t *msg); +extern void plat_midi_play_sysex(uint8_t *sysex, unsigned int len); extern int plat_midi_write(uint8_t val); + extern int plat_midi_get_num_devs(); extern void plat_midi_get_dev_name(int num, char *s); diff --git a/src/png.c b/src/png.c index eaa2d7f..035e4a7 100644 --- a/src/png.c +++ b/src/png.c @@ -8,7 +8,7 @@ * * Provide centralized access to the PNG image handler. * - * Version: @(#)png.c 1.0.2 2018/09/02 + * Version: @(#)png.c 1.0.3 2018/10/05 * * Author: Fred N. van Kempen, * @@ -44,20 +44,26 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include #include #include #include #include #include +#include #define PNG_DEBUG 0 #include #include "./png.h" #include "emu.h" -#include "plat.h" +#include "plat.h" +#include "ui/ui.h" +#include "devices/video/video.h" -#define PATH_PNG_DLL "libpng16.dll" +#ifdef _WIN32 +# define PATH_PNG_DLL "libpng16.dll" +#else +# define PATH_PNG_DLL "libpng16.so" +#endif #define USE_CUSTOM_IO 1 @@ -130,14 +136,14 @@ static const dllimp_t png_imports[] = { static void error_handler(png_structp arg, const char *str) { - pclog("PNG: stream 0x%08lx error '%s'\n", arg, str); + ERRLOG("PNG: stream 0x%08lx error '%s'\n", arg, str); } static void warning_handler(png_structp arg, const char *str) { - pclog("PNG: stream 0x%08lx warning '%s'\n", arg, str); + ERRLOG("PNG: stream 0x%08lx warning '%s'\n", arg, str); } @@ -149,7 +155,7 @@ write_handler(png_struct *png_ptr, png_byte *bufp, png_size_t len) FILE *fp = (FILE *)PNGFUNC(get_io_ptr)(png_ptr); if (fwrite(bufp, 1, len, fp) != len) - pclog("PNG: error writing file!\n"); + ERRLOG("PNG: error writing file!\n"); } @@ -168,14 +174,22 @@ flush_handler(png_struct *png_ptr) int png_load(void) { +#if USE_LIBPNG == 2 + wchar_t temp[512]; + const char *fn = PATH_PNG_DLL; +#endif + /* If already loaded, good! */ if (png_handle != NULL) return(1); #if USE_LIBPNG == 2 /* Try loading the DLL. */ - png_handle = dynld_module(PATH_PNG_DLL, png_imports); + png_handle = dynld_module(fn, png_imports); if (png_handle == NULL) { - pclog("PNG: unable to load '%s'; format disabled!\n", PATH_PNG_DLL); + swprintf(temp, sizeof_w(temp), + get_string(IDS_ERR_NOLIB), "PNG", fn); + ui_msgbox(MBX_ERROR, temp); + ERRLOG("PNG: unable to load '%s'; format disabled!\n", fn); return(0); } #else @@ -217,10 +231,10 @@ png_write_gray(const wchar_t *fn, int inv, uint8_t *pix, int16_t w, int16_t h) if (fp == NULL) { /* Yes, this looks weird. */ if (fp == NULL) - pclog("PNG: file %ls could not be opened for writing!\n", fn); + ERRLOG("PNG: file %ls could not be opened for writing!\n", fn); else error: - pclog("PNG: fatal error, bailing out, error = %i\n", errno); + ERRLOG("PNG: fatal error, bailing out, error = %i\n", errno); if (png != NULL) PNGFUNC(destroy_write_struct)(&png, &info); if (fp != NULL) @@ -232,13 +246,13 @@ error: png = PNGFUNC(create_write_struct)(PNG_LIBPNG_VER_STRING, NULL, error_handler, warning_handler); if (png == NULL) { - pclog("PNG: create_write_struct failed!\n"); + ERRLOG("PNG: create_write_struct failed!\n"); goto error; } info = PNGFUNC(create_info_struct)(png); if (info == NULL) { - pclog("PNG: create_info_struct failed!\n"); + ERRLOG("PNG: create_info_struct failed!\n"); goto error; } @@ -271,7 +285,7 @@ error: PNGFUNC(write_info)(png, info); /* Create a buffer for one scanline of pixels. */ - row = (png_bytep)malloc(PNGFUNC(get_rowbytes)(png, info)); + row = (png_bytep)mem_alloc(PNGFUNC(get_rowbytes)(png, info)); /* Process all scanlines in the image. */ for (y = 0; y < h; y++) { @@ -309,6 +323,7 @@ png_write_rgb(const wchar_t *fn, uint8_t *pix, int16_t w, int16_t h) png_infop info = NULL; png_bytepp rows; uint8_t *r, *b; + uint32_t *rgb; FILE *fp; int y, x; @@ -318,7 +333,7 @@ png_write_rgb(const wchar_t *fn, uint8_t *pix, int16_t w, int16_t h) /* Create the image file. */ fp = plat_fopen(fn, L"wb"); if (fp == NULL) { - pclog("PNG: File %ls could not be opened for writing!\n", fn); + ERRLOG("PNG: File %ls could not be opened for writing!\n", fn); error: if (png != NULL) PNGFUNC(destroy_write_struct)(&png, &info); @@ -331,13 +346,13 @@ error: png = PNGFUNC(create_write_struct)(PNG_LIBPNG_VER_STRING, NULL, error_handler, warning_handler); if (png == NULL) { - pclog("PNG: create_write_struct failed!\n"); + ERRLOG("PNG: create_write_struct failed!\n"); goto error; } info = PNGFUNC(create_info_struct)(png); if (info == NULL) { - pclog("PNG: create_info_struct failed!\n"); + ERRLOG("PNG: create_info_struct failed!\n"); goto error; } @@ -362,10 +377,10 @@ error: PNGFUNC(write_info)(png, info); /* Create a buffer for scanlines of pixels. */ - rows = (png_bytepp)malloc(sizeof(png_bytep) * h); + rows = (png_bytepp)mem_alloc(sizeof(png_bytep) * h); for (y = 0; y < h; y++) { /* Create a buffer for this scanline. */ - rows[y] = (png_bytep)malloc(PNGFUNC(get_rowbytes)(png, info)); + rows[y] = (png_bytep)mem_alloc(PNGFUNC(get_rowbytes)(png, info)); } /* @@ -380,6 +395,12 @@ error: /* Get pointer to pixel in bitmap data. */ b = &pix[((y * w) + x) * 4]; + /* Transform if needed. */ + if (vid_grayscale || invert_display) { + rgb = (uint32_t *)b; + *rgb = video_color_transform(*rgb); + } + /* Get pointer to png row data. */ r = &rows[(h - 1) - y][x * 3]; diff --git a/src/random.c b/src/random.c index cb7a57a..09b75b7 100644 --- a/src/random.c +++ b/src/random.c @@ -9,7 +9,7 @@ * A better random number generation, used for floppy weak bits * and network MAC address generation. * - * Version: @(#)random.c 1.0.1 2018/02/14 + * Version: @(#)random.c 1.0.2 2018/10/05 * * Author: Miran Grca, * @@ -36,84 +36,96 @@ #include #include #include -#include -#include +#include "plat.h" #include "random.h" -uint32_t preconst = 0x6ED9EBA1; +static uint32_t preconst = 0x6ed9eba1; -static __inline uint32_t rotl32c (uint32_t x, uint32_t n) +static __inline uint32_t +rotl32c (uint32_t x, uint32_t n) { -#if 0 - assert (n<32); -#endif #ifdef _MSC_VER - return _rotl(x, n); + return _rotl(x, n); #else - return (x<>(-n&31)); + return (x << n) | (x >> (-n & 31)); #endif } -static __inline uint32_t rotr32c (uint32_t x, uint32_t n) + +static __inline uint32_t +rotr32c (uint32_t x, uint32_t n) { -#if 0 - assert (n<32); -#endif #ifdef _MSC_VER - return _rotr(x, n); + return _rotr(x, n); #else - return (x>>n) | (x<<(-n&31)); + return (x >> n) | (x << (-n & 31)); #endif } + #define ROTATE_LEFT rotl32c - #define ROTATE_RIGHT rotr32c -static __inline unsigned long long rdtsc(void) + +#if 0 /* deprecated */ +static __inline unsigned long long +rdtsc(void) { unsigned hi, lo; + #ifdef _MSC_VER __asm { - rdtsc - mov hi, edx ; EDX:EAX is already standard return!! - mov lo, eax + rdtsc + mov hi, edx ; EDX:EAX is already standard return!! + mov lo, eax } #else - __asm__ __volatile__ ("rdtsc" : "=a"(lo), "=d"(hi)); + __asm__ __volatile__ ("rdtsc" : "=a"(lo), "=d"(hi)); #endif + return ( (unsigned long long)lo)|( ((unsigned long long)hi)<<32 ); } -static uint32_t RDTSC(void) + +static uint32_t +RDTSC(void) { - return (uint32_t) (rdtsc()); + return (uint32_t) (rdtsc()); +} +#endif /* deprecated */ + + +static void +random_twist(uint32_t *val) +{ + *val = ROTATE_LEFT(*val, rand() % 32); + *val ^= 0x5a827999; + *val = ROTATE_RIGHT(*val, rand() % 32); + *val ^= 0x4ed32706; } -static void random_twist(uint32_t *val) +uint8_t +random_generate(void) { - *val = ROTATE_LEFT(*val, rand() % 32); - *val ^= 0x5A827999; - *val = ROTATE_RIGHT(*val, rand() % 32); - *val ^= 0x4ED32706; + uint16_t r = 0; + r = (rand() ^ ROTATE_LEFT(preconst, rand() % 32)) % 256; + random_twist(&preconst); + + return (r & 0xff); } -uint8_t random_generate(void) +void +random_init(void) { - uint16_t r = 0; - r = (rand() ^ ROTATE_LEFT(preconst, rand() % 32)) % 256; - random_twist(&preconst); - return (r & 0xff); -} +#if 0 /* deprecated */ + uint32_t seed = RDTSC(); +#else + uint32_t seed = (uint32_t)plat_timer_read(); +#endif - -void random_init(void) -{ - uint32_t seed = RDTSC(); - srand(seed); - return; + srand(seed); } diff --git a/src/rom.c b/src/rom.c index 8aafe9b..a9c883f 100644 --- a/src/rom.c +++ b/src/rom.c @@ -8,7 +8,7 @@ * * Handling of ROM image files. * - * Version: @(#)rom.c 1.0.14 2018/05/04 + * Version: @(#)rom.c 1.0.15 2018/10/05 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -42,8 +42,6 @@ #include #include #include "emu.h" -#include "config.h" -#include "cpu/cpu.h" #include "mem.h" #include "rom.h" #include "plat.h" @@ -80,7 +78,7 @@ rom_present(const wchar_t *fn) return(1); } - pclog("ROM: image for '%ls' not found!\n", fn); + ERRLOG("ROM: image for '%ls' not found!\n", fn); return(0); } @@ -94,7 +92,7 @@ rom_read(uint32_t addr, void *priv) #ifdef ROM_TRACE if (ptr->mapping.base==ROM_TRACE) - pclog("ROM: read byte from BIOS at %06lX\n", addr); + DEBUG("ROM: read byte from BIOS at %06lX\n", addr); #endif return(ptr->rom[addr & ptr->mask]); @@ -109,7 +107,7 @@ rom_readw(uint32_t addr, void *priv) #ifdef ROM_TRACE if (ptr->mapping.base==ROM_TRACE) - pclog("ROM: read word from BIOS at %06lX\n", addr); + DEBUG("ROM: read word from BIOS at %06lX\n", addr); #endif return(*(uint16_t *)&ptr->rom[addr & ptr->mask]); @@ -124,14 +122,14 @@ rom_readl(uint32_t addr, void *priv) #ifdef ROM_TRACE if (ptr->mapping.base==ROM_TRACE) - pclog("ROM: read long from BIOS at %06lX\n", addr); + DEBUG("ROM: read long from BIOS at %06lX\n", addr); #endif return(*(uint32_t *)&ptr->rom[addr & ptr->mask]); } -/* Load a ROM BIOS from its chips, interleaved mode. */ +/* Load a ROM BIOS from its chips, linear mode. */ int rom_load_linear(const wchar_t *fn, uint32_t addr, int sz, int off, uint8_t *ptr) { @@ -139,7 +137,7 @@ rom_load_linear(const wchar_t *fn, uint32_t addr, int sz, int off, uint8_t *ptr) f = plat_fopen(rom_path(fn), L"rb"); if (f == NULL) { - pclog("ROM: image '%ls' not found\n", fn); + ERRLOG("ROM: image '%ls' not found\n", fn); return(0); } @@ -166,9 +164,9 @@ rom_load_interleaved(const wchar_t *fnl, const wchar_t *fnh, uint32_t addr, int int c; if (fl == NULL || fh == NULL) { - if (fl == NULL) pclog("ROM: image '%ls' not found\n", fnl); + if (fl == NULL) ERRLOG("ROM: image '%ls' not found\n", fnl); else (void)fclose(fl); - if (fh == NULL) pclog("ROM: image '%ls' not found\n", fnh); + if (fh == NULL) ERRLOG("ROM: image '%ls' not found\n", fnh); else (void)fclose(fh); return(0); @@ -198,7 +196,7 @@ int rom_init(rom_t *ptr, const wchar_t *fn, uint32_t addr, int sz, int mask, int off, uint32_t fl) { /* Allocate a buffer for the image. */ - ptr->rom = malloc(sz); + ptr->rom = (uint8_t *)mem_alloc(sz); memset(ptr->rom, 0xff, sz); /* Load the image file into the buffer. */ @@ -211,10 +209,10 @@ rom_init(rom_t *ptr, const wchar_t *fn, uint32_t addr, int sz, int mask, int off ptr->mask = mask; - mem_mapping_add(&ptr->mapping, addr, sz, - rom_read, rom_readw, rom_readl, - mem_write_null, mem_write_nullw, mem_write_nulll, - ptr->rom, fl | MEM_MAPPING_ROM, ptr); + mem_map_add(&ptr->mapping, addr, sz, + rom_read, rom_readw, rom_readl, + mem_write_null, mem_write_nullw, mem_write_nulll, + ptr->rom, fl | MEM_MAPPING_ROM, ptr); return(1); } @@ -224,7 +222,7 @@ int rom_init_interleaved(rom_t *ptr, const wchar_t *fnl, const wchar_t *fnh, uint32_t addr, int sz, int mask, int off, uint32_t fl) { /* Allocate a buffer for the image. */ - ptr->rom = malloc(sz); + ptr->rom = (uint8_t *)mem_alloc(sz); memset(ptr->rom, 0xff, sz); /* Load the image file into the buffer. */ @@ -237,10 +235,10 @@ rom_init_interleaved(rom_t *ptr, const wchar_t *fnl, const wchar_t *fnh, uint32_ ptr->mask = mask; - mem_mapping_add(&ptr->mapping, addr, sz, - rom_read, rom_readw, rom_readl, - mem_write_null, mem_write_nullw, mem_write_nulll, - ptr->rom, fl | MEM_MAPPING_ROM, ptr); + mem_map_add(&ptr->mapping, addr, sz, + rom_read, rom_readw, rom_readl, + mem_write_null, mem_write_nullw, mem_write_nulll, + ptr->rom, fl | MEM_MAPPING_ROM, ptr); return(1); } diff --git a/src/rom.h b/src/rom.h index a30cfab..ca02141 100644 --- a/src/rom.h +++ b/src/rom.h @@ -8,7 +8,7 @@ * * Definitions for the ROM image handler. * - * Version: @(#)rom.h 1.0.11 2018/04/12 + * Version: @(#)rom.h 1.0.12 2018/09/11 * * Authors: Fred N. van Kempen, * @@ -52,9 +52,9 @@ typedef struct { - uint8_t *rom; - uint32_t mask; - mem_mapping_t mapping; + uint8_t *rom; + uint32_t mask; + mem_map_t mapping; } rom_t; typedef struct { diff --git a/src/rom_load.c b/src/rom_load.c index c0f7925..9582a24 100644 --- a/src/rom_load.c +++ b/src/rom_load.c @@ -17,7 +17,7 @@ * or to use a generic handler, and then pass it a pointer * to a command table. For now, we don't. * - * Version: @(#)rom_load.c 1.0.12 2018/06/14 + * Version: @(#)rom_load.c 1.0.13 2018/10/05 * * Author: Fred N. van Kempen, * @@ -88,7 +88,7 @@ again: else if (! strcmp(argv[1], "interleaved")) r->mode = 1; else { - pclog("ROM: invalid mode '%s' on line %d.\n", argv[1], ln); + ERRLOG("ROM: invalid mode '%s' on line %d.\n", argv[1], ln); return(0); } } else if (! strcmp(argv[0], "optional")) { @@ -136,7 +136,7 @@ again: mbstowcs(r->vidfn, argv[1], sizeof_w(r->vidfn)); sscanf(argv[2], "%i", &r->vidsz); } else { - pclog("ROM: invalid command '%s' on line %d.\n", argv[0], ln); + ERRLOG("ROM: invalid command '%s' on line %d.\n", argv[0], ln); return(0); } @@ -161,7 +161,7 @@ parser(FILE *fp, romdef_t *r) /* Clear the per-line stuff. */ skipnl = dolit = doquot = 0; doskip = 1; - for (a=0; atotal); - pclog("Offset : 0x%06lx (%lu)\n", r->offset, r->offset); - pclog("Mode : %s\n", (r->mode == 1)?"interleaved":"linear"); - pclog("Files : %d\n", r->nfiles); - for (c=0; cnfiles; c++) { - pclog("%c[%d] : '%ls', %i, 0x%06lx, %i\n", + INFO("Size : %lu\n", r->total); + INFO("Offset : 0x%06lx (%lu)\n", r->offset, r->offset); + INFO("Mode : %s\n", (r->mode == 1)?"interleaved":"linear"); + INFO("Files : %d\n", r->nfiles); + for (c = 0; c < r->nfiles; c++) { + INFO("%c[%d] : '%ls', %i, 0x%06lx, %i\n", (r->files[c].offset==0xffffffff)?'*':' ', c+1, r->files[c].path, r->files[c].skip, r->files[c].offset, r->files[c].size); } if (r->fontnum != -1) - pclog("Font : %i, '%ls'\n", r->fontnum, r->fontfn); + INFO("Font : %i, '%ls'\n", r->fontnum, r->fontfn); if (r->vidsz != 0) - pclog("VideoBIOS: '%ls', %i\n", r->vidfn, r->vidsz); + INFO("VideoBIOS: '%ls', %i\n", r->vidfn, r->vidsz); /* Actually perform the work. */ switch(r->mode) { case 0: /* linear file(s) */ /* We loop on all files. */ - for (c=0; cnfiles; c++) { + for (c = 0; c < r->nfiles; c++) { /* If this is a no-load file, skip. */ if (r->files[c].offset == 0xffffffff) continue; @@ -430,7 +427,7 @@ rom_load_bios(romdef_t *r, const wchar_t *fn, int test_only) case 1: /* interleaved file(s) */ /* We loop on all files. */ - for (c=0; cnfiles/2; c+=2) { + for (c = 0; c < r->nfiles / 2; c += 2) { /* If this is a no-load file, skip. */ if (r->files[c].offset == 0xffffffff) continue; @@ -467,11 +464,12 @@ rom_load_bios(romdef_t *r, const wchar_t *fn, int test_only) pc_path(r->vidfn, sizeof_w(r->vidfn), temp); } - pclog("ROM: status %d, tot %u, mask 0x%06lx\n", + INFO("ROM: status %d, tot %u, mask 0x%06lx\n", i, r->total, biosmask); } - if (! i) pclog("ROM: error in script '%ls'\n", script); + if (! i) + ERRLOG("ROM: error in script '%ls'\n", script); return(i); } diff --git a/src/timer.c b/src/timer.c index 2276781..2d7efdf 100644 --- a/src/timer.c +++ b/src/timer.c @@ -8,7 +8,7 @@ * * System timer module. * - * Version: @(#)timer.c 1.0.1 2018/02/14 + * Version: @(#)timer.c 1.0.2 2018/09/06 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -134,7 +134,6 @@ void timer_update_outstanding(void) void timer_reset(void) { - /* pclog("timer_reset\n"); */ timers_present = 0; timer_latch = timer_count = 0; } diff --git a/src/ui/lang/Extra-EN.txt b/src/ui/lang/Extra.txt similarity index 100% rename from src/ui/lang/Extra-EN.txt rename to src/ui/lang/Extra.txt diff --git a/src/ui/lang/VARCem-BY.str b/src/ui/lang/VARCem-BY.str index 909941e..b16b142 100644 --- a/src/ui/lang/VARCem-BY.str +++ b/src/ui/lang/VARCem-BY.str @@ -8,7 +8,7 @@ * * String definitions for "Belorussian (Belarus)" language. * - * Version: @(#)VARCem-BY.str 1.0.5 2018/09/23 + * Version: @(#)VARCem-BY.str 1.0.5 2018/10/01 * * Authors: paul_met, * Fred N. van Kempen, @@ -46,10 +46,13 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* Do not translate! */ -#define TAG_VERSION 1,0,4 -#define TAG_AUTHOR "paul_met" -#define TAG_EMAIL "paul_met@yandex.ru" +/* Main application strings (2000) - DO NOT TRANSLATE! */ +#define STR_VERSION 1,0,5 +#define STR_AUTHOR "paul_met" +#define STR_EMAIL "paul_met@yandex.ru" +#define STR_NAME "VARCem" +#define STR_TITLE "Virtual ARchaeological Computer EMulator" + /* Messagebox classes (2100.) */ #define STR_2100 "Памылка" @@ -64,27 +67,24 @@ #define STR_2202 "Немагчыма выкарыстоўваць PCap, верагодна ён не ініцыялізаваны" #define STR_2203 "Прылады PCap не знойдзены" #define STR_2204 "Няправільная прылада PCap" -#define STR_2205 "Немагчыма ініцыялізаваць OpenAL, пераканайцеся ў наяўнасці наступнай бібліятэкі\nу вашым каталогу з прыкладаннем:\n\nlibopenal-1.dll" -#define STR_2206 "Немагчыма ініцыялізаваць FluidSynth, пераканайцеся ў наяўнасці наступнай бібліятэкі\nу вашым каталогу з прыкладаннем:\n\nlibfluidsynth.dll" -#define STR_2207 "System out of memory!" +#define STR_2205 "Немагчыма ініцыялізаваць %s, пераканайцеся ў наяўнасці наступнай бібліятэкі\nу вашым каталогу з прыкладаннем:\n\n%s" /* Application error messages (2300.) */ -#define STR_2300 "Немагчыма стварыць bitmap-файл: %s" +#define STR_2300 "System is out of memory!" #define STR_2301 "Не знойдзены падтрымоўваныя вобразы ROM!" #define STR_2302 "Не знойдзена дапушчальная канфігурацыя.\n\nВы хацелі б адкрыць дыялог Налады і стварыць яе??" -#define STR_2303 "Сканфігураваны камп'ютар:\n\n %ls\n\nis недаступны.\n\nАдкрыць дыялог Налады?" -#define STR_2304 "Сканфігураваная відэакарта:\n\n %ls\n\nis недаступная.\n\nАдкрыць дыялог Налады?" -#define STR_2305 "Выбранны рэндэрэр '%S' недаступны. Выкарыстоўваць асноўны?" -#define STR_2306 "ST506 і ESDI дыскаводы CD-ROM ніколі не існавалі" +#define STR_2303 "Сканфігураваны %ls:\n\n %s\n\nнедаступны.\n\nАдкрыць дыялог Налады?" +#define STR_2304 "Выбранны рэндэрэр:\n\n %s\n\nнедаступны. Выкарыстоўваць асноўны?" +#define STR_2305 "You must save your settings first!" +#define STR_2306 "Немагчыма стварыць bitmap-файл: %ls" #define STR_2307 "USB пакуль не падтрымліваецца" -#define STR_2308 "You must save your settings first!" /* Application messages (2400.) */ #define STR_2400 "Вы ўпэўненыя, што жадаеце захаваць гэтыя настаўленні?\n\n(Магчыма, спатрэбіцца перазапуск...)" #define STR_2401 "Змены захаваны, калі ласка, перазапусціце эмулятар!" -#define STR_2402 "Выбраная прылада '% ls' яшчэ знаходзіцца ў працэсе распрацоўкі і можа выклікаць праблемы.\n\nВы ўпэўненыя, што жадаеце яе выкарыстоўваць?" +#define STR_2402 "Выбраная прылада:\n\n %s\n\nяшчэ знаходзіцца ў працэсе распрацоўкі і можа выклікаць праблемы.\n\nВы ўпэўненыя, што жадаеце яе выкарыстоўваць?" #define STR_2403 "Пстрыкніце мышшу для захопу курсора" #define STR_2404 "Націсніце F8+F12 каб вызваліць курсор" #define STR_2405 "Націсніце F8+F12 або сярэднюю кнопку мышы каб вызваліць курсор" @@ -98,11 +98,14 @@ /* UI: common elements (3000.) */ #define STR_OK "Добра" #define STR_CANCEL "Адмяніць" +#define STR_YES "Yes" +#define STR_NO "No" #define STR_CONFIGURE "Наладзіць" #define STR_BROWSE "Агляд.." /* UI: dialog shared strings (3100.) */ #define STR_NONE "Адсутнічае" +#define STR_INTERNAL "Internal" #define STR_DISABLED "Недаступна" #define STR_ENABLED "Даступна" #define STR_OFF "Выкл" @@ -122,7 +125,7 @@ #define STR_DEVCONF_2 "Прылада:" -/* UI: dialog: About (3200.) */ +/* UI dialog: About (3200.) */ #define STR_ABOUT "Аб прыкладанне VARCem.." #define STR_3201 "Аўтары:" #define STR_3202 "Fred N. van Kempen, Miran Grca, Sarah Walker і іншыя.\nПрыкладанне заснавана на кодзе эмулятараў 86Box, PCem, MAME, DOSbox и Qemu" @@ -133,7 +136,7 @@ #define STR_3211 "Аўтары перакладаў з англійскай на іншыя мовы:" /* UI dialog: Status (3225.) */ -#define STR_STATUS "Статус" +/* (Unused now) */ /* UI dialog: Sound Gain (3250.) */ #define STR_SNDGAIN "Узмацненне гуку" @@ -182,23 +185,16 @@ #define STR_3328 "Цыклы чакання:" #define STR_3329 "Памяць:" #define STR_3330 "МБ" -#define STR_3331 "Сінхранізацыя часу" +#define STR_3331 "Сінхранізацыя часу:" #define STR_3332 "Уключыць FPU" #define STR_3333 "Дынамічны рэкампілятар" #define STR_3334 "КБ" #define STR_3335 "па змаўчанні" +#define STR_3336 "Даступна (UTC)" /* UI dialog: Settings (Video, 3350.) */ #define STR_3350 "Відэа:" -#define STR_3351 "Хуткасць відэа:" -#define STR_3352 "Voodoo Graphics" -#define STR_3353 "па змаўчанні" -#define STR_3354 "8-біт" -#define STR_3355 "медленная 16-біт" -#define STR_3356 "высокая 16-біт" -#define STR_3357 "павольная VLB/PCI" -#define STR_3358 "сярэдняя VLB/PCI" -#define STR_3359 "высокая VLB/PCI" +#define STR_3351 "Voodoo Graphics" /* UI dialog: Settings (Input, 3375.) */ #define STR_3375 "Мыш:" @@ -231,8 +227,8 @@ /* UI dialog: Settings (Other Devices, 3475.) */ #define STR_3475 "Кантролер SCSI:" #define STR_3476 "Кантролер HD:" -#define STR_3477 "Трацічны IDE:" -#define STR_3478 "Чацвярцічны IDE:" +#define STR_3477 "Трацічны IDE" +#define STR_3478 "Чацвярцічны IDE" #define STR_3479 "Прылада ISABugger" #define STR_3480 "Карта расширения памяти (ISA)" #define STR_3481 "ISA Clock/RTC карта" @@ -253,10 +249,9 @@ #define STR_3512 "Параметры (вялікі)..." #define STR_3515 "ST506" #define STR_3516 "ESDI" -#define STR_3517 "IDE (PIO-only)" -#define STR_3518 "IDE (PIO+DMA)" -#define STR_3519 "SCSI" -#define STR_3520 "SCSI (здымны)" +#define STR_3517 "IDE" +#define STR_3518 "SCSI" +#define STR_3519 "USB" /* UI dialog: Settings (Add Hard Disk, 3525.) */ #define STR_3525 "Дадаць жорсткі дыск" @@ -287,13 +282,12 @@ #define STR_3577 "Дысководы ZIP:" #define STR_3578 "ZIP 250" #define STR_3579 "Хуткасць" -#define STR_3580 "<Зарэзервавана>" -#define STR_3581 "<Зарэзервавана>" -#define STR_3582 "ATAPI (PIO-only)" -#define STR_3583 "ATAPI (PIO+DMA)" -#define STR_3584 "SCSI" +#define STR_3580 "ATAPI" +#define STR_3581 "SCSI" +#define STR_3582 "USB" -/* UI dialog: status bar (3900.) */ + +/* UI: Status Bar (3900.) */ #define STR_3900 "(пуста)" #define STR_3901 "(хост-дыск %c:)" #define STR_3902 " [Абаронены ад запісу]" @@ -301,6 +295,7 @@ #define STR_3904 "Открыть образ.." #define STR_3905 "Загрузіць папярэдні лад" #define STR_3906 "Выняць" +#define STR_3907 "Паведаміць аб змене дыска" #define STR_3910 "Flopp %i (%s): %ls" #define STR_3911 "Усе вобразы\0*.0??;*.1??;*.360;*.720;*.86f;*.bin;*.cq?;*.dsk;*.flp;*.hdm;*.im?;*.json;*.td0;*.*fd?;*.xdf\0Прасунутыя сектарная вобразы\0*.imd;*.json;*.td0\0Простые секторные вобразы\0*.0??;*.1??;*.360;*.720;*.bin;*.cq?;*.dsk;*.flp;*.hdm;*.im?;*.xdf;*.*fd?\0Вобразы з магнітным патокам\0*.fdi\0Вобразы з бітавым патокам\0*.86f\0Усе файлы\0*.*\0" @@ -308,24 +303,21 @@ #define STR_3913 "Вобразы з бітавым патокам\0*.86f\0" #define STR_3914 "Экспартаваць у 86F.." -#define STR_3920 "CD-ROM %i (%s): %s" +#define STR_3920 "CD-ROM %i (%ls): %ls" #define STR_3921 "Хост-дыск с CD/DVD (%c:)" #define STR_3922 "Вобразы CD-ROM\0*.iso;*.cue\0Усе файлы (*.*)\0*.*\0" #define STR_3923 "Без гуку" -#define STR_3930 "Жорсткі дыск (%s)" +#define STR_3930 "Жорсткі дыск %i (%ls): %ls" -#define STR_3940 "Здымны дыск %i: %ls" -#define STR_3941 "Паведаміць аб змене дыска" - -#define STR_3950 "ZIP %i (%03i): %ls" +#define STR_3950 "ZIP%03i %i (%ls): %ls" #define STR_3951 "Вобразы для дыскаводаў ZIP\0*.im?;*.zdi\0Усе файлы\0*.*\0" #define STR_3952 "Вобразы для дыскаводаў ZIP\0*.im?;*.zdi\0" -#define STR_3960 "Сетка" -#define STR_3970 "Гук" +#define STR_3960 "Сетка (%s)" +#define STR_3970 "Гук (%s)" -/* Menu: Action (4000.) */ +/* UI menu: Action (4000.) */ #define STR_ACTION "Дзеянне" #define STR_4001 "Жорсткая перазагрузка" #define STR_4002 "Ctrl+Alt+Del" @@ -334,25 +326,25 @@ #define STR_4005 "Пауза" #define STR_4006 "Выхад" -/* Menu: View (4010.) */ + +/* UI menu: View (4010.) */ #define STR_VIEW "Від" #define STR_4011 "Змяняны памер акна" #define STR_4012 "Запомніць памер і пазіцыю" #define STR_4013 "Поўнаэкранны рэжым\tCtrl+Alt+PageUP" #define STR_4014 "Выкарыстоўваць правы CTRL як левы ALT" -#define STR_4015 "Абнаўляць абразкі ў панэлі статусу" -/* Menu: View > Renderer */ +/* UI menu: View > Renderer (4020.) */ #define STR_4020 "Рэндэрэр" -/* Menu: View > Window Scale Factor */ +/* UI menu: View > Window Scale Factor (4030.) */ #define STR_4030 "Маштаб акна" #define STR_4031 "0.5x" #define STR_4032 "1x" #define STR_4033 "1.5x" #define STR_4034 "2x" -/* Menu: View > Fullscreen Stretch Mode */ +/* UI menu: View > Fullscreen Stretch Mode (4040.) */ #define STR_4040 "Расцягнуты поўнаэкранны рэжым" #define STR_4041 "Расцягнуць на ўвесь экран" #define STR_4042 "4:3" @@ -360,14 +352,15 @@ #define STR_4044 "Цэлалікавае маштабаванне" #define STR_4045 "Захоўваць бягучы памер" -/* Menu: Display (4050.) */ + +/* UI menu: Display (4050.) */ #define STR_DISPLAY "Дысплей" #define STR_4051 "Інверсны дысплей" #define STR_4052 "Дазволіць Overscan" #define STR_4053 "Ўсталяваць суадносіны бакоў 4:3" #define STR_4054 "Змяніць кантраснасць манахромнага дысплея" -/* Menu: Display > Display Type */ +/* UI menu: Display > Display Type (4060.) */ #define STR_DISPTYPE "Тып дысплея" #define STR_4061 "RGB каляровы" #define STR_4062 "Манахромны" @@ -375,23 +368,26 @@ #define STR_4064 "Зялёнае свячэнне" #define STR_4065 "Белае свячэнне" -/* Menu: Display > Grayscale Conversion Type */ +/* UI menu: Display > Grayscale Conversion Type (4070.) */ #define STR_GRAYSCALE "Тып манахромнай канверсіі" #define STR_4071 "BT601 (NTSC/PAL)" #define STR_4072 "BT709 (HDTV)" #define STR_4073 "Асераднёны" -/* Menu: Tools (4080.) */ + +/* UI menu: Tools (4080.) */ #define STR_TOOLS "Інструменты" #define STR_4081 "Налады" #define STR_4082 "Мова" #define STR_4083 "Уваход" -#define STR_4084 "Загрузіць канфігурацыю" -#define STR_4085 "Захаваць канфігурацыю" -#define STR_4086 "Статус" -#define STR_4087 "Зрабіць здымак\tCtrl+Home" +#define STR_4084 "Log Breakpoint" +#define STR_4085 "Toggle %s logging" +#define STR_4086 "Загрузіць канфігурацыю" +#define STR_4087 "Захаваць канфігурацыю" +#define STR_4088 "Зрабіць здымак" -/* Menu: Help (4090.) */ + +/* UI menu: Help (4090.) */ #define STR_HELP "Дапамога" #define STR_4091 "Аб прыкладанні VARCem" diff --git a/src/ui/lang/VARCem-CZ.str b/src/ui/lang/VARCem-CZ.str index 5721e90..01a5086 100644 --- a/src/ui/lang/VARCem-CZ.str +++ b/src/ui/lang/VARCem-CZ.str @@ -8,7 +8,7 @@ * * String definitions for "Czech (Czech Republic)" language. * - * Version: @(#)VARCem-CZ.str 1.0.4 2018/09/23 + * Version: @(#)VARCem-CZ.str 1.0.5 2018/10/01 * * Authors: David Hrdlička, * Fred N. van Kempen, @@ -47,10 +47,13 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* Do not translate! */ -#define TAG_VERSION 1,0,3 -#define TAG_AUTHOR "David Hrdlička" -#define TAG_EMAIL "hrdlickadavid@outlook.com" +/* Main application strings (2000) - DO NOT TRANSLATE! */ +#define STR_VERSION 1,0,4 +#define STR_AUTHOR "David Hrdlička" +#define STR_EMAIL "hrdlickadavid@outlook.com" +#define STR_NAME "VARCem" +#define STR_TITLE "Virtual ARchaeological Computer EMulator" + /* Messagebox classes (2100.) */ #define STR_2100 "Chyba" @@ -65,27 +68,24 @@ #define STR_2202 "PCap failed to set up because it may not be initialized" #define STR_2203 "Nebyla nalezena žádná PCap zařízení." #define STR_2204 "Neplatné PCap zařížení" -#define STR_2205 "Nebylo možné načíst OpenAL. Ověřte, zda je následující soubor\nve složce s programem:\n\nlibopenal-1.dll" -#define STR_2206 "Nebylo možné načíst FluidSynth. Ověřte, zda je následující soubor\nve složce s programem:\n\nlibfluidsynth.dll" -#define STR_2207 "System out of memory!" +#define STR_2205 "Nebylo možné načíst %s. Ověřte, zda je následující soubor\nve složce s programem:\n\n%s" /* Application error messages (2300.) */ -#define STR_2300 "Chyba při vytváření rastrového obrázku: %s" +#define STR_2300 "System is out of memory!" #define STR_2301 "Nebyly nalezeny žádné použitelné ROM obrazy." #define STR_2302 "Nebyla nalezena žádná platná konfigurace.\n\nWould you like to enter the Settings dialog to create one?" -#define STR_2303 "Použitá základní deska:\n\n %ls\n\nnení dostupná.\n\nChcete otevřít Nastavení?" -#define STR_2304 "Použitá grafická karta:\n\n %ls\n\nnení dostupná.\n\nChcete otevřít Nastavení?" -#define STR_2305 "Zvolený renderer '%S' není dostupný. Chcete použít výchozí renderer?" -#define STR_2306 "CD-ROM jednotky pro ST506 a ESDI nikdy neexistovaly." +#define STR_2303 "Použitá %ls:\n\n %s\n\nnení dostupná.\n\nChcete otevřít Nastavení?" +#define STR_2304 "Zvolený renderer:\n\n %s\n\nnení dostupný. Chcete použít výchozí renderer?" +#define STR_2305 "You must save your settings first!" +#define STR_2306 "Chyba při vytváření rastrového obrázku: %ls" #define STR_2307 "USB není zatím podporováno." -#define STR_2308 "You must save your settings first!" /* Application messages (2400.) */ #define STR_2400 "Opravdu chcete uložit toto nastavení?\n\n(Může vyžadovat restart.)" #define STR_2401 "Změny byly uloženy, nyní prosím restartujte emulátor." -#define STR_2402 "Podpora zvoleného zařízení '%ls' ve VARCem je nedokončená a toto zařízení tak může způsobovat potíže.\n\nOpravdu jej chcete povolit?" +#define STR_2402 "Podpora zvoleného zařízení:\n\n %s\n\nve VARCem je nedokončená a toto zařízení tak může způsobovat potíže.\n\nOpravdu jej chcete povolit?" #define STR_2403 "Klikněte pro zachycení kurzoru" #define STR_2404 "Stiskněte F8+F12 pro uvolnění kurzoru" #define STR_2405 "Stiskněte F8+F12 nebo prostřední tlačítko myši pro uvolnění kurzoru" @@ -99,11 +99,15 @@ /* UI: common elements (3000.) */ #define STR_OK "OK" #define STR_CANCEL "Storno" +#define STR_YES "Yes" +#define STR_NO "No" #define STR_CONFIGURE "Nastavit" #define STR_BROWSE "Procházet..." + /* UI: dialog shared strings (3100.) */ #define STR_NONE "Žádný" +#define STR_INTERNAL "Internal" #define STR_DISABLED "Povoleno" #define STR_ENABLED "Nepovoleno" #define STR_OFF "Zapnuto" @@ -123,19 +127,19 @@ #define STR_DEVCONF_2 "Zařízení:" -/* UI: dialog: About (3200.) */ +/* UI dialog: About (3200.) */ #define STR_ABOUT "O VARCem.." #define STR_3201 "Autoři:" #define STR_3202 "Fred N. van Kempen, Miran Grca, Sarah Walker a další.\nZaloženo na předešlých pracích, jako je 86Box, PCem, MAME, DOSbox nebo Qemu." #define STR_3203 "Vydáno pod tříbodovou licencí BSD a Obecnou veřejnou licencí GNU (verze 2 nebo vyšší) pro již existující kód vložený z jiných projektů." #define STR_3204 "Pro další informace viz LICENSE.txt." -/* UI: dialog: Localization (3210.) */ +/* UI dialog: Localization (3210.) */ #define STR_LOCALIZE "Lokalizace" #define STR_3211 "Překlady z angličtiny do těchto dalších jazyků byly poskytnuty:" /* UI dialog: Status (3225.) */ -#define STR_STATUS "Status" +/* (Unused now) */ /* UI dialog: Sound Gain (3250.) */ #define STR_SNDGAIN "Sound Gain" @@ -184,23 +188,16 @@ #define STR_3328 "Čekací stavy:" #define STR_3329 "Pamět:" #define STR_3330 "MB" -#define STR_3331 "Povolit synchronizaci času mezi hostem a hostitelem" +#define STR_3331 "Povolit synchronizaci času mezi hostem a hostitelem:" #define STR_3332 "Povolit matematický koprocesor (FPU)" #define STR_3333 "Povolit dynamickou rekompilaci" #define STR_3334 "KB" #define STR_3335 "Výchozí" +#define STR_3336 "Nepovoleno (UTC)" /* UI dialog: Settings (Video, 3350.) */ #define STR_3350 "Grafická karta:" -#define STR_3351 "Rychlost:" -#define STR_3352 "Voodoo Graphics" -#define STR_3353 "Výchozí" -#define STR_3354 "8-bit" -#define STR_3355 "Slow 16-bit" -#define STR_3356 "Fast 16-bit" -#define STR_3357 "Slow VLB/PCI" -#define STR_3358 "Mid VLB/PCI" -#define STR_3359 "Fast VLB/PCI" +#define STR_3351 "Voodoo Graphics" /* UI dialog: Settings (Input, 3375.) */ #define STR_3375 "Myš:" @@ -233,8 +230,8 @@ /* UI dialog: Settings (Other Devices, 3475.) */ #define STR_3475 "Řadič SCSI:" #define STR_3476 "Řadič pevného disku:" -#define STR_3477 "Terciární IDE:" -#define STR_3478 "Kvartérní IDE:" +#define STR_3477 "Terciární IDE" +#define STR_3478 "Kvartérní IDE" #define STR_3479 "Zařízení ISABugger" #define STR_3480 "ISA Memory Expansion" #define STR_3481 "ISA Clock/RTC Card" @@ -255,11 +252,9 @@ #define STR_3512 "Vlastní (velký)..." #define STR_3515 "ST506" #define STR_3516 "ESDI" -#define STR_3517 "IDE (pouze PIO)" -#define STR_3518 "IDE (PIO a DMA)" -#define STR_3519 "SCSI" -#define STR_3520 "SCSI (vyměnitelný)" -#define STR_3521 "USB" +#define STR_3517 "IDE" +#define STR_3518 "SCSI" +#define STR_3519 "USB" /* UI dialog: Settings (Add Hard Disk, 3525.) */ #define STR_3525 "Přidat pevný disk" @@ -290,14 +285,12 @@ #define STR_3577 "Jednotky ZIP:" #define STR_3578 "ZIP 250" #define STR_3579 "Rychlost" -#define STR_3580 "" -#define STR_3581 "" -#define STR_3582 "ATAPI (pouze PIO)" -#define STR_3583 "ATAPI (PIO a DMA)" -#define STR_3584 "SCSI" -#define STR_3585 "USB" +#define STR_3580 "ATAPI" +#define STR_3581 "SCSI" +#define STR_3582 "USB" -/* UI dialog: status bar (3900.) */ + +/* UI: Status Bar (3900.) */ #define STR_3900 "(prázdné)" #define STR_3901 "(hostitelská jednotka %c:)" #define STR_3902 " [Chráněno proti zápisu]" @@ -305,6 +298,7 @@ #define STR_3904 "N&ačíst obraz..." #define STR_3905 "&Znovu načíst předchozí obraz" #define STR_3906 "&Vyjmout" +#define STR_3907 "&Notify disk change" #define STR_3910 "Disketa %i (%s): %ls" #define STR_3911 "Všechny obrazy\0*.0??;*.1??;*.360;*.720;*.86f;*.bin;*.cq?;*.dsk;*.flp;*.hdm;*.im?;*.json;*.td0;*.*fd?;*.xdf\0Pokročilé sektorové obrazy\0*.imd;*.json;*.td0\0Základní sektorové obrazy\0*.0??;*.1??;*.360;*.720;*.bin;*.cq?;*.dsk;*.flp;*.hdm;*.im?;*.xdf;*.*fd?\0Obrazy magnetického toku\0*.fdi\0Obrazy povrchu\0*.86f\0Všechny soubory\0*.*\0" @@ -312,24 +306,21 @@ #define STR_3913 "Obrazy povrchu\0*.86f\0" #define STR_3914 "E&xportovat do 86F..." -#define STR_3920 "CD-ROM %i (%s): %s" +#define STR_3920 "CD-ROM %i (%ls): %ls" #define STR_3921 "Hostitelská jednotka CD/DVD (%c:)" #define STR_3922 "Obrazy CD-ROM\0*.iso;*.cue\0Všechny soubory (*.*)\0*.*\0" #define STR_3923 "&Mute" -#define STR_3930 "Pevný disk (%s)" +#define STR_3930 "Pevný disk %i (%ls): %ls" -#define STR_3940 "Vyměnitelný disk %i: %ls" -#define STR_3941 "&Notify disk change" - -#define STR_3950 "ZIP %i (%03i): %ls" +#define STR_3950 "ZIP%03i %i (%ls): %ls" #define STR_3951 "Obrazy ZIP\0*.im?;*.zdi\0All files\0*.*\0" #define STR_3952 "Obrazy ZIP\0*.im?;*.zdi\0" -#define STR_3960 "Síť" -#define STR_3970 "Zvuk" +#define STR_3960 "Síť (%s)" +#define STR_3970 "Zvuk (%s)" -/* Menu: Action (4000.) */ +/* UI menu: Action (4000.) */ #define STR_ACTION "&Akce" #define STR_4001 "&Tvrdý reset" #define STR_4002 "&Ctrl+Alt+Del" @@ -338,25 +329,25 @@ #define STR_4005 "&Pozastavit" #define STR_4006 "&Ukončit" -/* Menu: View (4010.) */ + +/* UI menu: View (4010.) */ #define STR_VIEW "&Zobrazit" #define STR_4011 "&Změnitelná velikost okna" #define STR_4012 "P&amatovat si velikost a pozici okna" #define STR_4013 "&Celá obrazovka\tCtrl+Alt+Page Up" #define STR_4014 "&Pravý Ctrl je levý Alt" -#define STR_4015 "A&ktualizovat ikony v stavovém řádku" -/* Menu: View > Renderer */ +/* UI menu: View > Renderer (4020.) */ #define STR_4020 "Re&nderer" -/* Menu: View > Window Scale Factor */ +/* UI menu: View > Window Scale Factor (4030.) */ #define STR_4030 "&Násobek zvětšení okna" #define STR_4031 "&0.5x" #define STR_4032 "&1x" #define STR_4033 "1.&5x" #define STR_4034 "&2x" -/* Menu: View > Fullscreen Stretch Mode */ +/* UI menu: View > Fullscreen Stretch Mode (4040.) */ #define STR_4040 "Fullscreen &stretch mode" #define STR_4041 "&Full screen stretch" #define STR_4042 "&4:3" @@ -364,14 +355,15 @@ #define STR_4044 "&Integer scale" #define STR_4045 "&Keep size" -/* Menu: Display (4050.) */ + +/* UI menu: Display (4050.) */ #define STR_DISPLAY "&Displej" #define STR_4051 "&Invertovaný displej" #define STR_4052 "P&ovolit přesahy" #define STR_4053 "&Vnutit poměr stran 4:3" #define STR_4054 "Změnit &kontrast jednobarevného displeje" -/* Menu: Display > Display Type */ +/* UI menu: Display > Display Type (4060.) */ #define STR_DISPTYPE "&Typ displeje" #define STR_4061 "&Barevný RGB monitor" #define STR_4062 "Č&ernobílý monitor" @@ -379,23 +371,26 @@ #define STR_4064 "&Zelený monitor" #define STR_4065 "&Bílý monitor" -/* Menu: Display > Grayscale Conversion Type */ +/* UI menu: Display > Grayscale Conversion Type (4070.) */ #define STR_GRAYSCALE "Typ konverze &do odstínů šedi" #define STR_4071 "BT&601 (NTSC/PAL)" #define STR_4072 "BT&709 (HDTV)" #define STR_4073 "&Average" -/* Menu: Tools (4080.) */ + +/* UI menu: Tools (4080.) */ #define STR_TOOLS "&Nástroje" #define STR_4081 "&Nastavení" #define STR_4082 "&Jazyk" #define STR_4083 "Pr&otokolování" -#define STR_4084 "Načíst &konfiguraci" -#define STR_4085 "&Uložit konfiguraci" -#define STR_4086 "Stat&us" -#define STR_4087 "&Pořídit screenshott\tCtrl+Home" +#define STR_4084 "Log Breakpoint" +#define STR_4085 "Toggle %s logging" +#define STR_4086 "Načíst &konfiguraci" +#define STR_4087 "&Uložit konfiguraci" +#define STR_4088 "&Pořídit screenshott" -/* Menu: Help (4090.) */ + +/* UI menu: Help (4090.) */ #define STR_HELP "Ná&pověda" #define STR_4091 "&O VARCem" diff --git a/src/ui/lang/VARCem-DE.str b/src/ui/lang/VARCem-DE.str index 6484f4c..b96883b 100644 --- a/src/ui/lang/VARCem-DE.str +++ b/src/ui/lang/VARCem-DE.str @@ -8,7 +8,7 @@ * * String definitions for "German (Germany)" language. * - * Version: @(#)VARCem-DE.str 1.0.11 2018/09/23 + * Version: @(#)VARCem-DE.str 1.0.13 2018/10/01 * * Authors: Michael Drüing, * Fred N. van Kempen, @@ -47,10 +47,13 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* Do not translate! */ -#define TAG_VERSION 1,0,11 -#define TAG_AUTHOR "Michael Drüing" -#define TAG_EMAIL "michael@drueing.de" +/* Main application strings (2000) - DO NOT TRANSLATE! */ +#define STR_VERSION 1,0,12 +#define STR_AUTHOR "Michael Drüing" +#define STR_EMAIL "michael@drueing.de" +#define STR_NAME "VARCem" +#define STR_TITLE "Virtual ARchaeological Computer EMulator" + /* Messagebox classes (2100.) */ #define STR_2100 "Fehler" @@ -65,27 +68,24 @@ #define STR_2202 "PCap konnte nicht gestartet werden, da es eventuell nicht initialisiert ist." #define STR_2203 "Keine PCap-fähigen Geräte gefunden" #define STR_2204 "Ungültiges PCap-Gerät" -#define STR_2205 "OpenAL konnte nicht initialisiert werden, bitte stellen Sie sicher, dass sich die\nfolgende Laufzeitbibliothek in Ihrem Programmordner befindet:\n\nlibopenal-1.dll" -#define STR_2206 "FluidSynth konnte nicht initialisiert werden, bitte stellen Sie sicher, dass sich die\nfolgende Laufzeitbibliothek in Ihrem Programmordner befindet:\n\nlibfluidsynth.dll" -#define STR_2207 "Nicht genügend Hauptspeicher!" +#define STR_2205 "%s konnte nicht initialisiert werden, bitte stellen Sie sicher, dass sich die\nfolgende Laufzeitbibliothek in Ihrem Programmordner befindet:\n\n%s" /* Application error messages (2300.) */ -#define STR_2300 "Konnte Bitmap nicht erstellen: %s" +#define STR_2300 "Nicht genügend Hauptspeicher!" #define STR_2301 "Keine verwendbaren ROM Abbilder gefunden!" #define STR_2302 "Keine gültige Konfiguration gefunden.\n\nMöchten Sie den Einstellungsdialog öffnen, um eine zu erstellen?" -#define STR_2303 "Die konfigurierte Maschine:\n\n %ls\n\nist nicht verfügbar.\n\nMöchten Sie den Einstellungsdialog öffnen?" -#define STR_2304 "Die konfigurierte Grafikkarte:\n\n %ls\n\nist nicht verfügbar.\n\nMöchten Sie den Einstellungsdialog öffnen?" -#define STR_2305 "Gewählter Anzeigetreiber '%S' nicht verfügbar. Auf Standard zurücksetzen?" -#define STR_2306 "Es gab nie ST506 oder ESDI CD-ROM Laufwerke" +#define STR_2303 "Die konfigurierte %ls:\n\n %s\n\nist nicht verfügbar.\n\nMöchten Sie den Einstellungsdialog öffnen?" +#define STR_2304 "Gewählter Anzeigetreiber:\n\n %s\n\nnicht verfügbar. Auf Standard zurücksetzen?" +#define STR_2305 "Die Einstellungen müssen erst gespeichert werden!" +#define STR_2306 "Konnte Bitmap nicht erstellen: %ls" #define STR_2307 "USB wird noch nicht unterstützt" -#define STR_2308 "Die Einstellungen müssen erst gespeichert werden!" /* Application messages (2400.) */ #define STR_2400 "Sind Sie sicher dass Sie die Einstellungen speichern möchten?\n\n(Benötigt eventuell einen Neustart...)" #define STR_2401 "Änderungen gespeichert, bitte starten Sie den Emulator neu!" -#define STR_2402 "Das angeforderte Gerät '%ls' wird momentan als `In Entwicklung` geführt und kann Probleme verursachen.\n\nSind Sie sicher, dass Sie es aktivieren möchten?" +#define STR_2402 "Das angeforderte Gerät:\n\n %s\n\nwird momentan als `In Entwicklung` geführt und kann Probleme verursachen.\n\nSind Sie sicher, dass Sie es aktivieren möchten?" #define STR_2403 "Klicken, um den Mauszeiger zu erfassen" #define STR_2404 "F8+F12 drücken, um die Maus freizugeben" #define STR_2405 "F8+F12 oder mittleren Mausknopf drücken, um die Maus freizugeben" @@ -98,6 +98,8 @@ /* UI: common elements (3000.) */ #define STR_OK "OK" +#define STR_YES "Ja" +#define STR_NO "Nein" #define STR_CANCEL "Abbruch" #define STR_CONFIGURE "Konfigurieren" #define STR_BROWSE "Auswählen" @@ -105,14 +107,15 @@ /* UI: dialog shared strings (3100.) */ #define STR_NONE "Kein" +#define STR_INTERNAL "Intern" #define STR_DISABLED "Deaktiviert" #define STR_ENABLED "Aktiviert" -#define STR_OFF "Aus" -#define STR_ON "An" +#define STR_OFF "Aus" +#define STR_ON "An" #define STR_TYPE "Typ" #define STR_FILENAME "Dateiname:" #define STR_PROGRESS "Fortschritt:" -#define STR_BUS "Bus:" +#define STR_BUS "Bus:" #define STR_CHANNEL "Kanal:" #define STR_ID "ID:" #define STR_LUN "LUN:" @@ -124,7 +127,7 @@ #define STR_DEVCONF_2 "Gerät:" -/* UI: dialog: About (3200.) */ +/* UI dialog: About (3200.) */ #define STR_ABOUT "Über VARCem.." #define STR_3201 "Autoren:" #define STR_3202 "Fred N. van Kempen, Miran Grca, Sarah Walker und andere.\nBasiert auf früheren Projekten wie 86Box, PCem, MAME, DOSbox und Qemu." @@ -132,188 +135,178 @@ #define STR_3204 "Lesen Sie die Datei LICENSE.txt für weitere Informationen." -/* UI: dialog: Localization (3210.) */ +/* UI dialog: Localization (3210.) */ #define STR_LOCALIZE "Lokalisierung" #define STR_3211 "Übersetzung aus dem Englischen in die folgenden Sprachen beigesteuert von:" /* UI dialog: Status (3225.) */ -#define STR_STATUS "Status" +/* (Unused now) */ /* UI dialog: Sound Gain (3250.) */ #define STR_SNDGAIN "Sound-Verstärkung" -#define STR_3251 "Verstärkung" +#define STR_3251 "Verstärkung" /* UI dialog: New Image (3275.) */ #define STR_NEWIMG "Neues Diskettenabbild" -#define STR_3276 "Diskettengröße:" -#define STR_3277 "Modus für Umdrehungsgeschwindigkeit:" -#define STR_3278 "Exakte U/min" -#define STR_3279 "1% langsamere U/min" -#define STR_3280 "1,5% langsamere U/min" -#define STR_3281 "2% langsamere U/min" -#define STR_3282 "160 KB" -#define STR_3283 "180 KB" -#define STR_3284 "320 KB" -#define STR_3285 "360 KB" -#define STR_3286 "640 KB" -#define STR_3287 "720 KB" -#define STR_3288 "1.2 MB" -#define STR_3289 "1.25 MB" -#define STR_3290 "1.44 MB" -#define STR_3291 "DMF (1KB Cluster)" -#define STR_3292 "DMF (2KB Cluster)" -#define STR_3293 "2.88 MB" -#define STR_3294 "ZIP 100" -#define STR_3295 "ZIP 250" +#define STR_3276 "Diskettengröße:" +#define STR_3277 "Modus für Umdrehungsgeschwindigkeit:" +#define STR_3278 "Exakte U/min" +#define STR_3279 "1% langsamere U/min" +#define STR_3280 "1,5% langsamere U/min" +#define STR_3281 "2% langsamere U/min" +#define STR_3282 "160 KB" +#define STR_3283 "180 KB" +#define STR_3284 "320 KB" +#define STR_3285 "360 KB" +#define STR_3286 "640 KB" +#define STR_3287 "720 KB" +#define STR_3288 "1.2 MB" +#define STR_3289 "1.25 MB" +#define STR_3290 "1.44 MB" +#define STR_3291 "DMF (1KB Cluster)" +#define STR_3292 "DMF (2KB Cluster)" +#define STR_3293 "2.88 MB" +#define STR_3294 "ZIP 100" +#define STR_3295 "ZIP 250" /* UI dialog: Settings (3300.) */ #define STR_SETTINGS "Einstellungen" -#define STR_3310 "Maschine" -#define STR_3311 "Anzeige" -#define STR_3312 "Eingabegeräte" -#define STR_3313 "Sound" -#define STR_3314 "Netzwerk" -#define STR_3315 "Ports (COM & LPT)" -#define STR_3316 "Andere Peripherie" -#define STR_3317 "Festplatten" -#define STR_3318 "Diskettenlaufwerke" -#define STR_3319 "Andere Wechselmedien" +#define STR_3310 "Maschine" +#define STR_3311 "Anzeige" +#define STR_3312 "Eingabegeräte" +#define STR_3313 "Sound" +#define STR_3314 "Netzwerk" +#define STR_3315 "Ports (COM & LPT)" +#define STR_3316 "Andere Peripherie" +#define STR_3317 "Festplatten" +#define STR_3318 "Diskettenlaufwerke" +#define STR_3319 "Andere Wechselmedien" /* UI dialog: Settings (Machine, 3325.) */ -#define STR_3325 "Maschine:" -#define STR_3326 "CPU Typ:" -#define STR_3327 "CPU:" -#define STR_3328 "Waitstates:" -#define STR_3329 "Speicher:" -#define STR_3330 "MB" -#define STR_3331 "Zeitsynchronisation" -#define STR_3332 "Mathematischer Koprozessor" -#define STR_3333 "Dynamischer Recompiler" -#define STR_3334 "KB" -#define STR_3335 "Standard" +#define STR_3325 "Maschine:" +#define STR_3326 "CPU Typ:" +#define STR_3327 "CPU:" +#define STR_3328 "Waitstates:" +#define STR_3329 "Speicher:" +#define STR_3330 "MB" +#define STR_3331 "Zeitsynchronisation:" +#define STR_3332 "Mathematischer Koprozessor" +#define STR_3333 "Dynamischer Recompiler" +#define STR_3334 "KB" +#define STR_3335 "Standard" +#define STR_3336 "Aktiviert (UTC)" /* UI dialog: Settings (Video, 3350.) */ -#define STR_3350 "Grafikkarte:" -#define STR_3351 "Grafikgeschwindigkeit:" -#define STR_3352 "Voodoo Grafikkarte" -#define STR_3353 "Standard" -#define STR_3354 "8-bit" -#define STR_3355 "16-bit, langsam" -#define STR_3356 "16-bit, schnell" -#define STR_3357 "VLB/PCI, langsam" -#define STR_3358 "VLB/PCI, mittel" -#define STR_3359 "VLB/PCI, schnell" +#define STR_3350 "Grafikkarte:" +#define STR_3351 "Voodoo Grafikkarte" /* UI dialog: Settings (Input, 3375.) */ -#define STR_3375 "Maus:" -#define STR_3376 "Joystick:" -#define STR_3377 "Joystick 1" -#define STR_3378 "Joystick 2" -#define STR_3379 "Joystick 3" -#define STR_3380 "Joystick 4" +#define STR_3375 "Maus:" +#define STR_3376 "Joystick:" +#define STR_3377 "Joystick 1" +#define STR_3378 "Joystick 2" +#define STR_3379 "Joystick 3" +#define STR_3380 "Joystick 4" /* UI dialog: Settings (Sound, 3400.) */ -#define STR_3400 "Soundkarte:" -#define STR_3401 "MIDI Ausgabegerät:" -#define STR_3402 "Eigenständiges MPU-401" -#define STR_3403 "Nuked OPL benutzen" -#define STR_3404 "FLOAT32 Soundausgabe benutzen" +#define STR_3400 "Soundkarte:" +#define STR_3401 "MIDI Ausgabegerät:" +#define STR_3402 "Eigenständiges MPU-401" +#define STR_3403 "Nuked OPL benutzen" +#define STR_3404 "FLOAT32 Soundausgabe benutzen" /* UI dialog: Settings (Network, 3425.) */ -#define STR_3425 "Netzwerktyp:" +#define STR_3425 "Netzwerktyp:" #define STR_3426 "PCap Gerät:" -#define STR_3427 "Netzwerkadapter:" +#define STR_3427 "Netzwerkadapter:" /* UI dialog: Settings (Ports, 3450.) */ -#define STR_3450 "Gameport" -#define STR_3451 "Parallelport 1" -#define STR_3452 "Parallelport 2" -#define STR_3453 "Parallelport 3" -#define STR_3454 "Serieller Port 1" -#define STR_3455 "Serieller Port 2" +#define STR_3450 "Gameport" +#define STR_3451 "Parallelport 1" +#define STR_3452 "Parallelport 2" +#define STR_3453 "Parallelport 3" +#define STR_3454 "Serieller Port 1" +#define STR_3455 "Serieller Port 2" /* UI dialog: Settings (Other Devices, 3475.) */ -#define STR_3475 "SCSI Controller:" -#define STR_3476 "HD Controller:" -#define STR_3477 "Dritter IDE Bus:" -#define STR_3478 "Vierter IDE Bus:" -#define STR_3479 "ISABugger Gerät" -#define STR_3480 "ISA Speichererweiterung" -#define STR_3481 "ISA Echtzeituhr-Karte (RTC)" +#define STR_3475 "SCSI Controller:" +#define STR_3476 "HD Controller:" +#define STR_3477 "Dritter IDE Bus" +#define STR_3478 "Vierter IDE Bus" +#define STR_3479 "ISABugger Gerät" +#define STR_3480 "ISA Speichererweiterung" +#define STR_3481 "ISA Echtzeituhr-Karte (RTC)" /* UI dialog: Settings (Hard Disks, 3500.) */ -#define STR_3500 "Festplatten:" -#define STR_3501 "&Neu.." -#define STR_3502 "&Vorhandene.." -#define STR_3503 "&Entfernen" -#define STR_3504 "Bus" -#define STR_3505 "Datei" -#define STR_3506 "C" -#define STR_3507 "H" -#define STR_3508 "S" -#define STR_3509 "MB" -#define STR_3510 "MB (CHS: %u, %u, %u)" -#define STR_3511 "Benutzerdefiniert..." -#define STR_3512 "Benutzerdefiniert (groß)..." -#define STR_3515 "ST506" -#define STR_3516 "ESDI" -#define STR_3517 "IDE (nur PIO)" -#define STR_3518 "IDE (PIO und DMA)" -#define STR_3519 "SCSI" -#define STR_3520 "SCSI (Wechselmedium)" +#define STR_3500 "Festplatten:" +#define STR_3501 "&Neu.." +#define STR_3502 "&Vorhandene.." +#define STR_3503 "&Entfernen" +#define STR_3504 "Bus" +#define STR_3505 "Datei" +#define STR_3506 "C" +#define STR_3507 "H" +#define STR_3508 "S" +#define STR_3509 "MB" +#define STR_3510 "MB (CHS: %u, %u, %u)" +#define STR_3511 "Benutzerdefiniert..." +#define STR_3512 "Benutzerdefiniert (groß)..." +#define STR_3515 "ST506" +#define STR_3516 "ESDI" +#define STR_3517 "IDE" +#define STR_3518 "SCSI" +#define STR_3519 "USB" /* UI dialog: Settings (Add Hard Disk, 3525.) */ -#define STR_3525 "Festplatte hinzufügen" -#define STR_3526 "Neue Festplatte hinzufügen" -#define STR_3527 "Vorhandene Festplatte hinzufügen" -#define STR_3528 "Zylinder:" -#define STR_3529 "Köpfe:" -#define STR_3530 "Sektoren:" -#define STR_3531 "Größe (MB):" -#define STR_3532 "Typ:" -#define STR_3533 "HDI Abbilder können nicht größer als 4 GB sein" -#define STR_3534 "Sie haben versucht, eine unverhältnismäßig große Festplatte anzulegen" -#define STR_3535 "HDI oder HDX Abbilder mit einer Sektorgröße ungleich 512 Bytes wird nicht unterstützt" -#define STR_3536 "Festplattenabbilder\0*.hd?;*.im?;*.vhd\0Alle Dateien\0*.*\0" -#define STR_3537 "Denken Sie daran, die neue Festplatte zu partitionieren und zu formatieren" +#define STR_3525 "Festplatte hinzufügen" +#define STR_3526 "Neue Festplatte hinzufügen" +#define STR_3527 "Vorhandene Festplatte hinzufügen" +#define STR_3528 "Zylinder:" +#define STR_3529 "Köpfe:" +#define STR_3530 "Sektoren:" +#define STR_3531 "Größe (MB):" +#define STR_3532 "Typ:" +#define STR_3533 "HDI Abbilder können nicht größer als 4 GB sein" +#define STR_3534 "Sie haben versucht, eine unverhältnismäßig große Festplatte anzulegen" +#define STR_3535 "HDI oder HDX Abbilder mit einer Sektorgröße ungleich 512 Bytes wird nicht unterstützt" +#define STR_3536 "Festplattenabbilder\0*.hd?;*.im?;*.vhd\0Alle Dateien\0*.*\0" +#define STR_3537 "Denken Sie daran, die neue Festplatte zu partitionieren und zu formatieren" /* UI dialog: Settings (Floppy Drives, 3550.) */ -#define STR_3550 "Diskettenlaufwerke:" -#define STR_3551 "Typ:" -#define STR_3552 "Turbo Timing" -#define STR_3553 "BPB überprüfen" -#define STR_3554 "Turbo" -#define STR_3555 "BPB Überprüfen" +#define STR_3550 "Diskettenlaufwerke:" +#define STR_3551 "Typ:" +#define STR_3552 "Turbo Timing" +#define STR_3553 "BPB überprüfen" +#define STR_3554 "Turbo" +#define STR_3555 "BPB Überprüfen" /* UI dialog: Settings (Removable Devices, 3575.) */ -#define STR_3575 "CD-ROM Laufwerke:" -#define STR_3576 "Geschwindigkeit:" -#define STR_3577 "ZIP Laufwerke:" -#define STR_3578 "ZIP 250" -#define STR_3579 "Geschwindigkeit" -#define STR_3580 "" -#define STR_3581 "" -#define STR_3582 "ATAPI (nur PIO)" -#define STR_3583 "ATAPI (PIO und DMA)" -#define STR_3584 "SCSI" +#define STR_3575 "CD-ROM Laufwerke:" +#define STR_3576 "Geschwindigkeit:" +#define STR_3577 "ZIP Laufwerke:" +#define STR_3578 "ZIP 250" +#define STR_3579 "Geschwindigkeit" +#define STR_3580 "ATAPI" +#define STR_3581 "SCSI" +#define STR_3582 "USB" -/* UI dialog: status bar (3900.) */ +/* UI: Status Bar (3900.) */ #define STR_3900 "(leer)" #define STR_3901 "(Hostlaufwerk %c:)" #define STR_3902 " [Schreibgeschützt]" @@ -321,6 +314,7 @@ #define STR_3904 "Abbild &laden..." #define STR_3905 "Vor&heriges Abbild erneut laden" #define STR_3906 "Aus&werfen" +#define STR_3907 "Ä&nderungsbenachrichtigung bei Wechsel" #define STR_3910 "Diskettenlaufwerk %i (%s): %ls" #define STR_3911 "Alle Abbilder\0*.0??;*.1??;*.360;*.720;*.86f;*.bin;*.cq?;*.dsk;*.flp;*.hdm;*.im?;*.json;*.td0;*.*fd?;*.xdf\0Komplexe Sektorabbilder\0*.imd;*.json;*.td0\0Einfache Sektorabbilder\0*.0??;*.1??;*.360;*.720;*.bin;*.cq?;*.dsk;*.flp;*.hdm;*.im?;*.xdf;*.*fd?\0Magnetfluss-Abbilder\0*.fdi\0Bitstrom-Abbilder\0*.86f\0Alle Dateien\0*.*\0" @@ -328,93 +322,93 @@ #define STR_3913 "Bitstrom-Abbilder\0*.86f\0" #define STR_3914 "Als 86F e&xportieren..." -#define STR_3920 "CD-ROM %i (%s): %s" +#define STR_3920 "CD-ROM %i (%ls): %ls" #define STR_3921 "Host CD/DVD-Laufwerk (%c:)" #define STR_3922 "CD-ROM Abbilder\0*.iso;*.cue\0Alle Dateien (*.*)\0*.*\0" #define STR_3923 "&Stumm" -#define STR_3930 "Festplatte (%s)" +#define STR_3930 "Festplatte %i (%ls): %ls" -#define STR_3940 "Wechsellaufwerk %i (SCSI): %ls" -#define STR_3941 "Ä&nderungsbenachrichtigung bei Wechsel" - -#define STR_3950 "ZIP %i (%03i): %ls" +#define STR_3950 "ZIP%03i %i (%ls): %ls" #define STR_3951 "ZIP Abbilder\0*.im?;*.zdi\0Alle Dateien\0*.*\0" #define STR_3952 "ZIP Abbilder\0*.im?;*.zdi\0" -#define STR_3960 "Netzwerk" -#define STR_3970 "Sound" +#define STR_3960 "Netzwerk (%s)" +#define STR_3970 "Sound (%s)" -/* Menu: Action (4000.) */ +/* UI menu: Action (4000.) */ #define STR_ACTION "&Aktionen" -#define STR_4001 "&Harter Reset" -#define STR_4002 "&Strg+Alt+Entf" -#define STR_4003 "Strg+Alt+&Esc senden" -#define STR_4004 "Strg+Alt+&Unterbr senden" -#define STR_4005 "&Pause" -#define STR_4006 "&Beenden" +#define STR_4001 "&Harter Reset" +#define STR_4002 "&Strg+Alt+Entf" +#define STR_4003 "Strg+Alt+&Esc senden" +#define STR_4004 "Strg+Alt+&Unterbr senden" +#define STR_4005 "&Pause" +#define STR_4006 "&Beenden" -/* Menu: View (4010.) */ +/* UI menu: View (4010.) */ #define STR_VIEW "&Ansicht" -#define STR_4011 "&Veränderbare Fenstergröße" -#define STR_4012 "&Größe und Position speichern" -#define STR_4013 "&Vollbildmodus\tStrg+Alt+Bild Auf" -#define STR_4014 "&Rechtes STRG ist linkes ALT" -#define STR_4015 "&Statusleisten-Icons aktualisieren" +#define STR_4011 "&Veränderbare Fenstergröße" +#define STR_4012 "&Größe und Position speichern" +#define STR_4013 "&Vollbildmodus\tStrg+Alt+Bild Auf" +#define STR_4014 "&Rechtes STRG ist linkes ALT" -/* Menu: View > Renderer */ +/* UI menu: View > Renderer (4020.) */ #define STR_4020 "An&zeigetreiber" -/* Menu: View > Window Scale Factor */ +/* UI menu: View > Window Scale Factor (4030.) */ #define STR_4030 "&Fenster-Skalierungsfaktor" -#define STR_4031 "&0,5x" -#define STR_4032 "&1x" -#define STR_4033 "1,&5x" -#define STR_4034 "&2x" +#define STR_4031 "&0,5x" +#define STR_4032 "&1x" +#define STR_4033 "1,&5x" +#define STR_4034 "&2x" -/* Menu: View > Fullscreen Stretch Mode */ +/* UI menu: View > Fullscreen Stretch Mode (4040.) */ #define STR_4040 "&Vollbild Skalierungsmodus" -#define STR_4041 "&Auf ganzen Bildschirm ausdehnen" -#define STR_4042 "&4:3" -#define STR_4043 "&Quadratische Pixel" -#define STR_4044 "&Ganzzahlig skalieren" -#define STR_4045 "Größe &beibehalten" +#define STR_4041 "&Auf ganzen Bildschirm ausdehnen" +#define STR_4042 "&4:3" +#define STR_4043 "&Quadratische Pixel" +#define STR_4044 "&Ganzzahlig skalieren" +#define STR_4045 "Größe &beibehalten" -/* Menu: Display (4050.) */ + +/* UI menu: Display (4050.) */ #define STR_DISPLAY "An&zeige" -#define STR_4051 "Anzeige &invertieren" -#define STR_4052 "&Overscan aktiviert" -#define STR_4053 "&4:3 Seitenverhältnis erzwingen" -#define STR_4054 "Kontrast für Monochromanzeige ändern" +#define STR_4051 "Anzeige &invertieren" +#define STR_4052 "&Overscan aktiviert" +#define STR_4053 "&4:3 Seitenverhältnis erzwingen" +#define STR_4054 "Kontrast für Monochromanzeige ändern" -/* Menu: Display > Display Type */ +/* UI menu: Display > Display Type (4060.) */ #define STR_DISPTYPE "Display &type" -#define STR_4061 "RGB &Farbmonitor" -#define STR_4062 "&Graustufenmonitor" -#define STR_4063 "&Bernsteinmonitor" -#define STR_4064 "&Grünmonitor" -#define STR_4065 "&Weißer Monitor" +#define STR_4061 "RGB &Farbmonitor" +#define STR_4062 "&Graustufenmonitor" +#define STR_4063 "&Bernsteinmonitor" +#define STR_4064 "&Grünmonitor" +#define STR_4065 "&Weißer Monitor" -/* Menu: Display > Grayscale Conversion Type */ +/* UI menu: Display > Grayscale Conversion Type (4070.) */ #define STR_GRAYSCALE "&Graustufenumwandlung" -#define STR_4071 "BT&601 (NTSC/PAL)" -#define STR_4072 "BT&709 (HDTV)" -#define STR_4073 "&gemittelt" +#define STR_4071 "BT&601 (NTSC/PAL)" +#define STR_4072 "BT&709 (HDTV)" +#define STR_4073 "&gemittelt" -/* Menu: Tools (4080.) */ + +/* UI menu: Tools (4080.) */ #define STR_TOOLS "&Tools" -#define STR_4081 "&Einstellungen" -#define STR_4082 "S&prache" -#define STR_4083 "P&rotokollierung" -#define STR_4084 "Konfigurationsdatei &laden" -#define STR_4085 "Konfigurationsdatei &speichern" -#define STR_4086 "S&tatus" -#define STR_4087 "&Bildschirmfoto speichern\tStrg+Pos1" +#define STR_4081 "&Einstellungen" +#define STR_4082 "S&prache" +#define STR_4083 "P&rotokollierung" +#define STR_4084 "Log Breakpoint" +#define STR_4085 "Toggle %s logging" +#define STR_4086 "Konfigurationsdatei &laden" +#define STR_4087 "Konfigurationsdatei &speichern" +#define STR_4088 "&Bildschirmfoto speichern" -/* Menu: Help (4090.) */ + +/* UI menu: Help (4090.) */ #define STR_HELP "&Hilfe" -#define STR_4091 "&Über VARCem" +#define STR_4091 "&Über VARCem" /* End of file. */ diff --git a/src/ui/lang/VARCem-DU.str b/src/ui/lang/VARCem-DU.str index 35b8855..df72ff4 100644 --- a/src/ui/lang/VARCem-DU.str +++ b/src/ui/lang/VARCem-DU.str @@ -8,7 +8,7 @@ * * String definitions for "Dutch (Netherlands)" language. * - * Version: @(#)VARCem-DU.str 1.0.11 2018/09/23 + * Version: @(#)VARCem-DU.str 1.0.12 2018/10/01 * * Author: Fred N. van Kempen, * @@ -45,10 +45,13 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* Do not translate! */ -#define TAG_VERSION 1,0,11 -#define TAG_AUTHOR "Fred N. van Kempen" -#define TAG_EMAIL "waltje@varcem.com" +/* Main application strings (2000) - DO NOT TRANSLATE! */ +#define STR_VERSION 1,0,12 +#define STR_AUTHOR "Fred N. van Kempen" +#define STR_EMAIL "waltje@varcem.com" +#define STR_NAME "VARCem" +#define STR_TITLE "Virtual ARchaeological Computer EMulator" + /* Messagebox classes (2100.) */ #define STR_2100 "Fout" @@ -63,27 +66,24 @@ #define STR_2202 "PCap kon niet worden opgestart" #define STR_2203 "Geen beschikbare PCap apparaten gevonden" #define STR_2204 "Ongeldig PCap apparaat" -#define STR_2205 "Kon OpenAL niet initialiseren, controleer of u het volgende bestand\nin de programmamap heeft:\n\nlibopenal-1.dll" -#define STR_2206 "Kon FluidSynth niet initialiseren, controleer of u het volgende bestand\nin de programmamap heeft:\n\nlibfluidsynth.dll" -#define STR_2207 "Het systeem heeft geen geheugen meer vrij!" +#define STR_2205 "Kon %s niet initialiseren, controleer of u het '%s' bibliotheekbestand op uw systeem of in de programmap hebt!" /* Application error messages (2300.) */ -#define STR_2300 "Schermafdruk-bestand %s kon niet worden gemaakt" +#define STR_2300 "Het systeem heeft geen geheugen meer vrij!" #define STR_2301 "Geen bruikbare ROMs gevonden!" #define STR_2302 "Geen bruikbaar configuratiebestand gevonden.\n\nWilt u een nieuwe configuratie maken?" -#define STR_2303 "De machine:\n\n %ls\n\nis momenteel niet beschikbaar.\n\nWilt u dit wijzigen in de Instellingen?" -#define STR_2304 "De video-kaart:\n\n %ls\n\nis momenteel niet beschikbaar.\n\nWilt u dit wijzigen in Instellingen?" -#define STR_2305 "Ingestelde renderer '%S' niet beschikbaar - wilt u deze naar standaardwaarde terugzetten?" -#define STR_2306 "ST506/ESDI CD-ROM stations hebben nooit bestaan" +#define STR_2303 "De %ls:\n\n %s\n\nis momenteel niet beschikbaar.\n\nWilt u dit wijzigen in de Instellingen?" +#define STR_2304 "Ingestelde renderer:\n\n %s\n\nniet beschikbaar - wilt u deze naar standaardwaarde terugzetten?" +#define STR_2305 "De instellingen dienen eerst te worden opgeslagen!" +#define STR_2306 "Schermafdruk-bestand %ls kon niet worden gemaakt" #define STR_2307 "USB wordt nog niet ondersteund" -#define STR_2308 "De instellingen dienen eerst te worden opgeslagen!" /* Application messages (2400.) */ #define STR_2400 "Weet u zeker dat u deze instellingen wilt bewaren?\n\n(Een herstart kan nodig zijn...)" #define STR_2401 "Instellingen opgeslagen, vergeet niet het programma te herstarten!" -#define STR_2402 "Het gekozen apparaat '%ls' wordt momenteel als 'in ontwikkeling' beschouwd en kan problemen opleveren.\n\nWeet u zeker dat u dit apparaat wilt gebruiken?" +#define STR_2402 "Het gekozen apparaat:\n\n %s\n\nwordt momenteel als 'in ontwikkeling' beschouwd en kan problemen opleveren.\n\nWeet u zeker dat u dit apparaat wilt gebruiken?" #define STR_2403 "Klik om de muis te koppelen" #define STR_2404 "Gebruik F8+F12 om de muis te ontkoppelen" #define STR_2405 "Gebruik F8+F12 (of middelste knop) om te muis te ontkoppelen" @@ -96,12 +96,16 @@ /* UI: common elements (3000.) */ #define STR_OK "Akkoord" +#define STR_YES "Ja" +#define STR_NO "Nee" #define STR_CANCEL "Annuleren" #define STR_CONFIGURE "Configureer" #define STR_BROWSE "Bladeren" + /* UI: dialog shared strings (3100.) */ #define STR_NONE "Geen" +#define STR_INTERNAL "Geintegreerd" #define STR_DISABLED "Uitgeschakeld" #define STR_ENABLED "Ingeschakeld" #define STR_OFF "Uit" @@ -121,19 +125,19 @@ #define STR_DEVCONF_2 "Apparaat:" -/* UI: dialog: About (3200.) */ +/* UI dialog: About (3200.) */ #define STR_ABOUT "Over VARCem.." #define STR_3201 "Auteurs:" #define STR_3202 "Fred N. van Kempen, Miran Grca, Sarah Walker en anderen.\nGebaseerd op andere projecten zoals 86Box, PCem, MAME, DOSbox en Qemu." #define STR_3203 "Gepubliceerd onder de BSD 3-Clause License ('BSD3'), en de GNU General Public License (versie 2 of hoger) voor bestaande, geïmporteerde code van andere projecten." #define STR_3204 "Zie het bestand LICENSE.txt voor meer informatie." -/* UI: dialog: Localization (3210.) */ +/* UI dialog: Localization (3210.) */ #define STR_LOCALIZE "Vertalingen" #define STR_3211 "Vertalingen vanuit het Engels naar onderstaande talen zijn gedaan door:" /* UI dialog: Status (3225.) */ -#define STR_STATUS "Status" +/* (Unused now) */ /* UI dialog: Sound Gain (3250.) */ #define STR_SNDGAIN "Geluidsvolume" @@ -182,24 +186,16 @@ #define STR_3328 "Wachtcycli:" #define STR_3329 "Geheugen:" #define STR_3330 "MB" -#define STR_3331 "Gebruik Tijdsynchronisatie" +#define STR_3331 "Gebruik Tijdsynchronisatie:" #define STR_3332 "Gebruik FPU (reken-processor)" #define STR_3333 "Dynamic Re-compiler" #define STR_3334 "KB" #define STR_3335 "Standaard" - +#define STR_3336 "Ingesteld (UTC)" /* UI dialog: Settings (Video, 3350.) */ #define STR_3350 "Beeldschermadapter:" -#define STR_3351 "Toegangssnelheid:" -#define STR_3352 "3Dfx Voodoo" -#define STR_3353 "Standaard" -#define STR_3354 "8-bit" -#define STR_3355 "Langzaam 16-bit" -#define STR_3356 "Snel 16-bit" -#define STR_3357 "Langzaam VLB/PCI" -#define STR_3358 "Middel VLB/PCI" -#define STR_3359 "Snel VLB/PCI" +#define STR_3351 "3Dfx Voodoo" /* UI dialog: Settings (Input, 3375.) */ #define STR_3375 "Muis:" @@ -232,8 +228,8 @@ /* UI dialog: Settings (Other Devices, 3475.) */ #define STR_3475 "SCSI adapter:" #define STR_3476 "HD controller:" -#define STR_3477 "Derde IDE:" -#define STR_3478 "Vierde IDE:" +#define STR_3477 "Derde IDE" +#define STR_3478 "Vierde IDE" #define STR_3479 "ISABugger apparaat" #define STR_3480 "ISA geheugenuitbreiding" #define STR_3481 "ISA Clock/RTC uitbreiding" @@ -254,10 +250,9 @@ #define STR_3512 "Aangepast (groot).." #define STR_3515 "ST506" #define STR_3516 "ESDI" -#define STR_3517 "IDE (alléén PIO)" -#define STR_3518 "IDE (PIO+DMA)" -#define STR_3519 "SCSI" -#define STR_3520 "SCSI (verwisselbaar)" +#define STR_3517 "IDE" +#define STR_3518 "SCSI" +#define STR_3519 "USB" /* UI dialog: Settings (Add Hard Disk, 3525.) */ #define STR_3525 "Voeg schijf toe" @@ -288,13 +283,12 @@ #define STR_3577 "ZIP stations:" #define STR_3578 "ZIP 250" #define STR_3579 "Snelheid" -#define STR_3580 "" -#define STR_3581 "" -#define STR_3582 "ATAPI (alléén PIO)" -#define STR_3583 "ATAPI (PIO+DMA)" -#define STR_3584 "SCSI" +#define STR_3580 "ATAPI" +#define STR_3581 "SCSI" +#define STR_3582 "USB" -/* UI dialog: status bar (3900.) */ + +/* UI: Status Bar (3900.) */ #define STR_3900 "(leeg)" #define STR_3901 "(PC station %c:)" #define STR_3902 " [Schrijfbeveiligd" @@ -302,6 +296,7 @@ #define STR_3904 "&Bestaand bestand..." #define STR_3905 "&Her-laad vorige bestand" #define STR_3906 "&Uitwerpen" +#define STR_3907 "&Terugmelding disk-wissel" #define STR_3910 "Diskette %i (%s): %ls" #define STR_3911 "Alle diskettebestanden\0*.0??;*.1??;*.360;*.720;*.86f;*.bin;*.cq?;*.dsk;*.flp;*.hdm;*.im?;*.json;*.td0;*.*fd?;*.xdf\0Advanced Sector bestanden\0*.imd;*.json;*.td0\0Basic Sector bestanden\0*.0??;*.1??;*.360;*.720;*.bin;*.cq?;*.dsk;*.flp;*.hdm;*.im?;*.xdf;*.*fd?\0Flux bestanden\0*.fdi\0Surface bestanden\0*.86f\0Alle bestanden\0*.*\0" @@ -309,24 +304,21 @@ #define STR_3913 "Surface bestanden\0*.86f\0" #define STR_3914 "E&xporteer als 86F..." -#define STR_3920 "CD-ROM %i (%s): %s" +#define STR_3920 "CD-ROM %i (%ls): %ls" #define STR_3921 "PC CD/DVD station (%c:)" #define STR_3922 "CD-ROM bestanden\0*.iso;*.cue\0Alle bestanden (*.*)\0*.*\0" #define STR_3923 "&Stil" -#define STR_3930 "Vaste schijf (%s)" +#define STR_3930 "Vaste schijf %i (%ls): %ls" -#define STR_3940 "Verwisselbare schijf %i: %ls" -#define STR_3941 "&Terugmelding disk-wissel" - -#define STR_3950 "ZIP %i (%03i): %ls" +#define STR_3950 "ZIP%03i %i (%ls): %ls" #define STR_3951 "ZIP bestanden\0*.im?;*.zdi\0Alle bestanden\0*.*\0" #define STR_3952 "ZIP bestanden\0*.im?;*.zdi\0" -#define STR_3960 "Netwerk" -#define STR_3970 "Geluid" +#define STR_3960 "Netwerk (%s)" +#define STR_3970 "Geluid (%s)" -/* Menu: Action (4000.) */ +/* UI menu: Action (4000.) */ #define STR_ACTION "&Aktie" #define STR_4001 "&Harde Reset" #define STR_4002 "&Ctrl+Alt+Del" @@ -335,25 +327,25 @@ #define STR_4005 "&Pauzeer" #define STR_4006 "&Einde" -/* Menu: View (4010.) */ + +/* UI menu: View (4010.) */ #define STR_VIEW "&Beeld" #define STR_4011 "&Instelbaar venster" #define STR_4012 "&Onthoud plaats en grootte van venster" #define STR_4013 "&Volledig Scherm\tCtrl+Alt+PageUP" #define STR_4014 "&Rechter CTRL is linker ALT" -#define STR_4015 "&Activeer pictogrammen in de statusregel" -/* Menu: View > Renderer */ +/* UI menu: View > Renderer (4020.) */ #define STR_4020 "Re&nderer" -/* Menu: View > Window Scale Factor */ +/* UI menu: View > Window Scale Factor (4030.) */ #define STR_4030 "&Venster schaalfaktor" #define STR_4031 "&0.5x" #define STR_4032 "&1x" #define STR_4033 "1.&5x" #define STR_4034 "&2x" -/* Menu: View > Fullscreen Stretch Mode */ +/* UI menu: View > Fullscreen Stretch Mode (4040.) */ #define STR_4040 "&Rekmode volledig scherm" #define STR_4041 "&Rek volledig uit" #define STR_4042 "&4:3" @@ -361,14 +353,15 @@ #define STR_4044 "&Geheelgetal-schaling" #define STR_4045 "&Hou vast aan huidige grootte" -/* Menu: Display (4050.) */ + +/* UI menu: Display (4050.) */ #define STR_DISPLAY "&Beeldscherm" #define STR_4051 "&Geïnverteed scherm" #define STR_4052 "Gebruik &overscan" #define STR_4053 "F&orceer 4:3 schermverhouding" #define STR_4054 "Wijzig &contrast voor monochroom scherm" -/* Menu: Display > Display Type */ +/* UI menu: Display > Display Type (4060.) */ #define STR_DISPTYPE "&Soort beeldscherm" #define STR_4061 "RGB &kleurenscherm" #define STR_4062 "&Grijstinten scherm" @@ -376,23 +369,26 @@ #define STR_4064 "&Groen beeldscherm" #define STR_4065 "&Wit beeldscherm" -/* Menu: Display > Grayscale Conversion Type */ +/* UI menu: Display > Grayscale Conversion Type (4070.) */ #define STR_GRAYSCALE "&Grijstinten conversietype" #define STR_4071 "BT&601 (NTSC/PAL)" #define STR_4072 "BT&709 (HDTV)" #define STR_4073 "&Gemiddeld" -/* Menu: Tools (4080.) */ + +/* UI menu: Tools (4080.) */ #define STR_TOOLS "&Opties" #define STR_4081 "&Instellingen" #define STR_4082 "&Talen" -#define STR_4083 "L&ogging" -#define STR_4084 "&Laad configuratie" -#define STR_4085 "&Sla configuratie op" -#define STR_4086 "S&tatus" -#define STR_4087 "&Maak schermafdruk\tCtrl+Home" +#define STR_4083 "L&ogbestanden" +#define STR_4084 "Log Markeerpunt" +#define STR_4085 "Zet %s logging aan" +#define STR_4086 "&Laad configuratie" +#define STR_4087 "&Sla configuratie op" +#define STR_4088 "&Maak schermafdruk" -/* Menu: Help (4090.) */ + +/* UI menu: Help (4090.) */ #define STR_HELP "&Hulp" #define STR_4091 "&Over VARCem" diff --git a/src/ui/lang/VARCem-ES.str b/src/ui/lang/VARCem-ES.str index ab83946..cd82a40 100644 --- a/src/ui/lang/VARCem-ES.str +++ b/src/ui/lang/VARCem-ES.str @@ -8,7 +8,7 @@ * * String definitions for "Spanish (Spain, Normal Sort)" language. * - * Version: @(#)VARCem-ES.str 1.0.10 2018/09/23 + * Version: @(#)VARCem-ES.str 1.0.12 2018/10/01 * * Authors: Natalia Portillo, * Fred N. van Kempen, @@ -47,65 +47,67 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* Do not translate! */ -#define TAG_VERSION 1,0,10 -#define TAG_AUTHOR "Natalia Portillo" -#define TAG_EMAIL "claunia@claunia.com" +/* Main application strings (2000) - DO NOT TRANSLATE! */ +#define STR_VERSION 1,0,11 +#define STR_AUTHOR "Natalia Portillo" +#define STR_EMAIL "claunia@claunia.com" +#define STR_NAME "VARCem" +#define STR_TITLE "Virtual ARchaeological Computer EMulator" -/* Clases de avisos (2100.) */ +/* Messagebox classes (2100.) */ #define STR_2100 "Error" #define STR_2101 "Error fatal" #define STR_2102 "Error de configuración" #define STR_2103 "Advertencia" -/* Errores del sistema (2200.) */ +/* System errors (2200.) */ #define STR_2200 "¡No se pudieron cargar los accesos de teclado!" #define STR_2201 "¡No se pudo registrar la entrada sin procesar!" #define STR_2202 "Fallo al configurar PCap porque puede no estar inicializado" #define STR_2203 "No se encontraron dispositivos PCap" #define STR_2204 "Dispositivo PCap no válido" -#define STR_2205 "No se pudo inicializar OpenAL, compruebe que la siguiente librería está en\nla carpeta del programa:\n\nlibopenal-1.dll" -#define STR_2206 "No se pudo inicializar FluidSynth, compruebe que la siguiente librería está en\n la carpeta del programa:\n\nlibfluidsynth.dll" -#define STR_2207 "¡Memoria insuficiente!" +#define STR_2205 "No se pudo inicializar %s, compruebe que la siguiente librería está en\nla carpeta del programa:\n\n%s" -/* Mensajes de error de aplicación (2300.) */ -#define STR_2300 "No se pudo crear el archivo bitmap: %s" +/* Application error messages (2300.) */ +#define STR_2300 "¡Memoria insuficiente!" #define STR_2301 "¡No se han encontrado imágenes ROM utilizables!" #define STR_2302 "No se encontró una configuración válida.\n\n¿Quiere abrir el diálogo de preferencias para crear una?" -#define STR_2303 "El equipo configurado:\n\n %ls\n\nno está disponible.\n\n¿Quiere abrir el diálogo de preferencias?" -#define STR_2304 "La tarjeta de video configurada:\n\n %s\n\nno está disponible.\n\n¿Quiere abrir el diálogo de preferencias?" -#define STR_2305 "El renderizador '%S' seleccionado no está disponible. ¿Establecer renderizador por defecto?" -#define STR_2306 "Las unidades de CD-ROM ST506 o ESDI CD-ROM nunca existieron" +#define STR_2303 "El %ls configurado:\n\n %s\n\nno está disponible.\n\n¿Quiere abrir el diálogo de preferencias?" +#define STR_2304 "El renderizador:\n\n %s\n\nseleccionado no está disponible. ¿Establecer renderizador por defecto?" +#define STR_2305 "¡Debe guardar la configuración primero!" +#define STR_2306 "No se pudo crear el archivo bitmap: %ls" #define STR_2307 "El USB no está soportado aún" -#define STR_2308 "¡Debe guardar la configuración primero!" -/* Mensajes de aplicación (2400.) */ +/* Application messages (2400.) */ #define STR_2400 "¿Está seguro de guardar estas preferencias?\n\n(Puede ser necesario reiniciar...)" #define STR_2401 "Cambios guardados, ¡por favor reinicie el emulador!" -#define STR_2402 "El dispositivo '%ls' seleccionado se considera actualmente «en desarrollo» y puede causar problemas.\n\n¿Está seguro de querer activarlo?" +#define STR_2402 "El dispositivo:\n\n %s\n\nseleccionado se considera actualmente «en desarrollo» y puede causar problemas.\n\n¿Está seguro de querer activarlo?" #define STR_2403 "Clique para capturar el ratón" #define STR_2404 "Pulse F8 y F12 para liberar el ratón" #define STR_2405 "Pulse F8 y F12 o el botón del medio para liberar el ratón" #define STR_2406 "Pulse CTRL, ALT y AVPÁG para volver al modo ventana" -/* Strings misceláneas de aplicación (2500.) */ +/* Misc application strings (2500.) */ #define STR_2500 "Archivos de configuración\0*.varc\0Todos los archivos\0*.*\0" -/* UI: elementos comunes (3000.) */ +/* UI: common elements (3000.) */ #define STR_OK "Aceptar" #define STR_CANCEL "Cancelar" +#define STR_YES "Sí" +#define STR_NO "No" #define STR_CONFIGURE "Configurar" #define STR_BROWSE "Explorar" -/* UI: strings compartidas entre diálogos (3100.) */ +/* UI: dialog shared strings (3100.) */ #define STR_NONE "Ninguno" +#define STR_INTERNAL "Interna" #define STR_DISABLED "Desactivado" #define STR_ENABLED "Activado" #define STR_OFF "Apagado" @@ -125,25 +127,25 @@ #define STR_DEVCONF_2 "Dispositivo:" -/* UI: diálogo: Acerca de (3200.) */ +/* UI dialog: About (3200.) */ #define STR_ABOUT "Acerda de VARCem.." #define STR_3201 "Autores:" #define STR_3202 "Fred N. van Kempen, Miran Grca, Sarah Walker y otros.\nBasado en trabajos anteriores como 86Box, PCem, MAME, DOSbox y Qemu." #define STR_3203 "Bajo licencia BSD de tres cláusulas, y bajo la Licencia General Pública GNU (GPL, versión 2 o superior) para el código existente, importado de otros proyectos." #define STR_3204 "Vea LICENSE.txt para más información." -/* UI: diálogo: Localización (3210.) */ +/* UI dialog: Localization (3210.) */ #define STR_LOCALIZE "Localización" #define STR_3211 "Traducciones del inglés a estos idiomas contribuidas por:" -/* UI diálogo: Estado (3225.) */ -#define STR_STATUS "Estado" +/* UI dialog: Status (3225.) */ +/* (Unused now) */ -/* UI diálogo: Ganancia sonora (3250.) */ +/* UI dialog: Sound Gain (3250.) */ #define STR_SNDGAIN "Ganancia sonora" #define STR_3251 "Ganancia" -/* UI diálogo: Nueva imagen (3275.) */ +/* UI dialog: New Image (3275.) */ #define STR_NEWIMG "Nueva imagen de disquete" #define STR_3276 "Tamaño del disco:" #define STR_3277 "Modo de RPM:" @@ -166,7 +168,7 @@ #define STR_3294 "ZIP 100" #define STR_3295 "ZIP 250" -/* UI diálogo: Preferencias (3300.) */ +/* UI dialog: Settings (3300.) */ #define STR_SETTINGS "Preferencias" #define STR_3310 "Equipo" #define STR_3311 "Pantalla" @@ -179,32 +181,25 @@ #define STR_3318 "Disqueteras" #define STR_3319 "Otros dispositivos extraíbles" -/* UI diálogo: Preferencias (Equipo, 3325.) */ +/* UI dialog: Settings (Machine, 3325.) */ #define STR_3325 "Equipo:" #define STR_3326 "Tipo de procesador:" #define STR_3327 "Procesador:" #define STR_3328 "Estados de espera:" #define STR_3329 "Memoria:" #define STR_3330 "MB" -#define STR_3331 "Activar sincronización de reloj" +#define STR_3331 "Activar sincronización de reloj:" #define STR_3332 "Activar FPU" #define STR_3333 "Recompilador dinámico" #define STR_3334 "KB" #define STR_3335 "Por defecto" +#define STR_3336 "Activado (UTC)" -/* UI diálogo: Preferencias (Video, 3350.) */ +/* UI dialog: Settings (Video, 3350.) */ #define STR_3350 "Video:" -#define STR_3351 "Velocidad del video:" -#define STR_3352 "Voodoo Graphics" -#define STR_3353 "Por defecto" -#define STR_3354 "8 bits" -#define STR_3355 "16 bits lentos" -#define STR_3356 "16 bits rápidos" -#define STR_3357 "VLB/PCI lento" -#define STR_3358 "VLB/PCI medio" -#define STR_3359 "VLB/PCI rápido" +#define STR_3351 "Voodoo Graphics" -/* UI diálogo: Preferencias (Entrada, 3375.) */ +/* UI dialog: Settings (Input, 3375.) */ #define STR_3375 "Ratón:" #define STR_3376 "Joystick:" #define STR_3377 "Joystick 1" @@ -212,19 +207,19 @@ #define STR_3379 "Joystick 3" #define STR_3380 "Joystick 4" -/* UI diálogo: Preferencias (Sonido, 3400.) */ +/* UI dialog: Settings (Sound, 3400.) */ #define STR_3400 "Tarjeta de sonido:" #define STR_3401 "Dispositivo de salida MIDI:" #define STR_3402 "MPU-401 independiente" #define STR_3403 "Usar Nuked OPL" #define STR_3404 "Usar sonido FLOAT32" -/* UI diálogo: Preferencias (Red, 3425.) */ +/* UI dialog: Settings (Network, 3425.) */ #define STR_3425 "Tipo de red:" #define STR_3426 "Dispositivo PCap:" #define STR_3427 "Adaptador de red:" -/* UI diálogo: Preferencias (Puertos, 3450.) */ +/* UI dialog: Settings (Ports, 3450.) */ #define STR_3450 "Dispositivos de juegos" #define STR_3451 "Puerto paralelo 1" #define STR_3452 "Puerto paralelo 2" @@ -232,16 +227,16 @@ #define STR_3454 "Puerto serie 1" #define STR_3455 "Puerto serie 2" -/* UI diálogo: Preferencias (Otros dispositivos, 3475.) */ +/* UI dialog: Settings (Other Devices, 3475.) */ #define STR_3475 "Controladora SCSI:" #define STR_3476 "Controladora de disco duro:" -#define STR_3477 "IDE terciario:" -#define STR_3478 "IDE cuaternario:" +#define STR_3477 "IDE terciario" +#define STR_3478 "IDE cuaternario" #define STR_3479 "Dispositivo ISABugger" #define STR_3480 "Expansión de memoria (ISA)" #define STR_3481 "Reloj ISA / Tarjeta RTC" -/* UI diálogo: Preferencias (Discos duros, 3500.) */ +/* UI dialog: Settings (Hard disks, 3500.) */ #define STR_3500 "Discos duros:" #define STR_3501 "&Nuevo.." #define STR_3502 "&Existente.." @@ -257,12 +252,11 @@ #define STR_3512 "Personalizado (largo)..." #define STR_3515 "ST506" #define STR_3516 "ESDI" -#define STR_3517 "IDE (solo PIO)" -#define STR_3518 "IDE (PIO y DMA)" -#define STR_3519 "SCSI" -#define STR_3520 "SCSI (extraíble)" +#define STR_3517 "IDE" +#define STR_3518 "SCSI" +#define STR_3519 "USB" -/* UI diálogo: Preferencias (Añadir disco duro, 3525.) */ +/* UI dialog: Settings (Add Hard disk, 3525.) */ #define STR_3525 "Añadir disco duro" #define STR_3526 "Añadir disco duro nuevo" #define STR_3527 "Añadir disco duro existente" @@ -277,7 +271,7 @@ #define STR_3536 "Imágenes de disco duro\0*.hd?;*.im?;*.vhd\0Todos los archivos\0*.*\0" #define STR_3537 "Recuerde particionar y formatear la nueva unidad" -/* UI diálogo: Preferencias (Disqueteras, 3550.) */ +/* UI dialog: Settings (Floppy, 3550.) */ #define STR_3550 "Disqueteras:" #define STR_3551 "Tipo:" #define STR_3552 "Turbo" @@ -285,19 +279,18 @@ #define STR_3554 "Turbo" #define STR_3555 "Comprobar BPB" -/* UI diálogo: Preferencias (Dispositivos extraíbles, 3575.) */ +/* UI dialog: Settings (Removable Devices, 3575.) */ #define STR_3575 "Unidades de CD-ROM:" #define STR_3576 "Velocidad:" #define STR_3577 "Unidades ZIP:" #define STR_3578 "ZIP 250" #define STR_3579 "Velocidad" -#define STR_3580 "" -#define STR_3581 "" -#define STR_3582 "ATAPI (solo PIO)" -#define STR_3583 "ATAPI (PIO y DMA)" -#define STR_3584 "SCSI" +#define STR_3580 "ATAPI" +#define STR_3581 "SCSI" +#define STR_3582 "USB" -/* UI diálogo: barra de estado(3900.) */ + +/* UI: Status Bar (3900.) */ #define STR_3900 "(vacío)" #define STR_3901 "(unidad nativa %c:)" #define STR_3902 " [Protegida contra escritura]" @@ -305,6 +298,7 @@ #define STR_3904 "&Cargar imagen.." #define STR_3905 "&Recargar imagen anterior" #define STR_3906 "&Expulsar" +#define STR_3907 "&Notificar cambio de disco" #define STR_3910 "Disquetera %i (%s): %ls" #define STR_3911 "Todas las imágenes\0*.0??;*.1??;*.360;*.720;*.86f;*.bin;*.cq?;*.dsk;*.flp;*.hdm;*.im?;*.json;*.td0;*.*fd?;*.xdf\0Imágenes por sectores avanzadas\0*.imd;*.json;*.td0\0Imágenes por sectores básicas\0*.0??;*.1??;*.360;*.720;*.bin;*.cq?;*.dsk;*.flp;*.hdm;*.im?;*.xdf;*.*fd?\0Imágenes de flujo\0*.fdi\0Imágenes de superficie\0*.86f\0Todos los archivos\0*.*\0" @@ -312,24 +306,21 @@ #define STR_3913 "Imágenes de superficie\0*.86f\0" #define STR_3914 "E&xportar a 86F..." -#define STR_3920 "CD-ROM %i (%s): %s" +#define STR_3920 "CD-ROM %i (%ls): %ls" #define STR_3921 "Unidad CD/DVD nativa (%c:)" #define STR_3922 "Imágenes de CD-ROM\0*.iso;*.cue\0Todos los archivos(*.*)\0*.*\0" #define STR_3923 "&Silenciar" -#define STR_3930 "Disco duro (%s)" +#define STR_3930 "Disco duro %i (%ls): %ls" -#define STR_3940 "Disco extraíble %i: %ls" -#define STR_3941 "&Notificar cambio de disco" - -#define STR_3950 "ZIP %i (%03i): %ls" +#define STR_3950 "ZIP%03i %i (%ls): %ls" #define STR_3951 "Imágenes de disco ZIP\0*.im?;*.zdi\0Todos los archivos\0*.*\0" #define STR_3952 "Imágenes de disco ZIP\0*.im?;*.zdi\0" -#define STR_3960 "Red" -#define STR_3970 "Sonido" +#define STR_3960 "Red (%s)" +#define STR_3970 "Sonido (%s)" -/* Menú:: Acción (4000.) */ +/* UI menu: Action (4000.) */ #define STR_ACTION "&Acción" #define STR_4001 "&Reiniciar" #define STR_4002 "&Ctrl+Alt+Supr" @@ -338,25 +329,25 @@ #define STR_4005 "&Pausar" #define STR_4006 "&Salir" -/* Menú:: Vista (4010.) */ + +/* UI menu: View (4010.) */ #define STR_VIEW "&Vistar" #define STR_4011 "Ventana &redimensionable" #define STR_4012 "R&ecordar tamaño y posición" #define STR_4013 "&Pantalla completa\tCtrl+Alt+RePág" #define STR_4014 "CTRL derecho es ALT izquierdo" -#define STR_4015 "&Actualizar iconos de la barra de estado" -/* Menú:: Vista > Renderizador */ +/* UI menu: View > Renderer (4020.) */ #define STR_4020 "Re&nderizador" -/* Menú:: Vista > Factor de escala de ventana */ +/* UI menu: View > Window Scale Factor (4030.) */ #define STR_4030 "&Factor de escala de ventana" #define STR_4031 "&0.5x" #define STR_4032 "&1x" #define STR_4033 "1.&5x" #define STR_4034 "&2x" -/* Menú:: Vista > Modo de pantalla completa*/ +/* UI menu: View > Fullscreen Stretch Mode (4040.) */ #define STR_4040 "&Modo de pantalla completa" #define STR_4041 "&Estirar pantalla completa" #define STR_4042 "&4:3" @@ -364,14 +355,15 @@ #define STR_4044 "E&scala entera" #define STR_4045 "&Mantener tamaño" -/* Menú:: Pantalla (4050.) */ + +/* UI menu: Display (4050.) */ #define STR_DISPLAY "&Pantalla" #define STR_4051 "&Pantalla invertida" #define STR_4052 "Activar &sobre-escaneo" #define STR_4053 "F&orzar ratio de pantalla 4:3" #define STR_4054 "Cambiar &contraste para pantalla monócroma" -/* Menú:: Pantalla > Tipo de pantalla */ +/* UI menu: Display > Display Type (4060.) */ #define STR_DISPTYPE "&Tipo de pantalla" #define STR_4061 "Monitor &color RGB" #define STR_4062 "Monitor de escala de &grises" @@ -379,23 +371,26 @@ #define STR_4064 "Monitor &verde" #define STR_4065 "Monitor &blanco" -/* Menú:: Pantalla > Tipo de conversión de escala de grises */ +/* UI menu: Display > Grayscale Conversion Type (4070.) */ #define STR_GRAYSCALE "Tipo de conversión de escala de &grises" #define STR_4071 "BT&601 (NTSC/PAL)" #define STR_4072 "BT&709 (HDTV)" #define STR_4073 "&Media" -/* Menú:: Herramientas(4080.) */ + +/* UI menu: Tools (4080.) */ #define STR_TOOLS "&Herramientas" #define STR_4081 "&Preferencias" #define STR_4082 "&Idioma" #define STR_4083 "&Registro" -#define STR_4084 "&Cargar configruación" -#define STR_4085 "&Guardar configuración" -#define STR_4086 "&Estado" -#define STR_4087 "C&apturar pantalla\tCtrl+Inicio" +#define STR_4084 "Marca de registro" +#define STR_4085 "Activar registro de %s" +#define STR_4086 "&Cargar configruación" +#define STR_4087 "&Guardar configuración" +#define STR_4088 "C&apturar pantalla" -/* Menú:: Ayuda (4090.) */ + +/* UI menu: Help (4090.) */ #define STR_HELP "&Ayuda" #define STR_4091 "&Acerca de VARCem" diff --git a/src/ui/lang/VARCem-FI.str b/src/ui/lang/VARCem-FI.str index 564da06..126a4cd 100644 --- a/src/ui/lang/VARCem-FI.str +++ b/src/ui/lang/VARCem-FI.str @@ -8,12 +8,7 @@ * * String definitions for "Finnish (Finland)" language. * - * TRANSLATION: The application uses English as its primary language, and - * this file is the "Master" for all translations. Please use - * it as the line-by-line base for the translated version, and - * update fields as needed. - * - * Version: @(#)VARCem-FI.str 1.0.8 2018/09/23 + * Version: @(#)VARCem-FI.str 1.0.9 2018/10/01 * * Authors: Daniel Gurney, * Fred N. van Kempen, @@ -52,10 +47,13 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* Do not translate! */ -#define TAG_VERSION 1,0,8 -#define TAG_AUTHOR "Daniel Gurney" -#define TAG_EMAIL "dgurney@varcem.com" +/* Main application strings (2000) - DO NOT TRANSLATE! */ +#define STR_VERSION 1,0,9 +#define STR_AUTHOR "Daniel Gurney" +#define STR_EMAIL "dgurney@varcem.com" +#define STR_NAME "VARCem" +#define STR_TITLE "Virtual ARchaeological Computer EMulator" + /* Messagebox classes (2100.) */ #define STR_2100 "Virhe" @@ -70,27 +68,24 @@ #define STR_2202 "PCap epäonnistui, koska sitä ei välttämättä ole alustettu" #define STR_2203 "PCap-laitteita ei löytynyt" #define STR_2204 "Vääränlainen PCap-laite" -#define STR_2205 "OpenALia ei voitu alustaa, varmista että seuraava kirjasto\non ohjelman kansiossa:\n\nlibopenal-1.dll" -#define STR_2206 "FluidSynthiä ei voitu alustaa, varmista että seuraava tiedosto\non ohjelman kansiossa:\n\nlibfluidsynth.dll" -#define STR_2207 "Järjestelmän muisti on täynnä!" +#define STR_2205 "%s ei voitu alustaa, varmista että seuraava kirjasto\non ohjelman kansiossa:\n\n%s" /* Application error messages (2300.) */ -#define STR_2300 "Bittikarttatiedostoa ei voitu luoda: %s" +#define STR_2300 "Järjestelmän muisti on täynnä!" #define STR_2301 "Käyttökelpoisia ROM-tiedostoja ei löytynyt!" #define STR_2302 "Kelvollista konfiguraatiota ei löytynyt.\n\nHaluatko siirtyä asetuksiin luodaksesi sellaisen?" -#define STR_2303 "Määritetty kone:\n\n %ls\n\nei ole saatavilla.\n\nHaluatko avata asetusdialogin?" -#define STR_2304 "Määritetty näytönohjain:\n\n %ls\n\nei ole saatavilla.\n\nHaluatko avata asetusdialogin?" -#define STR_2305 "Valittu renderer '%S' ei ole saatavilla. Palauta oletusasetus?" -#define STR_2306 "ST506 tai ESDI CD-ROM-asemia ei ollut koskaan olemassa" +#define STR_2303 "Määritetty %ls:\n\n %s\n\nei ole saatavilla.\n\nHaluatko avata asetusdialogin?" +#define STR_2304 "Valittu renderer:\n\n %s\n\nei ole saatavilla. Palauta oletusasetus?" +#define STR_2305 "Sinun pitää ensin tallentaa uudet asetuksesi!" +#define STR_2306 "Bittikarttatiedostoa ei voitu luoda: %ls" #define STR_2307 "USB:ta ei vielä tueta" -#define STR_2308 "Sinun pitää ensin tallentaa uudet asetuksesi!" /* Application messages (2400.) */ #define STR_2400 "Haluatko varmasti tallentaa nämä asetukset?\n\n(Uudelleenkäynnistys voi olla tarpeellinen...)" #define STR_2401 "Muutokset tallennettu, käynnistä emulaattori uudelleen!" -#define STR_2402 "Valittu laite '%ls' on tällä hetkellä `kehitteillä`, ja voi aiheuttaa ongelmia.\n\nHaluatko varmasti käyttää sitä?" +#define STR_2402 "Valittu laite:\n\n %s\n\non tällä hetkellä `kehitteillä`, ja voi aiheuttaa ongelmia.\n\nHaluatko varmasti käyttää sitä?" #define STR_2403 "Klikkaa kaapataksesi hiiri" #define STR_2404 "Paina F8+F12 vapauttaaksesi hiiri" #define STR_2405 "Paina F8+F12 tai keskinäppäintä vapauttaaksesi hiiri" @@ -104,11 +99,15 @@ /* UI: common elements (3000.) */ #define STR_OK "OK" #define STR_CANCEL "Peruuta" +#define STR_YES "Yes" +#define STR_NO "No" #define STR_CONFIGURE "Määritä" #define STR_BROWSE "Selaa" + /* UI: dialog shared strings (3100.) */ #define STR_NONE "-" +#define STR_INTERNAL "Internal" #define STR_DISABLED "Pois käytöstä" #define STR_ENABLED "Käytössä" #define STR_OFF "Pois" @@ -128,19 +127,19 @@ #define STR_DEVCONF_2 "Laitteet:" -/* UI: dialog: About (3200.) */ +/* UI dialog: About (3200.) */ #define STR_ABOUT "Tietoja VARCemista.." #define STR_3201 "Tekijät:" #define STR_3202 "Fred N. van Kempen, Miran Grca, Sarah Walker ja muut.\nPerustuu aikaisempiin projekteihin, kuten 86Boxiin, PCemiin, MAMEen, DOSboxiin and Qemu:hun." #define STR_3203 "Julkaistu BSD 3-Clause-lisenssin alaisena, ja muista projekteista lainattu koodi on GNU General Public License (versio 2 tai uudempi) alaisena." #define STR_3204 "LICENSE.txt-tiedostossa on tarkempia tietoja." -/* UI: dialog: Localization (3210.) */ +/* UI dialog: Localization (3210.) */ #define STR_LOCALIZE "Lokalisaatio" #define STR_3211 "Englannista muille kielille kääntäneet:" /* UI dialog: Status (3225.) */ -#define STR_STATUS "Tila" +/* (Unused now) */ /* UI dialog: Sound Gain (3250.) */ #define STR_SNDGAIN "Äänen Gain" @@ -189,23 +188,16 @@ #define STR_3328 "Wait states:" #define STR_3329 "Muisti:" #define STR_3330 "MT" -#define STR_3331 "Käytä aikasynkronointia" +#define STR_3331 "Käytä aikasynkronointia:" #define STR_3332 "Käytä matematiikkasuoritinta" #define STR_3333 "Dynaaminen uudelleenkääntäjä" #define STR_3334 "KT" #define STR_3335 "Oletus" +#define STR_3336 "Käytössä (UTC)" /* UI dialog: Settings (Video, 3350.) */ #define STR_3350 "Video:" -#define STR_3351 "Videonopeus:" -#define STR_3352 "Voodoo-grafiikat" -#define STR_3353 "Oletus" -#define STR_3354 "8-bittinen" -#define STR_3355 "Hidas 16-bittinen" -#define STR_3356 "Nopea 16-bittinen" -#define STR_3357 "Hidas VLB/PCI" -#define STR_3358 "Keskinopea VLB/PCI" -#define STR_3359 "Nopea VLB/PCI" +#define STR_3351 "Voodoo-grafiikat" /* UI dialog: Settings (Input, 3375.) */ #define STR_3375 "Hiiri:" @@ -238,8 +230,8 @@ /* UI dialog: Settings (Other Devices, 3475.) */ #define STR_3475 "SCSI-ohjain:" #define STR_3476 "Kiintolevyohjain:" -#define STR_3477 "Tertiäärinen IDE:" -#define STR_3478 "Kvarternäärinen IDE:" +#define STR_3477 "Tertiäärinen IDE" +#define STR_3478 "Kvarternäärinen IDE" #define STR_3479 "ISABugger-laite" #define STR_3480 "ISA-muistilaajennus" #define STR_3481 "ISA-kello/RTC-kortti" @@ -260,10 +252,9 @@ #define STR_3512 "Oma (suuri)..." #define STR_3515 "ST506" #define STR_3516 "ESDI" -#define STR_3517 "IDE (vain PIO)" -#define STR_3518 "IDE (PIO+DMA)" -#define STR_3519 "SCSI" -#define STR_3520 "SCSI (irroitettava)" +#define STR_3517 "IDE" +#define STR_3518 "SCSI" +#define STR_3519 "USB" /* UI dialog: Settings (Add Hard Disk, 3525.) */ #define STR_3525 "Lisää kiintolevy" @@ -294,13 +285,12 @@ #define STR_3577 "ZIP-asemat:" #define STR_3578 "ZIP 250" #define STR_3579 "Nopeus" -#define STR_3580 "" -#define STR_3581 "" -#define STR_3582 "ATAPI (vain PIO)" -#define STR_3583 "ATAPI (PIO+DMA)" -#define STR_3584 "SCSI" +#define STR_3580 "ATAPI" +#define STR_3581 "SCSI" +#define STR_3582 "USB" -/* UI dialog: status bar (3900.) */ + +/* UI: Status Bar (3900.) */ #define STR_3900 "(tyhjä)" #define STR_3901 "(isäntäasema %c:)" #define STR_3902 " [Kirjoitussuojattu]" @@ -308,6 +298,7 @@ #define STR_3904 "&Lataa levykuva.." #define STR_3905 "L&ataa edellinen levykuva uudelleen" #define STR_3906 "&Poista" +#define STR_3907 "&Huomauta levyn vaihdosta" #define STR_3910 "Levyke %i (%s): %ls" #define STR_3911 "Kaikki levykuvat\0*.0??;*.1??;*.360;*.720;*.86f;*.bin;*.cq?;*.dsk;*.flp;*.hdm;*.im?;*.json;*.td0;*.*fd?;*.xdf\0Edistyneet sektorilevykuvat\0*.imd;*.json;*.td0\0Perussektorilevykuvat\0*.0??;*.1??;*.360;*.720;*.bin;*.cq?;*.dsk;*.flp;*.hdm;*.im?;*.xdf;*.*fd?\0Virtauslevykuvat\0*.fdi\0Pintalevykuvat\0*.86f\0Kaikki tiedostot\0*.*\0" @@ -315,24 +306,21 @@ #define STR_3913 "Pintalevykuvat\0*.86f\0" #define STR_3914 "&Vie 86F-formaattiin..." -#define STR_3920 "CD-ROM %i (%s): %s" +#define STR_3920 "CD-ROM %i (%ls): %ls" #define STR_3921 "Isäntä CD/DVD-asema (%c:)" #define STR_3922 "Levykuvat\0*.iso;*.cue\0Kaikki tiedostot (*.*)\0*.*\0" #define STR_3923 "&Mykistä" -#define STR_3930 "Kiintolevy (%s)" +#define STR_3930 "Kiintolevy %i (%ls): %ls" -#define STR_3940 "Irroitettava levy %i: %ls" -#define STR_3941 "&Huomauta levyn vaihdosta" - -#define STR_3950 "ZIP %i (%03i): %ls" +#define STR_3950 "ZIP%03i %i (%ls): %ls" #define STR_3951 "ZIP-levykuvat\0*.im?;*.zdi\0Kaikki tiedostot\0*.*\0" #define STR_3952 "ZIP-levykuvat\0*.im?;*.zdi\0" -#define STR_3960 "Verkko" -#define STR_3970 "Ääni" +#define STR_3960 "Verkko (%s)" +#define STR_3970 "Ääni (%s)" -/* Menu: Action (4000.) */ +/* UI menu: Action (4000.) */ #define STR_ACTION "&Toiminto" #define STR_4001 "&Pakkouudelleenkäynnistys" #define STR_4002 "&Ctrl+Alt+Del" @@ -341,25 +329,25 @@ #define STR_4005 "&Pysäytä" #define STR_4006 "P&oistu" -/* Menu: View (4010.) */ + +/* UI menu: View (4010.) */ #define STR_VIEW "&Näkymä" #define STR_4011 "Koonmuutokset &salliva ikkuna" #define STR_4012 "&Muista koko ja sijainti" #define STR_4013 "&Koko näyttö\tCtrl+Alt+PageUP" #define STR_4014 "&Oikea CTRL on vasen ALT" -#define STR_4015 "&Päivitä tilapalkin kuvakkeet" -/* Menu: View > Renderer */ +/* UI menu: View > Renderer (4020.) */ #define STR_4020 "Re&nderer" -/* Menu: View > Window Scale Factor */ +/* UI menu: View > Window Scale Factor (4030.) */ #define STR_4030 "Ikkunan skaalaustekijä" #define STR_4031 "&0.5x" #define STR_4032 "&1x" #define STR_4033 "1.&5x" #define STR_4034 "&2x" -/* Menu: View > Fullscreen Stretch Mode */ +/* UI menu: View > Fullscreen Stretch Mode (4040.) */ #define STR_4040 "Koko näytön &venytystila" #define STR_4041 "&Koko näytön venytys" #define STR_4042 "&4:3" @@ -367,14 +355,15 @@ #define STR_4044 "K&okonaislukuasteikko" #define STR_4045 "&Pidä koko" -/* Menu: Display (4050.) */ + +/* UI menu: Display (4050.) */ #define STR_DISPLAY "&Näyttö" #define STR_4051 "Kään&teinen näyttö" #define STR_4052 "Käytä &yliskannausta" #define STR_4053 "&Pakota 4:3-kuvasuhde" #define STR_4054 "Muuta yksivärinäytön &kontrastia" -/* Menu: Display > Display Type */ +/* UI menu: Display > Display Type (4060.) */ #define STR_DISPTYPE "Nä&yttötyyppi" #define STR_4061 "RGB-&värinäyttö" #define STR_4062 "&Harmaasävynäyttö" @@ -382,24 +371,28 @@ #define STR_4064 "&Vihreä näyttö" #define STR_4065 "V&alkoinen näyttö" -/* Menu: Display > Grayscale Conversion Type */ +/* UI menu: Display > Grayscale Conversion Type (4070.) */ #define STR_GRAYSCALE "&Harmaasävykäännöksen tyyppi" #define STR_4071 "BT&601 (NTSC/PAL)" #define STR_4072 "BT&709 (HDTV)" #define STR_4073 "&Keskiarvo" -/* Menu: Tools (4080.) */ + +/* UI menu: Tools (4080.) */ #define STR_TOOLS "&Työkalut" #define STR_4081 "&Asetukset" #define STR_4082 "&Kieli" #define STR_4083 "L&oggaus" -#define STR_4084 "&Lataa konfiguraatio" -#define STR_4085 "&Tallenna konfiguraatio" -#define STR_4086 "T&ila" -#define STR_4087 "Ota k&uvankaappaus\tCtrl+Home" +#define STR_4084 "Log Breakpoint" +#define STR_4085 "Toggle %s logging" +#define STR_4086 "&Lataa konfiguraatio" +#define STR_4087 "&Tallenna konfiguraatio" +#define STR_4088 "Ota k&uvankaappaus" -/* Menu: Help (4090.) */ + +/* UI menu: Help (4090.) */ #define STR_HELP "&Apua" #define STR_4091 "&Tietoja VARCemista" + /* End of file. */ diff --git a/src/ui/lang/VARCem-FR.str b/src/ui/lang/VARCem-FR.str index c9ba2c6..455b662 100644 --- a/src/ui/lang/VARCem-FR.str +++ b/src/ui/lang/VARCem-FR.str @@ -8,7 +8,7 @@ * * String definitions for "French (France)" language. * - * Version: @(#)VARCem-FR.str 1.0.11 2018/09/23 + * Version: @(#)VARCem-FR.str 1.0.11 2018/10/01 * * Authors: Altheos, * Fred N. van Kempen, @@ -47,10 +47,12 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* Do not translate! */ -#define TAG_VERSION 1,0,10 -#define TAG_AUTHOR "Altheos" -#define TAG_EMAIL "altheos@varcem.com" +/* Main application strings (2000) - DO NOT TRANSLATE! */ +#define STR_VERSION 1,0,11 +#define STR_AUTHOR "Altheos" +#define STR_EMAIL "altheos@varcem.com" +#define STR_NAME "VARCem" +#define STR_TITLE "Virtual ARchaeological Computer EMulator" /* Messagebox classes (2100.) */ @@ -66,27 +68,24 @@ #define STR_2202 "PCap n'a pas pu démarrer car il n'est peut-être pas initialisé" #define STR_2203 "Pas de périphérique PCap trouvé" #define STR_2204 "Périphérique PCap non valide" -#define STR_2205 "Impossible de démarrer OpenAL, vérifiez que vous disposez de la bibliothèque suivante\ndans le dossier du programme:\n\nlibopenal-1.dll" -#define STR_2206 "Impossible de démarrer FluidSynth, vérifiez que vous disposez des bibliothèques suivantes\ndans le dossier du programme:\n\nlibfluidsynth.dll" -#define STR_2207 "System out of memory!" +#define STR_2205 "Impossible de démarrer %s, vérifiez que vous disposez de la bibliothèque suivante\ndans le dossier du programme:\n\n%s" /* Application error messages (2300.) */ -#define STR_2300 "Impossible de créer le fichier bitmap: %s" +#define STR_2300 "Mémoire vive insuffisante!" #define STR_2301 "Pas de fichiers ROM trouvés!" #define STR_2302 "Configuration non valide.\n\nVoulez-vous lancer le menu Paramètres pour en créer une ?" -#define STR_2303 "La machine configurée:\n\n %ls\n\nn'est pas disponible.\n\nVoulez-vous aller au menu Paramètres?" -#define STR_2304 "La carte graphique configurée:\n\n %ls\n\nn'est pas disponible.\n\nVoulez-vous aller au menu Paramètres?" -#define STR_2305 "La méthode de rendu sélectionnée '%S' n'est pas disponible. Revenir au paramétrage par défaut ?" -#define STR_2306 "Les CD-ROM ST506 ou ESDI n'ont jamais existé" +#define STR_2303 "La %ls configureé:\n\n %s\n\nn'est pas disponible.\n\nVoulez-vous aller au menu Paramètres?" +#define STR_2304 "La méthode de rendu sélectionnée:\n\n %s\n\nn'est pas disponible. Revenir au paramétrage par défaut ?" +#define STR_2305 "Vous devez enregistrer vos paramètres avant!" +#define STR_2306 "Impossible de créer le fichier bitmap: %ls" #define STR_2307 "Le bus USB n'est pas implémenté" -#define STR_2308 "Vous devez enregistrer vos nouveaux paramètres avant!" /* Application messages (2400.) */ #define STR_2400 "Etes-vous sûr de vouloir utiliser ces paramètres?\n\n(Un redémarrage peut être requis..)" #define STR_2401 "Changements sauvegardés, veuillez redémarrer l'émulateur!" -#define STR_2402 "Le périphérique demandé '%ls' est 'en cours de développement' pour le moment et peut ne pas fonctionner correctement.\n\nEtes-vous sûr de vouloir l'activer ?" +#define STR_2402 "Le périphérique demandé:\n\n %s\n\nest 'en cours de développement' pour le moment et peut ne pas fonctionner correctement.\n\nEtes-vous sûr de vouloir l'activer ?" #define STR_2403 "Cliquer pour capturer la souris" #define STR_2404 "Appuyer sur F8+F12 pour libérer la souris" #define STR_2405 "Appuyer sur F8+F12 ou le bouton central pour libérer la souris" @@ -100,15 +99,19 @@ /* UI: common elements (3000.) */ #define STR_OK "Valider" #define STR_CANCEL "Annuler" +#define STR_YES "Oui" +#define STR_NO "Non" #define STR_CONFIGURE "Configurer" #define STR_BROWSE "Parcourir" + /* UI: dialog shared strings (3100.) */ #define STR_NONE "Aucun" +#define STR_INTERNAL "Carte Intégrée" #define STR_DISABLED "Désactivé" #define STR_ENABLED "Activé" -#define STR_OFF "Off" -#define STR_ON "On" +#define STR_OFF "Arrêt" +#define STR_ON "Marche" #define STR_TYPE "Type" #define STR_FILENAME "Nom:" #define STR_PROGRESS "Progression:" @@ -124,19 +127,19 @@ #define STR_DEVCONF_2 "Appareil:" -/* UI: dialog: About (3200.) */ +/* UI dialog: About (3200.) */ #define STR_ABOUT "A propos de VARCem.." #define STR_3201 "Auteurs:" -#define STR_3202 "Fred N. van Kempen, Miran Grca, Sarah Walker et d'autres.\nBasé sur 86Box, PCem, MAME, DOSbox et Qemu.", -#define STR_3203 "L'intégralite du code, existant et celui adapté d'autres projets, est conforme à la licence BSD (BSD-3-Clause), ainsi qu'à la licence GNU (version 2 et plus).", -#define STR_3204 "Voir le fichier LICENSE.txt pour plus de détails.", +#define STR_3202 "Fred N. van Kempen, Miran Grca, Sarah Walker et d'autres.\nBasé sur 86Box, PCem, MAME, DOSbox et Qemu." +#define STR_3203 "L'intégralite du code, existant et celui adapté d'autres projets, est conforme à la licence BSD (BSD-3-Clause), ainsi qu'à la licence GNU (version 2 et plus)." +#define STR_3204 "Voir le fichier LICENSE.txt pour plus de détails." -/* UI: dialog: Localization (3210.) */ +/* UI dialog: Localization (3210.) */ #define STR_LOCALIZE "Localisation" #define STR_3211 "Contributeurs des traductions de l'anglais vers les autres langues:" /* UI dialog: Status (3225.) */ -#define STR_STATUS "Statut" +/* (Unused now) */ /* UI dialog: Sound Gain (3250.) */ #define STR_SNDGAIN "Gain du son" @@ -185,23 +188,16 @@ #define STR_3328 "Etats d'attentes:" #define STR_3329 "Mémoire vive:" #define STR_3330 "Mo" -#define STR_3331 "Synchro temps avec l'hôte" +#define STR_3331 "Synchro temps avec l'hôte:" #define STR_3332 "Activer la FPU" #define STR_3333 "Recompilation dynamique" #define STR_3334 "ko" #define STR_3335 "Défaut" +#define STR_3336 "Activé (UTC)" /* UI dialog: Settings (Video, 3350.) */ #define STR_3350 "Carte vidéo:" -#define STR_3351 "Vitesse de la carte:" -#define STR_3352 "3DFX Voodoo" -#define STR_3353 "Défaut" -#define STR_3354 "8-bit" -#define STR_3355 "16-bit lente" -#define STR_3356 "16-bit rapide" -#define STR_3357 "VLB/PCI lente" -#define STR_3358 "VLB/PCI intermédiaire" -#define STR_3359 "VLB/PCI rapide" +#define STR_3351 "3DFX Voodoo" /* UI dialog: Settings (Input, 3375.) */ #define STR_3375 "Souris:" @@ -234,8 +230,8 @@ /* UI dialog: Settings (Other Devices, 3475.) */ #define STR_3475 "Contrôleur SCSI:" #define STR_3476 "Contrôleur HDD:" -#define STR_3477 "3ème interface IDE:" -#define STR_3478 "4ème interface IDE:" +#define STR_3477 "3ème interface IDE" +#define STR_3478 "4ème interface IDE" #define STR_3479 "Carte ISABugger" #define STR_3480 "Carte d'extension mémoire ISA" #define STR_3481 "Carte d'horloge temps réel" @@ -253,14 +249,12 @@ #define STR_3509 "Mo" #define STR_3510 "Mo (CHS: %u, %u, %u)" #define STR_3511 "Personnalisé..." -#define STR_3512 "Personnalisé (large)..." +#define STR_3512 "Personnalisé (grande capacité)..." #define STR_3515 "ST506" #define STR_3516 "ESDI" -#define STR_3517 "IDE (PIO)" -#define STR_3518 "IDE (PIO+DMA)" -#define STR_3519 "SCSI" -#define STR_3520 "SCSI (Amovible)" -#define STR_3521 "USB" +#define STR_3517 "IDE" +#define STR_3518 "SCSI" +#define STR_3519 "USB" /* UI dialog: Settings (Add Hard Disk, 3525.) */ #define STR_3525 "Ajout d'un disque dur" @@ -291,14 +285,12 @@ #define STR_3577 "Lecteurs ZIP:" #define STR_3578 "ZIP 250" #define STR_3579 "Vitesse" -#define STR_3580 "" -#define STR_3581 "" -#define STR_3582 "ATAPI (PIO)" -#define STR_3583 "ATAPI (PIO+DMA)" -#define STR_3584 "SCSI" -#define STR_3585 "USB" +#define STR_3580 "ATAPI" +#define STR_3581 "SCSI" +#define STR_3582 "USB" -/* UI dialog: status bar (3900.) */ + +/* UI: Status Bar (3900.) */ #define STR_3900 "(vide)" #define STR_3901 "(Lecteur hôte %c:)" #define STR_3902 " [Protégé en écriture]" @@ -306,6 +298,7 @@ #define STR_3904 "&Image existante..." #define STR_3905 "&Recharger l'image précédente" #define STR_3906 "E&jecter" +#define STR_3907 "&Notification de changement de disque" #define STR_3910 "Disquette %i (%s): %ls" #define STR_3911 "Toutes les images\0*.0??;*.1??;*.360;*.720;*.86f;*.bin;*.cq?;*.dsk;*.flp;*.hdm;*.im?;*.json;*.td0;*.*fd?;*.xdf\0Images secteur avancées\0*.imd;*.json;*.td0\0Images secteur basiques\0*.0??;*.1??;*.360;*.720;*.bin;*.cq?;*.dsk;*.flp;*.hdm;*.im?;*.xdf;*.*fd?\0Images Flux\0*.fdi\0Images de surface\0*.86f\0Tous les fichiers\0*.*\0" @@ -313,24 +306,21 @@ #define STR_3913 "Images de surface\0*.86f\0" #define STR_3914 "E&xport au format 86F..." -#define STR_3920 "CD-ROM %i (%s): %s" +#define STR_3920 "CD-ROM %i (%ls): %ls" #define STR_3921 "Lecteurs CD/DVD de l'hôte (%c:)" #define STR_3922 "Images CD-ROM \0*.iso;*.cue\0Tous les fichiers (*.*)\0*.*\0" #define STR_3923 "&Muet" -#define STR_3930 "Disque dur (%s)" +#define STR_3930 "Disque dur %i (%ls): %ls" -#define STR_3940 "Disque amovible %i: %ls" -#define STR_3941 "&Notification de changement de disque" - -#define STR_3950 "ZIP %i (%03i): %ls" +#define STR_3950 "ZIP%03i %i (%ls): %ls" #define STR_3951 "Images ZIP\0*.im?;*.zdi\0Tous les fichiers\0*.*\0" #define STR_3952 "Images ZIP\0*.im?;*.zdi\0" -#define STR_3960 "Résau" -#define STR_3970 "Son" +#define STR_3960 "Résau (%s)" +#define STR_3970 "Son (%s)" -/* Menu: Action (4000.) */ +/* UI menu: Action (4000.) */ #define STR_ACTION "&Action" #define STR_4001 "&Redémarrage à froid" #define STR_4002 "&Ctrl+Alt+Del" @@ -339,25 +329,25 @@ #define STR_4005 "&Pause" #define STR_4006 "&Quitter" -/* Menu: View (4010.) */ + +/* UI menu: View (4010.) */ #define STR_VIEW "&Affichage" #define STR_4011 "&Redimensionner la fenêtre" #define STR_4012 "G&arder la taille et la position" #define STR_4013 "&Plein écran\tCtrl+Alt+PageUP" #define STR_4014 "CTRL& droit devient ALT gauche" -#define STR_4015 "&Mise à jour de la barre d'état" -/* Menu: View > Renderer */ +/* UI menu: View > Renderer (4020.) */ #define STR_4020 "Mé&thode de rendu" -/* Menu: View > Window Scale Factor */ +/* UI menu: View > Window Scale Factor (4030.) */ #define STR_4030 "&Facteur d'agrandissement" #define STR_4031 "&0.5x" #define STR_4032 "&1x" #define STR_4033 "1.&5x" #define STR_4034 "&2x" -/* Menu: View > Fullscreen Stretch Mode */ +/* UI menu: View > Fullscreen Stretch Mode (4040.) */ #define STR_4040 "Mode plein écran" #define STR_4041 "&Etirer à la taille de l'écran" #define STR_4042 "&Format 4:3" @@ -365,14 +355,15 @@ #define STR_4044 "&Ratio d'entiers" #define STR_4045 "&Garder la taille d'origine" -/* Menu: Display (4050.) */ + +/* UI menu: Display (4050.) */ #define STR_DISPLAY "&Ecran" #define STR_4051 "&Couleurs négatives" #define STR_4052 "Activer l'&overscan" #define STR_4053 "F&orcer le ratio 4:3" #define STR_4054 "Changer le &contraste de l'écran monochrome" -/* Menu: Display > Display Type */ +/* UI menu: Display > Display Type (4060.) */ #define STR_DISPTYPE "Type d'&écran" #define STR_4061 "Moniteur RGB &couleur" #define STR_4062 "Moniteur &Monochrome" @@ -380,23 +371,26 @@ #define STR_4064 "Moniteur &vert" #define STR_4065 "Moniteur &blanc" -/* Menu: Display > Grayscale Conversion Type */ +/* UI menu: Display > Grayscale Conversion Type (4070.) */ #define STR_GRAYSCALE "&Type de conversion monochrome" #define STR_4071 "BT&601 (NTSC/PAL)" #define STR_4072 "BT&709 (HDTV)" #define STR_4073 "&Moyen" -/* Menu: Tools (4080.) */ + +/* UI menu: Tools (4080.) */ #define STR_TOOLS "&Outils" #define STR_4081 "&Paramètres" #define STR_4082 "&Langue" -#define STR_4083 "&Activer les traces" -#define STR_4084 "C&harger une configuration" -#define STR_4085 "S&auvegarder une configuration" -#define STR_4086 "&Statut" -#define STR_4087 "&Capturer une image de l'écran\tCtrl+Home" +#define STR_4083 "&Traces" +#define STR_4084 "Point d'arrêt" +#define STR_4085 "Activer les traces %s" +#define STR_4086 "C&harger une configuration" +#define STR_4087 "S&auvegarder une configuration" +#define STR_4088 "&Capturer une image de l'écran" -/* Menu: Help (4090.) */ + +/* UI menu: Help (4090.) */ #define STR_HELP "&Aide" #define STR_4091 "&A propos de VARCem" diff --git a/src/ui/lang/VARCem-IT.str b/src/ui/lang/VARCem-IT.str index b00e455..f50d261 100644 --- a/src/ui/lang/VARCem-IT.str +++ b/src/ui/lang/VARCem-IT.str @@ -8,7 +8,7 @@ * * String definitions for "Italian (Italy)" language. * - * Version: @(#)VARCem-IT.str 1.0.8 2018/09/23 + * Version: @(#)VARCem-IT.str 1.0.8 2018/10/01 * * Authors: Miran Grca, * Fred N. van Kempen, @@ -47,10 +47,13 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* Do not translate! */ -#define TAG_VERSION 1,0,7 -#define TAG_AUTHOR "Miran Grca" -#define TAG_EMAIL "mgrca8@gmail.com" +/* Main application strings (2000) - DO NOT TRANSLATE! */ +#define STR_VERSION 1,0,8 +#define STR_AUTHOR "Miran Grca" +#define STR_EMAIL "mgrca8@gmail.com" +#define STR_NAME "VARCem" +#define STR_TITLE "Virtual ARchaeological Computer EMulator" + /* Messagebox classes (2100.) */ #define STR_2100 "Errore" @@ -65,27 +68,24 @@ #define STR_2202 "Non è stato possible impostare PCap perché potrebbe non essere inizializzato" #define STR_2203 "Non è stato trovato nessun dispositivo PCap" #define STR_2204 "Dispositivo PCap non valido" -#define STR_2205 "Non è possibile inizializzare OpenAL, assicurarsi che le seguenti biblioteche\nsiano nella cartella del programma:\n\nlibopenal-1.dll" -#define STR_2206 "Non è possibile inizializzare FluidSynth, assicurarsi che le seguenti biblioteche\nsiano nella cartella del programma:\n\nlibfluidsynth.dll" -#define STR_2207 "System out of memory!" +#define STR_2205 "Non è possibile inizializzare %s, assicurarsi che le seguenti biblioteche\nsiano nella cartella del programma:\n\n%s" /* Application error messages (2300.) */ -#define STR_2300 "Impossibile creare il file bitmap: %s" +#define STR_2300 "System out of memory!" #define STR_2301 "Non è stata trovata nessuna immagine ROM utilizzabile!" #define STR_2302 "Non è stata trovata nessuna configurazione valida.\n\nSi desidera entrare nella finestra Impostazioni per crearne una?" -#define STR_2303 "Il computer configurato:\n\n %ls\n\nnon è disponibile.\n\nSi desidera entrare nella finestra Impostazioni?" -#define STR_2304 "La scheda video configurata:\n\n %ls\n\nnon è disponibile.\n\nSi desidera entrare nella finestra Impostazioni?" -#define STR_2305 "Il renderer selezionato '%S' non è disponibile. Riporlo all'opzione predefinita?" -#define STR_2306 "Unità CD-ROM ST506 o ESDI CD-ROM non sono mai esistite" +#define STR_2303 "Il %ls configurato:\n\n %s\n\nnon è disponibile.\n\nSi desidera entrare nella finestra Impostazioni?" +#define STR_2304 "Il renderer selezionato:\n\n %s\n\nnon è disponibile. Riporlo all'opzione predefinita?" +#define STR_2305 "You must save your settings first!" +#define STR_2306 "Impossibile creare il file bitmap: %ls" #define STR_2307 "USB non è ancora supportato" -#define STR_2308 "You must save your settings first!" /* Application messages (2400.) */ #define STR_2400 "Si desidera salvare queste impostazioni?\n\n(Potrebbe essere necessario un riavvio...)" #define STR_2401 "Cambiamenti salvati, si prega di riavviare l'emulatore!" -#define STR_2402 "Il dispositive richiesto '%ls' è almomento considerato «Sotto sviluppo» e potrebbe causare problemi.\n\nSi desidera comunque attivarlo?" +#define STR_2402 "Il dispositive richiesto:\n\n %s\n\nè almomento considerato «Sotto sviluppo» e potrebbe causare problemi.\n\nSi desidera comunque attivarlo?" #define STR_2403 "Fare clic per catturare il mouse" #define STR_2404 "Premere F8+F12 per rilasciare il mouse" #define STR_2405 "Premere F8+F12 o pulsante centrale per rilassare il mouse" @@ -99,11 +99,15 @@ /* UI: common elements (3000.) */ #define STR_OK "OK" #define STR_CANCEL "Annulla" +#define STR_YES "Yes" +#define STR_NO "No" #define STR_CONFIGURE "Configura" #define STR_BROWSE "Sfoglia" + /* UI: dialog shared strings (3100.) */ #define STR_NONE "Nessuno" +#define STR_INTERNAL "Internal" #define STR_DISABLED "Disattivato" #define STR_ENABLED "Attivato" #define STR_OFF "Spento" @@ -123,19 +127,18 @@ #define STR_DEVCONF_2 "Dispositivo:" -/* UI: dialog: About (3200.) */ +/* UI dialog: About (3200.) */ #define STR_ABOUT "Informazioni su VARCem..." #define STR_3201 "Autori:" #define STR_3202 "Fred N. van Kempen, Miran Grca, Sarah Walker e altri.\nBasato su opere anteriori come 86Box, PCem, MAME, DOSbox e Qemu." #define STR_3203 "Rilasciato sotto le licenze BSD 3-Clause License e GNU General Public License (versione 2 o superiore) por codice existene, importato da altri progetti." #define STR_3204 "Per ulteriori informazioni vedere il file LICENSE.txt." - -/* UI: dialog: Localization (3210.) */ +/* UI dialog: Localization (3210.) */ #define STR_LOCALIZE "Localization" #define STR_3211 "Translations from English to these other languages contributed by:" /* UI dialog: Status (3225.) */ -#define STR_STATUS "Stato" +/* (Unused now) */ /* UI dialog: Sound Gain (3250.) */ #define STR_SNDGAIN "Guadagno sonoro" @@ -184,23 +187,16 @@ #define STR_3328 "Wait state:" #define STR_3329 "Memoria:" #define STR_3330 "MB" -#define STR_3331 "Attiva sincronizzazione ora" +#define STR_3331 "Attiva sincronizzazione ora:" #define STR_3332 "Attiva coprocessore" #define STR_3333 "Ricompilatore dinamico" #define STR_3334 "KB" #define STR_3335 "Predefinito" +#define STR_3336 "Attivato (UTC)" /* UI dialog: Settings (Video, 3350.) */ #define STR_3350 "Video:" -#define STR_3351 "Velocità video:" -#define STR_3352 "Grafica Voodoo" -#define STR_3353 "Predefinito" -#define STR_3354 "A 8 bit" -#define STR_3355 "Lenta a 16 bit" -#define STR_3356 "Veloce a 16 bit" -#define STR_3357 "Lenta VLB/PCI" -#define STR_3358 "Media VLB/PCI" -#define STR_3359 "Veloce VLB/PCI" +#define STR_3351 "Grafica Voodoo" /* UI dialog: Settings (Input, 3375.) */ #define STR_3375 "Mouse:" @@ -233,8 +229,8 @@ /* UI dialog: Settings (Other Devices, 3475.) */ #define STR_3475 "Controller SCSI:" #define STR_3476 "Conctroller HD:" -#define STR_3477 "IDE terziario:" -#define STR_3478 "IDE quaternario:" +#define STR_3477 "IDE terziario" +#define STR_3478 "IDE quaternario" #define STR_3479 "Dispositivo ISABugger" #define STR_3480 "ISA Memory Expansion" #define STR_3481 "ISA Clock/RTC Card" @@ -255,10 +251,9 @@ #define STR_3512 "Personalizzato (grande)..." #define STR_3515 "ST506" #define STR_3516 "ESDI" -#define STR_3517 "IDE (solo PIO)" -#define STR_3518 "IDE (PIO+DMA)" -#define STR_3519 "SCSI" -#define STR_3520 "SCSI (rimuovibile)" +#define STR_3517 "IDE" +#define STR_3518 "SCSI" +#define STR_3519 "USB" /* UI dialog: Settings (Add Hard Disk, 3525.) */ #define STR_3525 "Aggiungi hard disk" @@ -274,7 +269,6 @@ #define STR_3535 "Immagini HDI o HDX con dimensione di settore diversa da 512 non sono supportate" #define STR_3536 "Immagini hard disk\0*.hd?;*.im?;*.vhd\0Tutti i file\0*.*\0" #define STR_3537 "Ricordarsi di partizionare e formattare il disco nuovo" - /* UI dialog: Settings (Floppy Drives, 3550.) */ #define STR_3550 "Unità floppy:" #define STR_3551 "Tipo:" @@ -289,14 +283,12 @@ #define STR_3577 "Unità ZIP:" #define STR_3578 "ZIP 250" #define STR_3579 "Velocità" -#define STR_3580 "" -#define STR_3581 "" -#define STR_3582 "ATAPI (solo PIO)" -#define STR_3583 "ATAPI (PIO+DMA)" -#define STR_3584 "SCSI" -#define STR_3585 "USB" +#define STR_3580 "ATAPI" +#define STR_3581 "SCSI" +#define STR_3582 "USB" -/* UI dialog: status bar (3900.) */ + +/* UI: Status Bar (3900.) */ #define STR_3900 "(vuoto)" #define STR_3901 "(unità host %c:)" #define STR_3902 " [Protetto contro la scrittura]" @@ -304,6 +296,7 @@ #define STR_3904 "&Carica immagine..." #define STR_3905 "&Ricarica immagine precedente" #define STR_3906 "&Espelli" +#define STR_3907 "&Notifica cambio di disco" #define STR_3910 "Floppy %i (%s): %ls" #define STR_3911 "Tutte le immagini\0*.0??;*.1??;*.360;*.720;*.86f;*.bin;*.cq?;*.dsk;*.flp;*.hdm;*.im?;*.json;*.td0;*.*fd?;*.xdf\0Immagini di settori avvanzate\0*.imd;*.json;*.td0\0Immagini di settori basiche\0*.0??;*.1??;*.360;*.720;*.bin;*.cq?;*.dsk;*.flp;*.hdm;*.im?;*.xdf;*.*fd?\0Immagini di flusso magnetico\0*.fdi\0Immagini bitstream\0*.86f\0Tutti i file\0*.*\0" @@ -311,24 +304,21 @@ #define STR_3913 "Immagini bistream\0*.86f\0" #define STR_3914 "E&sportare in 86F..." -#define STR_3920 "CD-ROM %i (%s): %s" +#define STR_3920 "CD-ROM %i (%ls): %ls" #define STR_3921 "Unità CD/DVD host (%c:)" #define STR_3922 "Immagini CD-ROM\0*.iso;*.cue\0Tutti i file (*.*)\0*.*\0" #define STR_3923 "&Muto" -#define STR_3930 "Hard disk (%s)" +#define STR_3930 "Hard disk %i (%ls): %ls" -#define STR_3940 "Disco rimuovibile %i: %ls" -#define STR_3941 "&Notifica cambio di disco" - -#define STR_3950 "ZIP %i (%03i): %ls" +#define STR_3950 "ZIP%03i %i (%ls): %ls" #define STR_3951 "Immagini ZIP\0*.im?;*.zdi\0All files\0*.*\0" #define STR_3952 "Immagini ZIP\0*.im?;*.zdi\0" -#define STR_3960 "Rete" -#define STR_3970 "Suono" +#define STR_3960 "Rete (%s)" +#define STR_3970 "Suono (%s)" -/* Menu: Action (4000.) */ +/* UI menu: Action (4000.) */ #define STR_ACTION "&Azione" #define STR_4001 "&Riavvio completo" #define STR_4002 "&Ctrl+Alt+Canc" @@ -337,25 +327,25 @@ #define STR_4005 "&Pausa" #define STR_4006 "U&scita" -/* Menu: View (4010.) */ + +/* UI menu: View (4010.) */ #define STR_VIEW "&Visualizza" #define STR_4011 "&Finestra ridimensionabile" #define STR_4012 "R&icorda dimensioni e posizione" #define STR_4013 "&Schermo intero\tCtrl+Alt+PageUP" #define STR_4014 "CTRL &destro è ALT sinistro" -#define STR_4015 "&Aggiora icone della barra di stato" -/* Menu: View > Renderer */ +/* UI menu: View > Renderer (4020.) */ #define STR_4020 "Re&nderer" -/* Menu: View > Window Scale Factor */ +/* UI menu: View > Window Scale Factor (4030.) */ #define STR_4030 "&Fattore di scala in finistra" #define STR_4031 "&0.5x" #define STR_4032 "&1x" #define STR_4033 "1.&5x" #define STR_4034 "&2x" -/* Menu: View > Fullscreen Stretch Mode */ +/* UI menu: View > Fullscreen Stretch Mode (4040.) */ #define STR_4040 "Modalità &allungamento a schermo intero" #define STR_4041 "&Allunga a tutto lo schermo" #define STR_4042 "&4:3" @@ -363,14 +353,15 @@ #define STR_4044 "&Scala a numeri interi" #define STR_4045 "&Mantieni proporzioni" -/* Menu: Display (4050.) */ + +/* UI menu: Display (4050.) */ #define STR_DISPLAY "&Monitor" #define STR_4051 "Monitor &invertito" #define STR_4052 "Abilita &overscan" #define STR_4053 "F&orza proporzioni 4:3" #define STR_4054 "Cambia &contrasto per monitor monocromatico" -/* Menu: Display > Display Type */ +/* UI menu: Display > Display Type (4060.) */ #define STR_DISPTYPE "&Tipo monitor" #define STR_4061 "Monitor RGB a &colori" #define STR_4062 "Monitor a scala di &grigi" @@ -378,23 +369,26 @@ #define STR_4064 "Monitor &verde" #define STR_4065 "Monitor &bianco" -/* Menu: Display > Grayscale Conversion Type */ +/* UI menu: Display > Grayscale Conversion Type (4070.) */ #define STR_GRAYSCALE "Tipo conversione a scala di &grigi" #define STR_4071 "BT&601 (NTSC/PAL)" #define STR_4072 "BT&709 (HDTV)" #define STR_4073 "&Media" -/* Menu: Tools (4080.) */ + +/* UI menu: Tools (4080.) */ #define STR_TOOLS "&Strumenti" #define STR_4081 "&Impostazioni" #define STR_4082 "&Lingua" #define STR_4083 "R&egistrazione" -#define STR_4084 "Carica &configurazione" -#define STR_4085 "S&alva configurazione" -#define STR_4086 "Stat&o" -#define STR_4087 "&Fare uno screenshot\tCtrl+Home" +#define STR_4084 "Log Breakpoint" +#define STR_4085 "Toggle %s logging" +#define STR_4086 "Carica &configurazione" +#define STR_4087 "S&alva configurazione" +#define STR_4088 "&Fare uno screenshot" -/* Menu: Help (4090.) */ + +/* UI menu: Help (4090.) */ #define STR_HELP "&Guida" #define STR_4091 "&Informazioni VARCem" diff --git a/src/ui/lang/VARCem-JP.str b/src/ui/lang/VARCem-JP.str index c5c0ee8..c001b3e 100644 --- a/src/ui/lang/VARCem-JP.str +++ b/src/ui/lang/VARCem-JP.str @@ -8,7 +8,7 @@ * * String definitions for "Japanese (Japan)" language. * - * Version: @(#)VARCem-JP.str 1.0.10 2018/09/23 + * Version: @(#)VARCem-JP.str 1.0.10 2018/10/01 * * Authors: Basic2004, * Fred N. van Kempen, @@ -47,10 +47,13 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* Do not translate! */ -#define TAG_VERSION 1,0,9 -#define TAG_AUTHOR "Basic2004" -#define TAG_EMAIL "basic2004@gmail.com" +/* Main application strings (2000) - DO NOT TRANSLATE! */ +#define STR_VERSION 1,0,10 +#define STR_AUTHOR "Basic2004" +#define STR_EMAIL "basic2004@gmail.com" +#define STR_NAME "VARCem" +#define STR_TITLE "Virtual ARchaeological Computer EMulator" + /* Messagebox classes (2100.) */ #define STR_2100 "エラー" @@ -65,27 +68,24 @@ #define STR_2202 "PCapデバイスが初期化されていないので設定に失敗しました" #define STR_2203 "PCapデバイスがありません" #define STR_2204 "不正なPCapデバイスです" -#define STR_2205 "OpenALが初期化できません、\nプログラムのフォルダーから下記のライブラリーファイルをご確認ください:\n\nlibopenal-1.dll" -#define STR_2206 "FluidSynthが初期化できません、\nプログラムのフォルダーから下記のライブラリーファイルをご確認ください:\n\nlibfluidsynth.dll" -#define STR_2207 "System out of memory!" +#define STR_2205 "%s が初期化できません、\nプログラムのフォルダーから下記のライブラリーファイルをご確認ください:\n\n%s" /* Application error messages (2300.) */ -#define STR_2300 "ビットマップファイルが生成できません:%s" +#define STR_2300 "System out of memory!" #define STR_2301 "使用可能なROMが見つかりません!" #define STR_2302 "有効な設定が見つかりません。\n\n新たな設定を作るために設定ウィンドウを開きますか?" -#define STR_2303 "設定したマシン:\n\n %ls\n\nは使用できません。\n\n設定ウィンドウを開きますか?" -#define STR_2304 "設定したビデオカード:\n\n %ls\n\nは使用できません。\n\n設定ウィンドウを開きますか?" -#define STR_2305 "設定したレンダラー「%S」は使用できません。既定値に戻しますか?" -#define STR_2306 "ST506またはESDI方式のCD-ROMドライブは存在しません" +#define STR_2303 "設定した%ls:\n\n %s\n\nは使用できません。\n\n設定ウィンドウを開きますか?" +#define STR_2304 "設定したビデオカード:\n\n %s\n\nは使用できません。\n\n設定ウィンドウを開きますか?" +#define STR_2305 "まずは新規設定を保存してください!" +#define STR_2306 "ビットマップファイルが生成できません:%s" #define STR_2307 "USBはまだサポートしません" -#define STR_2308 "まずは新規設定を保存してください!" /* Application messages (2400.) */ #define STR_2400 "現在の設定を保存しますか?\n\n (再起動の必要があるかもしれません...)" #define STR_2401 "設定を保存しました。再起動して下さい!" -#define STR_2402 "要請したデバイス「%ls」は現在開発中なので問題が発生する可能性があります。\n\n使用してもよろしいですか?" +#define STR_2402 "要請したデバイス「\n\n %s\n\n」は現在開発中なので問題が発生する可能性があります。\n\n使用してもよろしいですか?" #define STR_2403 "クリックするとマウスを直接入力します" #define STR_2404 "F12+F8キーでマウスの直接入力を解除します" #define STR_2405 "F12+F8キーまたは中クリックでマウスの直接入力を解除します" @@ -99,11 +99,15 @@ /* UI: common elements (3000.) */ #define STR_OK "OK" #define STR_CANCEL "キャンセル" +#define STR_YES "Yes" +#define STR_NO "No" #define STR_CONFIGURE "設定" #define STR_BROWSE "参照" + /* UI: dialog shared strings (3100.) */ #define STR_NONE "なし" +#define STR_INTERNAL "Internal" #define STR_DISABLED "使用しない" #define STR_ENABLED "使用する" #define STR_OFF "オフ" @@ -123,19 +127,19 @@ #define STR_DEVCONF_2 "デバイス:" -/* UI: dialog: About (3200.) */ +/* UI dialog: About (3200.) */ #define STR_ABOUT "VARCemについて.." #define STR_3201 "著者:" #define STR_3202 "Fred N. van Kempen、Miran Grca、Sarah Walker 外\nこのプログラムは既存の作品(86Box、PCem、MAME、DOSbox、Qemu)を元にして製作されました。" #define STR_3203 "このプログラムは3条項BSDライセンス、既存または他のプロジェクトからインポートしたコードについてはGNU GPL v2以降のライセンスに基いて配布されています。" #define STR_3204 "詳しい情報は LICENSE.txt をお読みください。" -/* UI: dialog: Localization (3210.) */ +/* UI dialog: Localization (3210.) */ #define STR_LOCALIZE "多言語化" #define STR_3211 "VARCemを翻訳してくれた貢献者たちを紹介致します:" /* UI dialog: Status (3225.) */ -#define STR_STATUS "ステータス" +/* (Unused now) */ /* UI dialog: Sound Gain (3250.) */ #define STR_SNDGAIN "音量増加" @@ -184,23 +188,16 @@ #define STR_3328 "待機状態:" #define STR_3329 "メモリ:" #define STR_3330 "MB" -#define STR_3331 "時刻同期化" +#define STR_3331 "時刻同期化:" #define STR_3332 "FPUを使用" #define STR_3333 "動的再コンパイル" #define STR_3334 "KB" #define STR_3335 "既定値" +#define STR_3336 "Enabled (UTC)" /* UI dialog: Settings (Video, 3350.) */ #define STR_3350 "ビデオカード:" -#define STR_3351 "ビデオの速度:" -#define STR_3352 "Voodoo Graphics" -#define STR_3353 "既定値" -#define STR_3354 "8-bit" -#define STR_3355 "低速16-bit" -#define STR_3356 "高速16-bit" -#define STR_3357 "低速VLB/PCI" -#define STR_3358 "中速VLB/PCI" -#define STR_3359 "高速VLB/PCI" +#define STR_3351 "Voodoo Graphics" /* UI dialog: Settings (Input, 3375.) */ #define STR_3375 "マウス:" @@ -233,8 +230,8 @@ /* UI dialog: Settings (Other Devices, 3475.) */ #define STR_3475 "SCSIコントローラー:" #define STR_3476 "HDコントローラー:" -#define STR_3477 "3番目のIDE:" -#define STR_3478 "4番目のIDE:" +#define STR_3477 "3番目のIDE" +#define STR_3478 "4番目のIDE" #define STR_3479 "ISABuggerデバイス" #define STR_3480 "ISAメモリー拡張ボード" #define STR_3481 "ISAクロック/RTCカード" @@ -255,10 +252,9 @@ #define STR_3512 "カスタム (大容量)..." #define STR_3515 "ST506" #define STR_3516 "ESDI" -#define STR_3517 "IDE (PIO専用)" -#define STR_3518 "IDE (PIO+DMA)" -#define STR_3519 "SCSI" -#define STR_3520 "SCSI (リムーバブル)" +#define STR_3517 "IDE" +#define STR_3518 "SCSI" +#define STR_3519 "USB" /* UI dialog: Settings (Add Hard Disk, 3525.) */ #define STR_3525 "ハードディスクの追加" @@ -289,13 +285,12 @@ #define STR_3577 "ZIPドライブ:" #define STR_3578 "ZIP 250" #define STR_3579 "速度" -#define STR_3580 "<予約済>" -#define STR_3581 "<予約済>" -#define STR_3582 "ATAPI (PIO専用)" -#define STR_3583 "ATAPI (PIO+DMA)" -#define STR_3584 "SCSI" +#define STR_3580 "ATAPI" +#define STR_3581 "SCSI" +#define STR_3582 "USB" -/* UI dialog: status bar (3900.) */ + +/* UI: Status Bar (3900.) */ #define STR_3900 "(空)" #define STR_3901 "(ホストドライブ %c:)" #define STR_3902 "[書き込み禁止]" @@ -303,6 +298,7 @@ #define STR_3904 "イメージをロード(&L).." #define STR_3905 "前のイメージをリロード(&R)" #define STR_3906 "取り出し(&U)" +#define STR_3907 "ディスク交換を通知(&N)" #define STR_3910 "フロッピー %i (%s): %ls" #define STR_3911 "すべてのイメージ\0*.0??;*.1??;*.360;*.720;*.86f;*.bin;*.cq?;*.dsk;*.flp;*.hdm;*.im?;*.json;*.td0;*.*fd?;*.xdf\0Advanced sector images\0*.imd;*.json;*.td0\0Basic sector images\0*.0??;*.1??;*.360;*.720;*.bin;*.cq?;*.dsk;*.flp;*.hdm;*.im?;*.xdf;*.*fd?\0Flux images\0*.fdi\0Surface images\0*.86f\0すべてのファイル\0*.*\0" @@ -310,24 +306,21 @@ #define STR_3913 "Surface images\0*.86f\0" #define STR_3914 "86F形式に変換(&X)..." -#define STR_3920 "CD-ROM %i (%s): %s" +#define STR_3920 "CD-ROM %i (%ls): %ls" #define STR_3921 "ホストCD/DVDドライブ (%c:)" #define STR_3922 "CD-ROMイメージ\0*.iso;*.cue\0すべてのファイル (*.*)\0*.*\0" #define STR_3923 "ミュート(&M)" -#define STR_3930 "ハードディスク(%s)" +#define STR_3930 "ハードディスク %i (%ls): %ls" -#define STR_3940 "リムーバブルディスク %i: %ls" -#define STR_3941 "ディスク交換を通知(&N)" - -#define STR_3950 "ZIP %i (%03i): %ls" +#define STR_3950 "ZIP%03i %i (%ls): %ls" #define STR_3951 "ZIP イメージ\0*.im?;*.zdi\0すべてのファイル\0*.*\0" #define STR_3952 "ZIP イメージ\0*.im?;*.zdi\0" -#define STR_3960 "ネットワーク" -#define STR_3970 "サウンド" +#define STR_3960 "ネットワーク (%s)" +#define STR_3970 "サウンド (%s)" -/* Menu: Action (4000.) */ +/* UI menu: Action (4000.) */ #define STR_ACTION "動作(&A)" #define STR_4001 "再起動(&H)" #define STR_4002 "Ctrl+Alt+Delの送信(&C)" @@ -336,25 +329,25 @@ #define STR_4005 "一時停止(&P)" #define STR_4006 "終了(&X)" -/* Menu: View (4010.) */ + +/* UI menu: View (4010.) */ #define STR_VIEW "表示(&V)" #define STR_4011 "ウィンドウのサイズを変更できるようにする(&R)" #define STR_4012 "ウィンドウのサイズと位置を記憶(&E)" #define STR_4013 "フルスクリーン(&F)\tCtrl+Alt+PageUP" #define STR_4014 "右CTRLを左ALTへ(&I)" -#define STR_4015 "ステータスバーアイコンを更新(&U)" -/* Menu: View > Renderer */ +/* UI menu: View > Renderer (4020.) */ #define STR_4020 "レンダラー(&N)" -/* Menu: View > Window Scale Factor */ +/* UI menu: View > Window Scale Factor (4030.) */ #define STR_4030 "ウィンドウの倍率(&W)" #define STR_4031 "0.5x(&0)" #define STR_4032 "1x(&1)" #define STR_4033 "1.5x(&5)" #define STR_4034 "2x(&2)" -/* Menu: View > Fullscreen Stretch Mode */ +/* UI menu: View > Fullscreen Stretch Mode (4040.) */ #define STR_4040 "フルスクリーンの比率(&S)" #define STR_4041 "フルスクリーンに拡大(&F)" #define STR_4042 "4:3(&4)" @@ -362,14 +355,15 @@ #define STR_4044 "定数倍(&I)" #define STR_4045 "サイズを維持(&K)" -/* Menu: Display (4050.) */ + +/* UI menu: Display (4050.) */ #define STR_DISPLAY "画面表示(&D)" #define STR_4051 "反転(&I)" #define STR_4052 "オーバースキャン(&O)" #define STR_4053 "4:3に合わせる(&F)" #define STR_4054 "単色モニター用対比転換(&C)" -/* Menu: Display > Display Type */ +/* UI menu: Display > Display Type (4060.) */ #define STR_DISPTYPE "画面タイプ(&T)" #define STR_4061 "RGBカラーモニター(&C)" #define STR_4062 "RGBグレースケール(&G)" @@ -377,23 +371,26 @@ #define STR_4064 "緑色モニター(&G)" #define STR_4065 "白色モニター(&W)" -/* Menu: Display > Grayscale Conversion Type */ +/* UI menu: Display > Grayscale Conversion Type (4070.) */ #define STR_GRAYSCALE "グレースケール表示方式(&G)" #define STR_4071 "BT601 (NTSC/PAL)(&6)" #define STR_4072 "BT709 (HDTV)(&7)" #define STR_4073 "平均値(&A)" -/* Menu: Tools (4080.) */ + +/* UI menu: Tools (4080.) */ #define STR_TOOLS "ツール(&T)" #define STR_4081 "設定(&S)" #define STR_4082 "言語(&L)" #define STR_4083 "ログ(&O)" -#define STR_4084 "設定をロード(&C)" -#define STR_4085 "設定を保存(&A)" -#define STR_4086 "ステータス(&U)" -#define STR_4087 "スクリーンショットを撮る(&T)\tCtrl+Home" +#define STR_4084 "Log Breakpoint" +#define STR_4085 "Toggle %s logging" +#define STR_4086 "設定をロード(&C)" +#define STR_4087 "設定を保存(&A)" +#define STR_4088 "スクリーンショットを撮る(&T)" -/* Menu: Help (4090.) */ + +/* UI menu: Help (4090.) */ #define STR_HELP "ヘルプ(&H)" #define STR_4091 "VARCemについて(&A)" diff --git a/src/ui/lang/VARCem-KR.str b/src/ui/lang/VARCem-KR.str index f5f9a59..22ff79f 100644 --- a/src/ui/lang/VARCem-KR.str +++ b/src/ui/lang/VARCem-KR.str @@ -8,7 +8,7 @@ * * String definitions for "Korean (South Korea)" language. * - * Version: @(#)VARCem-KR.str 1.0.12 2018/09/23 + * Version: @(#)VARCem-KR.str 1.0.12 2018/10/01 * * Authors: Yeong Uk Jo, * Fred N. van Kempen, @@ -47,10 +47,13 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* Do not translate! */ -#define TAG_VERSION 1,0,11 -#define TAG_AUTHOR "Yeong Uk Jo" -#define TAG_EMAIL "greatpsycho@yahoo.com" +/* Main application strings (2000) - DO NOT TRANSLATE! */ +#define STR_VERSION 1,0,12 +#define STR_AUTHOR "Yeong Uk Jo" +#define STR_EMAIL "greatpsycho@yahoo.com" +#define STR_NAME "VARCem" +#define STR_TITLE "Virtual ARchaeological Computer EMulator" + /* Messagebox classes (2100.) */ #define STR_2100 "오류" @@ -65,27 +68,24 @@ #define STR_2202 "PCap 장치가 초기화되지 않아서 설정에 실패했습니다" #define STR_2203 "PCap 장치가 없습니다" #define STR_2204 "PCap 장치가 올바르지 않습니다" -#define STR_2205 "OpenAL을 초기화할 수 없습니다, 프로그램 폴더에 아래의 라이브러리 파일이 있는지 확인하세요:\n\nlibopenal-1.dll" -#define STR_2206 "FluidSynth를 초기화할 수 없습니다, 프로그램 폴더에 아래의 라이브러리 파일이 있는지 확인하세요:\n\nlibfluidsynth.dll" -#define STR_2207 "System out of memory!" +#define STR_2205 "%s을 초기화할 수 없습니다, 프로그램 폴더에 아래의 라이브러리 파일이 있는지 확인하세요:\n\n%s" /* Application error messages (2300.) */ -#define STR_2300 "비트맵 파일을 만들 수 없습니다: %s" +#define STR_2300 "System out of memory!" #define STR_2301 "사용 가능한 롬을 찾을 수 없습니다!" #define STR_2302 "유효한 설정을 찾을 수 없습니다.\n\n새로운 설정을 만들기 위해 설정창으로 들어가시겠습니까?" -#define STR_2303 "설정된 기종:\n\n %ls\n\n은 사용할 수 없습니다.\n\n설정창으로 들어가시겠습니까?" -#define STR_2304 "설정된 그래픽 카드:\n\n %ls\n\n는 사용할 수 없습니다.\n\n설정창으로 들어가시겠습니까?" -#define STR_2305 "설정된 렌더러 '%S' 는 사용할 수 없습니다. 기본값으로 초기화하시겠습니까?" -#define STR_2306 "ST506 혹은 ESDI 방식의 CD-ROM 드라이브는 없습니다" +#define STR_2303 "설정된 %ls:\n\n %s\n\n은 사용할 수 없습니다.\n\n설정창으로 들어가시겠습니까?" +#define STR_2304 "설정된 렌더러:\n\n %s\n\n는 사용할 수 없습니다. 기본값으로 초기화하시겠습니까?" +#define STR_2305 "새 설정을 저장해야 합니다" +#define STR_2306 "비트맵 파일을 만들 수 없습니다: %s" #define STR_2307 "USB는 아직 지원하지 않습니다." -#define STR_2308 "새 설정을 저장해야 합니다" /* Application messages (2400.) */ #define STR_2400 "이 설정을 저장하시겠습니까?\n\n(재시작이 필요할 수도 있습니다...)" #define STR_2401 "설정이 저장되었습니다. 다시 시작하세요!" -#define STR_2402 "요청된 장치 '%ls' 는 현재 구현 중으로 사용시 문제가 있을 수 있습니다.\n\n그래도 사용하시겠습니까?" +#define STR_2402 "요청된 장치:\n\n %s\n\n는 현재 구현 중으로 사용시 문제가 있을 수 있습니다.\n\n그래도 사용하시겠습니까?" #define STR_2403 "이 창을 클릭하면 마우스를 사용합니다" #define STR_2404 "F12+F8키를 누르면 마우스를 해제합니다" #define STR_2405 "F12+F8키 또는 가운데 버튼을 클릭하면 마우스를 해제합니다" @@ -99,11 +99,15 @@ /* UI: common elements (3000.) */ #define STR_OK "확인" #define STR_CANCEL "취소" +#define STR_YES "Yes" +#define STR_NO "No" #define STR_CONFIGURE "설정" #define STR_BROWSE "탐색" + /* UI: dialog shared strings (3100.) */ #define STR_NONE "없음" +#define STR_INTERNAL "Internal" #define STR_DISABLED "사용안함" #define STR_ENABLED "사용" #define STR_OFF "꺼짐" @@ -123,19 +127,19 @@ #define STR_DEVCONF_2 "장치:" -/* UI: dialog: About (3200.) */ +/* UI dialog: About (3200.) */ #define STR_ABOUT "VARCem에 대해.." #define STR_3201 "저자:" #define STR_3202 "Fred N. van Kempen, Miran Grca, Sarah Walker 와 기타 지원자들에 의해\n초기 버전의 86Box, PCem, MAME, DOSbox 와 Qemu를 기반으로 개발되었습니다." #define STR_3203 "BSD 3-Clause 라이선스에 따라 출시되었고, 다른 프로젝트에서 이식된 부분은 GNU General Public 라이선스 (버전 2 이상)을 따릅니다." #define STR_3204 "추가적인 정보는 LICENSE.txt 를 확인하세요." -/* UI: dialog: Localization (3210.) */ +/* UI dialog: Localization (3210.) */ #define STR_LOCALIZE "다국어" #define STR_3211 "영어 메세지를 다른 언어로 번역해 주신 분들:" /* UI dialog: Status (3225.) */ -#define STR_STATUS "상태" +/* (Unused now) */ /* UI dialog: Sound Gain (3250.) */ #define STR_SNDGAIN "소리 증폭" @@ -184,23 +188,16 @@ #define STR_3328 "지연 시간:" #define STR_3329 "메모리:" #define STR_3330 "MB" -#define STR_3331 "시간 동기화" +#define STR_3331 "시간 동기화:" #define STR_3332 "FPU 활성화" #define STR_3333 "동적 재컴파일러" #define STR_3334 "KB" #define STR_3335 "기본값" +#define STR_3336 "Enabled (UTC)" /* UI dialog: Settings (Video, 3350.) */ #define STR_3350 "그래픽 카드:" -#define STR_3351 "그래픽 카드 속도:" -#define STR_3352 "부두 그래픽" -#define STR_3353 "기본" -#define STR_3354 "8-bit" -#define STR_3355 "저속 16-bit" -#define STR_3356 "고속 16-bit" -#define STR_3357 "저속 VLB/PCI" -#define STR_3358 "중속 VLB/PCI" -#define STR_3359 "고속 VLB/PCI" +#define STR_3351 "부두 그래픽" /* UI dialog: Settings (Input, 3375.) */ #define STR_3375 "마우스:" @@ -233,8 +230,8 @@ /* UI dialog: Settings (Other Devices, 3475.) */ #define STR_3475 "SCSI 컨트롤러:" #define STR_3476 "HD 컨트롤러:" -#define STR_3477 "3 번째 IDE:" -#define STR_3478 "4 번째 IDE:" +#define STR_3477 "3 번째 IDE" +#define STR_3478 "4 번째 IDE" #define STR_3479 "ISABugger 장치" #define STR_3480 "ISA 메모리 확장 카드" #define STR_3481 "ISA 내장 시계 카드" @@ -255,10 +252,9 @@ #define STR_3512 "사용자 설정 (대용량)..." #define STR_3515 "ST506" #define STR_3516 "ESDI" -#define STR_3517 "IDE (PIO 전용)" -#define STR_3518 "IDE (PIO+DMA)" -#define STR_3519 "SCSI" -#define STR_3520 "SCSI (이동식)" +#define STR_3517 "IDE" +#define STR_3518 "SCSI" +#define STR_3519 "USB" /* UI dialog: Settings (Add Hard Disk, 3525.) */ #define STR_3525 "하드 디스크 추가" @@ -289,13 +285,12 @@ #define STR_3577 "ZIP 드라이브:" #define STR_3578 "ZIP 250" #define STR_3579 "속도" -#define STR_3580 "<예약됨>" -#define STR_3581 "<예약됨>" -#define STR_3582 "ATAPI (PIO 전용)" -#define STR_3583 "ATAPI (PIO+DMA)" -#define STR_3584 "SCSI" +#define STR_3580 "ATAPI" +#define STR_3581 "SCSI" +#define STR_3582 "USB" -/* UI dialog: status bar (3900.) */ + +/* UI: Status Bar (3900.) */ #define STR_3900 "(비었음)" #define STR_3901 "(호스트 드라이브 %c:)" #define STR_3902 " [쓰기 방지됨]" @@ -303,6 +298,7 @@ #define STR_3904 "이미지 불러오기(&L).." #define STR_3905 "이전 이미지 다시 불러오기(&R)" #define STR_3906 "이미지 제거(&U)" +#define STR_3907 "디스크 교체 알림(&N)" #define STR_3910 "플로피 %i (%s): %ls" #define STR_3911 "모든 이미지\0*.0??;*.1??;*.360;*.720;*.86f;*.bin;*.cq?;*.dsk;*.flp;*.hdm;*.im?;*.json;*.td0;*.*fd?;*.xdf\0Advanced sector images\0*.imd;*.json;*.td0\0Basic sector images\0*.0??;*.1??;*.360;*.720;*.bin;*.cq?;*.dsk;*.flp;*.hdm;*.im?;*.xdf;*.*fd?\0Flux images\0*.fdi\0Surface images\0*.86f\0모든 파일\0*.*\0" @@ -310,24 +306,21 @@ #define STR_3913 "Surface images\0*.86f\0" #define STR_3914 "86F 형식으로(&X)..." -#define STR_3920 "CD-ROM %i (%s): %s" +#define STR_3920 "CD-ROM %i (%ls): %ls" #define STR_3921 "호스트 CD/DVD 드라이브 (%c:)" #define STR_3922 "CD-ROM 이미지\0*.iso;*.cue\0모든 파일 (*.*)\0*.*\0" #define STR_3923 "음소거(&M)" -#define STR_3930 "하드 디스크 (%s)" +#define STR_3930 "하드 디스크 %i (%ls): %ls" -#define STR_3940 "이동식 디스크 %i: %ls" -#define STR_3941 "디스크 교체 알림(&N)" - -#define STR_3950 "ZIP %i (%03i): %ls" +#define STR_3950 "ZIP%03i %i (%ls): %ls" #define STR_3951 "ZIP 이미지\0*.im?;*.zdi\0모든 파일\0*.*\0" #define STR_3952 "ZIP 이미지\0*.im?;*.zdi\0" -#define STR_3960 "네트워크" -#define STR_3970 "소리" +#define STR_3960 "네트워크 (%s)" +#define STR_3970 "소리 (%s)" -/* Menu: Action (4000.) */ +/* UI menu: Action (4000.) */ #define STR_ACTION "동작(&A)" #define STR_4001 "재시작(&H)" #define STR_4002 "&Ctrl+Alt+Del 전송" @@ -336,25 +329,25 @@ #define STR_4005 "일시정지(&P)" #define STR_4006 "종료(&X)" -/* Menu: View (4010.) */ + +/* UI menu: View (4010.) */ #define STR_VIEW "보기(&V)" #define STR_4011 "창 크기 설정 가능(&R)" #define STR_4012 "창 크기와 위치를 기억(&E)" #define STR_4013 "전체화면(&F)\tCtrl+Alt+PageUP" #define STR_4014 "오른쪽 CTRL키를 왼쪽 ALT키로(&I)" -#define STR_4015 "상태 바 아이콘 갱신(&U)" -/* Menu: View > Renderer */ +/* UI menu: View > Renderer (4020.) */ #define STR_4020 "렌더러(&N)" -/* Menu: View > Window Scale Factor */ +/* UI menu: View > Window Scale Factor (4030.) */ #define STR_4030 "창 표시 배율(&W)" #define STR_4031 "0.5배(&0)" #define STR_4032 "1배(&1)" #define STR_4033 "1.5배(&5)" #define STR_4034 "2배(&2)" -/* Menu: View > Fullscreen Stretch Mode */ +/* UI menu: View > Fullscreen Stretch Mode (4040.) */ #define STR_4040 "전체 화면 비율 설정(&S)" #define STR_4041 "전체 화면으로 확대(&F)" #define STR_4042 "4:3(&4)" @@ -362,14 +355,15 @@ #define STR_4044 "정수배 확대(&I)" #define STR_4045 "크기 유지(&K)" -/* Menu: Display (4050.) */ + +/* UI menu: Display (4050.) */ #define STR_DISPLAY "화면 표시(&D)" #define STR_4051 "반전 표시(&I)" #define STR_4052 "오버스캔 활성화(&O)" #define STR_4053 "4:3으로 맞춤(&F)" #define STR_4054 "흑백 표시를 위한 밝기 조정(&C)" -/* Menu: Display > Display Type */ +/* UI menu: Display > Display Type (4060.) */ #define STR_DISPTYPE "디스플레이 유형(&T)" #define STR_4061 "RGB 천연색 모니터(&C)" #define STR_4062 "RGB 회색조 모니터(&G)" @@ -377,23 +371,26 @@ #define STR_4064 "녹색 모니터(&G)" #define STR_4065 "흰색 모니터(&W)" -/* Menu: Display > Grayscale Conversion Type */ +/* UI menu: Display > Grayscale Conversion Type (4070.) */ #define STR_GRAYSCALE "회색조 표현방식(&G)" #define STR_4071 "BT&601 (NTSC/PAL)" #define STR_4072 "BT&709 (HDTV)" #define STR_4073 "평균값(&A)" -/* Menu: Tools (4080.) */ + +/* UI menu: Tools (4080.) */ #define STR_TOOLS "도구(&T)" #define STR_4081 "설정(&S)" #define STR_4082 "언어(&L)" #define STR_4083 "로그(&O)" -#define STR_4084 "설정 불러오기(&C)" -#define STR_4085 "설정 저장하기(&A)" -#define STR_4086 "현재 상태(&U)" -#define STR_4087 "스크린샷 찍기(&T)\tCtrl+Home" +#define STR_4084 "Log Breakpoint" +#define STR_4085 "Toggle %s logging" +#define STR_4086 "설정 불러오기(&C)" +#define STR_4087 "설정 저장하기(&A)" +#define STR_4088 "스크린샷 찍기(&T)" -/* Menu: Help (4090.) */ + +/* UI menu: Help (4090.) */ #define STR_HELP "도움말(&H)" #define STR_4091 "VARCem에 대해(&A)" diff --git a/src/ui/lang/VARCem-KZ.str b/src/ui/lang/VARCem-KZ.str index b1588ac..d98d6d2 100644 --- a/src/ui/lang/VARCem-KZ.str +++ b/src/ui/lang/VARCem-KZ.str @@ -8,7 +8,7 @@ * * String definitions for "Kazakh (Kazakhstan)" language. * - * Version: @(#)VARCem-KZ.str 1.0.4 2018/09/23 + * Version: @(#)VARCem-KZ.str 1.0.4 2018/10/01 * * Authors: Arbars Zagadkin, * Fred N. van Kempen, @@ -46,10 +46,13 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* Do not translate! */ -#define TAG_VERSION 1,0,3 -#define TAG_AUTHOR "Arbars Zagadkin" -#define TAG_EMAIL "arbars.zagadkin@mail.ru" +/* Main application strings (2000) - DO NOT TRANSLATE! */ +#define STR_VERSION 1,0,4 +#define STR_AUTHOR "Arbars Zagadkin" +#define STR_EMAIL "arbars.zagadkin@mail.ru" +#define STR_NAME "VARCem" +#define STR_TITLE "Virtual ARchaeological Computer EMulator" + /* Messagebox classes (2100.) */ #define STR_2100 "Қате" @@ -64,27 +67,24 @@ #define STR_2202 "PCap пайдалу мүмкін емес, мүмкін ол бастапқы жуктемейді" #define STR_2203 "PCap құрылғысы табылған емес" #define STR_2204 "PCap құрылғысы дұрыс емес" -#define STR_2205 "OpenAL бастапқы жуктемеу мүмкін емес, сіздің бағдарламен бумасына \nкелесі кітапханасың қол жетімді тексерініз\n :\n\nlibopenal-1.dll" -#define STR_2206 "FluidSynth бастапқы жуктемеу мүмкін емес, сіздің бағдарламен бумасына \nкелесі кітапханасың қол жетімді тексерініз\n :\n\nlibfluidsynth.dll" -#define STR_2207 "System out of memory!" +#define STR_2205 "%s бастапқы жуктемеу мүмкін емес, сіздің бағдарламен бумасына \nкелесі кітапханасың қол жетімді тексерініз\n :\n\n%s" /* Application error messages (2300.) */ -#define STR_2300 "%s bitmap-файлы құру мүмкін емес" +#define STR_2300 "System out of memory!" #define STR_2301 "Қолдауылық ROM бейнелер табылған емес!" -#define STR_2302 "Ықтималық құрылымдық кескін табылған емес. \n\nСіз Күйге келтіру диалоғы ашу және құру оны қалайсыз ба?" -#define STR_2303 "Бұны компьютердің құрылымдық кескіні: \n\n %ls\n\nis қол жетімсіз. Күйге келтіру диалогы ашу ма?" -#define STR_2304 "Бұны бейнетақтаңың құрылымдық кескіні:\n\n %ls\n\nis қол жетімсіз.\n\nКүйге келтіру диалогы ашу ма?" -#define STR_2305 "'%S' рендерері қол жетімсіз. Использовать основной? Негізгі пайдалау ма?" -#define STR_2306 "ST506 және ESDI CD-ROM табақжаджүргізіктер ешқашан болмайды" +#define STR_2302 "Ықтималық құрылымдық кескін табылған емес.\n\nСіз Күйге келтіру диалоғы ашу және құру оны қалайсыз ба?" +#define STR_2303 "Бұны %ls құрылымдық кескіні:\n\n %s\n\nқол жетімсіз. Күйге келтіру диалогы ашу ма?" +#define STR_2304 "'%s' рендерері қол жетімсіз. Использовать основной? Негізгі пайдалау ма?" +#define STR_2305 "You must save your settings first!" +#define STR_2306 "%ls bitmap-файлы құру мүмкін емес" #define STR_2307 "USB алайда қол жетімсіз" -#define STR_2308 "You must save your settings first!" /* Application messages (2400.) */ #define STR_2400 "Параметрлер сақтау керегінде сенімсіз ба? (Қайта жіберісі кажеті бар...)" #define STR_2401 "Өзгерiстер сақталды. Үлгелігіш қайта жіберініз" -#define STR_2402 "Бұның құралысы '%ls' алайда жасау барысында және мәселер тудыру мүмкін. Пайдалауда оны сенімсіз ба?" +#define STR_2402 "Бұның құралысы\n\n %s\n\nалайда жасау барысында және мәселер тудыру мүмкін. Пайдалауда оны сенімсіз ба?" #define STR_2403 "Тышқанның курсор ұстау үшің тышканда басыныз" #define STR_2404 "Тышқанның курсор босатылу F8+F12 басыныз" #define STR_2405 "Тышқанның курсор босатылу F8+F12 немеса тышқанның ортанғы түймесі басыныз" @@ -98,11 +98,15 @@ /* UI: common elements (3000.) */ #define STR_OK "OK" #define STR_CANCEL "Болдырмау" +#define STR_YES "Yes" +#define STR_NO "No" #define STR_CONFIGURE "Күйге келтіру" #define STR_BROWSE "Шолы..." + /* UI: dialog shared strings (3100.) */ #define STR_NONE "Жоқ" +#define STR_INTERNAL "Internal" #define STR_DISABLED "Қол жетімсіз" #define STR_ENABLED "Қол жетімді" #define STR_OFF "Өшіру" @@ -122,7 +126,7 @@ #define STR_DEVCONF_2 "Құрылығы:" -/* UI: dialog: About (3200.) */ +/* UI dialog: About (3200.) */ #define STR_ABOUT "VARCem туралы..." #define STR_3201 "Авторлар:" #define STR_3202 "Fred N. van Kempen, Miran Grca, Sarah Walker және тағы басқа.\nБағдарлама 86Box, PCem, MAME, DOSbox және Qemu алғашқы жазбахабардан негізделген" @@ -133,7 +137,7 @@ #define STR_3211 "Анғылыштан басқа тілдерге аудармалар авторлар:" /* UI dialog: Status (3225.) */ -#define STR_STATUS "Статус" +/* (Unused now) */ /* UI dialog: Sound Gain (3250.) */ #define STR_SNDGAIN "Дыбыстың күшейтуi" @@ -182,23 +186,16 @@ #define STR_3328 "Күту қайтамалалар:" #define STR_3329 "Жедел жады:" #define STR_3330 "MB" -#define STR_3331 "Уақыттың синхрондау" +#define STR_3331 "Уақыттың синхрондау:" #define STR_3332 "FPU қосу" #define STR_3333 "Динамикалық рекомпиляторы" #define STR_3334 "KB" #define STR_3335 "әдепкі бойынша" +#define STR_3336 "Қол жетімді (UTC)" /* UI dialog: Settings (Video, 3350.) */ #define STR_3350 "Бейне:" -#define STR_3351 "Бейнесің жылдамдығы:" -#define STR_3352 "Voodoo Graphics" -#define STR_3353 "әдепкі бойынша" -#define STR_3354 "8-bit" -#define STR_3355 "баяу 16-bit" -#define STR_3356 "жоғары 16-bit" -#define STR_3357 "баяу VLB/PCI" -#define STR_3358 "орташа VLB/PCI" -#define STR_3359 "жоғары VLB/PCI" +#define STR_3351 "Voodoo Graphics" /* UI dialog: Settings (Input, 3375.) */ #define STR_3375 "Тышқан:" @@ -231,8 +228,8 @@ /* UI dialog: Settings (Other Devices, 3475.) */ #define STR_3475 "SCSI бақылаушысы:" #define STR_3476 "HD бақылаушысы:" -#define STR_3477 "Үштік IDE:" -#define STR_3478 "Төрттік IDE:" +#define STR_3477 "Үштік IDE" +#define STR_3478 "Төрттік IDE" #define STR_3479 "ISABugger қурылғы" #define STR_3480 "ISA Memory Expansion" #define STR_3481 "ISA Clock/RTC Card" @@ -253,10 +250,9 @@ #define STR_3512 "Параметрлер (үлкен)..." #define STR_3515 "ST506" #define STR_3516 "ESDI" -#define STR_3517 "IDE (тек қана PIO)" -#define STR_3518 "IDE (PIO+DMA)" -#define STR_3519 "SCSI" -#define STR_3520 "SCSI (алмалы-салмалы)" +#define STR_3517 "IDE" +#define STR_3518 "SCSI" +#define STR_3519 "USB" /* UI dialog: Settings (Add Hard Disk, 3525.) */ #define STR_3525 "Қатты табақжады қосылу" @@ -287,13 +283,12 @@ #define STR_3577 "ZIP жабакжадты жүргізгілер:" #define STR_3578 "ZIP 250" #define STR_3579 "Жылдамдығы" -#define STR_3580 "<Бос емес>" -#define STR_3581 "<Бос емес>" -#define STR_3582 "ATAPI (PIO-only)" -#define STR_3583 "ATAPI (PIO+DMA)" -#define STR_3584 "SCSI" +#define STR_3580 "ATAPI" +#define STR_3581 "SCSI" +#define STR_3582 "USB" -/* UI dialog: status bar (3900.) */ + +/* UI: Status Bar (3900.) */ #define STR_3900 "(бос)" #define STR_3901 "(хост-табақжады %c:)" #define STR_3902 " [Жазбадан қорғалған]" @@ -301,6 +296,7 @@ #define STR_3904 "Бейне ашу.." #define STR_3905 "Алдыңғы бейнесі жүкту" #define STR_3906 "Ашып шығу" +#define STR_3907 "Табақжадының ауысымы хабарлау" #define STR_3910 "Иікпелі табакжад %i (%s): %ls" #define STR_3911 "Бәрі бейнелер\0*.0??;*.1??;*.360;*.720;*.86f;*.bin;*.cq?;*.dsk;*.flp;*.hdm;*.im?;*.json;*.td0;*.*fd?;*.xdf\0 Кенейтілген секторлық бейнелер\0*.imd;*.json;*.td0\0Тұр секторлық бейнелер\0*.0??;*.1??;*.360;*.720;*.bin;*.cq?;*.dsk;*.flp;*.hdm;*.im?;*.xdf;*.*fd?\0Магниттік ағыспен бейнелер\0*.fdi\0Биттік ағыспен бейнелер\0*.86f\0Бәрі файлдар\0*.*\0" @@ -308,24 +304,21 @@ #define STR_3913 "Биттік ағыспен бейнелер\0*.86f\0" #define STR_3914 "86F экспорт алу" -#define STR_3920 "CD-ROM %i (%s): %s" +#define STR_3920 "CD-ROM %i (%ls): %ls" #define STR_3921 "CD/DVD-мен хост-табақжады (%c:)" #define STR_3922 "CD-ROM бейнелер\0*.iso;*.cue\0Бәрі файлдар (*.*)\0*.*\0" #define STR_3923 "Дыбыссыз" -#define STR_3930 "Қатты табақжады (%s)" +#define STR_3930 "Қатты табақжады %i (%ls): %ls" -#define STR_3940 "Съёмный табақжад %i: %ls" -#define STR_3941 "Табақжадының ауысымы хабарлау" - -#define STR_3950 "ZIP %i (%03i): %ls" +#define STR_3950 "ZIP%03i %i (%ls): %ls" #define STR_3951 "ZIP\0*.im?;*.zdi табақжаджургізгілер үшін бейнелер\0Бәрі файлдар\0*.*\0" #define STR_3952 "ZIP\0*.im?;*.zdi табақжаджургізгілер үшін бейнелер\0" -#define STR_3960 "Торап" -#define STR_3970 "Дыбыс" +#define STR_3960 "Торап (%s)" +#define STR_3970 "Дыбыс (%s)" -/* Menu: Action (4000.) */ +/* UI menu: Action (4000.) */ #define STR_ACTION "Іс" #define STR_4001 "Алып тастап қайта орнату" #define STR_4002 "Ctrl+Alt+Del" @@ -334,25 +327,25 @@ #define STR_4005 "Пауза" #define STR_4006 "Шығу" -/* Menu: View (4010.) */ + +/* UI menu: View (4010.) */ #define STR_VIEW "Сыртқы түрi" #define STR_4011 "Өзгертiлетiндік терезенiң өлшемi" #define STR_4012 "Өлшем және позиция жадта қалу" #define STR_4013 "Тарт ақпаралық режімі\tCtrl+Alt+PageUP" #define STR_4014 "Оң CTRL бұл солы ALT пайдалану" -#define STR_4015 "Статустың панелде иконкалар жанарту" -/* Menu: View > Renderer */ +/* UI menu: View > Renderer (4020.) */ #define STR_4020 "Рендерер" -/* Menu: View > Window Scale Factor */ +/* UI menu: View > Window Scale Factor (4030.) */ #define STR_4030 "Терезенің ауқығы" #define STR_4031 "0.5x" #define STR_4032 "1x" #define STR_4033 "1.5x" #define STR_4034 "2x" -/* Menu: View > Fullscreen Stretch Mode */ +/* UI menu: View > Fullscreen Stretch Mode (4040.) */ #define STR_4040 "Көрелік тарт ақпаралық режімі" #define STR_4041 "Тарт ақпаралға көрелу" #define STR_4042 "4:3" @@ -360,14 +353,15 @@ #define STR_4044 "бүтiн санды ауқымауы" #define STR_4045 "Ағатын өлшемі сақтау" -/* Menu: Display (4050.) */ + +/* UI menu: Display (4050.) */ #define STR_DISPLAY "Дисплей" #define STR_4051 "Терістік дисплей" #define STR_4052 "Жазбаның ұшуы рұқсат беру" #define STR_4053 "4:3 жақтардың арақатысы көрсету" #define STR_4054 "Ақ-қара дисплейдің қарама-қайшылығы өзгерту" -/* Menu: Display > Display Type */ +/* UI menu: Display > Display Type (4060.) */ #define STR_DISPTYPE "Дисплейдің түрі" #define STR_4061 "Түрлi-түстi RGB" #define STR_4062 "Ақ-қара" @@ -375,23 +369,26 @@ #define STR_4064 "Жасыл жарығы" #define STR_4065 "Ақ жарығы" -/* Menu: Display > Grayscale Conversion Type */ +/* UI menu: Display > Grayscale Conversion Type (4070.) */ #define STR_GRAYSCALE "Ақ-қара конверсиясының түрі" #define STR_4071 "BT601 (NTSC/PAL)" #define STR_4072 "BT709 (HDTV)" #define STR_4073 "Орташа" -/* Menu: Tools (4080.) */ + +/* UI menu: Tools (4080.) */ #define STR_TOOLS "Құралдар" #define STR_4081 "Күйге келтіру" #define STR_4082 "Тілі" #define STR_4083 "Логгер" -#define STR_4084 "Конфигурация жұктелу" -#define STR_4085 "Конфигурация сақталу" -#define STR_4086 "Статус" -#define STR_4087 "Скриншотты жасау \tCtrl+Home" +#define STR_4084 "Log Breakpoint" +#define STR_4085 "Toggle %s logging" +#define STR_4086 "Конфигурация жұктелу" +#define STR_4087 "Конфигурация сақталу" +#define STR_4088 "Скриншотты жасау" -/* Menu: Help (4090.) */ + +/* UI menu: Help (4090.) */ #define STR_HELP "Көмек" #define STR_4091 "VARCem туралы" diff --git a/src/ui/lang/VARCem-LT.str b/src/ui/lang/VARCem-LT.str index 05bd3e2..a82b4a9 100644 --- a/src/ui/lang/VARCem-LT.str +++ b/src/ui/lang/VARCem-LT.str @@ -8,7 +8,7 @@ * * String definitions for "Lithuanian (Lithuania)" language. * - * Version: @(#)VARCem-LT.str 1.0.5 2018/09/23 + * Version: @(#)VARCem-LT.str 1.0.5 2018/10/01 * * Author: Vegas (emu-land.net) * Fred N. van Kempen, @@ -46,10 +46,13 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* Do not translate! */ -#define TAG_VERSION 1,0,4 -#define TAG_AUTHOR "Vegas" -#define TAG_EMAIL "emu-land.net" +/* Main application strings (2000) - DO NOT TRANSLATE! */ +#define STR_VERSION 1,0,5 +#define STR_AUTHOR "Vegas" +#define STR_EMAIL "emu-land.net" +#define STR_NAME "VARCem" +#define STR_TITLE "Virtual ARchaeological Computer EMulator" + /* Messagebox classes (2100.) */ #define STR_2100 "Klaida" @@ -64,27 +67,24 @@ #define STR_2202 "PCap nepavyko nustatyti, nes jis gali būti ne initializuotas" #define STR_2203 "Nerasta jokių Pcap įrenginių" #define STR_2204 "Netinkamas PCap įrenginys" -#define STR_2205 "Nepavyko inicijuoti OpenAL, įsitikinkite, kad jūsų programoje yra ši biblioteka aplankale:\n\nlibopenal-1.dll" -#define STR_2206 "Nepavyko inicijuoti FluidSynth, įsitikinkite, kad jūsų programoje yra ši biblioteka aplankale:\n\nlibfluidsynth.dll" -#define STR_2207 "System out of memory!" +#define STR_2205 "Nepavyko inicijuoti %s, įsitikinkite, kad jūsų programoje yra ši biblioteka aplankale:\n\n%s" /* Application error messages (2300.) */ -#define STR_2300 "Nepavyko sukurti bitmap failo: %s" +#define STR_2300 "System out of memory!" #define STR_2301 "Nerasta naudojamų ROM atvaizdų!" #define STR_2302 "Nerasta galiojančios konfigūracijos.\n\nAr norėtumėte įeiti į 'Nustatymai', kad sukurtumėte?" -#define STR_2303 "Sukonfigūruota mašina:\n\n %ls\n\nis nepasiekiama.\n\nAr norėtumėte įeiti į 'Nustatymai', kad sukurtumėte?" -#define STR_2304 "Sukonfigūruota vaizdo plokštė:\n\n %ls\n\nis nnepasiekiama.\n\n Ar norėtumėte įeiti į 'Nustatymai', kad sukurtumėte?" -#define STR_2305 "Pasirinktas renderis '%S' nepasiekiamas. Atstatyti pagal nutylėjimą?" -#define STR_2306 "ST506 arba ESDI CD-ROM diskai niekada nebuvo" +#define STR_2303 "Sukonfigūruota %ls:\n\n %s\n\nnepasiekiama.\n\nAr norėtumėte įeiti į 'Nustatymai', kad sukurtumėte?" +#define STR_2304 "Pasirinktas renderis:\n\n %s\n\nnepasiekiamas. Atstatyti pagal nutylėjimą?" +#define STR_2305 "You must save your settings first!" +#define STR_2306 "Nepavyko sukurti bitmap failo: %ls" #define STR_2307 "USB dar nepalaikomas" -#define STR_2308 "You must save your settings first!" /* Application messages (2400.) */ #define STR_2400 "Ar tikrai norite išsaugoti šiuos nustatymus?\n\n(gali tekti paleisti iš naujo...)" #define STR_2401 "Pakeitimai išsaugoti, iš naujo paleiskite emuliatorių!" -#define STR_2402 "Pasirinktas įrenginys '%ls' šiuo metu laikomas 'plėtros procese' ir gali sukelti problemų.\n\nAr tikrai norite jį įjungti?" +#define STR_2402 "Pasirinktas įrenginys:\n\n %s\n\nšiuo metu laikomas 'plėtros procese' ir gali sukelti problemų.\n\nAr tikrai norite jį įjungti?" #define STR_2403 "Spustelėkite norėdami užfiksuoti pelę" #define STR_2404 "Paspauskite F8 + F12, kad paleisti pelę" #define STR_2405 "Paspauskite F8 + F12 arba vidurinį mygtuką norėdami paleisti pelę" @@ -98,11 +98,15 @@ /* UI: common elements (3000.) */ #define STR_OK "OK" #define STR_CANCEL "Atšaukti" +#define STR_YES "Yes" +#define STR_NO "No" #define STR_CONFIGURE "Konfigūruoti" #define STR_BROWSE "Naršyti" + /* UI: dialog shared strings (3100.) */ #define STR_NONE "Nėra" +#define STR_INTERNAL "Internal" #define STR_DISABLED "Nepasiekiama" #define STR_ENABLED "Pasiekiama" #define STR_OFF "Išjungtas" @@ -122,19 +126,19 @@ #define STR_DEVCONF_2 "Įrenginys:" -/* UI: dialog: About (3200.) */ +/* UI dialog: About (3200.) */ #define STR_ABOUT "Apie VARCem.." #define STR_3201 "Authoriai:" #define STR_3202 "Fred N. van Kempen, Miran Grca, Sarah Walker and others.\nRemiantis ankstesniais darbais, tokiais kaip 86Box, PCem, MAME, DOSbox and Qemu." #define STR_3203 "Išleistas pagal BSD 3-Clause License, and the GNU General Public License (version 2 or up) esamų, importuotų kodų iš kitų projektų." #define STR_3204 "Daugiau informacijos rasite 'LICENSE.txt'." -/* UI: dialog: Localization (3210.) */ +/* UI dialog: Localization (3210.) */ #define STR_LOCALIZE "Lokalizacija" #define STR_3211 "Vertimus iš anglų kalbos i kitus kalbus pateikė:" /* UI dialog: Status (3225.) */ -#define STR_STATUS "Statusas" +/* (Unused now) */ /* UI dialog: Sound Gain (3250.) */ #define STR_SNDGAIN "Garso stiprumas" @@ -183,23 +187,16 @@ #define STR_3328 "Laukti būsenos:" #define STR_3329 "Atmintis:" #define STR_3330 "MB" -#define STR_3331 "Įjungti laiko sinchronizavimą" +#define STR_3331 "Įjungti laiko sinchronizavimą:" #define STR_3332 "Įjungti FPU" #define STR_3333 "Dinamiškas Rekompiliatorius" #define STR_3334 "KB" #define STR_3335 "Numatytas" +#define STR_3336 "Pasiekiama (UTC)" /* UI dialog: Settings (Video, 3350.) */ #define STR_3350 "Vaizdas:" -#define STR_3351 "Vaizdo greitis:" -#define STR_3352 "Voodoo Grafika" -#define STR_3353 "Numatytas" -#define STR_3354 "8-bit" -#define STR_3355 "Lėtas 16-bit" -#define STR_3356 "Greitas 16-bit" -#define STR_3357 "Lėtas VLB/PCI" -#define STR_3358 "Vidutinis VLB/PCI" -#define STR_3359 "Greitas VLB/PCI" +#define STR_3351 "Voodoo Grafika" /* UI dialog: Settings (Input, 3375.) */ #define STR_3375 "Pelė:" @@ -232,8 +229,8 @@ /* UI dialog: Settings (Other Devices, 3475.) */ #define STR_3475 "SCSI kontroleris:" #define STR_3476 "HD kontroleris:" -#define STR_3477 "Tretinis IDE:" -#define STR_3478 "Ketvirtinis IDE:" +#define STR_3477 "Tretinis IDE" +#define STR_3478 "Ketvirtinis IDE" #define STR_3479 "ISABugger įrenginys" #define STR_3480 "ISA Memory Expansion" #define STR_3481 "ISA Clock/RTC Card" @@ -254,11 +251,9 @@ #define STR_3512 "įprastas (didelis)..." #define STR_3515 "ST506" #define STR_3516 "ESDI" -#define STR_3517 "IDE (PIO-only)" -#define STR_3518 "IDE (PIO+DMA)" -#define STR_3519 "SCSI" -#define STR_3520 "SCSI (nuimamas)" -#define STR_3521 "USB" +#define STR_3517 "IDE" +#define STR_3518 "SCSI" +#define STR_3519 "USB" /* UI dialog: Settings (Add Hard Disk, 3525.) */ #define STR_3525 "Pridėti kietąjį diską" @@ -289,14 +284,12 @@ #define STR_3577 "ZIP diskai:" #define STR_3578 "ZIP 250" #define STR_3579 "Greitis" -#define STR_3580 "" -#define STR_3581 "" -#define STR_3582 "ATAPI (PIO-only)" -#define STR_3583 "ATAPI (PIO+DMA)" -#define STR_3584 "SCSI" -#define STR_3585 "USB" +#define STR_3580 "ATAPI" +#define STR_3581 "SCSI" +#define STR_3582 "USB" -/* UI dialog: status bar (3900.) */ + +/* UI: Status Bar (3900.) */ #define STR_3900 "(tuščia)" #define STR_3901 "(host diskas %c:)" #define STR_3902 " [Apsaugota irašymui]" @@ -304,6 +297,7 @@ #define STR_3904 "&įkelti atvaizdas.." #define STR_3905 "&Perkrauti ankstesnį atvaizda" #define STR_3906 "&Iškrauti" +#define STR_3907 "&Pranešti apie disko keitimą" #define STR_3910 "Floppy %i (%s): %ls" #define STR_3911 "Visi atvaizdai\0*.0??;*.1??;*.360;*.720;*.86f;*.bin;*.cq?;*.dsk;*.flp;*.hdm;*.im?;*.json;*.td0;*.*fd?;*.xdf\0Išplėstinių sektorių atvaizdai\0*.imd;*.json;*.td0\0Pagrindinių sektorių atvaizdai\0*.0??;*.1??;*.360;*.720;*.bin;*.cq?;*.dsk;*.flp;*.hdm;*.im?;*.xdf;*.*fd?\0Srauto atvaizdai\0*.fdi\0Paviršiaus atvaizdai\0*.86f\0Visi failai\0*.*\0" @@ -311,24 +305,21 @@ #define STR_3913 "Paviršiaus atvaizdai\0*.86f\0" #define STR_3914 "Eksportas į 86F..." -#define STR_3920 "CD-ROM %i (%s): %s" +#define STR_3920 "CD-ROM %i (%ls): %ls" #define STR_3921 "Host CD/DVD Drive (%c:)" #define STR_3922 "CD-ROM atvaizdai\0*.iso;*.cue\0Visi failai (*.*)\0*.*\0" #define STR_3923 "&Nutildyti" -#define STR_3930 "Kietasis diskas (%s)" +#define STR_3930 "Kietasis diskas %i (%ls): %ls" -#define STR_3940 "Keičiamasis diskas %i: %ls" -#define STR_3941 "&Pranešti apie disko keitimą" - -#define STR_3950 "ZIP %i (%03i): %ls" +#define STR_3950 "ZIP%03i %i (%ls): %ls" #define STR_3951 "ZIP atvaizdai\0*.im?;*.zdi\0Visi failai\0*.*\0" #define STR_3952 "ZIP atvaizdai\0*.im?;*.zdi\0" -#define STR_3960 "Tinklas" -#define STR_3970 "Garsas" +#define STR_3960 "Tinklas (%s)" +#define STR_3970 "Garsas (%s)" -/* Menu: Action (4000.) */ +/* UI menu: Action (4000.) */ #define STR_ACTION "&Veiksmas" #define STR_4001 "&Kietasis atstatymas" #define STR_4002 "&Ctrl+Alt+Del" @@ -337,25 +328,25 @@ #define STR_4005 "&Pauze" #define STR_4006 "&Išeiti" -/* Menu: View (4010.) */ + +/* UI menu: View (4010.) */ #define STR_VIEW "&Vaizdas" #define STR_4011 "&Keičiamas langas" #define STR_4012 "&Prisiminti dydį ir padėtį" #define STR_4013 "&Visas ekranas\tCtrl+Alt+PageUP" #define STR_4014 "&Dešiniuoju klavišu CTRL paliekamas ALT" -#define STR_4015 "&Atnaujinti būsenos piktogramams" -/* Menu: View > Renderer */ +/* UI menu: View > Renderer (4020.) */ #define STR_4020 "&Renderis" -/* Menu: View > Window Scale Factor */ +/* UI menu: View > Window Scale Factor (4030.) */ #define STR_4030 "&Langų masto koeficientas" #define STR_4031 "&0.5x" #define STR_4032 "&1x" #define STR_4033 "&1.5x" #define STR_4034 "&2x" -/* Menu: View > Fullscreen Stretch Mode */ +/* UI menu: View > Fullscreen Stretch Mode (4040.) */ #define STR_4040 "&Istemptas viso ekrano režimas" #define STR_4041 "&Visas ekranas" #define STR_4042 "&4:3" @@ -363,14 +354,15 @@ #define STR_4044 "&Integer skalė" #define STR_4045 "&Laikyti dydį" -/* Menu: Display (4050.) */ + +/* UI menu: Display (4050.) */ #define STR_DISPLAY "&Ekranas" #define STR_4051 "&Apverstas ekranas" #define STR_4052 "&Įgalinti perversmą" #define STR_4053 "&Priverstinis 4:3 rodymo santykis" #define STR_4054 "&Keisti kontrastą monochrominiam ekranui" -/* Menu: Display > Display Type */ +/* UI menu: Display > Display Type (4060.) */ #define STR_DISPTYPE "&Ekrano tipas" #define STR_4061 "&RGB ir spalvotas monitorius" #define STR_4062 "&Pilkos spalvos monitorius" @@ -378,23 +370,26 @@ #define STR_4064 "&Žalios spalvos monitorius" #define STR_4065 "&Baltos spalvos monitorius" -/* Menu: Display > Grayscale Conversion Type */ +/* UI menu: Display > Grayscale Conversion Type (4070.) */ #define STR_GRAYSCALE "&Pelėskolio konversijos tipas" #define STR_4071 "BT&601 (NTSC/PAL)" #define STR_4072 "BT&709 (HDTV)" #define STR_4073 "&Vidurkis" -/* Menu: Tools (4080.) */ + +/* UI menu: Tools (4080.) */ #define STR_TOOLS "&Įrankiai" #define STR_4081 "&Nustatymai" #define STR_4082 "&Kalba" #define STR_4083 "&Logging" -#define STR_4084 "&Įkelti konfigūraciją" -#define STR_4085 "&Išsaugoti konfigūraciją" -#define STR_4086 "&Statusas" -#define STR_4087 "&Padaryti ekrano nuotrauką\tCtrl+Home" +#define STR_4084 "Log Breakpoint" +#define STR_4085 "Toggle %s logging" +#define STR_4086 "&Įkelti konfigūraciją" +#define STR_4087 "&Išsaugoti konfigūraciją" +#define STR_4088 "&Padaryti ekrano nuotrauką" -/* Menu: Help (4090.) */ + +/* UI menu: Help (4090.) */ #define STR_HELP "&Pagalba" #define STR_4091 "&Apie VARCem" diff --git a/src/ui/lang/VARCem-NO.str b/src/ui/lang/VARCem-NO.str index a56e3de..032dabd 100644 --- a/src/ui/lang/VARCem-NO.str +++ b/src/ui/lang/VARCem-NO.str @@ -8,7 +8,7 @@ * * String definitions for "Norwegian (Norway)" language. * - * Version: @(#)VARCem-NO.str 1.0.4 2018/09/23 + * Version: @(#)VARCem-NO.str 1.0.5 2018/10/01 * * Author: Fred N. van Kempen, * Tore Sinding Bekkedal, " -#define STR_3581 "" -#define STR_3582 "ATAPI (kun PIO)" -#define STR_3583 "ATAPI (PIO+DMA)" -#define STR_3584 "SCSI" -#define STR_3585 "USB" +#define STR_3580 "ATAPI" +#define STR_3581 "SCSI" +#define STR_3582 "USB" -/* UI dialog: status bar (3900.) */ + +/* UI: Status Bar (3900.) */ #define STR_3900 "(tom)" #define STR_3901 "(vertsdisk %c:)" #define STR_3902 " [Skrivebeskyttet]" @@ -304,6 +297,7 @@ #define STR_3904 "&Last inn avtrykk.." #define STR_3905 "Oppdate&re avtrykk" #define STR_3906 "Løs &ut" +#define STR_3907 "(&N) Varsle diskbytte" #define STR_3910 "Diskett %i (%s): %ls" #define STR_3911 "Alle avtrykk\0*.0??;*.1??;*.360;*.720;*.86f;*.bin;*.cq?;*.dsk;*.flp;*.hdm;*.im?;*.json;*.td0;*.*fd?;*.xdf\0Avanserte sektoravtrykk\0*.imd;*.json;*.td0\0Enkle sektoravtrykk\0*.0??;*.1??;*.360;*.720;*.bin;*.cq?;*.dsk;*.flp;*.hdm;*.im?;*.xdf;*.*fd?\0Flux-avtrykk\0*.fdi\0Overflateavtrykk\0*.86f\0Alle filer\0*.*\0" @@ -311,24 +305,21 @@ #define STR_3913 "Overflateavtrykk\0*.86f\0" #define STR_3914 "(&x) Eksporter til 86F..." -#define STR_3920 "CD-ROM %i (%s): %s" +#define STR_3920 "CD-ROM %i (%ls): %ls" #define STR_3921 "Vertens CD/DVD-enhet (%c:)" #define STR_3922 "CD-ROM-avtrykk\0*.iso;*.cue\0Alle filer (*.*)\0*.*\0" #define STR_3923 "&Mute" -#define STR_3930 "Platelager (%s)" +#define STR_3930 "Platelager %i (%ls): %ls" -#define STR_3940 "Flyttbar disk %i: %ls" -#define STR_3941 "(&N) Varsle diskbytte" - -#define STR_3950 "ZIP %i (%03i): %ls" +#define STR_3950 "ZIP%03i %i (%ls): %ls" #define STR_3951 "ZIP-avtrykk\0*.im?;*.zdi\0Alle filer\0*.*\0" #define STR_3952 "ZIP-avtrykk\0*.im?;*.zdi\0" -#define STR_3960 "Nettverk" -#define STR_3970 "Lyd" +#define STR_3960 "Nettverk (%s)" +#define STR_3970 "Lyd (%s)" -/* Menu: Action (4000.) */ +/* UI menu: Action (4000.) */ #define STR_ACTION "H&andlinger" #define STR_4001 "&Hard omstart" #define STR_4002 "&Kontroll+Alt+Del" @@ -337,25 +328,25 @@ #define STR_4005 "&Pause" #define STR_4006 "(&x) Avslutt" -/* Menu: View (4010.) */ + +/* UI menu: View (4010.) */ #define STR_VIEW "&Vis" #define STR_4011 "Skale&rbart vindu" #define STR_4012 "Lagr&e størrelse && posisjon" #define STR_4013 "&Fullskjerm\tKontroll+Alt+PageUP" #define STR_4014 "Høyre Kontroll g&ir venstre Alt" -#define STR_4015 "Oppdater stat&uslinjeikoner" -/* Menu: View > Renderer */ +/* UI menu: View > Renderer (4020.) */ #define STR_4020 "Re&nderer" -/* Menu: View > Window Scale Factor */ +/* UI menu: View > Window Scale Factor (4030.) */ #define STR_4030 "(&w) Vinduskala" #define STR_4031 "&0.5x" #define STR_4032 "&1x" #define STR_4033 "1.&5x" #define STR_4034 "&2x" -/* Menu: View > Fullscreen Stretch Mode */ +/* UI menu: View > Fullscreen Stretch Mode (4040.) */ #define STR_4040 "Fullskjerm &strukket modus" #define STR_4041 "&Fullskjerm strukket" #define STR_4042 "&4:3" @@ -363,14 +354,15 @@ #define STR_4044 "Heltallskaler&ing" #define STR_4045 "Faktis&k størrelse" -/* Menu: Display (4050.) */ + +/* UI menu: Display (4050.) */ #define STR_DISPLAY "(&d) Skjerm" #define STR_4051 "&Omvendt video" #define STR_4052 "Bruk &overskanning" #define STR_4053 "Tving 4:3 bildeforh&old" #define STR_4054 "(&c) Endre kontrast for monokrom skjerm" -/* Menu: Display > Display Type */ +/* UI menu: Display > Display Type (4060.) */ #define STR_DISPTYPE "Skjerm&type" #define STR_4061 "(&c) RGB fargeskjerm" #define STR_4062 "&Gråskalaskjerm" @@ -378,23 +370,26 @@ #define STR_4064 "&Grønn skjerm" #define STR_4065 "(&w) Hvit skjerm" -/* Menu: Display > Grayscale Conversion Type */ +/* UI menu: Display > Grayscale Conversion Type (4070.) */ #define STR_GRAYSCALE "&Gråskala konverteringsmetode" #define STR_4071 "BT&601 (NTSC/PAL)" #define STR_4072 "BT&709 (HDTV)" #define STR_4073 "f&argesnitt" -/* Menu: Tools (4080.) */ + +/* UI menu: Tools (4080.) */ #define STR_TOOLS "Verk&tøy" #define STR_4081 "Inn&stillinger" #define STR_4082 "Språkva&lg" #define STR_4083 "L&ogging" -#define STR_4084 "(&c) Last inn konfigurasjon" -#define STR_4085 "L&agre konfigurasjon" -#define STR_4086 "Stat&us" -#define STR_4087 "&Ta skjermbilde\tKontroll+Hjem" +#define STR_4084 "Log Breakpoint" +#define STR_4085 "Toggle %s logging" +#define STR_4086 "(&c) Last inn konfigurasjon" +#define STR_4087 "L&agre konfigurasjon" +#define STR_4088 "&Ta skjermbilde" -/* Menu: Help (4090.) */ + +/* UI menu: Help (4090.) */ #define STR_HELP "&Hjelp" #define STR_4091 "Om V&ARCem" diff --git a/src/ui/lang/VARCem-RU.str b/src/ui/lang/VARCem-RU.str index 453cf3b..02977b0 100644 --- a/src/ui/lang/VARCem-RU.str +++ b/src/ui/lang/VARCem-RU.str @@ -8,7 +8,7 @@ * * String definitions for "Russian (Russia)" language. * - * Version: @(#)VARCem-RU.str 1.0.15 2018/09/23 + * Version: @(#)VARCem-RU.str 1.0.16 2018/10/01 * * Authors: Tarlabnor, * Fred N. van Kempen, @@ -46,10 +46,13 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* Do not translate! */ -#define TAG_VERSION 1,0,15 -#define TAG_AUTHOR "Tarlabnor" -#define TAG_EMAIL "tarlabnor@varcem.com" +/* Main application strings (2000) - DO NOT TRANSLATE! */ +#define STR_VERSION 1,0,16 +#define STR_AUTHOR "Tarlabnor" +#define STR_EMAIL "tarlabnor@varcem.com" +#define STR_NAME "VARCem" +#define STR_TITLE "Virtual ARchaeological Computer EMulator" + /* Messagebox classes (2100.) */ #define STR_2100 "Ошибка" @@ -64,27 +67,24 @@ #define STR_2202 "Невозможно использовать PCap, вероятно он не инициализирован" #define STR_2203 "Устройства PCap не найдены" #define STR_2204 "Неверное устройство PCap" -#define STR_2205 "Невозможно инициализировать OpenAL, убедитесь в наличии следующей библиотеки\nв вашей папке с программой:\n\nlibopenal-1.dll" -#define STR_2206 "Невозможно инициализировать FluidSynth, убедитесь в наличии следующей библиотеки\nв вашей папке с программой:\n\nlibfluidsynth.dll" -#define STR_2207 "Недостаточно памяти !" +#define STR_2205 "Невозможно инициализировать %s.\nУбедитесь в наличии библиотеки %s в вашей системе или в папке с программой." /* Application error messages (2300.) */ -#define STR_2300 "Невозможно создать bitmap-файл: %s" +#define STR_2300 "Недостаточно памяти !" #define STR_2301 "Не найдено поддерживаемых образов ROM!" #define STR_2302 "Не найдено допустимой конфигурации.\n\nВы хотели бы открыть диалог Настройки и создать её?" -#define STR_2303 "Сконфигурированный компьютер:\n\n %ls\n\nis недоступен.\n\nОткрыть диалог Настройки?" -#define STR_2304 "Сконфигурированная видеокарта:\n\n %ls\n\nis недоступна.\n\nОткрыть диалог Настройки?" -#define STR_2305 "Выбранный рендерер '%S' недоступен. Использовать основной?" -#define STR_2306 "ST506 и ESDI дисководы CD-ROM никогда не существовали" +#define STR_2303 "Сконфигурированный %ls:\n\n %s\n\nнедоступен.\n\nОткрыть диалог Настройки?" +#define STR_2304 "Выбранный рендерер:\n\n %s\n\nнедоступен. Использовать основной?" +#define STR_2305 "Сначала вы должны сохранить новые настройки!" +#define STR_2306 "Невозможно создать bitmap-файл: %ls" #define STR_2307 "USB пока не поддерживается" -#define STR_2308 "Сначала вы должны сохранить новые настройки!" /* Application messages (2400.) */ #define STR_2400 "Вы уверены, что хотите сохранить эти настройки?\n\n(Возможно, потребуется рестарт...)" #define STR_2401 "Изменения сохранены, пожалуйста перезапустите эмулятор!" -#define STR_2402 "Выбранное устройство '%ls' ещё находится `в процессе разработки` и может вызвать проблемы.\n\nВы уверены, что хотите его использовать?" +#define STR_2402 "Выбранное устройство:\n\n %s\n\nещё находится `в процессе разработки` и может вызвать проблемы.\n\nВы уверены, что хотите его использовать?" #define STR_2403 "Щёлкните мышью для захвата курсора" #define STR_2404 "Нажмите F8+F12 чтобы освободить курсор" #define STR_2405 "Нажмите F8+F12 или среднюю кнопку мыши чтобы освободить курсор" @@ -98,11 +98,15 @@ /* UI: common elements (3000.) */ #define STR_OK "OK" #define STR_CANCEL "Отменить" +#define STR_YES "Да" +#define STR_NO "Нет" #define STR_CONFIGURE "Настроить" #define STR_BROWSE "Обзор.." + /* UI: dialog shared strings (3100.) */ #define STR_NONE "Отсутствует" +#define STR_INTERNAL "Встроенная" #define STR_DISABLED "Недоступно" #define STR_ENABLED "Доступно" #define STR_OFF "Выкл" @@ -122,18 +126,19 @@ #define STR_DEVCONF_2 "Устройство:" -/* UI: dialog: About (3200.) */ +/* UI dialog: About (3200.) */ #define STR_ABOUT "О программе VARCem.." #define STR_3201 "Авторы:" #define STR_3202 "Fred N. van Kempen, Miran Grca, Sarah Walker и другие.\nПрограмма основана на коде эмуляторов 86Box, PCem, MAME, DOSbox и Qemu" #define STR_3203 "Опубликована под лицензией BSD 3 и GNU General Public License (версии 2 и выше) для собственного и импортированного кода. См." #define STR_3204 "детали в файле LICENSE.txt" +/* UI dialog: Localization (3210.) */ #define STR_LOCALIZE "Локализация" #define STR_3211 "Авторы переводов с английского на другие языки:" /* UI dialog: Status (3225.) */ -#define STR_STATUS "Статус" +/* (Unused now) */ /* UI dialog: Sound Gain (3250.) */ #define STR_SNDGAIN "Усиление звука" @@ -182,23 +187,16 @@ #define STR_3328 "Циклы ожидания:" #define STR_3329 "Память:" #define STR_3330 "MB" -#define STR_3331 "Синхронизация времени" +#define STR_3331 "Синхронизация времени:" #define STR_3332 "Включить FPU" #define STR_3333 "Динамический рекомпилятор" #define STR_3334 "KB" #define STR_3335 "по умолчанию" +#define STR_3336 "Доступно (UTC)" /* UI dialog: Settings (Video, 3350.) */ #define STR_3350 "Видео:" -#define STR_3351 "Скорость видео:" -#define STR_3352 "Voodoo Graphics" -#define STR_3353 "по умолчанию" -#define STR_3354 "8-bit" -#define STR_3355 "медленная 16-bit" -#define STR_3356 "высокая 16-bit" -#define STR_3357 "медленная VLB/PCI" -#define STR_3358 "средняя VLB/PCI" -#define STR_3359 "высокая VLB/PCI" +#define STR_3351 "Voodoo Graphics" /* UI dialog: Settings (Input, 3375.) */ #define STR_3375 "Мышь:" @@ -231,8 +229,8 @@ /* UI dialog: Settings (Other Devices, 3475.) */ #define STR_3475 "Контроллер SCSI:" #define STR_3476 "Контроллер HD:" -#define STR_3477 "Третичный IDE:" -#define STR_3478 "Четвертичный IDE:" +#define STR_3477 "Третичный IDE" +#define STR_3478 "Четвертичный IDE" #define STR_3479 "Устройство ISABugger" #define STR_3480 "Карта расширения памяти (ISA)" #define STR_3481 "ISA Clock/RTC карта" @@ -253,10 +251,9 @@ #define STR_3512 "Параметры (большой)..." #define STR_3515 "ST506" #define STR_3516 "ESDI" -#define STR_3517 "IDE (PIO-only)" -#define STR_3518 "IDE (PIO+DMA)" -#define STR_3519 "SCSI" -#define STR_3520 "SCSI (съёмный)" +#define STR_3517 "IDE" +#define STR_3518 "SCSI" +#define STR_3519 "USB" /* UI dialog: Settings (Add Hard Disk, 3525.) */ #define STR_3525 "Добавить жёсткий диск" @@ -287,13 +284,12 @@ #define STR_3577 "Дисководы ZIP:" #define STR_3578 "ZIP 250" #define STR_3579 "Скорость" -#define STR_3580 "<Зарезервировано>" -#define STR_3581 "<Зарезервировано>" -#define STR_3582 "ATAPI (PIO-only)" -#define STR_3583 "ATAPI (PIO+DMA)" -#define STR_3584 "SCSI" +#define STR_3580 "ATAPI" +#define STR_3581 "SCSI" +#define STR_3582 "USB" -/* UI dialog: status bar (3900.) */ + +/* UI: Status Bar (3900.) */ #define STR_3900 "(пусто)" #define STR_3901 "(хост-диск %c:)" #define STR_3902 " [Защищён от записи]" @@ -301,6 +297,7 @@ #define STR_3904 "Открыть образ.." #define STR_3905 "Загрузить предыдущий образ" #define STR_3906 "Извлечь" +#define STR_3907 "Уведомить о смене диска" #define STR_3910 "Флоппи %i (%s): %ls" #define STR_3911 "Все образы\0*.0??;*.1??;*.360;*.720;*.86f;*.bin;*.cq?;*.dsk;*.flp;*.hdm;*.im?;*.json;*.td0;*.*fd?;*.xdf\0Продвинутые секторные образы\0*.imd;*.json;*.td0\0Простые секторные образы\0*.0??;*.1??;*.360;*.720;*.bin;*.cq?;*.dsk;*.flp;*.hdm;*.im?;*.xdf;*.*fd?\0Образы с магнитным потоком\0*.fdi\0Образы с битовым потоком\0*.86f\0Все файлы\0*.*\0" @@ -308,24 +305,21 @@ #define STR_3913 "Образы с битовым потоком\0*.86f\0" #define STR_3914 "Экспортировать в 86F.." -#define STR_3920 "CD-ROM %i (%s): %s" +#define STR_3920 "CD-ROM %i (%ls): %ls" #define STR_3921 "Хост-диск с CD/DVD (%c:)" #define STR_3922 "Образы CD-ROM\0*.iso;*.cue\0Все файлы (*.*)\0*.*\0" #define STR_3923 "Без звука" -#define STR_3930 "Жёсткий диск (%s)" +#define STR_3930 "Жёсткий диск %i (%ls): %ls" -#define STR_3940 "Съёмный диск %i: %ls" -#define STR_3941 "Уведомить о смене диска" - -#define STR_3950 "ZIP %i (%03i): %ls" +#define STR_3950 "ZIP%03i %i (%ls): %ls" #define STR_3951 "Образы для дисководов ZIP\0*.im?;*.zdi\0Все файлы\0*.*\0" #define STR_3952 "Образы для дисководов ZIP\0*.im?;*.zdi\0" -#define STR_3960 "Сеть" -#define STR_3970 "Звук" +#define STR_3960 "Сеть (%s)" +#define STR_3970 "Звук (%s)" -/* Menu: Action (4000.) */ +/* UI menu: Action (4000.) */ #define STR_ACTION "Действие" #define STR_4001 "Жёсткая перезагрузка" #define STR_4002 "Ctrl+Alt+Del" @@ -334,25 +328,25 @@ #define STR_4005 "Пауза" #define STR_4006 "Выход" -/* Menu: View (4010.) */ + +/* UI menu: View (4010.) */ #define STR_VIEW "Вид" #define STR_4011 "Изменяемый размер окна" #define STR_4012 "Запомнить размер и позицию" #define STR_4013 "Полноэкранный режим\tCtrl+Alt+PageUP" #define STR_4014 "Использовать правый CTRL как левый ALT" -#define STR_4015 "Обновлять иконки в панели статуса" -/* Menu: View > Renderer */ +/* UI menu: View > Renderer (4020.) */ #define STR_4020 "Рендерер" -/* Menu: View > Window Scale Factor */ +/* UI menu: View > Window Scale Factor (4030.) */ #define STR_4030 "Масштаб окна" #define STR_4031 "0.5x" #define STR_4032 "1x" #define STR_4033 "1.5x" #define STR_4034 "2x" -/* Menu: View > Fullscreen Stretch Mode */ +/* UI menu: View > Fullscreen Stretch Mode (4040.) */ #define STR_4040 "Растянутый полноэкранный режим" #define STR_4041 "Растянуть на весь экран" #define STR_4042 "4:3" @@ -360,14 +354,15 @@ #define STR_4044 "Целочисленное масштабирование" #define STR_4045 "Сохранять текущий размер" -/* Menu: Display (4050.) */ + +/* UI menu: Display (4050.) */ #define STR_DISPLAY "Дисплей" #define STR_4051 "Инверсный дисплей" #define STR_4052 "Разрешить оверскан" #define STR_4053 "Установить соотношение сторон 4:3" #define STR_4054 "Изменить контрастность монохромного дисплея" -/* Menu: Display > Display Type */ +/* UI menu: Display > Display Type (4060.) */ #define STR_DISPTYPE "Тип дисплея" #define STR_4061 "RGB цветной" #define STR_4062 "Монохромный" @@ -375,23 +370,26 @@ #define STR_4064 "Зелёное свечение" #define STR_4065 "Белое свечение" -/* Menu: Display > Grayscale Conversion Type */ +/* UI menu: Display > Grayscale Conversion Type (4070.) */ #define STR_GRAYSCALE "Тип монохромной конверсии" #define STR_4071 "BT601 (NTSC/PAL)" #define STR_4072 "BT709 (HDTV)" #define STR_4073 "Усреднённый" -/* Menu: Tools (4080.) */ + +/* UI menu: Tools (4080.) */ #define STR_TOOLS "Инструменты" #define STR_4081 "Настройки" #define STR_4082 "Язык" #define STR_4083 "Логгер" -#define STR_4084 "Загрузить конфигурацию" -#define STR_4085 "Сохранить конфигурацию" -#define STR_4086 "Статус" -#define STR_4087 "Сделать скриншот\tCtrl+Home" +#define STR_4084 "Разделитель лога" +#define STR_4085 "Переключить %s логгер" +#define STR_4086 "Загрузить конфигурацию" +#define STR_4087 "Сохранить конфигурацию" +#define STR_4088 "Сделать скриншот" -/* Menu: Help (4090.) */ + +/* UI menu: Help (4090.) */ #define STR_HELP "Помощь" #define STR_4091 "О программе VARCem" diff --git a/src/ui/lang/VARCem-SL.str b/src/ui/lang/VARCem-SL.str index 352a687..147f5d0 100644 --- a/src/ui/lang/VARCem-SL.str +++ b/src/ui/lang/VARCem-SL.str @@ -8,7 +8,7 @@ * * String definitions for "Slovenian (Slovenia)" language. * - * Version: @(#)VARCem-SL.str 1.0.7 2018/09/23 + * Version: @(#)VARCem-SL.str 1.0.7 2018/10/01 * * Authors: David Simunic, * Fred N. van Kempen, @@ -47,10 +47,13 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* Do not translate! */ -#define TAG_VERSION 1,0,6 -#define TAG_AUTHOR "David Simunic" -#define TAG_EMAIL "simunic.david@outlook.com" +/* Main application strings (2000) - DO NOT TRANSLATE! */ +#define STR_VERSION 1,0,7 +#define STR_AUTHOR "David Simunic" +#define STR_EMAIL "simunic.david@outlook.com" +#define STR_NAME "VARCem" +#define STR_TITLE "Virtual ARchaeological Computer EMulator" + /* Messagebox classes (2100.) */ #define STR_2100 "Napaka" @@ -65,27 +68,24 @@ #define STR_2202 "PCap se ni uspel nastaviti, ker morda ni inicializiran" #define STR_2203 "Najdena ni bila nobena PCap naprava" #define STR_2204 "Neveljavna PCap naprava" -#define STR_2205 "Ne morem inicializirati OpenAL, prepričajte se, da imate naslednjo knjižico\nv svoji mapi programa:\n\nlibopenal-1.dll" -#define STR_2206 "Ne morem inicializirati FluidSynth, prepričajte se, da imate naslednjo knjižico\nv svoji mapi programa:\n\nlibfluidsynth.dll" -#define STR_2207 "System out of memory!" +#define STR_2205 "Ne morem inicializirati %s, prepričajte se, da imate naslednjo knjižico\nv svoji mapi programa:\n\n%s" /* Application error messages (2300.) */ -#define STR_2300 "Ne morem ustvariti bitne slike: %s" +#define STR_2300 "System out of memory!" #define STR_2301 "Najdena ni bila nobena uporabna ROM slika!" #define STR_2302 "Najdena ni bila nobena veljavna konfiguracija.\n\nŽelite odpreti Nastavitve, da jo ustvarite?" -#define STR_2303 "Nastavljen računalnik:\n\n %ls\n\nni na voljo.\n\nŽelite odpreti Nastavitve?" -#define STR_2304 "Nastavljevna grafična kartica:\n\n %ls\n\nni na voljo.\n\nŽelite odpreti Nastavitve?" -#define STR_2305 "Izbran upodabljalnik '%S' ni na voljo. Ponastavim na privzetega?" -#define STR_2306 "ST506 ali ESDI CD-ROM pogoni niso obstajali" +#define STR_2303 "Nastavljen %ls:\n\n %s\n\nni na voljo.\n\nŽelite odpreti Nastavitve?" +#define STR_2304 "Izbran upodabljalnik:\n\n %s\n\nni na voljo. Ponastavim na privzetega?" +#define STR_2305 "You must save your settings first!" +#define STR_2306 "Ne morem ustvariti bitne slike: %ls" #define STR_2307 "USB še ni podprt" -#define STR_2308 "You must save your settings first!" /* Application messages (2400.) */ #define STR_2400 "Ste prepričani, da želite shraniti te nastavitve?\n\n(Morda bo potrebno ponovno zagnati program...)" #define STR_2401 "Spremembe shranjene, prosim ponovno zaženite emulator!" -#define STR_2402 "Zahtevana naprava '%ls' je trenutno še `v razvoju` in lahko povzroča težave.\n\nSte prepričani, da jo želite omogočiti?" +#define STR_2402 "Zahtevana naprava:\n\n %s\n\nje trenutno še `v razvoju` in lahko povzroča težave.\n\nSte prepričani, da jo želite omogočiti?" #define STR_2403 "Kliknite za zajem miške" #define STR_2404 "Pritisnite F8+F12 za sprostitev miške" #define STR_2405 "Pritisnite F8+F12 ali srednji miškin gumb za sprostitev miške" @@ -99,11 +99,15 @@ /* UI: common elements (3000.) */ #define STR_OK "V redu" #define STR_CANCEL "Prekliči" +#define STR_YES "Yes" +#define STR_NO "No" #define STR_CONFIGURE "Nastavi" #define STR_BROWSE "Brskaj" + /* UI: dialog shared strings (3100.) */ #define STR_NONE "Brez" +#define STR_INTERNAL "Internal" #define STR_DISABLED "Onemogočeno" #define STR_ENABLED "Omogočeno" #define STR_OFF "Izključeno" @@ -123,19 +127,19 @@ #define STR_DEVCONF_2 "Naprava:" -/* UI: dialog: About (3200.) */ +/* UI dialog: About (3200.) */ #define STR_ABOUT "Vizitka za VARCem.." #define STR_3201 "Avtorji:" #define STR_3202 "Fred N. van Kempen, Miran Grca, Sarah Walker in drugi.\nTemelji na predhodnih delih, kot so 86Box, PCem, MAME, DOSbox in Qemu." #define STR_3203 "Izdano pod licenco BSD 3-Clause License, in licenco GNU General Public License (različica 2 ali novejše) za obstoječo kodo, preneseno iz drugih projektov." #define STR_3204 "Glej LICENSE.txt za več informacij." -/* UI: dialog: Localization (3210.) */ +/* UI dialog: Localization (3210.) */ #define STR_LOCALIZE "Lokalizacija" #define STR_3211 "Prevodi iz angleščine v te druge jezike, ki jih prispevajo:" /* UI dialog: Status (3225.) */ -#define STR_STATUS "Stanje" +/* (Unused now) */ /* UI dialog: Sound Gain (3250.) */ #define STR_SNDGAIN "Pridobitev zvoka" @@ -184,23 +188,16 @@ #define STR_3328 "Čakalna stanja:" #define STR_3329 "Pomnilnik:" #define STR_3330 "MB" -#define STR_3331 "Omogoči sinhronizacijo časa" +#define STR_3331 "Omogoči sinhronizacijo časa:" #define STR_3332 "Omogoči FPU" #define STR_3333 "Dinamični recompiler" #define STR_3334 "KB" #define STR_3335 "Privzeto" +#define STR_3336 "Omogočeno (UTC)" /* UI dialog: Settings (Video, 3350.) */ #define STR_3350 "Video:" -#define STR_3351 "Hitrost videa:" -#define STR_3352 "Voodoo grafika" -#define STR_3353 "Privzeto" -#define STR_3354 "8-bitna" -#define STR_3355 "Počasna 16-bitna" -#define STR_3356 "Hitra 16-bitna" -#define STR_3357 "Počasna VLB/PCI" -#define STR_3358 "Srednja VLB/PCI" -#define STR_3359 "Hitra VLB/PCI" +#define STR_3351 "Voodoo grafika" /* UI dialog: Settings (Input, 3375.) */ #define STR_3375 "Miška:" @@ -233,8 +230,8 @@ /* UI dialog: Settings (Other Devices, 3475.) */ #define STR_3475 "SCSI krmilnik:" #define STR_3476 "Krmilnik trdih diskov:" -#define STR_3477 "Terciarni IDE:" -#define STR_3478 "Kvartarni IDE:" +#define STR_3477 "Terciarni IDE" +#define STR_3478 "Kvartarni IDE" #define STR_3479 "ISABugger naprava" #define STR_3480 "ISA Memory Expansion" #define STR_3481 "ISA Clock/RTC Card" @@ -255,11 +252,9 @@ #define STR_3512 "Po meri (velik)..." #define STR_3515 "ST506" #define STR_3516 "ESDI" -#define STR_3517 "IDE (samo PIO)" -#define STR_3518 "IDE (PIO+DMA)" -#define STR_3519 "SCSI" -#define STR_3520 "SCSI (odstranljiv)" -#define STR_3521 "USB" +#define STR_3517 "IDE" +#define STR_3518 "SCSI" +#define STR_3519 "USB" /* UI dialog: Settings (Add Hard Disk, 3525.) */ #define STR_3525 "Dodaj trdi disk" @@ -290,14 +285,12 @@ #define STR_3577 "ZIP pogoni:" #define STR_3578 "ZIP 250" #define STR_3579 "Histrost" -#define STR_3580 "" -#define STR_3581 "" -#define STR_3582 "ATAPI (samo PIO)" -#define STR_3583 "ATAPI (PIO+DMA)" -#define STR_3584 "SCSI" -#define STR_3585 "USB" +#define STR_3580 "ATAPI" +#define STR_3581 "SCSI" +#define STR_3582 "USB" -/* UI dialog: status bar (3900.) */ + +/* UI: Status Bar (3900.) */ #define STR_3900 "(prazno)" #define STR_3901 "(gostiteljev pogon %c:)" #define STR_3902 " [Zaščiteno pred pisanjem]" @@ -305,6 +298,7 @@ #define STR_3904 "&Obstoječa slika..." #define STR_3905 "&Ponovno naloži prejšnjo sliko" #define STR_3906 "I&zvrzi" +#define STR_3907 "&Obvesti o spremembi diska" #define STR_3910 "Disketa %i (%s): %ls" #define STR_3911 "Vse slike disket\0*.0??;*.1??;*.360;*.720;*.86f;*.bin;*.cq?;*.dsk;*.flp;*.hdm;*.im?;*.json;*.td0;*.*fd?;*.xdf\0Napredne sektorske slike\0*.imd;*.json;*.td0\0Osnovne sektorske slike\0*.0??;*.1??;*.360;*.720;*.bin;*.cq?;*.dsk;*.flp;*.hdm;*.im?;*.xdf;*.*fd?\0Tokovne slike\0*.fdi\0Površinske slike\0*.86f\0Vse datoteke\0*.*\0" @@ -312,24 +306,21 @@ #define STR_3913 "Površinske slike\0*.86f\0" #define STR_3914 "&Izvozi v 86F..." -#define STR_3920 "CD-ROM %i (%s): %s" +#define STR_3920 "CD-ROM %i (%ls): %ls" #define STR_3921 "Gostiteljev CD/DVD pogon (%c:)" #define STR_3922 "CD-ROM slike\0*.iso;*.cue\0Vse datoteke (*.*)\0*.*\0" #define STR_3923 "&Utišaj" -#define STR_3930 "Trdi disk (%s)" +#define STR_3930 "Trdi disk %i (%ls): %ls" -#define STR_3940 "Odstranljiv disk %i: %ls" -#define STR_3941 "&Obvesti o spremembi diska" - -#define STR_3950 "ZIP %i (%03i): %ls" +#define STR_3950 "ZIP%03i %i (%ls): %ls" #define STR_3951 "ZIP slike\0*.im?;*.zdi\0Vse datoteke\0*.*\0" #define STR_3952 "ZIP slike\0*.im?;*.zdi\0" -#define STR_3960 "Omrežje" -#define STR_3970 "Zvok" +#define STR_3960 "Omrežje (%s)" +#define STR_3970 "Zvok (%s)" -/* Menu: Action (4000.) */ +/* UI menu: Action (4000.) */ #define STR_ACTION "&Dejanje" #define STR_4001 "P&onovni zagon" #define STR_4002 "&Ctrl+Alt+Del" @@ -338,25 +329,25 @@ #define STR_4005 "&Premor" #define STR_4006 "&Izhod" -/* Menu: View (4010.) */ + +/* UI menu: View (4010.) */ #define STR_VIEW "P&ogled" #define STR_4011 "&Spremenljiva velikost okna" #define STR_4012 "&Zapomni si velikost in pozicijo" #define STR_4013 "&Celoten zaslon\tCtrl+Alt+PageUP" #define STR_4014 "&Desni CTRL je levi ALT" -#define STR_4015 "&Posodabljaj ikone vrstice stanja" -/* Menu: View > Renderer */ +/* UI menu: View > Renderer (4020.) */ #define STR_4020 "&Upodabljalnik" -/* Menu: View > Window Scale Factor */ +/* UI menu: View > Window Scale Factor (4030.) */ #define STR_4030 "&Faktor velikosti okna" #define STR_4031 "&0.5x" #define STR_4032 "&1x" #define STR_4033 "1.&5x" #define STR_4034 "&2x" -/* Menu: View > Fullscreen Stretch Mode */ +/* UI menu: View > Fullscreen Stretch Mode (4040.) */ #define STR_4040 "&Način celozaslonskega raztezanja" #define STR_4041 "&Raztegni na celoten zaslon" #define STR_4042 "&4:3" @@ -364,14 +355,15 @@ #define STR_4044 "&Celoštevilska skala" #define STR_4045 "&Ohrani velikost" -/* Menu: Display (4050.) */ + +/* UI menu: Display (4050.) */ #define STR_DISPLAY "&Zaslon" #define STR_4051 "&Obrni barve zaslona" #define STR_4052 "O&mogoči &preskeniranje" #define STR_4053 "&Izsili razmerje stranic 4:3" #define STR_4054 "Spremeni &kontrast za enobarvni zaslon" -/* Menu: Display > Display Type */ +/* UI menu: Display > Display Type (4060.) */ #define STR_DISPTYPE "&Tip zaslona" #define STR_4061 "&RGB barvni zaslon" #define STR_4062 "&Sivinski zaslon" @@ -379,23 +371,26 @@ #define STR_4064 "&Zeleni zaslon" #define STR_4065 "&Beli zaslon" -/* Menu: Display > Grayscale Conversion Type */ +/* UI menu: Display > Grayscale Conversion Type (4070.) */ #define STR_GRAYSCALE "&Tip pretvorbe sivin" #define STR_4071 "BT&601 (NTSC/PAL)" #define STR_4072 "BT&709 (HDTV)" #define STR_4073 "&Povprečje" -/* Menu: Tools (4080.) */ + +/* UI menu: Tools (4080.) */ #define STR_TOOLS "&Orodja" #define STR_4081 "&Nastavitve" #define STR_4082 "&Jezik" #define STR_4083 "&Beleženje" -#define STR_4084 "N&aloži konfiguracijo" -#define STR_4085 "&Shrani konfiguracijo" -#define STR_4086 "S&tanje" -#define STR_4087 "&Zajemi posnetek zaslona\tCtrl+Home" +#define STR_4084 "Log Breakpoint" +#define STR_4085 "Toggle %s logging" +#define STR_4086 "N&aloži konfiguracijo" +#define STR_4087 "&Shrani konfiguracijo" +#define STR_4088 "&Zajemi posnetek zaslona" -/* Menu: Help (4090.) */ + +/* UI menu: Help (4090.) */ #define STR_HELP "&Pomoč" #define STR_4091 "&Vizitka za VARCem" diff --git a/src/ui/lang/VARCem-UA.str b/src/ui/lang/VARCem-UA.str index a9cb628..2657eb6 100644 --- a/src/ui/lang/VARCem-UA.str +++ b/src/ui/lang/VARCem-UA.str @@ -1,38 +1,38 @@ /* - * VARCem Virtual ARchaeological Computer EMulator. - * An emulator of (mostly) x86-based PC systems and devices, - * using the ISA,EISA,VLB,MCA and PCI system buses, roughly - * spanning the era between 1981 and 1995. + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. * - * This file is part of the VARCem Project. + * This file is part of the VARCem Project. * - * String definitions for "Ukrainian (Ukraine)" language. + * String definitions for "Ukrainian (Ukraine)" language. * - * Version: @(#)VARCem-UA.str 1.0.6 2018/09/23 + * Version: @(#)VARCem-UA.str 1.0.6 2018/10/01 * - * Authors: .SVD., - * Fred N. van Kempen, + * Authors: .SVD., + * Fred N. van Kempen, * * - * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2017,2018 Fred N. van Kempen. * - * Redistribution and use in source and binary forms, with - * or without modification, are permitted provided that the - * following conditions are met: + * Redistribution and use in source and binary forms, with + * or without modification, are permitted provided that the + * following conditions are met: * - * 1. Redistributions of source code must retain the entire - * above notice, this list of conditions and the following - * disclaimer. + * 1. Redistributions of source code must retain the entire + * above notice, this list of conditions and the following + * disclaimer. * - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the - * following disclaimer in the documentation and/or other - * materials provided with the distribution. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the + * following disclaimer in the documentation and/or other + * materials provided with the distribution. * - * 3. Neither the name of the copyright holder nor the names - * of its contributors may be used to endorse or promote - * products derived from this software without specific - * prior written permission. + * 3. Neither the name of the copyright holder nor the names + * of its contributors may be used to endorse or promote + * products derived from this software without specific + * prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -47,354 +47,352 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* Do not translate! */ -#define TAG_VERSION 1,0,5 -#define TAG_AUTHOR ".SVD." -#define TAG_EMAIL "old-dos.ru" +/* Main application strings (2000) - DO NOT TRANSLATE! */ +#define STR_VERSION 1,0,6 +#define STR_AUTHOR ".SVD." +#define STR_EMAIL "old-dos.ru" +#define STR_NAME "VARCem" +#define STR_TITLE "Virtual ARchaeological Computer EMulator" + /* Messagebox classes (2100.) */ -#define STR_2100 "Помилка" -#define STR_2101 "Фатальна помилка" -#define STR_2102 "Помилка конфiгурацiї" -#define STR_2103 "Попередження" +#define STR_2100 "Помилка" +#define STR_2101 "Фатальна помилка" +#define STR_2102 "Помилка конфiгурацiї" +#define STR_2103 "Попередження" /* System errors (2200.) */ -#define STR_2200 "Неможливо завантажити клавiатурнi акселератори!" -#define STR_2201 "Неможливо зареєструвати прямий ввод!" -#define STR_2202 "Неможливо використання PCap, може вiн неiнiцiалiзований" -#define STR_2203 "Пристрої PCap не знайденi" -#define STR_2204 "Невiрний пристрiй PCap" -#define STR_2205 "Неможливо iнiцiювати OpenAL, переконайтесь в iснуваннi такої бiблiотеки\nу каталозi програми:\n\nlibopenal-1.dll" -#define STR_2206 "Неможливо iнiцiювати FluidSynth, переконайтесь в iснуваннi такої бiблiотеки\nу каталозi програми:\n\nlibfluidsynth.dll" -#define STR_2207 "System out of memory!" +#define STR_2200 "Неможливо завантажити клавiатурнi акселератори!" +#define STR_2201 "Неможливо зареєструвати прямий ввод!" +#define STR_2202 "Неможливо використання PCap, може вiн неiнiцiалiзований" +#define STR_2203 "Пристрої PCap не знайденi" +#define STR_2204 "Невiрний пристрiй PCap" +#define STR_2205 "Неможливо iнiцiювати %s, переконайтесь в iснуваннi такої бiблiотеки\nу каталозi програми:\n\n%s" /* Application error messages (2300.) */ -#define STR_2300 "Неможливо створити bitmap-файл: %s" -#define STR_2301 "Не знайденi пiдтримуванi iмiджi ROM!" -#define STR_2302 "Не знайдено вiрної конфiгурацiї.\n\nБажаєте вiдкрити дiалог налаштувань та створити її?" -#define STR_2303 "Сконфiгурований комп'ютер:\n\n %ls\n\n недосяжний.\n\nВiдкрити дiалог налаштувань?" -#define STR_2304 "Сконфiгурована вiдеокарта:\n\n %ls\n\n недосяжна.\n\nВiдкрити дiалог налаштувань?" -#define STR_2305 "Обраний рендер '%S' недосяжний. Використати головний?" -#define STR_2306 "ST506 та ESDI дисководы CD-ROM нiколи не iснували" -#define STR_2307 "USB поки що не пiдтримується" -#define STR_2308 "You must save your settings first!" +#define STR_2300 "System is out of memory!" +#define STR_2301 "Не знайденi пiдтримуванi iмiджi ROM!" +#define STR_2302 "Не знайдено вiрної конфiгурацiї.\n\nБажаєте вiдкрити дiалог налаштувань та створити її?" +#define STR_2303 "Сконфiгурований %ls:\n\n %s\n\nнедосяжний.\n\nВiдкрити дiалог налаштувань?" +#define STR_2304 "Обраний рендер:\n\n %s\n\nнедосяжний. Використати головний?" +#define STR_2305 "You must save your settings first!" +#define STR_2306 "Неможливо створити bitmap-файл: %ls" +#define STR_2307 "USB поки що не пiдтримується" /* Application messages (2400.) */ -#define STR_2400 "Упевненi, що бажаєте зберегти цi налаштування?\n\n(Можливо, знадобиться рестарт...)" -#define STR_2401 "Змiни збережено. Будьласка, перезапустiть емулятор." -#define STR_2402 "Обраний пристрiй '%ls' iще 'у процесi розробки' та може викликати проблеми.\n\nУпевненi, що бажаєте його використовувати?" -#define STR_2403 "Клацнiть мишшю щоб захопити курсор" -#define STR_2404 "Натиснiть F8+F12 щоб звiльнити курсор" -#define STR_2405 "Натиснiть F8+F12 або середню кнопку мишi щоб звiльнити курсор" -#define STR_2406 "Використовувати CTRL+ALT+PAGE_DOWN для повернення у вiконний режим" +#define STR_2400 "Упевненi, що бажаєте зберегти цi налаштування?\n\n(Можливо, знадобиться рестарт...)" +#define STR_2401 "Змiни збережено. Будьласка, перезапустiть емулятор." +#define STR_2402 "Обраний пристрiй:\n\n %s\n\niще 'у процесi розробки' та може викликати проблеми.\n\nУпевненi, що бажаєте його використовувати?" +#define STR_2403 "Клацнiть мишшю щоб захопити курсор" +#define STR_2404 "Натиснiть F8+F12 щоб звiльнити курсор" +#define STR_2405 "Натиснiть F8+F12 або середню кнопку мишi щоб звiльнити курсор" +#define STR_2406 "Використовувати CTRL+ALT+PAGE_DOWN для повернення у вiконний режим" /* Misc application strings (2500.) */ -#define STR_2500 "Файлы конфигурации\0*.varc\0Все файлы\0*.*\0" +#define STR_2500 "Файлы конфигурации\0*.varc\0Все файлы\0*.*\0" /* UI: common elements (3000.) */ -#define STR_OK "OK" -#define STR_CANCEL "Вiдмiнити" -#define STR_CONFIGURE "Налаштувати" -#define STR_BROWSE "Огляд.." +#define STR_OK "OK" +#define STR_CANCEL "Вiдмiнити" +#define STR_YES "Yes" +#define STR_NO "No" +#define STR_CONFIGURE "Налаштувати" +#define STR_BROWSE "Огляд.." + /* UI: dialog shared strings (3100.) */ -#define STR_NONE "Вiдсутнiй" -#define STR_DISABLED "Недосяжно" -#define STR_ENABLED "Досяжно" -#define STR_OFF "Вимк." -#define STR_ON "Ввiмк." -#define STR_TYPE "Тип" -#define STR_FILENAME "Iм'я файла:" -#define STR_PROGRESS "Прогрес:" -#define STR_BUS "Шина:" -#define STR_CHANNEL "Канал:" -#define STR_ID "ID:" -#define STR_LUN "LUN:" -#define STR_INV_NAME "Будьласка, введiть вiрне iм'я файла" -#define STR_IMG_EXIST "Iмiдж вже iснує та буде перезаписаний.\nУпевненi, що бажаєте його використовувати?" -#define STR_OPEN_READ "Неможливо вiдкрити файл для зчитування" -#define STR_OPEN_WRITE "Неможливо вiдкрити файл для запису" -#define STR_DEVCONF_1 "Конфiгурацiя" -#define STR_DEVCONF_2 "Пристрiй:" +#define STR_NONE "Вiдсутнiй" +#define STR_INTERNAL "Internal" +#define STR_DISABLED "Недосяжно" +#define STR_ENABLED "Досяжно" +#define STR_OFF "Вимк." +#define STR_ON "Ввiмк." +#define STR_TYPE "Тип" +#define STR_FILENAME "Iм'я файла:" +#define STR_PROGRESS "Прогрес:" +#define STR_BUS "Шина:" +#define STR_CHANNEL "Канал:" +#define STR_ID "ID:" +#define STR_LUN "LUN:" +#define STR_INV_NAME "Будьласка, введiть вiрне iм'я файла" +#define STR_IMG_EXIST "Iмiдж вже iснує та буде перезаписаний.\nУпевненi, що бажаєте його використовувати?" +#define STR_OPEN_READ "Неможливо вiдкрити файл для зчитування" +#define STR_OPEN_WRITE "Неможливо вiдкрити файл для запису" +#define STR_DEVCONF_1 "Конфiгурацiя" +#define STR_DEVCONF_2 "Пристрiй:" -/* UI: dialog: About (3200.) */ -#define STR_ABOUT "Про програму VARCem.." -#define STR_3201 "Автори:" -#define STR_3202 "Fred N. van Kempen, Miran Grca, Sarah Walker та iншi.\nПрограма базована на кодi емуляторiв 86Box, PCem, MAME, DOSbox та Qemu" -#define STR_3203 "Публiкується за лiцензiєю BSD 3 та GNU General Public License (версiї 2 та вище) для власного та iмпортованого коду." -#define STR_3204 "детальнiше у файлi LICENSE.txt" +/* UI dialog: About (3200.) */ +#define STR_ABOUT "Про програму VARCem.." +#define STR_3201 "Автори:" +#define STR_3202 "Fred N. van Kempen, Miran Grca, Sarah Walker та iншi.\nПрограма базована на кодi емуляторiв 86Box, PCem, MAME, DOSbox та Qemu" +#define STR_3203 "Публiкується за лiцензiєю BSD 3 та GNU General Public License (версiї 2 та вище) для власного та iмпортованого коду." +#define STR_3204 "детальнiше у файлi LICENSE.txt" -#define STR_LOCALIZE "Локалiзацiя" -#define STR_3211 "Автори переводiв з английскої на iншi мови:" +/* UI dialog: Localization (3210.) */ +#define STR_LOCALIZE "Локалiзацiя" +#define STR_3211 "Автори переводiв з английскої на iншi мови:" /* UI dialog: Status (3225.) */ -#define STR_STATUS "Статус" +/* (Unused now) */ /* UI dialog: Sound Gain (3250.) */ -#define STR_SNDGAIN "Пiдсилення гучностi" -#define STR_3251 "Пiдсилення" +#define STR_SNDGAIN "Пiдсилення гучностi" +#define STR_3251 "Пiдсилення" /* UI dialog: New Image (3275.) */ -#define STR_NEWIMG "Новий iмiдж флоппi" -#define STR_3276 "Розмiр диску:" -#define STR_3277 "RPM режим:" -#define STR_3278 "Точний RPM" -#define STR_3279 "На 1% повiльнiше вiд точного RPM" -#define STR_3280 "На 1.5% повiльнiше вiд точного RPM" -#define STR_3281 "На 2% повiльнiше вiд точного RPM" -#define STR_3282 "160 KB" -#define STR_3283 "180 KB" -#define STR_3284 "320 KB" -#define STR_3285 "360 KB" -#define STR_3286 "640 KB" -#define STR_3287 "720 KB" -#define STR_3288 "1.2 MB" -#define STR_3289 "1.25 MB" -#define STR_3290 "1.44 MB" -#define STR_3291 "DMF (кластер 1024)" -#define STR_3292 "DMF (кластер 2048)" -#define STR_3293 "2.88 MB" -#define STR_3294 "ZIP 100" -#define STR_3295 "ZIP 250" +#define STR_NEWIMG "Новий iмiдж флоппi" +#define STR_3276 "Розмiр диску:" +#define STR_3277 "RPM режим:" +#define STR_3278 "Точний RPM" +#define STR_3279 "На 1% повiльнiше вiд точного RPM" +#define STR_3280 "На 1.5% повiльнiше вiд точного RPM" +#define STR_3281 "На 2% повiльнiше вiд точного RPM" +#define STR_3282 "160 KB" +#define STR_3283 "180 KB" +#define STR_3284 "320 KB" +#define STR_3285 "360 KB" +#define STR_3286 "640 KB" +#define STR_3287 "720 KB" +#define STR_3288 "1.2 MB" +#define STR_3289 "1.25 MB" +#define STR_3290 "1.44 MB" +#define STR_3291 "DMF (кластер 1024)" +#define STR_3292 "DMF (кластер 2048)" +#define STR_3293 "2.88 MB" +#define STR_3294 "ZIP 100" +#define STR_3295 "ZIP 250" /* UI dialog: Settings (3300.) */ -#define STR_SETTINGS "Налаштування" -#define STR_3310 "Комп'ютер" -#define STR_3311 "Дiсплей" -#define STR_3312 "Пристрiй вводу" -#define STR_3313 "Звук" -#define STR_3314 "Сiть" -#define STR_3315 "Порти (COM & LPT)" -#define STR_3316 "Контролери" -#define STR_3317 "Жорсткi диски" -#define STR_3318 "Дисководи флоппi" -#define STR_3319 "З'ємнi пристрої" +#define STR_SETTINGS "Налаштування" +#define STR_3310 "Комп'ютер" +#define STR_3311 "Дiсплей" +#define STR_3312 "Пристрiй вводу" +#define STR_3313 "Звук" +#define STR_3314 "Сiть" +#define STR_3315 "Порти (COM & LPT)" +#define STR_3316 "Контролери" +#define STR_3317 "Жорсткi диски" +#define STR_3318 "Дисководи флоппi" +#define STR_3319 "З'ємнi пристрої" /* UI dialog: Settings (Machine, 3325.) */ -#define STR_3325 "Комп'ютер:" -#define STR_3326 "Тип CPU:" -#define STR_3327 "CPU:" -#define STR_3328 "Цикли очiкування:" -#define STR_3329 "Пам'ять:" -#define STR_3330 "MB" -#define STR_3331 "Синхронiзацiя часу" -#define STR_3332 "Ввiмкнути FPU" -#define STR_3333 "Динамiчний рекомпiлятор" -#define STR_3334 "KB" -#define STR_3335 "за замовчуванням" +#define STR_3325 "Комп'ютер:" +#define STR_3326 "Тип CPU:" +#define STR_3327 "CPU:" +#define STR_3328 "Цикли очiкування:" +#define STR_3329 "Пам'ять:" +#define STR_3330 "MB" +#define STR_3331 "Синхронiзацiя часу:" +#define STR_3332 "Ввiмкнути FPU" +#define STR_3333 "Динамiчний рекомпiлятор" +#define STR_3334 "KB" +#define STR_3335 "за замовчуванням" +#define STR_3336 "Досяжно (UTC)" /* UI dialog: Settings (Video, 3350.) */ -#define STR_3350 "Вiдео:" -#define STR_3351 "Швидкiсть вiдео:" -#define STR_3352 "Voodoo Graphics" -#define STR_3353 "за замовчуванням" -#define STR_3354 "8-bit" -#define STR_3355 "повiльна 16-bit" -#define STR_3356 "швидка 16-bit" -#define STR_3357 "повiльна VLB/PCI" -#define STR_3358 "середня VLB/PCI" -#define STR_3359 "швидка VLB/PCI" +#define STR_3350 "Вiдео:" +#define STR_3351 "Voodoo Graphics" /* UI dialog: Settings (Input, 3375.) */ -#define STR_3375 "Миша:" -#define STR_3376 "Джойстiк:" -#define STR_3377 "Джойстiк 1" -#define STR_3378 "Джойстiк 2" -#define STR_3379 "Джойстiк 3" -#define STR_3380 "Джойстiк 4" +#define STR_3375 "Миша:" +#define STR_3376 "Джойстiк:" +#define STR_3377 "Джойстiк 1" +#define STR_3378 "Джойстiк 2" +#define STR_3379 "Джойстiк 3" +#define STR_3380 "Джойстiк 4" /* UI dialog: Settings (Sound, 3400.) */ -#define STR_3400 "Звукова карта:" -#define STR_3401 "MIDI-пристрiй:" -#define STR_3402 "Окремий MPU-401" -#define STR_3403 "Використовувати Nuked OPL" -#define STR_3404 "Використовувати FLOAT32 звук" +#define STR_3400 "Звукова карта:" +#define STR_3401 "MIDI-пристрiй:" +#define STR_3402 "Окремий MPU-401" +#define STR_3403 "Використовувати Nuked OPL" +#define STR_3404 "Використовувати FLOAT32 звук" /* UI dialog: Settings (Network, 3425.) */ -#define STR_3425 "Тип сiтки:" -#define STR_3426 "Пристрiй PCap:" -#define STR_3427 "Сiтьовий адаптер:" +#define STR_3425 "Тип сiтки:" +#define STR_3426 "Пристрiй PCap:" +#define STR_3427 "Сiтьовий адаптер:" /* UI dialog: Settings (Ports, 3450.) */ -#define STR_3450 "Iгровий порт" -#define STR_3451 "Паралельний порт 1" -#define STR_3452 "Паралельний порт 2" -#define STR_3453 "Паралельний порт 3" -#define STR_3454 "Послiдовний порт 1" -#define STR_3455 "Послiдовний порт 2" +#define STR_3450 "Iгровий порт" +#define STR_3451 "Паралельний порт 1" +#define STR_3452 "Паралельний порт 2" +#define STR_3453 "Паралельний порт 3" +#define STR_3454 "Послiдовний порт 1" +#define STR_3455 "Послiдовний порт 2" /* UI dialog: Settings (Other Devices, 3475.) */ -#define STR_3475 "Контролер SCSI:" -#define STR_3476 "Контролер HD:" -#define STR_3477 "Третичний IDE:" -#define STR_3478 "Четвертичний IDE:" -#define STR_3479 "Пристрiй ISABugger" +#define STR_3475 "Контролер SCSI:" +#define STR_3476 "Контролер HD:" +#define STR_3477 "Третичний IDE" +#define STR_3478 "Четвертичний IDE" +#define STR_3479 "Пристрiй ISABugger" #define STR_3480 "Карта расширения памяти (ISA)" #define STR_3481 "ISA Clock/RTC карта" /* UI dialog: Settings (Hard Disks, 3500.) */ -#define STR_3500 "Жорсткi диски:" -#define STR_3501 "Новий.." -#define STR_3502 "Iснуючий.." -#define STR_3503 "Прибрати" -#define STR_3504 "Шина" -#define STR_3505 "Файл" -#define STR_3506 "C" -#define STR_3507 "H" -#define STR_3508 "S" -#define STR_3509 "MB" -#define STR_3510 "MB (CHS: %u, %u, %u)" -#define STR_3511 "Параметри..." -#define STR_3512 "Параметри (бiльше)..." -#define STR_3515 "ST506" -#define STR_3516 "ESDI" -#define STR_3517 "IDE (PIO-only)" -#define STR_3518 "IDE (PIO+DMA)" -#define STR_3519 "SCSI" -#define STR_3520 "SCSI (з'ємний)" +#define STR_3500 "Жорсткi диски:" +#define STR_3501 "Новий.." +#define STR_3502 "Iснуючий.." +#define STR_3503 "Прибрати" +#define STR_3504 "Шина" +#define STR_3505 "Файл" +#define STR_3506 "C" +#define STR_3507 "H" +#define STR_3508 "S" +#define STR_3509 "MB" +#define STR_3510 "MB (CHS: %u, %u, %u)" +#define STR_3511 "Параметри..." +#define STR_3512 "Параметри (бiльше)..." +#define STR_3515 "ST506" +#define STR_3516 "ESDI" +#define STR_3517 "IDE" +#define STR_3518 "SCSI" +#define STR_3519 "USB" /* UI dialog: Settings (Add Hard Disk, 3525.) */ -#define STR_3525 "Добавити жорсткий диск" -#define STR_3526 "Добавити новий жорсткий диск" -#define STR_3527 "Добавити iснуючий жорсткий диск" -#define STR_3528 "Цилiндри:" -#define STR_3529 "Голiвки:" -#define STR_3530 "Сектори:" -#define STR_3531 "Розмiр (MB):" -#define STR_3532 "Тип:" -#define STR_3533 "Спроба створити iмiдж HDI об'єму бiльшого, нiж 4 GB" -#define STR_3534 "Спроба створити неймовiрно великий iмiдж жорсткого диску" -#define STR_3535 "Iмiджi HDI або HDX з розмiром сектора, вiдмiнним вiд 512 байтiв, не подтримуються" -#define STR_3536 "Iмiджi жорстких дискiв\0*.hd?;*.im?;*.vhd\0Усi файли\0*.*\0" -#define STR_3537 "Не забудьте створити роздiл(и) на новому диску та вiдформатувати його" +#define STR_3525 "Добавити жорсткий диск" +#define STR_3526 "Добавити новий жорсткий диск" +#define STR_3527 "Добавити iснуючий жорсткий диск" +#define STR_3528 "Цилiндри:" +#define STR_3529 "Голiвки:" +#define STR_3530 "Сектори:" +#define STR_3531 "Розмiр (MB):" +#define STR_3532 "Тип:" +#define STR_3533 "Спроба створити iмiдж HDI об'єму бiльшого, нiж 4 GB" +#define STR_3534 "Спроба створити неймовiрно великий iмiдж жорсткого диску" +#define STR_3535 "Iмiджi HDI або HDX з розмiром сектора, вiдмiнним вiд 512 байтiв, не подтримуються" +#define STR_3536 "Iмiджi жорстких дискiв\0*.hd?;*.im?;*.vhd\0Усi файли\0*.*\0" +#define STR_3537 "Не забудьте створити роздiл(и) на новому диску та вiдформатувати його" /* UI dialog: Settings (Floppy Drives, 3550.) */ -#define STR_3550 "Дисководи флоппi:" -#define STR_3551 "Тип:" -#define STR_3552 "Турбо таймiнги" -#define STR_3553 "Перевiряти BPB" -#define STR_3554 "Турбо" -#define STR_3555 "Перевiряти BPB" +#define STR_3550 "Дисководи флоппi:" +#define STR_3551 "Тип:" +#define STR_3552 "Турбо таймiнги" +#define STR_3553 "Перевiряти BPB" +#define STR_3554 "Турбо" +#define STR_3555 "Перевiряти BPB" /* UI dialog: Settings (Removable Devices, 3575.) */ -#define STR_3575 "Оптичнi дисководи:" -#define STR_3576 "Швидкiсть:" -#define STR_3577 "Дисководи ZIP:" -#define STR_3578 "ZIP 250" -#define STR_3579 "Швидкiсть" -#define STR_3580 "<Зарезервовано>" -#define STR_3581 "<Зарезервовано>" -#define STR_3582 "ATAPI (PIO-only)" -#define STR_3583 "ATAPI (PIO+DMA)" -#define STR_3584 "SCSI" - -/* UI dialog: status bar (3900.) */ -#define STR_3900 "(пусто)" -#define STR_3901 "(хост-диск %c:)" -#define STR_3902 " [Захищений вiд запису]" -#define STR_3903 "Новый iмiдж.." -#define STR_3904 "Вiдкрити iмiдж.." -#define STR_3905 "Завантажити попереднiй iмiдж" -#define STR_3906 "Вийняти" - -#define STR_3910 "Флоппi %i (%s): %ls" -#define STR_3911 "Усi iмiджi\0*.0??;*.1??;*.360;*.720;*.86f;*.bin;*.cq?;*.dsk;*.flp;*.hdm;*.im?;*.json;*.td0;*.*fd?;*.xdf\0Просунутi секторнi iмiджi\0*.imd;*.json;*.td0\0Простi секторнi iмiджi\0*.0??;*.1??;*.360;*.720;*.bin;*.cq?;*.dsk;*.flp;*.hdm;*.im?;*.xdf;*.*fd?\0Iмiджi з магнiтним стрiмом\0*.fdi\0Iмiджi з бiтовим стрiмом\0*.86f\0Усi файли\0*.*\0" -#define STR_3912 "Усi iмiджi\0*.86f;*.dsk;*.flp;*.im?;*.*fd?\0Простi секторнi iмiджi\0*.dsk;*.flp;*.im?;*.img;*.*fd?\0Iмiджi з бiтовым стрiмом\0*.86f\0" -#define STR_3913 "Iмiджi з бiтовим стрiмом\0*.86f\0" -#define STR_3914 "Экспортувати у 86F.." - -#define STR_3920 "CD-ROM %i (%s): %s" -#define STR_3921 "Хост-диск с CD/DVD (%c:)" -#define STR_3922 "Iмiджi CD-ROM\0*.iso;*.cue\0Усi файли (*.*)\0*.*\0" -#define STR_3923 "Без звуку" - -#define STR_3930 "Жорсткий диск (%s)" - -#define STR_3940 "З'ємний диск %i: %ls" -#define STR_3941 "Повiдомити про змiну диска" - -#define STR_3950 "ZIP %i (%03i): %ls" -#define STR_3951 "Iмiджi для дисководiв ZIP\0*.im?;*.zdi\0Усi файлы\0*.*\0" -#define STR_3952 "Iмiджi для дисководiв ZIP\0*.im?;*.zdi\0" -#define STR_3960 "Сiтка" -#define STR_3970 "Звук" +#define STR_3575 "Оптичнi дисководи:" +#define STR_3576 "Швидкiсть:" +#define STR_3577 "Дисководи ZIP:" +#define STR_3578 "ZIP 250" +#define STR_3579 "Швидкiсть" +#define STR_3580 "ATAPI" +#define STR_3581 "SCSI" +#define STR_3582 "USB" -/* Menu: Action (4000.) */ -#define STR_ACTION "Дiя" -#define STR_4001 "Жорстке перезавантаження" -#define STR_4002 "Ctrl+Alt+Del" -#define STR_4003 "Виконати Ctrl+Alt+Esc" -#define STR_4004 "Виконати Ctrl+Alt+Break" -#define STR_4005 "Пауза" -#define STR_4006 "Вихiд" +/* UI: Status Bar (3900.) */ +#define STR_3900 "(пусто)" +#define STR_3901 "(хост-диск %c:)" +#define STR_3902 " [Захищений вiд запису]" +#define STR_3903 "Новый iмiдж.." +#define STR_3904 "Вiдкрити iмiдж.." +#define STR_3905 "Завантажити попереднiй iмiдж" +#define STR_3906 "Вийняти" +#define STR_3907 "Повiдомити про змiну диска" -/* Menu: View (4010.) */ -#define STR_VIEW "Вигляд" -#define STR_4011 "Розмiр вiкна, що змiнюється" -#define STR_4012 "Запам'ятати розмiр та позицiю" -#define STR_4013 "Повноекранний режим\tCtrl+Alt+PageUP" -#define STR_4014 "Використовувати правий CTRL як лiвий ALT" -#define STR_4015 "Оновлювати iконки у панелi статуса" +#define STR_3910 "Флоппi %i (%s): %ls" +#define STR_3911 "Усi iмiджi\0*.0??;*.1??;*.360;*.720;*.86f;*.bin;*.cq?;*.dsk;*.flp;*.hdm;*.im?;*.json;*.td0;*.*fd?;*.xdf\0Просунутi секторнi iмiджi\0*.imd;*.json;*.td0\0Простi секторнi iмiджi\0*.0??;*.1??;*.360;*.720;*.bin;*.cq?;*.dsk;*.flp;*.hdm;*.im?;*.xdf;*.*fd?\0Iмiджi з магнiтним стрiмом\0*.fdi\0Iмiджi з бiтовим стрiмом\0*.86f\0Усi файли\0*.*\0" +#define STR_3912 "Усi iмiджi\0*.86f;*.dsk;*.flp;*.im?;*.*fd?\0Простi секторнi iмiджi\0*.dsk;*.flp;*.im?;*.img;*.*fd?\0Iмiджi з бiтовым стрiмом\0*.86f\0" +#define STR_3913 "Iмiджi з бiтовим стрiмом\0*.86f\0" +#define STR_3914 "Экспортувати у 86F.." -/* Menu: View > Renderer */ -#define STR_4020 "Рендер" +#define STR_3920 "CD-ROM %i (%ls): %ls" +#define STR_3921 "Хост-диск с CD/DVD (%c:)" +#define STR_3922 "Iмiджi CD-ROM\0*.iso;*.cue\0Усi файли (*.*)\0*.*\0" +#define STR_3923 "Без звуку" -/* Menu: View > Window Scale Factor */ -#define STR_4030 "Масштаб вiкна" -#define STR_4031 "0.5x" -#define STR_4032 "1x" -#define STR_4033 "1.5x" -#define STR_4034 "2x" +#define STR_3930 "Жорсткий диск %i (%ls): %ls" -/* Menu: View > Fullscreen Stretch Mode */ -#define STR_4040 "Розтягнутий повноекранний режим" -#define STR_4041 "Розтянути на весь екран" -#define STR_4042 "4:3" -#define STR_4043 "Квадратнi пiкселi" -#define STR_4044 "Цiлочисельне масштабування" -#define STR_4045 "Зберiгати поточний розмiр" +#define STR_3950 "ZIP%03i %i (%ls): %ls" +#define STR_3951 "Iмiджi для дисководiв ZIP\0*.im?;*.zdi\0Усi файлы\0*.*\0" +#define STR_3952 "Iмiджi для дисководiв ZIP\0*.im?;*.zdi\0" +#define STR_3960 "Сiтка (%s)" +#define STR_3970 "Звук (%s)" -/* Menu: Display (4050.) */ -#define STR_DISPLAY "Дiсплей" -#define STR_4051 "Iнверсний дiсплей" -#define STR_4052 "Дозволити оверскан" -#define STR_4053 "Встановити вiдношення сторiн 4:3" -#define STR_4054 "Змiнити контрастнiсть монохромного дiсплея" -/* Menu: Display > Display Type */ -#define STR_DISPTYPE "Тип дiсплея" -#define STR_4061 "RGB кольоровий" -#define STR_4062 "Монохромний" -#define STR_4063 "Янтарне сяйво" -#define STR_4064 "Зелене сяйво" -#define STR_4065 "Бiле сяйво" +/* UI menu: Action (4000.) */ +#define STR_ACTION "Дiя" +#define STR_4001 "Жорстке перезавантаження" +#define STR_4002 "Ctrl+Alt+Del" +#define STR_4003 "Виконати Ctrl+Alt+Esc" +#define STR_4004 "Виконати Ctrl+Alt+Break" +#define STR_4005 "Пауза" +#define STR_4006 "Вихiд" -/* Menu: Display > Grayscale Conversion Type */ -#define STR_GRAYSCALE "Тип монохромної конверсiї" -#define STR_4071 "BT601 (NTSC/PAL)" -#define STR_4072 "BT709 (HDTV)" -#define STR_4073 "Усереднений" -/* Menu: Tools (4080.) */ -#define STR_TOOLS "Iнструменти" -#define STR_4081 "Налаштування" -#define STR_4082 "Мова" -#define STR_4083 "Логер" -#define STR_4084 "Завантажити конфигурацiю" -#define STR_4085 "Зберегти конфигурацiю" -#define STR_4086 "Статус" -#define STR_4087 "Зробити скрiншот\tCtrl+Home" +/* UI menu: View (4010.) */ +#define STR_VIEW "Вигляд" +#define STR_4011 "Розмiр вiкна, що змiнюється" +#define STR_4012 "Запам'ятати розмiр та позицiю" +#define STR_4013 "Повноекранний режим\tCtrl+Alt+PageUP" +#define STR_4014 "Використовувати правий CTRL як лiвий ALT" -/* Menu: Help (4090.) */ -#define STR_HELP "Допомога" -#define STR_4091 "Про програму VARCem" +/* UI menu: View > Renderer (4020.) */ +#define STR_4020 "Рендер" + +/* UI menu: View > Window Scale Factor (4030.) */ +#define STR_4030 "Масштаб вiкна" +#define STR_4031 "0.5x" +#define STR_4032 "1x" +#define STR_4033 "1.5x" +#define STR_4034 "2x" + +/* UI menu: View > Fullscreen Stretch Mode (4040.) */ +#define STR_4040 "Розтягнутий повноекранний режим" +#define STR_4041 "Розтянути на весь екран" +#define STR_4042 "4:3" +#define STR_4043 "Квадратнi пiкселi" +#define STR_4044 "Цiлочисельне масштабування" +#define STR_4045 "Зберiгати поточний розмiр" + + +/* UI menu: Display (4050.) */ +#define STR_DISPLAY "Дiсплей" +#define STR_4051 "Iнверсний дiсплей" +#define STR_4052 "Дозволити оверскан" +#define STR_4053 "Встановити вiдношення сторiн 4:3" +#define STR_4054 "Змiнити контрастнiсть монохромного дiсплея" + +/* UI menu: Display > Display Type (4060.) */ +#define STR_DISPTYPE "Тип дiсплея" +#define STR_4061 "RGB кольоровий" +#define STR_4062 "Монохромний" +#define STR_4063 "Янтарне сяйво" +#define STR_4064 "Зелене сяйво" +#define STR_4065 "Бiле сяйво" + +/* UI menu: Display > Grayscale Conversion Type (4070.) */ +#define STR_GRAYSCALE "Тип монохромної конверсiї" +#define STR_4071 "BT601 (NTSC/PAL)" +#define STR_4072 "BT709 (HDTV)" +#define STR_4073 "Усереднений" + + +/* UI menu: Tools (4080.) */ +#define STR_TOOLS "Iнструменти" +#define STR_4081 "Налаштування" +#define STR_4082 "Мова" +#define STR_4083 "Логер" +#define STR_4084 "Log Breakpoint" +#define STR_4085 "Toggle %s logging" +#define STR_4086 "Завантажити конфигурацiю" +#define STR_4087 "Зберегти конфигурацiю" +#define STR_4088 "Зробити скрiншот" + + +/* UI menu: Help (4090.) */ +#define STR_HELP "Допомога" +#define STR_4091 "Про програму VARCem" /* End of file. */ diff --git a/src/ui/lang/VARCem.def b/src/ui/lang/VARCem.def new file mode 100644 index 0000000..5d53d0f --- /dev/null +++ b/src/ui/lang/VARCem.def @@ -0,0 +1,380 @@ +/* + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. + * + * This file is part of the VARCem Project. + * + * String table for the application, shared by all platforms. + * + * Version: @(#)VARCem.def 1.0.2 2018/10/01 + * + * Author: Fred N. van Kempen, + * + * Copyright 2018 Fred N. van Kempen. + * + * Redistribution and use in source and binary forms, with + * or without modification, are permitted provided that the + * following conditions are met: + * + * 1. Redistributions of source code must retain the entire + * above notice, this list of conditions and the following + * disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the + * following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names + * of its contributors may be used to endorse or promote + * products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* Common strings (2000.) */ +STRTBL( IDS_NAME, STR_NAME ) +STRTBL( IDS_TITLE, STR_TITLE ) + +/* Messagebox classes (2100.) */ +STRTBL( IDS_ERROR, STR_2100 ) +STRTBL( IDS_ERROR_FATAL, STR_2101 ) +STRTBL( IDS_ERROR_CONF, STR_2102 ) +STRTBL( IDS_WARNING, STR_2103 ) + +/* System errors (2200.) */ +STRTBL( IDS_ERR_ACCEL, STR_2200 ) +STRTBL( IDS_ERR_INPUT, STR_2201 ) +STRTBL( IDS_ERR_PCAP, STR_2202 ) +STRTBL( IDS_ERR_PCAP_NO, STR_2203 ) +STRTBL( IDS_ERR_PCAP_DEV, STR_2204 ) +STRTBL( IDS_ERR_NOLIB, STR_2205 ) + +/* Application error messages (2300.) */ +STRTBL( IDS_ERR_NOMEM, STR_2300 ) +STRTBL( IDS_ERR_NOROMS, STR_2301 ) +STRTBL( IDS_ERR_NOCONF, STR_2302 ) +STRTBL( IDS_ERR_NOAVAIL, STR_2303 ) +STRTBL( IDS_ERR_NORENDR, STR_2304 ) +STRTBL( IDS_ERR_SAVEIT, STR_2305 ) +STRTBL( IDS_ERR_SCRSHOT,STR_2306 ) +STRTBL( IDS_ERR_NO_USB, STR_2307 ) + +/* Application messages (2400.) */ +STRTBL( IDS_MSG_SAVE, STR_2400 ) +STRTBL( IDS_MSG_RESTART, STR_2401 ) +STRTBL( IDS_MSG_UNSTABL, STR_2402 ) +STRTBL( IDS_MSG_CAPTURE, STR_2403 ) +STRTBL( IDS_MSG_MRLS_1, STR_2404 ) +STRTBL( IDS_MSG_MRLS_2, STR_2405 ) +STRTBL( IDS_MSG_WINDOW, STR_2406 ) + +/* Misc application strings (2500.) */ +STRTBL( IDS_2500, STR_2500 ) + + +/* UI: common elements (3000.) */ +STRTBL( IDS_OK, STR_OK ) +STRTBL( IDS_CANCEL, STR_CANCEL ) +STRTBL( IDS_YES, STR_YES ) +STRTBL( IDS_NO, STR_NO ) +STRTBL( IDS_CONFIGURE, STR_CONFIGURE ) +STRTBL( IDS_BROWSE, STR_BROWSE ) + +/* UI: dialog shared strings (3100.) */ +STRTBL( IDS_NONE, STR_NONE ) +STRTBL( IDS_INTERNAL, STR_INTERNAL ) +STRTBL( IDS_DISABLED, STR_DISABLED ) +STRTBL( IDS_ENABLED, STR_ENABLED ) +STRTBL( IDS_OFF, STR_OFF ) +STRTBL( IDS_ON, STR_ON ) +STRTBL( IDS_TYPE, STR_TYPE ) +STRTBL( IDS_FILENAME, STR_FILENAME ) +STRTBL( IDS_PROGRESS, STR_PROGRESS ) +STRTBL( IDS_BUS, STR_BUS ) +STRTBL( IDS_CHANNEL, STR_CHANNEL ) +STRTBL( IDS_ID, STR_ID ) +STRTBL( IDS_LUN, STR_LUN ) +STRTBL( IDS_INV_NAME, STR_INV_NAME ) +STRTBL( IDS_IMG_EXIST, STR_IMG_EXIST ) +STRTBL( IDS_OPEN_READ, STR_OPEN_READ ) +STRTBL( IDS_OPEN_WRITE, STR_OPEN_WRITE ) +STRTBL( IDS_DEVCONF_1, STR_DEVCONF_1 ) +STRTBL( IDS_DEVCONF_2, STR_DEVCONF_2 ) + +/* UI: dialog: About (3200.) */ +STRTBL( IDS_ABOUT, STR_ABOUT ) +STRTBL( IDS_3201, STR_3201 ) +STRTBL( IDS_3202, STR_3202 ) +STRTBL( IDS_3203, STR_3203 ) +STRTBL( IDS_3204, STR_3204 ) + +/* UI: dialog: Localization (3210.) */ +STRTBL( IDS_LOCALIZE, STR_LOCALIZE ) +STRTBL( IDS_3211, STR_3211 ) + +/* UI dialog: Status (3225.) */ +/* (Unused now) */ + +/* UI dialog: Sound Gain (3250.) */ +STRTBL( IDS_SNDGAIN, STR_SNDGAIN ) +STRTBL( IDS_3251, STR_3251 ) + +/* UI dialog: New Image (3275.) */ +STRTBL( IDS_NEWIMG, STR_NEWIMG ) +STRTBL( IDS_3276, STR_3276 ) +STRTBL( IDS_3277, STR_3277 ) +STRTBL( IDS_3278, STR_3278 ) +STRTBL( IDS_3279, STR_3279 ) +STRTBL( IDS_3280, STR_3280 ) +STRTBL( IDS_3281, STR_3281 ) +STRTBL( IDS_3282, STR_3282 ) +STRTBL( IDS_3283, STR_3283 ) +STRTBL( IDS_3284, STR_3284 ) +STRTBL( IDS_3285, STR_3285 ) +STRTBL( IDS_3286, STR_3286 ) +STRTBL( IDS_3287, STR_3287 ) +STRTBL( IDS_3288, STR_3288 ) +STRTBL( IDS_3289, STR_3289 ) +STRTBL( IDS_3290, STR_3290 ) +STRTBL( IDS_3291, STR_3291 ) +STRTBL( IDS_3292, STR_3292 ) +STRTBL( IDS_3293, STR_3293 ) +STRTBL( IDS_3294, STR_3294 ) +STRTBL( IDS_3295, STR_3295 ) + +/* UI dialog: Settings (3300.) */ +STRTBL( IDS_SETTINGS, STR_SETTINGS ) +STRTBL( IDS_3310, STR_3310 ) +STRTBL( IDS_3311, STR_3311 ) +STRTBL( IDS_3312, STR_3312 ) +STRTBL( IDS_3313, STR_3313 ) +STRTBL( IDS_3314, STR_3314 ) +STRTBL( IDS_3315, STR_3315 ) +STRTBL( IDS_3316, STR_3316 ) +STRTBL( IDS_3317, STR_3317 ) +STRTBL( IDS_3318, STR_3318 ) +STRTBL( IDS_3319, STR_3319 ) + +/* UI dialog: Settings (Machine, 3325.) */ +STRTBL( IDS_3325, STR_3325 ) +STRTBL( IDS_3326, STR_3326 ) +STRTBL( IDS_3327, STR_3327 ) +STRTBL( IDS_3328, STR_3328 ) +STRTBL( IDS_3329, STR_3329 ) +STRTBL( IDS_3330, STR_3330 ) +STRTBL( IDS_3331, STR_3331 ) +STRTBL( IDS_3332, STR_3332 ) +STRTBL( IDS_3333, STR_3333 ) +STRTBL( IDS_3334, STR_3334 ) +STRTBL( IDS_3335, STR_3335 ) +STRTBL( IDS_3336, STR_3336 ) + +/* UI dialog: Settings (Video, 3350.) */ +STRTBL( IDS_3350, STR_3350 ) +STRTBL( IDS_3351, STR_3351 ) + +/* UI dialog: Settings (Input, 3375.) */ +STRTBL( IDS_3375, STR_3375 ) +STRTBL( IDS_3376, STR_3376 ) +STRTBL( IDS_3377, STR_3377 ) +STRTBL( IDS_3378, STR_3378 ) +STRTBL( IDS_3379, STR_3379 ) +STRTBL( IDS_3380, STR_3380 ) + +/* UI dialog: Settings (Sound, 3400.) */ +STRTBL( IDS_3400, STR_3400 ) +STRTBL( IDS_3401, STR_3401 ) +STRTBL( IDS_3402, STR_3402 ) +STRTBL( IDS_3403, STR_3403 ) +STRTBL( IDS_3404, STR_3404 ) + +/* UI dialog: Settings (Network, 3425.) */ +STRTBL( IDS_3425, STR_3425 ) +STRTBL( IDS_3426, STR_3426 ) +STRTBL( IDS_3427, STR_3427 ) + +/* UI dialog: Settings (Ports, 3450.) */ +STRTBL( IDS_3450, STR_3450 ) +STRTBL( IDS_3451, STR_3451 ) +STRTBL( IDS_3452, STR_3452 ) +STRTBL( IDS_3453, STR_3453 ) +STRTBL( IDS_3454, STR_3454 ) +STRTBL( IDS_3455, STR_3455 ) + +/* UI dialog: Settings (Other Devices, 3475.) */ +STRTBL( IDS_3475, STR_3475 ) +STRTBL( IDS_3476, STR_3476 ) +STRTBL( IDS_3477, STR_3477 ) +STRTBL( IDS_3478, STR_3478 ) +STRTBL( IDS_3479, STR_3479 ) +STRTBL( IDS_3480, STR_3480 ) +STRTBL( IDS_3481, STR_3481 ) + +/* UI dialog: Settings (Hard Disks, 3500.) */ +STRTBL( IDS_3500, STR_3500 ) +STRTBL( IDS_3501, STR_3501 ) +STRTBL( IDS_3502, STR_3502 ) +STRTBL( IDS_3503, STR_3503 ) +STRTBL( IDS_3504, STR_3504 ) +STRTBL( IDS_3505, STR_3505 ) +STRTBL( IDS_3506, STR_3506 ) +STRTBL( IDS_3507, STR_3507 ) +STRTBL( IDS_3508, STR_3508 ) +STRTBL( IDS_3509, STR_3509 ) +STRTBL( IDS_3510, STR_3510 ) +STRTBL( IDS_3511, STR_3511 ) +STRTBL( IDS_3512, STR_3512 ) +/* 3513 available */ +/* 3514 available */ +STRTBL( IDS_3515, STR_3515 ) +STRTBL( IDS_3516, STR_3516 ) +STRTBL( IDS_3517, STR_3517 ) +STRTBL( IDS_3518, STR_3518 ) +STRTBL( IDS_3519, STR_3519 ) + +/* UI dialog: Settings (Add Hard Disk, 3525.) */ +STRTBL( IDS_3525, STR_3525 ) +STRTBL( IDS_3526, STR_3526 ) +STRTBL( IDS_3527, STR_3527 ) +STRTBL( IDS_3528, STR_3528 ) +STRTBL( IDS_3529, STR_3529 ) +STRTBL( IDS_3530, STR_3530 ) +STRTBL( IDS_3531, STR_3531 ) +STRTBL( IDS_3532, STR_3532 ) +STRTBL( IDS_3533, STR_3533 ) +STRTBL( IDS_3534, STR_3534 ) +STRTBL( IDS_3535, STR_3535 ) +STRTBL( IDS_3536, STR_3536 ) +STRTBL( IDS_3537, STR_3537 ) + +/* UI dialog: Settings (Floppy Drives, 3550.) */ +STRTBL( IDS_3550, STR_3550 ) +STRTBL( IDS_3551, STR_3551 ) +STRTBL( IDS_3552, STR_3552 ) +STRTBL( IDS_3553, STR_3553 ) +STRTBL( IDS_3554, STR_3554 ) +STRTBL( IDS_3555, STR_3555 ) + +/* UI dialog: Settings (Removable Devices, 3575.) */ +STRTBL( IDS_3575, STR_3575 ) +STRTBL( IDS_3576, STR_3576 ) +STRTBL( IDS_3577, STR_3577 ) +STRTBL( IDS_3578, STR_3578 ) +STRTBL( IDS_3579, STR_3579 ) +STRTBL( IDS_3580, STR_3580 ) +STRTBL( IDS_3581, STR_3581 ) +STRTBL( IDS_3582, STR_3582 ) + +/* UI dialog: status bar (3900.) */ +STRTBL( IDS_3900, STR_3900 ) +STRTBL( IDS_3901, STR_3901 ) +STRTBL( IDS_3902, STR_3902 ) +STRTBL( IDS_3903, STR_3903 ) +STRTBL( IDS_3904, STR_3904 ) +STRTBL( IDS_3905, STR_3905 ) +STRTBL( IDS_3906, STR_3906 ) +STRTBL( IDS_3907, STR_3907 ) +/* 3908 available */ +/* 3909 available */ +STRTBL( IDS_3910, STR_3910 ) +STRTBL( IDS_3911, STR_3911 ) +STRTBL( IDS_3912, STR_3912 ) +STRTBL( IDS_3913, STR_3913 ) +STRTBL( IDS_3914, STR_3914 ) +STRTBL( IDS_3920, STR_3920 ) +STRTBL( IDS_3921, STR_3921 ) +STRTBL( IDS_3922, STR_3922 ) +STRTBL( IDS_3923, STR_3923 ) +STRTBL( IDS_3930, STR_3930 ) +STRTBL( IDS_3950, STR_3950 ) +STRTBL( IDS_3951, STR_3951 ) +STRTBL( IDS_3952, STR_3952 ) +STRTBL( IDS_3960, STR_3960 ) +STRTBL( IDS_3970, STR_3970 ) + +/* UI menu: Action (4000.) */ +STRTBL( IDS_ACTION, STR_ACTION ) +STRTBL( IDS_4001, STR_4001 ) +STRTBL( IDS_4002, STR_4002 ) +STRTBL( IDS_4003, STR_4003 ) +STRTBL( IDS_4004, STR_4004 ) +STRTBL( IDS_4005, STR_4005 ) +STRTBL( IDS_4006, STR_4006 ) + +/* UI menu: View (4010.) */ +STRTBL( IDS_VIEW, STR_VIEW ) +STRTBL( IDS_4011, STR_4011 ) +STRTBL( IDS_4012, STR_4012 ) +STRTBL( IDS_4013, STR_4013 ) +STRTBL( IDS_4014, STR_4014 ) + +/* UI menu: View > Renderer */ +STRTBL( IDS_4020, STR_4020 ) + +/* UI menu: View > Window Scale Factor */ +STRTBL( IDS_4030, STR_4030 ) +STRTBL( IDS_4031, STR_4031 ) +STRTBL( IDS_4032, STR_4032 ) +STRTBL( IDS_4033, STR_4033 ) +STRTBL( IDS_4034, STR_4034 ) + +/* UI menu: View > Fullscreen Stretch Mode */ +STRTBL( IDS_4040, STR_4040 ) +STRTBL( IDS_4041, STR_4041 ) +STRTBL( IDS_4042, STR_4042 ) +STRTBL( IDS_4043, STR_4043 ) +STRTBL( IDS_4044, STR_4044 ) +STRTBL( IDS_4045, STR_4045 ) + +/* UI menu: Display (4050.) */ +STRTBL( IDS_DISPLAY, STR_DISPLAY ) +STRTBL( IDS_4051, STR_4051 ) +STRTBL( IDS_4052, STR_4052 ) +STRTBL( IDS_4053, STR_4053 ) +STRTBL( IDS_4054, STR_4054 ) + +/* UI menu: Display > Display Type */ +STRTBL( IDS_DISPTYPE, STR_DISPTYPE ) +STRTBL( IDS_4061, STR_4061 ) +STRTBL( IDS_4062, STR_4062 ) +STRTBL( IDS_4063, STR_4063 ) +STRTBL( IDS_4064, STR_4064 ) +STRTBL( IDS_4065, STR_4065 ) + +/* UI menu: Display > Grayscale Conversion Type */ +STRTBL( IDS_GRAYSCALE, STR_GRAYSCALE ) +STRTBL( IDS_4071, STR_4071 ) +STRTBL( IDS_4072, STR_4072 ) +STRTBL( IDS_4073, STR_4073 ) + +/* UI menu: Tools (4080.) */ +STRTBL( IDS_TOOLS, STR_TOOLS ) +STRTBL( IDS_4081, STR_4081 ) +STRTBL( IDS_4082, STR_4082 ) +STRTBL( IDS_4083, STR_4083 ) +STRTBL( IDS_4084, STR_4084 ) +STRTBL( IDS_4085, STR_4085 ) +STRTBL( IDS_4086, STR_4086 ) +STRTBL( IDS_4087, STR_4087 ) +STRTBL( IDS_4088, STR_4088 ) + +/* UI menu: Help (4090.) */ +STRTBL( IDS_HELP, STR_HELP ) +STRTBL( IDS_4091, STR_4091 ) + + +/* End of table. */ diff --git a/src/ui/lang/VARCem.lang b/src/ui/lang/VARCem.lang index f63d80c..0823284 100644 --- a/src/ui/lang/VARCem.lang +++ b/src/ui/lang/VARCem.lang @@ -8,7 +8,7 @@ # # Supported Languages database. # -# Version: @(#)VARCem.lang 1.0.3 2018/07/11 +# Version: @(#)VARCem.lang 1.0.4 2018/09/26 # # Author: Fred N. van Kempen, # @@ -44,19 +44,19 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # -BY,0423,LANG_BELARUSIAN,SUBLANG_BELARUSIAN_BELARUS -CZ,0405,LANG_CZECH,SUBLANG_CZECH_CZECH_REPUBLIC -DE,0407,LANG_GERMAN,SUBLANG_GERMAN -DU,0413,LANG_DUTCH,SUBLANG_DUTCH -ES,040a,LANG_SPANISH,SUBLANG_SPANISH -FI,040b,LANG_FINNISH,SUBLANG_FINNISH_FINLAND -FR,040c,LANG_FRENCH,SUBLANG_FRENCH -IT,0410,LANG_ITALIAN,SUBLANG_ITALIAN -JP,0411,LANG_JAPANESE,SUBLANG_JAPANESE_JAPAN -KR,0412,LANG_KOREAN,SUBLANG_KOREAN -KZ,043f,LANG_KAZAK,SUBLANG_KAZAK_KAZAKHSTAN -LT,0427,LANG_LITHUANIAN,SUBLANG_LITHUANIAN_LITHUANIA -NO,0414,LANG_NORWEGIAN,SUBLANG_NORWEGIAN_BOKMAL -RU,0419,LANG_RUSSIAN,SUBLANG_RUSSIAN_RUSSIA -SL,0424,LANG_SLOVENIAN,SUBLANG_SLOVENIAN_SLOVENIA -UA,0422,LANG_UKRAINIAN,SUBLANG_UKRAINIAN_UKRAINE +BY,0423,LANG_BELARUSIAN,SUBLANG_BELARUSIAN_BELARUS,Belarusian +CZ,0405,LANG_CZECH,SUBLANG_CZECH_CZECH_REPUBLIC,Czech +DE,0407,LANG_GERMAN,SUBLANG_GERMAN,German +DU,0413,LANG_DUTCH,SUBLANG_DUTCH,Dutch +ES,040a,LANG_SPANISH,SUBLANG_SPANISH,Spanish +FI,040b,LANG_FINNISH,SUBLANG_FINNISH_FINLAND,Finnish +FR,040c,LANG_FRENCH,SUBLANG_FRENCH,French +IT,0410,LANG_ITALIAN,SUBLANG_ITALIAN,Italian +JP,0411,LANG_JAPANESE,SUBLANG_JAPANESE_JAPAN,Japanese +KR,0412,LANG_KOREAN,SUBLANG_KOREAN,Korean +KZ,043f,LANG_KAZAK,SUBLANG_KAZAK_KAZAKHSTAN,Kazakh +LT,0427,LANG_LITHUANIAN,SUBLANG_LITHUANIAN_LITHUANIA,Lithuanian +NO,0414,LANG_NORWEGIAN,SUBLANG_NORWEGIAN_BOKMAL,Norwegian +RU,0419,LANG_RUSSIAN,SUBLANG_RUSSIAN_RUSSIA,Russian +SL,0424,LANG_SLOVENIAN,SUBLANG_SLOVENIAN_SLOVENIA,Slovenian +UA,0422,LANG_UKRAINIAN,SUBLANG_UKRAINIAN_UKRAINE,Ukrainian diff --git a/src/ui/lang/VARCem-EN.str b/src/ui/lang/VARCem.str similarity index 78% rename from src/ui/lang/VARCem-EN.str rename to src/ui/lang/VARCem.str index e69e5db..9ddb300 100644 --- a/src/ui/lang/VARCem-EN.str +++ b/src/ui/lang/VARCem.str @@ -13,7 +13,7 @@ * it as the line-by-line base for the translated version, and * update fields as needed. * - * Version: @(#)VARCem-EN.str 1.0.10 2018/09/23 + * Version: @(#)VARCem.str 1.0.12 2018/10/01 * * Author: Fred N. van Kempen, * @@ -50,10 +50,13 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* Do not translate! */ -#define TAG_VERSION 1,0,1 -#define TAG_AUTHOR "Your Name" -#define TAG_EMAIL "your@email.address" +/* Main application strings (2000) - DO NOT TRANSLATE! */ +#define STR_VERSION 1,0,1 +#define STR_AUTHOR "Your Name" +#define STR_EMAIL "your@email.address" +#define STR_NAME "VARCem" +#define STR_TITLE "Virtual ARchaeological Computer EMulator" + /* Messagebox classes (2100.) */ #define STR_2100 "Error" @@ -68,27 +71,24 @@ #define STR_2202 "PCap failed to set up because it may not be initialized" #define STR_2203 "No PCap devices found" #define STR_2204 "Invalid PCap device" -#define STR_2205 "Unable to initialize OpenAL, make sure you have the following library\nin your program folder:\n\nlibopenal-1.dll" -#define STR_2206 "Unable to initialize FluidSynth, make sure you have the following library\nin your program folder:\n\nlibfluidsynth.dll" -#define STR_2207 "System out of memory!" +#define STR_2205 "Unable to initialize %s, make sure you have the '%s' library on your system or in your program folder!" /* Application error messages (2300.) */ -#define STR_2300 "Unable to create bitmap file: %s" +#define STR_2300 "System is out of memory!" #define STR_2301 "No usable ROM images found!" #define STR_2302 "No valid configuration found.\n\nWould you like to enter the Settings dialog to create one?" -#define STR_2303 "The configured machine:\n\n %ls\n\nis not available.\n\nWould you like to enter the Settings dialog?" -#define STR_2304 "Configured video card:\n\n %ls\n\nis not available.\n\nWould you like to enter the Settings dialog?" -#define STR_2305 "Selected renderer '%S' not available. Reset to default?" -#define STR_2306 "ST506/ESDI CDROM drives never existed!" +#define STR_2303 "The configured %ls:\n\n %s\n\nis not available.\n\nWould you like to enter the Settings dialog?" +#define STR_2304 "Selected renderer:\n\n %s\n\nis not available. Reset to default?" +#define STR_2305 "You must save your settings first!" +#define STR_2306 "Unable to create bitmap file: %ls" #define STR_2307 "USB is not yet supported" -#define STR_2308 "You must save your settings first!" /* Application messages (2400.) */ #define STR_2400 "Are you sure you want to save these settings?\n\n(A restart may be needed...)" #define STR_2401 "Changes saved, please restart the emulator!" -#define STR_2402 "The requested device '%ls' is currently considered to be `Under Development` and might cause problems.\n\nAre you sure you want to enable it?" +#define STR_2402 "The requested device:\n\n %s\n\nis currently considered to be `Under Development` and might cause problems.\n\nAre you sure you want to enable it?" #define STR_2403 "Click to capture mouse" #define STR_2404 "Press F8+F12 to release mouse" #define STR_2405 "Press F8+F12 or middle button to release mouse" @@ -102,11 +102,15 @@ /* UI: common elements (3000.) */ #define STR_OK "OK" #define STR_CANCEL "Cancel" +#define STR_YES "Yes" +#define STR_NO "No" #define STR_CONFIGURE "Configure" #define STR_BROWSE "Browse" + /* UI: dialog shared strings (3100.) */ #define STR_NONE "None" +#define STR_INTERNAL "Internal" #define STR_DISABLED "Disabled" #define STR_ENABLED "Enabled" #define STR_OFF "Off" @@ -126,19 +130,19 @@ #define STR_DEVCONF_2 "Device:" -/* UI: dialog: About (3200.) */ +/* UI dialog: About (3200.) */ #define STR_ABOUT "About VARCem.." #define STR_3201 "Authors:" #define STR_3202 "Fred N. van Kempen, Miran Grca, Sarah Walker and others.\nBased on earlier works like 86Box, PCem, MAME, DOSbox and Qemu." #define STR_3203 "Released under the BSD 3-Clause License, and the GNU General Public License (version 2 or up) for existing, imported code from other projects." #define STR_3204 "See LICENSE.txt for more information." -/* UI: dialog: Localization (3210.) */ +/* UI dialog: Localization (3210.) */ #define STR_LOCALIZE "Localization" #define STR_3211 "Translations from English to these other languages contributed by:" /* UI dialog: Status (3225.) */ -#define STR_STATUS "Status" +/* (Unused now) */ /* UI dialog: Sound Gain (3250.) */ #define STR_SNDGAIN "Sound Gain" @@ -187,23 +191,16 @@ #define STR_3328 "Wait states:" #define STR_3329 "Memory:" #define STR_3330 "MB" -#define STR_3331 "Enable time sync" +#define STR_3331 "Time sync:" #define STR_3332 "Enable FPU" #define STR_3333 "Dynamic Recompiler" #define STR_3334 "KB" #define STR_3335 "Default" +#define STR_3336 "Enabled (UTC)" /* UI dialog: Settings (Video, 3350.) */ #define STR_3350 "Video:" -#define STR_3351 "Video speed:" -#define STR_3352 "Voodoo Graphics" -#define STR_3353 "Default" -#define STR_3354 "8-bit" -#define STR_3355 "Slow 16-bit" -#define STR_3356 "Fast 16-bit" -#define STR_3357 "Slow VLB/PCI" -#define STR_3358 "Mid VLB/PCI" -#define STR_3359 "Fast VLB/PCI" +#define STR_3351 "Voodoo Graphics" /* UI dialog: Settings (Input, 3375.) */ #define STR_3375 "Mouse:" @@ -236,9 +233,9 @@ /* UI dialog: Settings (Other Devices, 3475.) */ #define STR_3475 "SCSI Controller:" #define STR_3476 "HD Controller:" -#define STR_3477 "Tertiary IDE:" -#define STR_3478 "Quaternary IDE:" -#define STR_3479 "ISABugger device" +#define STR_3477 "Tertiary IDE" +#define STR_3478 "Quaternary IDE" +#define STR_3479 "ISABugger Card" #define STR_3480 "ISA Memory Expansion Card" #define STR_3481 "ISA Clock/RTC Card" @@ -258,11 +255,9 @@ #define STR_3512 "Custom (large)..." #define STR_3515 "ST506" #define STR_3516 "ESDI" -#define STR_3517 "IDE (PIO-only)" -#define STR_3518 "IDE (PIO+DMA)" -#define STR_3519 "SCSI" -#define STR_3520 "SCSI (removable)" -#define STR_3521 "USB" +#define STR_3517 "IDE" +#define STR_3518 "SCSI" +#define STR_3519 "USB" /* UI dialog: Settings (Add Hard Disk, 3525.) */ #define STR_3525 "Add Hard Disk" @@ -293,14 +288,12 @@ #define STR_3577 "ZIP drives:" #define STR_3578 "ZIP 250" #define STR_3579 "Speed" -#define STR_3580 "" -#define STR_3581 "" -#define STR_3582 "ATAPI (PIO-only)" -#define STR_3583 "ATAPI (PIO+DMA)" -#define STR_3584 "SCSI" -#define STR_3585 "USB" +#define STR_3580 "ATAPI" +#define STR_3581 "SCSI" +#define STR_3582 "USB" -/* UI dialog: status bar (3900.) */ + +/* UI: Status Bar (3900.) */ #define STR_3900 "(empty)" #define STR_3901 "(host drive %c:)" #define STR_3902 " [Write Protected]" @@ -308,31 +301,29 @@ #define STR_3904 "&Load image.." #define STR_3905 "&Reload previous image" #define STR_3906 "&Unload" +#define STR_3907 "&Notify disk change" #define STR_3910 "Floppy %i (%s): %ls" -#define STR_3911 "All images\0*.0??;*.1??;*.360;*.720;*.86f;*.bin;*.cq?;*.dsk;*.flp;*.hdm;*.im?;*.json;*.td0;*.*fd?;*.xdf\0Advanced sector images\0*.imd;*.json;*.td0\0Basic sector images\0*.0??;*.1??;*.360;*.720;*.bin;*.cq?;*.dsk;*.flp;*.hdm;*.im?;*.xdf;*.*fd?\0Flux images\0*.fdi\0Surface images\0*.86f\0All files\0*.*\0" -#define STR_3912 "All images\0*.86f;*.dsk;*.flp;*.im?;*.*fd?\0Basic sector images\0*.dsk;*.flp;*.im?;*.img;*.*fd?\0Surface images\0*.86f\0" +#define STR_3911 "All images\0*.0??;*.1??;*.360;*.720;*.86f;*.bin;*.cq?;*.ddi;*.dsk;*.flp;*.hdm;*.im?;*.json;*.td0;*.*fd?;*.xdf\0Advanced sector images\0*.imd;*.json;*.td0\0Basic sector images\0*.0??;*.1??;*.360;*.720;*.bin;*.cq?;*.ddi;*.dsk;*.flp;*.hdm;*.im?;*.xdf;*.*fd?\0Flux images\0*.fdi\0Surface images\0*.86f\0All files\0*.*\0" +#define STR_3912 "All images\0*.86f;*.ddi;*.dsk;*.flp;*.im?;*.*fd?\0Basic sector images\0*.ddi;*.dsk;*.flp;*.im?;*.img;*.*fd?\0Surface images\0*.86f\0" #define STR_3913 "Surface images\0*.86f\0" #define STR_3914 "E&xport to 86F..." -#define STR_3920 "CD-ROM %i (%s): %s" +#define STR_3920 "CD-ROM %i (%ls): %ls" #define STR_3921 "Host CD/DVD Drive (%c:)" #define STR_3922 "CD-ROM images\0*.iso;*.cue\0All files (*.*)\0*.*\0" #define STR_3923 "&Mute" -#define STR_3930 "Hard disk (%s)" +#define STR_3930 "Disk %i (%ls): %ls" -#define STR_3940 "Removable disk %i: %ls" -#define STR_3941 "&Notify disk change" - -#define STR_3950 "ZIP %i (%03i): %ls" +#define STR_3950 "ZIP%03i %i (%ls): %ls" #define STR_3951 "ZIP images\0*.im?;*.zdi\0All files\0*.*\0" #define STR_3952 "ZIP images\0*.im?;*.zdi\0" -#define STR_3960 "Network" -#define STR_3970 "Sound" +#define STR_3960 "Network (%s)" +#define STR_3970 "Sound (%s)" -/* Menu: Action (4000.) */ +/* UI menu: Action (4000.) */ #define STR_ACTION "&Action" #define STR_4001 "&Hard Reset" #define STR_4002 "&Ctrl+Alt+Del" @@ -341,25 +332,25 @@ #define STR_4005 "&Pause" #define STR_4006 "E&xit" -/* Menu: View (4010.) */ + +/* UI menu: View (4010.) */ #define STR_VIEW "&View" #define STR_4011 "&Resizeable window" #define STR_4012 "R&emember size && position" #define STR_4013 "&Fullscreen\tCtrl+Alt+PageUP" #define STR_4014 "R&ight CTRL is left ALT" -#define STR_4015 "&Update status bar icons" -/* Menu: View > Renderer */ +/* UI menu: View > Renderer (4020.) */ #define STR_4020 "Re&nderer" -/* Menu: View > Window Scale Factor */ +/* UI menu: View > Window Scale Factor (4030.) */ #define STR_4030 "&Window scale factor" #define STR_4031 "&0.5x" #define STR_4032 "&1x" #define STR_4033 "1.&5x" #define STR_4034 "&2x" -/* Menu: View > Fullscreen Stretch Mode */ +/* UI menu: View > Fullscreen Stretch Mode (4040.) */ #define STR_4040 "Fullscreen &stretch mode" #define STR_4041 "&Full screen stretch" #define STR_4042 "&4:3" @@ -367,14 +358,15 @@ #define STR_4044 "&Integer scale" #define STR_4045 "&Keep size" -/* Menu: Display (4050.) */ + +/* UI menu: Display (4050.) */ #define STR_DISPLAY "&Display" #define STR_4051 "&Inverted display" #define STR_4052 "Enable &overscan" #define STR_4053 "F&orce 4:3 display ratio" #define STR_4054 "Change &contrast for monochrome display" -/* Menu: Display > Display Type */ +/* UI menu: Display > Display Type (4060.) */ #define STR_DISPTYPE "Display &type" #define STR_4061 "RGB &Color monitor" #define STR_4062 "&Grayscale monitor" @@ -382,23 +374,26 @@ #define STR_4064 "&Green monitor" #define STR_4065 "&White monitor" -/* Menu: Display > Grayscale Conversion Type */ +/* UI menu: Display > Grayscale Conversion Type (4070.) */ #define STR_GRAYSCALE "&Grayscale conversion type" #define STR_4071 "BT&601 (NTSC/PAL)" #define STR_4072 "BT&709 (HDTV)" #define STR_4073 "&Average" -/* Menu: Tools (4080.) */ + +/* UI menu: Tools (4080.) */ #define STR_TOOLS "&Tools" #define STR_4081 "&Settings" #define STR_4082 "&Language" #define STR_4083 "L&ogging" -#define STR_4084 "Load &configuration" -#define STR_4085 "S&ave configuration" -#define STR_4086 "Stat&us" -#define STR_4087 "&Take screenshot\tCtrl+Home" +#define STR_4084 "Log Breakpoint" +#define STR_4085 "Toggle %s logging" +#define STR_4086 "Load &configuration" +#define STR_4087 "S&ave configuration" +#define STR_4088 "&Take screenshot" -/* Menu: Help (4090.) */ + +/* UI menu: Help (4090.) */ #define STR_HELP "&Help" #define STR_4091 "&About VARCem" diff --git a/src/ui/ui.h b/src/ui/ui.h index 8a9bf3e..29a64aa 100644 --- a/src/ui/ui.h +++ b/src/ui/ui.h @@ -8,7 +8,7 @@ * * Define the various UI functions. * - * Version: @(#)ui.h 1.0.13 2018/05/23 + * Version: @(#)ui.h 1.0.15 2018/09/29 * * Author: Fred N. van Kempen, * @@ -69,120 +69,123 @@ /* Status Bar definitions. */ #define SB_ICON_WIDTH 24 #define SB_FLOPPY 0x00 -#define SB_CDROM 0x10 -#define SB_ZIP 0x20 -#define SB_RDISK 0x30 -#define SB_HDD 0x50 -#define SB_NETWORK 0x60 -#define SB_SOUND 0x70 -#define SB_TEXT 0x80 +#define SB_DISK 0x10 +#define SB_CDROM 0x20 +#define SB_ZIP 0x30 +#define SB_NETWORK 0x50 +#define SB_SOUND 0x60 +#define SB_TEXT 0x70 + +/* MenuItem types. */ +#define ITEM_SEPARATOR 0 +#define ITEM_NORMAL 1 +#define ITEM_CHECK 2 +#define ITEM_RADIO 3 + #ifdef USE_WX # define RENDER_FPS 30 /* default render speed */ #endif -/* Define whether or not we need the Logging submenu. */ -#if defined(ENABLE_BUS_LOG) || \ - defined(ENABLE_KEYBOARD_LOG) || defined(ENABLE_MOUSE_LOG) || \ - defined(ENABLE_GAME_LOG) || \ - defined(ENABLE_SERIAL_LOG) || defined(ENABLE_PARALLELL_LOG) || \ - defined(ENABLE_FDC_LOG) || defined(ENABLE_FDD_LOG) || \ - defined(ENABLE_D86F_LOG) || \ - defined(ENABLE_HDC_LOG) || defined(ENABLE_HDD_LOG) || \ - defined(ENABLE_ZIP_LOG) || defined(ENABLE_CDROM_LOG) || \ - defined(ENABLE_CDROM_IMAGE_LOG) || defined(ENABLE_CDROM_IOCTL_LOG) || \ - defined(ENABLE_SOUND_EMU8K_LOG) || defined(ENABLE_SOUND_MPU401_LOG) || \ - defined(ENABLE_SOUND_DEV_LOG) || \ - defined(ENABLE_NETWORK_LOG) || defined(ENABLE_NETWORK_DEV_LOG) || \ - defined(ENABLE_SCSI_BUS_LOG) || defined(ENABLE_SCSI_DISK_LOG) || \ - defined(ENABLE_SCSI_DEV_LOG) || \ - defined(ENABLE_VOODOO_LOG) -# define ENABLE_LOGGING -#endif - #ifdef __cplusplus extern "C" { #endif -#ifdef ENABLE_LOGGING -extern int pci_do_log; -extern int keyboard_do_log; -extern int mouse_do_log; -extern int game_do_log; -extern int parallel_do_log; -extern int serial_do_log; -extern int fdc_do_log; -extern int fdd_do_log; -extern int d86f_do_log; -extern int hdc_do_log; -extern int hdd_do_log; -extern int zip_do_log; -extern int cdrom_do_log; -extern int cdrom_image_do_log; -extern int cdrom_ioctl_do_log; -extern int sound_emu8k_do_log; -extern int sound_mpu401_do_log; -extern int sound_dev_do_log; -extern int network_do_log; -extern int network_dev_do_log; -extern int scsi_bus_do_log; -extern int scsi_hd_do_log; -extern int scsi_dev_do_log; -extern int voodoo_do_log; -#endif +/* Define an in-memory language entry. */ +typedef struct _lang_ { + const wchar_t *name; + const wchar_t *dll; + + const wchar_t *author; + const wchar_t *email; + const wchar_t *version; + + int id; + struct _lang_ *next; +} lang_t; + +/* Define an entry in the strings table. */ +typedef struct { + int id; + const wchar_t *str; +} string_t; + +typedef struct { + uint16_t width; + uint8_t flags; + uint8_t tag; + uint8_t icon; + wchar_t *tip; + wchar_t *text; +} sbpart_t; + /* Main GUI functions. */ +extern void ui_reset(void); +extern int ui_menu_command(int idm); +extern int ui_msgbox(int type, const void *arg); +extern void ui_fullscreen(int on); +extern void ui_mouse_capture(int on); + +extern int ui_lang_set(int id); +extern lang_t *ui_lang_get(void); +extern void ui_lang_add(lang_t *ptr, int sort); +extern void ui_lang_menu(void); + +extern void ui_floppy_mount(uint8_t drive, int part, int8_t wp, + const wchar_t *fn); +extern void ui_cdrom_eject(uint8_t id); +extern void ui_cdrom_reload(uint8_t id); +extern void ui_zip_mount(uint8_t drive, int part, int8_t wp, + const wchar_t *fn); +extern void ui_zip_eject(uint8_t id); +extern void ui_zip_reload(uint8_t id); +extern void ui_disk_mount(uint8_t drive, int part, int8_t wp, + const wchar_t *fn); +extern void ui_disk_unload(uint8_t id); +extern void ui_disk_eject(uint8_t id); +extern void ui_disk_reload(uint8_t id); + +/* Main GUI (platform) helper functions. */ +extern void ui_plat_reset(void); +extern void ui_resize(int x, int y); extern void ui_show_cursor(int on); extern void ui_show_render(int on); -extern void ui_resize(int x, int y); -extern int ui_msgbox(int type, const void *arg); -extern void ui_update(void); -extern void ui_menu_reset_all(void); -extern int ui_menu_command(int idm); -extern void ui_menu_set_logging_item(int idm, int val); -extern void ui_menu_toggle_video_item(int idm, int *val); - -/* Main GUI helper functions. */ -extern void menu_add_item(int idm, int id, const wchar_t *str); +extern wchar_t *ui_window_title(const wchar_t *s); +extern int ui_fdd_icon(int type); +extern void menu_add_item(int idm, int type, int id, const wchar_t *str); extern void menu_enable_item(int idm, int val); extern void menu_set_item(int idm, int val); extern void menu_set_radio_item(int idm, int num, int val); -extern wchar_t *ui_window_title(const wchar_t *s); /* Status Bar functions. */ -extern void ui_sb_update(void); +extern void ui_sb_reset(void); extern void ui_sb_click(int part); -extern void ui_sb_menu_command(int idm, int tag); -extern void ui_sb_menu_enable_item(int tag, int id, int val); -extern void ui_sb_menu_set_item(int tag, int id, int val); -extern void ui_sb_text_set_w(const wchar_t *str); -extern void ui_sb_text_set(const char *str); -extern void ui_sb_icon_update(int tag, int val); -extern void ui_sb_icon_state(int tag, int active); -extern void ui_sb_tip_update(int tag); -extern void ui_sb_mount_floppy(uint8_t drive, int part, int8_t wp, - const wchar_t *fn); -extern void ui_sb_mount_zip(uint8_t drive, int part, int8_t wp, - const wchar_t *fn); +extern void ui_sb_kbstate(int flags); +extern void ui_sb_icon_update(uint8_t tag, int val); +extern void ui_sb_icon_state(uint8_t tag, int active); +extern void ui_sb_tip_update(uint8_t tag); +extern void ui_sb_text_set_w(uint8_t tag, const wchar_t *str); +extern void ui_sb_text_set(uint8_t tag, const char *str); +extern void ui_sb_menu_command(int idm, uint8_t tag); +extern void ui_sb_menu_enable_item(uint8_t tag, int id, int val); +extern void ui_sb_menu_set_item(uint8_t tag, int id, int val); -/* Status Bar helper functions. */ -extern int sb_fdd_icon(int type); -extern void sb_setup(int parts, const int *widths); -extern void sb_menu_destroy(void); +/* Status Bar (platform) helper functions. */ +extern void sb_setup(int parts, const sbpart_t *data); +extern void sb_set_icon(int part, int icon); +extern void sb_set_text(int part, const wchar_t *str); +extern void sb_set_tooltip(int part, const wchar_t *str); extern void sb_menu_create(int part); extern void sb_menu_add_item(int part, int idm, const wchar_t *str); extern void sb_menu_enable_item(int part, int idm, int val);; extern void sb_menu_set_item(int part, int idm, int val); -extern void sb_set_icon(int part, int icon); -extern void sb_set_text(int part, const wchar_t *str); -extern void sb_set_tooltip(int part, const wchar_t *str); /* Dialogs. */ extern void dlg_about(void); +extern void dlg_localize(void); extern int dlg_settings(int ask); -extern void dlg_status(void); -extern void dlg_status_update(void); extern void dlg_new_image(int drive, int part, int is_zip); extern void dlg_sound_gain(void); extern int dlg_file(const wchar_t *filt, const wchar_t *ifn, diff --git a/src/ui/ui_cdrom.c b/src/ui/ui_cdrom.c new file mode 100644 index 0000000..946205d --- /dev/null +++ b/src/ui/ui_cdrom.c @@ -0,0 +1,345 @@ +/* + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. + * + * This file is part of the VARCem Project. + * + * Handle the UI part of CD-ROM/ZIP/DISK media changes. + * + * Version: @(#)ui_cdrom.c 1.0.3 2018/10/05 + * + * Author: Fred N. van Kempen, + * + * Copyright 2018 Fred N. van Kempen. + * + * Redistribution and use in source and binary forms, with + * or without modification, are permitted provided that the + * following conditions are met: + * + * 1. Redistributions of source code must retain the entire + * above notice, this list of conditions and the following + * disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the + * following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names + * of its contributors may be used to endorse or promote + * products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include +#include +#include +#include +#include +#include "../emu.h" +#include "../config.h" +#include "../plat.h" +#include "../devices/floppy/fdd.h" +#include "../devices/disk/hdd.h" +#include "../devices/scsi/scsi_device.h" +#include "../devices/scsi/scsi_disk.h" +#include "../devices/disk/zip.h" +#include "../devices/cdrom/cdrom.h" +#include "../devices/cdrom/cdrom_image.h" +#include "../devices/cdrom/cdrom_null.h" +#include "ui.h" + + +void +ui_floppy_mount(uint8_t drive, int part, int8_t wp, const wchar_t *fn) +{ + int len; + + fdd_close(drive); + + ui_writeprot[drive] = wp; + fdd_load(drive, fn); + + len = wcslen(floppyfns[drive]); + ui_sb_icon_state(SB_FLOPPY | drive, len ? 0 : 1); + + sb_menu_enable_item(part, IDM_FLOPPY_EJECT | drive, len ? 1 : 0); + sb_menu_enable_item(part, IDM_FLOPPY_EXPORT | drive, len ? 1 : 0); + + ui_sb_tip_update(SB_FLOPPY | drive); + + config_save(); +} + + +void +ui_cdrom_eject(uint8_t id) +{ + if (cdrom_drives[id].host_drive == 0) { + /* Switch from empty to empty. Do nothing. */ + return; + } + + if ((cdrom_drives[id].host_drive >= 'A') && + (cdrom_drives[id].host_drive <= 'Z')) { + ui_sb_menu_set_item(SB_CDROM | id, + IDM_CDROM_HOST_DRIVE | id | ((cdrom_drives[id].host_drive - 'A') << 3), 0); + } + + if (cdrom_image[id].prev_image_path) { + free(cdrom_image[id].prev_image_path); + cdrom_image[id].prev_image_path = NULL; + } + + if (cdrom_drives[id].host_drive == 200) { + cdrom_image[id].prev_image_path = (wchar_t *)mem_alloc(1024); + wcscpy(cdrom_image[id].prev_image_path, cdrom_image[id].image_path); + } + + cdrom_drives[id].prev_host_drive = cdrom_drives[id].host_drive; + cdrom[id]->handler->exit(id); + cdrom_close_handler(id); + memset(cdrom_image[id].image_path, 0, sizeof(cdrom_image[id].image_path)); + cdrom_null_open(id); + + if (cdrom_drives[id].bus_type) { + /* Signal disc change to the emulated machine. */ + cdrom_insert(cdrom[id]); + } + + ui_sb_menu_set_item(SB_CDROM|id, IDM_CDROM_IMAGE | id, 0); + cdrom_drives[id].host_drive = 0; + ui_sb_menu_set_item(SB_CDROM|id, IDM_CDROM_EMPTY | id, 1); + ui_sb_icon_state(SB_CDROM|id, 1); + ui_sb_menu_enable_item(SB_CDROM|id, IDM_CDROM_RELOAD | id, 1); + ui_sb_tip_update(SB_CDROM|id); + + config_save(); +} + + +void +ui_cdrom_reload(uint8_t id) +{ +#ifdef USE_CDROM_IOCTL + int new_cdrom_drive; +#endif + + if ((cdrom_drives[id].host_drive == cdrom_drives[id].prev_host_drive) || + (cdrom_drives[id].prev_host_drive == 0) || + (cdrom_drives[id].host_drive != 0)) { + /* Switch from empty to empty. Do nothing. */ + return; + } + + cdrom_close_handler(id); + memset(cdrom_image[id].image_path, 0, sizeof(cdrom_image[id].image_path)); + + if (cdrom_drives[id].prev_host_drive == 200) { + /* Reload a previous image. */ + wcscpy(cdrom_image[id].image_path, cdrom_image[id].prev_image_path); + free(cdrom_image[id].prev_image_path); + cdrom_image[id].prev_image_path = NULL; + image_open(id, cdrom_image[id].image_path); + + if (cdrom_drives[id].bus_type) { + /* Signal disc change to the emulated machine. */ + cdrom_insert(cdrom[id]); + } + + if (wcslen(cdrom_image[id].image_path) == 0) { + ui_sb_menu_set_item(SB_CDROM|id, IDM_CDROM_EMPTY | id, 1); + cdrom_drives[id].host_drive = 0; + ui_sb_menu_set_item(SB_CDROM|id, IDM_CDROM_IMAGE | id, 0); + ui_sb_icon_state(SB_CDROM|id, 1); + } else { + ui_sb_menu_set_item(SB_CDROM|id, IDM_CDROM_EMPTY | id, 0); + cdrom_drives[id].host_drive = 200; + ui_sb_menu_set_item(SB_CDROM|id, IDM_CDROM_IMAGE | id, 1); + ui_sb_icon_state(SB_CDROM|id, 0); + } +#ifdef USE_CDROM_IOCTL + } else { + /* Reload the previous host drive. */ + new_cdrom_drive = cdrom_drives[id].prev_host_drive; + ioctl_open(id, new_cdrom_drive); + if (cdrom_drives[id].bus_type) { + /* Signal disc change to the emulated machine. */ + cdrom_insert(id); + } + ui_sb_menu_set_item(SB_CDROM|id, IDM_CDROM_EMPTY | id, 0); + cdrom_drives[id].host_drive = new_cdrom_drive; + ui_sb_menu_set_item(SB_CDROM|id, IDM_CDROM_HOST_DRIVE | id | ((cdrom_drives[id].host_drive - 'A') << 3), 1); + ui_sb_icon_state(SB_CDROM|id, 0); +#endif + } + + ui_sb_menu_enable_item(SB_CDROM|id, IDM_CDROM_RELOAD | id, 0); + ui_sb_tip_update(SB_CDROM|id); + + config_save(); +} + + +void +ui_zip_mount(uint8_t drive, int part, int8_t wp, const wchar_t *fn) +{ + int len; + + zip_disk_close(zip[drive]); + + zip_drives[drive].ui_writeprot = wp; + zip_load(zip[drive], fn); + zip_insert(zip[drive]); + + len = wcslen(zip_drives[drive].image_path); + ui_sb_icon_state(SB_ZIP | drive, len ? 0 : 1); + + sb_menu_enable_item(part, IDM_ZIP_EJECT | drive, len ? 1 : 0); + sb_menu_enable_item(part, IDM_ZIP_RELOAD | drive, len ? 0 : 1); + + ui_sb_tip_update(SB_ZIP | drive); + + config_save(); +} + + +void +ui_zip_eject(uint8_t id) +{ + zip_disk_close(zip[id]); + + if (zip_drives[id].bus_type) { + /* Signal disk change to the emulated machine. */ + zip_insert(zip[id]); + } + + ui_sb_icon_state(SB_ZIP | id, 1); + ui_sb_menu_enable_item(SB_ZIP|id, IDM_ZIP_EJECT | id, 0); + ui_sb_menu_enable_item(SB_ZIP|id, IDM_ZIP_RELOAD | id, 1); + ui_sb_tip_update(SB_ZIP | id); + + config_save(); +} + + +void +ui_zip_reload(uint8_t id) +{ + zip_disk_reload(zip[id]); + + if (wcslen(zip_drives[id].image_path) == 0) { + ui_sb_menu_enable_item(SB_ZIP|id, IDM_ZIP_EJECT | id, 0); + ui_sb_icon_state(SB_ZIP|id, 1); + } else { + ui_sb_menu_enable_item(SB_ZIP|id, IDM_ZIP_EJECT | id, 1); + ui_sb_icon_state(SB_ZIP|id, 0); + } + + ui_sb_menu_enable_item(SB_ZIP|id, IDM_ZIP_RELOAD | id, 0); + ui_sb_tip_update(SB_ZIP|id); + + config_save(); +} + + +void +ui_disk_mount(uint8_t drive, int part, int8_t wp, const wchar_t *fn) +{ +#if 0 + disk_close(drive); +#endif + + //FIXME: this should be "disk_load(drive, fn)" --FvK + hdd[drive].wp = wp; + memset(hdd[drive].fn, 0x00, sizeof(hdd[drive].fn)); + wcscpy(hdd[drive].fn, fn); + +#if 0 + disk_insert(drive); +#endif + + if (wcslen(hdd[drive].fn) > 0) { + ui_sb_icon_state(SB_DISK | drive, 0); + sb_menu_enable_item(part, IDM_DISK_EJECT | drive, 1); + sb_menu_enable_item(part, IDM_DISK_RELOAD | drive, 0); + sb_menu_enable_item(part, IDM_DISK_NOTIFY | drive, 0); + } else { + ui_sb_icon_state(SB_DISK | drive, 1); + sb_menu_enable_item(part, IDM_DISK_EJECT | drive, 0); + sb_menu_enable_item(part, IDM_DISK_RELOAD | drive, 0); + sb_menu_enable_item(part, IDM_DISK_NOTIFY | drive, 0); + } + + ui_sb_tip_update(SB_DISK | drive); + + config_save(); +} + + +#ifdef USE_REMOVABLE_DISK +void +ui_disk_unload(uint8_t id) +{ + if (wcslen(hdd[id].fn) == 0) { + /* Switch from empty to empty. Do nothing. */ + return; + } + + scsi_unloadhd(hdd[id].id.scsi.id, hdd[id].id.scsi.lun, id); + scsi_disk_insert(id); +} + + +void +ui_disk_eject(uint8_t id) +{ + removable_disk_unload(id); + ui_sb_icon_state(SB_RDISK|id, 1); + ui_sb_menu_enable_item(SB_RDISK|id, IDM_RDISK_EJECT | id, 0); + ui_sb_menu_enable_item(SB_RDISK|id, IDM_RDISK_RELOAD | id, 1); + ui_sb_menu_enable_item(SB_RDISK|id, IDM_RDISK_SEND_CHANGE | id, 0); + + ui_sb_tip_update(SB_RDISK|id); + + config_save(); +} + + +void +ui_disk_reload(uint8_t id) +{ + if (wcslen(hdd[id].fn) != 0) { + /* Attempting to reload while an image is already loaded. Do nothing. */ + return; + } + + scsi_reloadhd(id); +#if 0 + scsi_disk_insert(id); +#endif + + ui_sb_icon_state(SB_RDISK|id, wcslen(hdd[id].fn) ? 0 : 1); + + ui_sb_menu_enable_item(SB_RDISK|id, IDM_RDISK_EJECT | id, wcslen(hdd[id].fn) ? 1 : 0); + ui_sb_menu_enable_item(SB_RDISK|id, IDM_RDISK_RELOAD | id, 0); + ui_sb_menu_enable_item(SB_RDISK|id, IDM_RDISK_SEND_CHANGE | id, wcslen(hdd[id].fn) ? 1 : 0); + + ui_sb_tip_update(SB_RDISK|id); + + config_save(); +} +#endif diff --git a/src/ui/ui_lang.c b/src/ui/ui_lang.c new file mode 100644 index 0000000..9dadd7f --- /dev/null +++ b/src/ui/ui_lang.c @@ -0,0 +1,252 @@ +/* + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. + * + * This file is part of the VARCem Project. + * + * Handle the generic part of the language support. + * + * Version: @(#)ui_lang.c 1.0.1 2018/10/05 + * + * Author: Fred N. van Kempen, + * + * Copyright 2018 Fred N. van Kempen. + * + * Redistribution and use in source and binary forms, with + * or without modification, are permitted provided that the + * following conditions are met: + * + * 1. Redistributions of source code must retain the entire + * above notice, this list of conditions and the following + * disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the + * following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names + * of its contributors may be used to endorse or promote + * products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include +#include +#include +#include +#include +#include "../emu.h" +#include "ui.h" +#include "../plat.h" + + +/* Local data. */ +static const string_t *strings = NULL; +static lang_t *languages = NULL; +static int languages_num = 0; + + +/* Set the correct item in the Language menu. */ +static void +lang_select(int id) +{ + lang_t *ptr; + int i = 0; + + for (ptr = languages; ptr != NULL; ptr = ptr->next) { + if (ptr->id == id) { + menu_set_radio_item(IDM_LANGUAGE+1, languages_num, i); + return; + } + i++; + } +} + + +/* Get language from index number. */ +static lang_t * +lang_index(int id) +{ + lang_t *ptr; + int i = 0; + + for (ptr = languages; ptr != NULL; ptr = ptr->next) + if (i++ == id) return(ptr); + + return(NULL); +} + + +void +ui_lang_menu(void) +{ + lang_t *ptr; + int i; + + i = IDM_LANGUAGE; + for (ptr = languages; ptr != NULL; ptr = ptr->next) { + i++; + + /* Add this language to the Languages menu. */ + menu_add_item(IDM_LANGUAGE, ITEM_RADIO, i, ptr->name); + +#ifndef USE_WX + /* Add separator after primary language. */ + //FIXME: with WX, a radio group cannot have any + // separators inbetween, it breaks the + // group. Maybe use 0 -sep- 1..n ? --FvK + if (ptr == languages) + menu_add_item(IDM_LANGUAGE, ITEM_SEPARATOR, i, NULL); +#endif + } + + /* Set active language. */ + lang_select(emu_lang_id); +} + + +/* Add a language to the list of supported languages. */ +void +ui_lang_add(lang_t *ptr, int sort) +{ + lang_t *p, *pp; + lang_t *prev = NULL; + + /* Create a copy of the entry data. */ + pp = (lang_t *)mem_alloc(sizeof(lang_t)); + memcpy(pp, ptr, sizeof(lang_t)); + + /* Add this entry to the tail of the list. */ + if (sort) { + p = languages; + if ((p == NULL) || (wcscmp(pp->name, p->name) <= 0)) { + pp->next = p; + languages = pp; + } else { + while (p != NULL) { + if (wcscmp(pp->name, p->name) >= 0) { + prev = p; + p = p->next; + continue; + } else { + prev->next = pp; + pp->next = p; + break; + } + } + prev->next = pp; + } + } else { + /* Just prepend to beginning. */ + pp->next = languages; + languages = pp; + } + + /* We got one more! */ + languages_num++; +} + + +/* Set (or re-set) the language for the application. */ +int +ui_lang_set(int id) +{ + const string_t *str; + lang_t *ptr; + + /* First, set up our language list if needed. */ + if (languages == NULL) plat_lang_scan(); + + /* If a small value, this is a menu index, not an ID. */ + if (id < 200) { + ptr = lang_index(id); + id = ptr->id; + } + + /* Set new language ID if not already set. */ + if (emu_lang_id == id) return(1); + + /* Find language in the table. */ + for (ptr = languages; ptr != NULL; ptr = ptr->next) + if (ptr->id == id) break; + if (ptr == NULL) { + ERRLOG("UI: language not supported, not setting.\n"); + return(0); + } + + /* + * Load the language module. + * + * For Windows, this will load dialogs, + * templates, icons and string tables. + * + * For UNIX, this will load strings. + */ + str = plat_lang_load(ptr); + if (str == NULL) { + ERRLOG("UI: unable to load language module '%ls' !\n", ptr->dll); + return(0); + } + + /* We are good to go! */ + strings = str; + emu_lang_id = id; + + /* Set active language. */ + lang_select(emu_lang_id); + + /* Activate the new language for the application. */ + plat_lang_set(emu_lang_id); + + /* All is good, language set! */ + return(1); +} + + +lang_t * +ui_lang_get(void) +{ + return(languages); +} + + +const wchar_t * +get_string(int id) +{ + static wchar_t buff[32]; + const wchar_t *str = NULL; + const string_t *tbl; + + tbl = strings; + while(tbl->str != NULL) { + if (tbl->id == id) { + str = tbl->str; + break; + } + + tbl++; + } + + /* Just to catch strings not in the table. */ + if (str == NULL) { + ERRLOG("UI: string %i not found in table!\n", id); + swprintf(buff, sizeof_w(buff), L"<%i>", id); + str = (const wchar_t *)buff; + } + + return(str); +} diff --git a/src/ui/ui_main.c b/src/ui/ui_main.c index 15d7b31..ea4c5c4 100644 --- a/src/ui/ui_main.c +++ b/src/ui/ui_main.c @@ -11,7 +11,10 @@ * This code is called by the UI frontend modules, and, also, * depends on those same modules for lower-level functions. * - * Version: @(#)ui_main.c 1.0.17 2018/05/24 + * FIXME: Still have to figure out how cleanly set initial logging + * levels for modules, and how to toggle/update those... + * + * Version: @(#)ui_main.c 1.0.18 2018/10/01 * * Author: Fred N. van Kempen, * @@ -57,181 +60,182 @@ #include "../device.h" #include "../plat.h" #include "../devices/input/keyboard.h" +#include "../devices/input/mouse.h" #include "../devices/video/video.h" #include "ui.h" -#ifdef ENABLE_LOGGING +#ifdef _LOGGING /* Simplest way to handle all these, for now.. */ -void -ui_menu_set_logging_item(int idm, int val) +static void +set_logging_item(int idm, int val) { - char temp[128]; - wchar_t tmpw[128]; + wchar_t temp[128]; + wchar_t tmp2[128]; void *ptr = NULL; int *iptr, i; switch(idm) { -#ifdef ENABLE_BUS_LOG +# ifdef ENABLE_BUS_LOG case IDM_LOG_BUS: ptr = (val != -3) ? &pci_do_log : (void *)"Bus"; break; -#endif +# endif -#ifdef ENABLE_KEYBOARD_LOG +# ifdef ENABLE_KEYBOARD_LOG case IDM_LOG_KEYBOARD: ptr = (val != -3) ? &keyboard_do_log : (void *)"Keyboard"; break; -#endif +# endif -#ifdef ENABLE_MOUSE_LOG +# ifdef ENABLE_MOUSE_LOG case IDM_LOG_MOUSE: ptr = (val != -3) ? &mouse_do_log : (void *)"Mouse"; break; -#endif +# endif -#ifdef ENABLE_GAME_LOG +# ifdef ENABLE_GAME_LOG case IDM_LOG_GAME: ptr = (val != -3) ? &game_do_log : (void *)"Game Port"; break; -#endif +# endif -#ifdef ENABLE_PARALLEL_LOG +# ifdef ENABLE_PARALLEL_LOG case IDM_LOG_PARALLEL: ptr = (val != -3) ? ¶llel_do_log : (void *)"Parallel Port"; break; -#endif +# endif -#ifdef ENABLE_SERIAL_LOG +# ifdef ENABLE_SERIAL_LOG case IDM_LOG_SERIAL: ptr = (val != -3) ? &serial_do_log : (void *)"Serial Port"; break; -#endif +# endif -#ifdef ENABLE_FDC_LOG +# ifdef ENABLE_FDC_LOG case IDM_LOG_FDC: ptr = (val != -3) ? &fdc_do_log : (void *)"FDC"; break; -#endif +# endif -#ifdef ENABLE_FDD_LOG +# ifdef ENABLE_FDD_LOG case IDM_LOG_FDD: ptr = (val != -3) ? &fdd_do_log : (void *)"FDD (image)"; break; -#endif +# endif -#ifdef ENABLE_D86F_LOG +# ifdef ENABLE_D86F_LOG case IDM_LOG_D86F: ptr = (val != -3) ? &d86f_do_log : (void *)"D86F"; break; -#endif +# endif -#ifdef ENABLE_HDC_LOG +# ifdef ENABLE_HDC_LOG case IDM_LOG_HDC: ptr = (val != -3) ? &hdc_do_log : (void *)"HDC"; break; -#endif +# endif -#ifdef ENABLE_HDD_LOG +# ifdef ENABLE_HDD_LOG case IDM_LOG_HDD: ptr = (val != -3) ? &hdd_do_log : (void *)"HDD (image)"; break; -#endif +# endif -#ifdef ENABLE_ZIP_LOG +# ifdef ENABLE_ZIP_LOG case IDM_LOG_ZIP: ptr = (val != -3) ? &zip_do_log : (void *)"ZIP"; break; -#endif +# endif -#ifdef ENABLE_CDROM_LOG +# ifdef ENABLE_CDROM_LOG case IDM_LOG_CDROM: ptr = (val != -3) ? &cdrom_do_log : (void *)"CD-ROM"; break; -#endif +# endif -#ifdef ENABLE_CDROM_IMAGE_LOG +# ifdef ENABLE_CDROM_IMAGE_LOG case IDM_LOG_CDROM_IMAGE: ptr = (val != -3) ? &cdrom_image_do_log : (void *)"CD-ROM (image)"; break; -#endif +# endif -#ifdef USE_CDROM_IOCTL -# ifdef ENABLE_CDROM_IOCTL_LOG +# ifdef USE_CDROM_IOCTL +# ifdef ENABLE_CDROM_IOCTL_LOG case IDM_LOG_CDROM_IOCTL: ptr = (val != -3) ? &cdrom_ioctl_do_log : (void *)"CD-ROM (ioctl)"; break; +# endif # endif -#endif -#ifdef ENABLE_NETWORK_LOG +# ifdef ENABLE_NETWORK_LOG case IDM_LOG_NETWORK: ptr = (val != -3) ? &network_do_log : (void *)"Network"; break; -#endif +# endif -#ifdef ENABLE_NETWORK_DEV_LOG +# ifdef ENABLE_NETWORK_DEV_LOG case IDM_LOG_NETWORK_DEV: ptr = (val != -3) ? &network_dev_do_log : (void *)"Network Device"; break; -#endif +# endif -#ifdef ENABLE_SOUND_EMU8K_LOG - case IDM_LOG_SOUND_EMU8K: - ptr = (val != -3) ? &sound_emu8k_do_log : (void *)"Sound (EMU8K)"; +# ifdef ENABLE_SOUND_LOG + case IDM_LOG_SOUND: + ptr = (val != -3) ? &sound_do_log : (void *)"Sound"; break; -#endif +# endif -#ifdef ENABLE_SOUND_MPU401_LOG - case IDM_LOG_SOUND_MPU401: - ptr = (val != -3) ? &sound_mpu401_do_log : (void *)"Sound (MPU401)"; +# ifdef ENABLE_SOUND_MIDI_LOG + case IDM_LOG_SOUND_MIDI: + ptr = (val != -3) ? &sound_midi_do_log : (void *)"Sound (MIDI)"; break; -#endif +# endif -#ifdef ENABLE_SOUND_DEV_LOG +# ifdef ENABLE_SOUND_DEV_LOG case IDM_LOG_SOUND_DEV: ptr = (val != -3) ? &sound_dev_do_log : (void *)"Sound Device"; break; -#endif +# endif -#ifdef ENABLE_SCSI_BUS_LOG - case IDM_LOG_SCSI_BUS: - ptr = (val != -3) ? &scsi_bus_do_log : (void *)"SCSI (Bus)"; +# ifdef ENABLE_SCSI_LOG + case IDM_LOG_SCSI: + ptr = (val != -3) ? &scsi_do_log : (void *)"SCSI"; break; -#endif +# endif -#ifdef ENABLE_SCSI_DISK_LOG +# ifdef ENABLE_SCSI_DISK_LOG case IDM_LOG_SCSI_DISK: - ptr = (val != -3) ? &scsi_hd_do_log : (void *)"SCSI (Disk)"; + ptr = (val != -3) ? &scsi_disk_do_log : (void *)"SCSI (Disk)"; break; -#endif +# endif -#ifdef ENABLE_SCSI_DEV_LOG +# ifdef ENABLE_SCSI_DEV_LOG case IDM_LOG_SCSI_DEV: ptr = (val != -3) ? &scsi_dev_do_log : (void *)"SCSI Device"; break; -#endif +# endif -#ifdef ENABLE_VOODOO_LOG - case IDM_LOG_VOODOO: - ptr = (val != -3) ? &voodoo_do_log : (void *)"Video (Voodoo)"; +# ifdef ENABLE_VIDEO_LOG + case IDM_LOG_VIDEO: + ptr = (val != -3) ? &video_do_log : (void *)"Video"; break; -#endif +# endif } if (ptr == NULL) return; - iptr = ptr; + iptr = (int *)ptr; switch(val) { case -3: /* create menu item */ /* Add a menu item. */ i = (idm - IDM_LOG_BEGIN); - sprintf(temp, "Toggle %s logging\tCtrl%s+F%d", - (const char *)ptr, - (i >= 12) ? "+Alt" : "", - ((i >= 12) ? i - 12 : i) + 1); - mbstowcs(tmpw, temp, sizeof_w(tmpw)); - menu_add_item(IDM_LOGGING, IDM_LOG_BEGIN + i, tmpw); + swprintf(temp, sizeof_w(temp), + get_string(IDS_4085), (const char *)ptr); + swprintf(tmp2, sizeof_w(tmp2), L"\tCtrl%s+F%i", + (i >= 12) ? "+Alt" : "", ((i >= 12) ? i - 12 : i) + 1); + wcscat(temp, tmp2); + menu_add_item(IDM_LOGGING, ITEM_CHECK, IDM_LOG_BEGIN+i, temp); break; case -2: /* set current value */ @@ -239,13 +243,26 @@ ui_menu_set_logging_item(int idm, int val) break; case -1: /* toggle */ +#if 1 + if (*iptr <= LOG_INFO) + *iptr = LOG_DEBUG; + else + *iptr = LOG_INFO; + menu_set_item(idm, (*iptr >= LOG_DEBUG) ? 1 : 0); +#else *iptr ^= 1; menu_set_item(idm, *iptr); +#endif break; default: /* 0 ... n */ +#if 1 + *iptr = LOG_INFO + val; + menu_set_item(idm, (*iptr > LOG_INFO) ? 1 : 0); +#else *iptr = val; menu_set_item(idm, *iptr); +#endif break; } } @@ -253,8 +270,8 @@ ui_menu_set_logging_item(int idm, int val) /* Toggle one of the Video options, with a lock on the blitter. */ -void -ui_menu_toggle_video_item(int idm, int *val) +static void +toggle_video_item(int idm, int *val) { plat_startblit(); video_wait_for_blit(); @@ -270,8 +287,8 @@ ui_menu_toggle_video_item(int idm, int *val) /* Reset all (main) menu items to their default state. */ -void -ui_menu_reset_all(void) +static void +main_reset_all(void) { wchar_t temp[128]; int i; @@ -284,7 +301,7 @@ ui_menu_reset_all(void) if (vidapi_available(i)) { /* Get name of the renderer and add a menu item. */ mbstowcs(temp, vidapi_internal_name(i), sizeof_w(temp)); - menu_add_item(IDM_RENDER, IDM_RENDER_1 + i, temp); + menu_add_item(IDM_RENDER, ITEM_RADIO, IDM_RENDER_1 + i, temp); } } menu_set_radio_item(IDM_RENDER_1, vidapi_count(), vid_api); @@ -297,8 +314,6 @@ ui_menu_reset_all(void) menu_set_item(IDM_RCTRL_IS_LALT, rctrl_is_lalt); - menu_set_item(IDM_UPDATE_ICONS, update_icons); - menu_set_item(IDM_INVERT, invert_display); menu_set_item(IDM_OVERSCAN, enable_overscan); @@ -310,11 +325,11 @@ ui_menu_reset_all(void) menu_set_item(IDM_CGA_CONTR, vid_cga_contrast); -#ifdef ENABLE_LOGGING +#ifdef _LOGGING for (i = IDM_LOG_BEGIN; i < IDM_LOG_END; i++) { - ui_menu_set_logging_item(i, -3); + set_logging_item(i, -3); - ui_menu_set_logging_item(i, -2); + set_logging_item(i, -2); } #endif @@ -323,6 +338,31 @@ ui_menu_reset_all(void) menu_enable_item(IDM_LOAD, 0); menu_enable_item(IDM_SAVE, 0); #endif + + /* Load the Languages into the current menu. */ + ui_lang_menu(); +} + + +/* Re-load and reset the entire UI. */ +void +ui_reset(void) +{ + int i; + + /* Maybe the underlying (platform) UI has to rebuild. */ + ui_plat_reset(); + + /* Reset all main menu items. */ + main_reset_all(); + + /* Update the statusbar menus. */ + ui_sb_reset(); + + /* Reset the mouse-capture message. */ + i = mouse_capture; + mouse_capture = !mouse_capture; + ui_mouse_capture(i); } @@ -343,21 +383,20 @@ ui_menu_command(int idm) break; case IDM_CAE: /* ACTION menu */ - keyboard_send_cae(); + keyboard_cae(); break; case IDM_CAB: /* ACTION menu */ - keyboard_send_cab(); + keyboard_cab(); break; case IDM_PAUSE: /* ACTION menu */ - plat_pause(dopause ^ 1); - menu_set_item(idm, dopause); + pc_pause(dopause ^ 1); break; #ifdef IDM_Test case IDM_Test: /* ACTION menu */ - pclog("TEST\n"); + pclog(LOG_ALWAYS, "TEST\n"); break; #endif @@ -377,7 +416,9 @@ ui_menu_command(int idm) /* Disable scaling settings. */ for (i = 0; i < 4; i++) menu_enable_item(IDM_SCALE_1+i, !vid_resize); - doresize = 1; + + device_force_redraw(); + video_force_resize_set(1); config_save(); return(0); @@ -399,7 +440,7 @@ ui_menu_command(int idm) break; case IDM_FULLSCREEN: /* VIEW menu */ - plat_setfullscreen(1); + ui_fullscreen(1); config_save(); break; @@ -426,7 +467,7 @@ ui_menu_command(int idm) break; case IDM_FORCE_43: /* VIEW menu */ - ui_menu_toggle_video_item(idm, &force_43); + toggle_video_item(idm, &force_43); video_force_resize_set(1); config_save(); break; @@ -437,19 +478,13 @@ ui_menu_command(int idm) config_save(); break; - case IDM_UPDATE_ICONS: /* VIEW menu */ - update_icons ^= 1; - menu_set_item(idm, update_icons); - config_save(); - break; - case IDM_INVERT: /* DISPLAY menu */ - ui_menu_toggle_video_item(idm, &invert_display); + toggle_video_item(idm, &invert_display); config_save(); break; case IDM_OVERSCAN: /* DISPLAY menu */ - ui_menu_toggle_video_item(idm, &enable_overscan); + toggle_video_item(idm, &enable_overscan); video_force_resize_set(1); config_save(); break; @@ -482,10 +517,10 @@ ui_menu_command(int idm) break; case IDM_SETTINGS: /* TOOLS menu */ - plat_pause(1); + pc_pause(1); if (dlg_settings(1) == 2) pc_reset_hard_init(); - plat_pause(0); + pc_pause(0); break; case IDM_LANGUAGE+1: /* select language */ @@ -508,75 +543,172 @@ ui_menu_command(int idm) case IDM_LANGUAGE+18: case IDM_LANGUAGE+19: case IDM_LANGUAGE+20: - plat_set_language(idm - IDM_LANGUAGE - 1); - ui_update(); + ui_lang_set(idm - (IDM_LANGUAGE + 1)); + ui_reset(); + config_save(); break; -#ifdef ENABLE_LOGGING +#ifdef _LOGGING case IDM_LOG_BREAKPOINT: /* TOOLS menu */ - pclog("---- LOG BREAKPOINT ----\n"); + pclog(LOG_ALWAYS, "---- LOG BREAKPOINT ----\n"); break; - case IDM_LOG_BUS: /* TOOLS menu */ - case IDM_LOG_KEYBOARD: - case IDM_LOG_MOUSE: - case IDM_LOG_GAME: - case IDM_LOG_PARALLEL: - case IDM_LOG_SERIAL: - case IDM_LOG_FDC: - case IDM_LOG_FDD: - case IDM_LOG_D86F: - case IDM_LOG_HDC: - case IDM_LOG_HDD: - case IDM_LOG_ZIP: - case IDM_LOG_CDROM: - case IDM_LOG_CDROM_IMAGE: - case IDM_LOG_CDROM_IOCTL: - case IDM_LOG_NETWORK: - case IDM_LOG_NETWORK_DEV: - case IDM_LOG_SOUND_EMU8K: - case IDM_LOG_SOUND_MPU401: - case IDM_LOG_SOUND_DEV: - case IDM_LOG_SCSI_BUS: - case IDM_LOG_SCSI_DISK: - case IDM_LOG_SCSI_DEV: - case IDM_LOG_VOODOO: - ui_menu_set_logging_item(idm, -1); + case IDM_LOG_BEGIN: /* TOOLS menu */ + case IDM_LOG_BEGIN+1: + case IDM_LOG_BEGIN+2: + case IDM_LOG_BEGIN+3: + case IDM_LOG_BEGIN+4: + case IDM_LOG_BEGIN+5: + case IDM_LOG_BEGIN+6: + case IDM_LOG_BEGIN+7: + case IDM_LOG_BEGIN+8: + case IDM_LOG_BEGIN+9: + case IDM_LOG_BEGIN+10: + case IDM_LOG_BEGIN+11: + case IDM_LOG_BEGIN+12: + case IDM_LOG_BEGIN+13: + case IDM_LOG_BEGIN+14: + case IDM_LOG_BEGIN+15: + case IDM_LOG_BEGIN+16: + case IDM_LOG_BEGIN+17: + case IDM_LOG_BEGIN+18: + case IDM_LOG_BEGIN+19: + case IDM_LOG_BEGIN+20: + case IDM_LOG_BEGIN+21: + case IDM_LOG_BEGIN+22: + case IDM_LOG_BEGIN+23: + case IDM_LOG_BEGIN+24: + case IDM_LOG_BEGIN+25: + case IDM_LOG_BEGIN+26: + case IDM_LOG_BEGIN+27: + case IDM_LOG_BEGIN+28: + case IDM_LOG_BEGIN+29: + set_logging_item(idm, -1); break; #endif /* FIXME: need to fix these.. */ case IDM_LOAD: /* TOOLS menu */ - plat_pause(1); + pc_pause(1); i = dlg_file(get_string(IDS_2500), NULL, temp, DLG_FILE_LOAD); if (i && (ui_msgbox(MBX_QUESTION, (wchar_t *)IDS_WARNING) == 0)) { pc_reload(temp); - ui_menu_reset_all(); + ui_reset(); config_ro = !!(i & DLG_FILE_RO); } - plat_pause(0); + pc_pause(0); break; case IDM_SAVE: /* TOOLS menu */ - plat_pause(1); + pc_pause(1); if (dlg_file(get_string(IDS_2500), NULL, temp, DLG_FILE_SAVE)) { config_write(temp); } - plat_pause(0); + pc_pause(0); break; - case IDM_STATUS: /* TOOLS menu */ - dlg_status(); - break; - case IDM_SCREENSHOT: /* TOOLS menu */ vidapi_screenshot(); break; case IDM_ABOUT: /* HELP menu */ + pc_pause(1); dlg_about(); + pc_pause(0); + break; + + case IDM_LOCALIZE: /* HELP MENU */ + pc_pause(1); + dlg_localize(); + pc_pause(0); break; } return(1); } + + +/* Set the desired fullscreen/windowed mode. */ +void +ui_fullscreen(int on) +{ + /* Want off and already off? */ + if (!on && !vid_fullscreen) return; + + /* Want on and already on? */ + if (on && vid_fullscreen) return; + + if (on && vid_fullscreen_first) { + vid_fullscreen_first = 0; + ui_msgbox(MBX_INFO, (wchar_t *)IDS_MSG_WINDOW); + } + + /* OK, claim the video. */ + plat_startblit(); + video_wait_for_blit(); + +// plat_mouse_close(); + + /* Close the current mode, and open the new one. */ + plat_vidapis[vid_api]->close(); + vid_fullscreen = on; + plat_vidapis[vid_api]->init(vid_fullscreen); + + plat_fullscreen(on); + +// plat_mouse_init(); + + /* Release video and make it redraw the screen. */ + plat_endblit(); + device_force_redraw(); + + /* Finally, handle the host's mouse cursor. */ + ui_show_cursor(vid_fullscreen ? 0 : -1); + + /* Update the menu item. */ + menu_set_item(IDM_FULLSCREEN, on); +} + + +/* Enable or disable mouse clipping. */ +void +ui_mouse_capture(int on) +{ + const wchar_t *str = NULL; + + /* Do not try to capture the mouse if no mouse configured. */ + if (mouse_type == MOUSE_NONE) return; + + if ((on == 1) && !mouse_capture) { + /* Disable the local cursor. */ + ui_show_cursor(0); + + if (mouse_get_buttons() > 2) + str = get_string(IDS_MSG_MRLS_1); + else + str = get_string(IDS_MSG_MRLS_2); + + /* Enable and clip the in-app mouse. */ + plat_mouse_capture(1); + + /* We got the mouse. */ + mouse_capture = 1; + } else if ((on == -1) || (!on && mouse_capture)) { + /* Unclip the in-app mouse. */ + if (! on) { + plat_mouse_capture(0); + + /* Restore the local cursor. */ + ui_show_cursor(1); + } + + str = get_string(IDS_MSG_CAPTURE); + + /* We (no longer) have the mouse. */ + mouse_capture = 0; + } + + /* Set the correct message on the status bar. */ + if (str != NULL) + ui_sb_text_set_w(SB_TEXT, str); +} diff --git a/src/ui/ui_misc.c b/src/ui/ui_misc.c new file mode 100644 index 0000000..32c3396 --- /dev/null +++ b/src/ui/ui_misc.c @@ -0,0 +1,91 @@ +/* + * VARCem Virtual ARchaeological Computer EMulator. + * An emulator of (mostly) x86-based PC systems and devices, + * using the ISA,EISA,VLB,MCA and PCI system buses, roughly + * spanning the era between 1981 and 1995. + * + * This file is part of the VARCem Project. + * + * Misc stuff for UI, doesn't fit anywhere else.. + * + * Version: @(#)ui_misc.c 1.0.1 2018/09/29 + * + * Author: Fred N. van Kempen, + * + * Copyright 2018 Fred N. van Kempen. + * + * Redistribution and use in source and binary forms, with + * or without modification, are permitted provided that the + * following conditions are met: + * + * 1. Redistributions of source code must retain the entire + * above notice, this list of conditions and the following + * disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the + * following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names + * of its contributors may be used to endorse or promote + * products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include +#include +#include +#include +#include +#include "../emu.h" +#include "../plat.h" +#include "ui.h" + + +/* Return icon number based on drive type. */ +int +ui_fdd_icon(int type) +{ + int ret = ICON_FLOPPY_D; + + switch(type) { + case 0: + break; + + case 1: + case 2: + case 3: + case 4: + case 5: + case 6: + ret = ICON_FLOPPY_525; + break; + + case 7: + case 8: + case 9: + case 10: + case 11: + case 12: + case 13: + ret = ICON_FLOPPY_35; + break; + + default: + break; + } + + return(ret); +} diff --git a/src/ui/ui_new_image.c b/src/ui/ui_new_image.c index 34e5104..8aa7738 100644 --- a/src/ui/ui_new_image.c +++ b/src/ui/ui_new_image.c @@ -12,7 +12,7 @@ * format handlers, and re-integrated with that code. This is * just the wrong place for it.. * - * Version: @(#)ui_new_image.c 1.0.3 2018/05/13 + * Version: @(#)ui_new_image.c 1.0.4 2018/10/05 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -47,6 +47,7 @@ #include "../random.h" #include "../ui/ui.h" #include "../plat.h" +#include "../devices/scsi/scsi_device.h" #include "../devices/disk/zip.h" @@ -162,7 +163,7 @@ floppy_create_86f(const wchar_t *fn, int8_t ds, int8_t rpm_mode) if (f == NULL) return 0; - empty = (uint8_t *)malloc(array_size); + empty = (uint8_t *)mem_alloc(array_size); memset(tarray, 0x00, 2048); memset(empty, 0x00, array_size); @@ -231,7 +232,7 @@ floppy_create_image(const wchar_t *fn, int8_t ds, int8_t is_fdi) zero_bytes = fat2_offs + fat_size + root_dir_bytes; if (is_fdi) { - empty = (uint8_t *)malloc(base); + empty = (uint8_t *)mem_alloc(base); memset(empty, 0x00, base); *(uint32_t *) &(empty[0x08]) = (uint32_t)base; @@ -246,7 +247,7 @@ floppy_create_image(const wchar_t *fn, int8_t ds, int8_t is_fdi) free(empty); } - empty = (uint8_t *)malloc(total_size); + empty = (uint8_t *)mem_alloc(total_size); memset(empty, 0x00, zero_bytes); memset(empty + zero_bytes, 0xF6, total_size - zero_bytes); @@ -372,7 +373,7 @@ zip_create_image(const wchar_t *fn, int8_t ds, int8_t is_zdi) pbar_max++; if (is_zdi) { - empty = (uint8_t *)malloc(base); + empty = (uint8_t *)mem_alloc(base); memset(empty, 0x00, base); *(uint32_t *) &(empty[0x08]) = (uint32_t) base; @@ -397,7 +398,7 @@ zip_create_image(const wchar_t *fn, int8_t ds, int8_t is_zdi) pbar_max -= 2; } - empty = (uint8_t *)malloc(total_size); + empty = (uint8_t *)mem_alloc(total_size); memset(empty, 0x00, zero_bytes); if (total_sectors == ZIP_SECTORS) { diff --git a/src/ui/ui_resource.h b/src/ui/ui_resource.h index 15b26d2..9d5f35f 100644 --- a/src/ui/ui_resource.h +++ b/src/ui/ui_resource.h @@ -8,15 +8,13 @@ * * Platform-independent resource identifiers. * - * NOTE: Many entries in the strings table do not have an IDS, as - * they are not referenced outside of the platform UI. This - * may change at some point. + * NOTE: All entries in the strings table now have an IDS, even if + * those are not used by the platform code. This is easier to + * maintain. * - * Version: @(#)ui_resource.h 1.0.17 2018/09/23 + * Version: @(#)ui_resource.h 1.0.16 2018/10/01 * - * Authors: Fred N. van Kempen, - * Miran Grca, - * Sarah Walker, + * Author: Fred N. van Kempen, * * Copyright 2018 Fred N. van Kempen. * @@ -96,8 +94,7 @@ # define IDM_STRETCH_INT (IDM_FULLSCREEN+5) # define IDM_STRETCH_KEEP (IDM_FULLSCREEN+6) #define IDM_RCTRL_IS_LALT (IDM_VIEW+5) -#define IDM_UPDATE_ICONS (IDM_VIEW+6) -#define IDM_VIEW_END (IDM_UPDATE_ICONS+1) +#define IDM_VIEW_END (IDM_RCTRL_IS_LALT+1) /* DISPLAY menu. */ #define IDM_DISPLAY (IDM_BASE+200) @@ -121,11 +118,9 @@ #define IDM_TOOLS (IDM_BASE+300) #define IDM_SETTINGS (IDM_TOOLS+1) #define IDM_LANGUAGE (IDM_TOOLS+10) -#define IDM_LOAD (IDM_TOOLS+2) -#define IDM_SAVE (IDM_TOOLS+3) -#define IDM_LOGGING (IDM_TOOLS+50) -# define IDM_LOG_BREAKPOINT (IDM_LOGGING+49) -# define IDM_LOG_BEGIN (IDM_LOGGING+1) +#define IDM_LOGGING (IDM_TOOLS+40) +# define IDM_LOG_BREAKPOINT (IDM_LOGGING+1) +# define IDM_LOG_BEGIN (IDM_LOGGING+2) # define IDM_LOG_BUS (IDM_LOG_BEGIN+0) # define IDM_LOG_KEYBOARD (IDM_LOG_BEGIN+1) # define IDM_LOG_MOUSE (IDM_LOG_BEGIN+2) @@ -143,21 +138,23 @@ # define IDM_LOG_CDROM_IOCTL (IDM_LOG_BEGIN+14) # define IDM_LOG_NETWORK (IDM_LOG_BEGIN+15) # define IDM_LOG_NETWORK_DEV (IDM_LOG_BEGIN+16) -# define IDM_LOG_SOUND_EMU8K (IDM_LOG_BEGIN+17) -# define IDM_LOG_SOUND_MPU401 (IDM_LOG_BEGIN+18) +# define IDM_LOG_SOUND (IDM_LOG_BEGIN+17) +# define IDM_LOG_SOUND_MIDI (IDM_LOG_BEGIN+18) # define IDM_LOG_SOUND_DEV (IDM_LOG_BEGIN+19) -# define IDM_LOG_SCSI_BUS (IDM_LOG_BEGIN+20) +# define IDM_LOG_SCSI (IDM_LOG_BEGIN+20) # define IDM_LOG_SCSI_DISK (IDM_LOG_BEGIN+21) # define IDM_LOG_SCSI_DEV (IDM_LOG_BEGIN+22) -# define IDM_LOG_VOODOO (IDM_LOG_BEGIN+23) +# define IDM_LOG_VIDEO (IDM_LOG_BEGIN+23) # define IDM_LOG_END (IDM_LOG_BEGIN+24) -#define IDM_STATUS (IDM_TOOLS+4) -#define IDM_SCREENSHOT (IDM_TOOLS+5) -#define IDM_TOOLS_END (IDM_LOG_BREAKPOINT+1) +#define IDM_LOAD (IDM_TOOLS+90) +#define IDM_SAVE (IDM_TOOLS+91) +#define IDM_SCREENSHOT (IDM_TOOLS+92) +#define IDM_TOOLS_END (IDM_SCREENSHOT+1) /* HELP menu. */ #define IDM_HELP (IDM_BASE+400) #define IDM_ABOUT (IDM_HELP+1) /* fixed on WxWidgets */ +#define IDM_LOCALIZE (IDM_HELP+2) #define IDM_END (IDM_HELP+99) @@ -165,226 +162,422 @@ * Status Bar commands. * * We need 7 bits for CDROM (2 bits ID and 5 bits for host drive), - * and 5 bits for Removable Disks (5 bits for ID), so we use an - * 8bit (256 entries) space for these devices. + * and 5 bits for Hard Disks (5 bits for ID), so we use an 8bit + * (256 entries) space for these devices. */ -#define IDM_SBAR (IDM_BASE+1024) +#define IDM_SBAR (IDM_BASE+1024) -#define IDM_FLOPPY_IMAGE_NEW (IDM_SBAR + 0x0000) -#define IDM_FLOPPY_IMAGE_EXISTING (IDM_SBAR + 0x0100) -#define IDM_FLOPPY_EXPORT_TO_86F (IDM_SBAR + 0x0200) -#define IDM_FLOPPY_EJECT (IDM_SBAR + 0x0300) +#define IDM_FLOPPY_IMAGE_NEW (IDM_SBAR + 0x0000) +#define IDM_FLOPPY_IMAGE_EXISTING (IDM_SBAR + 0x0100) +#define IDM_FLOPPY_EXPORT (IDM_SBAR + 0x0200) +#define IDM_FLOPPY_EJECT (IDM_SBAR + 0x0300) -#define IDM_CDROM_MUTE (IDM_SBAR + 0x0800) -#define IDM_CDROM_EMPTY (IDM_SBAR + 0x0900) -#define IDM_CDROM_RELOAD (IDM_SBAR + 0x0a00) -#define IDM_CDROM_IMAGE (IDM_SBAR + 0x0b00) -#define IDM_CDROM_HOST_DRIVE (IDM_SBAR + 0x0c00) +#define IDM_CDROM_MUTE (IDM_SBAR + 0x0800) +#define IDM_CDROM_EMPTY (IDM_SBAR + 0x0900) +#define IDM_CDROM_RELOAD (IDM_SBAR + 0x0a00) +#define IDM_CDROM_IMAGE (IDM_SBAR + 0x0b00) +#define IDM_CDROM_HOST_DRIVE (IDM_SBAR + 0x0c00) -#define IDM_ZIP_IMAGE_NEW (IDM_SBAR + 0x1000) -#define IDM_ZIP_IMAGE_EXISTING (IDM_SBAR + 0x1100) -#define IDM_ZIP_EJECT (IDM_SBAR + 0x1200) -#define IDM_ZIP_RELOAD (IDM_SBAR + 0x1300) +#define IDM_ZIP_IMAGE_NEW (IDM_SBAR + 0x1000) +#define IDM_ZIP_IMAGE_EXISTING (IDM_SBAR + 0x1100) +#define IDM_ZIP_EJECT (IDM_SBAR + 0x1200) +#define IDM_ZIP_RELOAD (IDM_SBAR + 0x1300) -#define IDM_RDISK_EJECT (IDM_SBAR + 0x1800) -#define IDM_RDISK_RELOAD (IDM_SBAR + 0x1900) -#define IDM_RDISK_SEND_CHANGE (IDM_SBAR + 0x1a00) -#define IDM_RDISK_IMAGE (IDM_SBAR + 0x1b00) +#define IDM_DISK_IMAGE_NEW (IDM_SBAR + 0x1800) +#define IDM_DISK_IMAGE_EXISTING (IDM_SBAR + 0x1900) +#define IDM_DISK_EJECT (IDM_SBAR + 0x1a00) +#define IDM_DISK_RELOAD (IDM_SBAR + 0x1b00) +#define IDM_DISK_NOTIFY (IDM_SBAR + 0x1c00) -#define IDM_SOUND (IDM_SBAR + 8192) +#define IDM_SOUND (IDM_SBAR + 8192) + + +/* Main icons. */ +#define ICON_MAIN 10 /* "varcem.ico" */ +#define ICON_DONATE 11 /* "paypal-donate.ico" */ + +/* Icons for status bar. */ +#define ICON_ACTIVE 1 /* add to base icon ID */ +#define ICON_EMPTY 128 /* add to base icon ID */ +#define ICON_MKREG(x) (x) +#define ICON_MKEMPTY(x) (ICON_EMPTY + x) +#define ICON_MKACTIVE(x) (ICON_ACTIVE + x) +#define ICON_MKIDLE(x) (ICON_MKEMPTY(x) + 1) + +#define ICON_FLOPPY_525 16 /* "floppy_525.ico" */ +#define ICON_FLOPPY_525_A 17 /* "floppy_525_active.ico" */ +#define ICON_FLOPPY_525_E 144 /* "floppy_525_empty.ico" */ +#define ICON_FLOPPY_525_I 145 /* "floppy_525_empty_active.ico" */ +#define ICON_FLOPPY_35 24 /* "floppy_35.ico" */ +#define ICON_FLOPPY_35_A 25 /* "floppy_35_active.ico" */ +#define ICON_FLOPPY_35_E 152 /* "floppy_35_empty.ico" */ +#define ICON_FLOPPY_35_I 153 /* "floppy_35_empty_active.ico" */ +#define ICON_CDROM 32 /* "cdrom.ico" */ +#define ICON_CDROM_A 33 /* "cdrom_active.ico" */ +#define ICON_CDROM_E 160 /* "cdrom_empty.ico" */ +#define ICON_CDROM_I 161 /* "cdrom_empty_active.ico" */ +#define ICON_ZIP 48 /* "zip.ico" */ +#define ICON_ZIP_A 49 /* "zip_active.ico" */ +#define ICON_ZIP_E 176 /* "zip_empty.ico" */ +#define ICON_ZIP_I 177 /* "zip_empty_active.ico" */ +#define ICON_DISK 64 /* "hard_disk.ico" */ +#define ICON_DISK_A 65 /* "hard_disk_active.ico" */ +#define ICON_NETWORK 80 /* "network.ico" */ +#define ICON_NETWORK_A 81 /* "network_active.ico" */ + +/* Icons for Settings UI. */ +#define ICON_MACHINE 240 /* "machine.ico" */ +#define ICON_DISPLAY 241 /* "display.ico" */ +#define ICON_INPDEV 242 /* "input_devices.ico" */ +#define ICON_SOUND 243 /* "sound.ico" */ +#define ICON_PORTS 244 /* "ports.ico" */ +#define ICON_PERIPH 245 /* "other_peripherals.ico" */ +#define ICON_FLOPPY 246 /* "floppy_drives.ico" */ +#define ICON_REMOV 247 /* "other_removable_devices.ico" */ +#define ICON_FLOPPY_D 248 /* "floppy_disabled.ico" */ +#define ICON_CDROM_D 249 /* "cdrom_disabled.ico" */ +#define ICON_ZIP_D 250 /* "zip_disabled.ico" */ /* String IDs. */ -#define IDS_BEGIN 2000 // start of accesible string IDs +#define IDS_BEGIN 2000 /* start of accessible string IDs */ -/* Unused block (2000.) */ +/* Application main strings (2000.) */ +#define IDS_VERSION 2000 /* "1.0.1" */ +#define IDS_AUTHOR 2001 /* "Your Name" */ +#define IDS_EMAIL 2002 /* "your@email.address" */ +#define IDS_NAME 2003 /* "VARCem" */ +#define IDS_TITLE 2004 /* "Virtual ARchaeological.." */ /* Messagebox classes (2100.) */ -#define IDS_ERROR 2100 // "Error" -#define IDS_FATAL_ERROR 2101 // "Fatal Error" -#define IDS_CONFIG_ERROR 2102 // "Configuration Error" -#define IDS_WARNING 2103 // "Warning" +#define IDS_ERROR 2100 /* "Error" */ +#define IDS_ERROR_FATAL 2101 /* "Fatal Error" */ +#define IDS_ERROR_CONF 2102 /* "Configuration Error" */ +#define IDS_WARNING 2103 /* "Warning" */ /* System errors (2200.) */ -#define IDS_ERR_ACCEL 2200 // "Unable to load Accelerators" -#define IDS_ERR_INPUT 2201 // "Unable to register Raw Input" -#define IDS_ERR_PCAP 2202 // "PCap failed to set up.." -#define IDS_ERR_PCAP_NO 2203 // "No PCap devices found" -#define IDS_ERR_PCAP_DEV 2204 // "Invalid PCap device" -#define IDS_ERR_OPENAL 2205 // "Unable to initialize OpenAL.." -#define IDS_ERR_FSYNTH 2206 // "Unable to initialize Flui.." -#define IDS_ERR_NOMEM 2207 // "System out of memory" +#define IDS_ERR_ACCEL 2200 /* "Unable to load Accelerators" */ +#define IDS_ERR_INPUT 2201 /* "Unable to register Raw Input" */ +#define IDS_ERR_PCAP 2202 /* "PCap failed to set up.." */ +#define IDS_ERR_PCAP_NO 2203 /* "No PCap devices found" */ +#define IDS_ERR_PCAP_DEV 2204 /* "Invalid PCap device" */ +#define IDS_ERR_NOLIB 2205 /* "Unable to initialize %s.." */ /* Application error messages (2300.) */ -#define IDS_ERR_SCRSHOT 2300 // "Unable to create bitmap file: %s" -#define IDS_ERR_NOROMS 2301 // "No usable ROM images found!" -#define IDS_ERR_NOCONF 2302 // "No valid configuration.." -#define IDS_ERR_NOMACH 2303 // "Configured machine not avai.." -#define IDS_ERR_NOVIDEO 2304 // "Configured video card not.." -#define IDS_ERR_NORENDR 2305 // "Selected renderer not avai.." -#define IDS_ERR_NOCDROM 2306 // "ST506/ESDI CDROM drives.." -#define IDS_ERR_NO_USB 2307 // "USB is not yet supported" -#define IDS_ERR_SAVEIT 2308 // "Must save new config first.." +#define IDS_ERR_NOMEM 2300 /* "System is out of memory!" */ +#define IDS_ERR_NOROMS 2301 /* "No usable ROM images found!" */ +#define IDS_ERR_NOCONF 2302 /* "No valid configuration.." */ +#define IDS_ERR_NOAVAIL 2303 /* "Configured %s not avai.." */ +#define IDS_ERR_NORENDR 2304 /* "Selected renderer not avai.." */ +#define IDS_ERR_SAVEIT 2305 /* "Must save settings first.." */ +#define IDS_ERR_SCRSHOT 2306 /* "Unable to create bitmap file" */ +#define IDS_ERR_NO_USB 2307 /* "USB is not yet supported" */ /* Application messages (2400.) */ -#define IDS_MSG_SAVE 2400 // "Are you sure you want to save.." -#define IDS_MSG_RESTART 2401 // "Changes saved, please restart.." -#define IDS_MSG_UNSTABL 2402 // "The requested device '%ls'.." -#define IDS_MSG_CAPTURE 2403 // "Click to capture mouse" -#define IDS_MSG_MRLS_1 2404 // "Press F12-F8 to release mouse" -#define IDS_MSG_MRLS_2 2405 // "Press F12-F8 or middle button.." -#define IDS_MSG_WINDOW 2406 // "Use CTRL+ALT+PAGE DOWN.." +#define IDS_MSG_SAVE 2400 /* "Are you sure you want to save.." */ +#define IDS_MSG_RESTART 2401 /* "Changes saved, please restart.." */ +#define IDS_MSG_UNSTABL 2402 /* "The requested device '%ls'.." */ +#define IDS_MSG_CAPTURE 2403 /* "Click to capture mouse" */ +#define IDS_MSG_MRLS_1 2404 /* "Press F12-F8 to release mouse" */ +#define IDS_MSG_MRLS_2 2405 /* "Press F12-F8 or middle button.." */ +#define IDS_MSG_WINDOW 2406 /* "Use CTRL+ALT+PAGE DOWN.." */ /* Misc application strings (2500.) */ -#define IDS_2500 2500 // "Configuration files (*.CF.." +#define IDS_2500 2500 /* "Configuration files (*.varc.." */ /* UI: common elements (3000.) */ -#define IDS_OK 3000 // "OK" -#define IDS_CANCEL 3001 // "Cancel" -#define IDS_CONFIGURE 3002 // "Configure" -#define IDS_BROWSE 3003 // "Browse" +#define IDS_OK 3000 /* "OK" */ +#define IDS_CANCEL 3001 /* "Cancel" */ +#define IDS_YES 3002 /* "Yes" */ +#define IDS_NO 3003 /* "No" */ +#define IDS_CONFIGURE 3004 /* "Configure" */ +#define IDS_BROWSE 3005 /* "Browse" */ /* UI: dialog shared strings (3100.) */ -#define IDS_NONE 3100 // "None" -#define IDS_DISABLED 3101 // "Disabled" -#define IDS_ENABLED 3102 // "Enabled" -#define IDS_OFF 3103 // "Off" -#define IDS_ON 3104 // "On" -#define IDS_TYPE 3105 // "Type" -#define IDS_FILENAME 3106 // "File name:" -#define IDS_PROGRESS 3107 // "Progress:" -#define IDS_BUS 3108 // "Bus:" -#define IDS_CHANNEL 3109 // "Channel:" -#define IDS_ID 3110 // "ID:" -#define IDS_LUN 3111 // "LUN:" -#define IDS_INV_NAME 3112 // "Please enter a valid file name" -#define IDS_IMG_EXIST 3113 // "This image exists and will be.." -#define IDS_OPEN_READ 3114 // "Unable to open the file for read" -#define IDS_OPEN_WRITE 3115 // "Unable to open the file for write" -#define IDS_DEVCONF_1 3116 // "Configuration" -#define IDS_DEVCONF_2 3117 // "Device:" +#define IDS_NONE 3100 /* "None" */ +#define IDS_INTERNAL 3101 /* "Internal" */ +#define IDS_DISABLED 3102 /* "Disabled" */ +#define IDS_ENABLED 3103 /* "Enabled" */ +#define IDS_OFF 3104 /* "Off" */ +#define IDS_ON 3105 /* "On" */ +#define IDS_TYPE 3106 /* "Type" */ +#define IDS_FILENAME 3107 /* "File name:" */ +#define IDS_PROGRESS 3108 /* "Progress:" */ +#define IDS_BUS 3109 /* "Bus:" */ +#define IDS_CHANNEL 3110 /* "Channel:" */ +#define IDS_ID 3111 /* "ID:" */ +#define IDS_LUN 3112 /* "LUN:" */ +#define IDS_INV_NAME 3113 /* "Please enter a valid file name" */ +#define IDS_IMG_EXIST 3114 /* "This image exists and will be.." */ +#define IDS_OPEN_READ 3115 /* "Unable to open for read" */ +#define IDS_OPEN_WRITE 3116 /* "Unable to open for write" */ +#define IDS_DEVCONF_1 3117 /* "Configuration" */ +#define IDS_DEVCONF_2 3118 /* "Device:" */ /* UI: dialog: About (3200.) */ +#define IDS_ABOUT 3200 /* "About VARCem.." */ +#define IDS_3201 3201 /* "Authors:" */ +#define IDS_3202 3202 /* "Fred.., Miran.., .." */ +#define IDS_3203 3203 /* "Released under.." */ +#define IDS_3204 3204 /* "See LICENSE.txt.." */ +#define IDS_LOCALIZE 3210 /* "Localization" */ +#define IDS_3211 3211 /* "Translations provided by.." */ /* UI dialog: Status (3225.) */ +/* not used anymore */ /* UI dialog: Sound Gain (3250.) */ +#define IDS_SNDGAIN 3250 /* "Sound Gain" */ +#define IDS_3251 3251 /* "Gain" */ /* UI dialog: New Image (3275.) */ -#define IDS_3278 3278 // "Perfect RPM" -#define IDS_3279 3279 // "1% below perfect RPM" -#define IDS_3280 3280 // "1.5% below perfect RPM" -#define IDS_3281 3281 // "2% below perfect RPM" -#define IDS_3282 3282 // "160 KB" -#define IDS_3283 3283 // "180 KB" -#define IDS_3284 3284 // "320 KB" -#define IDS_3285 3285 // "360 KB" -#define IDS_3286 3286 // "640 KB" -#define IDS_3287 3287 // "720 KB" -#define IDS_3288 3288 // "1.2 MB" -#define IDS_3289 3289 // "1.25 MB" -#define IDS_3290 3290 // "1.44 MB" -#define IDS_3291 3291 // "DMF (cluster 1024)" -#define IDS_3292 3292 // "DMF (cluster 2048)" -#define IDS_3293 3293 // "2.88 MB" -#define IDS_3294 3294 // "ZIP 100" -#define IDS_3295 3295 // "ZIP 250" +#define IDS_NEWIMG 3275 /* "New Floppy Image" */ +#define IDS_3276 3276 /* "Disk size:" */ +#define IDS_3277 3277 /* "RPM mode:" */ +#define IDS_3278 3278 /* "Perfect RPM" */ +#define IDS_3279 3279 /* "1% below perfect RPM" */ +#define IDS_3280 3280 /* "1.5% below perfect RPM" */ +#define IDS_3281 3281 /* "2% below perfect RPM" */ +#define IDS_3282 3282 /* "160 KB" */ +#define IDS_3283 3283 /* "180 KB" */ +#define IDS_3284 3284 /* "320 KB" */ +#define IDS_3285 3285 /* "360 KB" */ +#define IDS_3286 3286 /* "640 KB" */ +#define IDS_3287 3287 /* "720 KB" */ +#define IDS_3288 3288 /* "1.2 MB" */ +#define IDS_3289 3289 /* "1.25 MB" */ +#define IDS_3290 3290 /* "1.44 MB" */ +#define IDS_3291 3291 /* "DMF (cluster 1024)" */ +#define IDS_3292 3292 /* "DMF (cluster 2048)" */ +#define IDS_3293 3293 /* "2.88 MB" */ +#define IDS_3294 3294 /* "ZIP 100" */ +#define IDS_3295 3295 /* "ZIP 250" */ /* UI dialog: Settings (3300.) */ -#define IDS_3310 3310 // "Machine" -#define IDS_3311 3311 // "Display" -#define IDS_3312 3312 // "Input devices" -#define IDS_3313 3313 // "Sound" -#define IDS_3314 3314 // "Network" -#define IDS_3315 3315 // "Ports (COM & LPT)" -#define IDS_3316 3316 // "Other peripherals" -#define IDS_3317 3317 // "Hard disks" -#define IDS_3318 3318 // "Floppy drives" -#define IDS_3319 3319 // "Other removable devices" +#define IDS_SETTINGS 3300 /* "Settings"*/ +#define IDS_3310 3310 /* "Machine" */ +#define IDS_3311 3311 /* "Display" */ +#define IDS_3312 3312 /* "Input devices" */ +#define IDS_3313 3313 /* "Sound" */ +#define IDS_3314 3314 /* "Network" */ +#define IDS_3315 3315 /* "Ports (COM & LPT)" */ +#define IDS_3316 3316 /* "Other peripherals" */ +#define IDS_3317 3317 /* "Hard disks" */ +#define IDS_3318 3318 /* "Floppy drives" */ +#define IDS_3319 3319 /* "Other removable devices" */ /* UI dialog: Settings (Machine, 3325.) */ -#define IDS_3330 3330 // "MB" -#define IDS_3334 3334 // "KB" -#define IDS_3335 3335 // "Default" +#define IDS_3325 3325 /* "Machine:" */ +#define IDS_3326 3326 /* "CPU type:" */ +#define IDS_3327 3327 /* "CPU:" */ +#define IDS_3328 3328 /* "Wait states:" */ +#define IDS_3329 3329 /* "Memory:" */ +#define IDS_3330 3330 /* "MB" */ +#define IDS_3331 3331 /* "Time sync:" */ +#define IDS_3332 3332 /* "Enable FPU" */ +#define IDS_3333 3333 /* "Dynamic Recompiler" */ +#define IDS_3334 3334 /* "KB" */ +#define IDS_3335 3335 /* "Default" */ +#define IDS_3336 3336 /* "Enabled (UTC)" */ /* UI dialog: Settings (Video, 3350.) */ -#define IDS_3353 3353 // "Default" -#define IDS_3354 3354 // "8-bit" -#define IDS_3355 3355 // "Slow 16-bit" -#define IDS_3356 3356 // "Fast 16-bit" -#define IDS_3357 3357 // "Slow VLB/PCI" -#define IDS_3358 3358 // "Mid VLB/PCI" -#define IDS_3359 3359 // "Fast VLB/PCI" +#define IDS_3350 3350 /* "Video:" */ +#define IDS_3351 3351 /* "Voodoo Graphics" */ -/* UI dialog: Settings (Other Peripherals, 3475.) */ +/* UI dialog: Settings (Other Peripherals, 3375.) */ +#define IDS_3375 3375 /* "Mouse:" */ +#define IDS_3376 3376 /* "Joystick:" */ +#define IDS_3377 3377 /* "Joystick 1" */ +#define IDS_3378 3378 /* "Joystick 2" */ +#define IDS_3379 3379 /* "Joystick 3" */ +#define IDS_3380 3380 /* "Joystick 4" */ +/* UI dialogs: Settings (Sound, 3400.) */ +#define IDS_3400 3400 /* "Sound card:" */ +#define IDS_3401 3401 /* "MIDI Out Device:" */ +#define IDS_3402 3402 /* "Standalone MPU-401" */ +#define IDS_3403 3403 /* "Use Nuked OPL" */ +#define IDS_3404 3404 /* "Use FLOAT32 sound" */ + +/* UI dialog: Settings (Network, 3425.) */ +#define IDS_3425 3425 /* "Network type:" */ +#define IDS_3426 3426 /* "PCap device:" */ +#define IDS_3427 3427 /* "Network adapter:" */ + +/* UI dialog: Settings (Ports, 3450.) */ +#define IDS_3450 3450 /* "Game port" */ +#define IDS_3451 3451 /* "Parallel port 1" */ +#define IDS_3452 3452 /* "Parallel port 2" */ +#define IDS_3453 3453 /* "Parallel port 3" */ +#define IDS_3454 3454 /* "Serial port 1" */ +#define IDS_3455 3455 /* "Serial port 2" */ + +/* UI dialog: Settings (Other Devices, 3475.) */ +#define IDS_3475 3475 /* "SCSI Controller:" */ +#define IDS_3476 3476 /* "HD Controller:" */ +#define IDS_3477 3477 /* "Tertiary IDE" */ +#define IDS_3478 3478 /* "Quaternary IDE" */ +#define IDS_3479 3479 /* "ISABugger Card" */ +#define IDS_3480 3480 /* "ISA Memory Expansion Card" */ +#define IDS_3481 3481 /* "ISA Clock/RTC Card" */ + /* UI dialog: Settings (Hard Disks, 3500.) */ -#define IDS_3504 3504 // "Bus" -#define IDS_3505 3505 // "File" -#define IDS_3506 3506 // "C" -#define IDS_3507 3507 // "H" -#define IDS_3508 3508 // "S" -#define IDS_3509 3509 // "MB" -#define IDS_3510 3510 // "MB (CHS: %".." -#define IDS_3511 3511 // "Custom..." -#define IDS_3512 3512 // "Custom (large)..." -#define IDS_3515 3515 // "ST506" -#define IDS_3516 3516 // "ESDI" -#define IDS_3517 3517 // "IDE (PIO-only)" -#define IDS_3518 3518 // "IDE (PIO+DMA)" -#define IDS_3519 3519 // "SCSI" -#define IDS_3520 3520 // "SCSI (removable)" -#define IDS_3526 3526 // "Add New Hard Disk" -#define IDS_3527 3527 // "Add Existing Hard Disk" -#define IDS_3533 3533 // "Attempting to create a HDI ima.." -#define IDS_3534 3534 // "Attempting to create a spurio.." -#define IDS_3535 3535 // "HDI or HDX image with a sect.." -#define IDS_3536 3536 // "Hard disk images (*.HDI;*.HD.." -#define IDS_3537 3537 // "Remember to partition and fo.." +#define IDS_3500 3500 /* "Hard disks:" */ +#define IDS_3501 3501 /* "&New.." */ +#define IDS_3502 3502 /* "&Existing.." */ +#define IDS_3503 3503 /* "&Remove" */ +#define IDS_3504 3504 /* "Bus" */ +#define IDS_3505 3505 /* "File" */ +#define IDS_3506 3506 /* "C" */ +#define IDS_3507 3507 /* "H" */ +#define IDS_3508 3508 /* "S" */ +#define IDS_3509 3509 /* "MB" */ +#define IDS_3510 3510 /* "MB (CHS: %".." */ +#define IDS_3511 3511 /* "Custom..." */ +#define IDS_3512 3512 /* "Custom (large)..." */ +#define IDS_3515 3515 /* "ST506" */ +#define IDS_3516 3516 /* "ESDI" */ +#define IDS_3517 3517 /* "IDE" */ +#define IDS_3518 3518 /* "SCSI" */ +#define IDS_3519 3519 /* "USB" */ + +/* UI dialog: Settings (Add Hard Disk, 3525.) */ +#define IDS_3525 3525 /* "Add Hard Disk" */ +#define IDS_3526 3526 /* "Add New Hard Disk" */ +#define IDS_3527 3527 /* "Add Existing Hard Disk" */ +#define IDS_3528 3528 /* "Cylinders:" */ +#define IDS_3529 3529 /* "Heads:" */ +#define IDS_3530 3530 /* "Sectors:" */ +#define IDS_3531 3531 /* "Size (MB):" */ +#define IDS_3532 3532 /* "Type:" */ +#define IDS_3533 3533 /* "Attempting to create a HDI ima.." */ +#define IDS_3534 3534 /* "Attempting to create a spurio.." */ +#define IDS_3535 3535 /* "HDI or HDX image with a sect.." */ +#define IDS_3536 3536 /* "Hard disk images (*.HDI;*.HD.." */ +#define IDS_3537 3537 /* "Remember to partition and fo.." */ /* UI dialog: Settings (Floppy Drives, 3550.) */ -#define IDS_3554 3554 // "Turbo" -#define IDS_3555 3555 // "Check BPB" +#define IDS_3550 3550 /* "Floppy drives:" */ +#define IDS_3551 3551 /* "Type:" */ +#define IDS_3552 3552 /* "Turbo timings" */ +#define IDS_3553 3553 /* "Check BPB" */ +#define IDS_3554 3554 /* "Turbo" */ +#define IDS_3555 3555 /* "Check BPB" */ /* UI dialog: Settings (Removable Devices, 3575) */ -#define IDS_3579 3579 // "Speed" -#define IDS_3580 3580 // "" -#define IDS_3581 3581 // "" -#define IDS_3582 3582 // "ATAPI (PIO-only)" -#define IDS_3583 3583 // "ATAPI (PIO and DMA)" -#define IDS_3584 3584 // "SCSI" +#define IDS_3575 3575 /* "CD-ROM drives:" */ +#define IDS_3576 3576 /* "Speed:" */ +#define IDS_3577 3577 /* "ZIP drives:" */ +#define IDS_3578 3578 /* "ZIP 250" */ +#define IDS_3579 3579 /* "Speed" */ +#define IDS_3580 3580 /* "ATAPI" */ +#define IDS_3581 3581 /* "SCSI" */ +#define IDS_3582 3582 /* "USB" */ + /* UI dialog: Status Bar (3900.) */ -#define IDS_3900 3900 // "(empty)" -#define IDS_3901 3901 // "(host drive %c:)" -#define IDS_3902 3902 // "[WP]" -#define IDS_3903 3903 // "&New image..." -#define IDS_3904 3904 // "&Load image..." -#define IDS_3905 3905 // "&Reload previous image" -#define IDS_3906 3906 // "&Unload" -#define IDS_3910 3910 // "Floppy %i (%s): %ls" -#define IDS_3911 3911 // "All floppy images (*.0??;*.." -#define IDS_3912 3912 // "All floppy images (*.DSK..." -#define IDS_3913 3913 // "Surface-based images (*.8.." -#define IDS_3914 3914 // "E&xport to 86F..." -#define IDS_3920 3920 // "CD-ROM %i (%s): %s" -#define IDS_3921 3921 // "Host CD/DVD Drive (%c:)" -#define IDS_3922 3922 // "CD-ROM images (*.ISO;*.CU.." -#define IDS_3923 3923 // "&Mute" -#define IDS_3930 3930 // "Hard disk (%s)" -#define IDS_3940 3940 // "Removable disk %i: %ls" -#define IDS_3941 3941 // "&Notify disk change" -#define IDS_3950 3950 // "ZIP %i (%03i): %ls" -#define IDS_3951 3951 // "ZIP images (*.IM?)\0*.IM..." -#define IDS_3952 3952 // "ZIP images (*.IM?)\0*.IM..." -#define IDS_3960 3960 // "Network (%s) -#define IDS_3970 3970 // "Sound (%s) +#define IDS_3900 3900 /* "(empty)" */ +#define IDS_3901 3901 /* "(host drive %c:)" */ +#define IDS_3902 3902 /* "[WP]" */ +#define IDS_3903 3903 /* "&New image..." */ +#define IDS_3904 3904 /* "&Load image..." */ +#define IDS_3905 3905 /* "&Reload previous image" */ +#define IDS_3906 3906 /* "&Unload" */ +#define IDS_3907 3907 /* "Notify disk &change" */ +#define IDS_3910 3910 /* "Floppy %i (%s): %ls" */ +#define IDS_3911 3911 /* "All floppy images (*.0??;*.." */ +#define IDS_3912 3912 /* "All floppy images (*.dsk..." */ +#define IDS_3913 3913 /* "Surface-based images (*.8.." */ +#define IDS_3914 3914 /* "E&xport to ..." */ +#define IDS_3920 3920 /* "CD-ROM %i (%ls): %ls" */ +#define IDS_3921 3921 /* "Host CD/DVD Drive (%c:)" */ +#define IDS_3922 3922 /* "CD-ROM images (*.iso;*.cu.." */ +#define IDS_3923 3923 /* "&Mute" */ +#define IDS_3930 3930 /* "Disk %i (%ls): %ls" */ +#define IDS_3950 3950 /* "ZIP%03i %i (%ls): %ls" */ +#define IDS_3951 3951 /* "ZIP images (*.im?)\0*.im..." */ +#define IDS_3952 3952 /* "ZIP images (*.im?)\0*.im..." */ +#define IDS_3960 3960 /* "Network (%s) */ +#define IDS_3970 3970 /* "Sound (%s) */ -#define IDS_END 4000 // end of accesible string IDs +/* UI menu: Action (4000.) */ +#define IDS_ACTION 4000 /* "&Action" */ +#define IDS_4001 4001 /* "&Hard Reset" */ +#define IDS_4002 4002 /* "&Ctrl+Alt+Del" */ +#define IDS_4003 4003 /* "Send Ctrl+Alt+&Esc" */ +#define IDS_4004 4004 /* "Send Ctrl+Alt+&Break" */ +#define IDS_4005 4005 /* "&Pause" */ +#define IDS_4006 4006 /* "E&xit" */ + +/* UI menu: View (4010.) */ +#define IDS_VIEW 4010 /* "&View" */ +#define IDS_4011 4011 /* "&Resizeable window" */ +#define IDS_4012 4012 /* "R&emember size && position" */ +#define IDS_4013 4013 /* "&Fullscreen\tCtrl+Alt+PageUP" */ +#define IDS_4014 4014 /* "R&ight CTRL is left ALT" */ + +/* UI menu: View > Renderer (4020.) */ +#define IDS_4020 4020 /* "Re&nderer" */ + +/* UI menu: View > Window Scale Factor (4030.) */ +#define IDS_4030 4030 /* "&Window scale factor" */ +#define IDS_4031 4031 /* "&0.5x" */ +#define IDS_4032 4032 /* "&1x" */ +#define IDS_4033 4033 /* "1.&5x" */ +#define IDS_4034 4034 /* "&2x" */ + +/* UI menu: View > Fullscreen Stretch Mode (4040.) */ +#define IDS_4040 4040 /* "Fullscreen &stretch mode" */ +#define IDS_4041 4041 /* "&Full screen stretch" */ +#define IDS_4042 4042 /* "&4:3" */ +#define IDS_4043 4043 /* "&Square pixels" */ +#define IDS_4044 4044 /* "&Integer scale" */ +#define IDS_4045 4045 /* "&Keep size" */ + +/* UI menu: Display (4050.) */ +#define IDS_DISPLAY 4050 /* "&Display" */ +#define IDS_4051 4051 /* "&Inverted display" */ +#define IDS_4052 4052 /* "Enable &overscan" */ +#define IDS_4053 4053 /* "F&orce 4:3 display ratio" */ +#define IDS_4054 4054 /* "Change &contrast.." */ + +/* UI menu: Display > DisplayType (4060.) */ +#define IDS_DISPTYPE 4060 /* "Display &type" */ +#define IDS_4061 4061 /* "RGB &Color monitor" */ +#define IDS_4062 4062 /* "&Grayscale monitor" */ +#define IDS_4063 4063 /* "&Amber monitor" */ +#define IDS_4064 4064 /* "&Green monitor" */ +#define IDS_4065 4065 /* "&White monitor" */ + +/* UI menu: Display > GrayscaleType (4070.) */ +#define IDS_GRAYSCALE 4070 /* "&Grayscale conversion type" */ +#define IDS_4071 4071 /* "BT&601 (NTSC/PAL)" */ +#define IDS_4072 4072 /* "BT&709 (HDTV)" */ +#define IDS_4073 4073 /* "&Average" */ + + +/* UI menu: Tools (4080.) */ +#define IDS_TOOLS 4080 /* "&Tools" */ +#define IDS_4081 4081 /* "&Settings" */ +#define IDS_4082 4082 /* "&Language" */ +#define IDS_4083 4083 /* "L&ogging" */ +#define IDS_4084 4084 /* "Log Breakpoint" */ +#define IDS_4085 4085 /* "Toggle %s logging" */ +#define IDS_4086 4086 /* "Load &configuration" */ +#define IDS_4087 4087 /* "S&ave configuration" */ +#define IDS_4088 4088 /* "&Take screenshot\tCtrl+Home" */ + + +/* UI menu: Help (4090.) */ +#define IDS_HELP 4090 /* "&Help" */ +#define IDS_4091 4091 /* "&About VARCem" */ + + +#define IDS_END 4100 /* end of string IDs */ #endif /*EMU_UI_RESOURCE_H*/ diff --git a/src/ui/ui_stbar.c b/src/ui/ui_stbar.c index dd9889b..f3560ac 100644 --- a/src/ui/ui_stbar.c +++ b/src/ui/ui_stbar.c @@ -8,7 +8,7 @@ * * Common UI support functions for the Status Bar module. * - * Version: @(#)ui_stbar.c 1.0.9 2018/05/27 + * Version: @(#)ui_stbar.c 1.0.10 2018/10/05 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -45,15 +45,16 @@ #include "../machines/machine.h" #include "../device.h" #include "../plat.h" +#include "../devices/input/keyboard.h" #include "../devices/floppy/fdd.h" #include "../devices/disk/hdd.h" #include "../devices/disk/hdc.h" +#include "../devices/scsi/scsi_device.h" +#include "../devices/scsi/scsi_disk.h" #include "../devices/disk/zip.h" #include "../devices/cdrom/cdrom.h" #include "../devices/cdrom/cdrom_image.h" #include "../devices/cdrom/cdrom_null.h" -#include "../devices/scsi/scsi.h" -#include "../devices/scsi/scsi_disk.h" #include "../devices/network/network.h" #include "../devices/sound/sound.h" #include "../devices/video/video.h" @@ -61,28 +62,30 @@ #include "ui_resource.h" -static int *sb_widths; -static int *sb_flags; -static int *sb_tags; -static int *sb_icons; -static wchar_t **sb_tips; -static wchar_t *sb_text; +#define USE_SPACER 1 /* include a spacer field */ -static int sb_parts = 0; +#define SB_MESSAGE SB_TEXT|0x00 /* general messages */ +#define SB_DEVICE SB_TEXT|0x01 /* device info (Bugger) */ +#define SB_NUMLK SB_TEXT|0x02 /* NUM LOCK field */ +#define SB_CAPLK SB_TEXT|0x03 /* CAPS LOCK field */ + + +static sbpart_t *sb_parts = NULL; +static int sb_nparts = 0; static int sb_ready = 0; /* Find the part in which a given tag lives. */ static int -find_tag(int tag) +find_tag(uint8_t tag) { - int part; + int i; - if (sb_tags == NULL) return(-1); + if (sb_parts == NULL) return(-1); - for (part = 0; part < sb_parts; part++) { - if (sb_tags[part] == tag) - return(part); + for (i = 0; i < sb_nparts; i++) { + if (sb_parts[i].tag == tag) + return(i); } return(-1); @@ -91,7 +94,7 @@ find_tag(int tag) /* Enable or disable a given status bar menu item. */ void -ui_sb_menu_enable_item(int tag, int idm, int val) +ui_sb_menu_enable_item(uint8_t tag, int idm, int val) { int part; @@ -104,7 +107,7 @@ ui_sb_menu_enable_item(int tag, int idm, int val) /* Set (check) or clear (uncheck) a given status bar menu item. */ void -ui_sb_menu_set_item(int tag, int idm, int val) +ui_sb_menu_set_item(uint8_t tag, int idm, int val) { int part; @@ -118,117 +121,121 @@ ui_sb_menu_set_item(int tag, int idm, int val) /* Update one of the icons after activity. */ // FIXME: implement a timer on each icon! void -ui_sb_icon_update(int tag, int active) +ui_sb_icon_update(uint8_t tag, int active) { + sbpart_t *ptr; int part; - if (! update_icons) return; - - if (((tag & 0xf0) >= SB_TEXT) || !sb_ready || (sb_parts == 0)) return; + if ((sb_parts == NULL) || !sb_ready || (sb_nparts == 0)) return; /* Find the status bar part for this tag. */ if ((part = find_tag(tag)) == -1) return; - if ((sb_flags[part] & 1) != active) { - sb_flags[part] &= ~1; - sb_flags[part] |= active; + ptr = &sb_parts[part]; + if ((ptr->flags & ICON_ACTIVE) != active) { + ptr->flags &= ~ICON_ACTIVE; + ptr->flags |= (uint8_t)active; - sb_icons[part] &= ~257; - sb_icons[part] |= sb_flags[part]; + ptr->icon &= ~(ICON_EMPTY | ICON_ACTIVE); + ptr->icon |= ptr->flags; - sb_set_icon(part, sb_icons[part]); + sb_set_icon(part, ptr->icon); } } /* Set the 'active' state for an icon. */ void -ui_sb_icon_state(int tag, int state) +ui_sb_icon_state(uint8_t tag, int state) { + sbpart_t *ptr; int part; - if (((tag & 0xf0) >= SB_HDD) || !sb_ready || - (sb_parts == 0) || (sb_flags == NULL) || (sb_icons == NULL)) return; + if ((sb_parts == NULL) || !sb_ready || (sb_nparts == 0)) return; /* Find the status bar part for this tag. */ if ((part = find_tag(tag)) == -1) return; - sb_flags[part] &= ~256; - sb_flags[part] |= state ? 256 : 0; + ptr = &sb_parts[part]; + ptr->flags &= ~ICON_EMPTY; + ptr->flags |= state ? ICON_EMPTY : 0; - sb_icons[part] &= ~257; - sb_icons[part] |= sb_flags[part]; + ptr->icon &= ~(ICON_EMPTY | ICON_ACTIVE); + ptr->icon |= ptr->flags; - sb_set_icon(part, sb_icons[part]); + sb_set_icon(part, ptr->icon); } /* Set the 'text' field with a given (Unicode) string. */ void -ui_sb_text_set_w(const wchar_t *str) +ui_sb_text_set_w(uint8_t tag, const wchar_t *str) { + sbpart_t *ptr; int part; - if (!sb_ready || (sb_parts == 0)) return; + if ((sb_parts == NULL) || !sb_ready || (sb_nparts == 0)) return; /* Find the status bar part for this tag. */ - if ((part = find_tag(SB_TEXT)) == -1) return; + if ((part = find_tag(tag)) == -1) return; - sb_set_text(part, str); + ptr = &sb_parts[part]; + if (ptr->text != NULL) + free(ptr->text); + ptr->text = (wchar_t *)mem_alloc(sizeof(wchar_t) * (wcslen(str) + 1)); + wcscpy(ptr->text, str); - if (sb_text != NULL) - free(sb_text); - sb_text = (wchar_t *)malloc(sizeof(wchar_t) * (wcslen(str) + 1)); - wcscpy(sb_text, str); + sb_set_text(part, ptr->text); } /* Set the 'text' field with a given (ANSI) string. */ void -ui_sb_text_set(const char *str) +ui_sb_text_set(uint8_t tag, const char *str) { wchar_t temp[512]; mbstowcs(temp, str, sizeof_w(temp)); - ui_sb_text_set_w(temp); + ui_sb_text_set_w(tag, temp); } /* Update the 'tool tip' text on one of the parts. */ void -ui_sb_tip_update(int tag) +ui_sb_tip_update(uint8_t tag) { wchar_t tip[512]; wchar_t temp[512]; const wchar_t *str; const char *stransi; + sbpart_t *ptr; int bus, drive, id; int type, part; - if (sb_tags == NULL) return; + if ((sb_parts == NULL) || (sb_nparts == 0)) return; /* Find the status bar part for this tag. */ if ((part = find_tag(tag)) == -1) return; + ptr = &sb_parts[part]; switch(tag & 0xf0) { case SB_FLOPPY: - drive = sb_tags[part] & 0x0f; + drive = ptr->tag & 0x0f; stransi = fdd_getname(fdd_get_type(drive)); - mbstowcs(temp, stransi, sizeof_w(temp)); str = floppyfns[drive]; if (*str == L'\0') str = get_string(IDS_3900); /*"(empty)"*/ swprintf(tip, sizeof_w(tip), - get_string(IDS_3910), drive+1, temp, str); + get_string(IDS_3910), drive+1, stransi, str); if (ui_writeprot[drive]) wcscat(tip, get_string(IDS_3902)); /*"[WP]"*/ break; case SB_CDROM: - drive = sb_tags[part] & 0x0f; + drive = ptr->tag & 0x0f; bus = cdrom_drives[drive].bus_type; - id = IDS_3515 + (bus - 1); + id = IDS_3580 + (bus - 1); wcscpy(temp, get_string(id)); str = cdrom_image[drive].image_path; if (*str == L'\0') @@ -251,75 +258,71 @@ ui_sb_tip_update(int tag) break; case SB_ZIP: - drive = sb_tags[part] & 0x0f; + drive = ptr->tag & 0x0f; + bus = cdrom_drives[drive].bus_type; + id = IDS_3580 + (bus - 1); + wcscpy(temp, get_string(id)); type = zip_drives[drive].is_250 ? 250 : 100; str = zip_drives[drive].image_path; if (*str == L'\0') str = get_string(IDS_3900); /*"(empty)"*/ swprintf(tip, sizeof_w(tip), - get_string(IDS_3950), drive+1, type, str); + get_string(IDS_3950), type, drive+1, temp, str); if (zip_drives[drive].ui_writeprot) wcscat(tip, get_string(IDS_3902)); /*"[WP]"*/ break; - case SB_RDISK: - drive = sb_tags[part] & 0x1f; + case SB_DISK: + drive = ptr->tag & 0x0f; + id = IDS_3515 + hdd[drive].bus - 1; + str = hdd[drive].fn; if (*str == L'\0') str = get_string(IDS_3900); /*"(empty)"*/ - swprintf(tip, sizeof_w(tip), - get_string(IDS_3940), drive, str); - if (0) - wcscat(tip, get_string(IDS_3902)); /*"[WP]"*/ - break; - case SB_HDD: - bus = sb_tags[part] & 0x0f; - id = IDS_3515 + (bus - 1); - str = get_string(id); swprintf(tip, sizeof_w(tip), - get_string(IDS_3930), str); - if (0) + get_string(IDS_3930), drive+1, get_string(id), str); + + if (hdd[drive].wp) wcscat(tip, get_string(IDS_3902)); /*"[WP]"*/ break; case SB_NETWORK: - swprintf(tip, sizeof_w(tip), get_string(IDS_3960)); + stransi = network_card_getname(network_card); + swprintf(tip, sizeof_w(tip), + get_string(IDS_3960), stransi); break; case SB_SOUND: - swprintf(tip, sizeof_w(tip), get_string(IDS_3970)); + stransi = sound_card_getname(sound_card); + swprintf(tip, sizeof_w(tip), + get_string(IDS_3970), stransi); break; default: break; } - if (sb_tips[part] != NULL) - free(sb_tips[part]); + if (ptr->tip != NULL) + free(ptr->tip); + ptr->tip = (wchar_t *)mem_alloc(sizeof(wchar_t) * (wcslen(tip) + 1)); + wcscpy(ptr->tip, tip); - sb_tips[part] = (wchar_t *)malloc(sizeof(wchar_t) * (wcslen(tip) + 1)); - wcscpy(sb_tips[part], tip); - - sb_set_tooltip(part, sb_tips[part]); + sb_set_tooltip(part, ptr->tip); } -void -ui_sb_tip_destroy(void) +/* Create the "hard disk" menu. */ +static void +menu_disk(int part, int drive) { - int part; - - if ((sb_parts == 0) || (sb_tips == NULL)) return; - - for (part = 0; part < sb_parts; part++) { - if (sb_tips[part] != NULL) - free(sb_tips[part]); - } - - free(sb_tips); - - sb_tips = NULL; + sb_menu_add_item(part, IDM_DISK_NOTIFY|drive, get_string(IDS_3907)); + sb_menu_add_item(part, -1, NULL); + sb_menu_add_item(part, IDM_DISK_IMAGE_NEW|drive, get_string(IDS_3903)); + sb_menu_add_item(part, IDM_DISK_IMAGE_EXISTING|drive, get_string(IDS_3904)); + sb_menu_add_item(part, IDM_DISK_RELOAD|drive, get_string(IDS_3905)); + sb_menu_add_item(part, -1, NULL); + sb_menu_add_item(part, IDM_DISK_EJECT|drive, get_string(IDS_3906)); } @@ -333,12 +336,12 @@ menu_floppy(int part, int drive) sb_menu_add_item(part, -1, NULL); sb_menu_add_item(part, IDM_FLOPPY_EJECT|drive, get_string(IDS_3906)); sb_menu_add_item(part, -1, NULL); - sb_menu_add_item(part, IDM_FLOPPY_EXPORT_TO_86F|drive, + sb_menu_add_item(part, IDM_FLOPPY_EXPORT|drive, get_string(IDS_3914)); if (floppyfns[drive][0] == L'\0') { sb_menu_enable_item(part, IDM_FLOPPY_EJECT | drive, 0); - sb_menu_enable_item(part, IDM_FLOPPY_EXPORT_TO_86F | drive, 0); + sb_menu_enable_item(part, IDM_FLOPPY_EXPORT | drive, 0); } } @@ -363,7 +366,7 @@ menu_cdrom(int part, int drive) cdrom_drives[drive].host_drive = 0; } - goto check_menu_items; + goto check_items; } else { if ((cdrom_drives[drive].host_drive >= 'A') && (cdrom_drives[drive].host_drive <= 'Z')) { @@ -381,7 +384,7 @@ menu_cdrom(int part, int drive) sb_menu_add_item(part, IDM_CDROM_HOST_DRIVE | (i << 3)|drive, temp); } -check_menu_items: +check_items: if (! cdrom_drives[drive].sound_on) sb_menu_set_item(part, IDM_CDROM_MUTE | drive, 1); @@ -419,81 +422,64 @@ menu_zip(int part, int drive) } -/* Create the "Removable Media" menu. */ -static void -menu_remov(int part, int drive) -{ - sb_menu_add_item(part, IDM_RDISK_SEND_CHANGE|drive, get_string(IDS_3941)); - sb_menu_add_item(part, -1, NULL); - sb_menu_add_item(part, IDM_RDISK_IMAGE|drive, get_string(IDS_3904)); - sb_menu_add_item(part, IDM_RDISK_RELOAD|drive, get_string(IDS_3905)); - sb_menu_add_item(part, -1, NULL); - sb_menu_add_item(part, IDM_RDISK_EJECT|drive, get_string(IDS_3906)); -} - - /* Initialize or update the entire status bar. */ void -ui_sb_update(void) +ui_sb_reset(void) { - int c_st506, c_esdi, c_scsi; - int c_ide_pio, c_ide_dma; - int do_net, edge = 0; - int drive, part; - int hdint; + int drive, hdint, part; + int do_net, do_sound; const char *hdc; + sbpart_t *ptr; sb_ready = 0; /* First, remove any existing parts of the status bar. */ - if (sb_parts > 0) { - /* Clear all the current icons from the status bar. */ - for (part = 0; part < sb_parts; part++) - sb_set_icon(part, -1); + if (sb_nparts > 0) { + for (part = 0; part < sb_nparts; part++) { + if (sb_parts[part].tip != NULL) + free(sb_parts[part].tip); + } - /* Reset the status bar to 0 parts. */ - sb_setup(0, NULL); + /* Now release the entire array. */ + free(sb_parts); - if (sb_widths != NULL) - free(sb_widths); - if (sb_tags != NULL) - free(sb_tags); - if (sb_icons != NULL) - free(sb_icons); - if (sb_flags != NULL) - free(sb_flags); - - /* Destroy all existing tool tips. */ - ui_sb_tip_destroy(); - - /* Destroy all current menus. */ - sb_menu_destroy(); + /* OK, all cleaned up. */ + sb_nparts = 0; } - /* OK, all cleaned up. */ - sb_parts = 0; - - /* Calculate the number of part classes. */ hdint = (machines[machine].flags & MACHINE_HDC) ? 1 : 0; - c_st506 = hdd_count(HDD_BUS_ST506); - c_esdi = hdd_count(HDD_BUS_ESDI); - c_ide_pio = hdd_count(HDD_BUS_IDE_PIO_ONLY); - c_ide_dma = hdd_count(HDD_BUS_IDE_PIO_AND_DMA); - c_scsi = hdd_count(HDD_BUS_SCSI); do_net = network_available(); - - for (drive = 0; drive < FDD_NUM; drive++) { - if (fdd_get_type(drive) != 0) - sb_parts++; - } + do_sound = !!(sound_card != 0); /* Get name of current HDC. */ hdc = hdc_get_internal_name(hdc_type); + /* Count all the floppy drives. */ + for (drive = 0; drive < FDD_NUM; drive++) { + if (fdd_get_type(drive) != 0) + sb_nparts++; + } + + /* Check all (active) hard disks. */ + for (drive = 0; drive < HDD_NUM; drive++) { + if ((hdd[drive].bus == HDD_BUS_IDE) && + !(hdint || !strncmp(hdc, "ide", 3) || !strncmp(hdc, "xta", 3))) { + /* Disk, but no controller for it. */ + continue; + } + + if ((hdd[drive].bus == HDD_BUS_SCSI) && (scsi_card == 0)) { + /* Disk, but no controller for it. */ + continue; + } + + if (hdd[drive].bus != HDD_BUS_DISABLED) + sb_nparts++; + } + for (drive = 0; drive < CDROM_NUM; drive++) { /* Could be Internal or External IDE.. */ - if (((cdrom_drives[drive].bus_type==CDROM_BUS_ATAPI_PIO_ONLY) && - (cdrom_drives[drive].bus_type==CDROM_BUS_ATAPI_PIO_AND_DMA)) && + if ((cdrom_drives[drive].bus_type == CDROM_BUS_ATAPI) && !(hdint || !strncmp(hdc, "ide", 3) || !strncmp(hdc, "xta", 3))) { continue; } @@ -502,287 +488,253 @@ ui_sb_update(void) continue; } - if (cdrom_drives[drive].bus_type != 0) { - sb_parts++; - } + if (cdrom_drives[drive].bus_type != CDROM_BUS_DISABLED) + sb_nparts++; } for (drive = 0; drive < ZIP_NUM; drive++) { /* Could be Internal or External IDE.. */ - if (((zip_drives[drive].bus_type==ZIP_BUS_ATAPI_PIO_ONLY) && - (zip_drives[drive].bus_type==ZIP_BUS_ATAPI_PIO_AND_DMA)) && + if ((zip_drives[drive].bus_type == ZIP_BUS_ATAPI) && !(hdint || !strncmp(hdc, "ide", 3) || !strncmp(hdc, "xta", 3))) { continue; } - if ((zip_drives[drive].bus_type == ZIP_BUS_SCSI) && - (scsi_card == 0)) { + if ((zip_drives[drive].bus_type == ZIP_BUS_SCSI) && (scsi_card == 0)) continue; - } - if (zip_drives[drive].bus_type != 0) { - sb_parts++; - } + if (zip_drives[drive].bus_type != CDROM_BUS_DISABLED) + sb_nparts++; } - for (drive = 0; drive < HDD_NUM; drive++) { - if ((hdd[drive].bus==HDD_BUS_SCSI_REMOVABLE) && (scsi_card != 0)) { - sb_parts++; - } - } + if (do_net) + sb_nparts++; - if (c_st506 && (hdint || !strncmp(hdc, "st506", 5))) { - /* ST506 MFM/RLL drives, and MFM or Internal controller. */ - sb_parts++; - } - if (c_esdi && (hdint || !strncmp(hdc, "esdi", 4))) { - /* ESDI drives, and ESDI or Internal controller. */ - sb_parts++; - } - if (c_ide_pio && (hdint || !strncmp(hdc, "ide", 3) || !strncmp(hdc, "xta", 3))) { - /* IDE_PIO drives, and IDE or Internal controller. */ - sb_parts++; - } - if (c_ide_dma && (hdint || !strncmp(hdc, "ide", 3))) { - /* IDE_DMA drives, and IDE or Internal controller. */ - sb_parts++; - } - if (c_scsi && (scsi_card != 0)) { - sb_parts++; - } - if (do_net) { - sb_parts++; - } - sb_parts += 2; + if (do_sound) + sb_nparts++; - /* Now (re-)allocate the fields. */ - sb_widths = (int *)malloc(sb_parts * sizeof(int)); - memset(sb_widths, 0x00, sb_parts * sizeof(int)); - sb_tags = (int *)malloc(sb_parts * sizeof(int)); - memset(sb_tags, 0x00, sb_parts * sizeof(int)); - sb_icons = (int *)malloc(sb_parts * sizeof(int)); - memset(sb_icons, 0x00, sb_parts * sizeof(int)); - sb_flags = (int *)malloc(sb_parts * sizeof(int)); - memset(sb_flags, 0x00, sb_parts * sizeof(int)); - sb_tips = (wchar_t **)malloc(sb_parts * sizeof(wchar_t *)); - memset(sb_tips, 0x00, sb_parts * sizeof(wchar_t *)); +#ifdef USE_SPACER + /* A spacer. */ + sb_nparts++; +#endif - /* Start populating the fields. */ - sb_parts = 0; + /* For devices like ISAbugger. */ + if (bugger_enabled) + sb_nparts++; + + /* General text message field. */ + sb_nparts++; + + /* Keyboard fields. */ + sb_nparts += 2; + + /* Now (re-)allocate the parts. */ + sb_parts = (sbpart_t *)mem_alloc(sb_nparts * sizeof(sbpart_t)); + memset(sb_parts, 0x00, sb_nparts * sizeof(sbpart_t)); + + /* Start populating the fields at the left edge of the window. */ + sb_nparts = 0; for (drive = 0; drive < FDD_NUM; drive++) { if (fdd_get_type(drive) != 0) { - edge += SB_ICON_WIDTH; - sb_widths[sb_parts] = edge; - sb_tags[sb_parts] = SB_FLOPPY | drive; - sb_parts++; + ptr = &sb_parts[sb_nparts++]; + ptr->width = SB_ICON_WIDTH; + ptr->tag = SB_FLOPPY | drive; + } + } + + for (drive = 0; drive < HDD_NUM; drive++) { + if ((hdd[drive].bus == HDD_BUS_IDE) && + !(hdint || !strncmp(hdc, "ide", 3) || !strncmp(hdc, "xta", 3))) { + /* Disk, but no controller for it. */ + continue; + } + + if ((hdd[drive].bus == HDD_BUS_SCSI) && (scsi_card == 0)) { + /* Disk, but no controller for it. */ + continue; + } + + if (hdd[drive].bus != HDD_BUS_DISABLED) { + ptr = &sb_parts[sb_nparts++]; + ptr->width = SB_ICON_WIDTH; + ptr->tag = SB_DISK | drive; } } for (drive = 0; drive < CDROM_NUM; drive++) { /* Could be Internal or External IDE.. */ - if ((cdrom_drives[drive].bus_type==CDROM_BUS_ATAPI_PIO_ONLY) && + if ((cdrom_drives[drive].bus_type == CDROM_BUS_ATAPI) && !(hdint || !strncmp(hdc, "ide", 3))) { continue; } - /* Could be Internal or External IDE.. */ - if ((cdrom_drives[drive].bus_type==CDROM_BUS_ATAPI_PIO_AND_DMA) && - !(hdint || !strncmp(hdc, "ide", 3))) { + if ((cdrom_drives[drive].bus_type == CDROM_BUS_SCSI) && (scsi_card == 0)) continue; - } - if ((cdrom_drives[drive].bus_type == CDROM_BUS_SCSI) && (scsi_card == 0)) { - continue; - } - - if (cdrom_drives[drive].bus_type != 0) { - edge += SB_ICON_WIDTH; - sb_widths[sb_parts] = edge; - sb_tags[sb_parts] = SB_CDROM | drive; - sb_parts++; + if (cdrom_drives[drive].bus_type != CDROM_BUS_DISABLED) { + ptr = &sb_parts[sb_nparts++]; + ptr->width = SB_ICON_WIDTH; + ptr->tag = SB_CDROM | drive; } } for (drive = 0; drive < ZIP_NUM; drive++) { /* Could be Internal or External IDE.. */ - if ((zip_drives[drive].bus_type==ZIP_BUS_ATAPI_PIO_ONLY) && + if ((zip_drives[drive].bus_type == ZIP_BUS_ATAPI) && !(hdint || !strncmp(hdc, "ide", 3))) { continue; } - /* Could be Internal or External IDE.. */ - if ((zip_drives[drive].bus_type==ZIP_BUS_ATAPI_PIO_AND_DMA) && - !(hdint || !strncmp(hdc, "ide", 3))) { + if ((zip_drives[drive].bus_type == ZIP_BUS_SCSI) && (scsi_card == 0)) continue; - } - - if ((zip_drives[drive].bus_type == ZIP_BUS_SCSI) && (scsi_card == 0)) { - continue; - } if (zip_drives[drive].bus_type != 0) { - edge += SB_ICON_WIDTH; - sb_widths[sb_parts] = edge; - sb_tags[sb_parts] = SB_ZIP | drive; - sb_parts++; + ptr = &sb_parts[sb_nparts++]; + ptr->width = SB_ICON_WIDTH; + ptr->tag = SB_ZIP | drive; } } - for (drive = 0; drive < HDD_NUM; drive++) { - if ((hdd[drive].bus==HDD_BUS_SCSI_REMOVABLE) && (scsi_card != 0)) { - edge += SB_ICON_WIDTH; - sb_widths[sb_parts] = edge; - sb_tags[sb_parts] = SB_RDISK | drive; - sb_parts++; - } - } - - if (c_st506 && (hdint || !strncmp(hdc, "st506", 5))) { - edge += SB_ICON_WIDTH; - sb_widths[sb_parts] = edge; - sb_tags[sb_parts] = SB_HDD | HDD_BUS_ST506; - sb_parts++; - } - - if (c_esdi && (hdint || !strncmp(hdc, "esdi", 4))) { - edge += SB_ICON_WIDTH; - sb_widths[sb_parts] = edge; - sb_tags[sb_parts] = SB_HDD | HDD_BUS_ESDI; - sb_parts++; - } - - if (c_ide_pio && (hdint || !strncmp(hdc, "ide", 3) || !strncmp(hdc, "xta", 3))) { - edge += SB_ICON_WIDTH; - sb_widths[sb_parts] = edge; - sb_tags[sb_parts] = SB_HDD | HDD_BUS_IDE_PIO_ONLY; - sb_parts++; - } - - if (c_ide_dma && (hdint || !strncmp(hdc, "ide", 3))) { - edge += SB_ICON_WIDTH; - sb_widths[sb_parts] = edge; - sb_tags[sb_parts] = SB_HDD | HDD_BUS_IDE_PIO_AND_DMA; - sb_parts++; - } - - if (c_scsi && (scsi_card != 0)) { - edge += SB_ICON_WIDTH; - sb_widths[sb_parts] = edge; - sb_tags[sb_parts] = SB_HDD | HDD_BUS_SCSI; - sb_parts++; - } - if (do_net) { - edge += SB_ICON_WIDTH; - sb_widths[sb_parts] = edge; - sb_tags[sb_parts] = SB_NETWORK; - sb_parts++; + ptr = &sb_parts[sb_nparts++]; + ptr->width = SB_ICON_WIDTH; + ptr->tag = SB_NETWORK; } /* Initialize the Sound field. */ - if (sound_card != 0) { - edge += SB_ICON_WIDTH; - sb_widths[sb_parts] = edge; - sb_tags[sb_parts] = SB_SOUND; - sb_parts++; + if (do_sound) { + ptr = &sb_parts[sb_nparts++]; + ptr->width = SB_ICON_WIDTH; + ptr->tag = SB_SOUND; + } + +#ifdef USE_SPACER + /* A spacer. */ + ptr = &sb_parts[sb_nparts++]; + ptr->width = 10; + ptr->tag = 0xff; + ptr->icon = 255; +#endif + + /* Fun! */ + if (bugger_enabled) { + /* Add a text field for the ISAbugger. */ + ptr = &sb_parts[sb_nparts++]; + ptr->width = 175; + ptr->tag = SB_TEXT|1; + ptr->icon = 255; } /* Add a text field and finalize the field settings. */ - if (sb_parts) - sb_widths[sb_parts - 1] += (24 - SB_ICON_WIDTH); - sb_widths[sb_parts] = -1; - sb_tags[sb_parts] = SB_TEXT; - sb_parts++; + ptr = &sb_parts[sb_nparts++]; + ptr->width = 0; + ptr->tag = SB_TEXT; + ptr->icon = 255; - /* Set up the status bar parts and their widths. */ - sb_setup(sb_parts, sb_widths); + /* Add the two keyboard-state indicators. */ + ptr = &sb_parts[sb_nparts++]; + ptr->width = 40; + ptr->tag = SB_NUMLK; + ptr->icon = 255; + ptr = &sb_parts[sb_nparts++]; + ptr->width = 45; + ptr->tag = SB_CAPLK; + ptr->icon = 255; + + /* Set up the platform status bar. */ + sb_setup(sb_nparts, sb_parts); /* Initialize each status bar part. */ - for (part = 0; part < sb_parts; part++) { - switch (sb_tags[part] & 0xf0) { + for (part = 0; part < sb_nparts; part++) { + ptr = &sb_parts[part]; + + switch (ptr->tag & 0xf0) { case SB_FLOPPY: /* Floppy */ - drive = sb_tags[part] & 0x0f; - sb_flags[part] = (wcslen(floppyfns[drive]) == 0) ? 256 : 0; - sb_icons[part] = plat_fdd_icon(fdd_get_type(drive)) | sb_flags[part]; + drive = ptr->tag & 0x0f; + ptr->flags = (wcslen(floppyfns[drive]) == 0) ? ICON_EMPTY : 0; + ptr->icon = (uint8_t)ui_fdd_icon(fdd_get_type(drive)) | ptr->flags; sb_menu_create(part); menu_floppy(part, drive); - ui_sb_tip_update(sb_tags[part]); + ui_sb_tip_update(ptr->tag); break; case SB_CDROM: /* CD-ROM */ - drive = sb_tags[part] & 0x0f; + drive = ptr->tag & 0x0f; if (cdrom_drives[drive].host_drive == 200) { - sb_flags[part] = (wcslen(cdrom_image[drive].image_path) == 0) ? 256 : 0; + ptr->flags = (wcslen(cdrom_image[drive].image_path) == 0) ? ICON_EMPTY : 0; } else if ((cdrom_drives[drive].host_drive >= 'A') && (cdrom_drives[drive].host_drive <= 'Z')) { - sb_flags[part] = 0; + ptr->flags = 0; } else { - sb_flags[part] = 256; + ptr->flags = ICON_EMPTY; } //FIXME: different icons for CD,DVD,BD ? - sb_icons[part] = 160 | sb_flags[part]; + ptr->icon = (uint8_t)(ICON_CDROM | ptr->flags); sb_menu_create(part); menu_cdrom(part, drive); - ui_sb_tip_update(sb_tags[part]); + ui_sb_tip_update(ptr->tag); break; case SB_ZIP: /* Iomega ZIP */ - drive = sb_tags[part] & 0x0f; - sb_flags[part] = (wcslen(zip_drives[drive].image_path) == 0) ? 256 : 0; - sb_icons[part] = 176 + sb_flags[part]; + drive = ptr->tag & 0x0f; + ptr->flags = (wcslen(zip_drives[drive].image_path) == 0) ? ICON_EMPTY : 0; + ptr->icon = (uint8_t)(ICON_ZIP + ptr->flags); sb_menu_create(part); menu_zip(part, drive); - ui_sb_tip_update(sb_tags[part]); + ui_sb_tip_update(ptr->tag); break; - case SB_RDISK: /* Removable hard disk */ - sb_flags[part] = (wcslen(hdd[drive].fn) == 0) ? 256 : 0; - sb_icons[part] = 192 + sb_flags[part]; + case SB_DISK: /* Hard disk */ + drive = ptr->tag & 0x0f; + ptr->flags = (wcslen(hdd[drive].fn) == 0) ? ICON_EMPTY : 0; + ptr->icon = (uint8_t)(ICON_DISK + ptr->flags); sb_menu_create(part); - menu_remov(part, drive); - ui_sb_tip_update(sb_tags[part]); - break; - - case SB_HDD: /* Hard disk */ - sb_icons[part] = 208; - ui_sb_tip_update(sb_tags[part]); + if (hdd[drive].removable) + menu_disk(part, drive); + ui_sb_tip_update(ptr->tag); break; case SB_NETWORK: /* Network */ - sb_icons[part] = 224; - ui_sb_tip_update(sb_tags[part]); + ptr->icon = ICON_NETWORK; + ui_sb_tip_update(ptr->tag); break; case SB_SOUND: /* Sound */ - sb_icons[part] = 259; - ui_sb_tip_update(sb_tags[part]); + ptr->icon = ICON_SOUND; + ui_sb_tip_update(ptr->tag); break; case SB_TEXT: /* Status text */ - sb_icons[part] = -1; - if (sb_text != NULL) - sb_set_text(part, sb_text); - else - sb_set_text(part, L""); + switch(ptr->tag & 0x03) { + case 0: /* message field */ + case 1: /* Bugger/Info field */ + sb_set_text(part, L""); + break; + + case 2: /* NUM keyboard flag */ + case 3: /* CAP keyboard flag */ + drive = keyboard_get_state(); + ui_sb_kbstate(drive); + break; + } break; } /* Set up the correct icon for this part. */ - if (sb_icons[part] != -1) { - sb_set_text(part, L""); - sb_set_icon(part, sb_icons[part]); - } else { - sb_set_icon(part, -1); - } + if (ptr->icon != 255) + sb_set_icon(part, ptr->icon); } + /* The status bar is now ready. */ sb_ready = 1; + + /* Set a default text message. */ + ui_sb_text_set_w(SB_TEXT, L"Welcome to VARCem !!"); } /* Handle a command from one of the status bar menus. */ void -ui_sb_menu_command(int idm, int tag) +ui_sb_menu_command(int idm, uint8_t tag) { wchar_t temp[512]; int new_cdrom_drive; @@ -793,7 +745,7 @@ ui_sb_menu_command(int idm, int tag) switch (idm) { case IDM_FLOPPY_IMAGE_NEW: - drive = tag & 0x0003; + drive = tag & 0x03; part = find_tag(SB_FLOPPY | drive); if (part == -1) break; @@ -801,47 +753,47 @@ ui_sb_menu_command(int idm, int tag) break; case IDM_FLOPPY_IMAGE_EXISTING: - drive = tag & 0x0003; + drive = tag & 0x03; part = find_tag(SB_FLOPPY | drive); if (part == -1) break; str = floppyfns[drive]; i = dlg_file(get_string(IDS_3911), str, temp, DLG_FILE_LOAD); if (i) { - ui_sb_mount_floppy(drive, part, - !!(i & DLG_FILE_RO), temp); + ui_floppy_mount(drive, part, + !!(i & DLG_FILE_RO), temp); } break; case IDM_FLOPPY_EJECT: - drive = tag & 0x0003; + drive = tag & 0x03; part = find_tag(SB_FLOPPY | drive); if (part == -1) break; fdd_close(drive); ui_sb_icon_state(SB_FLOPPY | drive, 1); sb_menu_enable_item(part, IDM_FLOPPY_EJECT | drive, 0); - sb_menu_enable_item(part, IDM_FLOPPY_EXPORT_TO_86F | drive, 0); + sb_menu_enable_item(part, IDM_FLOPPY_EXPORT | drive, 0); ui_sb_tip_update(SB_FLOPPY | drive); config_save(); break; - case IDM_FLOPPY_EXPORT_TO_86F: - drive = tag & 0x0003; + case IDM_FLOPPY_EXPORT: + drive = tag & 0x03; part = find_tag(SB_FLOPPY | drive); if (part == -1) break; str = floppyfns[drive]; if (dlg_file(get_string(IDS_3913), str, temp, DLG_FILE_SAVE)) { - plat_pause(1); + pc_pause(1); if (! d86f_export(drive, temp)) ui_msgbox(MBX_ERROR, (wchar_t *)IDS_OPEN_WRITE); - plat_pause(0); + pc_pause(0); } break; case IDM_CDROM_MUTE: - drive = tag & 0x0007; + drive = tag & 0x07; part = find_tag(SB_CDROM | drive); if (part == -1) break; @@ -853,34 +805,43 @@ ui_sb_menu_command(int idm, int tag) break; case IDM_CDROM_EMPTY: - drive = tag & 0x0007; - cdrom_eject(drive); + drive = tag & 0x07; + ui_cdrom_eject(drive); break; case IDM_CDROM_RELOAD: - drive = tag & 0x0007; - cdrom_reload(drive); + drive = tag & 0x07; + ui_cdrom_reload(drive); break; case IDM_CDROM_IMAGE: - drive = tag & 0x0007; + drive = tag & 0x07; part = find_tag(SB_CDROM | drive); if (part == -1) break; + /* Browse for a new image to use. */ str = cdrom_image[drive].image_path; if (! dlg_file(get_string(IDS_3922), str, temp, DLG_FILE_LOAD|DLG_FILE_RO)) break; + /* Save current drive/pathname for later re-use. */ cdrom_drives[drive].prev_host_drive = cdrom_drives[drive].host_drive; if (! cdrom_image[drive].prev_image_path) - cdrom_image[drive].prev_image_path = (wchar_t *)malloc(1024); + cdrom_image[drive].prev_image_path = (wchar_t *)mem_alloc(1024); wcscpy(cdrom_image[drive].prev_image_path, str); - cdrom_drives[drive].handler->exit(drive); - cdrom_close(drive); + + /* Close the current drive/pathname. */ + cdrom[drive]->handler->exit(drive); + cdrom_close_handler(drive); + memset(cdrom_image[drive].image_path, 0, sizeof(cdrom_image[drive].image_path)); + + /* Now open new image. */ image_open(drive, temp); /* Signal media change to the emulated machine. */ - cdrom_insert(drive); + cdrom_insert(cdrom[drive]); + + /* Update stuff. */ sb_menu_set_item(part, IDM_CDROM_EMPTY | drive, 0); if ((cdrom_drives[drive].host_drive >= 'A') && (cdrom_drives[drive].host_drive <= 'Z')) { @@ -903,7 +864,7 @@ ui_sb_menu_command(int idm, int tag) break; case IDM_CDROM_HOST_DRIVE: - drive = tag & 0x0007; + drive = tag & 0x07; i = ((tag >> 3) & 0x001f) + 'A'; part = find_tag(SB_CDROM | drive); if (part == -1) break; @@ -914,14 +875,20 @@ ui_sb_menu_command(int idm, int tag) break; } cdrom_drives[drive].prev_host_drive = cdrom_drives[drive].host_drive; - cdrom_drives[drive].handler->exit(drive); - cdrom_close(drive); + + /* Close the current drive/pathname. */ + cdrom[drive]->handler->exit(drive); + cdrom_close_handler(drive); + memset(cdrom_image[drive].image_path, 0, sizeof(cdrom_image[drive].image_path)); + #ifdef USE_CDROM_IOCTL ioctl_open(drive, new_cdrom_drive); #endif /* Signal media change to the emulated machine. */ - cdrom_insert(drive); + cdrom_insert(cdrom[drive]); + + /* Update stuff. */ sb_menu_set_item(part, IDM_CDROM_EMPTY | drive, 0); if ((cdrom_drives[drive].host_drive >= 'A') && (cdrom_drives[drive].host_drive <= 'Z')) { @@ -937,7 +904,7 @@ ui_sb_menu_command(int idm, int tag) break; case IDM_ZIP_IMAGE_NEW: - drive = tag & 0x0003; + drive = tag & 0x03; part = find_tag(SB_ZIP | drive); if (part == -1) break; @@ -945,76 +912,67 @@ ui_sb_menu_command(int idm, int tag) break; case IDM_ZIP_IMAGE_EXISTING: - drive = tag & 0x0003; + drive = tag & 0x03; part = find_tag(SB_ZIP | drive); if (part == -1) break; str = zip_drives[drive].image_path; i = dlg_file(get_string(IDS_3951), str, temp, DLG_FILE_LOAD); if (i) { - ui_sb_mount_zip(drive, part, - !!(i & DLG_FILE_RO), temp); + ui_zip_mount(drive, part, + !!(i & DLG_FILE_RO), temp); } break; case IDM_ZIP_EJECT: - drive = tag & 0x0003; - zip_eject(drive); + drive = tag & 0x03; + ui_zip_eject(drive); break; case IDM_ZIP_RELOAD: - drive = tag & 0x0003; - zip_reload(drive); + drive = tag & 0x03; + ui_zip_reload(drive); break; - case IDM_RDISK_EJECT: - drive = tag & 0x001f; - removable_disk_eject(drive); + case IDM_DISK_NOTIFY: + drive = tag & 0x0f; +#if 0 + disk_insert(drive); +#endif break; - case IDM_RDISK_RELOAD: - drive = tag & 0x001f; - removable_disk_reload(drive); + case IDM_DISK_IMAGE_NEW: + drive = tag & 0x0f; + part = find_tag(SB_DISK | drive); + if (part == -1) break; + + dlg_new_image(drive, part, 1); break; - case IDM_RDISK_SEND_CHANGE: - drive = tag & 0x001f; - scsi_disk_insert(drive); - break; - - case IDM_RDISK_IMAGE: - drive = tag & 0x001f; - part = find_tag(idm | drive); + case IDM_DISK_IMAGE_EXISTING: + drive = tag & 0x0f; + part = find_tag(SB_DISK | drive); + if (part == -1) break; str = hdd[drive].fn; i = dlg_file(get_string(IDS_3536), str, temp, DLG_FILE_LOAD); if (! i) break; - removable_disk_unload(drive); - - memset(hdd[drive].fn, 0x00, sizeof(hdd[drive].fn)); - wcscpy(hdd[drive].fn, temp); - hdd[drive].wp = !!(i & DLG_FILE_RO); - - scsi_loadhd(hdd[drive].id.scsi.id, hdd[drive].id.scsi.lun, drive); - scsi_disk_insert(drive); - - if (wcslen(hdd[drive].fn) > 0) { - ui_sb_icon_state(SB_RDISK | drive, 0); - sb_menu_enable_item(part, IDM_RDISK_EJECT | drive, 1); - sb_menu_enable_item(part, IDM_RDISK_RELOAD | drive, 0); - sb_menu_enable_item(part, IDM_RDISK_SEND_CHANGE | drive, 0); - } else { - ui_sb_icon_state(SB_RDISK | drive, 1); - sb_menu_enable_item(part, IDM_RDISK_EJECT | drive, 0); - sb_menu_enable_item(part, IDM_RDISK_RELOAD | drive, 0); - sb_menu_enable_item(part, IDM_RDISK_SEND_CHANGE | drive, 0); - } - ui_sb_tip_update(SB_RDISK | drive); - config_save(); + ui_disk_mount(drive, part, !!(i & DLG_FILE_RO), temp); break; - default: + case IDM_DISK_EJECT: + drive = tag & 0x0f; +#if 0 + ui_disk_eject(drive); +#endif + break; + + case IDM_DISK_RELOAD: + drive = tag & 0x0f; +#if 0 + ui_disk_reload(drive); +#endif break; } } @@ -1024,9 +982,9 @@ ui_sb_menu_command(int idm, int tag) void ui_sb_click(int part) { - if (part >= sb_parts) return; + if (part >= sb_nparts) return; - switch(sb_tags[part] & 0xf0) { + switch(sb_parts[part].tag & 0xf0) { case SB_SOUND: dlg_sound_gain(); break; @@ -1034,46 +992,21 @@ ui_sb_click(int part) } +/* Handle a keyboard state change. */ void -ui_sb_mount_floppy(uint8_t drive, int part, int8_t wp, const wchar_t *fn) +ui_sb_kbstate(int flags) { - int len; + int part; - fdd_close(drive); + part = find_tag(SB_NUMLK); + if (flags & KBD_FLAG_NUM) + sb_set_text(part, L"NUM"); + else + sb_set_text(part, L""); - ui_writeprot[drive] = wp; - fdd_load(drive, fn); - - len = wcslen(floppyfns[drive]); - ui_sb_icon_state(SB_FLOPPY | drive, len ? 0 : 1); - - sb_menu_enable_item(part, IDM_FLOPPY_EJECT | drive, len ? 1 : 0); - sb_menu_enable_item(part, IDM_FLOPPY_EXPORT_TO_86F | drive, len ? 1 : 0); - - ui_sb_tip_update(SB_FLOPPY | drive); - - config_save(); -} - - -void -ui_sb_mount_zip(uint8_t drive, int part, int8_t wp, const wchar_t *fn) -{ - int len; - - zip_close(drive); - - zip_drives[drive].ui_writeprot = wp; - zip_load(drive, fn); - zip_insert(drive); - - len = wcslen(zip_drives[drive].image_path); - ui_sb_icon_state(SB_ZIP | drive, len ? 0 : 1); - - sb_menu_enable_item(part, IDM_ZIP_EJECT | drive, len ? 1 : 0); - sb_menu_enable_item(part, IDM_ZIP_RELOAD | drive, len ? 0 : 1); - - ui_sb_tip_update(SB_ZIP | drive); - - config_save(); + part = find_tag(SB_CAPLK); + if (flags & KBD_FLAG_CAPS) + sb_set_text(part, L"CAPS"); + else + sb_set_text(part, L""); } diff --git a/src/ui/ui_vidapi.c b/src/ui/ui_vidapi.c index d54919b..b747787 100644 --- a/src/ui/ui_vidapi.c +++ b/src/ui/ui_vidapi.c @@ -8,7 +8,7 @@ * * Handle the various video renderer modules. * - * Version: @(#)ui_vidapi.c 1.0.2 2018/05/13 + * Version: @(#)ui_vidapi.c 1.0.3 2018/09/26 * * Author: Fred N. van Kempen, * @@ -63,8 +63,8 @@ vidapi_available(int api) { int ret = 1; - if (plat_vidapis[api]->available != NULL) - ret = plat_vidapis[api]->available(); + if (plat_vidapis[api]->is_available != NULL) + ret = plat_vidapis[api]->is_available(); return(ret); } @@ -109,7 +109,7 @@ vidapi_set(int api) { int i; - pclog("Initializing VIDAPI: api=%d\n", api); + INFO("Initializing VIDAPI: api=%d\n", api); /* Lock the blitter. */ plat_startblit(); @@ -189,7 +189,8 @@ vidapi_screenshot(void) struct tm *info; time_t now; - pclog("Screenshot: video API is: %i\n", vid_api); + DEBUG("Screenshot: video API is: %i\n", vid_api); + if (vid_api < 0) return; (void)time(&now); @@ -201,7 +202,7 @@ vidapi_screenshot(void) if (! plat_dir_check(path)) plat_dir_create(path); - wcscat(path, L"\\"); + plat_append_slash(path); wcsftime(fn, sizeof_w(fn), L"%Y%m%d_%H%M%S.png", info); wcscat(path, fn); diff --git a/src/version.h b/src/version.h index 718a3fe..3e96354 100644 --- a/src/version.h +++ b/src/version.h @@ -8,7 +8,7 @@ * * Define application version and build info. * - * Version: @(#)version.h 1.0.20 2018/09/22 + * Version: @(#)version.h 1.0.20 2018/10/05 * * Author: Fred N. van Kempen, * @@ -52,10 +52,10 @@ #define EMU_NAME "VARCem" /* Version info. */ -#define EMU_VER_MAJOR 0 -#define EMU_VER_MINOR 1 -#define EMU_VER_REV 6 -#define EMU_VER_PATCH 6 +#define EMU_VER_MAJOR 1 +#define EMU_VER_MINOR 7 +#define EMU_VER_REV 0 +//#define EMU_VER_PATCH 0 /* Standard C preprocessor macros. */ @@ -66,7 +66,7 @@ /* These are used in the application. */ #define EMU_VER_NUM EMU_VER_MAJOR.EMU_VER_MINOR.EMU_VER_REV -#ifdef EMU_VER_PATCH +#if defined(EMU_VER_PATCH) && EMU_VER_PATCH > 0 # define EMU_VER_NUM_4 EMU_VER_MAJOR.EMU_VER_MINOR.EMU_VER_REV.EMU_VER_PATCH #else # define EMU_VER_NUM_4 EMU_VER_MAJOR.EMU_VER_MINOR.EMU_VER_REV.0 diff --git a/src/vnc.c b/src/vnc.c index 9560a40..0de3a44 100644 --- a/src/vnc.c +++ b/src/vnc.c @@ -8,9 +8,9 @@ * * Implement the VNC remote renderer with LibVNCServer. * - * TODO: Implement screenshots, and maybe Audio? + * TODO: Implement screenshots, and Audio Redirection. * - * Version: @(#)vnc.c 1.0.5 2018/08/27 + * Version: @(#)vnc.c 1.0.7 2018/10/05 * * Author: Fred N. van Kempen, * Based on raw code by RichardG, @@ -50,6 +50,7 @@ #include #include #include +#include #include #include #include @@ -119,11 +120,36 @@ static dllimp_t vnc_imports[] = { }; +/* Local handlers for VNCserver event logging. */ static void -vnc_kbdevent(rfbBool down, rfbKeySym k, rfbClientPtr cl) +vnc_dbglog(const char *fmt, ...) { - (void)cl; + char temp[1024]; + va_list ap; + va_start(ap, fmt); + vsprintf(temp, fmt, ap); + va_end(ap); + pclog(LOG_INFO, "VNC: %s", temp); +} + + +static void +vnc_errlog(const char *fmt, ...) +{ + char temp[1024]; + va_list ap; + + va_start(ap, fmt); + vsprintf(temp, fmt, ap); + va_end(ap); + pclog(LOG_ERR, "VNC: %s", temp); +} + + +static void +vnc_kbdevent(rfbBool down, rfbKeySym k, UNUSED(rfbClientPtr cl)) +{ /* Handle it through the lookup tables. */ vnc_kbinput(down?1:0, (int)k); } @@ -132,7 +158,7 @@ vnc_kbdevent(rfbBool down, rfbKeySym k, rfbClientPtr cl) static void vnc_ptrevent(int but, int x, int y, rfbClientPtr cl) { - if (x>=0 && x=0 && y= 0 && x < allowedX && y >= 0 && y < allowedY) { /* VNC uses absolute positions within the window, no deltas. */ if (x != ptr_x || y != ptr_y) { mouse_x += (x - ptr_x); @@ -159,18 +185,18 @@ vnc_ptrevent(int but, int x, int y, rfbClientPtr cl) static void vnc_clientgone(rfbClientPtr cl) { - pclog("VNC: client disconnected: %s\n", cl->host); + vnc_dbglog("client disconnected: %s\n", cl->host); if (clients > 0) clients--; if (clients == 0) { /* No more clients, pause the emulator. */ - pclog("VNC: no clients, pausing..\n"); + vnc_dbglog("no more clients, pausing..\n"); /* Disable the mouse. */ plat_mouse_capture(0); - plat_pause(1); + pc_pause(1); } } @@ -181,7 +207,7 @@ vnc_newclient(rfbClientPtr cl) /* Hook the ClientGone function so we know when they're gone. */ cl->clientGoneHook = vnc_clientgone; - pclog("VNC: new client: %s\n", cl->host); + vnc_dbglog("new client: %s\n", cl->host); if (++clients == 1) { /* Reset the mouse. */ ptr_x = allowedX/2; @@ -190,12 +216,12 @@ vnc_newclient(rfbClientPtr cl) mouse_buttons = 0x00; /* We now have clients, un-pause the emulator if needed. */ - pclog("VNC: unpausing..\n"); + vnc_dbglog("unpausing..\n"); /* Enable the mouse. */ plat_mouse_capture(1); - plat_pause(0); + pc_pause(0); } /* For now, we always accept clients. */ @@ -224,11 +250,15 @@ vnc_blit(int x, int y, int y1, int y2, int w, int h) uint32_t *p; int yy; - for (yy=y1; yyframeBuffer)[yy*VNC_MAX_X]); - if ((y+yy) >= 0 && (y+yy) < VNC_MAX_Y) - memcpy(p, &(((uint32_t *)buffer32->line[y+yy])[x]), w*4); + if ((y+yy) >= 0 && (y+yy) < VNC_MAX_Y) { + if (vid_grayscale || invert_display) + video_transform_copy(p, &(((uint32_t *)buffer32->line[y+yy])[x]), w); + else + memcpy(p, &(((uint32_t *)buffer32->line[y+yy])[x]), w*4); + } } video_blit_complete(); @@ -255,20 +285,33 @@ vnc_init(int fs) */ 32, 32, 0, 1, 255,255,255, 16, 8, 0, 0, 0 }; + wchar_t temp[512]; + const char *fn = PATH_VNC_DLL; /* We do not support fullscreen, folks. */ if (fs) { - pclog("VNC: fullscreen mode is not supported!\n"); + vnc_errlog("fullscreen mode is not supported!\n"); return(0); } /* Try loading the DLL. */ - vnc_handle = dynld_module(PATH_VNC_DLL, vnc_imports); + vnc_handle = dynld_module(fn, vnc_imports); if (vnc_handle == NULL) { - pclog("VNC: unable to load '%s', VNC not available.\n", PATH_VNC_DLL); + swprintf(temp, sizeof_w(temp), + get_string(IDS_ERR_NOLIB), "VNCserver", fn); + ui_msgbox(MBX_ERROR, temp); + vnc_errlog("unable to load '%s', VNC not available.\n", fn); return(0); } +#ifdef _WIN32 + //FIXME: these are defined in Linux version, but not present.. --FvK + /* Set up and enable VNC server logging. */ + rfbLog = vnc_dbglog; + rfbErr = vnc_errlog; + rfbLogEnable(1); +#endif + cgapal_rebuild(); if (rfb == NULL) { @@ -279,7 +322,7 @@ vnc_init(int fs) rfb = f_rfbGetScreen(0, NULL, VNC_MAX_X, VNC_MAX_Y, 8, 3, 4); rfb->desktopName = title; - rfb->frameBuffer = (char *)malloc(VNC_MAX_X*VNC_MAX_Y*4); + rfb->frameBuffer = (char *)mem_alloc(VNC_MAX_X*VNC_MAX_Y*4); rfb->serverFormat = rpf; rfb->alwaysShared = TRUE; @@ -302,7 +345,7 @@ vnc_init(int fs) clients = 0; - pclog("VNC: init complete.\n"); + vnc_dbglog("init complete.\n"); return(1); } @@ -339,12 +382,12 @@ vnc_resize(int x, int y) /* TightVNC doesn't like certain sizes.. */ if (x < VNC_MIN_X || x > VNC_MAX_X || y < VNC_MIN_Y || y > VNC_MAX_Y) { - pclog("VNC: invalid resoltion %dx%d requested!\n", x, y); + vnc_errlog("invalid resoltion %ix%i requested!\n", x, y); return; } if ((x != rfb->width || y != rfb->height) && x > 160 && y > 0) { - pclog("VNC: updating resolution: %dx%d\n", x, y); + vnc_dbglog("updating resolution: %dx%d\n", x, y); allowedX = (rfb->width < x) ? rfb->width : x; allowedY = (rfb->width < y) ? rfb->width : y; @@ -373,7 +416,7 @@ vnc_pause(void) static void vnc_screenshot(const wchar_t *fn) { - pclog("VNC: take_screenshot\n"); + vnc_dbglog("take_screenshot\n"); } diff --git a/src/vnc_keymap.c b/src/vnc_keymap.c index af9afc0..a583e6e 100644 --- a/src/vnc_keymap.c +++ b/src/vnc_keymap.c @@ -22,7 +22,7 @@ * NOTE: The values are as defined in the Microsoft document named * "Keyboard Scan Code Specification", v1.3a of 2000/03/16. * - * Version: @(#)vnc_keymap.c 1.0.3 2018/05/06 + * Version: @(#)vnc_keymap.c 1.0.4 2018/10/05 * * Author: Fred N. van Kempen, * Based on raw code by RichardG, @@ -656,9 +656,7 @@ vnc_kbinput(int down, int k) { uint16_t scan; -#if 0 - pclog("VNC: kbinput %d %04x\n", down, k); -#endif + DEBUG("VNC: kbinput %d %04x\n", down, k); switch(k >> 8) { case 0x00: /* page 00, Latin-1 */ @@ -670,17 +668,16 @@ vnc_kbinput(int down, int k) break; default: - pclog("VNC: unhandled Xkbd page: %02x\n", k>>8); + ERRLOG("VNC: unhandled Xkbd page: %02x\n", k>>8); return; } if (scan == 0x0000) { - pclog("VNC: unhandled Xkbd key: %d (%04x)\n", k, k); + ERRLOG("VNC: unhandled Xkbd key: %d (%04x)\n", k, k); return; + } else { + DEBUG("VNC: translated to %02x %02x\n", (scan>>8)&0xff, scan&0xff); } -#if 0 - else pclog("VNC: translated to %02x %02x\n", (scan>>8)&0xff, scan&0xff); -#endif /* Send this scancode sequence to the PC keyboard. */ keyboard_input(down, scan); diff --git a/src/win/VARCem-common.rc b/src/win/VARCem-common.rc index 0352591..5d3d56b 100644 --- a/src/win/VARCem-common.rc +++ b/src/win/VARCem-common.rc @@ -8,7 +8,7 @@ * * Common resources for the application. * - * Version: @(#)VARCem-common.rc 1.0.10 2018/09/23 + * Version: @(#)VARCem-common.rc 1.0.10 2018/10/01 * * Author: Fred N. van Kempen, * @@ -98,8 +98,6 @@ BEGIN MENUITEM STR_4044,IDM_STRETCH_INT MENUITEM STR_4045,IDM_STRETCH_KEEP END - MENUSEPARATOR - MENUITEM STR_4015,IDM_UPDATE_ICONS END POPUP STR_DISPLAY @@ -133,24 +131,23 @@ BEGIN MENUSEPARATOR END MENUSEPARATOR -#ifdef ENABLE_LOGGING +#ifdef _LOGGING POPUP STR_4083,IDM_LOGGING BEGIN MENUITEM "&Log breakpoint\tCtrl+Insert", IDM_LOG_BREAKPOINT MENUSEPARATOR END #endif - MENUITEM STR_4084,IDM_LOAD - MENUITEM STR_4085,IDM_SAVE + MENUITEM STR_4086,IDM_LOAD + MENUITEM STR_4087,IDM_SAVE MENUSEPARATOR - MENUITEM STR_4086,IDM_STATUS - MENUSEPARATOR - MENUITEM STR_4087,IDM_SCREENSHOT + MENUITEM STR_4088,IDM_SCREENSHOT END POPUP STR_HELP BEGIN MENUITEM STR_4091,IDM_ABOUT + MENUITEM STR_LOCALIZE,IDM_LOCALIZE END END @@ -188,8 +185,7 @@ BEGIN CTEXT "",IDT_TITLE,55,5,195,20 - CTEXT "Virtual ARchaeological Computer EMulator", - IDC_ABOUT_ICON,55,22,195,10 + CTEXT STR_TITLE,IDC_ABOUT_ICON,55,22,195,10 CTEXT "",IDT_VERSION,55,33,195,10 CONTROL "",IDC_ABOUT_ICON,"Static", @@ -208,14 +204,6 @@ BEGIN CONTROL "",IDC_DONATE,"Static",SS_BITMAP|SS_NOTIFY,175,130,105,50 END -DLG_STATUS DIALOG 0, 0, 186, 386 -STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU -CAPTION STR_STATUS -FONT 9, FONT_NAME -BEGIN - LTEXT "1",IDT_SDEVICE,16,16,180,1000 - LTEXT "1",IDT_STEXT,16,186,180,1000 -END DLG_SND_GAIN DIALOG 0, 0, 113, 136 STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION @@ -232,6 +220,7 @@ BEGIN PUSHBUTTON STR_CANCEL,IDCANCEL,57,24,50,14 END + DLG_NEW_FLOPPY DIALOG 0, 0, 226, 95 STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION CAPTION STR_NEWIMG @@ -258,6 +247,7 @@ BEGIN PUSHBUTTON STR_CANCEL,IDCANCEL,130,75,50,14 END + DLG_CONFIG DIALOG 0, 0, 366, 251 STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION CAPTION STR_SETTINGS @@ -273,7 +263,7 @@ BEGIN PUSHBUTTON STR_CANCEL,IDCANCEL,307,230,50,14 END -DLG_CFG_MACHINE DIALOG 97, 0, 267, 114 +DLG_CFG_MACHINE DIALOG 97, 0, 267, 200 STYLE DS_CONTROL | WS_CHILD FONT 9, FONT_NAME BEGIN @@ -302,37 +292,34 @@ BEGIN 113,63,12,12 LTEXT STR_3330,IDT_1705,123,64,10,10 - CONTROL STR_3331,IDC_CHECK_SYNC,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,7,81,102,10 + LTEXT STR_3331,IDT_1708,7,81,60,10 + COMBOBOX IDC_COMBO_SYNC,71,80,100,120, + CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP CONTROL STR_3332,IDC_CHECK_FPU,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,147,81,113,10 + BS_AUTOCHECKBOX | WS_TABSTOP,7,96,113,10 #ifdef USE_DYNAREC CONTROL STR_3333,IDC_CHECK_DYNAREC,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,7,96,120,10 + BS_AUTOCHECKBOX | WS_TABSTOP,7,111,120,10 #endif END -DLG_CFG_VIDEO DIALOG 97, 0, 267, 63 +DLG_CFG_VIDEO DIALOG 97, 0, 267, 200 STYLE DS_CONTROL | WS_CHILD FONT 9, FONT_NAME BEGIN LTEXT STR_3350,IDT_1707,7,8,55,10 COMBOBOX IDC_COMBO_VIDEO,71,7,140,120, CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - PUSHBUTTON STR_CONFIGURE,IDC_CONFIGURE_VID,214,7,46,12 + PUSHBUTTON STR_CONFIGURE,IDC_CONFIGURE_VIDEO,214,7,46,12 - LTEXT STR_3351,IDT_1708,7,26,58,10 - COMBOBOX IDC_COMBO_VIDEO_SPEED,71,25,189,120, - CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - - CONTROL STR_3352,IDC_CHECK_VOODOO,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,7,45,199,10 - PUSHBUTTON STR_CONFIGURE,IDC_BUTTON_VOODOO,214,44,46,12 + CONTROL STR_3351,IDC_CHECK_VOODOO,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,7,27,199,10 + PUSHBUTTON STR_CONFIGURE,IDC_CONFIGURE_VOODOO,214,26,46,12 END -DLG_CFG_INPUT DIALOG 97, 0, 267, 65 +DLG_CFG_INPUT DIALOG 97, 0, 267, 200 STYLE DS_CONTROL | WS_CHILD FONT 9, FONT_NAME BEGIN @@ -344,21 +331,20 @@ BEGIN LTEXT STR_3376,IDT_1710,7,26,58,10 COMBOBOX IDC_COMBO_JOYSTICK,71,25,189,120, CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - - PUSHBUTTON STR_3377,IDC_JOY1,7,44,60,14 - PUSHBUTTON STR_3378,IDC_JOY2,72,44,60,14 - PUSHBUTTON STR_3379,IDC_JOY3,137,44,60,14 - PUSHBUTTON STR_3380,IDC_JOY4,202,44,60,14 + PUSHBUTTON STR_3377,IDC_CONFIGURE_JOY1,7,44,60,14 + PUSHBUTTON STR_3378,IDC_CONFIGURE_JOY2,72,44,60,14 + PUSHBUTTON STR_3379,IDC_CONFIGURE_JOY3,137,44,60,14 + PUSHBUTTON STR_3380,IDC_CONFIGURE_JOY4,202,44,60,14 END -DLG_CFG_SOUND DIALOG 97, 0, 267, 116 +DLG_CFG_SOUND DIALOG 97, 0, 267, 200 STYLE DS_CONTROL | WS_CHILD FONT 9, FONT_NAME BEGIN LTEXT STR_3400,IDT_1711,7,8,59,10 COMBOBOX IDC_COMBO_SOUND,71,7,140,120, CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - PUSHBUTTON STR_CONFIGURE,IDC_CONFIGURE_SND,214,7,46,12 + PUSHBUTTON STR_CONFIGURE,IDC_CONFIGURE_SOUND,214,7,46,12 LTEXT STR_3401,IDT_1712,7,26,59,10 COMBOBOX IDC_COMBO_MIDI,71,25,140,120, @@ -376,7 +362,7 @@ BEGIN BS_AUTOCHECKBOX | WS_TABSTOP,7,81,120,10 END -DLG_CFG_NETWORK DIALOG 97, 0, 267, 63 +DLG_CFG_NETWORK DIALOG 97, 0, 267, 200 STYLE DS_CONTROL | WS_CHILD FONT 9, FONT_NAME BEGIN @@ -389,12 +375,12 @@ BEGIN CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP LTEXT STR_3427,IDT_1715,7,44,59,10 - COMBOBOX IDC_COMBO_NET,71,43,140,120, + COMBOBOX IDC_COMBO_NET_CARD,71,43,140,120, CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - PUSHBUTTON STR_CONFIGURE,IDC_CONFIGURE_NET,214,43,46,14 + PUSHBUTTON STR_CONFIGURE,IDC_CONFIGURE_NET_CARD,214,43,46,14 END -DLG_CFG_PORTS DIALOG 97, 0, 267, 120 +DLG_CFG_PORTS DIALOG 97, 0, 267, 200 STYLE DS_CONTROL | WS_CHILD FONT 9, FONT_NAME BEGIN @@ -437,13 +423,13 @@ BEGIN CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP PUSHBUTTON STR_CONFIGURE,IDC_CONFIGURE_HDC,214,25,46,12 - LTEXT STR_3477,IDT_1718,7,44,61,10 - COMBOBOX IDC_COMBO_IDE_TER,71,43,189,120, - CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + CONTROL STR_3477,IDC_CHECK_IDE_TER,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,7,44,199,10 + PUSHBUTTON STR_CONFIGURE,IDC_CONFIGURE_IDE_TER,214,43,46,12 - LTEXT STR_3478,IDT_1719,7,62,61,10 - COMBOBOX IDC_COMBO_IDE_QUA,71,61,189,120, - CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + CONTROL STR_3478,IDC_CHECK_IDE_QUA,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,7,62,199,10 + PUSHBUTTON STR_CONFIGURE,IDC_CONFIGURE_IDE_QUA,214,61,46,12 CONTROL STR_3479,IDC_CHECK_BUGGER,"Button", BS_AUTOCHECKBOX | WS_TABSTOP,7,80,94,10 @@ -472,7 +458,7 @@ BEGIN PUSHBUTTON STR_CONFIGURE,IDC_CONFIGURE_ISAMEM_4,209,171,46,12 END -DLG_CFG_DISK DIALOG 97, 0, 267, 154 +DLG_CFG_DISK DIALOG 97, 0, 267, 200 STYLE DS_CONTROL | WS_CHILD FONT 9, FONT_NAME BEGIN @@ -551,7 +537,7 @@ BEGIN PUSHBUTTON STR_CANCEL,IDCANCEL,112,89,50,14 END -DLG_CFG_FLOPPY DIALOG 97, 0, 267, 103 +DLG_CFG_FLOPPY DIALOG 97, 0, 267, 200 STYLE DS_CONTROL | WS_CHILD FONT 9, FONT_NAME BEGIN @@ -626,250 +612,12 @@ BEGIN END -/* Common strings (2000.) */ -#ifdef STR_VERSION +/* The string table. */ +#define STRTBL(num,str) num str + STRINGTABLE BEGIN - IDS_VERSION STR_VERSION - IDS_AUTHOR STR_AUTHOR - IDS_EMAIL STR_EMAIL -END -#endif - -/* Messagebox classes (2100.) */ -STRINGTABLE -BEGIN - IDS_ERROR STR_2100 - IDS_FATAL_ERROR STR_2101 - IDS_CONFIG_ERROR STR_2102 - IDS_WARNING STR_2103 +#include "../ui/lang/VARCem.def" END -/* System errors (2200.) */ -STRINGTABLE -BEGIN - IDS_ERR_ACCEL STR_2200 - IDS_ERR_INPUT STR_2201 - IDS_ERR_PCAP STR_2202 - IDS_ERR_PCAP_NO STR_2203 - IDS_ERR_PCAP_DEV STR_2204 - IDS_ERR_OPENAL STR_2205 - IDS_ERR_FSYNTH STR_2206 - IDS_ERR_NOMEM STR_2207 -END - -/* Application error messages (2300.) */ -STRINGTABLE -BEGIN - IDS_ERR_SCRSHOT STR_2300 - IDS_ERR_NOROMS STR_2301 - IDS_ERR_NOCONF STR_2302 - IDS_ERR_NOMACH STR_2303 - IDS_ERR_NOVIDEO STR_2304 - IDS_ERR_NORENDR STR_2305 - IDS_ERR_NOCDROM STR_2306 - IDS_ERR_NO_USB STR_2307 - IDS_ERR_SAVEIT STR_2308 -END - -/* Application messages (2400.) */ -STRINGTABLE -BEGIN - IDS_MSG_SAVE STR_2400 - IDS_MSG_RESTART STR_2401 - IDS_MSG_UNSTABL STR_2402 - IDS_MSG_CAPTURE STR_2403 - IDS_MSG_MRLS_1 STR_2404 - IDS_MSG_MRLS_2 STR_2405 - IDS_MSG_WINDOW STR_2406 -END - -/* Misc application strings (2500.) */ -STRINGTABLE -BEGIN - IDS_2500 STR_2500 -END - - -/* UI: common elements (3000.) */ -STRINGTABLE -BEGIN - IDS_OK STR_OK - IDS_CANCEL STR_CANCEL - IDS_CONFIGURE STR_CONFIGURE - IDS_BROWSE STR_BROWSE -END - -/* UI: dialog shared strings (3100.) */ -STRINGTABLE -BEGIN - IDS_NONE STR_NONE - IDS_DISABLED STR_DISABLED - IDS_ENABLED STR_ENABLED - IDS_OFF STR_OFF - IDS_ON STR_ON - IDS_TYPE STR_TYPE - IDS_FILENAME STR_FILENAME - IDS_PROGRESS STR_PROGRESS - IDS_BUS STR_BUS - IDS_CHANNEL STR_CHANNEL - IDS_ID STR_ID - IDS_LUN STR_LUN - IDS_INV_NAME STR_INV_NAME - IDS_IMG_EXIST STR_IMG_EXIST - IDS_OPEN_READ STR_OPEN_READ - IDS_OPEN_WRITE STR_OPEN_WRITE -END - -/* UI: dialog: About (3200.) */ - -/* UI dialog: Status (3225.) */ - -/* UI dialog: Sound Gain (3250.) */ - -/* UI dialog: New Image (3275.) */ -STRINGTABLE -BEGIN - IDS_3278 STR_3278 - IDS_3279 STR_3279 - IDS_3280 STR_3280 - IDS_3281 STR_3281 - IDS_3282 STR_3282 - IDS_3283 STR_3283 - IDS_3284 STR_3284 - IDS_3285 STR_3285 - IDS_3286 STR_3286 - IDS_3287 STR_3287 - IDS_3288 STR_3288 - IDS_3289 STR_3289 - IDS_3290 STR_3290 - IDS_3291 STR_3291 - IDS_3292 STR_3292 - IDS_3293 STR_3293 - IDS_3294 STR_3294 - IDS_3295 STR_3295 -END - -/* UI dialog: Settings (3300.) */ -STRINGTABLE -BEGIN - IDS_3310 STR_3310 - IDS_3311 STR_3311 - IDS_3312 STR_3312 - IDS_3313 STR_3313 - IDS_3314 STR_3314 - IDS_3315 STR_3315 - IDS_3316 STR_3316 - IDS_3317 STR_3317 - IDS_3318 STR_3318 - IDS_3319 STR_3319 -END - -/* UI dialog: Settings (Machine, 3325.) */ -STRINGTABLE -BEGIN - IDS_3330 STR_3330 - IDS_3334 STR_3334 - IDS_3335 STR_3335 -END - -/* UI dialog: Settings (Video, 3350.) */ -STRINGTABLE -BEGIN - IDS_3353 STR_3353 - IDS_3354 STR_3354 - IDS_3355 STR_3355 - IDS_3356 STR_3356 - IDS_3357 STR_3357 - IDS_3358 STR_3358 - IDS_3359 STR_3359 -END - -/* UI dialog: Settings (Input, 3375.) */ - -/* UI dialog: Settings (Sound, 3400.) */ - -/* UI dialog: Settings (Network, 3425.) */ - -/* UI dialog: Settings (Ports, 3450.) */ - -/* UI dialog: Settings (Other Devices, 3475.) */ - -/* UI dialog: Settings (Hard Disks, 3500.) */ -STRINGTABLE -BEGIN - IDS_3504 STR_3504 - IDS_3505 STR_3505 - IDS_3506 STR_3506 - IDS_3507 STR_3507 - IDS_3508 STR_3508 - IDS_3509 STR_3509 - IDS_3510 STR_3510 - IDS_3511 STR_3511 - IDS_3512 STR_3512 - IDS_3515 STR_3515 - IDS_3516 STR_3516 - IDS_3517 STR_3517 - IDS_3518 STR_3518 - IDS_3519 STR_3519 - IDS_3520 STR_3520 -END - -/* UI dialog: Settings (Add Hard Disk, 3525.) */ -STRINGTABLE -BEGIN - IDS_3526 STR_3526 - IDS_3527 STR_3527 - IDS_3533 STR_3533 - IDS_3534 STR_3534 - IDS_3535 STR_3535 - IDS_3536 STR_3536 - IDS_3537 STR_3537 -END - -/* UI dialog: Settings (Floppy Drives, 3550.) */ -STRINGTABLE -BEGIN - IDS_3554 STR_3554 - IDS_3555 STR_3555 -END - -/* UI dialog: Settings (Removable Devices, 3575.) */ -STRINGTABLE -BEGIN - IDS_3579 STR_3579 - IDS_3580 STR_3580 - IDS_3581 STR_3581 - IDS_3582 STR_3582 - IDS_3583 STR_3583 - IDS_3584 STR_3584 -END - -/* UI dialog: status bar (3900.) */ -STRINGTABLE -BEGIN - IDS_3900 STR_3900 - IDS_3901 STR_3901 - IDS_3902 STR_3902 - IDS_3903 STR_3903 - IDS_3904 STR_3904 - IDS_3905 STR_3905 - IDS_3906 STR_3906 - IDS_3910 STR_3910 - IDS_3911 STR_3911 - IDS_3912 STR_3912 - IDS_3913 STR_3913 - IDS_3914 STR_3914 - IDS_3920 STR_3920 - IDS_3921 STR_3921 - IDS_3922 STR_3922 - IDS_3923 STR_3923 - IDS_3930 STR_3930 - IDS_3940 STR_3940 - IDS_3941 STR_3941 - IDS_3950 STR_3950 - IDS_3951 STR_3951 - IDS_3952 STR_3952 - IDS_3960 STR_3960 - IDS_3970 STR_3970 -END +/* End of file. */ diff --git a/src/win/VARCem.rc b/src/win/VARCem.rc index 54bf795..449469d 100644 --- a/src/win/VARCem.rc +++ b/src/win/VARCem.rc @@ -8,7 +8,7 @@ * * Application resource script for Windows. * - * Version: @(#)VARCem.rc 1.0.33 2018/06/16 + * Version: @(#)VARCem.rc 1.0.33 2018/09/27 * * Author: Fred N. van Kempen, * @@ -44,86 +44,85 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include #include #include "../emu.h" #include "../version.h" #include "../ui/ui.h" -#include "../plat.h" #include "resource.h" LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US -#include "../ui/lang/VARCem-EN.str" +#include "../ui/lang/VARCem.str" #include "VARCem-common.rc" MainAccel ACCELERATORS BEGIN -#ifdef ENABLE_BUS_LOG +#ifdef _LOGGING +# ifdef ENABLE_BUS_LOG VK_F1, IDM_LOG_BUS, VIRTKEY, CONTROL -#endif -#ifdef ENABLE_KEYBOARD_LOG - VK_F2, IDM_LOG_KEYBOARD, VIRTKEY, CONTROL -#endif -#ifdef ENABLE_MOUSE_LOG - VK_F3, IDM_LOG_MOUSE, VIRTKEY, CONTROL -#endif -#ifdef ENABLE_GAME_LOG - VK_F4, IDM_LOG_GAME, VIRTKEY, CONTROL -#endif -#ifdef ENABLE_PARALLEL_LOG - VK_F5, IDM_LOG_PARALLEL, VIRTKEY, CONTROL -#endif -#ifdef ENABLE_SERIAL_LOG - VK_F6, IDM_LOG_SERIAL, VIRTKEY, CONTROL -#endif -#ifdef ENABLE_FDC_LOG - VK_F7, IDM_LOG_FDC, VIRTKEY, CONTROL -#endif -#ifdef ENABLE_FDD_LOG - VK_F8, IDM_LOG_FDD, VIRTKEY, CONTROL -#endif -#ifdef ENABLE_D86F_LOG - VK_F9, IDM_LOG_D86F, VIRTKEY, CONTROL -#endif -#ifdef ENABLE_HDC_LOG - VK_F10, IDM_LOG_HDC, VIRTKEY, CONTROL -#endif -#ifdef ENABLE_HDD_LOG - VK_F11, IDM_LOG_HDD, VIRTKEY, CONTROL -#endif -#ifdef ENABLE_ZIP_LOG - VK_F12, IDM_LOG_ZIP, VIRTKEY, CONTROL -#endif -#ifdef ENABLE_CDROM_LOG - VK_F1, IDM_LOG_CDROM, VIRTKEY, CONTROL -#endif -#ifdef ENABLE_CDROM_IMAGE_LOG - VK_F2, IDM_LOG_CDROM_IMAGE, VIRTKEY, CONTROL -#endif -#ifdef ENABLE_CDROM_IOCTL_LOG - VK_F3, IDM_LOG_CDROM_IOCTL, VIRTKEY, CONTROL -#endif -#ifdef ENABLE_NETWORK_LOG - VK_F4, IDM_LOG_NETWORK, VIRTKEY, CONTROL -#endif -#ifdef ENABLE_NETWORK_DEV_LOG - VK_F5, IDM_LOG_NETWORK_DEV, VIRTKEY, CONTROL -#endif -# ifdef ENABLE_EMU8K_LOG - VK_F6, IDM_LOG_SOUND_EMU8K, VIRTKEY, CONTROL, ALT # endif -# ifdef ENABLE_MPU401_LOG - VK_F7, IDM_LOG_SOUND_MPU401, VIRTKEY, CONTROL, ALT +# ifdef ENABLE_KEYBOARD_LOG + VK_F2, IDM_LOG_KEYBOARD, VIRTKEY, CONTROL +# endif +# ifdef ENABLE_MOUSE_LOG + VK_F3, IDM_LOG_MOUSE, VIRTKEY, CONTROL +# endif +# ifdef ENABLE_GAME_LOG + VK_F4, IDM_LOG_GAME, VIRTKEY, CONTROL +# endif +# ifdef ENABLE_PARALLEL_LOG + VK_F5, IDM_LOG_PARALLEL, VIRTKEY, CONTROL +# endif +# ifdef ENABLE_SERIAL_LOG + VK_F6, IDM_LOG_SERIAL, VIRTKEY, CONTROL +# endif +# ifdef ENABLE_FDC_LOG + VK_F7, IDM_LOG_FDC, VIRTKEY, CONTROL +# endif +# ifdef ENABLE_FDD_LOG + VK_F8, IDM_LOG_FDD, VIRTKEY, CONTROL +# endif +# ifdef ENABLE_D86F_LOG + VK_F9, IDM_LOG_D86F, VIRTKEY, CONTROL +# endif +# ifdef ENABLE_HDC_LOG + VK_F10, IDM_LOG_HDC, VIRTKEY, CONTROL +# endif +# ifdef ENABLE_HDD_LOG + VK_F11, IDM_LOG_HDD, VIRTKEY, CONTROL +# endif +# ifdef ENABLE_ZIP_LOG + VK_F12, IDM_LOG_ZIP, VIRTKEY, CONTROL +# endif +# ifdef ENABLE_CDROM_LOG + VK_F1, IDM_LOG_CDROM, VIRTKEY, CONTROL +# endif +# ifdef ENABLE_CDROM_IMAGE_LOG + VK_F2, IDM_LOG_CDROM_IMAGE, VIRTKEY, CONTROL +# endif +# ifdef ENABLE_CDROM_IOCTL_LOG + VK_F3, IDM_LOG_CDROM_IOCTL, VIRTKEY, CONTROL +# endif +# ifdef ENABLE_NETWORK_LOG + VK_F4, IDM_LOG_NETWORK, VIRTKEY, CONTROL +# endif +# ifdef ENABLE_NETWORK_DEV_LOG + VK_F5, IDM_LOG_NETWORK_DEV, VIRTKEY, CONTROL +# endif +# ifdef ENABLE_SOUND_LOG + VK_F6, IDM_LOG_SOUND, VIRTKEY, CONTROL, ALT +# endif +# ifdef ENABLE_SOUND_MIDI_LOG + VK_F7, IDM_LOG_SOUND_MIDI, VIRTKEY, CONTROL, ALT # endif # ifdef ENABLE_SOUND_DEV_LOG VK_F8, IDM_LOG_SOUND_DEV, VIRTKEY, CONTROL, ALT # endif -# ifdef ENABLE_SCSI_BUS_LOG - VK_F9, IDM_LOG_SCSI_BUS, VIRTKEY, CONTROL, ALT +# ifdef ENABLE_SCSI_LOG + VK_F9, IDM_LOG_SCSI, VIRTKEY, CONTROL, ALT # endif # ifdef ENABLE_SCSI_DISK_LOG VK_F10, IDM_LOG_SCSI_DISK, VIRTKEY, CONTROL, ALT @@ -131,12 +130,13 @@ BEGIN # ifdef ENABLE_SCSI_DEV_LOG VK_F11, IDM_LOG_SCSI_DEV, VIRTKEY, CONTROL, ALT # endif -# ifdef ENABLE_VOODOO_LOG - VK_F12, IDM_LOG_VOODOO, VIRTKEY, CONTROL, ALT +# ifdef ENABLE_VIDEO_LOG + VK_F12, IDM_LOG_VIDEO, VIRTKEY, CONTROL, ALT # endif -#ifdef ENABLE_LOG_BREAKPOINT +# ifdef ENABLE_LOG_BREAKPOINT VK_INSERT, IDM_LOG_BREAKPOINT, VIRTKEY, CONTROL +# endif #endif VK_PRIOR,IDM_FULLSCREEN, VIRTKEY, CONTROL, ALT VK_HOME, IDM_SCREENSHOT, VIRTKEY, CONTROL @@ -144,60 +144,52 @@ BEGIN END -100 ICON "icons/varcem.ico" +ICON_MAIN ICON "icons/varcem.ico" #if 1 -101 BITMAP "icons/donate-button-blue-128x55.bmp" +ICON_DONATE BITMAP "icons/donate-button-blue-128x55.bmp" #else -101 ICON "icons/paypal.ico" +ICON_DONATE ICON "icons/paypal.ico" #endif -128 ICON "icons/floppy_525.ico" -384 ICON "icons/floppy_525_empty.ico" -129 ICON "icons/floppy_525_active.ico" -385 ICON "icons/floppy_525_empty_active.ico" -144 ICON "icons/floppy_35.ico" -145 ICON "icons/floppy_35_active.ico" -400 ICON "icons/floppy_35_empty.ico" -401 ICON "icons/floppy_35_empty_active.ico" +ICON_FLOPPY_525 ICON "icons/floppy_525.ico" +ICON_FLOPPY_525_E ICON "icons/floppy_525_empty.ico" +ICON_FLOPPY_525_A ICON "icons/floppy_525_active.ico" +ICON_FLOPPY_525_I ICON "icons/floppy_525_empty_active.ico" +ICON_FLOPPY_35 ICON "icons/floppy_35.ico" +ICON_FLOPPY_35_E ICON "icons/floppy_35_empty.ico" +ICON_FLOPPY_35_A ICON "icons/floppy_35_active.ico" +ICON_FLOPPY_35_I ICON "icons/floppy_35_empty_active.ico" -160 ICON "icons/cdrom.ico" -161 ICON "icons/cdrom_active.ico" -416 ICON "icons/cdrom_empty.ico" -417 ICON "icons/cdrom_empty_active.ico" +ICON_CDROM ICON "icons/cdrom.ico" +ICON_CDROM_E ICON "icons/cdrom_empty.ico" +ICON_CDROM_A ICON "icons/cdrom_active.ico" +ICON_CDROM_I ICON "icons/cdrom_empty_active.ico" -176 ICON "icons/zip.ico" -177 ICON "icons/zip_active.ico" -432 ICON "icons/zip_empty.ico" -433 ICON "icons/zip_empty_active.ico" +ICON_ZIP ICON "icons/zip.ico" +ICON_ZIP_E ICON "icons/zip_empty.ico" +ICON_ZIP_A ICON "icons/zip_active.ico" +ICON_ZIP_I ICON "icons/zip_empty_active.ico" -192 ICON "icons/removable_disk.ico" -193 ICON "icons/removable_disk_active.ico" -448 ICON "icons/removable_disk_empty.ico" -449 ICON "icons/removable_disk_empty_active.ico" +ICON_DISK ICON "icons/hard_disk.ico" +ICON_DISK_A ICON "icons/hard_disk_active.ico" -208 ICON "icons/hard_disk.ico" -209 ICON "icons/hard_disk_active.ico" +ICON_NETWORK ICON "icons/network.ico" +ICON_NETWORK_A ICON "icons/network_active.ico" -224 ICON "icons/network.ico" -225 ICON "icons/network_active.ico" +ICON_MACHINE ICON "icons/machine.ico" +ICON_DISPLAY ICON "icons/display.ico" +ICON_INPDEV ICON "icons/input_devices.ico" +ICON_SOUND ICON "icons/sound.ico" +ICON_PORTS ICON "icons/ports.ico" +ICON_PERIPH ICON "icons/other_peripherals.ico" +ICON_FLOPPY ICON "icons/floppy_drives.ico" +ICON_REMOV ICON "icons/other_removable_devices.ico" -256 ICON "icons/machine.ico" -257 ICON "icons/display.ico" -258 ICON "icons/input_devices.ico" -259 ICON "icons/sound.ico" -260 ICON "icons/network.ico" -261 ICON "icons/ports.ico" -262 ICON "icons/other_peripherals.ico" -263 ICON "icons/hard_disk.ico" -264 ICON "icons/floppy_drives.ico" -265 ICON "icons/other_removable_devices.ico" +ICON_FLOPPY_D ICON "icons/floppy_disabled.ico" +ICON_CDROM_D ICON "icons/cdrom_disabled.ico" +ICON_ZIP_D ICON "icons/zip_disabled.ico" -512 ICON "icons/floppy_disabled.ico" -514 ICON "icons/cdrom_disabled.ico" -515 ICON "icons/zip_disabled.ico" - - -1 RT_MANIFEST "VARCem.manifest" +1 RT_MANIFEST "VARCem.manifest" VS_VERSION_INFO VERSIONINFO @@ -239,12 +231,12 @@ VS_VERSION_INFO VERSIONINFO VALUE "ProductName", "VARCem Emulator" VALUE "ProductVersion", EMU_VERSION #ifndef RELEASE_BUILD - VALUE "SpecialBuild", "Internal Development Build" + VALUE "SpecialBuild", "Development Build" #endif END END BLOCK "VarFileInfo" BEGIN - VALUE "Translation", 0x409, 65001 + VALUE "Translation", 0x0409, 65001 END END diff --git a/src/win/VARCem.rpp b/src/win/VARCem.rpp index 6c5188a..fd2ffa5 100644 --- a/src/win/VARCem.rpp +++ b/src/win/VARCem.rpp @@ -10,7 +10,7 @@ * which require some weird processing. This file allows us * to use a single master for all those languages. * - * Version: @(#)VARCem.rpp 1.0.1 2018/06/19 + * Version: @(#)VARCem.rpp 1.0.2 2018/09/26 * * Author: Fred N. van Kempen, * @@ -80,8 +80,8 @@ PREAMBLE #include "VARCem-common.rc" PREAMBLE #pragma code_page(DEFAULT) VS_VERSION_INFO VERSIONINFO - FILEVERSION TAG_VERSION,0 - PRODUCTVERSION TAG_VERSION,0 + FILEVERSION STR_VERSION,0 + PRODUCTVERSION STR_VERSION,0 FILEFLAGSMASK 0x3fL FILEFLAGS 0x0L FILEOS VOS_NT_WINDOWS32 @@ -94,13 +94,13 @@ VS_VERSION_INFO VERSIONINFO BEGIN VALUE "CompanyName", "IRC #VARCem on FreeNode" VALUE "FileDescription", "VARCem Language Module" - VALUE "FileVersion", STR(TAG_VERSION) + VALUE "FileVersion", STR(STR_VERSION) VALUE "InternalName", EMU_NAME VALUE "LegalCopyright", "Copyright 2018 The VARCem Team" VALUE "OriginalFilename", DLLNAME(LANG) VALUE "ProductName", "VARCem Emulator" VALUE "ProductVersion", EMU_VERSION - VALUE "Comments", STR_RC(TAG_AUTHOR,TAG_EMAIL) + VALUE "Comments", STR_RC(STR_AUTHOR,STR_EMAIL) END END BLOCK "VarFileInfo" diff --git a/src/win/icons/removable_disk.ico b/src/win/icons/removable_disk.ico deleted file mode 100644 index 6f67d6a..0000000 Binary files a/src/win/icons/removable_disk.ico and /dev/null differ diff --git a/src/win/icons/removable_disk_active.ico b/src/win/icons/removable_disk_active.ico deleted file mode 100644 index bfbc370..0000000 Binary files a/src/win/icons/removable_disk_active.ico and /dev/null differ diff --git a/src/win/icons/removable_disk_empty.ico b/src/win/icons/removable_disk_empty.ico deleted file mode 100644 index 09229f5..0000000 Binary files a/src/win/icons/removable_disk_empty.ico and /dev/null differ diff --git a/src/win/icons/removable_disk_empty_active.ico b/src/win/icons/removable_disk_empty_active.ico deleted file mode 100644 index 4fcd2eb..0000000 Binary files a/src/win/icons/removable_disk_empty_active.ico and /dev/null differ diff --git a/src/win/mingw/Makefile.MinGW b/src/win/mingw/Makefile.MinGW index 0d0a89d..b899566 100644 --- a/src/win/mingw/Makefile.MinGW +++ b/src/win/mingw/Makefile.MinGW @@ -8,7 +8,7 @@ # # Makefile for Windows systems using the MinGW32 environment. # -# Version: @(#)Makefile.mingw 1.0.60 2018/09/19 +# Version: @(#)Makefile.mingw 1.0.60 2018/10/05 # # Author: Fred N. van Kempen, # @@ -68,6 +68,9 @@ endif ifndef DEBUG DEBUG := n endif +ifndef LOGGING + LOGGING := n +endif ifndef PROFILER PROFILER := n endif @@ -134,9 +137,6 @@ endif ifndef PAS16 PAS16 := n endif -ifndef STEALTH32 - STEALTH32 := n -endif ifndef XL24 XL24 := n endif @@ -160,6 +160,11 @@ endif ifeq ($(DEBUG), y) PROG := $(PROG)-d NETIF := $(NETIF)-d + LOGGING := y +else + ifeq ($(LOGGING), y) + PROG := $(PROG)-l + endif endif @@ -172,7 +177,6 @@ ifeq ($(DEV_BUILD), y) PORTABLE3 := y I686 := y PAS16 := y - STEALTH32 := y XL24 := y WONDER := y endif @@ -272,10 +276,12 @@ else endif DEPS = -MMD -MF $*.d -c $< -DEPFILE := win/.depends-mingw +DEPFILE := win/mingw/.depends # Set up the correct toolchain flags. -OPTS := $(EXTRAS) $(STUFF) +OPTS := $(EXTRAS) $(STUFF) \ + -D_CRT_NON_CONFORMING_SWPRINTFS \ + -D__USE_MINGW_ANSI_STDIO_X AFLAGS := -msse2 -mfpmath=sse RFLAGS := --input-format=rc -O coff LDFLAGS := @@ -333,6 +339,10 @@ endif ifeq ($(PROFILER), y) LDFLAGS += -Xlinker -Map=$(PROG).map endif +ifeq ($(LOGGING), y) + OPTS += -D_LOGGING + RFLAGS += -D_LOGGING +endif ifeq ($(CRASHDUMP), y) OPTS += -DUSE_CRASHDUMP endif @@ -356,7 +366,7 @@ endif LIBS := -mwindows \ -lddraw -ldinput8 -ldxguid -ld3d9 -ld3dx9 \ -lversion -lcomctl32 -lwinmm -LIBS += -lwsock32 -liphlpapi -lpsapi #-lpthread +LIBS += -lwsock32 -liphlpapi -lpsapi LIBS += -static -lstdc++ -lgcc ifneq ($(X64), y) LIBS += -Wl,--large-address-aware @@ -448,7 +458,7 @@ ifneq ($(VNC), n) endif endif ifeq ($(VNC), y) - LIBS += -lvncserver + LIBS += -lvncserver_shared #-static -lpthreads endif MISCOBJ += vnc.o vnc_keymap.o endif @@ -501,9 +511,8 @@ ifneq ($(WX), n) else UIOBJ := win_ui.o \ win_ddraw.o win_d3d.o $(SDLOBJ) $(D2DOBJ) \ - win_dialog.o win_about.o win_status.o \ - win_settings.o win_devconf.o win_snd_gain.o \ - win_new_image.o + win_dialog.o win_about.o win_settings.o \ + win_devconf.o win_snd_gain.o win_new_image.o endif @@ -527,7 +536,6 @@ ifeq ($(DEV_BRANCH), y) ifeq ($(I686), y) OPTS += -DUSE_I686 - DEVBROBJ += m_at_440fx.o endif ifeq ($(PAS16), y) @@ -535,11 +543,6 @@ ifeq ($(DEV_BRANCH), y) DEVBROBJ += snd_pas16.o endif - ifeq ($(STEALTH32), y) - OPTS += -DUSE_STEALTH32 - DEVBROBJ += vid_icd2061.o - endif - ifeq ($(WONDER), y) OPTS += -DUSE_WONDER endif @@ -576,7 +579,8 @@ CXXFLAGS := $(WX_FLAGS) $(OPTS) $(DFLAGS) $(COPTIM) $(AOPTIM) \ MAINOBJ := pc.o config.o misc.o random.o timer.o io.o mem.o \ rom.o rom_load.o device.o nvr.o -UIOBJ += ui_main.o ui_new_image.o ui_stbar.o ui_vidapi.o +UIOBJ += ui_main.o ui_lang.o ui_stbar.o ui_vidapi.o \ + ui_cdrom.o ui_new_image.o ui_misc.o SYSOBJ := dma.o nmi.o pic.o pit.o ppi.o pci.o mca.o mcr.o \ memregs.o nvr_at.o nvr_ps2.o @@ -601,13 +605,12 @@ MCHOBJ := machine.o machine_table.o \ m_at_opti495.o m_at_scat.o \ m_at_compaq.o m_at_wd76c10.o \ m_at_sis_85c471.o m_at_sis_85c496.o \ - m_at_430lx_nx.o m_at_430fx.o \ - m_at_430hx.o m_at_430vx.o + m_at_4x0.o INTELOBJ := intel.o \ intel_flash.o \ intel_sio.o \ - intel_piix.o intel_piix4.o + intel_piix.o DEVOBJ := bugger.o \ isamem.o isartc.o \ @@ -639,7 +642,8 @@ HDDOBJ := hdd.o \ hdc_ide_ata.o hdc_ide_xta.o hdc_xtide.o CDROMOBJ := cdrom.o \ - cdrom_dosbox.o cdrom_image.o cdrom_null.o + cdrom_null.o cdrom_speed.o \ + cdrom_dosbox.o cdrom_image.o ZIPOBJ := zip.o @@ -648,7 +652,7 @@ USBOBJ := usb.o endif SCSIOBJ := scsi.o \ - scsi_bus.o scsi_device.o \ + scsi_device.o \ scsi_disk.o \ scsi_x54x.o \ scsi_aha154x.o scsi_buslogic.o \ @@ -661,7 +665,8 @@ NETOBJ := network.o \ cksum.o ip_input.o queue.o tcp_input.o debug.o \ ip_output.o sbuf.o tcp_output.o udp.o if.o mbuf.o \ slirp.o tcp_subr.o \ - net_ne2000.o + net_dp8390.o \ + net_ne2000.o net_wd80x3.o net_3c503.o SNDOBJ := sound.o \ sound_dev.o \ @@ -689,7 +694,7 @@ SNDOBJ := sound.o \ VIDOBJ := video.o \ video_dev.o \ vid_cga.o vid_cga_comp.o \ - vid_compaq_cga.o \ + vid_cga_compaq.o \ vid_mda.o \ vid_hercules.o vid_herculesplus.o vid_incolor.o \ vid_colorplus.o \ @@ -701,7 +706,7 @@ VIDOBJ := video.o \ vid_ati_eeprom.o \ vid_ati18800.o vid_ati28800.o \ vid_ati_mach64.o vid_ati68860_ramdac.o \ - vid_ics2595.o \ + vid_bt48x_ramdac.o vid_icd2061.o vid_ics2595.o \ vid_cl54xx.o \ vid_et4000.o vid_sc1502x_ramdac.o \ vid_et4000w32.o vid_stg_ramdac.o \ @@ -716,8 +721,8 @@ VIDOBJ := video.o \ PLATOBJ := win.o \ win_lang.o win_dynld.o win_opendir.o win_thread.o \ - win_cdrom.o win_cdrom_ioctl.o win_keyboard.o \ - win_mouse.o win_joystick.o win_midi.o + win_cdrom.o win_keyboard.o win_mouse.o win_joystick.o \ + win_midi.o ifeq ($(CRASHDUMP), y) PLATOBJ += win_crashdump.o endif diff --git a/src/win/msvc/Makefile.VC b/src/win/msvc/Makefile.VC index 301a9ea..41f5c93 100644 --- a/src/win/msvc/Makefile.VC +++ b/src/win/msvc/Makefile.VC @@ -8,7 +8,7 @@ # # Makefile for Windows using Visual Studio 2015. # -# Version: @(#)Makefile.VC 1.0.46 2018/09/19 +# Version: @(#)Makefile.VC 1.0.46 2018/10/05 # # Author: Fred N. van Kempen, # @@ -69,6 +69,9 @@ endif ifndef DEBUG DEBUG := n endif +ifndef LOGGING + LOGGING := n +endif ifndef PROFILER PROFILER := n endif @@ -135,9 +138,6 @@ endif ifndef PAS16 PAS16 := n endif -ifndef STEALTH32 - STEALTH32 := n -endif ifndef XL24 XL24 := n endif @@ -159,8 +159,13 @@ ifndef PROG endif endif ifeq ($(DEBUG), y) - PROG := $(PROG)-d - NETIF := $(NETIF)-d + PROG := $(PROG)-d + NETIF := $(NETIF)-d + LOGGING := y +else + ifeq ($(LOGGING), y) + PROG := $(PROG)-l + endif endif @@ -173,7 +178,6 @@ ifeq ($(DEV_BUILD), y) PORTABLE3 := y I686 := y PAS16 := y - STEALTH32 := y XL24 := y WONDER := y endif @@ -241,7 +245,7 @@ ifeq ($(X64), y) ARCH := x64 else CPP := cl -nologo - CC := cl -nologo + CC := cl -nologo #-TP ARCH := x86 endif PREPROC := cl -nologo -EP @@ -253,7 +257,7 @@ SYSINC := -Iwin/msvc/Include -Iwin/mingw/include SYSLIB := DEPS = -MMD -MF $*.d -DEPFILE := win\.depends-msvc +DEPFILE := win\msvc\.depends # Set up the correct toolchain flags. OPTS := $(EXTRAS) $(STUFF) $(VCOPTS) \ @@ -261,6 +265,7 @@ OPTS := $(EXTRAS) $(STUFF) $(VCOPTS) \ -D_CRT_NONSTDC_NO_DEPRECATE \ -D_WINSOCK_DEPRECATED_NO_WARNINGS \ -D_CRT_SECURE_NO_WARNINGS \ + -D_CRT_STDIO_ISO_WIDE_SPECIFIERS \ $(WPCAPINC) $(SYSINC) AFLAGS := /arch:SSE2 RFLAGS := /n @@ -287,7 +292,7 @@ ifdef EXINC endif OPTS += $(SYSINC) ifeq ($(OPTIM), y) - DOPTS := -march=native + AFLAGS := /arch:AVX2 endif ifeq ($(DEBUG), y) OPTS += -D_DEBUG @@ -304,6 +309,10 @@ else COPTIM := -O2 endif endif +ifeq ($(LOGGING), y) + OPTS += -D_LOGGING + RFLAGS += -D_LOGGING +endif ifeq ($(CRASHDUMP), y) OPTS += -DUSE_CRASHDUMP endif @@ -475,9 +484,8 @@ ifneq ($(WX), n) else UIOBJ := win_ui.obj \ win_ddraw.obj win_d3d.obj $(SDLOBJ) $(D2DOBJ) \ - win_dialog.obj win_about.obj win_status.obj \ - win_settings.obj win_devconf.obj win_snd_gain.obj \ - win_new_image.obj + win_dialog.obj win_about.obj win_settings.obj \ + win_devconf.obj win_snd_gain.obj win_new_image.obj endif @@ -501,7 +509,6 @@ ifeq ($(DEV_BRANCH), y) ifeq ($(I686), y) OPTS += -DUSE_I686 - DEVBROBJ += m_at_440fx.obj endif ifeq ($(PAS16), y) @@ -509,11 +516,6 @@ ifeq ($(DEV_BRANCH), y) DEVBROBJ += snd_pas16.obj endif - ifeq ($(STEALTH32), y) - OPTS += -DUSE_STEALTH32 - DEVBROBJ += vid_icd2061.obj - endif - ifeq ($(XL24), y) OPTS += -DUSE_XL24 endif @@ -544,7 +546,8 @@ RESDLL := VARCem-$(LANG) MAINOBJ := pc.obj config.obj misc.obj random.obj timer.obj io.obj \ mem.obj rom.obj rom_load.obj device.obj nvr.obj -UIOBJ += ui_main.obj ui_new_image.obj ui_stbar.obj ui_vidapi.obj +UIOBJ += ui_main.obj ui_lang.obj ui_stbar.obj ui_vidapi.obj \ + ui_cdrom.obj ui_new_image.obj ui_misc.obj SYSOBJ := dma.obj nmi.obj pic.obj pit.obj ppi.obj pci.obj mca.obj \ mcr.obj memregs.obj nvr_at.obj nvr_ps2.obj @@ -569,13 +572,12 @@ MCHOBJ := machine.obj machine_table.obj \ m_at_opti495.obj m_at_scat.obj \ m_at_compaq.obj m_at_wd76c10.obj \ m_at_sis_85c471.obj m_at_sis_85c496.obj \ - m_at_430lx_nx.obj m_at_430fx.obj \ - m_at_430hx.obj m_at_430vx.obj + m_at_4x0.obj INTELOBJ := intel.obj \ intel_flash.obj \ intel_sio.obj \ - intel_piix.obj intel_piix4.obj + intel_piix.obj DEVOBJ := bugger.obj \ isamem.obj isartc.obj \ @@ -607,7 +609,8 @@ HDDOBJ := hdd.obj \ hdc_ide_ata.obj hdc_ide_xta.obj hdc_xtide.obj CDROMOBJ := cdrom.obj \ - cdrom_dosbox.obj cdrom_image.obj cdrom_null.obj + cdrom_null.obj cdrom_speed.obj \ + cdrom_dosbox.obj cdrom_image.obj ZIPOBJ := zip.obj @@ -616,7 +619,7 @@ USBOBJ := usb.obj endif SCSIOBJ := scsi.obj \ - scsi_bus.obj scsi_device.obj \ + scsi_device.obj \ scsi_disk.obj \ scsi_x54x.obj \ scsi_aha154x.obj scsi_buslogic.obj \ @@ -630,7 +633,8 @@ NETOBJ := network.obj \ tcp_input.obj debug.obj ip_output.obj sbuf.obj \ tcp_output.obj udp.obj if.obj mbuf.obj slirp.obj \ tcp_subr.obj \ - net_ne2000.obj + net_dp8390.obj \ + net_ne2000.obj net_wd80x3.obj net_3c503.obj SNDOBJ := sound.obj \ sound_dev.obj \ @@ -658,7 +662,7 @@ SNDOBJ := sound.obj \ VIDOBJ := video.obj \ video_dev.obj \ vid_cga.obj vid_cga_comp.obj \ - vid_compaq_cga.obj \ + vid_cga_compaq.obj \ vid_mda.obj \ vid_hercules.obj vid_herculesplus.obj vid_incolor.obj \ vid_colorplus.obj \ @@ -670,7 +674,7 @@ VIDOBJ := video.obj \ vid_ati_eeprom.obj \ vid_ati18800.obj vid_ati28800.obj \ vid_ati_mach64.obj vid_ati68860_ramdac.obj \ - vid_ics2595.obj \ + vid_bt48x_ramdac.obj vid_icd2061.obj vid_ics2595.obj \ vid_cl54xx.obj \ vid_et4000.obj vid_sc1502x_ramdac.obj \ vid_et4000w32.obj vid_stg_ramdac.obj \ @@ -685,8 +689,8 @@ VIDOBJ := video.obj \ PLATOBJ := win.obj \ win_lang.obj win_opendir.obj win_dynld.obj win_thread.obj \ - win_cdrom.obj win_cdrom_ioctl.obj win_keyboard.obj \ - win_mouse.obj win_joystick.obj win_midi.obj + win_cdrom.obj win_keyboard.obj win_mouse.obj \ + win_joystick.obj win_midi.obj ifeq ($(CRASHDUMP), y) PLATOBJ += win_crashdump.obj endif diff --git a/src/win/msvc/vc15/VARCem.vcxproj b/src/win/msvc/vc15/VARCem.vcxproj index 3f51d77..282101c 100644 --- a/src/win/msvc/vc15/VARCem.vcxproj +++ b/src/win/msvc/vc15/VARCem.vcxproj @@ -55,8 +55,6 @@ - - @@ -75,9 +73,6 @@ - - - @@ -212,6 +207,7 @@ + @@ -252,7 +248,6 @@ - @@ -405,8 +400,6 @@ - - @@ -428,7 +421,6 @@ - @@ -544,7 +536,6 @@ - @@ -701,7 +692,7 @@ Level3 Disabled true - WIN32;_DEBUG;_WINDOWS;USE_STANDARD_MALLOC;%(PreprocessorDefinitions) + WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) Windows @@ -740,7 +731,7 @@ true true true - WIN32;NDEBUG;_WINDOWS;USE_STANDARD_MALLOC;%(PreprocessorDefinitions) + WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) Windows diff --git a/src/win/msvc/vc15/VARCem.vcxproj.filters b/src/win/msvc/vc15/VARCem.vcxproj.filters index 7506327..cc44658 100644 --- a/src/win/msvc/vc15/VARCem.vcxproj.filters +++ b/src/win/msvc/vc15/VARCem.vcxproj.filters @@ -752,6 +752,9 @@ machines + + machines + machines @@ -879,22 +882,6 @@ win - - devices\printer - - - devices\printer - - - devices\printer - - - devices\misc - - - devices\misc - - @@ -1649,16 +1636,6 @@ win - - devices\printer - - - devices\misc - - - devices\misc - - @@ -1733,9 +1710,6 @@ {51f1c4aa-4a2a-4639-bcbc-2075ffaf3e27} - - {ab4ace08-f0ba-404e-b2ed-dbcacbb291c7} - diff --git a/src/win/pcap_if.rc b/src/win/pcap_if.rc index 99aedad..2f592b0 100644 --- a/src/win/pcap_if.rc +++ b/src/win/pcap_if.rc @@ -10,7 +10,7 @@ * * NOTE: Will be moved to the tools/ folder soon. * - * Version: @(#)pcap_if.rc 1.0.4 2018/05/28 + * Version: @(#)pcap_if.rc 1.0.5 2018/09/15 * * Author: Fred N. van Kempen, * @@ -53,8 +53,8 @@ VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,0,3,0 - PRODUCTVERSION 1,0,3,0 + FILEVERSION 1,0,5,0 + PRODUCTVERSION 1,0,5,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -67,20 +67,20 @@ VS_VERSION_INFO VERSIONINFO BEGIN BLOCK "StringFileInfo" BEGIN - BLOCK "040904b0" + BLOCK "0409fde9" BEGIN VALUE "CompanyName", "IRC #VARCem on FreeNode" VALUE "FileDescription", "PCap_IF - test tool for WinPcap" - VALUE "FileVersion", "1.0.3" + VALUE "FileVersion", "1.0.5" VALUE "InternalName", "pcap_if" VALUE "LegalCopyright", "Copyright 2017,2018 Fred N. van Kempen" VALUE "OriginalFilename", "pcap_if.exe" VALUE "ProductName", "WinPcap Test Tool" - VALUE "ProductVersion", "1.0.3" + VALUE "ProductVersion", "1.0.5" END END BLOCK "VarFileInfo" BEGIN - VALUE "Translation", 0x0409, 1200 + VALUE "Translation", 0x0409, 65001 END END diff --git a/src/win/resource.h b/src/win/resource.h index 0e1bcaf..67471fe 100644 --- a/src/win/resource.h +++ b/src/win/resource.h @@ -8,7 +8,7 @@ * * Windows resource defines. * - * Version: @(#)resource.h 1.0.18 2018/08/27 + * Version: @(#)resource.h 1.0.19 2018/09/09 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -43,21 +43,21 @@ /* Dialog IDs. */ #define DLG_ABOUT 1000 /* top-level dialog */ # define DLG_LOCALIZE 1001 -#define DLG_STATUS 1010 /* top-level dialog */ -#define DLG_SND_GAIN 1020 /* top-level dialog */ -#define DLG_NEW_FLOPPY 1030 /* top-level dialog */ -#define DLG_CONFIG 1040 /* top-level dialog */ -#define DLG_CFG_MACHINE 1041 /* sub-dialog of config */ -#define DLG_CFG_VIDEO 1042 /* sub-dialog of config */ -#define DLG_CFG_INPUT 1043 /* sub-dialog of config */ -#define DLG_CFG_SOUND 1044 /* sub-dialog of config */ -#define DLG_CFG_NETWORK 1045 /* sub-dialog of config */ -#define DLG_CFG_PORTS 1046 /* sub-dialog of config */ -#define DLG_CFG_PERIPHERALS 1047 /* sub-dialog of config */ -#define DLG_CFG_DISK 1048 /* sub-dialog of config */ -#define DLG_CFG_DISK_ADD 1049 /* sub-dialog of config */ -#define DLG_CFG_FLOPPY 1050 /* sub-dialog of config */ -#define DLG_CFG_RMV_DEVICES 1051 /* sub-dialog of config */ +#define DLG_SND_GAIN 1010 /* top-level dialog */ +#define DLG_NEW_FLOPPY 1020 /* top-level dialog */ +#define DLG_CONFIG 1030 /* top-level dialog */ +#define DLG_CFG_MACHINE 1031 /* sub-dialog of config */ +#define DLG_CFG_VIDEO 1032 /* sub-dialog of config */ +#define DLG_CFG_INPUT 1033 /* sub-dialog of config */ +#define DLG_CFG_SOUND 1034 /* sub-dialog of config */ +#define DLG_CFG_NETWORK 1035 /* sub-dialog of config */ +#define DLG_CFG_PORTS 1036 /* sub-dialog of config */ +#define DLG_CFG_PERIPHERALS 1037 /* sub-dialog of config */ +#define DLG_CFG_DISK 1038 /* sub-dialog of config */ +#define DLG_CFG_DISK_ADD 1039 /* sub-dialog of config */ +#define DLG_CFG_FLOPPY 1040 /* sub-dialog of config */ +#define DLG_CFG_RMV_DEVICES 1041 /* sub-dialog of config */ + /* Static text label IDs. */ #define IDT_1700 1700 /* Language: */ @@ -68,7 +68,7 @@ #define IDT_1705 1705 /* MB == IDC_TEXT_MB */ #define IDT_1706 1706 /* Memory: */ #define IDT_1707 1707 /* Video: */ -#define IDT_1708 1708 /* Video speed: */ +#define IDT_1708 1708 /* Time sync: */ #define IDT_1709 1709 /* Mouse: */ #define IDT_1710 1710 /* Joystick: */ #define IDT_1711 1711 /* Sound card: */ @@ -78,8 +78,8 @@ #define IDT_1715 1715 /* Network adapter: */ #define IDT_1716 1716 /* SCSI Controller: */ #define IDT_1717 1717 /* HD Controller: */ -#define IDT_1718 1718 /* Tertiary IDE: */ -#define IDT_1719 1719 /* Quaternary IDE: */ +/* 1718 unused */ +/* 1719 unused */ #define IDT_1720 1720 /* Hard disks: */ #define IDT_1721 1721 /* Bus: */ #define IDT_1722 1722 /* Channel: */ @@ -98,8 +98,7 @@ #define IDT_1741 1741 /* ID: */ #define IDT_1742 1742 /* LUN: */ #define IDT_1743 1743 /* Channel: */ -#define IDT_STEXT 1744 /* text in status window */ -#define IDT_SDEVICE 1745 /* text in status window */ +/* 1744/1745 unused */ #define IDT_1746 1746 /* Gain */ #define IDT_1749 1749 /* File name: */ #define IDT_1750 1750 /* Disk size: */ @@ -131,7 +130,7 @@ */ #define IDC_SETTINGSCATLIST 1001 /* generic config */ #define IDC_CFILE 1002 /* Select File dialog */ -#define IDC_CHECK_SYNC 1008 +#define IDC_COMBO_SYNC 1008 #define IDC_COMBO_MACHINE 1010 /* machine/cpu config */ #define IDC_CONFIGURE_MACHINE 1011 @@ -148,27 +147,36 @@ #define IDC_VIDEO 1030 /* video config */ #define IDC_COMBO_VIDEO 1031 -#define IDC_COMBO_VIDEO_SPEED 1032 +#define IDC_CONFIGURE_VIDEO 1032 #define IDC_CHECK_VOODOO 1033 -#define IDC_BUTTON_VOODOO 1034 +#define IDC_CONFIGURE_VOODOO 1034 #define IDC_INPUT 1050 /* input config */ #define IDC_COMBO_MOUSE 1051 -#define IDC_COMBO_JOYSTICK 1052 -#define IDC_COMBO_JOY 1053 -#define IDC_CONFIGURE_MOUSE 1054 +#define IDC_CONFIGURE_MOUSE 1052 +#define IDC_COMBO_JOYSTICK 1053 +#define IDC_COMBO_JOY 1054 +#define IDC_CONFIGURE_JOY1 1235 +#define IDC_CONFIGURE_JOY2 1236 +#define IDC_CONFIGURE_JOY3 1237 +#define IDC_CONFIGURE_JOY4 1238 #define IDC_SOUND 1070 /* sound config */ #define IDC_COMBO_SOUND 1071 -#define IDC_COMBO_MIDI 1072 -#define IDC_CHECK_NUKEDOPL 1073 -#define IDC_CHECK_FLOAT 1074 -#define IDC_CHECK_MPU401 1075 -#define IDC_CONFIGURE_MPU401 1076 +#define IDC_CONFIGURE_SOUND 1072 +#define IDC_COMBO_MIDI 1073 +#define IDC_CONFIGURE_MIDI 1074 +#define IDC_CHECK_NUKEDOPL 1075 +#define IDC_CHECK_FLOAT 1076 +#define IDC_CHECK_MPU401 1077 +#define IDC_CONFIGURE_MPU401 1078 #define IDC_COMBO_NET_TYPE 1090 /* network config */ -#define IDC_COMBO_PCAP 1091 -#define IDC_COMBO_NET 1092 +#define IDC_CONFIGURE_NET_TYPE 1091 +#define IDC_COMBO_PCAP 1092 +#define IDC_CONFIGURE_PCAP 1093 +#define IDC_COMBO_NET_CARD 1094 +#define IDC_CONFIGURE_NET_CARD 1095 #define IDC_CHECK_GAME 1110 /* ports config */ #define IDC_CHECK_PARALLEL1 1111 @@ -185,12 +193,14 @@ #define IDC_CONFIGURE_SCSI 1122 #define IDC_COMBO_HDC 1123 #define IDC_CONFIGURE_HDC 1124 -#define IDC_COMBO_IDE_TER 1125 -#define IDC_COMBO_IDE_QUA 1126 -#define IDC_CHECK_BUGGER 1127 -#define IDC_CONFIGURE_BUGGER 1128 -#define IDC_COMBO_ISARTC 1129 -#define IDC_CONFIGURE_ISARTC 1130 +#define IDC_CHECK_IDE_TER 1125 +#define IDC_CONFIGURE_IDE_TER 1126 +#define IDC_CHECK_IDE_QUA 1127 +#define IDC_CONFIGURE_IDE_QUA 1128 +#define IDC_CHECK_BUGGER 1129 +#define IDC_CONFIGURE_BUGGER 1130 +#define IDC_COMBO_ISARTC 1131 +#define IDC_CONFIGURE_ISARTC 1132 #define IDC_GROUP_ISAMEM 1140 #define IDC_COMBO_ISAMEM_1 1141 @@ -245,35 +255,16 @@ #define IDC_COMBO_DISK_SIZE 1196 #define IDC_COMBO_RPM_MODE 1197 - -/* For the DeviceConfig code, re-do later. */ -#define IDC_CONFIG_BASE 1200 -#define IDC_CONFIGURE_VID 1200 -#define IDC_CONFIGURE_SND 1201 -#define IDC_CONFIGURE_VOODOO 1202 -#define IDC_CONFIGURE_MOD 1203 -#define IDC_CONFIGURE_NET_TYPE 1204 -#define IDC_CONFIGURE_BUSLOGIC 1205 -#define IDC_CONFIGURE_PCAP 1206 -#define IDC_CONFIGURE_NET 1207 -#define IDC_CONFIGURE_MIDI 1208 -#define IDC_JOY1 1210 -#define IDC_JOY2 1211 -#define IDC_JOY3 1212 -#define IDC_JOY4 1213 - -#define IDC_HDTYPE 1280 - -#define IDC_RENDER 1281 - -#define IDC_STATBAR 1282 +/* Misc items. */ +#define IDC_CONFIGURE_DEV 1200 /* dynamic DeviceConfig code */ +#define IDC_STATBAR 1201 /* status bar events */ /* HELP menu. */ #define IDC_LOCALIZE 1290 #define IDC_DONATE 1291 #define IDC_SUPPORT 1292 -#define IDC_ABOUT_ICON 65535 +#define IDC_ABOUT_ICON 65535 #endif /*WIN_RESOURCE_H*/ diff --git a/src/win/win.c b/src/win/win.c index bdb7f45..83f873e 100644 --- a/src/win/win.c +++ b/src/win/win.c @@ -8,7 +8,7 @@ * * Platform main support module for Windows. * - * Version: @(#)win.c 1.0.20 2018/09/23 + * Version: @(#)win.c 1.0.20 2018/10/05 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -49,12 +49,10 @@ #include #include #include "../emu.h" -#undef malloc #include "../version.h" #include "../config.h" #include "../device.h" #include "../ui/ui.h" -#define GLOBAL #include "../plat.h" #ifdef USE_SDL # include "win_sdl.h" @@ -77,12 +75,13 @@ /* Platform Public data, specific. */ -HINSTANCE hInstance; /* application instance */ +HINSTANCE hInstance; /* application instance */ +int quited; /* system exit requested */ /* Local data. */ -static HANDLE hBlitMutex, /* video mutex */ - thMain; /* main thread */ +static HANDLE hBlitMutex, /* video mutex */ + thMain; /* main thread */ /* The list with supported VidAPI modules. */ @@ -152,7 +151,7 @@ ProcessCommandLine(wchar_t ***argw) if (argc >= argc_max) { argc_max += 64; - args = realloc(args, sizeof(wchar_t *)*argc_max); + args = (wchar_t **)realloc(args, sizeof(wchar_t *)*argc_max); if (args == NULL) { free(argbuf); return(0); @@ -191,12 +190,27 @@ WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR lpszArg, int nCmdShow) wchar_t **argw = NULL; int argc, i, lang; - /* Set this to the default value (windowed mode). */ - vid_fullscreen = 0; - /* We need this later. */ hInstance = hInst; + /* + * Grab the commandline arguments, and do the pre-init. + * + * We do this BEFORE initializing other things, because + * this also sets up a proper (and corrected) argv[0] + * value, in turn needed by pc_setup() .. + */ + argc = ProcessCommandLine(&argw); + + /* Initialize the version data. CrashDump needs it early. */ + pc_version("Windows"); + + /* Set up the basic pathname info for the application. */ + (void)pc_setup(0, NULL); + + /* Set this to the default value (windowed mode). */ + vid_fullscreen = 0; + /* First, set our (default) language. */ lang = (int)GetUserDefaultUILanguage(); @@ -204,19 +218,15 @@ WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR lpszArg, int nCmdShow) * Set the initial active language for this application. * * We must do this early, because if we are on a localized - * Windows system, we must have the language set up so the + * system, we must have the language set up so that the * "pc_setup" phase (config file etc) can display error - * messages... *cough* + * messages... */ - if (! plat_set_language(lang)) { + if (! ui_lang_set(lang)) { /* That did not work. Revert back to default and try again. */ - lang = lang_id; - (void)plat_set_language(lang); + lang = 0x0409; + (void)ui_lang_set(lang); } - lang_id = lang; - - /* Initialize the version data. CrashDump needs it early. */ - pc_version("Windows"); #ifdef USE_CRASHDUMP /* Enable crash dump services. */ @@ -227,10 +237,7 @@ WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR lpszArg, int nCmdShow) if (force_debug) plat_console(1); - /* Process the command line for options. */ - argc = ProcessCommandLine(&argw); - - /* Pre-initialize the system, this loads the config file. */ + /* Set up standard emulator stuff, read config file. */ if (pc_setup(argc, argw) <= 0) { /* Error, detach from console and abort. */ plat_console(0); @@ -242,10 +249,10 @@ WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR lpszArg, int nCmdShow) plat_console(0); /* Set the active language for this application. */ - if (! plat_set_language(lang_id)) { + if (! ui_lang_set(language)) { /* That did not work. Revert back to default and try again. */ - lang_id = 0x0409; - (void)plat_set_language(lang_id); + lang = emu_lang_id; + (void)ui_lang_set(lang); } /* Create a mutex for the video handler. */ @@ -267,6 +274,7 @@ void plat_start(void) { LARGE_INTEGER qpc; + uint64_t freq; /* We have not stopped yet. */ quited = 0; @@ -274,8 +282,8 @@ plat_start(void) /* Initialize the high-precision timer. */ timeBeginPeriod(1); QueryPerformanceFrequency(&qpc); - timer_freq = qpc.QuadPart; - pclog("Main timer precision: %llu\n", timer_freq); + freq = qpc.QuadPart; + INFO("Main timer precision: %llu\n", freq); /* Start the emulator, really. */ thMain = thread_create(pc_thread, &quited); @@ -343,43 +351,6 @@ plat_console(int init) #endif /*USE_WX*/ -/* Return icon number based on drive type. */ -int -plat_fdd_icon(int type) -{ - int ret = 512; - - switch(type) { - case 0: - break; - - case 1: - case 2: - case 3: - case 4: - case 5: - case 6: - ret = 128; - break; - - case 7: - case 8: - case 9: - case 10: - case 11: - case 12: - case 13: - ret = 144; - break; - - default: - break; - } - - return(ret); -} - - void plat_get_exe_name(wchar_t *bufp, int size) { @@ -399,9 +370,10 @@ plat_tempfile(wchar_t *bufp, const wchar_t *prefix, const wchar_t *suffix) strcpy(temp, ""); GetSystemTime(&SystemTime); - sprintf(&temp[strlen(temp)], "%d%02d%02d-%02d-%02d-%02d-%03d%ls", - SystemTime.wYear, SystemTime.wMonth, SystemTime.wDay, SystemTime.wHour, - SystemTime.wMinute, SystemTime.wSecond, SystemTime.wMilliseconds, + sprintf(&temp[strlen(temp)], "%d%02d%02d-%02d%02d%02d-%03d%ls", + SystemTime.wYear, SystemTime.wMonth, SystemTime.wDay, + SystemTime.wHour, SystemTime.wMinute, SystemTime.wSecond, + SystemTime.wMilliseconds, suffix); mbstowcs(bufp, temp, strlen(temp)+1); } @@ -572,6 +544,14 @@ vidapi_count(void) } +/* Interface to get_string() for Windows-internal functions using LPARAM. */ +LPARAM +win_string(int id) +{ + return((LPARAM)get_string(id)); +} + + void plat_startblit(void) { diff --git a/src/win/win.h b/src/win/win.h index e72b78e..7f974a2 100644 --- a/src/win/win.h +++ b/src/win/win.h @@ -6,9 +6,11 @@ * * This file is part of the VARCem Project. * - * Platform support defintions for Win32. + * Platform support defintions for Win32. This file describes + * only things used globally within the Windows platform; the + * generic platform defintions are in the plat.h file. * - * Version: @(#)win.h 1.0.18 2018/07/28 + * Version: @(#)win.h 1.0.19 2018/10/01 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -50,63 +52,40 @@ # define PLAT_WIN_H -#include "resource.h" /* platform resources */ -#include "../ui/ui_resource.h" /* common resources */ - - /* Class names and such. */ -#define MUTEX_NAME L"VARCem.BlitMutex" -#define CLASS_NAME L"VARCem.MainWindow" -#define FS_CLASS_NAME L"VARCem.FullScreen" -#define MENU_NAME L"MainMenu" -#define SB_MENU_NAME L"StatusBarMenu" -#define ACCEL_NAME L"MainAccel" +#define MUTEX_NAME L"VARCem.BlitMutex" +#define CLASS_NAME L"VARCem.MainWindow" +#define FS_CLASS_NAME L"VARCem.FullScreen" +#define MENU_MAIN_NAME L"MainMenu" +#define MENU_SB_NAME L"StatusBarMenu" +#define ACCEL_NAME L"MainAccel" /* Application-specific window messages. */ -#define WM_PAUSE WM_USER -#define WM_LEAVEFULLSCREEN WM_USER+1 -#define WM_RESETD3D WM_USER+2 -#define WM_SAVESETTINGS WM_USER+3 -#define WM_SHOWSETTINGS WM_USER+4 +#define WM_PAUSE WM_USER +#define WM_LEAVE_FS WM_USER+1 +#define WM_RESET_D3D WM_USER+2 +#define WM_SAVE_CFG WM_USER+3 +#define WM_SHOW_CFG WM_USER+4 /* Status bar definitions. */ -#define SB_HEIGHT 16 /* for 16x16 icons */ -#define SB_PADDING 1 /* 1px of padding */ +#define SB_HEIGHT 16 /* for 16x16 icons */ +#define SB_PADDING 1 /* 1px of padding */ #ifdef __cplusplus extern "C" { #endif -/* Define an in-memory language entry. */ -typedef struct _lang_ { - const wchar_t *name; - const wchar_t *dll; - - const wchar_t *author; - const wchar_t *email; - const wchar_t *version; - - int id; - struct _lang_ *next; -} lang_t; - - extern HINSTANCE hInstance; -extern HICON hIcon[512]; extern HWND hwndMain, hwndRender; extern DWORD filterindex; -extern int status_is_open; /* VidApi initializers. */ extern const vidapi_t ddraw_vidapi; extern const vidapi_t d3d_vidapi; -/* Languages. */ -extern lang_t *languages; - /* Internal platform support functions. */ #ifdef USE_CRASHDUMP @@ -114,7 +93,7 @@ extern void InitCrashDump(void); #endif extern HICON LoadIconEx(PCTSTR name); extern void keyboard_getkeymap(void); -extern void keyboard_handle(LPARAM lParam, int infocus); +extern void keyboard_handle(LPARAM lParam, int focus); extern void win_mouse_init(void); extern void win_mouse_close(void); @@ -123,15 +102,15 @@ extern void dialog_center(HWND hdlg); extern int dlg_file_ex(HWND hwnd, const wchar_t *filt, const wchar_t *ifn, wchar_t *fn, int save); #ifdef EMU_DEVICE_H -extern uint8_t dlg_devconf(HWND hwnd, device_t *device); +extern uint8_t dlg_devconf(HWND hwnd, const device_t *device); #endif extern uint8_t dlg_jsconf(HWND hwnd, int joy_nr, int type); /* Platform UI support functions. */ extern int ui_init(int nCmdShow); +extern LPARAM win_string(int id); extern void plat_set_input(HWND h); extern HMODULE plat_lang_dll(void); -extern void plat_lang_menu(void); #ifdef __cplusplus } diff --git a/src/win/win_about.c b/src/win/win_about.c index 468d970..d044a42 100644 --- a/src/win/win_about.c +++ b/src/win/win_about.c @@ -12,7 +12,7 @@ * 24bit image would be preferred, but we cant use LoadImage * for those (and keep transparency...) * - * Version: @(#)win_about.c 1.0.9 2018/06/02 + * Version: @(#)win_about.c 1.0.10 2018/10/05 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -53,12 +53,14 @@ #include "../ui/ui.h" #include "../plat.h" #include "win.h" +#include "resource.h" static void donate_handle(HWND hdlg) { - pclog("UI: DONATE button clicked, opening browser to PayPal\n"); + pclog(LOG_ALWAYS, + "UI: DONATE button clicked, opening browser to PayPal\n"); ShellExecute(NULL, L"open", URL_PAYPAL, NULL, NULL , SW_SHOW); } @@ -112,7 +114,7 @@ static LRESULT CALLBACK #else static BOOL CALLBACK #endif -localize_dlg_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) +localize_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) { HBITMAP hBmp; lang_t *lang; @@ -125,13 +127,14 @@ localize_dlg_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) dialog_center(hdlg); /* Load the main icon. */ - hBmp = LoadImage(hInstance,(PCTSTR)100, IMAGE_ICON, 64, 64, 0); + hBmp = (HBITMAP) LoadImage(hInstance,MAKEINTRESOURCE(ICON_MAIN), + IMAGE_ICON, 64, 64, 0); h = GetDlgItem(hdlg, IDC_ABOUT_ICON); SendMessage(h, STM_SETIMAGE, (WPARAM)IMAGE_ICON, (LPARAM)hBmp); /* Add the languages. */ h = GetDlgItem(hdlg, IDC_LOCALIZE); - for (lang = languages->next; lang != NULL; lang = lang->next) { + for (lang = ui_lang_get()->next; lang != NULL; lang = lang->next) { c = SendMessage(h, LB_ADDSTRING, 0, (LPARAM)lang->name); SendMessage(h, LB_SETITEMDATA, c, (LPARAM)lang); } @@ -171,9 +174,9 @@ static LRESULT CALLBACK #else static BOOL CALLBACK #endif -dlg_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) +about_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) { -static HBRUSH brush = NULL; + static HBRUSH brush = NULL; wchar_t temp[128]; HBITMAP hBmp; HWND h; @@ -183,8 +186,8 @@ static HBRUSH brush = NULL; /* Center in the main window. */ dialog_center(hdlg); - hBmp = LoadImage(hInstance, - MAKEINTRESOURCE(100), IMAGE_ICON, 64, 64, 0); + hBmp = (HBITMAP)LoadImage(hInstance, MAKEINTRESOURCE(ICON_MAIN), + IMAGE_ICON, 64, 64, 0); h = GetDlgItem(hdlg, IDC_ABOUT_ICON); SendMessage(h, STM_SETIMAGE, (WPARAM)IMAGE_ICON, (LPARAM)hBmp); mbstowcs(temp, emu_title, sizeof_w(temp)); @@ -199,13 +202,13 @@ static HBRUSH brush = NULL; /* Load the Paypal Donate icon. */ h = GetDlgItem(hdlg, IDC_DONATE); #if 1 - hBmp = LoadImage(hInstance, MAKEINTRESOURCE(101), + hBmp = (HBITMAP)LoadImage(hInstance, MAKEINTRESOURCE(ICON_DONATE), IMAGE_BITMAP, 105, 50, LR_LOADTRANSPARENT|LR_LOADMAP3DCOLORS); SendMessage(h, STM_SETIMAGE, (WPARAM)IMAGE_BITMAP, (LPARAM)hBmp); #else - hBmp = LoadImage(hInstance, - MAKEINTRESOURCE(101), IMAGE_ICON, 128, 128, 0); + hBmp = LoadImage(hInstance, MAKEINTRESOURCE(ICON_DONATE), + IMAGE_ICON, 128, 128, 0); SendMessage(h, STM_SETIMAGE, (WPARAM)IMAGE_ICON, (LPARAM)hBmp); #endif break; @@ -217,9 +220,7 @@ static HBRUSH brush = NULL; return TRUE; case IDC_LOCALIZE: - DialogBox(plat_lang_dll(), - (LPCTSTR)DLG_LOCALIZE, - hdlg, localize_dlg_proc); + dlg_localize(); break; default: @@ -263,9 +264,12 @@ static HBRUSH brush = NULL; void dlg_about(void) { - plat_pause(1); - - DialogBox(plat_lang_dll(), (LPCTSTR)DLG_ABOUT, hwndMain, dlg_proc); - - plat_pause(0); + DialogBox(plat_lang_dll(), (LPCTSTR)DLG_ABOUT, hwndMain, about_proc); +} + + +void +dlg_localize(void) +{ + DialogBox(plat_lang_dll(), (LPCTSTR)DLG_LOCALIZE, hwndMain, localize_proc); } diff --git a/src/win/win_cdrom.c b/src/win/win_cdrom.c index 6b5d447..717f916 100644 --- a/src/win/win_cdrom.c +++ b/src/win/win_cdrom.c @@ -7,8 +7,10 @@ * This file is part of the VARCem Project. * * Handle the platform-side of CDROM drives. + * Implementation of the CD-ROM host drive IOCTL interface for + * Windows using SCSI Passthrough Direct. * - * Version: @(#)win_cdrom.c 1.0.9 2018/05/08 + * Version: @(#)win_cdrom.c 1.0.10 2018/10/05 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -35,8 +37,11 @@ * USA. */ #define UNICODE -#define WIN32_LEAN_AND_MEAN +#define WINVER 0x0600 #include +#include +#include +#include #include #include #include @@ -46,224 +51,1365 @@ #include "../config.h" #include "../ui/ui.h" #include "../plat.h" -#include "../devices/disk/hdd.h" -#include "../devices/disk/zip.h" +#include "../devices/scsi/scsi_device.h" #include "../devices/cdrom/cdrom.h" -#include "../devices/cdrom/cdrom_image.h" -#include "../devices/cdrom/cdrom_null.h" -#include "../devices/scsi/scsi.h" -#include "../devices/scsi/scsi_disk.h" #include "win.h" -uint8_t host_cdrom_drive_available[26]; -uint8_t host_cdrom_drive_available_num = 0; +uint8_t host_cdrom_drive_available_num = 0; +uint8_t host_cdrom_drive_available[26]; void cdrom_init_host_drives(void) { - WCHAR s[64]; + WCHAR temp[16]; int i = 0; host_cdrom_drive_available_num = 0; - for (i='A'; i<='Z'; i++) { - _swprintf(s, L"%c:\\", i); + for (i = 'A'; i <= 'Z'; i++) { + swprintf(temp, sizeof_w(temp), L"%c:\\", i); - if (GetDriveType(s)==DRIVE_CDROM) { + if (GetDriveType(temp) == DRIVE_CDROM) { host_cdrom_drive_available[i - 'A'] = 1; host_cdrom_drive_available_num++; - } else { + } else host_cdrom_drive_available[i - 'A'] = 0; - } } } -void -cdrom_eject(uint8_t id) -{ - if (cdrom_drives[id].host_drive == 0) { - /* Switch from empty to empty. Do nothing. */ - return; - } - - if ((cdrom_drives[id].host_drive >= 'A') && - (cdrom_drives[id].host_drive <= 'Z')) { - ui_sb_menu_set_item(SB_CDROM | id, - IDM_CDROM_HOST_DRIVE | id | ((cdrom_drives[id].host_drive - 'A') << 3), 0); - } - - if (cdrom_image[id].prev_image_path) { - free(cdrom_image[id].prev_image_path); - cdrom_image[id].prev_image_path = NULL; - } - - if (cdrom_drives[id].host_drive == 200) { - cdrom_image[id].prev_image_path = (wchar_t *)malloc(1024); - wcscpy(cdrom_image[id].prev_image_path, cdrom_image[id].image_path); - } - cdrom_drives[id].prev_host_drive = cdrom_drives[id].host_drive; - cdrom_drives[id].handler->exit(id); - cdrom_close(id); - cdrom_null_open(id, 0); - if (cdrom_drives[id].bus_type) { - /* Signal disc change to the emulated machine. */ - cdrom_insert(id); - } - - ui_sb_menu_set_item(SB_CDROM|id, IDM_CDROM_IMAGE | id, 0); - cdrom_drives[id].host_drive=0; - ui_sb_menu_set_item(SB_CDROM|id, IDM_CDROM_EMPTY | id, 1); - ui_sb_icon_state(SB_CDROM|id, 1); - ui_sb_menu_enable_item(SB_CDROM|id, IDM_CDROM_RELOAD | id, 1); - ui_sb_tip_update(SB_CDROM|id); - - config_save(); -} - - -void -cdrom_reload(uint8_t id) -{ #ifdef USE_CDROM_IOCTL - int new_cdrom_drive; + + +#define MSFtoLBA(m,s,f) ((((m*60)+s)*75)+f) + + +enum { + CD_STOPPED = 0, + CD_PLAYING, + CD_PAUSED +}; + + +typedef struct { + HANDLE hIOCTL; + CDROM_TOC toc; + int is_playing; +} cdrom_ioctl_windows_t; + + +cdrom_ioctl_windows_t cdrom_ioctl_windows[CDROM_NUM]; + +#ifdef ENABLE_CDROM_IOCTL_LOG +int cdrom_ioctl_do_log = ENABLE_CDROM_IOCTL_LOG; #endif - if ((cdrom_drives[id].host_drive == cdrom_drives[id].prev_host_drive) || (cdrom_drives[id].prev_host_drive == 0) || (cdrom_drives[id].host_drive != 0)) { - /* Switch from empty to empty. Do nothing. */ - return; + +static CDROM ioctl_cdrom; + + +static void +cdrom_ioctl_log(const char *format, ...) +{ +#ifdef ENABLE_CDROM_IOCTL_LOG + va_list ap; + + if (cdrom_ioctl_do_log) { + va_start(ap, format); + pclog_ex(format, ap); + va_end(ap); } - - cdrom_close(id); - - if (cdrom_drives[id].prev_host_drive == 200) { - wcscpy(cdrom_image[id].image_path, cdrom_image[id].prev_image_path); - free(cdrom_image[id].prev_image_path); - cdrom_image[id].prev_image_path = NULL; - image_open(id, cdrom_image[id].image_path); - if (cdrom_drives[id].bus_type) { - /* Signal disc change to the emulated machine. */ - cdrom_insert(id); - } - if (wcslen(cdrom_image[id].image_path) == 0) { - ui_sb_menu_set_item(SB_CDROM|id, IDM_CDROM_EMPTY | id, 1); - cdrom_drives[id].host_drive = 0; - ui_sb_menu_set_item(SB_CDROM|id, IDM_CDROM_IMAGE | id, 0); - ui_sb_icon_state(SB_CDROM|id, 1); - } else { - ui_sb_menu_set_item(SB_CDROM|id, IDM_CDROM_EMPTY | id, 0); - cdrom_drives[id].host_drive = 200; - ui_sb_menu_set_item(SB_CDROM|id, IDM_CDROM_IMAGE | id, 1); - ui_sb_icon_state(SB_CDROM|id, 0); - } -#ifdef USE_CDROM_IOCTL - } else { - new_cdrom_drive = cdrom_drives[id].prev_host_drive; - ioctl_open(id, new_cdrom_drive); - if (cdrom_drives[id].bus_type) { - /* Signal disc change to the emulated machine. */ - cdrom_insert(id); - } - ui_sb_menu_set_item(SB_CDROM|id, IDM_CDROM_EMPTY | id, 0); - cdrom_drives[id].host_drive = new_cdrom_drive; - ui_sb_menu_set_item(SB_CDROM|id, IDM_CDROM_HOST_DRIVE | id | ((cdrom_drives[id].host_drive - 'A') << 3), 1); - ui_sb_icon_state(SB_CDROM|id, 0); #endif - } +} - ui_sb_menu_enable_item(SB_CDROM|id, IDM_CDROM_RELOAD | id, 0); - ui_sb_tip_update(SB_CDROM|id); +static int ioctl_hopen(uint8_t id); - config_save(); +void ioctl_audio_callback(uint8_t id, int16_t *output, int len) +{ + cdrom_t *dev = cdrom[id]; + RAW_READ_INFO in; + DWORD count; + + if (!cdrom_drives[id].sound_on || (dev->cd_state != CD_PLAYING)) + { + if (dev->cd_state == CD_PLAYING) + { + dev->seek_pos += (len >> 11); + cdrom_ioctl_log("ioctl_audio_callback(): playing but mute\n"); + } else + cdrom_ioctl_log("ioctl_audio_callback(): not playing\n"); + cdrom_ioctl_windows[id].is_playing = 0; + memset(output, 0, len * 2); + return; + } + cdrom_ioctl_log("ioctl_audio_callback(): dev->cd_buflen = %i, len = %i\n", dev->cd_buflen, len); + while (dev->cd_buflen < len) + { + if (dev->seek_pos < dev->cd_end) + { + in.DiskOffset.LowPart = dev->seek_pos * 2048; + in.DiskOffset.HighPart = 0; + in.SectorCount = 1; + in.TrackMode = CDDA; + if (!DeviceIoControl(cdrom_ioctl_windows[id].hIOCTL, IOCTL_CDROM_RAW_READ, &in, sizeof(in), &(dev->cd_buffer[dev->cd_buflen]), 2352, &count, NULL)) + { + memset(&(dev->cd_buffer[dev->cd_buflen]), 0, (BUF_SIZE - dev->cd_buflen) * 2); + cdrom_ioctl_windows[id].is_playing = 0; + ioctl_close(id); + dev->cd_state = CD_STOPPED; + dev->cd_buflen = len; + cdrom_ioctl_log("ioctl_audio_callback(): read sector error, stopped\n"); + } + else + { + dev->seek_pos++; + dev->cd_buflen += (2352 / 2); + cdrom_ioctl_log("ioctl_audio_callback(): dev->seek_pos = %i\n", dev->seek_pos); + } + } + else + { + memset(&(dev->cd_buffer[dev->cd_buflen]), 0, (BUF_SIZE - dev->cd_buflen) * 2); + cdrom_ioctl_windows[id].is_playing = 0; + ioctl_close(id); + dev->cd_state = CD_STOPPED; + dev->cd_buflen = len; + cdrom_ioctl_log("ioctl_audio_callback(): reached the end\n"); + } + } + memcpy(output, dev->cd_buffer, len * 2); + memcpy(&dev->cd_buffer[0], &(dev->cd_buffer[len]), (BUF_SIZE - len) * 2); + dev->cd_buflen -= len; +} + +void ioctl_audio_stop(uint8_t id) +{ + cdrom_t *dev = cdrom[id]; + + cdrom_ioctl_windows[id].is_playing = 0; + ioctl_close(id); + dev->cd_state = CD_STOPPED; +} + +static int get_track_nr(uint8_t id, uint32_t pos) +{ + cdrom_t *dev = cdrom[id]; + int c; + int track = 0; + + if (dev->disc_changed) + { + return 0; + cdrom_ioctl_log("get_track_nr(): disc changed\n"); + } + + if (cdrom_ioctl[id].last_track_pos == pos) + { + cdrom_ioctl_log("get_track_nr(): cdrom_ioctl[id].last_track_pos == pos\n"); + return cdrom_ioctl[id].last_track_nr; + } + + /* for (c = cdrom_ioctl_windows[id].toc.FirstTrack; c < cdrom_ioctl_windows[id].toc.LastTrack; c++) */ + for (c = 0; c < cdrom_ioctl_windows[id].toc.LastTrack; c++) + { + uint32_t track_address = MSFtoLBA(cdrom_ioctl_windows[id].toc.TrackData[c].Address[1], + cdrom_ioctl_windows[id].toc.TrackData[c].Address[2], + cdrom_ioctl_windows[id].toc.TrackData[c].Address[3]) - 150; + + if (track_address <= pos) + { + cdrom_ioctl_log("get_track_nr(): track = %i\n", c); + track = c; + } + } + cdrom_ioctl[id].last_track_pos = pos; + cdrom_ioctl[id].last_track_nr = track; + + cdrom_ioctl_log("get_track_nr(): return %i\n", track); + return track; +} + +static uint32_t get_track_msf(uint8_t id, uint32_t track_no) +{ + cdrom_t *dev = cdrom[id]; + int c; + + if (dev->disc_changed) + { + return 0; + } + + for (c = cdrom_ioctl_windows[id].toc.FirstTrack; c < cdrom_ioctl_windows[id].toc.LastTrack; c++) + { + if (c == track_no) + { + return cdrom_ioctl_windows[id].toc.TrackData[c].Address[3] + (cdrom_ioctl_windows[id].toc.TrackData[c].Address[2] << 8) + (cdrom_ioctl_windows[id].toc.TrackData[c].Address[1] << 16); + } + } + return 0xffffffff; +} + +static void ioctl_playaudio(uint8_t id, uint32_t pos, uint32_t len, int ismsf) +{ + cdrom_t *dev = cdrom[id]; + int m = 0, s = 0, f = 0; + uint32_t start_msf = 0, end_msf = 0; + if (!cdrom_drives[id].host_drive) + { + return; + } + cdrom_ioctl_log("Play audio - %08X %08X %i\n", pos, len, ismsf); + if (ismsf == 2) + { + start_msf = get_track_msf(id, pos); + end_msf = get_track_msf(id, len); + if (start_msf == 0xffffffff) + { + return; + } + if (end_msf == 0xffffffff) + { + return; + } + m = (start_msf >> 16) & 0xff; + s = (start_msf >> 8) & 0xff; + f = start_msf & 0xff; + pos = MSFtoLBA(m, s, f) - 150; + m = (end_msf >> 16) & 0xff; + s = (end_msf >> 8) & 0xff; + f = end_msf & 0xff; + len = MSFtoLBA(m, s, f) - 150; + } + else if (ismsf == 1) + { + m = (pos >> 16) & 0xff; + s = (pos >> 8) & 0xff; + f = pos & 0xff; + + if (pos == 0xffffff) + { + cdrom_ioctl_log("Playing from current position (MSF)\n"); + pos = dev->seek_pos; + } + else + { + pos = MSFtoLBA(m, s, f) - 150; + } + + m = (len >> 16) & 0xff; + s = (len >> 8) & 0xff; + f = len & 0xff; + len = MSFtoLBA(m, s, f) - 150; + } + else if (ismsf == 0) + { + if (pos == 0xffffffff) + { + cdrom_ioctl_log("Playing from current position\n"); + pos = dev->seek_pos; + } + len += pos; + } + dev->seek_pos = pos; + dev->cd_end = len; + + if (!cdrom_ioctl_windows[id].is_playing) + { + ioctl_hopen(id); + cdrom_ioctl_windows[id].is_playing = 1; + } + dev->cd_state = CD_PLAYING; +} + +static void ioctl_pause(uint8_t id) +{ + cdrom_t *dev = cdrom[id]; + + if (!cdrom_drives[id].host_drive) + { + return; + } + if (dev->cd_state == CD_PLAYING) + { + dev->cd_state = CD_PAUSED; + } +} + +static void ioctl_resume(uint8_t id) +{ + cdrom_t *dev = cdrom[id]; + + if (!cdrom_drives[id].host_drive) + { + return; + } + if (dev->cd_state == CD_PAUSED) + { + dev->cd_state = CD_PLAYING; + } +} + +static void ioctl_stop(uint8_t id) +{ + cdrom_t *dev = cdrom[id]; + + if (!cdrom_drives[id].host_drive) + { + return; + } + if (cdrom_ioctl_windows[id].is_playing) + { + cdrom_ioctl_windows[id].is_playing = 0; + ioctl_close(id); + } + dev->cd_state = CD_STOPPED; +} + +static int ioctl_ready(uint8_t id) +{ + cdrom_t *dev = cdrom[id]; + unsigned long size; + int temp; + CDROM_TOC ltoc; + + if (!cdrom_drives[id].host_drive) + { + return 0; + } + if (cdrom_ioctl_windows[id].hIOCTL == NULL) + { + ioctl_hopen(id); + temp = DeviceIoControl(cdrom_ioctl_windows[id].hIOCTL, IOCTL_CDROM_READ_TOC, NULL, 0, <oc, sizeof(ltoc), &size, NULL); + ioctl_close(id); + } + else + { + temp = DeviceIoControl(cdrom_ioctl_windows[id].hIOCTL, IOCTL_CDROM_READ_TOC, NULL, 0, <oc, sizeof(ltoc), &size, NULL); + } + if (!temp) + { + return 0; + } + if ((ltoc.TrackData[ltoc.LastTrack].Address[1] != cdrom_ioctl_windows[id].toc.TrackData[cdrom_ioctl_windows[id].toc.LastTrack].Address[1]) || + (ltoc.TrackData[ltoc.LastTrack].Address[2] != cdrom_ioctl_windows[id].toc.TrackData[cdrom_ioctl_windows[id].toc.LastTrack].Address[2]) || + (ltoc.TrackData[ltoc.LastTrack].Address[3] != cdrom_ioctl_windows[id].toc.TrackData[cdrom_ioctl_windows[id].toc.LastTrack].Address[3]) || + dev->disc_changed || (cdrom_drives[id].host_drive != cdrom_drives[id].prev_host_drive)) + { + dev->cd_state = CD_STOPPED; + if (cdrom_drives[id].host_drive != cdrom_drives[id].prev_host_drive) + { + cdrom_drives[id].prev_host_drive = cdrom_drives[id].host_drive; + } + return 1; + } + return 1; +} + +static int ioctl_get_last_block(uint8_t id, unsigned char starttrack, int msf, int maxlen, int single) +{ + cdrom_t *dev = cdrom[id]; + unsigned long size; + int c, d = 0; + CDROM_TOC lbtoc; + uint32_t lb = 0; + if (!cdrom_drives[id].host_drive) + { + return 0; + } + dev->cd_state = CD_STOPPED; + ioctl_hopen(id); + DeviceIoControl(cdrom_ioctl_windows[id].hIOCTL, IOCTL_CDROM_READ_TOC, NULL, 0, &lbtoc, sizeof(lbtoc), &size, NULL); + ioctl_close(id); + dev->disc_changed=0; + for (c=d; c <= lbtoc.LastTrack; c++) + { + uint32_t address; + address = MSFtoLBA(cdrom_ioctl_windows[id].toc.TrackData[c].Address[1], cdrom_ioctl_windows[id].toc.TrackData[c].Address[2], cdrom_ioctl_windows[id].toc.TrackData[c].Address[3]); + if (address > lb) + { + lb = address; + } + } + return lb; +} + +static void ioctl_read_capacity(uint8_t id, uint8_t *b); + +static int ioctl_medium_changed(uint8_t id) +{ + cdrom_t *dev = cdrom[id]; + unsigned long size; + int temp; + CDROM_TOC ltoc; + if (!cdrom_drives[id].host_drive) + { + return 0; /* This will be handled by the not ready handler instead. */ + } + ioctl_hopen(id); + temp = DeviceIoControl(cdrom_ioctl_windows[id].hIOCTL, IOCTL_CDROM_READ_TOC, NULL, 0, <oc,sizeof(ltoc), &size, NULL); + ioctl_close(id); + if (!temp) + { + return 0; /* Drive empty, a not ready handler matter, not disc change. */ + } + if (dev->disc_changed || (cdrom_drives[id].host_drive != cdrom_drives[id].prev_host_drive)) + { + dev->cd_state = CD_STOPPED; + cdrom_ioctl_windows[id].toc = ltoc; + dev->disc_changed = 0; + if (cdrom_drives[id].host_drive != cdrom_drives[id].prev_host_drive) + { + cdrom_drives[id].prev_host_drive = cdrom_drives[id].host_drive; + } + ioctl_hopen(id); + cdrom_ioctl[id].capacity_read=0; /* With this two lines, we read the READ CAPACITY command output from the host drive into our cache buffer. */ + ioctl_read_capacity(id, NULL); + ioctl_close(id); + dev->cdrom_capacity = ioctl_get_last_block(id, 0, 0, 4096, 0); + return 1; + } + else + { + if ((ltoc.TrackData[ltoc.LastTrack].Address[1] != cdrom_ioctl_windows[id].toc.TrackData[cdrom_ioctl_windows[id].toc.LastTrack].Address[1]) || + (ltoc.TrackData[ltoc.LastTrack].Address[2] != cdrom_ioctl_windows[id].toc.TrackData[cdrom_ioctl_windows[id].toc.LastTrack].Address[2]) || + (ltoc.TrackData[ltoc.LastTrack].Address[3] != cdrom_ioctl_windows[id].toc.TrackData[cdrom_ioctl_windows[id].toc.LastTrack].Address[3])) + { + dev->cd_state = CD_STOPPED; + cdrom_ioctl_log("Setting TOC...\n"); + cdrom_ioctl_windows[id].toc = ltoc; + ioctl_hopen(id); + cdrom_ioctl[id].capacity_read=0; /* With this two lines, we read the READ CAPACITY command output from the host drive into our cache buffer. */ + ioctl_read_capacity(id, NULL); + ioctl_close(id); + dev->cdrom_capacity = ioctl_get_last_block(id, 0, 0, 4096, 0); + return 1; /* TOC mismatches. */ + } + } + return 0; /* None of the above, return 0. */ +} + +static uint8_t ioctl_getcurrentsubchannel(uint8_t id, uint8_t *b, int msf) +{ + cdrom_t *dev = cdrom[id]; + CDROM_SUB_Q_DATA_FORMAT insub; + SUB_Q_CHANNEL_DATA sub; + unsigned long size; + int pos = 0, track; + uint32_t cdpos, track_address, dat; + + if (!cdrom_drives[id].host_drive) return 0; + + cdpos = dev->seek_pos; + + if (dev->last_subchannel_pos == cdpos) + { + memcpy(&insub, dev->sub_q_data_format, sizeof(insub)); + memcpy(&sub, dev->sub_q_channel_data, sizeof(sub)); + } + else + { + insub.Format = IOCTL_CDROM_CURRENT_POSITION; + ioctl_hopen(id); + DeviceIoControl(cdrom_ioctl_windows[id].hIOCTL,IOCTL_CDROM_READ_Q_CHANNEL,&insub,sizeof(insub),&sub,sizeof(sub),&size,NULL); + ioctl_close(id); + memset(dev->sub_q_data_format, 0, 16); + memcpy(dev->sub_q_data_format, &insub, sizeof(insub)); + memset(dev->sub_q_channel_data, 0, 256); + memcpy(dev->sub_q_channel_data, &sub, sizeof(sub)); + dev->last_subchannel_pos = cdpos; + } + + if (dev->cd_state == CD_PLAYING || dev->cd_state == CD_PAUSED) + { + track = get_track_nr(id, cdpos); + track_address = MSFtoLBA(cdrom_ioctl_windows[id].toc.TrackData[track].Address[1], + cdrom_ioctl_windows[id].toc.TrackData[track].Address[2], + cdrom_ioctl_windows[id].toc.TrackData[track].Address[3]) - 150; + + cdrom_ioctl_log("ioctl_getcurrentsubchannel(): cdpos = %i, track = %i, track_address = %i\n", cdpos, track, track_address); + + b[pos++] = sub.CurrentPosition.Control; + b[pos++] = track + 1; + b[pos++] = sub.CurrentPosition.IndexNumber; + + if (msf) + { + dat = cdpos + 150; + b[pos + 3] = (uint8_t)(dat % 75); dat /= 75; + b[pos + 2] = (uint8_t)(dat % 60); dat /= 60; + b[pos + 1] = (uint8_t)dat; + b[pos] = 0; + pos += 4; + dat = cdpos - track_address; + b[pos + 3] = (uint8_t)(dat % 75); dat /= 75; + b[pos + 2] = (uint8_t)(dat % 60); dat /= 60; + b[pos + 1] = (uint8_t)dat; + b[pos] = 0; + pos += 4; + } + else + { + b[pos++] = (cdpos >> 24) & 0xff; + b[pos++] = (cdpos >> 16) & 0xff; + b[pos++] = (cdpos >> 8) & 0xff; + b[pos++] = cdpos & 0xff; + cdpos -= track_address; + b[pos++] = (cdpos >> 24) & 0xff; + b[pos++] = (cdpos >> 16) & 0xff; + b[pos++] = (cdpos >> 8) & 0xff; + b[pos++] = cdpos & 0xff; + } + + if (dev->cd_state == CD_PLAYING) return 0x11; + return 0x12; + } + + b[pos++]=sub.CurrentPosition.Control; + b[pos++]=sub.CurrentPosition.TrackNumber; + b[pos++]=sub.CurrentPosition.IndexNumber; + + cdrom_ioctl_log("cdpos = %i, track_address = %i\n", MSFtoLBA(sub.CurrentPosition.AbsoluteAddress[1], sub.CurrentPosition.AbsoluteAddress[2], sub.CurrentPosition.AbsoluteAddress[3]), MSFtoLBA(sub.CurrentPosition.TrackRelativeAddress[1], sub.CurrentPosition.TrackRelativeAddress[2], sub.CurrentPosition.TrackRelativeAddress[3])); + + if (msf) + { + int c; + for (c = 0; c < 4; c++) + { + b[pos++] = sub.CurrentPosition.AbsoluteAddress[c]; + } + for (c = 0; c < 4; c++) + { + b[pos++] = sub.CurrentPosition.TrackRelativeAddress[c]; + } + } + else + { + uint32_t temp = MSFtoLBA(sub.CurrentPosition.AbsoluteAddress[1], sub.CurrentPosition.AbsoluteAddress[2], sub.CurrentPosition.AbsoluteAddress[3]) - 150; + b[pos++] = temp >> 24; + b[pos++] = temp >> 16; + b[pos++] = temp >> 8; + b[pos++] = temp; + temp = MSFtoLBA(sub.CurrentPosition.TrackRelativeAddress[1], sub.CurrentPosition.TrackRelativeAddress[2], sub.CurrentPosition.TrackRelativeAddress[3]) - 150; + b[pos++] = temp >> 24; + b[pos++] = temp >> 16; + b[pos++] = temp >> 8; + b[pos++] = temp; + } + + return 0x13; +} + +static void ioctl_eject(uint8_t id) +{ + cdrom_t *dev = cdrom[id]; + unsigned long size; + if (!cdrom_drives[id].host_drive) + { + return; + } + if (cdrom_ioctl_windows[id].is_playing) + { + cdrom_ioctl_windows[id].is_playing = 0; + ioctl_stop(id); + } + dev->cd_state = CD_STOPPED; + ioctl_hopen(id); + DeviceIoControl(cdrom_ioctl_windows[id].hIOCTL,IOCTL_STORAGE_EJECT_MEDIA,NULL,0,NULL,0,&size,NULL); + ioctl_close(id); +} + +static void ioctl_load(uint8_t id) +{ + cdrom_t *dev = cdrom[id]; + unsigned long size; + if (!cdrom_drives[id].host_drive) + { + return; + } + if (cdrom_ioctl_windows[id].is_playing) + { + cdrom_ioctl_windows[id].is_playing = 0; + ioctl_stop(id); + } + dev->cd_state = CD_STOPPED; + ioctl_hopen(id); + DeviceIoControl(cdrom_ioctl_windows[id].hIOCTL,IOCTL_STORAGE_LOAD_MEDIA,NULL,0,NULL,0,&size,NULL); + cdrom_ioctl[id].capacity_read=0; /* With this two lines, we read the READ CAPACITY command output from the host drive into our cache buffer. */ + ioctl_read_capacity(id, NULL); + ioctl_close(id); + dev->cdrom_capacity = ioctl_get_last_block(id, 0, 0, 4096, 0); +} + +static int ioctl_is_track_audio(uint8_t id, uint32_t pos, int ismsf) +{ + cdrom_t *dev = cdrom[id]; + int c; + int control = 0; + + uint32_t track_address = 0; + + if (dev->disc_changed) + { + return 0; + } + + for (c = 0; cdrom_ioctl_windows[id].toc.TrackData[c].TrackNumber != 0xaa; c++) + { + if (ismsf) { + track_address = cdrom_ioctl_windows[id].toc.TrackData[c].Address[3]; + track_address |= (cdrom_ioctl_windows[id].toc.TrackData[c].Address[2] << 8); + track_address |= (cdrom_ioctl_windows[id].toc.TrackData[c].Address[1] << 16); + } else { + track_address = MSFtoLBA(cdrom_ioctl_windows[id].toc.TrackData[c].Address[1],cdrom_ioctl_windows[id].toc.TrackData[c].Address[2],cdrom_ioctl_windows[id].toc.TrackData[c].Address[3]); + track_address -= 150; + } + + if (cdrom_ioctl_windows[id].toc.TrackData[c].TrackNumber >= cdrom_ioctl_windows[id].toc.FirstTrack && + cdrom_ioctl_windows[id].toc.TrackData[c].TrackNumber <= cdrom_ioctl_windows[id].toc.LastTrack && + track_address <= pos) + control = cdrom_ioctl_windows[id].toc.TrackData[c].Control; + } + + if ((control & 0xd) <= 1) + return 1; + else + return 0; +} + +/* 00, 08, 10, 18, 20, 28, 30, 38 */ +static const int flags_to_size[5][32] = { { 0, 0, 2352, 2352, 2352, 2352, 2352, 2352, /* 00-38 (CD-DA) */ + 2352, 2352, 2352, 2352, 2352, 2352, 2352, 2352, /* 40-78 */ + 2352, 2352, 2352, 2352, 2352, 2352, 2352, 2352, /* 80-B8 */ + 2352, 2352, 2352, 2352, 2352, 2352, 2352, 2352 }, /* C0-F8 */ + { 0, 0, 2048, 2336, 4, -296, 2052, 2344, /* 00-38 (Mode 1) */ + 8, -296, 2048, 2048, 12, -296, 2052, 2052, /* 40-78 */ + -296, -296, -296, -296, 16, -296, 2064, 2344, /* 80-B8 */ + -296, -296, 2048, 2048, 24, -296, 2064, 2352 }, /* C0-F8 */ + { 0, 0, 2336, 2336, 4, -296, 2340, 2340, /* 00-38 (Mode 2 non-XA) */ + 8, -296, 2336, 2336, 12, -296, 2340, 2340, /* 40-78 */ + -296, -296, -296, -296, 16, -296, 2352, 2340, /* 80-B8 */ + -296, -296, 2336, 2336, 24, -296, 2352, 2352 }, /* C0-F8 */ + { 0, 0, 2048, 2336, 4, -296, -296, -296, /* 00-38 (Mode 2 Form 1) */ + 8, -296, 2056, 2344, 12, -296, 2060, 2340, /* 40-78 */ + -296, -296, -296, -296, 16, -296, -296, -296, /* 80-B8 */ + -296, -296, -296, -296, 24, -296, 2072, 2352 }, /* C0-F8 */ + { 0, 0, 2328, 2328, 4, -296, -296, -296, /* 00-38 (Mode 2 Form 2) */ + 8, -296, 2336, 2336, 12, -296, 2340, 2340, /* 40-78 */ + -296, -296, -296, -296, 16, -296, -296, -296, /* 80-B8 */ + -296, -296, -296, -296, 24, -296, 2352, 2352 } /* C0-F8 */ + }; + +static int ioctl_get_sector_data_type(uint8_t id, uint8_t b0, uint8_t b1, uint8_t b2, uint8_t b3, int ismsf); + +static void cdrom_illegal_mode(uint8_t id) +{ + cdrom_sense_key = SENSE_ILLEGAL_REQUEST; + cdrom_asc = ASC_ILLEGAL_MODE_FOR_THIS_TRACK; + cdrom_ascq = 0; +} + +/* FIXME: allocate on heap! */ +struct sptd_with_sense +{ + SCSI_PASS_THROUGH s; + ULONG Filler; + UCHAR sense[32]; + UCHAR data[65536]; +} sptd; + +static int ioctl_get_block_length(uint8_t id, const UCHAR *cdb, int number_of_blocks, int no_length_check) +{ + cdrom_t *dev = cdrom[id]; + int sector_type = 0; + int temp_len = 0; + + if (no_length_check) + { + switch (cdb[0]) + { + case 0x25: /* READ CAPACITY */ + case 0x44: /* READ HEADER */ + return 8; + case 0x42: /* READ SUBCHANNEL */ + case 0x43: /* READ TOC */ + case 0x51: /* READ DISC INFORMATION */ + case 0x52: /* READ TRACK INFORMATION */ + case 0x5A: /* MODE SENSE (10) */ + return (((uint32_t) cdb[7]) << 8) | ((uint32_t) cdb[8]); + case 0xAD: /* READ DVD STRUCTURE */ + return (((uint32_t) cdb[8]) << 8) | ((uint32_t) cdb[9]); + default: + return 65534; + } + } + + switch (cdb[0]) + { + case 0x25: /* READ CAPACITY */ + case 0x44: /* READ HEADER */ + return 8; + case 0x42: /* READ SUBCHANNEL */ + case 0x43: /* READ TOC */ + case 0x51: /* READ DISC INFORMATION */ + case 0x52: /* READ TRACK INFORMATION */ + case 0x5A: /* MODE SENSE (10) */ + return (((uint32_t) cdb[7]) << 8) | ((uint32_t) cdb[8]); + case 0xAD: /* READ DVD STRUCTURE */ + return (((uint32_t) cdb[8]) << 8) | ((uint32_t) cdb[9]); + case 0x08: + case 0x28: + case 0xa8: + /* READ (6), READ (10), READ (12) */ + return 2048 * number_of_blocks; + + case 0xb9: + sector_type = (cdb[1] >> 2) & 7; + if (sector_type == 0) + { + sector_type = ioctl_get_sector_data_type(id, 0, cdb[3], cdb[4], cdb[5], 1); + if (sector_type == 0) + { + cdrom_illegal_mode(id); + return -1; + } + } + goto common_handler; + case 0xbe: + /* READ CD MSF, READ CD */ + sector_type = (cdb[1] >> 2) & 7; + if (sector_type == 0) + { + sector_type = ioctl_get_sector_data_type(id, cdb[2], cdb[3], cdb[4], cdb[5], 0); + if (sector_type == 0) + { + cdrom_illegal_mode(id); + return -1; + } + } +common_handler: + temp_len = flags_to_size[sector_type - 1][cdb[9] >> 3]; + if ((cdb[9] & 6) == 2) + { + temp_len += 294; + } + else if ((cdb[9] & 6) == 4) + { + temp_len += 296; + } + if ((cdb[10] & 7) == 1) + { + temp_len += 96; + } + else if ((cdb[10] & 7) == 2) + { + temp_len += 16; + } + else if ((cdb[10] & 7) == 4) + { + temp_len += 96; + } + if (temp_len <= 0) + { + cdrom_illegal_mode(id); + return -1; + } + return temp_len * dev->requested_blocks; + + default: + /* Other commands */ + return 65534; + + } + +} + +static int SCSICommand(uint8_t id, const UCHAR *cdb, UCHAR *buf, uint32_t *len, int no_length_check) +{ + DWORD ioctl_bytes; + int ioctl_rv = 0; + + SCSISense.SenseKey = 0; + SCSISense.Asc = 0; + SCSISense.Ascq = 0; + + *len = 0; + memset(&sptd, 0, sizeof(sptd)); + sptd.s.Length = sizeof(SCSI_PASS_THROUGH); + sptd.s.CdbLength = 12; + sptd.s.DataIn = SCSI_IOCTL_DATA_IN; + sptd.s.TimeOutValue = 80 * 60; + sptd.s.DataTransferLength = ioctl_get_block_length(id, cdb, cdrom_ioctl[id].actual_requested_blocks, no_length_check); + sptd.s.SenseInfoOffset = (uintptr_t)&sptd.sense - (uintptr_t)&sptd; + sptd.s.SenseInfoLength = 32; + sptd.s.DataBufferOffset = (uintptr_t)&sptd.data - (uintptr_t)&sptd; + + memcpy(sptd.s.Cdb, cdb, 12); + ioctl_rv = DeviceIoControl(cdrom_ioctl_windows[id].hIOCTL, IOCTL_SCSI_PASS_THROUGH, &sptd, sizeof(sptd), &sptd, sizeof(sptd), &ioctl_bytes, NULL); + + if (sptd.s.SenseInfoLength) + { + cdrom_sense_key = sptd.sense[2]; + cdrom_asc = sptd.sense[12]; + cdrom_ascq = sptd.sense[13]; + } + + cdrom_ioctl_log("Transferred length: %i (command: %02X)\n", sptd.s.DataTransferLength, cdb[0]); + cdrom_ioctl_log("Sense length: %i (%02X %02X %02X %02X %02X)\n", sptd.s.SenseInfoLength, sptd.sense[0], sptd.sense[1], sptd.sense[2], sptd.sense[12], sptd.sense[13]); + cdrom_ioctl_log("IOCTL bytes: %i; SCSI status: %i, status: %i, LastError: %08X\n", ioctl_bytes, sptd.s.ScsiStatus, ioctl_rv, GetLastError()); + cdrom_ioctl_log("DATA: %02X %02X %02X %02X %02X %02X\n", sptd.data[0], sptd.data[1], sptd.data[2], sptd.data[3], sptd.data[4], sptd.data[5]); + cdrom_ioctl_log(" %02X %02X %02X %02X %02X %02X\n", sptd.data[6], sptd.data[7], sptd.data[8], sptd.data[9], sptd.data[10], sptd.data[11]); + cdrom_ioctl_log(" %02X %02X %02X %02X %02X %02X\n", sptd.data[12], sptd.data[13], sptd.data[14], sptd.data[15], sptd.data[16], sptd.data[17]); + cdrom_ioctl_log("SENSE: %02X %02X %02X %02X %02X %02X\n", sptd.sense[0], sptd.sense[1], sptd.sense[2], sptd.sense[3], sptd.sense[4], sptd.sense[5]); + cdrom_ioctl_log(" %02X %02X %02X %02X %02X %02X\n", sptd.sense[6], sptd.sense[7], sptd.sense[8], sptd.sense[9], sptd.sense[10], sptd.sense[11]); + cdrom_ioctl_log(" %02X %02X %02X %02X %02X %02X\n", sptd.sense[12], sptd.sense[13], sptd.sense[14], sptd.sense[15], sptd.sense[16], sptd.sense[17]); + *len = sptd.s.DataTransferLength; + if (sptd.s.DataTransferLength != 0) + { + memcpy(buf, sptd.data, sptd.s.DataTransferLength); + } + + return ioctl_rv; +} + +static void ioctl_read_capacity(uint8_t id, uint8_t *b) +{ + cdrom_t *dev = cdrom[id]; + uint32_t len = 0; + + const UCHAR cdb[] = { 0x25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + UCHAR buf[16]; + + if (!cdrom_ioctl[id].capacity_read || (b == NULL)) + { + SCSICommand(id, cdb, buf, &len, 1); + + memcpy(dev->rcbuf, buf, len); + cdrom_ioctl[id].capacity_read = 1; + } + else + { + memcpy(b, dev->rcbuf, 16); + } +} + +static int ioctl_media_type_id(uint8_t id) +{ + uint8_t old_sense[3] = { 0, 0, 0 }; + + UCHAR msbuf[28]; + uint32_t len = 0; + int sense = 0; + + const UCHAR cdb[] = { 0x5A, 0x00, 0x2A, 0, 0, 0, 0, 0, 28, 0, 0, 0 }; + + old_sense[0] = cdrom_sense_key; + old_sense[1] = cdrom_asc; + old_sense[2] = cdrom_asc; + + ioctl_hopen(id); + + SCSICommand(id, cdb, msbuf, &len, 1); + + ioctl_close(id); + + sense = cdrom_sense_key; + cdrom_sense_key = old_sense[0]; + cdrom_asc = old_sense[1]; + cdrom_asc = old_sense[2]; + + if (sense == 0) + { + return msbuf[2]; + } + else + { + return 3; + } +} + +static uint32_t msf_to_lba32(int lba) +{ + int m = (lba >> 16) & 0xff; + int s = (lba >> 8) & 0xff; + int f = lba & 0xff; + return (m * 60 * 75) + (s * 75) + f; +} + +static int ioctl_get_type(uint8_t id, UCHAR *cdb, UCHAR *buf) +{ + int i = 0; + int ioctl_rv = 0; + + uint32_t len = 0; + + for (i = 2; i <= 5; i++) + { + cdb[1] = i << 2; + ioctl_rv = SCSICommand(id, cdb, buf, &len, 1); /* Bypass length check so we don't risk calling this again and getting stuck in an endless up. */ + if (ioctl_rv) + { + return i; + } + } + return 0; +} + +static int ioctl_sector_data_type(uint8_t id, int sector, int ismsf) +{ + int ioctl_rv = 0; + UCHAR cdb_lba[] = { 0xBE, 0, 0, 0, 0, 0, 0, 0, 1, 0x10, 0, 0 }; + UCHAR cdb_msf[] = { 0xB9, 0, 0, 0, 0, 0, 0, 0, 0, 0x10, 0, 0 }; + UCHAR buf[2352]; + + cdb_lba[2] = (sector >> 24); + cdb_lba[3] = ((sector >> 16) & 0xff); + cdb_lba[4] = ((sector >> 8) & 0xff); + cdb_lba[5] = (sector & 0xff); + + cdb_msf[3] = cdb_msf[6] = ((sector >> 16) & 0xff); + cdb_msf[4] = cdb_msf[7] = ((sector >> 8) & 0xff); + cdb_msf[5] = cdb_msf[8] = (sector & 0xff); + + ioctl_hopen(id); + + if (ioctl_is_track_audio(id, sector, ismsf)) + { + return 1; + } + + if (ismsf) + { + ioctl_rv = ioctl_get_type(id, cdb_msf, buf); + } + else + { + ioctl_rv = ioctl_get_type(id, cdb_lba, buf); + } + + if (ioctl_rv) + { + ioctl_close(id); + return ioctl_rv; + } + + if (ismsf) + { + sector = msf_to_lba32(sector); + if (sector < 150) + { + ioctl_close(id); + return 0; + } + sector -= 150; + ioctl_rv = ioctl_get_type(id, (UCHAR *) cdb_lba, buf); + } + + ioctl_close(id); + return ioctl_rv; +} + +static int ioctl_get_sector_data_type(uint8_t id, uint8_t b0, uint8_t b1, uint8_t b2, uint8_t b3, int ismsf) +{ + int sector = b3; + sector |= ((uint32_t) b2) << 8; + sector |= ((uint32_t) b1) << 16; + sector |= ((uint32_t) b0) << 24; + return ioctl_sector_data_type(id, sector, ismsf); +} + +static void ioctl_validate_toc(uint8_t id) +{ + cdrom_t *dev = cdrom[id]; + unsigned long size; + if (!cdrom_drives[id].host_drive) + { + return; + } + dev->cd_state = CD_STOPPED; + ioctl_hopen(id); + cdrom_ioctl_log("Validating TOC...\n"); + DeviceIoControl(cdrom_ioctl_windows[id].hIOCTL,IOCTL_CDROM_READ_TOC, NULL,0,&cdrom_ioctl_windows[id].toc,sizeof(cdrom_ioctl_windows[id].toc),&size,NULL); + ioctl_close(id); + dev->disc_changed = 0; +} + +/* FIXME: malloc this as needed? */ +UCHAR buf[262144]; + +static int ioctl_pass_through(uint8_t id, uint8_t *in_cdb, uint8_t *b, uint32_t *len) +{ + cdrom_t *dev = cdrom[id]; + const UCHAR cdb[12]; + + int ret = 0; + + int temp_block_length = 0; + int buffer_pos = 0; + + uint32_t temp_len = 0; + + int i = 0; + + if (in_cdb[0] == 0x43) + { + /* This is a read TOC, so we have to validate the TOC to make the rest of the emulator happy. */ + ioctl_validate_toc(id); + } + + ioctl_hopen(id); + + memcpy((void *) cdb, in_cdb, 12); + + temp_len = 0; + temp_block_length = ioctl_get_block_length(id, cdb, dev->requested_blocks, 0); + if (temp_block_length != -1) { + cdrom_ioctl[id].actual_requested_blocks = 1; + if ((cdb[0] == 0x08) || (cdb[0] == 0x28) || (cdb[0] == 0xA8) || (cdb[0] == 0xB9) || (cdb[0] == 0xBE)) { + buffer_pos = 0; + temp_len = 0; + + for (i = 0; i < dev->requested_blocks; i++) + { + cdrom_ioctl_log("CD-ROM %i: ioctl_pass_through(): Transferring block...\n", id, cdrom_ioctl[id].actual_requested_blocks); + cdrom_update_cdb((uint8_t *) cdb, dev->sector_pos + i, 1); + ret = SCSICommand(id, cdb, b + buffer_pos, &temp_len, 0); + buffer_pos += temp_len; + } + *len = buffer_pos; + } else { + cdrom_ioctl_log("CD-ROM %i: ioctl_pass_through(): Expected transfer length %i is smaller than 65534, transferring all at once...\n", id, temp_block_length); + ret = SCSICommand(id, cdb, b, len, 0); + cdrom_ioctl_log("CD-ROM %i: ioctl_pass_through(): Single transfer done\n", id); + } + } + + cdrom_ioctl_log("IOCTL DATA: %02X %02X %02X %02X %02X %02X %02X %02X\n", b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7]); + + ioctl_close(id); + + cdrom_ioctl_log("IOCTL Returned value: %i\n", ret); + + return ret; +} + +static int ioctl_readtoc(uint8_t id, unsigned char *b, unsigned char starttrack, int msf, int maxlen, int single) +{ + cdrom_t *dev = cdrom[id]; + int len=4; + DWORD size; + int c,d; + uint32_t temp; + uint32_t last_block; + if (!cdrom_drives[id].host_drive) + { + return 0; + } + dev->cd_state = CD_STOPPED; + ioctl_hopen(id); + DeviceIoControl(cdrom_ioctl_windows[id].hIOCTL,IOCTL_CDROM_READ_TOC, NULL,0,&cdrom_ioctl_windows[id].toc,sizeof(cdrom_ioctl_windows[id].toc),&size,NULL); + ioctl_close(id); + dev->disc_changed = 0; + b[2]=cdrom_ioctl_windows[id].toc.FirstTrack; + b[3]=cdrom_ioctl_windows[id].toc.LastTrack; + d=0; + for (c=0;c<=cdrom_ioctl_windows[id].toc.LastTrack;c++) + { + if (cdrom_ioctl_windows[id].toc.TrackData[c].TrackNumber>=starttrack) + { + d=c; + break; + } + } + last_block = 0; + for (c=d;c<=cdrom_ioctl_windows[id].toc.LastTrack;c++) + { + uint32_t address; + if ((len+8)>maxlen) break; + b[len++]=0; /*Reserved*/ + b[len++]=(cdrom_ioctl_windows[id].toc.TrackData[c].Adr<<4)|cdrom_ioctl_windows[id].toc.TrackData[c].Control; + b[len++]=cdrom_ioctl_windows[id].toc.TrackData[c].TrackNumber; + b[len++]=0; /*Reserved*/ + address = MSFtoLBA(cdrom_ioctl_windows[id].toc.TrackData[c].Address[1],cdrom_ioctl_windows[id].toc.TrackData[c].Address[2],cdrom_ioctl_windows[id].toc.TrackData[c].Address[3]); + if (address > last_block) + last_block = address; + + if (msf) + { + b[len++]=cdrom_ioctl_windows[id].toc.TrackData[c].Address[0]; + b[len++]=cdrom_ioctl_windows[id].toc.TrackData[c].Address[1]; + b[len++]=cdrom_ioctl_windows[id].toc.TrackData[c].Address[2]; + b[len++]=cdrom_ioctl_windows[id].toc.TrackData[c].Address[3]; + } + else + { + temp=MSFtoLBA(cdrom_ioctl_windows[id].toc.TrackData[c].Address[1],cdrom_ioctl_windows[id].toc.TrackData[c].Address[2],cdrom_ioctl_windows[id].toc.TrackData[c].Address[3]) - 150; + b[len++]=temp>>24; + b[len++]=temp>>16; + b[len++]=temp>>8; + b[len++]=temp; + } + if (single) break; + } + b[0] = (uint8_t)(((len-2) >> 8) & 0xff); + b[1] = (uint8_t)((len-2) & 0xff); + return len; +} + +static int ioctl_readtoc_session(uint8_t id, unsigned char *b, int msf, int maxlen) +{ + cdrom_t *dev = cdrom[id]; + int len=4; + int size; + uint32_t temp; + CDROM_READ_TOC_EX toc_ex; + CDROM_TOC_SESSION_DATA toc; + if (!cdrom_drives[id].host_drive) + { + return 0; + } + dev->cd_state = CD_STOPPED; + memset(&toc_ex,0,sizeof(toc_ex)); + memset(&toc,0,sizeof(toc)); + toc_ex.Format=CDROM_READ_TOC_EX_FORMAT_SESSION; + toc_ex.Msf=msf; + toc_ex.SessionTrack=0; + ioctl_hopen(id); + DeviceIoControl(cdrom_ioctl_windows[id].hIOCTL,IOCTL_CDROM_READ_TOC_EX, &toc_ex,sizeof(toc_ex),&toc,sizeof(toc),(PDWORD)&size,NULL); + ioctl_close(id); + b[2]=toc.FirstCompleteSession; + b[3]=toc.LastCompleteSession; + b[len++]=0; /*Reserved*/ + b[len++]=(toc.TrackData[0].Adr<<4)|toc.TrackData[0].Control; + b[len++]=toc.TrackData[0].TrackNumber; + b[len++]=0; /*Reserved*/ + if (msf) + { + b[len++]=toc.TrackData[0].Address[0]; + b[len++]=toc.TrackData[0].Address[1]; + b[len++]=toc.TrackData[0].Address[2]; + b[len++]=toc.TrackData[0].Address[3]; + } + else + { + temp=MSFtoLBA(toc.TrackData[0].Address[1],toc.TrackData[0].Address[2],toc.TrackData[0].Address[3]) - 150; + b[len++]=temp>>24; + b[len++]=temp>>16; + b[len++]=temp>>8; + b[len++]=temp; + } + + return len; +} + +static int ioctl_readtoc_raw(uint8_t id, uint8_t *b, int maxlen) +{ + cdrom_t *dev = cdrom[id]; + int len=4; + int size; + int i; + CDROM_READ_TOC_EX toc_ex; + CDROM_TOC_FULL_TOC_DATA toc; + if (!cdrom_drives[id].host_drive) + { + return 0; + } + dev->cd_state = CD_STOPPED; + memset(&toc_ex,0,sizeof(toc_ex)); + memset(&toc,0,sizeof(toc)); + toc_ex.Format=CDROM_READ_TOC_EX_FORMAT_FULL_TOC; + toc_ex.Msf=1; + toc_ex.SessionTrack=0; + ioctl_hopen(id); + DeviceIoControl(cdrom_ioctl_windows[id].hIOCTL,IOCTL_CDROM_READ_TOC_EX, &toc_ex,sizeof(toc_ex),&toc,sizeof(toc),(PDWORD)&size,NULL); + ioctl_close(id); + if (maxlen >= 3) b[2]=toc.FirstCompleteSession; + if (maxlen >= 4) b[3]=toc.LastCompleteSession; + + if (len >= maxlen) return len; + + size -= sizeof(CDROM_TOC_FULL_TOC_DATA); + size /= sizeof(toc.Descriptors[0]); + + for (i = 0; i <= size; i++) + { + b[len++]=toc.Descriptors[i].SessionNumber; + if (len == maxlen) return len; + b[len++]=(toc.Descriptors[i].Adr<<4)|toc.Descriptors[i].Control; + if (len == maxlen) return len; + b[len++]=0; + if (len == maxlen) return len; + b[len++]=toc.Descriptors[i].Reserved1; /*Reserved*/ + if (len == maxlen) return len; + b[len++]=toc.Descriptors[i].MsfExtra[0]; + if (len == maxlen) return len; + b[len++]=toc.Descriptors[i].MsfExtra[1]; + if (len == maxlen) return len; + b[len++]=toc.Descriptors[i].MsfExtra[2]; + if (len == maxlen) return len; + b[len++]=toc.Descriptors[i].Zero; + if (len == maxlen) return len; + b[len++]=toc.Descriptors[i].Msf[0]; + if (len == maxlen) return len; + b[len++]=toc.Descriptors[i].Msf[1]; + if (len == maxlen) return len; + b[len++]=toc.Descriptors[i].Msf[2]; + if (len == maxlen) return len; + } + + return len; +} + +static uint32_t ioctl_size(uint8_t id) +{ + uint8_t capacity_buffer[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + uint32_t capacity = 0; + + ioctl_read_capacity(id, capacity_buffer); + capacity = ((uint32_t) capacity_buffer[0]) << 24; + capacity |= ((uint32_t) capacity_buffer[1]) << 16; + capacity |= ((uint32_t) capacity_buffer[2]) << 8; + capacity |= (uint32_t) capacity_buffer[3]; + return capacity + 1; +} + +static int ioctl_status(uint8_t id) +{ + cdrom_t *dev = cdrom[id]; + + if (!(ioctl_ready(id)) && (cdrom_drives[id].host_drive <= 0)) + { + return CD_STATUS_EMPTY; + } + + switch(dev->cd_state) + { + case CD_PLAYING: + return CD_STATUS_PLAYING; + case CD_PAUSED: + return CD_STATUS_PAUSED; + case CD_STOPPED: + return CD_STATUS_STOPPED; + default: + return CD_STATUS_EMPTY; + } } void -zip_eject(uint8_t id) +ioctl_reset(uint8_t id) { - zip_close(id); - if (zip_drives[id].bus_type) { - /* Signal disk change to the emulated machine. */ - zip_insert(id); - } + cdrom_t *dev = cdrom[id]; + CDROM_TOC ltoc; + unsigned long size; - ui_sb_icon_state(SB_ZIP | id, 1); - ui_sb_menu_enable_item(SB_ZIP|id, IDM_ZIP_EJECT | id, 0); - ui_sb_menu_enable_item(SB_ZIP|id, IDM_ZIP_RELOAD | id, 1); - ui_sb_tip_update(SB_ZIP | id); - config_save(); -} - - -void -zip_reload(uint8_t id) -{ - zip_disk_reload(id); - if (wcslen(zip_drives[id].image_path) == 0) { - ui_sb_menu_enable_item(SB_ZIP|id, IDM_ZIP_EJECT | id, 0); - ui_sb_icon_state(SB_ZIP|id, 1); - } else { - ui_sb_menu_enable_item(SB_ZIP|id, IDM_ZIP_EJECT | id, 1); - ui_sb_icon_state(SB_ZIP|id, 0); - } - - ui_sb_menu_enable_item(SB_ZIP|id, IDM_ZIP_RELOAD | id, 0); - ui_sb_tip_update(SB_ZIP|id); - - config_save(); -} - - -void -removable_disk_unload(uint8_t id) -{ - if (wcslen(hdd[id].fn) == 0) { - /* Switch from empty to empty. Do nothing. */ + if (!cdrom_drives[id].host_drive) { + dev->disc_changed = 1; return; } + + ioctl_hopen(id); - scsi_unloadhd(hdd[id].id.scsi.id, hdd[id].id.scsi.lun, id); - scsi_disk_insert(id); + DeviceIoControl(cdrom_ioctl_windows[id].hIOCTL, + IOCTL_CDROM_READ_TOC, + NULL, 0, <oc, sizeof(ltoc), &size, NULL); + + ioctl_close(id); + + cdrom_ioctl_windows[id].toc = ltoc; + + dev->disc_changed = 0; +} + + +int +ioctl_hopen(uint8_t id) +{ + if (cdrom_ioctl_windows[id].is_playing) return 0; + + cdrom_ioctl_windows[id].hIOCTL = CreateFile(cdrom_ioctl[id].ioctl_path, + GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, OPEN_EXISTING, 0, NULL); + return 0; +} + +#define rcs "Read capacity: %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n" +#define drb dev->rcbuf + + +int +ioctl_open(uint8_t id, char d) +{ + cdrom_t *dev = cdrom[id]; + + sprintf(cdrom_ioctl[id].ioctl_path,"\\\\.\\%c:",d); + pclog("IOCTL path: %s\n", cdrom_ioctl[id].ioctl_path); + dev->disc_changed = 1; + + cdrom_ioctl_windows[id].hIOCTL = CreateFile(cdrom_ioctl[id].ioctl_path, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); + cdrom_drives[id].handler = &ioctl_cdrom; + dev->handler_inited = 1; + cdrom_ioctl_windows[id].is_playing = 0; + cdrom_ioctl[id].capacity_read=0; /* With these two lines, we read the READ CAPACITY command output from the host drive into our cache buffer. */ + ioctl_read_capacity(id, NULL); + pclog(rcs, drb[0], drb[1], drb[2], drb[3], drb[4], drb[5], drb[6], drb[7], + drb[8], drb[9], drb[10], drb[11], drb[12], drb[13], drb[14], drb[15]); + CloseHandle(cdrom_ioctl_windows[id].hIOCTL); + + cdrom_ioctl_windows[id].hIOCTL = NULL; + + return 0; } void -removable_disk_eject(uint8_t id) +ioctl_close(uint8_t id) { - removable_disk_unload(id); - ui_sb_icon_state(SB_RDISK|id, 1); - ui_sb_menu_enable_item(SB_RDISK|id, IDM_RDISK_EJECT | id, 0); - ui_sb_menu_enable_item(SB_RDISK|id, IDM_RDISK_RELOAD | id, 1); - ui_sb_menu_enable_item(SB_RDISK|id, IDM_RDISK_SEND_CHANGE | id, 0); + if (cdrom_ioctl_windows[id].is_playing) return; - ui_sb_tip_update(SB_RDISK|id); - - config_save(); -} - - -void -removable_disk_reload(uint8_t id) -{ - if (wcslen(hdd[id].fn) != 0) { - /* Attempting to reload while an image is already loaded. Do nothing. */ - return; + if (cdrom_ioctl_windows[id].hIOCTL) { + CloseHandle(cdrom_ioctl_windows[id].hIOCTL); + cdrom_ioctl_windows[id].hIOCTL = NULL; } +} - scsi_reloadhd(id); -#if 0 - scsi_disk_insert(id); + +static void +ioctl_exit(uint8_t id) +{ + cdrom_t *dev = cdrom[id]; + + cdrom_ioctl_windows[id].is_playing = 0; + + ioctl_stop(id); + dev->handler_inited = 0; + dev->disc_changed = 1; +} + + +static CDROM ioctl_cdrom = { + ioctl_ready, + ioctl_medium_changed, + ioctl_media_type_id, + ioctl_audio_callback, + ioctl_audio_stop, + ioctl_readtoc, + ioctl_readtoc_session, + ioctl_readtoc_raw, + ioctl_getcurrentsubchannel, + ioctl_pass_through, + NULL, + ioctl_playaudio, + ioctl_load, + ioctl_eject, + ioctl_pause, + ioctl_resume, + ioctl_size, + ioctl_status, + ioctl_is_track_audio, + ioctl_stop, + ioctl_exit +}; #endif - - ui_sb_icon_state(SB_RDISK|id, wcslen(hdd[id].fn) ? 0 : 1); - - ui_sb_menu_enable_item(SB_RDISK|id, IDM_RDISK_EJECT | id, wcslen(hdd[id].fn) ? 1 : 0); - ui_sb_menu_enable_item(SB_RDISK|id, IDM_RDISK_RELOAD | id, 0); - ui_sb_menu_enable_item(SB_RDISK|id, IDM_RDISK_SEND_CHANGE | id, wcslen(hdd[id].fn) ? 1 : 0); - - ui_sb_tip_update(SB_RDISK|id); - - config_save(); -} diff --git a/src/win/win_cdrom_ioctl.c b/src/win/win_cdrom_ioctl.c deleted file mode 100644 index 91b0732..0000000 --- a/src/win/win_cdrom_ioctl.c +++ /dev/null @@ -1,1371 +0,0 @@ -/* - * VARCem Virtual ARchaeological Computer EMulator. - * An emulator of (mostly) x86-based PC systems and devices, - * using the ISA,EISA,VLB,MCA and PCI system buses, roughly - * spanning the era between 1981 and 1995. - * - * This file is part of the VARCem Project. - * - * Implementation of the CD-ROM host drive IOCTL interface for - * Windows using SCSI Passthrough Direct. - * - * Version: @(#)cdrom_ioctl.c 1.0.10 2018/05/08 - * - * Authors: Fred N. van Kempen, - * Miran Grca, - * Sarah Walker, - * - * Copyright 2017,2018 Fred N. van Kempen. - * Copyright 2016-2018 Miran Grca. - * Copyright 2008-2018 Sarah Walker. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the: - * - * Free Software Foundation, Inc. - * 59 Temple Place - Suite 330 - * Boston, MA 02111-1307 - * USA. - */ -#define WINVER 0x0600 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#define HAVE_STDARG_H -#include "../emu.h" -#include "../device.h" -#include "../plat.h" -#include "../devices/scsi/scsi.h" -#include "../devices/cdrom/cdrom.h" - - -#ifdef USE_CDROM_IOCTL - - -#define MSFtoLBA(m,s,f) ((((m*60)+s)*75)+f) - - -enum { - CD_STOPPED = 0, - CD_PLAYING, - CD_PAUSED -}; - - -typedef struct { - HANDLE hIOCTL; - CDROM_TOC toc; - int is_playing; -} cdrom_ioctl_windows_t; - - -cdrom_ioctl_windows_t cdrom_ioctl_windows[CDROM_NUM]; - -#ifdef ENABLE_CDROM_IOCTL_LOG -int cdrom_ioctl_do_log = ENABLE_CDROM_IOCTL_LOG; -#endif - - -static CDROM ioctl_cdrom; - - -static void -cdrom_ioctl_log(const char *format, ...) -{ -#ifdef ENABLE_CDROM_IOCTL_LOG - va_list ap; - - if (cdrom_ioctl_do_log) { - va_start(ap, format); - pclog_ex(format, ap); - va_end(ap); - } -#endif -} - -static int ioctl_hopen(uint8_t id); - -void ioctl_audio_callback(uint8_t id, int16_t *output, int len) -{ - cdrom_t *dev = cdrom[id]; - RAW_READ_INFO in; - DWORD count; - - if (!cdrom_drives[id].sound_on || (dev->cd_state != CD_PLAYING)) - { - if (dev->cd_state == CD_PLAYING) - { - dev->seek_pos += (len >> 11); - cdrom_ioctl_log("ioctl_audio_callback(): playing but mute\n"); - } else - cdrom_ioctl_log("ioctl_audio_callback(): not playing\n"); - cdrom_ioctl_windows[id].is_playing = 0; - memset(output, 0, len * 2); - return; - } - cdrom_ioctl_log("ioctl_audio_callback(): dev->cd_buflen = %i, len = %i\n", dev->cd_buflen, len); - while (dev->cd_buflen < len) - { - if (dev->seek_pos < dev->cd_end) - { - in.DiskOffset.LowPart = dev->seek_pos * 2048; - in.DiskOffset.HighPart = 0; - in.SectorCount = 1; - in.TrackMode = CDDA; - if (!DeviceIoControl(cdrom_ioctl_windows[id].hIOCTL, IOCTL_CDROM_RAW_READ, &in, sizeof(in), &(dev->cd_buffer[dev->cd_buflen]), 2352, &count, NULL)) - { - memset(&(dev->cd_buffer[dev->cd_buflen]), 0, (BUF_SIZE - dev->cd_buflen) * 2); - cdrom_ioctl_windows[id].is_playing = 0; - ioctl_close(id); - dev->cd_state = CD_STOPPED; - dev->cd_buflen = len; - cdrom_ioctl_log("ioctl_audio_callback(): read sector error, stopped\n"); - } - else - { - dev->seek_pos++; - dev->cd_buflen += (2352 / 2); - cdrom_ioctl_log("ioctl_audio_callback(): dev->seek_pos = %i\n", dev->seek_pos); - } - } - else - { - memset(&(dev->cd_buffer[dev->cd_buflen]), 0, (BUF_SIZE - dev->cd_buflen) * 2); - cdrom_ioctl_windows[id].is_playing = 0; - ioctl_close(id); - dev->cd_state = CD_STOPPED; - dev->cd_buflen = len; - cdrom_ioctl_log("ioctl_audio_callback(): reached the end\n"); - } - } - memcpy(output, dev->cd_buffer, len * 2); - memcpy(&dev->cd_buffer[0], &(dev->cd_buffer[len]), (BUF_SIZE - len) * 2); - dev->cd_buflen -= len; -} - -void ioctl_audio_stop(uint8_t id) -{ - cdrom_t *dev = cdrom[id]; - - cdrom_ioctl_windows[id].is_playing = 0; - ioctl_close(id); - dev->cd_state = CD_STOPPED; -} - -static int get_track_nr(uint8_t id, uint32_t pos) -{ - cdrom_t *dev = cdrom[id]; - int c; - int track = 0; - - if (dev->disc_changed) - { - return 0; - cdrom_ioctl_log("get_track_nr(): disc changed\n"); - } - - if (cdrom_ioctl[id].last_track_pos == pos) - { - cdrom_ioctl_log("get_track_nr(): cdrom_ioctl[id].last_track_pos == pos\n"); - return cdrom_ioctl[id].last_track_nr; - } - - /* for (c = cdrom_ioctl_windows[id].toc.FirstTrack; c < cdrom_ioctl_windows[id].toc.LastTrack; c++) */ - for (c = 0; c < cdrom_ioctl_windows[id].toc.LastTrack; c++) - { - uint32_t track_address = MSFtoLBA(cdrom_ioctl_windows[id].toc.TrackData[c].Address[1], - cdrom_ioctl_windows[id].toc.TrackData[c].Address[2], - cdrom_ioctl_windows[id].toc.TrackData[c].Address[3]) - 150; - - if (track_address <= pos) - { - cdrom_ioctl_log("get_track_nr(): track = %i\n", c); - track = c; - } - } - cdrom_ioctl[id].last_track_pos = pos; - cdrom_ioctl[id].last_track_nr = track; - - cdrom_ioctl_log("get_track_nr(): return %i\n", track); - return track; -} - -static uint32_t get_track_msf(uint8_t id, uint32_t track_no) -{ - cdrom_t *dev = cdrom[id]; - int c; - - if (dev->disc_changed) - { - return 0; - } - - for (c = cdrom_ioctl_windows[id].toc.FirstTrack; c < cdrom_ioctl_windows[id].toc.LastTrack; c++) - { - if (c == track_no) - { - return cdrom_ioctl_windows[id].toc.TrackData[c].Address[3] + (cdrom_ioctl_windows[id].toc.TrackData[c].Address[2] << 8) + (cdrom_ioctl_windows[id].toc.TrackData[c].Address[1] << 16); - } - } - return 0xffffffff; -} - -static void ioctl_playaudio(uint8_t id, uint32_t pos, uint32_t len, int ismsf) -{ - cdrom_t *dev = cdrom[id]; - int m = 0, s = 0, f = 0; - uint32_t start_msf = 0, end_msf = 0; - if (!cdrom_drives[id].host_drive) - { - return; - } - cdrom_ioctl_log("Play audio - %08X %08X %i\n", pos, len, ismsf); - if (ismsf == 2) - { - start_msf = get_track_msf(id, pos); - end_msf = get_track_msf(id, len); - if (start_msf == 0xffffffff) - { - return; - } - if (end_msf == 0xffffffff) - { - return; - } - m = (start_msf >> 16) & 0xff; - s = (start_msf >> 8) & 0xff; - f = start_msf & 0xff; - pos = MSFtoLBA(m, s, f) - 150; - m = (end_msf >> 16) & 0xff; - s = (end_msf >> 8) & 0xff; - f = end_msf & 0xff; - len = MSFtoLBA(m, s, f) - 150; - } - else if (ismsf == 1) - { - m = (pos >> 16) & 0xff; - s = (pos >> 8) & 0xff; - f = pos & 0xff; - - if (pos == 0xffffff) - { - cdrom_ioctl_log("Playing from current position (MSF)\n"); - pos = dev->seek_pos; - } - else - { - pos = MSFtoLBA(m, s, f) - 150; - } - - m = (len >> 16) & 0xff; - s = (len >> 8) & 0xff; - f = len & 0xff; - len = MSFtoLBA(m, s, f) - 150; - } - else if (ismsf == 0) - { - if (pos == 0xffffffff) - { - cdrom_ioctl_log("Playing from current position\n"); - pos = dev->seek_pos; - } - len += pos; - } - dev->seek_pos = pos; - dev->cd_end = len; - - if (!cdrom_ioctl_windows[id].is_playing) - { - ioctl_hopen(id); - cdrom_ioctl_windows[id].is_playing = 1; - } - dev->cd_state = CD_PLAYING; -} - -static void ioctl_pause(uint8_t id) -{ - cdrom_t *dev = cdrom[id]; - - if (!cdrom_drives[id].host_drive) - { - return; - } - if (dev->cd_state == CD_PLAYING) - { - dev->cd_state = CD_PAUSED; - } -} - -static void ioctl_resume(uint8_t id) -{ - cdrom_t *dev = cdrom[id]; - - if (!cdrom_drives[id].host_drive) - { - return; - } - if (dev->cd_state == CD_PAUSED) - { - dev->cd_state = CD_PLAYING; - } -} - -static void ioctl_stop(uint8_t id) -{ - cdrom_t *dev = cdrom[id]; - - if (!cdrom_drives[id].host_drive) - { - return; - } - if (cdrom_ioctl_windows[id].is_playing) - { - cdrom_ioctl_windows[id].is_playing = 0; - ioctl_close(id); - } - dev->cd_state = CD_STOPPED; -} - -static int ioctl_ready(uint8_t id) -{ - cdrom_t *dev = cdrom[id]; - unsigned long size; - int temp; - CDROM_TOC ltoc; - - if (!cdrom_drives[id].host_drive) - { - return 0; - } - if (cdrom_ioctl_windows[id].hIOCTL == NULL) - { - ioctl_hopen(id); - temp = DeviceIoControl(cdrom_ioctl_windows[id].hIOCTL, IOCTL_CDROM_READ_TOC, NULL, 0, <oc, sizeof(ltoc), &size, NULL); - ioctl_close(id); - } - else - { - temp = DeviceIoControl(cdrom_ioctl_windows[id].hIOCTL, IOCTL_CDROM_READ_TOC, NULL, 0, <oc, sizeof(ltoc), &size, NULL); - } - if (!temp) - { - return 0; - } - if ((ltoc.TrackData[ltoc.LastTrack].Address[1] != cdrom_ioctl_windows[id].toc.TrackData[cdrom_ioctl_windows[id].toc.LastTrack].Address[1]) || - (ltoc.TrackData[ltoc.LastTrack].Address[2] != cdrom_ioctl_windows[id].toc.TrackData[cdrom_ioctl_windows[id].toc.LastTrack].Address[2]) || - (ltoc.TrackData[ltoc.LastTrack].Address[3] != cdrom_ioctl_windows[id].toc.TrackData[cdrom_ioctl_windows[id].toc.LastTrack].Address[3]) || - dev->disc_changed || (cdrom_drives[id].host_drive != cdrom_drives[id].prev_host_drive)) - { - dev->cd_state = CD_STOPPED; - if (cdrom_drives[id].host_drive != cdrom_drives[id].prev_host_drive) - { - cdrom_drives[id].prev_host_drive = cdrom_drives[id].host_drive; - } - return 1; - } - return 1; -} - -static int ioctl_get_last_block(uint8_t id, unsigned char starttrack, int msf, int maxlen, int single) -{ - cdrom_t *dev = cdrom[id]; - unsigned long size; - int c, d = 0; - CDROM_TOC lbtoc; - uint32_t lb = 0; - if (!cdrom_drives[id].host_drive) - { - return 0; - } - dev->cd_state = CD_STOPPED; - ioctl_hopen(id); - DeviceIoControl(cdrom_ioctl_windows[id].hIOCTL, IOCTL_CDROM_READ_TOC, NULL, 0, &lbtoc, sizeof(lbtoc), &size, NULL); - ioctl_close(id); - dev->disc_changed=0; - for (c=d; c <= lbtoc.LastTrack; c++) - { - uint32_t address; - address = MSFtoLBA(cdrom_ioctl_windows[id].toc.TrackData[c].Address[1], cdrom_ioctl_windows[id].toc.TrackData[c].Address[2], cdrom_ioctl_windows[id].toc.TrackData[c].Address[3]); - if (address > lb) - { - lb = address; - } - } - return lb; -} - -static void ioctl_read_capacity(uint8_t id, uint8_t *b); - -static int ioctl_medium_changed(uint8_t id) -{ - cdrom_t *dev = cdrom[id]; - unsigned long size; - int temp; - CDROM_TOC ltoc; - if (!cdrom_drives[id].host_drive) - { - return 0; /* This will be handled by the not ready handler instead. */ - } - ioctl_hopen(id); - temp = DeviceIoControl(cdrom_ioctl_windows[id].hIOCTL, IOCTL_CDROM_READ_TOC, NULL, 0, <oc,sizeof(ltoc), &size, NULL); - ioctl_close(id); - if (!temp) - { - return 0; /* Drive empty, a not ready handler matter, not disc change. */ - } - if (dev->disc_changed || (cdrom_drives[id].host_drive != cdrom_drives[id].prev_host_drive)) - { - dev->cd_state = CD_STOPPED; - cdrom_ioctl_windows[id].toc = ltoc; - dev->disc_changed = 0; - if (cdrom_drives[id].host_drive != cdrom_drives[id].prev_host_drive) - { - cdrom_drives[id].prev_host_drive = cdrom_drives[id].host_drive; - } - ioctl_hopen(id); - cdrom_ioctl[id].capacity_read=0; /* With this two lines, we read the READ CAPACITY command output from the host drive into our cache buffer. */ - ioctl_read_capacity(id, NULL); - ioctl_close(id); - dev->cdrom_capacity = ioctl_get_last_block(id, 0, 0, 4096, 0); - return 1; - } - else - { - if ((ltoc.TrackData[ltoc.LastTrack].Address[1] != cdrom_ioctl_windows[id].toc.TrackData[cdrom_ioctl_windows[id].toc.LastTrack].Address[1]) || - (ltoc.TrackData[ltoc.LastTrack].Address[2] != cdrom_ioctl_windows[id].toc.TrackData[cdrom_ioctl_windows[id].toc.LastTrack].Address[2]) || - (ltoc.TrackData[ltoc.LastTrack].Address[3] != cdrom_ioctl_windows[id].toc.TrackData[cdrom_ioctl_windows[id].toc.LastTrack].Address[3])) - { - dev->cd_state = CD_STOPPED; - cdrom_ioctl_log("Setting TOC...\n"); - cdrom_ioctl_windows[id].toc = ltoc; - ioctl_hopen(id); - cdrom_ioctl[id].capacity_read=0; /* With this two lines, we read the READ CAPACITY command output from the host drive into our cache buffer. */ - ioctl_read_capacity(id, NULL); - ioctl_close(id); - dev->cdrom_capacity = ioctl_get_last_block(id, 0, 0, 4096, 0); - return 1; /* TOC mismatches. */ - } - } - return 0; /* None of the above, return 0. */ -} - -static uint8_t ioctl_getcurrentsubchannel(uint8_t id, uint8_t *b, int msf) -{ - cdrom_t *dev = cdrom[id]; - CDROM_SUB_Q_DATA_FORMAT insub; - SUB_Q_CHANNEL_DATA sub; - unsigned long size; - int pos = 0, track; - uint32_t cdpos, track_address, dat; - - if (!cdrom_drives[id].host_drive) return 0; - - cdpos = dev->seek_pos; - - if (dev->last_subchannel_pos == cdpos) - { - memcpy(&insub, dev->sub_q_data_format, sizeof(insub)); - memcpy(&sub, dev->sub_q_channel_data, sizeof(sub)); - } - else - { - insub.Format = IOCTL_CDROM_CURRENT_POSITION; - ioctl_hopen(id); - DeviceIoControl(cdrom_ioctl_windows[id].hIOCTL,IOCTL_CDROM_READ_Q_CHANNEL,&insub,sizeof(insub),&sub,sizeof(sub),&size,NULL); - ioctl_close(id); - memset(dev->sub_q_data_format, 0, 16); - memcpy(dev->sub_q_data_format, &insub, sizeof(insub)); - memset(dev->sub_q_channel_data, 0, 256); - memcpy(dev->sub_q_channel_data, &sub, sizeof(sub)); - dev->last_subchannel_pos = cdpos; - } - - if (dev->cd_state == CD_PLAYING || dev->cd_state == CD_PAUSED) - { - track = get_track_nr(id, cdpos); - track_address = MSFtoLBA(cdrom_ioctl_windows[id].toc.TrackData[track].Address[1], - cdrom_ioctl_windows[id].toc.TrackData[track].Address[2], - cdrom_ioctl_windows[id].toc.TrackData[track].Address[3]) - 150; - - cdrom_ioctl_log("ioctl_getcurrentsubchannel(): cdpos = %i, track = %i, track_address = %i\n", cdpos, track, track_address); - - b[pos++] = sub.CurrentPosition.Control; - b[pos++] = track + 1; - b[pos++] = sub.CurrentPosition.IndexNumber; - - if (msf) - { - dat = cdpos + 150; - b[pos + 3] = (uint8_t)(dat % 75); dat /= 75; - b[pos + 2] = (uint8_t)(dat % 60); dat /= 60; - b[pos + 1] = (uint8_t)dat; - b[pos] = 0; - pos += 4; - dat = cdpos - track_address; - b[pos + 3] = (uint8_t)(dat % 75); dat /= 75; - b[pos + 2] = (uint8_t)(dat % 60); dat /= 60; - b[pos + 1] = (uint8_t)dat; - b[pos] = 0; - pos += 4; - } - else - { - b[pos++] = (cdpos >> 24) & 0xff; - b[pos++] = (cdpos >> 16) & 0xff; - b[pos++] = (cdpos >> 8) & 0xff; - b[pos++] = cdpos & 0xff; - cdpos -= track_address; - b[pos++] = (cdpos >> 24) & 0xff; - b[pos++] = (cdpos >> 16) & 0xff; - b[pos++] = (cdpos >> 8) & 0xff; - b[pos++] = cdpos & 0xff; - } - - if (dev->cd_state == CD_PLAYING) return 0x11; - return 0x12; - } - - b[pos++]=sub.CurrentPosition.Control; - b[pos++]=sub.CurrentPosition.TrackNumber; - b[pos++]=sub.CurrentPosition.IndexNumber; - - cdrom_ioctl_log("cdpos = %i, track_address = %i\n", MSFtoLBA(sub.CurrentPosition.AbsoluteAddress[1], sub.CurrentPosition.AbsoluteAddress[2], sub.CurrentPosition.AbsoluteAddress[3]), MSFtoLBA(sub.CurrentPosition.TrackRelativeAddress[1], sub.CurrentPosition.TrackRelativeAddress[2], sub.CurrentPosition.TrackRelativeAddress[3])); - - if (msf) - { - int c; - for (c = 0; c < 4; c++) - { - b[pos++] = sub.CurrentPosition.AbsoluteAddress[c]; - } - for (c = 0; c < 4; c++) - { - b[pos++] = sub.CurrentPosition.TrackRelativeAddress[c]; - } - } - else - { - uint32_t temp = MSFtoLBA(sub.CurrentPosition.AbsoluteAddress[1], sub.CurrentPosition.AbsoluteAddress[2], sub.CurrentPosition.AbsoluteAddress[3]) - 150; - b[pos++] = temp >> 24; - b[pos++] = temp >> 16; - b[pos++] = temp >> 8; - b[pos++] = temp; - temp = MSFtoLBA(sub.CurrentPosition.TrackRelativeAddress[1], sub.CurrentPosition.TrackRelativeAddress[2], sub.CurrentPosition.TrackRelativeAddress[3]) - 150; - b[pos++] = temp >> 24; - b[pos++] = temp >> 16; - b[pos++] = temp >> 8; - b[pos++] = temp; - } - - return 0x13; -} - -static void ioctl_eject(uint8_t id) -{ - cdrom_t *dev = cdrom[id]; - unsigned long size; - if (!cdrom_drives[id].host_drive) - { - return; - } - if (cdrom_ioctl_windows[id].is_playing) - { - cdrom_ioctl_windows[id].is_playing = 0; - ioctl_stop(id); - } - dev->cd_state = CD_STOPPED; - ioctl_hopen(id); - DeviceIoControl(cdrom_ioctl_windows[id].hIOCTL,IOCTL_STORAGE_EJECT_MEDIA,NULL,0,NULL,0,&size,NULL); - ioctl_close(id); -} - -static void ioctl_load(uint8_t id) -{ - cdrom_t *dev = cdrom[id]; - unsigned long size; - if (!cdrom_drives[id].host_drive) - { - return; - } - if (cdrom_ioctl_windows[id].is_playing) - { - cdrom_ioctl_windows[id].is_playing = 0; - ioctl_stop(id); - } - dev->cd_state = CD_STOPPED; - ioctl_hopen(id); - DeviceIoControl(cdrom_ioctl_windows[id].hIOCTL,IOCTL_STORAGE_LOAD_MEDIA,NULL,0,NULL,0,&size,NULL); - cdrom_ioctl[id].capacity_read=0; /* With this two lines, we read the READ CAPACITY command output from the host drive into our cache buffer. */ - ioctl_read_capacity(id, NULL); - ioctl_close(id); - dev->cdrom_capacity = ioctl_get_last_block(id, 0, 0, 4096, 0); -} - -static int ioctl_is_track_audio(uint8_t id, uint32_t pos, int ismsf) -{ - cdrom_t *dev = cdrom[id]; - int c; - int control = 0; - - uint32_t track_address = 0; - - if (dev->disc_changed) - { - return 0; - } - - for (c = 0; cdrom_ioctl_windows[id].toc.TrackData[c].TrackNumber != 0xaa; c++) - { - if (ismsf) { - track_address = cdrom_ioctl_windows[id].toc.TrackData[c].Address[3]; - track_address |= (cdrom_ioctl_windows[id].toc.TrackData[c].Address[2] << 8); - track_address |= (cdrom_ioctl_windows[id].toc.TrackData[c].Address[1] << 16); - } else { - track_address = MSFtoLBA(cdrom_ioctl_windows[id].toc.TrackData[c].Address[1],cdrom_ioctl_windows[id].toc.TrackData[c].Address[2],cdrom_ioctl_windows[id].toc.TrackData[c].Address[3]); - track_address -= 150; - } - - if (cdrom_ioctl_windows[id].toc.TrackData[c].TrackNumber >= cdrom_ioctl_windows[id].toc.FirstTrack && - cdrom_ioctl_windows[id].toc.TrackData[c].TrackNumber <= cdrom_ioctl_windows[id].toc.LastTrack && - track_address <= pos) - control = cdrom_ioctl_windows[id].toc.TrackData[c].Control; - } - - if ((control & 0xd) <= 1) - return 1; - else - return 0; -} - -/* 00, 08, 10, 18, 20, 28, 30, 38 */ -static const int flags_to_size[5][32] = { { 0, 0, 2352, 2352, 2352, 2352, 2352, 2352, /* 00-38 (CD-DA) */ - 2352, 2352, 2352, 2352, 2352, 2352, 2352, 2352, /* 40-78 */ - 2352, 2352, 2352, 2352, 2352, 2352, 2352, 2352, /* 80-B8 */ - 2352, 2352, 2352, 2352, 2352, 2352, 2352, 2352 }, /* C0-F8 */ - { 0, 0, 2048, 2336, 4, -296, 2052, 2344, /* 00-38 (Mode 1) */ - 8, -296, 2048, 2048, 12, -296, 2052, 2052, /* 40-78 */ - -296, -296, -296, -296, 16, -296, 2064, 2344, /* 80-B8 */ - -296, -296, 2048, 2048, 24, -296, 2064, 2352 }, /* C0-F8 */ - { 0, 0, 2336, 2336, 4, -296, 2340, 2340, /* 00-38 (Mode 2 non-XA) */ - 8, -296, 2336, 2336, 12, -296, 2340, 2340, /* 40-78 */ - -296, -296, -296, -296, 16, -296, 2352, 2340, /* 80-B8 */ - -296, -296, 2336, 2336, 24, -296, 2352, 2352 }, /* C0-F8 */ - { 0, 0, 2048, 2336, 4, -296, -296, -296, /* 00-38 (Mode 2 Form 1) */ - 8, -296, 2056, 2344, 12, -296, 2060, 2340, /* 40-78 */ - -296, -296, -296, -296, 16, -296, -296, -296, /* 80-B8 */ - -296, -296, -296, -296, 24, -296, 2072, 2352 }, /* C0-F8 */ - { 0, 0, 2328, 2328, 4, -296, -296, -296, /* 00-38 (Mode 2 Form 2) */ - 8, -296, 2336, 2336, 12, -296, 2340, 2340, /* 40-78 */ - -296, -296, -296, -296, 16, -296, -296, -296, /* 80-B8 */ - -296, -296, -296, -296, 24, -296, 2352, 2352 } /* C0-F8 */ - }; - -static int ioctl_get_sector_data_type(uint8_t id, uint8_t b0, uint8_t b1, uint8_t b2, uint8_t b3, int ismsf); - -static void cdrom_illegal_mode(uint8_t id) -{ - cdrom_sense_key = SENSE_ILLEGAL_REQUEST; - cdrom_asc = ASC_ILLEGAL_MODE_FOR_THIS_TRACK; - cdrom_ascq = 0; -} - -/* FIXME: allocate on heap! */ -struct sptd_with_sense -{ - SCSI_PASS_THROUGH s; - ULONG Filler; - UCHAR sense[32]; - UCHAR data[65536]; -} sptd; - -static int ioctl_get_block_length(uint8_t id, const UCHAR *cdb, int number_of_blocks, int no_length_check) -{ - cdrom_t *dev = cdrom[id]; - int sector_type = 0; - int temp_len = 0; - - if (no_length_check) - { - switch (cdb[0]) - { - case 0x25: /* READ CAPACITY */ - case 0x44: /* READ HEADER */ - return 8; - case 0x42: /* READ SUBCHANNEL */ - case 0x43: /* READ TOC */ - case 0x51: /* READ DISC INFORMATION */ - case 0x52: /* READ TRACK INFORMATION */ - case 0x5A: /* MODE SENSE (10) */ - return (((uint32_t) cdb[7]) << 8) | ((uint32_t) cdb[8]); - case 0xAD: /* READ DVD STRUCTURE */ - return (((uint32_t) cdb[8]) << 8) | ((uint32_t) cdb[9]); - default: - return 65534; - } - } - - switch (cdb[0]) - { - case 0x25: /* READ CAPACITY */ - case 0x44: /* READ HEADER */ - return 8; - case 0x42: /* READ SUBCHANNEL */ - case 0x43: /* READ TOC */ - case 0x51: /* READ DISC INFORMATION */ - case 0x52: /* READ TRACK INFORMATION */ - case 0x5A: /* MODE SENSE (10) */ - return (((uint32_t) cdb[7]) << 8) | ((uint32_t) cdb[8]); - case 0xAD: /* READ DVD STRUCTURE */ - return (((uint32_t) cdb[8]) << 8) | ((uint32_t) cdb[9]); - case 0x08: - case 0x28: - case 0xa8: - /* READ (6), READ (10), READ (12) */ - return 2048 * number_of_blocks; - - case 0xb9: - sector_type = (cdb[1] >> 2) & 7; - if (sector_type == 0) - { - sector_type = ioctl_get_sector_data_type(id, 0, cdb[3], cdb[4], cdb[5], 1); - if (sector_type == 0) - { - cdrom_illegal_mode(id); - return -1; - } - } - goto common_handler; - case 0xbe: - /* READ CD MSF, READ CD */ - sector_type = (cdb[1] >> 2) & 7; - if (sector_type == 0) - { - sector_type = ioctl_get_sector_data_type(id, cdb[2], cdb[3], cdb[4], cdb[5], 0); - if (sector_type == 0) - { - cdrom_illegal_mode(id); - return -1; - } - } -common_handler: - temp_len = flags_to_size[sector_type - 1][cdb[9] >> 3]; - if ((cdb[9] & 6) == 2) - { - temp_len += 294; - } - else if ((cdb[9] & 6) == 4) - { - temp_len += 296; - } - if ((cdb[10] & 7) == 1) - { - temp_len += 96; - } - else if ((cdb[10] & 7) == 2) - { - temp_len += 16; - } - else if ((cdb[10] & 7) == 4) - { - temp_len += 96; - } - if (temp_len <= 0) - { - cdrom_illegal_mode(id); - return -1; - } - return temp_len * dev->requested_blocks; - - default: - /* Other commands */ - return 65534; - - } - -} - -static int SCSICommand(uint8_t id, const UCHAR *cdb, UCHAR *buf, uint32_t *len, int no_length_check) -{ - DWORD ioctl_bytes; - int ioctl_rv = 0; - - SCSISense.SenseKey = 0; - SCSISense.Asc = 0; - SCSISense.Ascq = 0; - - *len = 0; - memset(&sptd, 0, sizeof(sptd)); - sptd.s.Length = sizeof(SCSI_PASS_THROUGH); - sptd.s.CdbLength = 12; - sptd.s.DataIn = SCSI_IOCTL_DATA_IN; - sptd.s.TimeOutValue = 80 * 60; - sptd.s.DataTransferLength = ioctl_get_block_length(id, cdb, cdrom_ioctl[id].actual_requested_blocks, no_length_check); - sptd.s.SenseInfoOffset = (uintptr_t)&sptd.sense - (uintptr_t)&sptd; - sptd.s.SenseInfoLength = 32; - sptd.s.DataBufferOffset = (uintptr_t)&sptd.data - (uintptr_t)&sptd; - - memcpy(sptd.s.Cdb, cdb, 12); - ioctl_rv = DeviceIoControl(cdrom_ioctl_windows[id].hIOCTL, IOCTL_SCSI_PASS_THROUGH, &sptd, sizeof(sptd), &sptd, sizeof(sptd), &ioctl_bytes, NULL); - - if (sptd.s.SenseInfoLength) - { - cdrom_sense_key = sptd.sense[2]; - cdrom_asc = sptd.sense[12]; - cdrom_ascq = sptd.sense[13]; - } - - cdrom_ioctl_log("Transferred length: %i (command: %02X)\n", sptd.s.DataTransferLength, cdb[0]); - cdrom_ioctl_log("Sense length: %i (%02X %02X %02X %02X %02X)\n", sptd.s.SenseInfoLength, sptd.sense[0], sptd.sense[1], sptd.sense[2], sptd.sense[12], sptd.sense[13]); - cdrom_ioctl_log("IOCTL bytes: %i; SCSI status: %i, status: %i, LastError: %08X\n", ioctl_bytes, sptd.s.ScsiStatus, ioctl_rv, GetLastError()); - cdrom_ioctl_log("DATA: %02X %02X %02X %02X %02X %02X\n", sptd.data[0], sptd.data[1], sptd.data[2], sptd.data[3], sptd.data[4], sptd.data[5]); - cdrom_ioctl_log(" %02X %02X %02X %02X %02X %02X\n", sptd.data[6], sptd.data[7], sptd.data[8], sptd.data[9], sptd.data[10], sptd.data[11]); - cdrom_ioctl_log(" %02X %02X %02X %02X %02X %02X\n", sptd.data[12], sptd.data[13], sptd.data[14], sptd.data[15], sptd.data[16], sptd.data[17]); - cdrom_ioctl_log("SENSE: %02X %02X %02X %02X %02X %02X\n", sptd.sense[0], sptd.sense[1], sptd.sense[2], sptd.sense[3], sptd.sense[4], sptd.sense[5]); - cdrom_ioctl_log(" %02X %02X %02X %02X %02X %02X\n", sptd.sense[6], sptd.sense[7], sptd.sense[8], sptd.sense[9], sptd.sense[10], sptd.sense[11]); - cdrom_ioctl_log(" %02X %02X %02X %02X %02X %02X\n", sptd.sense[12], sptd.sense[13], sptd.sense[14], sptd.sense[15], sptd.sense[16], sptd.sense[17]); - *len = sptd.s.DataTransferLength; - if (sptd.s.DataTransferLength != 0) - { - memcpy(buf, sptd.data, sptd.s.DataTransferLength); - } - - return ioctl_rv; -} - -static void ioctl_read_capacity(uint8_t id, uint8_t *b) -{ - cdrom_t *dev = cdrom[id]; - uint32_t len = 0; - - const UCHAR cdb[] = { 0x25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - UCHAR buf[16]; - - if (!cdrom_ioctl[id].capacity_read || (b == NULL)) - { - SCSICommand(id, cdb, buf, &len, 1); - - memcpy(dev->rcbuf, buf, len); - cdrom_ioctl[id].capacity_read = 1; - } - else - { - memcpy(b, dev->rcbuf, 16); - } -} - -static int ioctl_media_type_id(uint8_t id) -{ - uint8_t old_sense[3] = { 0, 0, 0 }; - - UCHAR msbuf[28]; - uint32_t len = 0; - int sense = 0; - - const UCHAR cdb[] = { 0x5A, 0x00, 0x2A, 0, 0, 0, 0, 0, 28, 0, 0, 0 }; - - old_sense[0] = cdrom_sense_key; - old_sense[1] = cdrom_asc; - old_sense[2] = cdrom_asc; - - ioctl_hopen(id); - - SCSICommand(id, cdb, msbuf, &len, 1); - - ioctl_close(id); - - sense = cdrom_sense_key; - cdrom_sense_key = old_sense[0]; - cdrom_asc = old_sense[1]; - cdrom_asc = old_sense[2]; - - if (sense == 0) - { - return msbuf[2]; - } - else - { - return 3; - } -} - -static uint32_t msf_to_lba32(int lba) -{ - int m = (lba >> 16) & 0xff; - int s = (lba >> 8) & 0xff; - int f = lba & 0xff; - return (m * 60 * 75) + (s * 75) + f; -} - -static int ioctl_get_type(uint8_t id, UCHAR *cdb, UCHAR *buf) -{ - int i = 0; - int ioctl_rv = 0; - - uint32_t len = 0; - - for (i = 2; i <= 5; i++) - { - cdb[1] = i << 2; - ioctl_rv = SCSICommand(id, cdb, buf, &len, 1); /* Bypass length check so we don't risk calling this again and getting stuck in an endless up. */ - if (ioctl_rv) - { - return i; - } - } - return 0; -} - -static int ioctl_sector_data_type(uint8_t id, int sector, int ismsf) -{ - int ioctl_rv = 0; - UCHAR cdb_lba[] = { 0xBE, 0, 0, 0, 0, 0, 0, 0, 1, 0x10, 0, 0 }; - UCHAR cdb_msf[] = { 0xB9, 0, 0, 0, 0, 0, 0, 0, 0, 0x10, 0, 0 }; - UCHAR buf[2352]; - - cdb_lba[2] = (sector >> 24); - cdb_lba[3] = ((sector >> 16) & 0xff); - cdb_lba[4] = ((sector >> 8) & 0xff); - cdb_lba[5] = (sector & 0xff); - - cdb_msf[3] = cdb_msf[6] = ((sector >> 16) & 0xff); - cdb_msf[4] = cdb_msf[7] = ((sector >> 8) & 0xff); - cdb_msf[5] = cdb_msf[8] = (sector & 0xff); - - ioctl_hopen(id); - - if (ioctl_is_track_audio(id, sector, ismsf)) - { - return 1; - } - - if (ismsf) - { - ioctl_rv = ioctl_get_type(id, cdb_msf, buf); - } - else - { - ioctl_rv = ioctl_get_type(id, cdb_lba, buf); - } - - if (ioctl_rv) - { - ioctl_close(id); - return ioctl_rv; - } - - if (ismsf) - { - sector = msf_to_lba32(sector); - if (sector < 150) - { - ioctl_close(id); - return 0; - } - sector -= 150; - ioctl_rv = ioctl_get_type(id, (UCHAR *) cdb_lba, buf); - } - - ioctl_close(id); - return ioctl_rv; -} - -static int ioctl_get_sector_data_type(uint8_t id, uint8_t b0, uint8_t b1, uint8_t b2, uint8_t b3, int ismsf) -{ - int sector = b3; - sector |= ((uint32_t) b2) << 8; - sector |= ((uint32_t) b1) << 16; - sector |= ((uint32_t) b0) << 24; - return ioctl_sector_data_type(id, sector, ismsf); -} - -static void ioctl_validate_toc(uint8_t id) -{ - cdrom_t *dev = cdrom[id]; - unsigned long size; - if (!cdrom_drives[id].host_drive) - { - return; - } - dev->cd_state = CD_STOPPED; - ioctl_hopen(id); - cdrom_ioctl_log("Validating TOC...\n"); - DeviceIoControl(cdrom_ioctl_windows[id].hIOCTL,IOCTL_CDROM_READ_TOC, NULL,0,&cdrom_ioctl_windows[id].toc,sizeof(cdrom_ioctl_windows[id].toc),&size,NULL); - ioctl_close(id); - dev->disc_changed = 0; -} - -/* FIXME: malloc this as needed? */ -UCHAR buf[262144]; - -static int ioctl_pass_through(uint8_t id, uint8_t *in_cdb, uint8_t *b, uint32_t *len) -{ - cdrom_t *dev = cdrom[id]; - const UCHAR cdb[12]; - - int ret = 0; - - int temp_block_length = 0; - int buffer_pos = 0; - - uint32_t temp_len = 0; - - int i = 0; - - if (in_cdb[0] == 0x43) - { - /* This is a read TOC, so we have to validate the TOC to make the rest of the emulator happy. */ - ioctl_validate_toc(id); - } - - ioctl_hopen(id); - - memcpy((void *) cdb, in_cdb, 12); - - temp_len = 0; - temp_block_length = ioctl_get_block_length(id, cdb, dev->requested_blocks, 0); - if (temp_block_length != -1) { - cdrom_ioctl[id].actual_requested_blocks = 1; - if ((cdb[0] == 0x08) || (cdb[0] == 0x28) || (cdb[0] == 0xA8) || (cdb[0] == 0xB9) || (cdb[0] == 0xBE)) { - buffer_pos = 0; - temp_len = 0; - - for (i = 0; i < dev->requested_blocks; i++) - { - cdrom_ioctl_log("CD-ROM %i: ioctl_pass_through(): Transferring block...\n", id, cdrom_ioctl[id].actual_requested_blocks); - cdrom_update_cdb((uint8_t *) cdb, dev->sector_pos + i, 1); - ret = SCSICommand(id, cdb, b + buffer_pos, &temp_len, 0); - buffer_pos += temp_len; - } - *len = buffer_pos; - } else { - cdrom_ioctl_log("CD-ROM %i: ioctl_pass_through(): Expected transfer length %i is smaller than 65534, transferring all at once...\n", id, temp_block_length); - ret = SCSICommand(id, cdb, b, len, 0); - cdrom_ioctl_log("CD-ROM %i: ioctl_pass_through(): Single transfer done\n", id); - } - } - - cdrom_ioctl_log("IOCTL DATA: %02X %02X %02X %02X %02X %02X %02X %02X\n", b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7]); - - ioctl_close(id); - - cdrom_ioctl_log("IOCTL Returned value: %i\n", ret); - - return ret; -} - -static int ioctl_readtoc(uint8_t id, unsigned char *b, unsigned char starttrack, int msf, int maxlen, int single) -{ - cdrom_t *dev = cdrom[id]; - int len=4; - DWORD size; - int c,d; - uint32_t temp; - uint32_t last_block; - if (!cdrom_drives[id].host_drive) - { - return 0; - } - dev->cd_state = CD_STOPPED; - ioctl_hopen(id); - DeviceIoControl(cdrom_ioctl_windows[id].hIOCTL,IOCTL_CDROM_READ_TOC, NULL,0,&cdrom_ioctl_windows[id].toc,sizeof(cdrom_ioctl_windows[id].toc),&size,NULL); - ioctl_close(id); - dev->disc_changed = 0; - b[2]=cdrom_ioctl_windows[id].toc.FirstTrack; - b[3]=cdrom_ioctl_windows[id].toc.LastTrack; - d=0; - for (c=0;c<=cdrom_ioctl_windows[id].toc.LastTrack;c++) - { - if (cdrom_ioctl_windows[id].toc.TrackData[c].TrackNumber>=starttrack) - { - d=c; - break; - } - } - last_block = 0; - for (c=d;c<=cdrom_ioctl_windows[id].toc.LastTrack;c++) - { - uint32_t address; - if ((len+8)>maxlen) break; - b[len++]=0; /*Reserved*/ - b[len++]=(cdrom_ioctl_windows[id].toc.TrackData[c].Adr<<4)|cdrom_ioctl_windows[id].toc.TrackData[c].Control; - b[len++]=cdrom_ioctl_windows[id].toc.TrackData[c].TrackNumber; - b[len++]=0; /*Reserved*/ - address = MSFtoLBA(cdrom_ioctl_windows[id].toc.TrackData[c].Address[1],cdrom_ioctl_windows[id].toc.TrackData[c].Address[2],cdrom_ioctl_windows[id].toc.TrackData[c].Address[3]); - if (address > last_block) - last_block = address; - - if (msf) - { - b[len++]=cdrom_ioctl_windows[id].toc.TrackData[c].Address[0]; - b[len++]=cdrom_ioctl_windows[id].toc.TrackData[c].Address[1]; - b[len++]=cdrom_ioctl_windows[id].toc.TrackData[c].Address[2]; - b[len++]=cdrom_ioctl_windows[id].toc.TrackData[c].Address[3]; - } - else - { - temp=MSFtoLBA(cdrom_ioctl_windows[id].toc.TrackData[c].Address[1],cdrom_ioctl_windows[id].toc.TrackData[c].Address[2],cdrom_ioctl_windows[id].toc.TrackData[c].Address[3]) - 150; - b[len++]=temp>>24; - b[len++]=temp>>16; - b[len++]=temp>>8; - b[len++]=temp; - } - if (single) break; - } - b[0] = (uint8_t)(((len-2) >> 8) & 0xff); - b[1] = (uint8_t)((len-2) & 0xff); - return len; -} - -static int ioctl_readtoc_session(uint8_t id, unsigned char *b, int msf, int maxlen) -{ - cdrom_t *dev = cdrom[id]; - int len=4; - int size; - uint32_t temp; - CDROM_READ_TOC_EX toc_ex; - CDROM_TOC_SESSION_DATA toc; - if (!cdrom_drives[id].host_drive) - { - return 0; - } - dev->cd_state = CD_STOPPED; - memset(&toc_ex,0,sizeof(toc_ex)); - memset(&toc,0,sizeof(toc)); - toc_ex.Format=CDROM_READ_TOC_EX_FORMAT_SESSION; - toc_ex.Msf=msf; - toc_ex.SessionTrack=0; - ioctl_hopen(id); - DeviceIoControl(cdrom_ioctl_windows[id].hIOCTL,IOCTL_CDROM_READ_TOC_EX, &toc_ex,sizeof(toc_ex),&toc,sizeof(toc),(PDWORD)&size,NULL); - ioctl_close(id); - b[2]=toc.FirstCompleteSession; - b[3]=toc.LastCompleteSession; - b[len++]=0; /*Reserved*/ - b[len++]=(toc.TrackData[0].Adr<<4)|toc.TrackData[0].Control; - b[len++]=toc.TrackData[0].TrackNumber; - b[len++]=0; /*Reserved*/ - if (msf) - { - b[len++]=toc.TrackData[0].Address[0]; - b[len++]=toc.TrackData[0].Address[1]; - b[len++]=toc.TrackData[0].Address[2]; - b[len++]=toc.TrackData[0].Address[3]; - } - else - { - temp=MSFtoLBA(toc.TrackData[0].Address[1],toc.TrackData[0].Address[2],toc.TrackData[0].Address[3]) - 150; - b[len++]=temp>>24; - b[len++]=temp>>16; - b[len++]=temp>>8; - b[len++]=temp; - } - - return len; -} - -static int ioctl_readtoc_raw(uint8_t id, uint8_t *b, int maxlen) -{ - cdrom_t *dev = cdrom[id]; - int len=4; - int size; - int i; - CDROM_READ_TOC_EX toc_ex; - CDROM_TOC_FULL_TOC_DATA toc; - if (!cdrom_drives[id].host_drive) - { - return 0; - } - dev->cd_state = CD_STOPPED; - memset(&toc_ex,0,sizeof(toc_ex)); - memset(&toc,0,sizeof(toc)); - toc_ex.Format=CDROM_READ_TOC_EX_FORMAT_FULL_TOC; - toc_ex.Msf=1; - toc_ex.SessionTrack=0; - ioctl_hopen(id); - DeviceIoControl(cdrom_ioctl_windows[id].hIOCTL,IOCTL_CDROM_READ_TOC_EX, &toc_ex,sizeof(toc_ex),&toc,sizeof(toc),(PDWORD)&size,NULL); - ioctl_close(id); - if (maxlen >= 3) b[2]=toc.FirstCompleteSession; - if (maxlen >= 4) b[3]=toc.LastCompleteSession; - - if (len >= maxlen) return len; - - size -= sizeof(CDROM_TOC_FULL_TOC_DATA); - size /= sizeof(toc.Descriptors[0]); - - for (i = 0; i <= size; i++) - { - b[len++]=toc.Descriptors[i].SessionNumber; - if (len == maxlen) return len; - b[len++]=(toc.Descriptors[i].Adr<<4)|toc.Descriptors[i].Control; - if (len == maxlen) return len; - b[len++]=0; - if (len == maxlen) return len; - b[len++]=toc.Descriptors[i].Reserved1; /*Reserved*/ - if (len == maxlen) return len; - b[len++]=toc.Descriptors[i].MsfExtra[0]; - if (len == maxlen) return len; - b[len++]=toc.Descriptors[i].MsfExtra[1]; - if (len == maxlen) return len; - b[len++]=toc.Descriptors[i].MsfExtra[2]; - if (len == maxlen) return len; - b[len++]=toc.Descriptors[i].Zero; - if (len == maxlen) return len; - b[len++]=toc.Descriptors[i].Msf[0]; - if (len == maxlen) return len; - b[len++]=toc.Descriptors[i].Msf[1]; - if (len == maxlen) return len; - b[len++]=toc.Descriptors[i].Msf[2]; - if (len == maxlen) return len; - } - - return len; -} - -static uint32_t ioctl_size(uint8_t id) -{ - uint8_t capacity_buffer[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - uint32_t capacity = 0; - - ioctl_read_capacity(id, capacity_buffer); - capacity = ((uint32_t) capacity_buffer[0]) << 24; - capacity |= ((uint32_t) capacity_buffer[1]) << 16; - capacity |= ((uint32_t) capacity_buffer[2]) << 8; - capacity |= (uint32_t) capacity_buffer[3]; - return capacity + 1; -} - -static int ioctl_status(uint8_t id) -{ - cdrom_t *dev = cdrom[id]; - - if (!(ioctl_ready(id)) && (cdrom_drives[id].host_drive <= 0)) - { - return CD_STATUS_EMPTY; - } - - switch(dev->cd_state) - { - case CD_PLAYING: - return CD_STATUS_PLAYING; - case CD_PAUSED: - return CD_STATUS_PAUSED; - case CD_STOPPED: - return CD_STATUS_STOPPED; - default: - return CD_STATUS_EMPTY; - } -} - -void ioctl_reset(uint8_t id) -{ - cdrom_t *dev = cdrom[id]; - CDROM_TOC ltoc; - unsigned long size; - - if (!cdrom_drives[id].host_drive) - { - dev->disc_changed = 1; - return; - } - - ioctl_hopen(id); - DeviceIoControl(cdrom_ioctl_windows[id].hIOCTL, IOCTL_CDROM_READ_TOC, NULL, 0, <oc, sizeof(ltoc), &size, NULL); - ioctl_close(id); - - cdrom_ioctl_windows[id].toc = ltoc; - dev->disc_changed = 0; -} - -int ioctl_hopen(uint8_t id) -{ - if (cdrom_ioctl_windows[id].is_playing) return 0; - cdrom_ioctl_windows[id].hIOCTL = CreateFile(cdrom_ioctl[id].ioctl_path, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); - return 0; -} - -#define rcs "Read capacity: %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n" -#define drb dev->rcbuf - -int ioctl_open(uint8_t id, char d) -{ - cdrom_t *dev = cdrom[id]; - - sprintf(cdrom_ioctl[id].ioctl_path,"\\\\.\\%c:",d); - pclog("IOCTL path: %s\n", cdrom_ioctl[id].ioctl_path); - dev->disc_changed = 1; - - cdrom_ioctl_windows[id].hIOCTL = CreateFile(cdrom_ioctl[id].ioctl_path, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); - cdrom_drives[id].handler = &ioctl_cdrom; - dev->handler_inited = 1; - cdrom_ioctl_windows[id].is_playing = 0; - cdrom_ioctl[id].capacity_read=0; /* With these two lines, we read the READ CAPACITY command output from the host drive into our cache buffer. */ - ioctl_read_capacity(id, NULL); - pclog(rcs, drb[0], drb[1], drb[2], drb[3], drb[4], drb[5], drb[6], drb[7], - drb[8], drb[9], drb[10], drb[11], drb[12], drb[13], drb[14], drb[15]); - CloseHandle(cdrom_ioctl_windows[id].hIOCTL); - cdrom_ioctl_windows[id].hIOCTL = NULL; - return 0; -} - -void ioctl_close(uint8_t id) -{ - if (cdrom_ioctl_windows[id].is_playing) return; - if (cdrom_ioctl_windows[id].hIOCTL) - { - CloseHandle(cdrom_ioctl_windows[id].hIOCTL); - cdrom_ioctl_windows[id].hIOCTL = NULL; - } -} - -static void ioctl_exit(uint8_t id) -{ - cdrom_t *dev = cdrom[id]; - - cdrom_ioctl_windows[id].is_playing = 0; - ioctl_stop(id); - dev->handler_inited = 0; - dev->disc_changed = 1; -} - -static CDROM ioctl_cdrom= -{ - ioctl_ready, - ioctl_medium_changed, - ioctl_media_type_id, - ioctl_audio_callback, - ioctl_audio_stop, - ioctl_readtoc, - ioctl_readtoc_session, - ioctl_readtoc_raw, - ioctl_getcurrentsubchannel, - ioctl_pass_through, - NULL, - ioctl_playaudio, - ioctl_load, - ioctl_eject, - ioctl_pause, - ioctl_resume, - ioctl_size, - ioctl_status, - ioctl_is_track_audio, - ioctl_stop, - ioctl_exit -}; - - -#endif diff --git a/src/win/win_crashdump.c b/src/win/win_crashdump.c index 25affbe..8d85703 100644 --- a/src/win/win_crashdump.c +++ b/src/win/win_crashdump.c @@ -8,7 +8,7 @@ * * Handle generation of crash-dump reports. * - * Version: @(#)win_crashdump.c 1.0.7 2018/08/31 + * Version: @(#)win_crashdump.c 1.0.8 2018/10/05 * * Authors: Fred N. van Kempen, * Riley (Rai-chan), @@ -249,7 +249,7 @@ InitCrashDump(void) * so allocate 10kb for it to use if it gets called, * an amount which should be more than enough. */ - ExceptionHandlerBuffer = malloc(ExceptionHandlerBufferSize); + ExceptionHandlerBuffer = (char *)mem_alloc(ExceptionHandlerBufferSize); CurrentBufferPointer = ExceptionHandlerBuffer; /* diff --git a/src/win/win_d2d.cpp b/src/win/win_d2d.cpp index 247b656..b05acf0 100644 --- a/src/win/win_d2d.cpp +++ b/src/win/win_d2d.cpp @@ -8,7 +8,7 @@ * * Rendering module for Microsoft Direct2D. * - * Version: @(#)win_d2d.cpp 1.0.1 2018/07/28 + * Version: @(#)win_d2d.cpp 1.0.2 2018/10/05 * * Authors: Fred N. van Kempen, * David Hrdlicka, @@ -42,12 +42,13 @@ #include #include #include -#define PNG_DEBUG 0 -#include #include "../emu.h" #include "../version.h" #include "../device.h" #include "../plat.h" +#ifdef USE_LIBPNG +# include "../png.h" +#endif #ifdef _MSC_VER # pragma warning(disable: 4200) #endif @@ -195,9 +196,7 @@ d2d_blit(int x, int y, int y1, int y2, int w, int h) float fs_w = (float)w; float fs_h = (float)h; -#if 0 - pclog("D2D: blit(x=%d, y=%d, y1=%d, y2=%d, w=%d, h=%d)\n", x,y, y1,y2, w,h); -#endif + DEBUG("D2D: blit(x=%d, y=%d, y1=%d, y2=%d, w=%d, h=%d)\n", x,y, y1,y2, w,h); // TODO: Detect double scanned mode and resize render target // appropriately for more clear picture @@ -229,7 +228,7 @@ d2d_blit(int x, int y, int y1, int y2, int w, int h) } // TODO: Copy data directly from buffer32 to d2d_bitmap - srcdata = malloc(h * w * 4); + srcdata = mem_alloc(h * w * 4); for (yy = y1; yy < y2; yy++) { if ((y + yy) >= 0 && (y + yy) < buffer32->h) { #if 0 @@ -283,7 +282,7 @@ d2d_blit(int x, int y, int y1, int y2, int w, int h) } if (FAILED(hr)) - pclog("D2D: blit: error 0x%08lx\n", hr); + ERRLOG("D2D: blit: error 0x%08lx\n", hr); /* Clean up. */ free(srcdata); @@ -293,7 +292,7 @@ d2d_blit(int x, int y, int y1, int y2, int w, int h) static void d2d_close(void) { - pclog("D2D: close()\n"); + DEBUG("D2D: close()\n"); video_setblit(NULL); @@ -339,7 +338,7 @@ d2d_init(int fs) D2D1_HWND_RENDER_TARGET_PROPERTIES props; HRESULT hr = S_OK; - pclog("D2D: init(fs=%d)\n", fs); + INFO("D2D: init(fs=%d)\n", fs); cgapal_rebuild(); @@ -347,7 +346,7 @@ d2d_init(int fs) /* Try loading the DLL. */ d2d_handle = dynld_module(PATH_D2D_DLL, d2d_imports); if (d2d_handle == NULL) { - pclog("D2D: unable to load '%s', D2D not available.\n", PATH_D2D_DLL); + ERRLOG("D2D: unable to load '%s', D2D not available.\n", PATH_D2D_DLL); return(0); } #endif @@ -408,7 +407,7 @@ d2d_init(int fs) } if (FAILED(hr)) { - pclog("D2D: init: error 0x%08lx\n", hr); + ERRLOG("D2D: init: error 0x%08lx\n", hr); d2d_close(); return(0); } @@ -433,7 +432,7 @@ d2d_screenshot(const wchar_t *fn) // Saving a screenshot of a Direct2D render target is harder than // one would think. Keeping this stubbed for the moment // -ryu - pclog("D2D: screenshot(%ls)\n", fn); + INFO("D2D: screenshot(%ls)\n", fn); } diff --git a/src/win/win_d3d.cpp b/src/win/win_d3d.cpp index 861037c..42c1664 100644 --- a/src/win/win_d3d.cpp +++ b/src/win/win_d3d.cpp @@ -8,7 +8,7 @@ * * Rendering module for Microsoft Direct3D 9. * - * Version: @(#)win_d3d.cpp 1.0.11 2018/05/07 + * Version: @(#)win_d3d.cpp 1.0.12 2018/10/05 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -208,8 +208,14 @@ d3d_blit_fs(int x, int y, int y1, int y2, int w, int h) hr = d3dTexture->LockRect(0, &dr, &lock_rect, 0); if (hr == D3D_OK) { - for (yy = y1; yy < y2; yy++) - if (buffer32) memcpy((void *)((uintptr_t)dr.pBits + ((yy - y1) * dr.Pitch)), &(((uint32_t *)buffer32->line[yy + y])[x]), w * 4); + for (yy = y1; yy < y2; yy++) { + if (buffer32) { + if (vid_grayscale || invert_display) + video_transform_copy((uint32_t *)((uintptr_t)dr.pBits + ((yy - y1) * dr.Pitch)), &(((uint32_t *)buffer32->line[yy + y])[x]), w); + else + memcpy((void *)((uintptr_t)dr.pBits + ((yy - y1) * dr.Pitch)), &(((uint32_t *)buffer32->line[yy + y])[x]), w * 4); + } + } video_blit_complete(); d3dTexture->UnlockRect(0); @@ -286,7 +292,7 @@ d3d_blit_fs(int x, int y, int y1, int y2, int w, int h) hr = d3ddev->Present(NULL, NULL, d3d_device_window, NULL); if (hr == D3DERR_DEVICELOST || hr == D3DERR_INVALIDCALL) - PostMessage(hwndMain, WM_RESETD3D, 0, 0); + PostMessage(hwndMain, WM_RESET_D3D, 0, 0); } @@ -313,9 +319,14 @@ d3d_blit(int x, int y, int y1, int y2, int w, int h) hr = d3dTexture->LockRect(0, &dr, &r, 0); if (hr == D3D_OK) { for (yy = y1; yy < y2; yy++) { - if (buffer32) - if ((y + yy) >= 0 && (y + yy) < buffer32->h) - memcpy((void *)((uintptr_t)dr.pBits + ((yy - y1) * dr.Pitch)), &(((uint32_t *)buffer32->line[yy + y])[x]), w * 4); + if (buffer32) { + if ((y + yy) >= 0 && (y + yy) < buffer32->h) { + if (vid_grayscale || invert_display) + video_transform_copy((uint32_t *)((uintptr_t)dr.pBits + ((yy - y1) * dr.Pitch)), &(((uint32_t *)buffer32->line[yy + y])[x]), w); + else + memcpy((void *)((uintptr_t)dr.pBits + ((yy - y1) * dr.Pitch)), &(((uint32_t *)buffer32->line[yy + y])[x]), w * 4); + } + } } video_blit_complete(); @@ -378,7 +389,7 @@ d3d_blit(int x, int y, int y1, int y2, int w, int h) hr = d3ddev->Present(NULL, NULL, d3d_hwnd, NULL); if (hr == D3DERR_DEVICELOST || hr == D3DERR_INVALIDCALL) - PostMessage(d3d_hwnd, WM_RESETD3D, 0, 0); + PostMessage(d3d_hwnd, WM_RESET_D3D, 0, 0); } @@ -417,7 +428,7 @@ d3d_reset(int fs) hr = d3ddev->Reset(&d3dpp); if (hr == D3DERR_DEVICELOST) { - pclog("D3D: Unable to reset device!\n"); + ERRLOG("D3D: Unable to reset device!\n"); return; } @@ -471,7 +482,7 @@ d3d_init(int fs) RECT r; int y; - pclog("D3D: init (fs=%d)\n", fs); + INFO("D3D: init (fs=%d)\n", fs); d3d_hwnd = hwndRender; @@ -481,7 +492,7 @@ d3d_init(int fs) d3d_w = GetSystemMetrics(SM_CXSCREEN); d3d_h = GetSystemMetrics(SM_CYSCREEN); - _swprintf(title, L"%s v%s", TEXT(EMU_NAME), TEXT(EMU_VERSION)); + swprintf(title, sizeof_w(title), L"%s v%s", EMU_NAME, emu_version); d3d_device_window = CreateWindow( FS_CLASS_NAME, title, @@ -527,7 +538,7 @@ d3d_init(int fs) D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &d3ddev); if (FAILED(hr)) { - pclog("D3D: CreateDevice failed, result = 0x%08x\n", hr); + ERRLOG("D3D: CreateDevice failed, result = 0x%08x\n", hr); return(0); } @@ -538,7 +549,7 @@ d3d_init(int fs) &v_buffer, NULL); if (FAILED(hr)) { - pclog("D3D: CreateVertexBuffer failed, result = %08lx\n", hr); + ERRLOG("D3D: CreateVertexBuffer failed, result = %08lx\n", hr); return(0); } @@ -549,7 +560,7 @@ d3d_init(int fs) D3DPOOL_MANAGED, &d3dTexture, NULL); if (FAILED(hr)) { - pclog("D3D: CreateTexture failed, result = %08lx\n", hr); + ERRLOG("D3D: CreateTexture failed, result = %08lx\n", hr); return(0); } @@ -557,7 +568,7 @@ d3d_init(int fs) r.bottom = r.right = 2047; hr = d3dTexture->LockRect(0, &dr, &r, 0); if (FAILED(hr)) { - pclog("D3D: LockRect failed, result = %08lx\n", hr); + ERRLOG("D3D: LockRect failed, result = %08lx\n", hr); return(0); } diff --git a/src/win/win_ddraw.cpp b/src/win/win_ddraw.cpp index f087268..d445d76 100644 --- a/src/win/win_ddraw.cpp +++ b/src/win/win_ddraw.cpp @@ -8,7 +8,7 @@ * * Rendering module for Microsoft DirectDraw 9. * - * Version: @(#)win_ddraw.cpp 1.0.17 2018/09/02 + * Version: @(#)win_ddraw.cpp 1.0.18 2018/10/05 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -279,8 +279,15 @@ ddraw_blit_fs(int x, int y, int y1, int y2, int w, int h) return; } - for (yy = y1; yy < y2; yy++) - if (buffer32) memcpy((void *)((uintptr_t)ddsd.lpSurface + (yy * ddsd.lPitch)), &(((uint32_t *)buffer32->line[y + yy])[x]), w * 4); + for (yy = y1; yy < y2; yy++) { + if (buffer32) { + if (vid_grayscale || invert_display) + video_transform_copy((uint32_t *)((uintptr_t)ddsd.lpSurface + (yy * ddsd.lPitch)), &(((uint32_t *)buffer32->line[y + yy])[x]), w); + else + memcpy((void *)((uintptr_t)ddsd.lpSurface + (yy * ddsd.lPitch)), &(((uint32_t *)buffer32->line[y + yy])[x]), w * 4); + } + } + video_blit_complete(); lpdds_back->Unlock(NULL); @@ -352,10 +359,16 @@ ddraw_blit(int x, int y, int y1, int y2, int w, int h) } for (yy = y1; yy < y2; yy++) { - if (buffer32) - if ((y + yy) >= 0 && (y + yy) < buffer32->h) - memcpy((uint32_t *) &(((uint8_t *) ddsd.lpSurface)[yy * ddsd.lPitch]), &(((uint32_t *)buffer32->line[y + yy])[x]), w * 4); + if (buffer32) { + if ((y + yy) >= 0 && (y + yy) < buffer32->h) { + if (vid_grayscale || invert_display) + video_transform_copy((uint32_t *) &(((uint8_t *) ddsd.lpSurface)[yy * ddsd.lPitch]), &(((uint32_t *)buffer32->line[y + yy])[x]), w); + else + memcpy((uint32_t *) &(((uint8_t *) ddsd.lpSurface)[yy * ddsd.lPitch]), &(((uint32_t *)buffer32->line[y + yy])[x]), w * 4); + } + } } + video_blit_complete(); lpdds_back->Unlock(NULL); @@ -389,7 +402,7 @@ ddraw_blit(int x, int y, int y1, int y2, int w, int h) static void ddraw_close(void) { - pclog("DDRAW: close\n"); + DEBUG("DDRAW: close\n"); video_setblit(NULL); @@ -425,18 +438,18 @@ ddraw_init(int fs) DWORD dw; HWND h; - pclog("DDraw: initializing (fs=%d)\n", fs); + INFO("DDraw: initializing (fs=%d)\n", fs); cgapal_rebuild(); hr = DirectDrawCreate(NULL, &lpdd, NULL); if (FAILED(hr)) { - pclog("DDRAW: cannot create an instance (%s)\n", GetError(hr)); + ERRLOG("DDRAW: cannot create an instance (%s)\n", GetError(hr)); return(0); } hr = lpdd->QueryInterface(IID_IDirectDraw4, (LPVOID *)&lpdd4); if (FAILED(hr)) { - pclog("DDRAW: no interfaces found (%s)\n", GetError(hr)); + ERRLOG("DDRAW: no interfaces found (%s)\n", GetError(hr)); return(0); } lpdd->Release(); @@ -453,7 +466,7 @@ ddraw_init(int fs) } hr = lpdd4->SetCooperativeLevel(h, dw); if (FAILED(hr)) { - pclog("DDRAW: SetCooperativeLevel failed (%s)\n", GetError(hr)); + ERRLOG("DDRAW: SetCooperativeLevel failed (%s)\n", GetError(hr)); return(0); } @@ -462,7 +475,7 @@ ddraw_init(int fs) ddraw_h = GetSystemMetrics(SM_CYSCREEN); hr = lpdd4->SetDisplayMode(ddraw_w, ddraw_h, 32, 0, 0); if (FAILED(hr)) { - pclog("DDRAW: SetDisplayMode failed (%s)\n", GetError(hr)); + ERRLOG("DDRAW: SetDisplayMode failed (%s)\n", GetError(hr)); return(0); } } @@ -478,7 +491,7 @@ ddraw_init(int fs) } hr = lpdd4->CreateSurface(&ddsd, &lpdds_pri, NULL); if (FAILED(hr)) { - pclog("DDRAW: CreateSurface failed (%s)\n", GetError(hr)); + ERRLOG("DDRAW: CreateSurface failed (%s)\n", GetError(hr)); return(0); } @@ -489,7 +502,7 @@ ddraw_init(int fs) ddsd.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER; hr = lpdds_pri->GetAttachedSurface(&ddsd.ddsCaps, &lpdds_back2); if (FAILED(hr)) { - pclog("DDRAW: GetAttachedSurface failed (%s)\n", GetError(hr)); + ERRLOG("DDRAW: GetAttachedSurface failed (%s)\n", GetError(hr)); return(0); } } @@ -508,7 +521,7 @@ ddraw_init(int fs) ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY; hr = lpdd4->CreateSurface(&ddsd, &lpdds_back, NULL); if (FAILED(hr)) { - pclog("DDRAW: CreateSurface(back) failed (%s)\n", GetError(hr)); + ERRLOG("DDRAW: CreateSurface(back) failed (%s)\n", GetError(hr)); return(0); } } @@ -528,26 +541,26 @@ ddraw_init(int fs) ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY; hr = lpdd4->CreateSurface(&ddsd, &lpdds_back2, NULL); if (FAILED(hr)) { - pclog("DDRAW: CreateSurface(back2) failed (%s)\n", GetError(hr)); + ERRLOG("DDRAW: CreateSurface(back2) failed (%s)\n", GetError(hr)); return(0); } } hr = lpdd4->CreateClipper(0, &lpdd_clipper, NULL); if (FAILED(hr)) { - pclog("DDRAW: CreateClipper failed (%s)\n", GetError(hr)); + ERRLOG("DDRAW: CreateClipper failed (%s)\n", GetError(hr)); return(0); } hr = lpdd_clipper->SetHWnd(0, h); if (FAILED(hr)) { - pclog("DDRAW: SetHWnd failed (%s)\n", GetError(hr)); + ERRLOG("DDRAW: SetHWnd failed (%s)\n", GetError(hr)); return(0); } hr = lpdds_pri->SetClipper(lpdd_clipper); if (FAILED(hr)) { - pclog("DDRAW: SetClipper failed (%s)\n", GetError(hr)); + ERRLOG("DDRAW: SetClipper failed (%s)\n", GetError(hr)); return(0); } } @@ -570,7 +583,7 @@ SaveBMP(const wchar_t *fn, BITMAPINFO *bmi, uint8_t *pixels) FILE *fp; if ((fp = plat_fopen(fn, L"wb")) == NULL) { - pclog("[SaveBMP] File %ls could not be opened for writing!\n", fn); + ERRLOG("[SaveBMP] File %ls could not be opened for writing!\n", fn); return(0); } @@ -645,8 +658,7 @@ ddraw_screenshot(const wchar_t *fn) } #endif - xs = get_actual_size_x(); - ys = ys2 = get_actual_size_y(); + get_screen_size_natural(&xs, &ys); if (ysize <= 250) { ys >>= 1; @@ -668,9 +680,10 @@ ddraw_screenshot(const wchar_t *fn) } /* Allocate a buffer for the pixel data. */ - if ((pixels = (uint8_t *)malloc(bmi.bmiHeader.biSizeImage)) == NULL) { - pclog("DDraw: unable to allocate bitmap memory!\n"); - _swprintf(temp, get_string(IDS_ERR_SCRSHOT), fn); + if ((pixels = (uint8_t *)mem_alloc(bmi.bmiHeader.biSizeImage)) == NULL) { + ERRLOG("DDraw: unable to allocate bitmap memory!\n"); + swprintf(temp, sizeof_w(temp), + get_string(IDS_ERR_SCRSHOT), fn); ui_msgbox(MBX_ERROR, temp); ReleaseDC(NULL, hDC); return; @@ -698,7 +711,7 @@ ddraw_screenshot(const wchar_t *fn) bmi.bmiHeader.biSizeImage <<= 1; /* Allocate new buffer, doubled-up. */ - pixels = (uint8_t *)malloc(bmi.bmiHeader.biSizeImage); + pixels = (uint8_t *)mem_alloc(bmi.bmiHeader.biSizeImage); /* Copy scanlines. */ for (i = 0; i < ys; i++) { @@ -739,7 +752,8 @@ ddraw_screenshot(const wchar_t *fn) /* Show error message if needed. */ if (i == 0) { - _swprintf(temp, get_string(IDS_ERR_SCRSHOT), path); + swprintf(temp, sizeof_w(temp), + get_string(IDS_ERR_SCRSHOT), path); ui_msgbox(MBX_ERROR, temp); } } diff --git a/src/win/win_devconf.c b/src/win/win_devconf.c index 45fd81a..421a4d8 100644 --- a/src/win/win_devconf.c +++ b/src/win/win_devconf.c @@ -12,7 +12,7 @@ * and builds a complete Win32 DIALOG resource block in a * buffer in memory, and then passes that to the API handler. * - * Version: @(#)win_devconf.c 1.0.20 2018/05/26 + * Version: @(#)win_devconf.c 1.0.21 2018/10/05 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -54,6 +54,7 @@ #include "../ui/ui.h" #include "../plat.h" #include "win.h" +#include "resource.h" #define STR_FONTNAME "Segoe UI" @@ -75,7 +76,7 @@ dlg_init(HWND hdlg) wchar_t* str; HWND h; - id = IDC_CONFIG_BASE; + id = IDC_CONFIGURE_DEV; cfg = dev->config; while (cfg->type != -1) { @@ -122,7 +123,7 @@ dlg_init(HWND hdlg) case CONFIG_SPINNER: val = config_get_int(dev->name, cfg->name, cfg->default_int); - _swprintf(temp, L"%i", val); + swprintf(temp, sizeof_w(temp), L"%i", val); SendMessage(h, WM_SETTEXT, 0, (LPARAM)temp); id += 2; break; @@ -193,7 +194,7 @@ dlg_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) case WM_COMMAND: cid = LOWORD(wParam); if (cid == IDOK) { - id = IDC_CONFIG_BASE; + id = IDC_CONFIGURE_DEV; changed = 0; while (cfg->type != -1) { @@ -293,7 +294,7 @@ dlg_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) devconf_changed = 1; - id = IDC_CONFIG_BASE; + id = IDC_CONFIGURE_DEV; cfg = dev->config; while (cfg->type != -1) { @@ -372,7 +373,7 @@ dlg_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) EndDialog(hdlg, 0); return TRUE; } else { - id = IDC_CONFIG_BASE; + id = IDC_CONFIGURE_DEV; cfg = dev->config; while (cfg->type != -1) { @@ -468,7 +469,7 @@ AddWideString(uint16_t *data, int ids) */ #define DLG_MAX_SIZE 16384 uint8_t -dlg_devconf(HWND hwnd, device_t *device) +dlg_devconf(HWND hwnd, const device_t *device) { char temp[128]; const device_config_t *cfg = device->config; @@ -480,7 +481,7 @@ dlg_devconf(HWND hwnd, device_t *device) devconf_changed = 0; /* Allocate the dialog data block. */ - blk = malloc(DLG_MAX_SIZE); + blk = (uint16_t *)mem_alloc(DLG_MAX_SIZE); memset(blk, 0x00, DLG_MAX_SIZE); dlg = (DLGTEMPLATE *)blk; @@ -498,19 +499,19 @@ dlg_devconf(HWND hwnd, device_t *device) *data++ = 0; /* no menu bar */ *data++ = 0; /* predefined dialog box class */ sprintf(temp, "%s ", device->name); - data += MultiByteToWideChar(CP_ACP, 0, temp, -1, data, 120); + data += MultiByteToWideChar(CP_ACP, 0, temp, -1, (LPWSTR)data, 120); data--; /* back over the NUL */ data = AddWideString(data, IDS_DEVCONF_1); /* Font style and size to use. */ *data++ = 9; /* point size */ - data += MultiByteToWideChar(CP_ACP, 0, STR_FONTNAME, -1, data, 120); + data += MultiByteToWideChar(CP_ACP, 0, STR_FONTNAME, -1, (LPWSTR)data, 120); if (((uintptr_t)data) & 2) data++; /* Now add the items from the configuration. */ - id = IDC_CONFIG_BASE; + id = IDC_CONFIGURE_DEV; while (cfg->type != -1) { /* Align 'data' to DWORD */ itm = (DLGITEMTEMPLATE *)data; @@ -528,7 +529,7 @@ dlg_devconf(HWND hwnd, device_t *device) *data++ = 0xffff; *data++ = 0x0080; /* button class */ data += MultiByteToWideChar(CP_ACP, 0, - cfg->description, -1, data, 256); + cfg->description, -1, (LPWSTR)data, 256); *data++ = 0; /* no creation data */ /* Move to next available line. */ @@ -552,7 +553,7 @@ dlg_devconf(HWND hwnd, device_t *device) *data++ = 0xffff; *data++ = 0x0085; /* combo box class */ data += MultiByteToWideChar(CP_ACP, 0, - cfg->description, -1, data, 256); + cfg->description, -1, (LPWSTR)data, 256); *data++ = 0; /* no creation data */ if (((uintptr_t)data) & 2) data++; /* align */ @@ -570,7 +571,7 @@ dlg_devconf(HWND hwnd, device_t *device) *data++ = 0xffff; *data++ = 0x0082; /* static class */ data += MultiByteToWideChar(CP_ACP, 0, - cfg->description, -1, data, 256); + cfg->description, -1, (LPWSTR)data, 256); *data++ = 0; /* no creation data */ if (((uintptr_t)data) & 2) data++; /* align */ @@ -594,7 +595,7 @@ dlg_devconf(HWND hwnd, device_t *device) *data++ = 0xffff; *data++ = 0x0081; /* edit text class */ data += MultiByteToWideChar(CP_ACP, 0, - "", -1, data, 256); + "", -1, (LPWSTR)data, 256); *data++ = 0; /* no creation data */ if (((uintptr_t)data) & 2) data++; /* align */ @@ -613,7 +614,7 @@ dlg_devconf(HWND hwnd, device_t *device) *data++ = 0xffff; *data++ = 0x0082; /* static class */ data += MultiByteToWideChar(CP_ACP, 0, - cfg->description, -1, data, 256); + cfg->description, -1, (LPWSTR)data, 256); *data++ = 0; /* no creation data */ if (((uintptr_t)data) & 2) data++; /* align */ @@ -636,7 +637,7 @@ dlg_devconf(HWND hwnd, device_t *device) *data++ = 0xffff; *data++ = 0x0081; /* edit text class */ data += MultiByteToWideChar(CP_ACP, 0, - "", -1, data, 256); + "", -1, (LPWSTR)data, 256); *data++ = 0; /* no creation data */ if (((uintptr_t)data) & 2) data++; /* align */ @@ -671,7 +672,7 @@ dlg_devconf(HWND hwnd, device_t *device) *data++ = 0xffff; *data++ = 0x0082; /* static class */ data += MultiByteToWideChar(CP_ACP, 0, - cfg->description, -1, data, 256); + cfg->description, -1, (LPWSTR)data, 256); *data++ = 0; /* no creation data */ if (((uintptr_t)data) & 2) data++; /* align */ @@ -689,7 +690,7 @@ dlg_devconf(HWND hwnd, device_t *device) cfg++; } - dlg->cdit = (id - IDC_CONFIG_BASE) + 2; + dlg->cdit = (id - IDC_CONFIGURE_DEV) + 2; itm = (DLGITEMTEMPLATE *)data; itm->style = WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON; diff --git a/src/win/win_dialog.c b/src/win/win_dialog.c index 55ce210..35f89ee 100644 --- a/src/win/win_dialog.c +++ b/src/win/win_dialog.c @@ -8,7 +8,7 @@ * * Implementation of server several dialogs. * - * Version: @(#)win_dialog.c 1.0.12 2018/05/24 + * Version: @(#)win_dialog.c 1.0.13 2018/10/05 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -130,7 +130,7 @@ ui_msgbox(int flags, const void *arg) case MBX_ERROR: /* error message */ if (flags & MBX_FATAL) { fl = (MB_OK | MB_ICONERROR); - cap = get_string(IDS_FATAL_ERROR); + cap = get_string(IDS_ERROR_FATAL); } else { fl = (MB_OK | MB_ICONWARNING); cap = get_string(IDS_ERROR); @@ -144,7 +144,7 @@ ui_msgbox(int flags, const void *arg) case MBX_CONFIG: /* configuration */ fl = (MB_YESNO | MB_ICONERROR); - cap = get_string(IDS_CONFIG_ERROR); + cap = get_string(IDS_ERROR_CONF); break; } @@ -313,7 +313,7 @@ dlg_file_ex(HWND h, const wchar_t *f, const wchar_t *ifn, wchar_t *fn, int fl) sprintf((char *)temp, "%sFile('%ls', %02x):\n\n error 0x%08lx", (fl & DLG_FILE_SAVE)?"Save":"Open", temp, fl, err); - pclog("%s\n", (char *)temp); + ERRLOG("%s\n", (char *)temp); (void)ui_msgbox(MBX_ERROR|MBX_ANSI, (char *)temp); } diff --git a/src/win/win_dynld.c b/src/win/win_dynld.c index 8dda446..4818d8d 100644 --- a/src/win/win_dynld.c +++ b/src/win/win_dynld.c @@ -8,7 +8,7 @@ * * Try to load a support DLL. * - * Version: @(#)win_dynld.c 1.0.6 2018/05/14 + * Version: @(#)win_dynld.c 1.0.7 2018/10/05 * * Authors: Fred N. van Kempen, * @@ -64,9 +64,7 @@ dynld_module(const char *name, const dllimp_t *table) /* See if we can load the desired module. */ if ((h = LoadLibrary(name)) == NULL) { -#ifdef _DEBUG - pclog("DynLd(\"%s\"): library not found!\n", name); -#endif + ERRLOG("DynLd(\"%s\"): library not found!\n", name); return(NULL); } @@ -80,7 +78,7 @@ dynld_module(const char *name, const dllimp_t *table) for (imp = table; imp->name != NULL; imp++) { func = GetProcAddress(h, imp->name); if (func == NULL) { - pclog("DynLd(\"%s\"): function '%s' not found!\n", + ERRLOG("DynLd(\"%s\"): function '%s' not found!\n", name, imp->name); FreeLibrary(h); return(NULL); diff --git a/src/win/win_joystick.cpp b/src/win/win_joystick.cpp index 791b208..c316530 100644 --- a/src/win/win_joystick.cpp +++ b/src/win/win_joystick.cpp @@ -13,7 +13,7 @@ * NOTE: Hacks currently needed to compile with MSVC; DX needs to * be updated to 11 or 12 or so. --FvK * - * Version: @(#)win_joystick.cpp 1.0.17 2018/05/24 + * Version: @(#)win_joystick.cpp 1.0.18 2018/10/05 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -61,9 +61,11 @@ #include "../config.h" #include "../device.h" #include "../plat.h" +#include "../ui/ui.h" #include "../devices/ports/game_dev.h" #include "../devices/input/game/joystick.h" #include "win.h" +#include "resource.h" #define MAX_PLAT_JOYSTICKS 8 @@ -104,8 +106,8 @@ static LPDIRECTINPUT8 lpdi; static BOOL CALLBACK enum_callback(LPCDIDEVICEINSTANCE lpddi, UNUSED(LPVOID data)) { - pclog("JOYSTICK: found game device%i: %s\n", - joysticks_present, lpddi->tszProductName); + INFO("JOYSTICK: found game device%i: %s\n", + joysticks_present, lpddi->tszProductName); /* If we got too many, ignore it. */ if (joysticks_present >= MAX_JOYSTICKS) return(DIENUM_STOP); @@ -131,7 +133,7 @@ obj_callback(LPCDIDEVICEOBJECTINSTANCE lpddoi, LPVOID pvRef) strncpy(state->axis[state->nr_axes].name, lpddoi->tszName, sizeof(state->axis[state->nr_axes].name)); - pclog("Axis%i: %s %x %x\n", + DEBUG("Axis%i: %s %x %x\n", state->nr_axes, state->axis[state->nr_axes].name, lpddoi->dwOfs, lpddoi->dwType); @@ -152,7 +154,7 @@ obj_callback(LPCDIDEVICEOBJECTINSTANCE lpddoi, LPVOID pvRef) } else if (lpddoi->guidType == GUID_Button) { strncpy(state->button[state->nr_buttons].name, lpddoi->tszName, sizeof(state->button[state->nr_buttons].name)); - pclog("Button%i: %s %x %x\n", + DEBUG("Button%i: %s %x %x\n", state->nr_buttons, state->button[state->nr_buttons].name, lpddoi->dwOfs, lpddoi->dwType); @@ -160,7 +162,7 @@ obj_callback(LPCDIDEVICEOBJECTINSTANCE lpddoi, LPVOID pvRef) } else if (lpddoi->guidType == GUID_POV) { strncpy(state->pov[state->nr_povs].name, lpddoi->tszName, sizeof(state->pov[state->nr_povs].name)); - pclog("POV%i: %s %x %x\n", + DEBUG("POV%i: %s %x %x\n", state->nr_povs, state->pov[state->nr_povs].name, lpddoi->dwOfs, lpddoi->dwType); @@ -179,7 +181,7 @@ joystick_init(void) /* Only initialize if the game port is enabled. */ if (! game_enabled) return; - pclog("JOYSTICK: initializing (type=%d)\n", joystick_type); + INFO("JOYSTICK: initializing (type=%d)\n", joystick_type); atexit(joystick_close); @@ -194,7 +196,7 @@ joystick_init(void) enum_callback, NULL, DIEDFL_ATTACHEDONLY))) fatal("joystick_init : EnumDevices failed\n"); - pclog("JOYSTICK: %i game device(s) found.\n", joysticks_present); + INFO("JOYSTICK: %i game device(s) found.\n", joysticks_present); for (c = 0; c < joysticks_present; c++) { LPDIRECTINPUTDEVICE8 lpdi_joystick_temp = NULL; @@ -215,9 +217,9 @@ joystick_init(void) if (FAILED(lpdi_joystick[c]->GetDeviceInfo(&device_instance))) fatal("joystick_init : GetDeviceInfo failed\n"); - pclog("Joystick%i:\n", c); - pclog(" Name = %s\n", device_instance.tszInstanceName); - pclog(" ProductName = %s\n", device_instance.tszProductName); + DEBUG("Joystick%i:\n", c); + DEBUG(" Name = %s\n", device_instance.tszInstanceName); + DEBUG(" ProductName = %s\n", device_instance.tszProductName); strncpy(plat_joystick_state[c].name, device_instance.tszInstanceName, 64); @@ -225,9 +227,9 @@ joystick_init(void) devcaps.dwSize = sizeof(devcaps); if (FAILED(lpdi_joystick[c]->GetCapabilities(&devcaps))) fatal("joystick_init : GetCapabilities failed\n"); - pclog(" Axes = %i\n", devcaps.dwAxes); - pclog(" Buttons = %i\n", devcaps.dwButtons); - pclog(" POVs = %i\n", devcaps.dwPOVs); + DEBUG(" Axes = %i\n", devcaps.dwAxes); + DEBUG(" Buttons = %i\n", devcaps.dwButtons); + DEBUG(" POVs = %i\n", devcaps.dwPOVs); lpdi_joystick[c]->EnumObjects(obj_callback, &plat_joystick_state[c], DIDFT_ALL); @@ -380,11 +382,11 @@ static uint8_t joystickconfig_changed = 0; static void rebuild_selections(HWND hdlg) { - int id = IDC_CONFIG_BASE + 2; + int id = IDC_CONFIGURE_DEV + 2; int c, d, joystick; HWND h; - h = GetDlgItem(hdlg, IDC_CONFIG_BASE); + h = GetDlgItem(hdlg, IDC_CONFIGURE_DEV); joystick = SendMessage(h, CB_GETCURSEL, 0, 0); for (c = 0; c < gamedev_get_axis_count(joystick_config_type); c++) { @@ -507,8 +509,8 @@ dlg_init(HWND hdlg) int nr_axes; int nr_povs; - h = GetDlgItem(hdlg, IDC_CONFIG_BASE); - id = IDC_CONFIG_BASE + 2; + h = GetDlgItem(hdlg, IDC_CONFIGURE_DEV); + id = IDC_CONFIGURE_DEV + 2; joystick = joystick_state[joystick_nr].plat_joystick_nr; SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)"None"); @@ -585,15 +587,15 @@ dlg_proc(HWND hdlg, UINT message, WPARAM wParam, UNUSED(LPARAM lParam)) case WM_COMMAND: switch (LOWORD(wParam)) { - case IDC_CONFIG_BASE: + case IDC_CONFIGURE_DEV: if (HIWORD(wParam) == CBN_SELCHANGE) rebuild_selections(hdlg); break; case IDOK: - id = IDC_CONFIG_BASE + 2; + id = IDC_CONFIGURE_DEV + 2; - h = GetDlgItem(hdlg, IDC_CONFIG_BASE); + h = GetDlgItem(hdlg, IDC_CONFIGURE_DEV); joystick_state[joystick_nr].plat_joystick_nr = SendMessage(h, CB_GETCURSEL, 0, 0); if (joystick_state[joystick_nr].plat_joystick_nr) { @@ -653,12 +655,12 @@ AddWideString(uint16_t *data, int ids) uint8_t dlg_jsconf(HWND hwnd, int joy_nr, int type) { - uint16_t *data_block = (uint16_t *)malloc(16384); + uint16_t *data_block = (uint16_t *)mem_alloc(16384); uint16_t *data; DLGTEMPLATE *dlg = (DLGTEMPLATE *)data_block; DLGITEMTEMPLATE *item; int c, y = 10; - int id = IDC_CONFIG_BASE; + int id = IDC_CONFIGURE_DEV; joystickconfig_changed = 0; joystick_nr = joy_nr; @@ -836,7 +838,7 @@ dlg_jsconf(HWND hwnd, int joy_nr, int type) y += 20; } - dlg->cdit = (id - IDC_CONFIG_BASE) + 2; + dlg->cdit = (id - IDC_CONFIGURE_DEV) + 2; item = (DLGITEMTEMPLATE *)data; item->style = WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON; diff --git a/src/win/win_keyboard.c b/src/win/win_keyboard.c index c5a1716..b18ffda 100644 --- a/src/win/win_keyboard.c +++ b/src/win/win_keyboard.c @@ -8,7 +8,7 @@ * * Windows raw keyboard input handler. * - * Version: @(#)win_keyboard.c 1.0.7 2018/05/10 + * Version: @(#)win_keyboard.c 1.0.8 2018/10/05 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -115,7 +115,7 @@ keyboard_getkeymap(void) scancode_unmapped = convert_scan_code(scancode_unmapped); scancode_mapped = convert_scan_code(scancode_mapped); - /* pclog("Scan code map found: %04X -> %04X\n", scancode_unmapped, scancode_mapped); */ + /* DEBUG("Scan code map found: %04X -> %04X\n", scancode_unmapped, scancode_mapped); */ /* Ignore source scan codes with prefixes other than E1 that are not E1 1D. */ @@ -144,9 +144,9 @@ keyboard_handle(LPARAM lParam, int focus) /* See how much data the RI has for us, and allocate a buffer. */ GetRawInputData((HRAWINPUT)lParam, RID_INPUT, NULL, &size, sizeof(RAWINPUTHEADER)); - raw = (RAWINPUT *)malloc(size); + raw = (RAWINPUT *)mem_alloc(size); if (raw == NULL) { - pclog("KBD: out of memory for Raw Input buffer!\n"); + ERRLOG("KBD: out of memory for Raw Input buffer!\n"); return; } @@ -154,7 +154,7 @@ keyboard_handle(LPARAM lParam, int focus) ri_size = GetRawInputData((HRAWINPUT)(lParam), RID_INPUT, raw, &size, sizeof(RAWINPUTHEADER)); if (ri_size != size) { - pclog("KBD: bad event buffer %d/%d\n", size, ri_size); + ERRLOG("KBD: bad event buffer %d/%d\n", size, ri_size); return; } @@ -176,9 +176,7 @@ keyboard_handle(LPARAM lParam, int focus) code = convert_scan_code(code); /* Remap it according to the list from the Registry */ -#if 0 - pclog("Scan code: %04X (map: %04X)\n", code, scancode_map[code]); -#endif + DBGLOG(1, "Scan code: %04X (map: %04X)\n", code, scancode_map[code]); code = scancode_map[code]; /* diff --git a/src/win/win_lang.c b/src/win/win_lang.c index d1fb74b..b61e394 100644 --- a/src/win/win_lang.c +++ b/src/win/win_lang.c @@ -8,7 +8,7 @@ * * Handle language support for the platform. * - * Version: @(#)win_lang.c 1.0.6 2018/09/03 + * Version: @(#)win_lang.c 1.0.6 2018/10/05 * * Author: Fred N. van Kempen, * @@ -65,21 +65,12 @@ typedef struct { } dll_lang_t; -/* Platform Public data, specific. */ -const string_t *plat_strings; -DWORD dwSubLangID; -lang_t *languages = NULL; - - /* Local data. */ -static int languages_num = 0; static HMODULE lang_handle = NULL; -static LANGID lang_curr = 0; -/* Set the localized language name. */ static void -lang_setname(lang_t *ptr) +lang_add(lang_t *ptr, int sort) { wchar_t name[128]; wchar_t *str; @@ -88,60 +79,22 @@ lang_setname(lang_t *ptr) /* Convert the language ID to a (localized) name. */ lcid = MAKELCID(ptr->id, SORT_DEFAULT); if (! GetLocaleInfo(lcid, LOCALE_SLANGUAGE, name, sizeof_w(name))) { - pclog("UI: unable to get name for language ID 0x%04X\n", ptr->id); + ERRLOG("UI: unable to get name for language ID 0x%04X\n", ptr->id); return; } /* Clean up any existing name. */ - if (ptr->name != NULL) free((void *)ptr->name); + if (ptr->name != NULL) + free((void *)ptr->name); /* Set the (new) name. */ - str = (wchar_t *)malloc(sizeof(wchar_t) * (wcslen(name) + 1)); + str = (wchar_t *)mem_alloc(sizeof(wchar_t) * (wcslen(name) + 1)); memset(str, 0x00, sizeof(wchar_t) * (wcslen(name) + 1)); wcscpy(str, name); ptr->name = (const wchar_t *)str; -} - -/* Add a language to the list of supported languages. */ -static void -lang_add(lang_t *ptr, int sort) -{ - lang_t *p, *pp; - lang_t *prev = NULL; - - /* Create a copy of the entry data. */ - pp = (lang_t *)malloc(sizeof(lang_t)); - memcpy(pp, ptr, sizeof(lang_t)); - - /* Add this entry to the tail of the list. */ - if (sort) { - p = languages; - if ((p == NULL) || (wcscmp(pp->name, p->name) < 0)) { - pp->next = p; - languages = pp; - } else { - while (p != NULL) { - if (wcscmp(pp->name, p->name) > 0) { - prev = p; - p = p->next; - continue; - } else { - prev->next = pp; - pp->next = p; - break; - } - } - prev->next = pp; - } - } else { - /* Just prepend to beginning. */ - pp->next = languages; - languages = pp; - } - - /* We got one more! */ - languages_num++; + /* Actually add this language. */ + ui_lang_add(ptr, sort); } @@ -151,8 +104,8 @@ lang_add(lang_t *ptr, int sort) * only has English compiled in, any others are * kept in separate language modules. */ -static void -lang_scan(void) +void +plat_lang_scan(void) { wchar_t path[512], temp[512]; uint8_t buffer[8192]; @@ -161,10 +114,9 @@ lang_scan(void) dll_lang_t *lptr; lang_t lang; DIR *dir; - int l; + int l, lflen; - /* None yet.. */ - languages_num = 0; + lflen = wcslen(LANG_FILE); /* Open the "language modules" directory. */ swprintf(path, sizeof_w(temp), L"%ls%ls", exe_path, LANGUAGE_PATH); @@ -176,28 +128,27 @@ lang_scan(void) if ((de = readdir(dir)) == NULL) break; /* Is this a file we want? */ - l = wcslen(LANG_FILE); - if (de->d_reclen < l) continue; - if (wcsncmp(de->d_name, LANG_FILE, l)) continue; + if ((int)wcslen(de->d_name) < lflen) continue; + if (wcsncmp(de->d_name, LANG_FILE, lflen)) continue; str = wcschr(de->d_name, L'.'); if (str == NULL) continue; if (wcsncasecmp(str, L".dll", 4)) continue; /* Looks like we have one here.. */ memset(temp, 0x00, sizeof(temp)); - de->d_name[de->d_reclen] = L'\0'; swprintf(temp, sizeof_w(temp), L"%ls\\%ls", path, de->d_name); + l = wcslen(temp) + 1; /* Create a buffer for the DLL file name. */ memset(&lang, 0x00, sizeof(lang)); - str = (wchar_t *)malloc(sizeof(wchar_t) * (wcslen(temp) + 1)); - memset(str, 0x00, sizeof(wchar_t) * (wcslen(temp) + 1)); + str = (wchar_t *)mem_alloc(sizeof(wchar_t) * l); + memset(str, 0x00, sizeof(wchar_t) * l); wcscpy(str, temp); lang.dll = (const wchar_t *)str; /* Grab the version info block from the DLL. */ if (! GetFileVersionInfo(temp, 0, sizeof(buffer), buffer)) { - pclog("UI: unable to access '%ls', skipping!\n", temp); + ERRLOG("UI: unable to access '%ls', skipping!\n", temp); free((void *)lang.dll); continue; } @@ -212,13 +163,11 @@ lang_scan(void) L"\\StringFileInfo\\%04x%04x\\%ls", lptr->wLanguage, lptr->wCodePage, L"FileVersion"); if (! VerQueryValue(buffer, temp, (LPVOID*)&str, (PUINT)&l)) { -#ifdef _DEBUG - pclog("UI: invalid data in DLL, skipping!\n"); -#endif + ERRLOG("UI: invalid data in DLL, skipping!\n"); free((void *)lang.dll); continue; } - ptr = (wchar_t *)malloc(sizeof(wchar_t) * (l+1)); + ptr = (wchar_t *)mem_alloc(sizeof(wchar_t) * (l+1)); lang.version = (const wchar_t *)ptr; *ptr++ = L'v'; do { @@ -233,9 +182,7 @@ lang_scan(void) L"\\StringFileInfo\\%04x%04x\\%ls", lptr->wLanguage, lptr->wCodePage, L"Comments"); if (! VerQueryValue(buffer, temp, (LPVOID*)&str, (PUINT)&l)) { -#ifdef _DEBUG - pclog("UI: invalid data in DLL, skipping!\n"); -#endif + ERRLOG("UI: invalid data in DLL, skipping!\n"); free((void *)lang.version); free((void *)lang.dll); continue; @@ -245,17 +192,14 @@ lang_scan(void) *ptr++ = *str++; *ptr++ = *str++; l -= (ptr - temp); - ptr = (wchar_t *)malloc(sizeof(wchar_t) * (ptr-temp)); + ptr = (wchar_t *)mem_alloc(sizeof(wchar_t) * (ptr-temp)); wcscpy(ptr, temp); lang.author = (const wchar_t *)ptr; - ptr = (wchar_t *)malloc(sizeof(wchar_t) * l); + ptr = (wchar_t *)mem_alloc(sizeof(wchar_t) * l); wcscpy(ptr, str); lang.email = (const wchar_t *)ptr; - /* Set the name of this language. */ - lang_setname(&lang); - /* Add this language. */ lang_add(&lang, 1); } @@ -265,19 +209,49 @@ lang_scan(void) /* Add the application's primary language. */ memset(&lang, 0x00, sizeof(lang)); lang.id = 0x0409; - lang_setname(&lang); lang_add(&lang, 0); } +/* Activate the new language for the application. */ +void +plat_lang_set(int id) +{ + LCID lcid; + + SetThreadUILanguage(id); + + /* This can be removed, it no longer works since Vista+ */ + lcid = MAKELCID(id, SORT_DEFAULT); + SetThreadLocale(lcid); +} + + /* Pre-load the strings from our resource file. */ -static void -lang_strings(void) +const string_t * +plat_lang_load(lang_t *ptr) { wchar_t temp[512], *str; string_t *array, *tbl; int c = 0, i; + /* Do we need to unload a resource DLL? */ + if (lang_handle != NULL) { + FreeLibrary(lang_handle); + lang_handle = NULL; + } + + /* Do we need to load a resource DLL? */ + if (ptr->dll != NULL) { + lang_handle = LoadLibraryEx(ptr->dll, 0, + LOAD_LIBRARY_AS_IMAGE_RESOURCE | \ + LOAD_LIBRARY_AS_DATAFILE); + if (lang_handle == NULL) { + ERRLOG("UI: unable to load resource DLL '%ls' !\n", ptr->dll); + return(NULL); + } + } + /* * First, we need to know how many strings are in the table. * Sadly, there is no other way to determine this but to try @@ -291,7 +265,7 @@ lang_strings(void) * our string_table array. */ i = (c + 1) * sizeof(string_t); - array = (string_t *)malloc(i); + array = (string_t *)mem_alloc(i); memset(array, 0x00, i); /* Now load the actual strings into our string table. */ @@ -301,7 +275,7 @@ lang_strings(void) if (c == 0) continue; tbl->id = i; - str = (wchar_t *)malloc((c + 1) * sizeof(wchar_t)); + str = (wchar_t *)mem_alloc((c + 1) * sizeof(wchar_t)); memset(str, 0x00, (c + 1) * sizeof(wchar_t)); memcpy(str, temp, c * sizeof(wchar_t)); tbl->str = str; @@ -312,129 +286,7 @@ lang_strings(void) /* Terminate the table. */ tbl->str = NULL; - /* Consider this table const. */ - plat_strings = array; -} - - -/* Set the correct item in the Language menu. */ -static void -lang_check(int id) -{ - lang_t *ptr; - int i = 1; - - ptr = languages; - while (ptr != NULL) { - if (ptr->id == id) { - menu_set_radio_item(IDM_LANGUAGE, languages_num, i); - return; - } - i++; - ptr = ptr->next; - } -} - - -/* Get language from index number. */ -static lang_t * -lang_index(int id) -{ - lang_t *ptr; - int i = 0; - - for (ptr = languages; ptr != NULL; ptr = ptr->next) - if (i++ == id) return(ptr); - - return(NULL); -} - - -/* Set (or re-set) the language for the application. */ -int -plat_set_language(int id) -{ - LANGID lang; - lang_t *ptr; - LCID lcid; - - /* First, set up our language list if needed. */ - if (languages == NULL) lang_scan(); - - /* If a small value, this is a menu index, not an ID. */ - if (id < 200) { - ptr = lang_index(id); - id = ptr->id; - lang_id = id; - } - - /* Set new language ID if not already set. */ - lang = MAKELANGID(id, dwSubLangID); - if (lang_curr == lang) return(1); - - /* Find language in the table. */ - for (ptr = languages; ptr != NULL; ptr = ptr->next) - if (ptr->id == id) break; - if (ptr == NULL) { - pclog("UI: language not supported, not setting.\n"); - return(0); - } - - /* Do we need to unload a resource DLL? */ - if (lang_handle != NULL) { - FreeLibrary(lang_handle); - lang_handle = NULL; - } - - /* Do we need to load a resource DLL? */ - if (ptr->dll != NULL) { - lang_handle = LoadLibraryEx(ptr->dll, 0, - LOAD_LIBRARY_AS_IMAGE_RESOURCE | \ - LOAD_LIBRARY_AS_DATAFILE); - if (lang_handle == NULL) { - pclog("UI: unable to load resource DLL '%ls' !\n", ptr->dll); - return(0); - } - } - - /* We are good to go! */ - lang_curr = lang; - - /* Load the strings table for this ID. */ - lang_strings(); - - /* Activate the new language for the application. */ - SetThreadUILanguage(lang_curr); - - /* This can be removed, it no longer works since Vista+ */ - lcid = MAKELCID(id, SORT_DEFAULT); - SetThreadLocale(lcid); - - /* All is good, language set! */ - return(1); -} - - -void -plat_lang_menu(void) -{ - lang_t *ptr; - int i; - - i = IDM_LANGUAGE; - for (ptr = languages; ptr != NULL; ptr = ptr->next) { - i++; - - /* Add this language to the Languages menu. */ - menu_add_item(IDM_LANGUAGE, i, ptr->name); - - /* Add separator after primary language. */ - if (ptr == languages) - menu_add_item(IDM_LANGUAGE, i, NULL); - } - - /* Set active language. */ - lang_check(lang_id); + return((const string_t *)array); } diff --git a/src/win/win_midi.c b/src/win/win_midi.c index 88074a8..439d341 100644 --- a/src/win/win_midi.c +++ b/src/win/win_midi.c @@ -8,7 +8,7 @@ * * Implementation of the System MIDI interface. * - * Version: @(#)win_midi.c 1.0.4 2018/05/06 + * Version: @(#)win_midi.c 1.0.5 2018/10/05 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -42,6 +42,7 @@ #include #include #include +#include #include #include "../emu.h" #include "../config.h" @@ -50,74 +51,61 @@ #include "win.h" -int midi_id = 0; -HANDLE m_event; -MIDIHDR m_hdr; +typedef struct { + int id; + HANDLE event; + HMIDIOUT out_device; + MIDIHDR hdr; +} midi_t; -static HMIDIOUT midi_out_device = NULL; -static uint8_t midi_rt_buf[1024]; -static uint8_t midi_cmd_buf[1024]; -static int midi_cmd_pos = 0; -static int midi_cmd_len = 0; -static uint8_t midi_status = 0; -static unsigned int midi_sysex_start = 0; -static unsigned int midi_sysex_delay = 0; +static midi_t *pm = NULL; void plat_midi_init(void) { - MMRESULT hr = MMSYSERR_NOERROR; + MMRESULT hr; - /* This is for compatibility with old configuration files. */ - midi_id = config_get_int("Sound", "midi_host_device", -1); - if (midi_id == -1) { - midi_id = config_get_int(SYSTEM_MIDI_NAME, "midi", 0); - } else { - config_delete_var("Sound", "midi_host_device"); - config_set_int(SYSTEM_MIDI_NAME, "midi", midi_id); - } + pm = (midi_t *)mem_alloc(sizeof(midi_t)); + memset(pm, 0x00, sizeof(midi_t)); - memset(midi_rt_buf, 0, sizeof(midi_rt_buf)); - memset(midi_cmd_buf, 0, sizeof(midi_cmd_buf)); + pm->id = config_get_int(SYSTEM_MIDI_NAME, "midi", 0); - midi_cmd_pos = midi_cmd_len = 0; - midi_status = 0; + pm->event = CreateEvent(NULL, TRUE, TRUE, NULL); - midi_sysex_start = midi_sysex_delay = 0; - - m_event = CreateEvent(NULL, TRUE, TRUE, NULL); - - hr = midiOutOpen(&midi_out_device, midi_id, (uintptr_t) m_event, - 0, CALLBACK_EVENT); + hr = midiOutOpen(&pm->out_device, pm->id, + (uintptr_t)pm->event, 0, CALLBACK_EVENT); if (hr != MMSYSERR_NOERROR) { - pclog("midiOutOpen error - %08X\n",hr); - midi_id = 0; - hr = midiOutOpen(&midi_out_device, midi_id, (uintptr_t) m_event, - 0, CALLBACK_EVENT); + pm->id = 0; + hr = midiOutOpen(&pm->out_device, pm->id, + (uintptr_t)pm->event, 0, CALLBACK_EVENT); if (hr != MMSYSERR_NOERROR) { - pclog("midiOutOpen error - %08X\n",hr); + ERRLOG("WIN MIDI: midiOutOpen error - %08X\n", hr); + free(pm); return; } } - midiOutReset(midi_out_device); + midiOutReset(pm->out_device); } void plat_midi_close(void) { - if (midi_out_device != NULL) { - midiOutReset(midi_out_device); - midiOutClose(midi_out_device); -#if 0 - midi_out_device = NULL; -#endif + if (pm == NULL) return; - CloseHandle(m_event); + if (pm->out_device != NULL) { + midiOutReset(pm->out_device); + midiOutClose(pm->out_device); + + CloseHandle(pm->event); } + + free(pm); + + pm = NULL; } @@ -141,7 +129,9 @@ plat_midi_get_dev_name(int num, char *s) void plat_midi_play_msg(uint8_t *msg) { - midiOutShortMsg(midi_out_device, *(uint32_t *) msg); + if (pm == NULL) return; + + midiOutShortMsg(pm->out_device, *(uint32_t *)msg); } @@ -150,26 +140,28 @@ plat_midi_play_sysex(uint8_t *sysex, unsigned int len) { MMRESULT result; - if (WaitForSingleObject(m_event, 2000) == WAIT_TIMEOUT) { - pclog("Can't send MIDI message\n"); + if (pm == NULL) return; + + if (WaitForSingleObject(pm->event, 2000) == WAIT_TIMEOUT) { + ERRLOG("WIN MIDI: can't send MIDI message\n"); return; } - midiOutUnprepareHeader(midi_out_device, &m_hdr, sizeof(m_hdr)); + midiOutUnprepareHeader(pm->out_device, &pm->hdr, sizeof(pm->hdr)); - m_hdr.lpData = (char *) sysex; - m_hdr.dwBufferLength = len; - m_hdr.dwBytesRecorded = len; - m_hdr.dwUser = 0; + pm->hdr.lpData = (char *)sysex; + pm->hdr.dwBufferLength = len; + pm->hdr.dwBytesRecorded = len; + pm->hdr.dwUser = 0; - result = midiOutPrepareHeader(midi_out_device, &m_hdr, sizeof(m_hdr)); + result = midiOutPrepareHeader(pm->out_device, &pm->hdr, sizeof(pm->hdr)); if (result != MMSYSERR_NOERROR) return; - ResetEvent(m_event); + ResetEvent(pm->event); - result = midiOutLongMsg(midi_out_device, &m_hdr, sizeof(m_hdr)); + result = midiOutLongMsg(pm->out_device, &pm->hdr, sizeof(pm->hdr)); if (result != MMSYSERR_NOERROR) - SetEvent(m_event); + SetEvent(pm->event); } diff --git a/src/win/win_mouse.cpp b/src/win/win_mouse.cpp index a2809d7..e2f4549 100644 --- a/src/win/win_mouse.cpp +++ b/src/win/win_mouse.cpp @@ -8,7 +8,7 @@ * * Mouse interface to host device. * - * Version: @(#)win_mouse.cpp 1.0.6 2018/05/06 + * Version: @(#)win_mouse.cpp 1.0.7 2018/10/05 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -47,12 +47,9 @@ #include "win.h" -int mouse_capture; - - -static LPDIRECTINPUT8 lpdi; -static LPDIRECTINPUTDEVICE8 lpdi_mouse = NULL; -static DIMOUSESTATE mousestate; +static LPDIRECTINPUT8 lpdi; +static LPDIRECTINPUTDEVICE8 lpdi_mouse = NULL; +static DIMOUSESTATE mousestate; void diff --git a/src/win/win_new_image.c b/src/win/win_new_image.c index 7769571..1fb55ca 100644 --- a/src/win/win_new_image.c +++ b/src/win/win_new_image.c @@ -8,7 +8,7 @@ * * Implementation of the New Floppy/ZIP Image dialog. * - * Version: @(#)win_new_image.c 1.0.19 2018/06/05 + * Version: @(#)win_new_image.c 1.0.20 2018/10/05 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -46,8 +46,10 @@ #include "../emu.h" #include "../ui/ui.h" #include "../plat.h" +#include "../devices/scsi/scsi_device.h" #include "../devices/disk/zip.h" #include "win.h" +#include "resource.h" static wchar_t fd_file_name[512]; @@ -84,19 +86,17 @@ dlg_init(HWND hdlg) if (is_zip) { zip_types = zip_drives[drive_id].is_250 ? 2 : 1; for (i = 0; i < zip_types; i++) - SendMessage(h, CB_ADDSTRING, 0, - (LPARAM)get_string(IDS_3282 + 12 + i)); + SendMessage(h, CB_ADDSTRING, 0, win_string(IDS_3282 + 12 + i)); } else { for (i = 0; i < 12; i++) - SendMessage(h, CB_ADDSTRING, 0, - (LPARAM)get_string(IDS_3282 + i)); + SendMessage(h, CB_ADDSTRING, 0, win_string(IDS_3282 + i)); } SendMessage(h, CB_SETCURSEL, 0, 0); EnableWindow(h, FALSE); h = GetDlgItem(hdlg, IDC_COMBO_RPM_MODE); for (i = 0; i < 4; i++) - SendMessage(h, CB_ADDSTRING, 0, (LPARAM)get_string(IDS_3278 + i)); + SendMessage(h, CB_ADDSTRING, 0, win_string(IDS_3278 + i)); SendMessage(h, CB_SETCURSEL, 0, 0); EnableWindow(h, FALSE); ShowWindow(h, SW_HIDE); @@ -136,7 +136,7 @@ dlg_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) switch (message) { case WM_INITDIALOG: - plat_pause(1); + pc_pause(1); dialog_center(hdlg); @@ -166,18 +166,18 @@ dlg_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) } if (ret) { if (is_zip) - ui_sb_mount_zip(drive_id, sb_part, 0, fd_file_name); + ui_zip_mount(drive_id, sb_part, 0, fd_file_name); else - ui_sb_mount_floppy(drive_id, sb_part, 0, fd_file_name); + ui_floppy_mount(drive_id, sb_part, 0, fd_file_name); } else { msg_box(hdlg, MBX_ERROR, (wchar_t *)IDS_OPEN_WRITE); - plat_pause(0); + pc_pause(0); return TRUE; } case IDCANCEL: EndDialog(hdlg, 0); - plat_pause(0); + pc_pause(0); return TRUE; case IDC_CFILE: @@ -207,11 +207,9 @@ dlg_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) if (f != NULL) { fclose(f); if (msg_box(hdlg, MBX_QUESTION, (wchar_t *)IDS_IMG_EXIST) != 0) /* yes */ { -pclog("SELECT: != 0 (NO)\n"); return FALSE; } } -pclog("SELECT: YES\n"); SendMessage(h, WM_SETTEXT, 0, (LPARAM)temp_path); memset(fd_file_name, 0x00, sizeof(fd_file_name)); wcscpy(fd_file_name, temp_path); diff --git a/src/win/win_opendir.c b/src/win/win_opendir.c index 916f1d8..d0a1ea9 100644 --- a/src/win/win_opendir.c +++ b/src/win/win_opendir.c @@ -10,7 +10,7 @@ * * Based on old original code @(#)dir_win32.c 1.2.0 2007/04/19 * - * Version: @(#)win_opendir.c 1.0.7 2018/05/18 + * Version: @(#)win_opendir.c 1.0.8 2018/10/05 * * Author: Fred N. van Kempen, * @@ -73,16 +73,16 @@ opendir(const wchar_t *name) DIR *p; /* Create a new control structure. */ - p = (DIR *) malloc(sizeof(DIR)); + p = (DIR *)mem_alloc(sizeof(DIR)); if (p == NULL) return(NULL); memset(p, 0x00, sizeof(DIR)); - p->flags = (DIR_F_LOWER | DIR_F_SANE); + p->flags = DIR_F_LOWER | DIR_F_SANE; p->offset = 0; p->sts = 0; /* Create a work area. */ - p->dta = (char *)malloc(sizeof(FINDATA)); + p->dta = (char *)mem_alloc(sizeof(FINDATA)); if (p->dta == NULL) { free(p); return(NULL); @@ -117,7 +117,8 @@ closedir(DIR *p) if (p == NULL) return(0); - _findclose(p->handle); + if (p->handle) + _findclose(p->handle); if (p->dta != NULL) free(p->dta); @@ -129,6 +130,7 @@ closedir(DIR *p) /* * Read the next entry from a directory. + * * Note that the DOS (FAT), Windows (FAT, FAT32) and Windows NTFS * file systems do not have a root directory containing the UNIX- * standard "." and ".." entries. Many applications do assume @@ -159,7 +161,7 @@ readdir(DIR *p) default: /* regular entry. */ wcsncpy(p->dent.d_name, ffp->name, MAXNAMLEN+1); - p->dent.d_reclen = (char) wcslen(p->dent.d_name); + p->dent.d_reclen = (unsigned short)wcslen(p->dent.d_name); } /* Read next entry. */ @@ -203,7 +205,7 @@ seekdir(DIR *p, long newpos) if (newpos == 0L) return; /* Nope.. read entries until we hit the right spot. */ - pos = (short) newpos; + pos = (short)newpos; while (p->offset != pos) { p->offset++; if (FINDNEXT(p->handle, (FINDATA *)p->dta) < 0) { diff --git a/src/win/win_opendir.h b/src/win/win_opendir.h index ed55aca..8b0fdc5 100644 --- a/src/win/win_opendir.h +++ b/src/win/win_opendir.h @@ -8,7 +8,7 @@ * * Definitions for the platform OpenDir module. * - * Version: @(#)win_opendir.h 1.0.3 2018/05/18 + * Version: @(#)win_opendir.h 1.0.4 2018/09/25 * * Author: Fred N. van Kempen, * @@ -51,16 +51,16 @@ #ifdef _MAX_FNAME # define MAXNAMLEN _MAX_FNAME #else -# define MAXNAMLEN 15 +# define MAXNAMLEN 255 #endif -# define MAXDIRLEN 127 +#define MAXDIRLEN 255 struct direct { long d_ino; unsigned short d_reclen; unsigned short d_off; - wchar_t d_name[MAXNAMLEN + 1]; + wchar_t d_name[MAXNAMLEN+1]; }; #define d_namlen d_reclen diff --git a/src/win/win_sdl.c b/src/win/win_sdl.c index 15f930a..342463c 100644 --- a/src/win/win_sdl.c +++ b/src/win/win_sdl.c @@ -12,7 +12,7 @@ * we will not use that, but, instead, use a new window which * coverrs the entire desktop. * - * Version: @(#)win_sdl.c 1.0.4 2018/06/10 + * Version: @(#)win_sdl.c 1.0.5 2018/10/05 * * Authors: Fred N. van Kempen, * Michael Dring, @@ -224,24 +224,24 @@ sdl_init(int fs) wchar_t temp[128]; SDL_version ver; - pclog("SDL: init (fs=%d)\n", fs); + INFO("SDL: init (fs=%d)\n", fs); cgapal_rebuild(); /* Try loading the DLL. */ sdl_handle = dynld_module(PATH_SDL_DLL, sdl_imports); if (sdl_handle == NULL) { - pclog("SDL: unable to load '%s', SDL not available.\n", PATH_SDL_DLL); + ERRLOG("SDL: unable to load '%s', SDL not available.\n", PATH_SDL_DLL); return(0); } /* Get and log the version of the DLL we are using. */ sdl_GetVersion(&ver); - pclog("SDL: version %d.%d.%d\n", ver.major, ver.minor, ver.patch); + INFO("SDL: version %d.%d.%d\n", ver.major, ver.minor, ver.patch); /* Initialize the SDL system. */ if (sdl_Init(SDL_INIT_VIDEO) < 0) { - pclog("SDL: initialization failed (%s)\n", sdl_GetError()); + ERRLOG("SDL: initialization failed (%s)\n", sdl_GetError()); return(0); } @@ -251,8 +251,8 @@ sdl_init(int fs) sdl_h = GetSystemMetrics(SM_CYSCREEN); /* Create the desktop-covering window. */ - _swprintf(temp, L"%s v%s Full-Screen", - TEXT(EMU_NAME), TEXT(EMU_VERSION)); + swprintf(temp, sizeof_w(temp), + L"%s v%s Full-Screen", EMU_NAME, emu_version); sdl_hwnd = CreateWindow(FS_CLASS_NAME, temp, WS_POPUP, @@ -261,7 +261,7 @@ sdl_init(int fs) NULL, hInstance, NULL); -pclog("SDL: FS %dx%d window at %08lx\n", sdl_w, sdl_h, sdl_hwnd); + DEBUG("SDL: FS %dx%d window at %08lx\n", sdl_w, sdl_h, sdl_hwnd); /* Redirect RawInput to this new window. */ plat_set_input(sdl_hwnd); @@ -277,7 +277,7 @@ pclog("SDL: FS %dx%d window at %08lx\n", sdl_w, sdl_h, sdl_hwnd); sdl_win = sdl_CreateWindowFrom((void *)hwndRender); } if (sdl_win == NULL) { - pclog("SDL: unable to CreateWindowFrom (%s)\n", sdl_GetError()); + ERRLOG("SDL: unable to CreateWindowFrom (%s)\n", sdl_GetError()); sdl_close(); return(0); } @@ -291,7 +291,7 @@ pclog("SDL: FS %dx%d window at %08lx\n", sdl_w, sdl_h, sdl_hwnd); */ sdl_render = sdl_CreateRenderer(sdl_win, -1, SDL_RENDERER_SOFTWARE); if (sdl_render == NULL) { - pclog("SDL: unable to create renderer (%s)\n", sdl_GetError()); + ERRLOG("SDL: unable to create renderer (%s)\n", sdl_GetError()); sdl_close(); return(0); } @@ -305,7 +305,7 @@ pclog("SDL: FS %dx%d window at %08lx\n", sdl_w, sdl_h, sdl_hwnd); sdl_tex = sdl_CreateTexture(sdl_render, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, 2048, 2048); if (sdl_tex == NULL) { - pclog("SDL: unable to create texture (%s)\n", sdl_GetError()); + ERRLOG("SDL: unable to create texture (%s)\n", sdl_GetError()); sdl_close(); return(0); } @@ -323,7 +323,7 @@ pclog("SDL: FS %dx%d window at %08lx\n", sdl_w, sdl_h, sdl_hwnd); static void sdl_resize(int x, int y) { - pclog("SDL: resizing to %dx%d\n", x, y); + DEBUG("SDL: resizing to %dx%d\n", x, y); } @@ -340,21 +340,21 @@ sdl_screenshot(const wchar_t *fn) /* Create file. */ if ((fp = plat_fopen(fn, L"wb")) == NULL) { - pclog("SDL: screenshot: file %ls could not be opened for writing\n", fn); + ERRLOG("SDL: screenshot: file %ls could not be opened for writing\n", fn); return; } /* initialize stuff */ png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (png_ptr == NULL) { - pclog("SDL: screenshot: create_write_struct failed\n"); + ERRLOG("SDL: screenshot: create_write_struct failed\n"); fclose(fp); return; } info_ptr = png_create_info_struct(png_ptr); if (info_ptr == NULL) { - pclog("SDL: screenshot: create_info_struct failed"); + ERRLOG("SDL: screenshot: create_info_struct failed"); fclose(fp); return; } @@ -365,9 +365,9 @@ sdl_screenshot(const wchar_t *fn) 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); - pixels = (uint8_t *)malloc(width * height * 4); + pixels = (uint8_t *)mem_alloc(width * height * 4); if (pixels == NULL) { - pclog("SDL: screenshot: unable to allocate RGBA Bitmap memory\n"); + ERRLOG("SDL: screenshot: unable to allocate RGBA Bitmap memory\n"); fclose(fp); return; } @@ -375,21 +375,21 @@ sdl_screenshot(const wchar_t *fn) res = sdl_RenderReadPixels(sdl_render, NULL, SDL_PIXELFORMAT_ABGR8888, pixels, width * 4); if (res != 0) { - pclog("SDL: screenshot: error reading render pixels\n"); + ERRLOG("SDL: screenshot: error reading render pixels\n"); free(pixels); fclose(fp); return; } - if ((b_rgb = (png_bytep *) malloc(sizeof(png_bytep) * height)) == NULL) { - sdl_log("[sdl_take_screenshot] Unable to Allocate RGB Bitmap Memory"); + if ((b_rgb = (png_bytep *)mem_alloc(sizeof(png_bytep) * height)) == NULL) { + ERRLOG("[sdl_take_screenshot] Unable to Allocate RGB Bitmap Memory"); free(rgba); fclose(fp); return; } for (y = 0; y < height; ++y) { - b_rgb[y] = (png_byte *) malloc(png_get_rowbytes(png_ptr, info_ptr)); + b_rgb[y] = (png_byte *)mem_alloc(png_get_rowbytes(png_ptr, info_ptr)); for (x = 0; x < width; ++x) { b_rgb[y][(x) * 3 + 0] = rgba[(y * width + x) * 4 + 0]; b_rgb[y][(x) * 3 + 1] = rgba[(y * width + x) * 4 + 1]; diff --git a/src/win/win_serial.c b/src/win/win_serial.c index 9785f0e..0157d1b 100644 --- a/src/win/win_serial.c +++ b/src/win/win_serial.c @@ -417,7 +417,7 @@ bhtty_open(char *port, int tmo) DWORD d; /* First things first... create a control block. */ - if ((pp = (BHTTY *)malloc(sizeof(BHTTY))) == NULL) { + if ((pp = (BHTTY *)mem_alloc(sizeof(BHTTY))) == NULL) { pclog("%s: out of memory!\n", port); return(NULL); } diff --git a/src/win/win_settings.c b/src/win/win_settings.c index 9181f2c..29ac6ad 100644 --- a/src/win/win_settings.c +++ b/src/win/win_settings.c @@ -8,7 +8,7 @@ * * Implementation of the Settings dialog. * - * Version: @(#)win_settings.c 1.0.33 2018/08/27 + * Version: @(#)win_settings.c 1.0.34 2018/10/05 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -66,15 +66,17 @@ #include "../devices/disk/hdd.h" #include "../devices/disk/hdc.h" #include "../devices/disk/hdc_ide.h" -#include "../devices/disk/zip.h" -#include "../devices/cdrom/cdrom.h" #include "../devices/scsi/scsi.h" +#include "../devices/scsi/scsi_device.h" +#include "../devices/cdrom/cdrom.h" +#include "../devices/disk/zip.h" #include "../devices/network/network.h" #include "../devices/sound/sound.h" #include "../devices/sound/midi.h" #include "../devices/sound/snd_mpu401.h" #include "../devices/video/video.h" #include "win.h" +#include "resource.h" /* Defined in the Video module. */ @@ -90,14 +92,14 @@ static int temp_dynarec; #endif /* Video category. */ -static int temp_video_card, temp_video_speed, temp_voodoo; +static int temp_video_card, temp_voodoo; /* Input devices category. */ static int temp_mouse, temp_joystick; /* Sound category. */ static int temp_sound_card, temp_midi_device, temp_mpu401, - temp_opl3_type, temp_float; + temp_opl_type, temp_float; /* Network category. */ static int temp_net_type, temp_net_card; @@ -112,9 +114,9 @@ static int temp_game, /* Other peripherals category. */ static int temp_hdc_type, temp_scsi_card, - temp_ide_ter, temp_ide_ter_irq, - temp_ide_qua, temp_ide_qua_irq; -static int temp_bugger, + temp_ide_ter, + temp_ide_qua, + temp_bugger, temp_isartc, temp_isamem[ISAMEM_MAX]; @@ -185,11 +187,10 @@ settings_init(void) temp_dynarec = cpu_use_dynarec; #endif temp_fpu = enable_external_fpu; - temp_sync = enable_sync; + temp_sync = time_sync; /* Video category */ temp_video_card = video_card; - temp_video_speed = video_speed; temp_voodoo = voodoo_enabled; /* Input devices category */ @@ -200,7 +201,7 @@ settings_init(void) temp_sound_card = sound_card; temp_midi_device = midi_device; temp_mpu401 = mpu401_standalone_enable; - temp_opl3_type = opl3_type; + temp_opl_type = opl_type; temp_float = sound_is_float; /* Network category */ @@ -221,10 +222,8 @@ settings_init(void) /* Other peripherals category */ temp_scsi_card = scsi_card; temp_hdc_type = hdc_type; - temp_ide_ter = ide_enable[2]; - temp_ide_ter_irq = ide_irq[2]; - temp_ide_qua = ide_enable[3]; - temp_ide_qua_irq = ide_irq[3]; + temp_ide_ter = ide_ter_enabled; + temp_ide_qua = ide_qua_enabled; temp_bugger = bugger_enabled; temp_isartc = isartc_type; @@ -266,11 +265,10 @@ settings_changed(void) i = i || (temp_dynarec != cpu_use_dynarec); #endif i = i || (temp_fpu != enable_external_fpu); - i = i || (temp_sync != enable_sync); + i = i || (temp_sync != time_sync); /* Video category */ i = i || (video_card != temp_video_card); - i = i || (video_speed != temp_video_speed); i = i || (voodoo_enabled != temp_voodoo); /* Input devices category */ @@ -281,7 +279,7 @@ settings_changed(void) i = i || (sound_card != temp_sound_card); i = i || (midi_device != temp_midi_device); i = i || (mpu401_standalone_enable != temp_mpu401); - i = i || (opl3_type != temp_opl3_type); + i = i || (opl_type != temp_opl_type); i = i || (sound_is_float != temp_float); /* Network category */ @@ -301,10 +299,8 @@ settings_changed(void) /* Peripherals category */ i = i || (temp_scsi_card != scsi_card); i = i || (temp_hdc_type != hdc_type); - i = i || (temp_ide_ter != ide_enable[2]); - i = i || (temp_ide_ter_irq != ide_irq[2]); - i = i || (temp_ide_qua != ide_enable[3]); - i = i || (temp_ide_qua_irq != ide_irq[3]); + i = i || (temp_ide_ter != ide_ter_enabled); + i = i || (temp_ide_qua != ide_qua_enabled); i = i || (temp_bugger != bugger_enabled); i = i || (temp_isartc != isartc_type); @@ -364,7 +360,6 @@ settings_save(void) /* Machine category */ machine = temp_machine; - romset = machine_getromset(); cpu_manufacturer = temp_cpu_m; cpu_waitstates = temp_wait_states; cpu = temp_cpu; @@ -373,11 +368,10 @@ settings_save(void) cpu_use_dynarec = temp_dynarec; #endif enable_external_fpu = temp_fpu; - enable_sync = temp_sync; + time_sync = temp_sync; /* Video category */ video_card = temp_video_card; - video_speed = temp_video_speed; voodoo_enabled = temp_voodoo; /* Input devices category */ @@ -388,7 +382,7 @@ settings_save(void) sound_card = temp_sound_card; midi_device = temp_midi_device; mpu401_standalone_enable = temp_mpu401; - opl3_type = temp_opl3_type; + opl_type = temp_opl_type; sound_is_float = temp_float; /* Network category */ @@ -409,10 +403,8 @@ settings_save(void) /* Peripherals category */ scsi_card = temp_scsi_card; hdc_type = temp_hdc_type; - ide_enable[2] = temp_ide_ter; - ide_irq[2] = temp_ide_ter_irq; - ide_enable[3] = temp_ide_qua; - ide_irq[3] = temp_ide_qua_irq; + ide_ter_enabled = temp_ide_ter; + ide_qua_enabled = temp_ide_qua; bugger_enabled = temp_bugger; isartc_type = temp_isartc; @@ -457,6 +449,9 @@ settings_save(void) #define PAGE_OTHER_REMOVABLE_DEVICES 9 #define PAGE_MAX 10 +/* Icon, Bus, File, C, H, S, Size. */ +#define C_COLUMNS_HARD_DISKS 6 + static void show_child(HWND hwndParent, DWORD child_id) @@ -465,7 +460,7 @@ show_child(HWND hwndParent, DWORD child_id) displayed_category = child_id; - SendMessage(hwndChildDialog, WM_SAVESETTINGS, 0, 0); + SendMessage(hwndChildDialog, WM_SAVE_CFG, 0, 0); DestroyWindow(hwndChildDialog); @@ -542,6 +537,18 @@ show_child(HWND hwndParent, DWORD child_id) static BOOL image_list_init(HWND hwndList) { + int icons[PAGE_MAX] = { + ICON_MACHINE, + ICON_DISPLAY, + ICON_INPDEV, + ICON_SOUND, + ICON_NETWORK, + ICON_PORTS, + ICON_PERIPH, + ICON_DISK, + ICON_FLOPPY, + ICON_REMOV + }; HICON hiconItem; HIMAGELIST hSmall; int i; @@ -550,8 +557,9 @@ image_list_init(HWND hwndList) GetSystemMetrics(SM_CYSMICON), ILC_MASK | ILC_COLOR32, 1, 1); + for (i = 0; i < PAGE_MAX; i++) { - hiconItem = LoadIcon(hInstance, (LPCWSTR)(256 + i)); + hiconItem = LoadIcon(hInstance, (LPCWSTR)icons[i]); ImageList_AddIcon(hSmall, hiconItem); DestroyIcon(hiconItem); } @@ -629,7 +637,7 @@ dlg_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) case WM_COMMAND: switch (LOWORD(wParam)) { case IDOK: - SendMessage(hwndChildDialog, WM_SAVESETTINGS, 0, 0); + SendMessage(hwndChildDialog, WM_SAVE_CFG, 0, 0); if (ask_sure) { i = msgbox_reset(); if (i == 0) { @@ -665,22 +673,71 @@ dlg_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) } +/* + * Find all available machine ROMs. + * + * While we scan for the roms, we also build + * the arrays needed by the Machines dialog, + * saving us from having to do it twice.. + */ +static int +find_roms(void) +{ + const char *str; + int c, d, i; + + c = d = 0; + while(1) { + /* Get ANSI name of machine. */ + str = machine_getname_ex(c); + if (str == NULL) + break; + + /* If entry already used, clear it. */ + if (mach_names[d] != NULL) + free(mach_names[d]); + + /* Is this machine available? */ + if (machine_available(c)) { + /* Allocate space and copy name to Unicode. */ + i = strlen(str) + 1; + mach_names[d] = (wchar_t *)mem_alloc(i * sizeof(wchar_t)); + mbstowcs(mach_names[d], str, i); + + /* Add entry to the conversion lists. */ + list_to_mach[d] = c; + mach_to_list[c] = d++; + } + + /* Next machine from table. */ + c++; + } + + return(d); +} + + int dlg_settings(int ask) { - int i, m, v; + int i; - /* Enumerate the available machines. */ - m = machine_detect(); + /* + * This looks weird here, but we have to do it + * before we open up the Settings dialog, else + * we cannot close it after the msgbox exits.. + */ + INFO("Scanning for ROM images:\n"); + if ((i = find_roms()) <= 0) { + /* No usable ROMs found, aborting. */ + ERRLOG("No usable machine has been found!\n"); - /* Enumerate the available video cards. */ - v = video_detect(); - - if (m == 0 || v == 0) { + /* Tell the user about it. */ ui_msgbox(MBX_ERROR|MBX_FATAL, (wchar_t *)IDS_ERR_NOROMS); return(0); } + INFO("A total of %i machines are available.\n", i); ask_sure = ask; i = DialogBox(plat_lang_dll(), (LPCWSTR)DLG_CONFIG, hwndMain, dlg_proc); diff --git a/src/win/win_settings_disk.h b/src/win/win_settings_disk.h index bfa7a3b..972e057 100644 --- a/src/win/win_settings_disk.h +++ b/src/win/win_settings_disk.h @@ -8,7 +8,7 @@ * * Implementation of the Settings dialog. * - * Version: @(#)win_settings_disk.h 1.0.13 2018/09/03 + * Version: @(#)win_settings_disk.h 1.0.14 2018/09/22 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -64,16 +64,6 @@ static int hdlv_current_sel; static int next_free_id = 0; -static int -combo_to_ids(int id) -{ - if (id == 0) - return(IDS_DISABLED); - - return(IDS_3515 + id - 1); -} - - static void disk_track_init(void) { @@ -88,14 +78,10 @@ disk_track_init(void) st506_tracking |= (1ULL << (hdd[i].id.st506_channel << 3)); else if (hdd[i].bus == HDD_BUS_ESDI) esdi_tracking |= (1ULL << (hdd[i].id.esdi_channel << 3)); - else if (hdd[i].bus == HDD_BUS_IDE_PIO_ONLY) - ide_tracking |= (1ULL << (hdd[i].id.ide_channel << 3)); - else if (hdd[i].bus == HDD_BUS_IDE_PIO_AND_DMA) + else if (hdd[i].bus == HDD_BUS_IDE) ide_tracking |= (1ULL << (hdd[i].id.ide_channel << 3)); else if (hdd[i].bus == HDD_BUS_SCSI) scsi_tracking[hdd[i].id.scsi.id] |= (1ULL << (hdd[i].id.scsi.lun << 3)); - else if (hdd[i].bus == HDD_BUS_SCSI_REMOVABLE) - scsi_tracking[hdd[i].id.scsi.id] |= (1ULL << (hdd[i].id.scsi.lun << 3)); } } @@ -110,11 +96,7 @@ disk_image_list_init(HWND hwndList) GetSystemMetrics(SM_CYSMICON), ILC_MASK | ILC_COLOR32, 1, 1); - hiconItem = LoadIcon(hInstance, (LPCWSTR)208); - ImageList_AddIcon(hSmall, hiconItem); - DestroyIcon(hiconItem); - - hiconItem = LoadIcon(hInstance, (LPCWSTR)192); + hiconItem = LoadIcon(hInstance, (LPCWSTR)ICON_DISK); ImageList_AddIcon(hSmall, hiconItem); DestroyIcon(hiconItem); @@ -174,9 +156,8 @@ disk_add_locations(HWND hdlg) int i; h = GetDlgItem(hdlg, IDC_COMBO_HD_BUS); - for (i = 0; i < 6; i++) - SendMessage(h, CB_ADDSTRING, 0, - (LPARAM)get_string(combo_to_ids(i))); + for (i = 0; i < HDD_BUS_MAX; i++) + SendMessage(h, CB_ADDSTRING, 0, (LPARAM)hdd_bus_to_ids(i)); h = GetDlgItem(hdlg, IDC_COMBO_HD_CHANNEL); for (i = 0; i < 8; i++) { @@ -338,8 +319,7 @@ disk_recalc_location_controls(HWND hdlg, int is_add_dlg, int assign_id) SendMessage(h, CB_SETCURSEL, is_add_dlg ? new_hdd.id.esdi_channel : temp_hdd[hdlv_current_sel].id.esdi_channel, 0); break; - case HDD_BUS_IDE_PIO_ONLY: /* IDE (PIO-only) */ - case HDD_BUS_IDE_PIO_AND_DMA: /* IDE (PIO and DMA) */ + case HDD_BUS_IDE: /* IDE */ h = GetDlgItem(hdlg, IDT_1722); ShowWindow(h, SW_SHOW); EnableWindow(h, TRUE); @@ -352,8 +332,7 @@ disk_recalc_location_controls(HWND hdlg, int is_add_dlg, int assign_id) SendMessage(h, CB_SETCURSEL, is_add_dlg ? new_hdd.id.ide_channel : temp_hdd[hdlv_current_sel].id.ide_channel, 0); break; - case HDD_BUS_SCSI: /* SCSI */ - case HDD_BUS_SCSI_REMOVABLE: /* SCSI (removable) */ + case HDD_BUS_SCSI: /* SCSI */ h = GetDlgItem(hdlg, IDT_1723); ShowWindow(h, SW_SHOW); EnableWindow(h, TRUE); @@ -374,6 +353,10 @@ disk_recalc_location_controls(HWND hdlg, int is_add_dlg, int assign_id) EnableWindow(h, TRUE); SendMessage(h, CB_SETCURSEL, is_add_dlg ? new_hdd.id.scsi.lun : temp_hdd[hdlv_current_sel].id.scsi.lun, 0); break; + + case HDD_BUS_USB: /* USB */ + /* Just kidding. Not yet supported. */ + break; } } @@ -403,8 +386,7 @@ recalc_next_free_id(HWND hdlg) HWND h; int c_st506 = 0; int c_esdi = 0; - int c_ide_pio = 0; - int c_ide_dma = 0; + int c_ide = 0; int c_scsi = 0; int enable_add = 0; int i; @@ -416,14 +398,10 @@ recalc_next_free_id(HWND hdlg) c_st506++; else if (temp_hdd[i].bus == HDD_BUS_ESDI) c_esdi++; - else if (temp_hdd[i].bus == HDD_BUS_IDE_PIO_ONLY) - c_ide_pio++; - else if (temp_hdd[i].bus == HDD_BUS_IDE_PIO_AND_DMA) - c_ide_dma++; + else if (temp_hdd[i].bus == HDD_BUS_IDE) + c_ide++; else if (temp_hdd[i].bus == HDD_BUS_SCSI) c_scsi++; - else if (temp_hdd[i].bus == HDD_BUS_SCSI_REMOVABLE) - c_scsi++; } for (i = 0; i < HDD_NUM; i++) { @@ -434,7 +412,10 @@ recalc_next_free_id(HWND hdlg) } enable_add = enable_add || (next_free_id >= 0); - enable_add = enable_add && ((c_st506 < ST506_NUM) || (c_esdi < ESDI_NUM) || (c_ide_pio < IDE_NUM) || (c_ide_dma < IDE_NUM) || (c_scsi < SCSI_NUM)); + enable_add = enable_add && ((c_st506 < ST506_NUM) || + (c_esdi < ESDI_NUM) || + (c_ide < IDE_NUM) || + (c_scsi < SCSI_NUM)); enable_add = enable_add && !bus_full(&st506_tracking, 2); enable_add = enable_add && !bus_full(&esdi_tracking, 2); enable_add = enable_add && !bus_full(&ide_tracking, 8); @@ -454,7 +435,7 @@ recalc_next_free_id(HWND hdlg) EnableWindow(h, FALSE); h = GetDlgItem(hdlg, IDC_BUTTON_HDD_REMOVE); - if ((c_st506 == 0) && (c_esdi == 0) && (c_ide_pio == 0) && (c_ide_dma == 0) && (c_scsi == 0)) + if ((c_st506 == 0) && (c_esdi == 0) && (c_ide == 0) && (c_scsi == 0)) EnableWindow(h, FALSE); else EnableWindow(h, TRUE); @@ -476,37 +457,39 @@ disk_update_item(HWND hwndList, int i, int column) switch(temp_hdd[i].bus) { case HDD_BUS_ST506: swprintf(temp, sizeof_w(temp), L"%ls (%01i:%01i)", - get_string(combo_to_ids(temp_hdd[i].bus)), + hdd_bus_to_ids(temp_hdd[i].bus), temp_hdd[i].id.st506_channel >> 1, temp_hdd[i].id.st506_channel & 1); break; case HDD_BUS_ESDI: swprintf(temp, sizeof_w(temp), L"%ls (%01i:%01i)", - get_string(combo_to_ids(temp_hdd[i].bus)), + hdd_bus_to_ids(temp_hdd[i].bus), temp_hdd[i].id.esdi_channel >> 1, temp_hdd[i].id.esdi_channel & 1); break; - case HDD_BUS_IDE_PIO_ONLY: - case HDD_BUS_IDE_PIO_AND_DMA: + case HDD_BUS_IDE: swprintf(temp, sizeof_w(temp), L"%ls (%01i:%01i)", - get_string(combo_to_ids(temp_hdd[i].bus)), + hdd_bus_to_ids(temp_hdd[i].bus), temp_hdd[i].id.ide_channel >> 1, temp_hdd[i].id.ide_channel & 1); break; case HDD_BUS_SCSI: - case HDD_BUS_SCSI_REMOVABLE: swprintf(temp, sizeof_w(temp), L"%ls (%02i:%02i)", - get_string(combo_to_ids(temp_hdd[i].bus)), + hdd_bus_to_ids(temp_hdd[i].bus), temp_hdd[i].id.scsi.id, temp_hdd[i].id.scsi.lun); break; + + case HDD_BUS_USB: + /* Nope. Not yet. */ + break; } lvI.pszText = temp; - lvI.iImage = (temp_hdd[i].bus == HDD_BUS_SCSI_REMOVABLE) ? 1 : 0; + lvI.iImage = 0; } else if (column == 1) { lvI.pszText = temp_hdd[i].fn; lvI.iImage = 0; @@ -565,38 +548,40 @@ disk_recalc_list(HWND hwndList) switch(temp_hdd[i].bus) { case HDD_BUS_ST506: swprintf(temp, sizeof_w(temp), L"%ls (%01i:%01i)", - get_string(combo_to_ids(temp_hdd[i].bus)), + hdd_bus_to_ids(temp_hdd[i].bus), temp_hdd[i].id.st506_channel >> 1, temp_hdd[i].id.st506_channel & 1); break; case HDD_BUS_ESDI: swprintf(temp, sizeof_w(temp), L"%ls (%01i:%01i)", - get_string(combo_to_ids(temp_hdd[i].bus)), + hdd_bus_to_ids(temp_hdd[i].bus), temp_hdd[i].id.esdi_channel >> 1, temp_hdd[i].id.esdi_channel & 1); break; - case HDD_BUS_IDE_PIO_ONLY: - case HDD_BUS_IDE_PIO_AND_DMA: + case HDD_BUS_IDE: swprintf(temp, sizeof_w(temp), L"%ls (%01i:%01i)", - get_string(combo_to_ids(temp_hdd[i].bus)), + hdd_bus_to_ids(temp_hdd[i].bus), temp_hdd[i].id.ide_channel >> 1, temp_hdd[i].id.ide_channel & 1); break; case HDD_BUS_SCSI: - case HDD_BUS_SCSI_REMOVABLE: swprintf(temp, sizeof_w(temp), L"%ls (%02i:%02i)", - get_string(combo_to_ids(temp_hdd[i].bus)), + hdd_bus_to_ids(temp_hdd[i].bus), temp_hdd[i].id.scsi.id, temp_hdd[i].id.scsi.lun); break; + + case HDD_BUS_USB: + /* Still not implemened. Submit yours! */ + break; } lvI.pszText = temp; lvI.iItem = j; - lvI.iImage = (temp_hdd[i].bus == HDD_BUS_SCSI_REMOVABLE) ? 1 : 0; + lvI.iImage = 0; if (ListView_InsertItem(hwndList, &lvI) == -1) return FALSE; lvI.iSubItem = 1; @@ -765,8 +750,8 @@ disk_initialize_hdt(HWND hdlg) * Add the "Custom" and "Custom (large)" strings. * Maybe we should have these first in the list? */ - SendMessage(h, CB_ADDSTRING, 0, (LPARAM)get_string(IDS_3511)); - SendMessage(h, CB_ADDSTRING, 0, (LPARAM)get_string(IDS_3512)); + SendMessage(h, CB_ADDSTRING, 0, win_string(IDS_3511)); + SendMessage(h, CB_ADDSTRING, 0, win_string(IDS_3512)); SendMessage(h, CB_SETCURSEL, selection & 0xffff, 0); @@ -804,7 +789,7 @@ disk_add_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) { wchar_t temp_path[512]; char buf[512], *big_buf; - HWND h = INVALID_HANDLE_VALUE; + HWND h; uint64_t i = 0; uint64_t temp; FILE *f; @@ -864,19 +849,27 @@ disk_add_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) disk_add_locations(hdlg); h = GetDlgItem(hdlg, IDC_COMBO_HD_BUS); +#ifdef USE_REMOVABLE_DISK + /* Will leave this for now, we may have removables again! */ if (existing & 2) { hdd_ptr->bus = HDD_BUS_SCSI_REMOVABLE; max_spt = 99; max_hpc = 255; } else { - hdd_ptr->bus = HDD_BUS_IDE_PIO_ONLY; + hdd_ptr->bus = HDD_BUS_IDE; max_spt = 63; max_hpc = 255; } +#else + hdd_ptr->bus = HDD_BUS_IDE; + max_spt = 63; + max_hpc = 255; +#endif SendMessage(h, CB_SETCURSEL, hdd_ptr->bus, 0); max_tracks = 266305; disk_recalc_location_controls(hdlg, 1, 0); +#ifdef USE_REMOVABLE_DISK if (existing & 2) { /* * If we are being called as a "load image" dialog @@ -904,6 +897,7 @@ disk_add_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) SendMessage(h, WM_SETTEXT, 0, (LPARAM)hdd[next_free_id].fn); } else { +#endif channel = next_free_ide_channel(); next_free_scsi_id_and_lun(&id, &lun); h = GetDlgItem(hdlg, IDC_COMBO_HD_CHANNEL); @@ -920,7 +914,9 @@ disk_add_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) new_hdd.id.ide_channel = channel; new_hdd.id.scsi.id = id; new_hdd.id.scsi.lun = lun; +#ifdef USE_REMOVABLE_DISK } +#endif h = GetDlgItem(hdlg, IDC_EDIT_HD_FILE_NAME); EnableWindow(h, FALSE); @@ -943,18 +939,23 @@ disk_add_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) hdd_ptr->bus = SendMessage(h, CB_GETCURSEL, 0, 0) & 0xff; } - /* Make sure no file name is allowed with removable SCSI hard disks. */ - if ((wcslen(hd_file_name) == 0) && (hdd_ptr->bus != HDD_BUS_SCSI_REMOVABLE)) { + /* Do we have a file name? */ + if (wcslen(hd_file_name) == 0) { +#ifdef USE_REMOVABLE_DISK + /* No, this is OK with removables. */ + if (hdd_ptr->bus == HDD_BUS_SCSI_REMOVABLE)) { + /* Mark disk added but return empty. */ + hdd_ptr->tracks = 0; + hdd_ptr->spt = hdd_ptr->hpc = 0; + memset(hdd_ptr->fn, 0, sizeof(hdd_ptr->fn)); + goto hd_add_ok_common; + } +#endif + /* Not allowed, disable disk. */ hdd_ptr->bus = HDD_BUS_DISABLED; - settings_msgbox(MBX_ERROR, (wchar_t *)IDS_INV_NAME); + settings_msgbox(MBX_ERROR, + (wchar_t *)IDS_INV_NAME); return TRUE; - } else if ((wcslen(hd_file_name) == 0) && (hdd_ptr->bus == HDD_BUS_SCSI_REMOVABLE)) { - /* Mark hard disk added but return empty - it will signify the disk was ejected. */ - hdd_ptr->tracks = 0; - hdd_ptr->spt = hdd_ptr->hpc = 0; - memset(hdd_ptr->fn, 0, sizeof(hdd_ptr->fn)); - - goto hd_add_ok_common; } get_edit_box_contents(hdlg, IDC_EDIT_HD_SPT, &i); @@ -968,10 +969,12 @@ disk_add_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) tracks = hdd_ptr->tracks; if (existing & 2) { +#ifdef USE_REMOVABLE_DISK if (hdd_ptr->bus == HDD_BUS_SCSI_REMOVABLE) { memset(hdd_ptr->prev_fn, 0, sizeof(hdd_ptr->prev_fn)); wcscpy(hdd_ptr->prev_fn, hdd_ptr->fn); } +#endif } else { switch(hdd_ptr->bus) { case HDD_BUS_ST506: @@ -984,19 +987,20 @@ disk_add_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) hdd_ptr->id.esdi_channel = SendMessage(h, CB_GETCURSEL, 0, 0) & 0xff; break; - case HDD_BUS_IDE_PIO_ONLY: - case HDD_BUS_IDE_PIO_AND_DMA: + case HDD_BUS_IDE: h = GetDlgItem(hdlg, IDC_COMBO_HD_CHANNEL_IDE); hdd_ptr->id.ide_channel = SendMessage(h, CB_GETCURSEL, 0, 0) & 0xff; break; case HDD_BUS_SCSI: - case HDD_BUS_SCSI_REMOVABLE: h = GetDlgItem(hdlg, IDC_COMBO_HD_ID); hdd_ptr->id.scsi.id = SendMessage(h, CB_GETCURSEL, 0, 0) & 0xff; h = GetDlgItem(hdlg, IDC_COMBO_HD_LUN); hdd_ptr->id.scsi.lun = SendMessage(h, CB_GETCURSEL, 0, 0) & 0xff; break; + + case HDD_BUS_USB: + break; } } @@ -1082,7 +1086,7 @@ disk_add_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) } if (r) { - big_buf = (char *) malloc(1048576); + big_buf = (char *)mem_alloc(1048576); memset(big_buf, 0, 1048576); for (i = 0; i < r; i++) { fwrite(big_buf, 1, 1048576, f); @@ -1095,7 +1099,9 @@ disk_add_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) settings_msgbox(MBX_INFO, (wchar_t *)IDS_3537); } +#ifdef USE_REMOVABLE_DISK hd_add_ok_common: +#endif hard_disk_added = 1; EndDialog(hdlg, 0); return TRUE; @@ -1224,15 +1230,15 @@ hdd_add_file_open_error: get_edit_box_contents(hdlg, IDC_EDIT_HD_CYL, &temp); if (temp != tracks) { tracks = temp; - size = (tracks * hpc * spt) << 9; + size = ((uint64_t) tracks * (uint64_t) hpc * (uint64_t) spt) << 9LL; set_edit_box_contents(hdlg, IDC_EDIT_HD_SIZE, size >> 20); disk_recalc_selection(hdlg); } if (tracks > max_tracks) { tracks = max_tracks; - size = (tracks * hpc * spt) << 9; - set_edit_box_contents(hdlg, IDC_EDIT_HD_CYL, tracks); + size = ((uint64_t) tracks * (uint64_t) hpc * (uint64_t) spt) << 9LL; + set_edit_box_contents(hdlg, IDC_EDIT_HD_CYL, (uint32_t) tracks); set_edit_box_contents(hdlg, IDC_EDIT_HD_SIZE, (size >> 20)); disk_recalc_selection(hdlg); } @@ -1246,17 +1252,17 @@ hdd_add_file_open_error: no_update = 1; get_edit_box_contents(hdlg, IDC_EDIT_HD_HPC, &temp); - if (temp != hpc) { + if (hpc != temp) { hpc = temp; - size = (tracks * hpc * spt) << 9; + size = ((uint64_t)tracks * (uint64_t)hpc * (uint64_t)spt) << 9LL; set_edit_box_contents(hdlg, IDC_EDIT_HD_SIZE, size >> 20); disk_recalc_selection(hdlg); } if (hpc > max_hpc) { hpc = max_hpc; - size = (tracks * hpc * spt) << 9; - set_edit_box_contents(hdlg, IDC_EDIT_HD_HPC, hpc); + size = ((uint64_t)tracks * (uint64_t)hpc * (uint64_t)spt) << 9LL; + set_edit_box_contents(hdlg, IDC_EDIT_HD_HPC, (uint32_t) hpc); set_edit_box_contents(hdlg, IDC_EDIT_HD_SIZE, (size >> 20)); disk_recalc_selection(hdlg); } @@ -1270,16 +1276,16 @@ hdd_add_file_open_error: no_update = 1; get_edit_box_contents(hdlg, IDC_EDIT_HD_SPT, &temp); - if (temp != spt) { + if (spt != temp) { spt = temp; - size = (tracks * hpc * spt) << 9; + size = ((uint64_t)tracks * (uint64_t)hpc * (uint64_t)spt) << 9LL; set_edit_box_contents(hdlg, IDC_EDIT_HD_SIZE, size >> 20); disk_recalc_selection(hdlg); } if (spt > max_spt) { spt = max_spt; - size = (tracks * hpc * spt) << 9; + size = ((uint64_t)tracks * (uint64_t)hpc * (uint64_t)spt) << 9LL; set_edit_box_contents(hdlg, IDC_EDIT_HD_SPT, spt); set_edit_box_contents(hdlg, IDC_EDIT_HD_SIZE, (size >> 20)); disk_recalc_selection(hdlg); @@ -1358,7 +1364,7 @@ hdd_add_file_open_error: if (tracks > max_tracks) { tracks = max_tracks; - size = (tracks * hpc * spt) << 9; + size = ((uint64_t)tracks * (uint64_t)hpc * (uint64_t)spt) << 9LL; set_edit_box_contents(hdlg, IDC_EDIT_HD_CYL, tracks); set_edit_box_contents(hdlg, IDC_EDIT_HD_SIZE, (size >> 20)); disk_recalc_selection(hdlg); @@ -1397,13 +1403,13 @@ hdd_add_file_open_error: max_tracks = 1023; break; - case HDD_BUS_IDE_PIO_ONLY: - case HDD_BUS_IDE_PIO_AND_DMA: + case HDD_BUS_IDE: max_spt = 63; max_hpc = 255; max_tracks = 266305; break; +#ifdef USE_REMOVABLE_DISK case HDD_BUS_SCSI_REMOVABLE: if (spt == 0) { spt = 63; @@ -1424,41 +1430,51 @@ hdd_add_file_open_error: set_edit_box_contents(hdlg, IDC_EDIT_HD_SIZE, (size >> 20)); } /*FALLTHROUGH*/ +#endif case HDD_BUS_SCSI: max_spt = 99; max_hpc = 255; max_tracks = 266305; break; + + case HDD_BUS_USB: + break; } - if ((hdd_ptr->bus == HDD_BUS_SCSI_REMOVABLE) && !chs_enabled) { - h = GetDlgItem(hdlg, IDC_EDIT_HD_SPT); - EnableWindow(h, TRUE); - h = GetDlgItem(hdlg, IDC_EDIT_HD_HPC); - EnableWindow(h, TRUE); - h = GetDlgItem(hdlg, IDC_EDIT_HD_CYL); - EnableWindow(h, TRUE); - h = GetDlgItem(hdlg, IDC_EDIT_HD_SIZE); - EnableWindow(h, TRUE); - h = GetDlgItem(hdlg, IDC_COMBO_HD_TYPE); - EnableWindow(h, TRUE); - } else if ((hdd_ptr->bus != HDD_BUS_SCSI_REMOVABLE) && !chs_enabled) { - h = GetDlgItem(hdlg, IDC_EDIT_HD_SPT); - EnableWindow(h, FALSE); - h = GetDlgItem(hdlg, IDC_EDIT_HD_HPC); - EnableWindow(h, FALSE); - h = GetDlgItem(hdlg, IDC_EDIT_HD_CYL); - EnableWindow(h, FALSE); - h = GetDlgItem(hdlg, IDC_EDIT_HD_SIZE); - EnableWindow(h, FALSE); - h = GetDlgItem(hdlg, IDC_COMBO_HD_TYPE); - EnableWindow(h, FALSE); + if (! chs_enabled) { +#ifdef USE_REMOVABLE_DISK + if (hdd_ptr->bus == HDD_BUS_SCSI_REMOVABLE) { + h = GetDlgItem(hdlg, IDC_EDIT_HD_SPT); + EnableWindow(h, TRUE); + h = GetDlgItem(hdlg, IDC_EDIT_HD_HPC); + EnableWindow(h, TRUE); + h = GetDlgItem(hdlg, IDC_EDIT_HD_CYL); + EnableWindow(h, TRUE); + h = GetDlgItem(hdlg, IDC_EDIT_HD_SIZE); + EnableWindow(h, TRUE); + h = GetDlgItem(hdlg, IDC_COMBO_HD_TYPE); + EnableWindow(h, TRUE); + } else { +#endif + h = GetDlgItem(hdlg, IDC_EDIT_HD_SPT); + EnableWindow(h, FALSE); + h = GetDlgItem(hdlg, IDC_EDIT_HD_HPC); + EnableWindow(h, FALSE); + h = GetDlgItem(hdlg, IDC_EDIT_HD_CYL); + EnableWindow(h, FALSE); + h = GetDlgItem(hdlg, IDC_EDIT_HD_SIZE); + EnableWindow(h, FALSE); + h = GetDlgItem(hdlg, IDC_COMBO_HD_TYPE); + EnableWindow(h, FALSE); +#ifdef USE_REMOVABLE_DISK + } +#endif } if (spt > max_spt) { spt = max_spt; - size = (tracks * hpc * spt) << 9; + size = ((uint64_t)tracks * (uint64_t)hpc * (uint64_t)spt) << 9LL; set_edit_box_contents(hdlg, IDC_EDIT_HD_SPT, spt); set_edit_box_contents(hdlg, IDC_EDIT_HD_SIZE, (size >> 20)); disk_recalc_selection(hdlg); @@ -1466,7 +1482,7 @@ hdd_add_file_open_error: if (hpc > max_hpc) { hpc = max_hpc; - size = (tracks * hpc * spt) << 9; + size = ((uint64_t)tracks * (uint64_t)hpc * (uint64_t)spt) << 9LL; set_edit_box_contents(hdlg, IDC_EDIT_HD_HPC, hpc); set_edit_box_contents(hdlg, IDC_EDIT_HD_SIZE, (size >> 20)); disk_recalc_selection(hdlg); @@ -1474,7 +1490,7 @@ hdd_add_file_open_error: if (tracks > max_tracks) { tracks = max_tracks; - size = (tracks * hpc * spt) << 9; + size = ((uint64_t)tracks * (uint64_t)hpc * (uint64_t)spt) << 9LL; set_edit_box_contents(hdlg, IDC_EDIT_HD_CYL, tracks); set_edit_box_contents(hdlg, IDC_EDIT_HD_SIZE, (size >> 20)); disk_recalc_selection(hdlg); @@ -1508,20 +1524,18 @@ disk_track(uint8_t id) { switch(temp_hdd[id].bus) { case HDD_BUS_ST506: - st506_tracking |= (1ULL << (temp_hdd[id].id.st506_channel << 3)); - break; + st506_tracking |= (1ULL << (temp_hdd[id].id.st506_channel << 3)); + break; case HDD_BUS_ESDI: - esdi_tracking |= (1ULL << (temp_hdd[id].id.esdi_channel << 3)); - break; + esdi_tracking |= (1ULL << (temp_hdd[id].id.esdi_channel << 3)); + break; - case HDD_BUS_IDE_PIO_ONLY: - case HDD_BUS_IDE_PIO_AND_DMA: - ide_tracking |= (1ULL << (temp_hdd[id].id.ide_channel << 3)); + case HDD_BUS_IDE: + ide_tracking |= (1ULL << (temp_hdd[id].id.ide_channel << 3)); break; case HDD_BUS_SCSI: - case HDD_BUS_SCSI_REMOVABLE: scsi_tracking[temp_hdd[id].id.scsi.id] |= (1ULL << (temp_hdd[id].id.scsi.lun << 3)); break; } @@ -1540,13 +1554,11 @@ disk_untrack(uint8_t id) esdi_tracking &= ~(1 << (temp_hdd[id].id.esdi_channel << 3)); break; - case HDD_BUS_IDE_PIO_ONLY: - case HDD_BUS_IDE_PIO_AND_DMA: + case HDD_BUS_IDE: ide_tracking &= ~(1 << (temp_hdd[id].id.ide_channel << 3)); break; case HDD_BUS_SCSI: - case HDD_BUS_SCSI_REMOVABLE: scsi_tracking[temp_hdd[id].id.scsi.id] &= ~(1 << (temp_hdd[id].id.scsi.lun << 3)); break; } @@ -1570,7 +1582,7 @@ static BOOL CALLBACK #endif disk_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) { - HWND h = INVALID_HANDLE_VALUE; + HWND h; int old_sel = 0; int b = 0; int assign = 0; @@ -1614,6 +1626,7 @@ disk_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) if ((((LPNMHDR)lParam)->code == LVN_ITEMCHANGED) && (((LPNMHDR)lParam)->idFrom == IDC_LIST_HARD_DISKS)) { old_sel = hdlv_current_sel; + h = GetDlgItem(hdlg, IDC_LIST_HARD_DISKS); hdlv_current_sel = disk_get_selected(hdlg); if (hdlv_current_sel == old_sel) return FALSE; @@ -1647,9 +1660,7 @@ disk_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) goto hd_bus_skip; disk_untrack(hdlv_current_sel); assign = (temp_hdd[hdlv_current_sel].bus == b) ? 0 : 1; - if ((b == HDD_BUS_IDE_PIO_ONLY) && (temp_hdd[hdlv_current_sel].bus == HDD_BUS_IDE_PIO_AND_DMA)) - assign = 0; - else if ((b == HDD_BUS_IDE_PIO_AND_DMA) && (temp_hdd[hdlv_current_sel].bus == HDD_BUS_IDE_PIO_ONLY)) + if ((b == HDD_BUS_IDE) && (temp_hdd[hdlv_current_sel].bus == HDD_BUS_IDE)) assign = 0; temp_hdd[hdlv_current_sel].bus = b; disk_recalc_location_controls(hdlg, 0, assign); @@ -1746,8 +1757,19 @@ hd_bus_skip: case IDC_BUTTON_HDD_REMOVE: wcscpy(temp_hdd[hdlv_current_sel].fn, L""); disk_untrack(hdlv_current_sel); - temp_hdd[hdlv_current_sel].bus = HDD_BUS_DISABLED; /* Only set the bus to zero, the list normalize code below will take care of turning this entire entry to a complete zero. */ - disk_normalize_list(); /* Normalize the hard disks so that non-disabled hard disks start from index 0, and so they are contiguous. */ + + /* + * Only set the bus to zero, the list normalize + * code below will take care of turning this + * entire entry to a complete zero. + */ + temp_hdd[hdlv_current_sel].bus = HDD_BUS_DISABLED; + /* + * Normalize the hard disks so that all + * non-disabled hard disks start from index 0, + * and so they are contiguous. + */ + disk_normalize_list(); ignore_change = 1; h = GetDlgItem(hdlg, IDC_LIST_HARD_DISKS); disk_recalc_list(h); diff --git a/src/win/win_settings_floppy.h b/src/win/win_settings_floppy.h index 04cc339..1a62c72 100644 --- a/src/win/win_settings_floppy.h +++ b/src/win/win_settings_floppy.h @@ -8,7 +8,7 @@ * * Implementation of the Settings dialog. * - * Version: @(#)win_settings_floppy.h 1.0.6 2018/05/24 + * Version: @(#)win_settings_floppy.h 1.0.7 2018/09/19 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -50,7 +50,7 @@ static int fdlv_current_sel; static void floppy_image_list_init(HWND hwndList) { - HICON hiconItem; + HICON hIconItem; HIMAGELIST hSmall; int i; @@ -59,9 +59,9 @@ floppy_image_list_init(HWND hwndList) ILC_MASK | ILC_COLOR32, 1, 1); for (i = 0; i < 14; i++) { - hiconItem = LoadIcon(hInstance, (LPCWSTR)plat_fdd_icon(i)); - ImageList_AddIcon(hSmall, hiconItem); - DestroyIcon(hiconItem); + hIconItem = LoadIcon(hInstance, (LPCWSTR)ui_fdd_icon(i)); + ImageList_AddIcon(hSmall, hIconItem); + DestroyIcon(hIconItem); } ListView_SetImageList(hwndList, hSmall, LVSIL_SMALL); @@ -210,8 +210,8 @@ static BOOL CALLBACK floppy_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) { WCHAR temp[128]; - HWND h = INVALID_HANDLE_VALUE; - int i = 0; + HWND h; + int i; int old_sel = 0; switch (message) { @@ -251,6 +251,7 @@ floppy_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) if ((((LPNMHDR)lParam)->code == LVN_ITEMCHANGED) && (((LPNMHDR)lParam)->idFrom == IDC_LIST_FLOPPY_DRIVES)) { old_sel = fdlv_current_sel; + h = GetDlgItem(hdlg, IDC_LIST_FLOPPY_DRIVES); fdlv_current_sel = floppy_get_selected(hdlg); if (fdlv_current_sel == old_sel) { return FALSE; diff --git a/src/win/win_settings_input.h b/src/win/win_settings_input.h index 7face04..7bb9128 100644 --- a/src/win/win_settings_input.h +++ b/src/win/win_settings_input.h @@ -8,7 +8,7 @@ * * Implementation of the Settings dialog. * - * Version: @(#)win_settings_input.h 1.0.7 2018/05/02 + * Version: @(#)win_settings_input.h 1.0.8 2018/09/29 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -108,13 +108,13 @@ input_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) SendMessage(h, CB_SETCURSEL, temp_joystick, 0); EnableWindow(h, (temp_game)?TRUE:FALSE); - h = GetDlgItem(hdlg, IDC_JOY1); + h = GetDlgItem(hdlg, IDC_CONFIGURE_JOY1); EnableWindow(h, (temp_game && (gamedev_get_max_joysticks(temp_joystick) >= 1)) ? TRUE : FALSE); - h = GetDlgItem(hdlg, IDC_JOY2); + h = GetDlgItem(hdlg, IDC_CONFIGURE_JOY2); EnableWindow(h, (temp_game && (gamedev_get_max_joysticks(temp_joystick) >= 2)) ? TRUE : FALSE); - h = GetDlgItem(hdlg, IDC_JOY3); + h = GetDlgItem(hdlg, IDC_CONFIGURE_JOY3); EnableWindow(h, (temp_game && (gamedev_get_max_joysticks(temp_joystick) >= 3)) ? TRUE : FALSE); - h = GetDlgItem(hdlg, IDC_JOY4); + h = GetDlgItem(hdlg, IDC_CONFIGURE_JOY4); EnableWindow(h, (temp_game && (gamedev_get_max_joysticks(temp_joystick) >= 4)) ? TRUE : FALSE); return TRUE; @@ -135,42 +135,42 @@ input_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) case IDC_CONFIGURE_MOUSE: h = GetDlgItem(hdlg, IDC_COMBO_MOUSE); temp_mouse = list_to_mouse[SendMessage(h, CB_GETCURSEL, 0, 0)]; - temp_deviceconfig |= dlg_devconf(hdlg, (void *)mouse_get_device(temp_mouse)); + temp_deviceconfig |= dlg_devconf(hdlg, mouse_get_device(temp_mouse)); break; case IDC_COMBO_JOYSTICK: h = GetDlgItem(hdlg, IDC_COMBO_JOYSTICK); temp_joystick = SendMessage(h, CB_GETCURSEL, 0, 0); - h = GetDlgItem(hdlg, IDC_JOY1); + h = GetDlgItem(hdlg, IDC_CONFIGURE_JOY1); EnableWindow(h, (gamedev_get_max_joysticks(temp_joystick) >= 1) ? TRUE : FALSE); - h = GetDlgItem(hdlg, IDC_JOY2); + h = GetDlgItem(hdlg, IDC_CONFIGURE_JOY2); EnableWindow(h, (gamedev_get_max_joysticks(temp_joystick) >= 2) ? TRUE : FALSE); - h = GetDlgItem(hdlg, IDC_JOY3); + h = GetDlgItem(hdlg, IDC_CONFIGURE_JOY3); EnableWindow(h, (gamedev_get_max_joysticks(temp_joystick) >= 3) ? TRUE : FALSE); - h = GetDlgItem(hdlg, IDC_JOY4); + h = GetDlgItem(hdlg, IDC_CONFIGURE_JOY4); EnableWindow(h, (gamedev_get_max_joysticks(temp_joystick) >= 4) ? TRUE : FALSE); break; - case IDC_JOY1: + case IDC_CONFIGURE_JOY1: h = GetDlgItem(hdlg, IDC_COMBO_JOYSTICK); temp_joystick = SendMessage(h, CB_GETCURSEL, 0, 0); temp_deviceconfig |= dlg_jsconf(hdlg, 0, temp_joystick); break; - case IDC_JOY2: + case IDC_CONFIGURE_JOY2: h = GetDlgItem(hdlg, IDC_COMBO_JOYSTICK); temp_joystick = SendMessage(h, CB_GETCURSEL, 0, 0); temp_deviceconfig |= dlg_jsconf(hdlg, 1, temp_joystick); break; - case IDC_JOY3: + case IDC_CONFIGURE_JOY3: h = GetDlgItem(hdlg, IDC_COMBO_JOYSTICK); temp_joystick = SendMessage(h, CB_GETCURSEL, 0, 0); temp_deviceconfig |= dlg_jsconf(hdlg, 2, temp_joystick); break; - case IDC_JOY4: + case IDC_CONFIGURE_JOY4: h = GetDlgItem(hdlg, IDC_COMBO_JOYSTICK); temp_joystick = SendMessage(h, CB_GETCURSEL, 0, 0); temp_deviceconfig |= dlg_jsconf(hdlg, 3, temp_joystick); @@ -178,7 +178,7 @@ input_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) } return FALSE; - case WM_SAVESETTINGS: + case WM_SAVE_CFG: h = GetDlgItem(hdlg, IDC_COMBO_MOUSE); temp_mouse = list_to_mouse[SendMessage(h, CB_GETCURSEL, 0, 0)]; diff --git a/src/win/win_settings_machine.h b/src/win/win_settings_machine.h index 1becefc..b1571fa 100644 --- a/src/win/win_settings_machine.h +++ b/src/win/win_settings_machine.h @@ -8,7 +8,7 @@ * * Implementation of the Settings dialog. * - * Version: @(#)win_settings_machine.h 1.0.9 2018/09/28 + * Version: @(#)win_settings_machine.h 1.0.9 2018/09/29 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -42,9 +42,9 @@ * * ************************************************************************/ -static int romstolist[ROM_MAX], - romstomachine[ROM_MAX], - machinetolist[ROM_MAX], listtomachine[ROM_MAX]; +static wchar_t *mach_names[256]; +static int mach_to_list[256], + list_to_mach[256]; static void @@ -55,16 +55,14 @@ machine_recalc_cpu(HWND hdlg) int cpu_flags; #endif int cpu_type; - int rs = 0; - rs = machine_getromset_ex(temp_machine); - cpu_flags = machines[romstomachine[rs]].cpu[temp_cpu_m].cpus[temp_cpu].cpu_flags; - cpu_type = machines[romstomachine[rs]].cpu[temp_cpu_m].cpus[temp_cpu].cpu_type; + cpu_type = machines[temp_machine].cpu[temp_cpu_m].cpus[temp_cpu].cpu_type; + cpu_flags = machines[temp_machine].cpu[temp_cpu_m].cpus[temp_cpu].cpu_flags; h = GetDlgItem(hdlg, IDC_COMBO_WS); if ((cpu_type >= CPU_286) && (cpu_type <= CPU_386DX)) EnableWindow(h, TRUE); - else + else EnableWindow(h, FALSE); #ifdef USE_DYNAREC @@ -79,12 +77,17 @@ machine_recalc_cpu(HWND hdlg) * a warning so they know. */ if (cpu_flags & CPU_REQUIRES_DYNAREC) { -#ifdef RELEASE_BUILD +#if 0 if (! temp_dynarec) { //FIXME: make this a messagebox with a user warning instead! --FvK fatal("Attempting to select a CPU that requires the recompiler and does not support it at the same time\n"); } #endif + +#ifdef RELEASE_BUILD + /* Since it is required, lock the checkbox. */ + EnableWindow(h, FALSE); +#endif } else { /* Supported but not required, unlock the checkbox. */ EnableWindow(h, TRUE); @@ -100,7 +103,6 @@ machine_recalc_cpu(HWND hdlg) #endif h = GetDlgItem(hdlg, IDC_CHECK_FPU); - cpu_type = machines[romstomachine[rs]].cpu[temp_cpu_m].cpus[temp_cpu].cpu_type; if ((cpu_type < CPU_i486DX) && (cpu_type >= CPU_286)) { EnableWindow(h, TRUE); } else if (cpu_type < CPU_286) { @@ -122,15 +124,12 @@ machine_recalc_cpu_m(HWND hdlg) const char *stransi; HWND h; int c = 0; - int rs = 0; - - rs = machine_getromset_ex(temp_machine); h = GetDlgItem(hdlg, IDC_COMBO_CPU); SendMessage(h, CB_RESETCONTENT, 0, 0); c = 0; - while (machines[romstomachine[rs]].cpu[temp_cpu_m].cpus[c].cpu_type != -1) { - stransi = machines[romstomachine[rs]].cpu[temp_cpu_m].cpus[c].name; + while (machines[temp_machine].cpu[temp_cpu_m].cpus[c].cpu_type != -1) { + stransi = machines[temp_machine].cpu[temp_cpu_m].cpus[c].name; mbstowcs(temp, stransi, sizeof_w(temp)); SendMessage(h, CB_ADDSTRING, 0, (LPARAM)temp); c++; @@ -151,25 +150,22 @@ machine_recalc_machine(HWND hdlg) WCHAR temp[128]; const char *stransi; const device_t *dev; - HWND h; - int c = 0; - int rs = 0; UDACCEL accel; - - rs = machine_getromset_ex(temp_machine); + HWND h; + int c; h = GetDlgItem(hdlg, IDC_CONFIGURE_MACHINE); dev = machine_getdevice(temp_machine); if (dev != NULL && dev->config != NULL) EnableWindow(h, TRUE); - else + else EnableWindow(h, FALSE); h = GetDlgItem(hdlg, IDC_COMBO_CPU_TYPE); SendMessage(h, CB_RESETCONTENT, 0, 0); c = 0; - while (machines[romstomachine[rs]].cpu[c].cpus != NULL && c < 4) { - stransi = machines[romstomachine[rs]].cpu[c].name; + while (machines[temp_machine].cpu[c].cpus != NULL && c < 4) { + stransi = machines[temp_machine].cpu[c].name; mbstowcs(temp, stransi, sizeof_w(temp)); SendMessage(h, CB_ADDSTRING, 0, (LPARAM)temp); c++; @@ -181,25 +177,25 @@ machine_recalc_machine(HWND hdlg) SendMessage(h, CB_SETCURSEL, temp_cpu_m, 0); if (c == 1) EnableWindow(h, FALSE); - else + else EnableWindow(h, TRUE); machine_recalc_cpu_m(hdlg); h = GetDlgItem(hdlg, IDC_MEMSPIN); - SendMessage(h, UDM_SETRANGE, 0, (machines[romstomachine[rs]].min_ram << 16) | machines[romstomachine[rs]].max_ram); + SendMessage(h, UDM_SETRANGE, 0, (machines[temp_machine].min_ram << 16) | machines[temp_machine].max_ram); accel.nSec = 0; - accel.nInc = machines[romstomachine[rs]].ram_granularity; + accel.nInc = machines[temp_machine].ram_granularity; SendMessage(h, UDM_SETACCEL, 1, (LPARAM)&accel); - if (!(machines[romstomachine[rs]].flags & MACHINE_AT) || (machines[romstomachine[rs]].ram_granularity >= 128)) { + if (!(machines[temp_machine].flags & MACHINE_AT) || (machines[temp_machine].ram_granularity >= 128)) { SendMessage(h, UDM_SETPOS, 0, temp_mem_size); h = GetDlgItem(hdlg, IDC_TEXT_MB); - SendMessage(h, WM_SETTEXT, 0, (LPARAM)get_string(IDS_3334)); + SendMessage(h, WM_SETTEXT, 0, win_string(IDS_3334)); } else { SendMessage(h, UDM_SETPOS, 0, temp_mem_size / 1024); h = GetDlgItem(hdlg, IDC_TEXT_MB); - SendMessage(h, WM_SETTEXT, 0, (LPARAM)get_string(IDS_3330)); + SendMessage(h, WM_SETTEXT, 0, win_string(IDS_3330)); } } @@ -213,40 +209,38 @@ machine_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) { WCHAR temp[128]; char tempA[128]; - const char *stransi; + wchar_t *str; HWND h; - int c; - int d = 0; + int c, d; switch (message) { case WM_INITDIALOG: h = GetDlgItem(hdlg, IDC_COMBO_MACHINE); - for (c = 0; c < ROM_MAX; c++) - romstolist[c] = 0; - c = d = 0; - while (machines[c].id != -1) { - if (romspresent[machines[c].id]) { - stransi = machines[c].name; - mbstowcs(temp, stransi, sizeof_w(temp)); - SendMessage(h, CB_ADDSTRING, 0, (LPARAM)temp); - machinetolist[c] = d; - listtomachine[d] = c; - romstolist[machines[c].id] = d; - romstomachine[machines[c].id] = c; - d++; - } - c++; + + /* + * Populate the Machines combo. + * + * The necessary data was already built + * by the calling code, so we only have + * to add it to the combo here. + */ + c = 0; + while(1) { + str = mach_names[c++]; + if (str == NULL) + break; + + SendMessage(h, CB_ADDSTRING, 0, (LPARAM)str); } - SendMessage(h, CB_SETCURSEL, machinetolist[temp_machine], 0); + + SendMessage(h, CB_SETCURSEL, mach_to_list[temp_machine], 0); h = GetDlgItem(hdlg, IDC_COMBO_WS); - SendMessage(h, CB_ADDSTRING, 0, (LPARAM)get_string(IDS_3335)); - + SendMessage(h, CB_ADDSTRING, 0, win_string(IDS_3335)); for (c = 0; c < 8; c++) { swprintf(temp, sizeof_w(temp), L"%i", c); SendMessage(h, CB_ADDSTRING, 0, (LPARAM)temp); } - SendMessage(h, CB_SETCURSEL, temp_wait_states, 0); #ifdef USE_DYNAREC @@ -257,8 +251,14 @@ machine_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) h = GetDlgItem(hdlg, IDC_MEMSPIN); SendMessage(h, UDM_SETBUDDY, (WPARAM)GetDlgItem(hdlg, IDC_MEMTEXT), 0); - h = GetDlgItem(hdlg, IDC_CHECK_SYNC); - SendMessage(h, BM_SETCHECK, temp_sync, 0); + h = GetDlgItem(hdlg, IDC_COMBO_SYNC); + SendMessage(h, CB_ADDSTRING, + TIME_SYNC_DISABLED, win_string(IDS_DISABLED)); + SendMessage(h, CB_ADDSTRING, + TIME_SYNC_ENABLED, win_string(IDS_ENABLED)); + SendMessage(h, CB_ADDSTRING, + TIME_SYNC_ENABLED_UTC, win_string(IDS_3336)); + SendMessage(h, CB_SETCURSEL, temp_sync, 0); machine_recalc_machine(hdlg); @@ -269,8 +269,8 @@ machine_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) case IDC_COMBO_MACHINE: if (HIWORD(wParam) == CBN_SELCHANGE) { h = GetDlgItem(hdlg, IDC_COMBO_MACHINE); - temp_machine = listtomachine[SendMessage(h, CB_GETCURSEL, 0, 0)]; - + d = SendMessage(h, CB_GETCURSEL, 0, 0); + temp_machine = list_to_mach[d]; machine_recalc_machine(hdlg); } break; @@ -296,23 +296,27 @@ machine_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) case IDC_CONFIGURE_MACHINE: h = GetDlgItem(hdlg, IDC_COMBO_MACHINE); - temp_machine = listtomachine[SendMessage(h, CB_GETCURSEL, 0, 0)]; + d = SendMessage(h, CB_GETCURSEL, 0, 0); + temp_machine = list_to_mach[d]; + temp_deviceconfig |= dlg_devconf(hdlg, machine_getdevice(temp_machine)); + break; - temp_deviceconfig |= dlg_devconf(hdlg, (void *)machine_getdevice(temp_machine)); + case IDC_COMBO_SYNC: + if (HIWORD(wParam) == CBN_SELCHANGE) { + h = GetDlgItem(hdlg, IDC_COMBO_SYNC); + temp_sync = SendMessage(h, CB_GETCURSEL, 0, 0); + } break; } return FALSE; - case WM_SAVESETTINGS: + case WM_SAVE_CFG: #ifdef USE_DYNAREC h = GetDlgItem(hdlg, IDC_CHECK_DYNAREC); temp_dynarec = SendMessage(h, BM_GETCHECK, 0, 0); #endif - h = GetDlgItem(hdlg, IDC_CHECK_SYNC); - temp_sync = SendMessage(h, BM_GETCHECK, 0, 0); - h = GetDlgItem(hdlg, IDC_CHECK_FPU); temp_fpu = SendMessage(h, BM_GETCHECK, 0, 0); @@ -324,9 +328,9 @@ machine_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) wcstombs(tempA, temp, sizeof(tempA)); sscanf(tempA, "%i", &temp_mem_size); temp_mem_size &= ~(machines[temp_machine].ram_granularity - 1); - if (temp_mem_size < machines[temp_machine].min_ram) + if (temp_mem_size < (int)machines[temp_machine].min_ram) temp_mem_size = machines[temp_machine].min_ram; - else if (temp_mem_size > machines[temp_machine].max_ram) + else if (temp_mem_size > (int)machines[temp_machine].max_ram) temp_mem_size = machines[temp_machine].max_ram; if ((machines[temp_machine].flags & MACHINE_AT) && (machines[temp_machine].ram_granularity < 128)) temp_mem_size *= 1024; diff --git a/src/win/win_settings_network.h b/src/win/win_settings_network.h index 0e0fb8a..3a94713 100644 --- a/src/win/win_settings_network.h +++ b/src/win/win_settings_network.h @@ -8,7 +8,7 @@ * * Implementation of the Settings dialog. * - * Version: @(#)win_settings_network.h 1.0.5 2018/05/02 + * Version: @(#)win_settings_network.h 1.0.6 2018/09/29 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -61,7 +61,7 @@ network_recalc_combos(HWND hdlg) else EnableWindow(h, FALSE); - h = GetDlgItem(hdlg, IDC_COMBO_NET); + h = GetDlgItem(hdlg, IDC_COMBO_NET_CARD); if (temp_net_type == NET_TYPE_SLIRP) EnableWindow(h, TRUE); else if ((temp_net_type == NET_TYPE_PCAP) && (network_dev_to_id(temp_host_dev) > 0)) @@ -69,7 +69,7 @@ network_recalc_combos(HWND hdlg) else EnableWindow(h, FALSE); - h = GetDlgItem(hdlg, IDC_CONFIGURE_NET); + h = GetDlgItem(hdlg, IDC_CONFIGURE_NET_CARD); if (network_card_has_config(temp_net_card) && (temp_net_type == NET_TYPE_SLIRP)) { EnableWindow(h, TRUE); } else if (network_card_has_config(temp_net_card) && @@ -91,8 +91,10 @@ static BOOL CALLBACK #endif network_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) { + char tempA[128]; WCHAR temp[128]; const char *stransi; + const device_t *dev; HWND h; int c, d; @@ -119,24 +121,32 @@ network_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) SendMessage(h, CB_SETCURSEL, network_dev_to_id(temp_host_dev), 0); /*NIC config*/ - h = GetDlgItem(hdlg, IDC_COMBO_NET); + h = GetDlgItem(hdlg, IDC_COMBO_NET_CARD); c = d = 0; while (1) { - stransi = network_card_getname(c); + stransi = network_card_get_internal_name(c); if (stransi == NULL) break; - nic_to_list[c] = d; - - if (network_card_available(c) && device_is_valid(network_card_getdevice(c), machines[temp_machine].flags)) { - mbstowcs(temp, stransi, sizeof_w(temp)); - SendMessage(h, CB_ADDSTRING, 0, (LPARAM)temp); - - list_to_nic[d] = c; - d++; + dev = network_card_getdevice(c); + if (dev == NULL) { + /* Translate "None". */ + wcscpy(temp, get_string(IDS_NONE)); + } else if (network_card_available(c) && + device_is_valid(dev, machines[temp_machine].flags)) { + sprintf(tempA, "[%s] %s", + device_get_bus_name(dev), + network_card_getname(c)); + mbstowcs(temp, tempA, sizeof_w(temp)); + } else { + c++; + continue; } - c++; + SendMessage(h, CB_ADDSTRING, 0, (LPARAM)temp); + + nic_to_list[c] = d; + list_to_nic[d++] = c++; } SendMessage(h, CB_SETCURSEL, nic_to_list[temp_net_card], 0); @@ -167,29 +177,29 @@ network_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) network_recalc_combos(hdlg); break; - case IDC_COMBO_NET: + case IDC_COMBO_NET_CARD: if (net_ignore_message) return FALSE; - h = GetDlgItem(hdlg, IDC_COMBO_NET); + h = GetDlgItem(hdlg, IDC_COMBO_NET_CARD); temp_net_card = list_to_nic[SendMessage(h, CB_GETCURSEL, 0, 0)]; network_recalc_combos(hdlg); break; - case IDC_CONFIGURE_NET: + case IDC_CONFIGURE_NET_CARD: if (net_ignore_message) return FALSE; - h = GetDlgItem(hdlg, IDC_COMBO_NET); + h = GetDlgItem(hdlg, IDC_COMBO_NET_CARD); temp_net_card = list_to_nic[SendMessage(h, CB_GETCURSEL, 0, 0)]; - temp_deviceconfig |= dlg_devconf(hdlg, (void *)network_card_getdevice(temp_net_card)); + temp_deviceconfig |= dlg_devconf(hdlg, network_card_getdevice(temp_net_card)); break; } return FALSE; - case WM_SAVESETTINGS: + case WM_SAVE_CFG: h = GetDlgItem(hdlg, IDC_COMBO_NET_TYPE); temp_net_type = SendMessage(h, CB_GETCURSEL, 0, 0); @@ -197,7 +207,7 @@ network_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) memset(temp_host_dev, '\0', sizeof(temp_host_dev)); strcpy(temp_host_dev, network_devs[SendMessage(h, CB_GETCURSEL, 0, 0)].device); - h = GetDlgItem(hdlg, IDC_COMBO_NET); + h = GetDlgItem(hdlg, IDC_COMBO_NET_CARD); temp_net_card = list_to_nic[SendMessage(h, CB_GETCURSEL, 0, 0)]; return FALSE; diff --git a/src/win/win_settings_periph.h b/src/win/win_settings_periph.h index 8fec5a9..54e649b 100644 --- a/src/win/win_settings_periph.h +++ b/src/win/win_settings_periph.h @@ -8,7 +8,7 @@ * * Implementation of the Settings dialog. * - * Version: @(#)win_settings_periph.h 1.0.12 2018/09/03 + * Version: @(#)win_settings_periph.h 1.0.13 2018/09/29 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -45,76 +45,113 @@ static int scsi_to_list[20], list_to_scsi[20]; static const char *hdc_names[16]; -static const int valid_ide_irqs[11] = { 2, 3, 4, 5, 7, 9, 10, 11, 12, 14, 15 }; - - -static int -find_irq_in_array(int irq, int def) -{ - int i; - - for (i = 0; i < 11; i++) { - if (valid_ide_irqs[i] == irq) - return(i + 1); - } - - return(7 + def); -} +/* Populate the HDC combo. */ static void -recalc_hdc_list(HWND hdlg, int m, int use_selected_hdc) +recalc_scsi_list(HWND hdlg) { WCHAR temp[128]; - char old_name[32]; + char tempA[128]; const char *stransi; + const device_t *dev; HWND h; - int valid; int c, d; - h = GetDlgItem(hdlg, IDC_COMBO_HDC); - valid = 0; - - if (use_selected_hdc) { - c = SendMessage(h, CB_GETCURSEL, 0, 0); - - if (c != -1 && hdc_names[c]) - strcpy(old_name, hdc_names[c]); - else - strcpy(old_name, "none"); - } else { - strcpy(old_name, hdc_get_internal_name(temp_hdc_type)); - } - + h = GetDlgItem(hdlg, IDC_COMBO_SCSI); SendMessage(h, CB_RESETCONTENT, 0, 0); + c = d = 0; while (1) { - stransi = hdc_get_name(c); + stransi = scsi_card_get_internal_name(c); if (stransi == NULL) break; - if (c==1 && !(machines[m].flags&MACHINE_HDC)) { - /* Skip "Internal" if machine doesn't have one. */ - c++; - continue; - } - if (!hdc_available(c) || !device_is_valid(hdc_get_device(c), machines[m].flags)) { - c++; - continue; - } - mbstowcs(temp, stransi, sizeof_w(temp)); - SendMessage(h, CB_ADDSTRING, 0, (LPARAM)temp); + dev = scsi_card_getdevice(c); - hdc_names[d] = hdc_get_internal_name(c); - if (! strcmp(old_name, hdc_names[d])) { - SendMessage(h, CB_SETCURSEL, d, 0); - valid = 1; + if (!scsi_card_available(c) || + !device_is_valid(dev, machines[temp_machine].flags)) { + c++; + continue; } + + if (c == 0) { + SendMessage(h, CB_ADDSTRING, 0, win_string(IDS_NONE)); + } else { + stransi = scsi_card_getname(c); + sprintf(tempA, "[%s] %s", + device_get_bus_name(dev), stransi); + mbstowcs(temp, tempA, sizeof_w(temp)); + SendMessage(h, CB_ADDSTRING, 0, (LPARAM)temp); + } + + scsi_to_list[c] = d; + list_to_scsi[d++] = c++; + } + + SendMessage(h, CB_SETCURSEL, scsi_to_list[temp_scsi_card], 0); + EnableWindow(h, d ? TRUE : FALSE); +} + + +/* Populate the HDC combo. */ +static void +recalc_hdc_list(HWND hdlg) +{ + WCHAR temp[128]; + char tempA[128]; + char tempB[128]; + const char *stransi; + const device_t *dev; + HWND h; + int c, d; + + h = GetDlgItem(hdlg, IDC_COMBO_HDC); + SendMessage(h, CB_RESETCONTENT, 0, 0); + + c = d = 0; + while (1) { + stransi = hdc_get_internal_name(c); + if (stransi == NULL) + break; + + dev = hdc_get_device(c); + + if (!hdc_available(c) || + !device_is_valid(dev, machines[temp_machine].flags)) { + c++; + continue; + } + + hdc_names[d] = stransi; + + if (c == 0) { + SendMessage(h, CB_ADDSTRING, 0, win_string(IDS_NONE)); + } else if (c == 1) { + if (! (machines[temp_machine].flags&MACHINE_HDC)) { + /* Skip "Internal" if machine doesn't have one. */ + c++; + continue; + } + SendMessage(h, CB_ADDSTRING, 0, win_string(IDS_INTERNAL)); + } else { + wcstombs(tempB, + hdd_bus_to_ids((dev->local >> 8) & 255), + sizeof(tempB)); + stransi = hdc_get_name(c); + sprintf(tempA, "[%s] %s (%s)", + device_get_bus_name(dev), stransi, tempB); + mbstowcs(temp, tempA, sizeof_w(temp)); + SendMessage(h, CB_ADDSTRING, 0, (LPARAM)temp); + } + c++; d++; } - if (! valid) + if (temp_hdc_type != -1 && temp_hdc_type < d) + SendMessage(h, CB_SETCURSEL, temp_hdc_type, 0); + else SendMessage(h, CB_SETCURSEL, 0, 0); EnableWindow(h, d ? TRUE : FALSE); @@ -136,34 +173,7 @@ peripherals_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) switch (message) { case WM_INITDIALOG: - /*SCSI config*/ - h = GetDlgItem(hdlg, IDC_COMBO_SCSI); - c = d = 0; - while (1) { - stransi = scsi_card_getname(c); - if (stransi == NULL) - break; - - scsi_to_list[c] = d; - if (scsi_card_available(c)) { - dev = scsi_card_getdevice(c); - - if (device_is_valid(dev, machines[temp_machine].flags)) { - if (c == 0) { - SendMessage(h, CB_ADDSTRING, 0, (LPARAM)get_string(IDS_NONE)); - } else { - mbstowcs(temp, stransi, sizeof_w(temp)); - SendMessage(h, CB_ADDSTRING, 0, (LPARAM)temp); - } - list_to_scsi[d] = c; - d++; - } - } - - c++; - } - SendMessage(h, CB_SETCURSEL, scsi_to_list[temp_scsi_card], 0); - EnableWindow(h, d ? TRUE : FALSE); + recalc_scsi_list(hdlg); h = GetDlgItem(hdlg, IDC_CONFIGURE_SCSI); if (scsi_card_has_config(temp_scsi_card)) @@ -171,41 +181,37 @@ peripherals_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) else EnableWindow(h, FALSE); + recalc_hdc_list(hdlg); + h = GetDlgItem(hdlg, IDC_CONFIGURE_HDC); if (hdc_has_config(temp_hdc_type)) EnableWindow(h, TRUE); else EnableWindow(h, FALSE); - recalc_hdc_list(hdlg, temp_machine, 0); + if (machines[temp_machine].flags & MACHINE_AT) { + h = GetDlgItem(hdlg, IDC_CHECK_IDE_TER); + EnableWindow(h, TRUE); + SendMessage(h, BM_SETCHECK, temp_ide_ter, 0); + h = GetDlgItem(hdlg, IDC_CONFIGURE_IDE_TER); + EnableWindow(h, TRUE); - h = GetDlgItem(hdlg, IDC_COMBO_IDE_TER); - SendMessage(h, CB_ADDSTRING, 0, - (LPARAM)get_string(IDS_DISABLED)); - for (c = 0; c < 11; c++) { - swprintf(temp, sizeof_w(temp), - L"IRQ %i", valid_ide_irqs[c]); - SendMessage(h, CB_ADDSTRING, 0, (LPARAM)temp); - } - if (temp_ide_ter) - SendMessage(h, CB_SETCURSEL, - find_irq_in_array(temp_ide_ter_irq, 0), 0); - else - SendMessage(h, CB_SETCURSEL, 0, 0); + h = GetDlgItem(hdlg, IDC_CHECK_IDE_QUA); + EnableWindow(h, TRUE); + SendMessage(h, BM_SETCHECK, temp_ide_qua, 0); + h = GetDlgItem(hdlg, IDC_CONFIGURE_IDE_QUA); + EnableWindow(h, TRUE); + } else { + h = GetDlgItem(hdlg, IDC_CHECK_IDE_TER); + EnableWindow(h, FALSE); + h = GetDlgItem(hdlg, IDC_CONFIGURE_IDE_TER); + EnableWindow(h, FALSE); - h = GetDlgItem(hdlg, IDC_COMBO_IDE_QUA); - SendMessage(h, CB_ADDSTRING, 0, - (LPARAM)get_string(IDS_DISABLED)); - for (c = 0; c < 11; c++) { - swprintf(temp, sizeof_w(temp), - L"IRQ %i", valid_ide_irqs[c]); - SendMessage(h, CB_ADDSTRING, 0, (LPARAM)temp); + h = GetDlgItem(hdlg, IDC_CHECK_IDE_QUA); + EnableWindow(h, FALSE); + h = GetDlgItem(hdlg, IDC_CONFIGURE_IDE_QUA); + EnableWindow(h, FALSE); } - if (temp_ide_qua) - SendMessage(h, CB_SETCURSEL, - find_irq_in_array(temp_ide_qua_irq, 1), 0); - else - SendMessage(h, CB_SETCURSEL, 0, 0); h = GetDlgItem(hdlg, IDC_CHECK_BUGGER); SendMessage(h, BM_SETCHECK, temp_bugger, 0); @@ -220,7 +226,7 @@ peripherals_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) if (d == 0) { /* Translate "None". */ SendMessage(h, CB_ADDSTRING, 0, - (LPARAM)get_string(IDS_NONE)); + win_string(IDS_NONE)); } else { stransi = isartc_get_name(d); mbstowcs(temp, stransi, sizeof_w(temp)); @@ -245,7 +251,7 @@ peripherals_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) if (d == 0) { /* Translate "None". */ SendMessage(h, CB_ADDSTRING, 0, - (LPARAM)get_string(IDS_NONE)); + win_string(IDS_NONE)); } else { stransi = isamem_get_name(d); mbstowcs(temp, stransi, sizeof_w(temp)); @@ -264,20 +270,6 @@ peripherals_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) case WM_COMMAND: switch (LOWORD(wParam)) { - case IDC_CONFIGURE_SCSI: - h = GetDlgItem(hdlg, IDC_COMBO_SCSI); - temp_scsi_card = list_to_scsi[SendMessage(h, CB_GETCURSEL, 0, 0)]; - - temp_deviceconfig |= dlg_devconf(hdlg, (void *)scsi_card_getdevice(temp_scsi_card)); - break; - - case IDC_CONFIGURE_HDC: - h = GetDlgItem(hdlg, IDC_COMBO_HDC); - temp_hdc_type = hdc_get_from_internal_name(hdc_names[SendMessage(h, CB_GETCURSEL, 0, 0)]); - - temp_deviceconfig |= dlg_devconf(hdlg, (void *)hdc_get_device(temp_hdc_type)); - break; - case IDC_COMBO_SCSI: h = GetDlgItem(hdlg, IDC_COMBO_SCSI); temp_scsi_card = list_to_scsi[SendMessage(h, CB_GETCURSEL, 0, 0)]; @@ -289,6 +281,13 @@ peripherals_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) EnableWindow(h, FALSE); break; + case IDC_CONFIGURE_SCSI: + h = GetDlgItem(hdlg, IDC_COMBO_SCSI); + temp_scsi_card = list_to_scsi[SendMessage(h, CB_GETCURSEL, 0, 0)]; + + temp_deviceconfig |= dlg_devconf(hdlg, scsi_card_getdevice(temp_scsi_card)); + break; + case IDC_COMBO_HDC: h = GetDlgItem(hdlg, IDC_COMBO_HDC); temp_hdc_type = hdc_get_from_internal_name(hdc_names[SendMessage(h, CB_GETCURSEL, 0, 0)]); @@ -300,6 +299,35 @@ peripherals_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) EnableWindow(h, FALSE); break; + case IDC_CONFIGURE_HDC: + h = GetDlgItem(hdlg, IDC_COMBO_HDC); + temp_hdc_type = hdc_get_from_internal_name(hdc_names[SendMessage(h, CB_GETCURSEL, 0, 0)]); + + temp_deviceconfig |= dlg_devconf(hdlg, hdc_get_device(temp_hdc_type)); + break; + + case IDC_CHECK_IDE_TER: + h = GetDlgItem(hdlg, IDC_CHECK_IDE_TER); + temp_ide_ter = SendMessage(h, BM_GETCHECK, 0, 0); + h = GetDlgItem(hdlg, IDC_CONFIGURE_IDE_TER); + EnableWindow(h, temp_ide_ter ? TRUE : FALSE); + break; + + case IDC_CONFIGURE_IDE_TER: + temp_deviceconfig |= dlg_devconf(hdlg, &ide_ter_device); + break; + + case IDC_CHECK_IDE_QUA: + h = GetDlgItem(hdlg, IDC_CHECK_IDE_QUA); + temp_ide_qua = SendMessage(h, BM_GETCHECK, 0, 0); + h = GetDlgItem(hdlg, IDC_CONFIGURE_IDE_QUA); + EnableWindow(h, temp_ide_qua ? TRUE : FALSE); + break; + + case IDC_CONFIGURE_IDE_QUA: + temp_deviceconfig |= dlg_devconf(hdlg, &ide_qua_device); + break; + case IDC_COMBO_ISARTC: h = GetDlgItem(hdlg, IDC_COMBO_ISARTC); temp_isartc = SendMessage(h, CB_GETCURSEL, 0, 0); @@ -328,7 +356,7 @@ peripherals_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) case IDC_CONFIGURE_ISARTC: dev = isartc_get_device(temp_isartc); if (dev != NULL) - temp_deviceconfig |= dlg_devconf(hdlg, (void *)dev); + temp_deviceconfig |= dlg_devconf(hdlg, dev); break; case IDC_CONFIGURE_ISAMEM_1: @@ -338,14 +366,14 @@ peripherals_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) c = LOWORD(wParam) - IDC_CONFIGURE_ISAMEM_1; dev = isamem_get_device(c); if (dev != NULL) - temp_deviceconfig |= dlg_devconf(hdlg, (void *)dev); + temp_deviceconfig |= dlg_devconf(hdlg, dev); else ui_msgbox(MBX_INFO, (wchar_t *)IDS_ERR_SAVEIT); break; } return FALSE; - case WM_SAVESETTINGS: + case WM_SAVE_CFG: h = GetDlgItem(hdlg, IDC_COMBO_HDC); c = SendMessage(h, CB_GETCURSEL, 0, 0); if (hdc_names[c]) @@ -356,20 +384,6 @@ peripherals_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) h = GetDlgItem(hdlg, IDC_COMBO_SCSI); temp_scsi_card = list_to_scsi[SendMessage(h, CB_GETCURSEL, 0, 0)]; - h = GetDlgItem(hdlg, IDC_COMBO_IDE_TER); - temp_ide_ter = SendMessage(h, CB_GETCURSEL, 0, 0); - if (temp_ide_ter > 1) { - temp_ide_ter_irq = valid_ide_irqs[temp_ide_ter - 1]; - temp_ide_ter = 1; - } - - h = GetDlgItem(hdlg, IDC_COMBO_IDE_QUA); - temp_ide_qua = SendMessage(h, CB_GETCURSEL, 0, 0); - if (temp_ide_qua > 1) { - temp_ide_qua_irq = valid_ide_irqs[temp_ide_qua - 1]; - temp_ide_qua = 1; - } - h = GetDlgItem(hdlg, IDC_CHECK_BUGGER); temp_bugger = SendMessage(h, BM_GETCHECK, 0, 0); diff --git a/src/win/win_settings_ports.h b/src/win/win_settings_ports.h index 2a2e3bf..a2cfa48 100644 --- a/src/win/win_settings_ports.h +++ b/src/win/win_settings_ports.h @@ -108,7 +108,7 @@ ports_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) } return FALSE; - case WM_SAVESETTINGS: + case WM_SAVE_CFG: h = GetDlgItem(hdlg, IDC_CHECK_GAME); temp_game = SendMessage(h, BM_GETCHECK, 0, 0); diff --git a/src/win/win_settings_remov.h b/src/win/win_settings_remov.h index 7748294..6bbabff 100644 --- a/src/win/win_settings_remov.h +++ b/src/win/win_settings_remov.h @@ -8,7 +8,7 @@ * * Implementation of the "Removable Devices" dialog. * - * Version: @(#)win_settings_remov.h 1.0.7 2018/05/26 + * Version: @(#)win_settings_remov.h 1.0.8 2018/09/19 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -54,9 +54,7 @@ cdrom_track_init(void) int i; for (i = 0; i < CDROM_NUM; i++) { - if (cdrom_drives[i].bus_type == CDROM_BUS_ATAPI_PIO_ONLY) - ide_tracking |= (2 << (cdrom_drives[i].ide_channel << 3)); - else if (cdrom_drives[i].bus_type == CDROM_BUS_ATAPI_PIO_AND_DMA) + if (cdrom_drives[i].bus_type == CDROM_BUS_ATAPI) ide_tracking |= (2 << (cdrom_drives[i].ide_channel << 3)); else if (cdrom_drives[i].bus_type == CDROM_BUS_SCSI) scsi_tracking[cdrom_drives[i].scsi_device_id] |= (2 << (cdrom_drives[i].scsi_device_lun << 3)); @@ -97,11 +95,11 @@ cdrom_image_list_init(HWND hwndList) GetSystemMetrics(SM_CYSMICON), ILC_MASK | ILC_COLOR32, 1, 1); - hiconItem = LoadIcon(hInstance, (LPCWSTR)514); + hiconItem = LoadIcon(hInstance, (LPCWSTR)ICON_CDROM_D); ImageList_AddIcon(hSmall, hiconItem); DestroyIcon(hiconItem); - hiconItem = LoadIcon(hInstance, (LPCWSTR)160); + hiconItem = LoadIcon(hInstance, (LPCWSTR)ICON_CDROM); ImageList_AddIcon(hSmall, hiconItem); DestroyIcon(hiconItem); @@ -119,7 +117,7 @@ cdrom_recalc_list(HWND hwndList) lvI.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_STATE; lvI.stateMask = lvI.iSubItem = lvI.state = 0; - for (i = 0; i < 4; i++) { + for (i = CDROM_BUS_DISABLED; i < CDROM_BUS_MAX; i++) { fsid = temp_cdrom_drives[i].bus_type; lvI.iSubItem = 0; @@ -130,8 +128,7 @@ cdrom_recalc_list(HWND hwndList) lvI.iImage = 0; break; - case CDROM_BUS_ATAPI_PIO_ONLY: - case CDROM_BUS_ATAPI_PIO_AND_DMA: + case CDROM_BUS_ATAPI: swprintf(temp, sizeof_w(temp), L"%ls (%01i:%01i)", get_string(combo_to_string(fsid)), temp_cdrom_drives[i].ide_channel >> 1, @@ -155,10 +152,10 @@ cdrom_recalc_list(HWND hwndList) lvI.iSubItem = 1; if (fsid == CDROM_BUS_DISABLED) { - lvI.pszText = (LPTSTR)get_string(IDS_NONE); // "None" + lvI.pszText = (LPTSTR)get_string(IDS_NONE); } else { wsprintf(temp, L"%ix", - cdrom_speeds[temp_cdrom_drives[i].speed_idx].speed); + cdrom_speeds[temp_cdrom_drives[i].speed_idx].speed); lvI.pszText = temp; } lvI.iItem = i; @@ -179,14 +176,14 @@ cdrom_init_columns(HWND hwndList) lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM; lvc.iSubItem = 0; - lvc.pszText = (LPTSTR)get_string(IDS_BUS); // "Bus" + lvc.pszText = (LPTSTR)get_string(IDS_BUS); lvc.cx = 342; lvc.fmt = LVCFMT_LEFT; if (ListView_InsertColumn(hwndList, 0, &lvc) == -1) return FALSE; lvc.iSubItem = 1; - lvc.pszText = (LPTSTR)get_string(IDS_3579); // "Speed" + lvc.pszText = (LPTSTR)get_string(IDS_3579); lvc.cx = 80; lvc.fmt = LVCFMT_LEFT; if (ListView_InsertColumn(hwndList, 1, &lvc) == -1) @@ -236,8 +233,7 @@ cdrom_update_item(HWND hwndList, int i) lvI.iImage = 0; break; - case CDROM_BUS_ATAPI_PIO_ONLY: - case CDROM_BUS_ATAPI_PIO_AND_DMA: + case CDROM_BUS_ATAPI: swprintf(temp, sizeof_w(temp), L"%ls (%01i:%01i)", get_string(combo_to_string(fsid)), temp_cdrom_drives[i].ide_channel >> 1, @@ -263,7 +259,7 @@ cdrom_update_item(HWND hwndList, int i) lvI.pszText = (LPTSTR)get_string(IDS_NONE); } else { wsprintf(temp, L"%ix", - cdrom_speeds[temp_cdrom_drives[i].speed_idx].speed); + cdrom_speeds[temp_cdrom_drives[i].speed_idx].speed); lvI.pszText = temp; } lvI.iItem = i; @@ -281,12 +277,8 @@ cdrom_add_locations(HWND hdlg) int i = 0; h = GetDlgItem(hdlg, IDC_COMBO_CD_BUS); - for (i = CDROM_BUS_DISABLED; i <= CDROM_BUS_SCSI; i++) { - if ((i == CDROM_BUS_DISABLED) || (i >= CDROM_BUS_ATAPI_PIO_ONLY)) { - SendMessage(h, CB_ADDSTRING, 0, - (LPARAM)get_string(combo_to_string(i))); - } - } + for (i = CDROM_BUS_DISABLED; i < CDROM_BUS_MAX; i++) + SendMessage(h, CB_ADDSTRING, 0, win_string(combo_to_string(i))); /* Create a list of usable CD-ROM speeds. */ h = GetDlgItem(hdlg, IDC_COMBO_CD_SPEED); @@ -346,8 +338,7 @@ cdrom_recalc_location_controls(HWND hdlg, int assign_id) } switch(bus) { - case CDROM_BUS_ATAPI_PIO_ONLY: /* ATAPI (PIO-only) */ - case CDROM_BUS_ATAPI_PIO_AND_DMA: /* ATAPI (PIO and DMA) */ + case CDROM_BUS_ATAPI: h = GetDlgItem(hdlg, IDT_1743); ShowWindow(h, SW_SHOW); EnableWindow(h, TRUE); @@ -361,7 +352,7 @@ cdrom_recalc_location_controls(HWND hdlg, int assign_id) temp_cdrom_drives[cdlv_current_sel].ide_channel, 0); break; - case CDROM_BUS_SCSI: /* SCSI */ + case CDROM_BUS_SCSI: h = GetDlgItem(hdlg, IDT_1741); ShowWindow(h, SW_SHOW); EnableWindow(h, TRUE); @@ -390,7 +381,7 @@ cdrom_recalc_location_controls(HWND hdlg, int assign_id) static void cdrom_track(uint8_t id) { - if ((temp_cdrom_drives[id].bus_type == CDROM_BUS_ATAPI_PIO_ONLY) || (temp_cdrom_drives[id].bus_type == CDROM_BUS_ATAPI_PIO_ONLY)) + if (temp_cdrom_drives[id].bus_type == CDROM_BUS_ATAPI) ide_tracking |= (2 << (temp_cdrom_drives[id].ide_channel << 3)); else if (temp_cdrom_drives[id].bus_type == CDROM_BUS_SCSI) scsi_tracking[temp_cdrom_drives[id].scsi_device_id] |= (1ULL << temp_cdrom_drives[id].scsi_device_lun); @@ -400,7 +391,7 @@ cdrom_track(uint8_t id) static void cdrom_untrack(uint8_t id) { - if ((temp_cdrom_drives[id].bus_type == CDROM_BUS_ATAPI_PIO_ONLY) || (temp_cdrom_drives[id].bus_type == CDROM_BUS_ATAPI_PIO_ONLY)) + if (temp_cdrom_drives[id].bus_type == CDROM_BUS_ATAPI) ide_tracking &= ~(2 << (temp_cdrom_drives[id].ide_channel << 3)); else if (temp_cdrom_drives[id].bus_type == CDROM_BUS_SCSI) scsi_tracking[temp_cdrom_drives[id].scsi_device_id] &= ~(1ULL << temp_cdrom_drives[id].scsi_device_lun); @@ -425,9 +416,7 @@ zip_track_init(void) int i; for (i = 0; i < ZIP_NUM; i++) { - if (zip_drives[i].bus_type == ZIP_BUS_ATAPI_PIO_ONLY) - ide_tracking |= (4 << (zip_drives[i].ide_channel << 3)); - else if (zip_drives[i].bus_type == ZIP_BUS_ATAPI_PIO_AND_DMA) + if (zip_drives[i].bus_type == ZIP_BUS_ATAPI) ide_tracking |= (4 << (zip_drives[i].ide_channel << 3)); else if (zip_drives[i].bus_type == ZIP_BUS_SCSI) scsi_tracking[zip_drives[i].scsi_device_id] |= (4 << (zip_drives[i].scsi_device_lun << 3)); @@ -445,11 +434,11 @@ zip_image_list_init(HWND hwndList) GetSystemMetrics(SM_CYSMICON), ILC_MASK | ILC_COLOR32, 1, 1); - hiconItem = LoadIcon(hInstance, (LPCWSTR)515); + hiconItem = LoadIcon(hInstance, (LPCWSTR)ICON_ZIP_D); ImageList_AddIcon(hSmall, hiconItem); DestroyIcon(hiconItem); - hiconItem = LoadIcon(hInstance, (LPCWSTR)176); + hiconItem = LoadIcon(hInstance, (LPCWSTR)ICON_ZIP); ImageList_AddIcon(hSmall, hiconItem); DestroyIcon(hiconItem); @@ -467,7 +456,7 @@ zip_recalc_list(HWND hwndList) lvI.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_STATE; lvI.stateMask = lvI.iSubItem = lvI.state = 0; - for (i = 0; i < 4; i++) { + for (i = ZIP_BUS_DISABLED; i < ZIP_BUS_MAX; i++) { fsid = temp_zip_drives[i].bus_type; lvI.iSubItem = 0; @@ -478,8 +467,7 @@ zip_recalc_list(HWND hwndList) lvI.iImage = 0; break; - case ZIP_BUS_ATAPI_PIO_ONLY: - case ZIP_BUS_ATAPI_PIO_AND_DMA: + case ZIP_BUS_ATAPI: swprintf(temp, sizeof_w(temp), L"%ls (%01i:%01i)", get_string(combo_to_string(fsid)), temp_zip_drives[i].ide_channel >> 1, @@ -521,14 +509,14 @@ zip_init_columns(HWND hwndList) lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM; lvc.iSubItem = 0; - lvc.pszText = (LPTSTR)get_string(IDS_BUS); // "Bus" + lvc.pszText = (LPTSTR)get_string(IDS_BUS); lvc.cx = 342; lvc.fmt = LVCFMT_LEFT; if (ListView_InsertColumn(hwndList, 0, &lvc) == -1) return FALSE; lvc.iSubItem = 1; - lvc.pszText = (LPTSTR)get_string(IDS_TYPE); // "Type" + lvc.pszText = (LPTSTR)get_string(IDS_TYPE); lvc.cx = 50; lvc.fmt = LVCFMT_LEFT; if (ListView_InsertColumn(hwndList, 1, &lvc) == -1) @@ -545,7 +533,7 @@ zip_get_selected(HWND hdlg) int i, j = 0; HWND h; - for (i = 0; i < 6; i++) { + for (i = 0; i < 6; i++) { // FIXME: ZIP_NUM ? h = GetDlgItem(hdlg, IDC_LIST_ZIP_DRIVES); j = ListView_GetItemState(h, i, LVIS_SELECTED); if (j) @@ -578,8 +566,7 @@ zip_update_item(HWND hwndList, int i) lvI.iImage = 0; break; - case ZIP_BUS_ATAPI_PIO_ONLY: - case ZIP_BUS_ATAPI_PIO_AND_DMA: + case ZIP_BUS_ATAPI: swprintf(temp, sizeof_w(temp), L"%ls (%01i:%01i)", get_string(combo_to_string(fsid)), temp_zip_drives[i].ide_channel >> 1, @@ -617,12 +604,8 @@ zip_add_locations(HWND hdlg) int i; h = GetDlgItem(hdlg, IDC_COMBO_ZIP_BUS); - for (i = ZIP_BUS_DISABLED; i <= ZIP_BUS_SCSI; i++) { - if ((i == ZIP_BUS_DISABLED) || (i >= ZIP_BUS_ATAPI_PIO_ONLY)) { - SendMessage(h, CB_ADDSTRING, 0, - (LPARAM)get_string(combo_to_string(i))); - } - } + for (i = ZIP_BUS_DISABLED; i < ZIP_BUS_MAX; i++) + SendMessage(h, CB_ADDSTRING, 0, win_string(combo_to_string(i))); h = GetDlgItem(hdlg, IDC_COMBO_ZIP_ID); id_to_combo(h, 16); @@ -664,8 +647,7 @@ zip_recalc_location_controls(HWND hdlg, int assign_id) ShowWindow(h, SW_HIDE); switch(bus) { - case ZIP_BUS_ATAPI_PIO_ONLY: /* ATAPI (PIO-only) */ - case ZIP_BUS_ATAPI_PIO_AND_DMA: /* ATAPI (PIO and DMA) */ + case ZIP_BUS_ATAPI: h = GetDlgItem(hdlg, IDT_1756); ShowWindow(h, SW_SHOW); EnableWindow(h, TRUE); @@ -680,7 +662,7 @@ zip_recalc_location_controls(HWND hdlg, int assign_id) temp_zip_drives[zdlv_current_sel].ide_channel, 0); break; - case ZIP_BUS_SCSI: /* SCSI */ + case ZIP_BUS_SCSI: h = GetDlgItem(hdlg, IDT_1754); ShowWindow(h, SW_SHOW); EnableWindow(h, TRUE); @@ -709,7 +691,7 @@ zip_recalc_location_controls(HWND hdlg, int assign_id) static void zip_track(uint8_t id) { - if ((temp_zip_drives[id].bus_type == ZIP_BUS_ATAPI_PIO_ONLY) || (temp_zip_drives[id].bus_type == ZIP_BUS_ATAPI_PIO_ONLY)) + if (temp_zip_drives[id].bus_type == ZIP_BUS_ATAPI) ide_tracking |= (1ULL << temp_zip_drives[id].ide_channel); else if (temp_zip_drives[id].bus_type == ZIP_BUS_SCSI) scsi_tracking[temp_zip_drives[id].scsi_device_id] |= (1ULL << temp_zip_drives[id].scsi_device_lun); @@ -719,7 +701,7 @@ zip_track(uint8_t id) static void zip_untrack(uint8_t id) { - if ((temp_zip_drives[id].bus_type == ZIP_BUS_ATAPI_PIO_ONLY) || (temp_zip_drives[id].bus_type == ZIP_BUS_ATAPI_PIO_ONLY)) + if (temp_zip_drives[id].bus_type == ZIP_BUS_ATAPI) ide_tracking &= ~(1ULL << temp_zip_drives[id].ide_channel); else if (temp_zip_drives[id].bus_type == ZIP_BUS_SCSI) scsi_tracking[temp_zip_drives[id].scsi_device_id] &= ~(1ULL << temp_zip_drives[id].scsi_device_lun); @@ -745,11 +727,10 @@ static BOOL CALLBACK #endif rmv_devices_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) { - HWND h = INVALID_HANDLE_VALUE; + HWND h; int old_sel = 0; - int b = 0; - int b2 = 0; int assign = 0; + int b; switch (message) { case WM_INITDIALOG: @@ -763,24 +744,7 @@ rmv_devices_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) ListView_SetItemState(h, 0, LVIS_FOCUSED | LVIS_SELECTED, 0x000F); cdrom_add_locations(hdlg); h = GetDlgItem(hdlg, IDC_COMBO_CD_BUS); - switch (temp_cdrom_drives[cdlv_current_sel].bus_type) { - case CDROM_BUS_DISABLED: - default: - b = 0; - break; - - case CDROM_BUS_ATAPI_PIO_ONLY: - b = 1; - break; - - case CDROM_BUS_ATAPI_PIO_AND_DMA: - b = 2; - break; - - case CDROM_BUS_SCSI: - b = 3; - break; - } + b = temp_cdrom_drives[cdlv_current_sel].bus_type; SendMessage(h, CB_SETCURSEL, b, 0); cdrom_recalc_location_controls(hdlg, 0); @@ -791,24 +755,7 @@ rmv_devices_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) zip_recalc_list(h); zip_add_locations(hdlg); h = GetDlgItem(hdlg, IDC_COMBO_ZIP_BUS); - switch (temp_zip_drives[zdlv_current_sel].bus_type) { - case ZIP_BUS_DISABLED: - default: - b = 0; - break; - - case ZIP_BUS_ATAPI_PIO_ONLY: - b = 1; - break; - - case ZIP_BUS_ATAPI_PIO_AND_DMA: - b = 2; - break; - - case ZIP_BUS_SCSI: - b = 3; - break; - } + b = temp_zip_drives[zdlv_current_sel].bus_type; SendMessage(h, CB_SETCURSEL, b, 0); zip_recalc_location_controls(hdlg, 0); h = GetDlgItem(hdlg, IDC_CHECK250); @@ -823,6 +770,7 @@ rmv_devices_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) if ((((LPNMHDR)lParam)->code == LVN_ITEMCHANGED) && (((LPNMHDR)lParam)->idFrom == IDC_LIST_CDROM_DRIVES)) { old_sel = cdlv_current_sel; + h = GetDlgItem(hdlg, IDC_LIST_CDROM_DRIVES); cdlv_current_sel = cdrom_get_selected(hdlg); if (cdlv_current_sel == old_sel) return FALSE; @@ -836,25 +784,12 @@ rmv_devices_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) rd_ignore_change = 1; h = GetDlgItem(hdlg, IDC_COMBO_CD_BUS); - switch (temp_cdrom_drives[cdlv_current_sel].bus_type) { - case CDROM_BUS_DISABLED: - default: - b = 0; - break; - case CDROM_BUS_ATAPI_PIO_ONLY: - b = 1; - break; - case CDROM_BUS_ATAPI_PIO_AND_DMA: - b = 2; - break; - case CDROM_BUS_SCSI: - b = 3; - break; - } + b = temp_cdrom_drives[cdlv_current_sel].bus_type; SendMessage(h, CB_SETCURSEL, b, 0); cdrom_recalc_location_controls(hdlg, 0); } else if ((((LPNMHDR)lParam)->code == LVN_ITEMCHANGED) && (((LPNMHDR)lParam)->idFrom == IDC_LIST_ZIP_DRIVES)) { old_sel = zdlv_current_sel; + h = GetDlgItem(hdlg, IDC_LIST_ZIP_DRIVES); zdlv_current_sel = zip_get_selected(hdlg); if (zdlv_current_sel == old_sel) return FALSE; @@ -869,24 +804,7 @@ rmv_devices_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) rd_ignore_change = 1; h = GetDlgItem(hdlg, IDC_COMBO_ZIP_BUS); - switch (temp_zip_drives[zdlv_current_sel].bus_type) { - case ZIP_BUS_DISABLED: - default: - b = 0; - break; - - case ZIP_BUS_ATAPI_PIO_ONLY: - b = 1; - break; - - case ZIP_BUS_ATAPI_PIO_AND_DMA: - b = 2; - break; - - case ZIP_BUS_SCSI: - b = 3; - break; - } + b = temp_zip_drives[zdlv_current_sel].bus_type; SendMessage(h, CB_SETCURSEL, b, 0); zip_recalc_location_controls(hdlg, 0); h = GetDlgItem(hdlg, IDC_CHECK250); @@ -905,41 +823,20 @@ rmv_devices_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) rd_ignore_change = 1; h = GetDlgItem(hdlg, IDC_COMBO_CD_BUS); b = SendMessage(h, CB_GETCURSEL, 0, 0); - switch (b) { - case 0: - b2 = CDROM_BUS_DISABLED; - break; - - case 1: - b2 = CDROM_BUS_ATAPI_PIO_ONLY; - break; - - case 2: - b2 = CDROM_BUS_ATAPI_PIO_AND_DMA; - break; - - case 3: - b2 = CDROM_BUS_SCSI; - break; - } - if (b2 == temp_cdrom_drives[cdlv_current_sel].bus_type) + if (b == temp_cdrom_drives[cdlv_current_sel].bus_type) goto cdrom_bus_skip; cdrom_untrack(cdlv_current_sel); - assign = (temp_cdrom_drives[cdlv_current_sel].bus_type == b2) ? 0 : 1; + assign = (temp_cdrom_drives[cdlv_current_sel].bus_type == b) ? 0 : 1; if (temp_cdrom_drives[cdlv_current_sel].bus_type == CDROM_BUS_DISABLED) temp_cdrom_drives[cdlv_current_sel].speed_idx = cdrom_speed_idx(cdrom_speed_idx(CDROM_SPEED_DEFAULT)); - if ((b2 == CDROM_BUS_ATAPI_PIO_ONLY) && (temp_cdrom_drives[cdlv_current_sel].bus_type == CDROM_BUS_ATAPI_PIO_AND_DMA)) - assign = 0; - else if ((b2 == CDROM_BUS_ATAPI_PIO_AND_DMA) && (temp_cdrom_drives[cdlv_current_sel].bus_type == CDROM_BUS_ATAPI_PIO_ONLY)) - assign = 0; - temp_cdrom_drives[cdlv_current_sel].bus_type = b2; + temp_cdrom_drives[cdlv_current_sel].bus_type = b; cdrom_recalc_location_controls(hdlg, assign); cdrom_track(cdlv_current_sel); h = GetDlgItem(hdlg, IDC_LIST_CDROM_DRIVES); cdrom_update_item(h, cdlv_current_sel); cdrom_bus_skip: - rd_ignore_change = 0; - return FALSE; + rd_ignore_change = 0; + return FALSE; case IDC_COMBO_CD_ID: if (rd_ignore_change) @@ -948,7 +845,8 @@ cdrom_bus_skip: rd_ignore_change = 1; h = GetDlgItem(hdlg, IDC_COMBO_CD_ID); cdrom_untrack(cdlv_current_sel); - temp_cdrom_drives[cdlv_current_sel].scsi_device_id = SendMessage(h, CB_GETCURSEL, 0, 0); + b = SendMessage(h, CB_GETCURSEL, 0, 0); + temp_cdrom_drives[cdlv_current_sel].scsi_device_id = (uint8_t)b; cdrom_track(cdlv_current_sel); h = GetDlgItem(hdlg, IDC_LIST_CDROM_DRIVES); cdrom_update_item(h, cdlv_current_sel); @@ -962,7 +860,8 @@ cdrom_bus_skip: rd_ignore_change = 1; h = GetDlgItem(hdlg, IDC_COMBO_CD_LUN); cdrom_untrack(cdlv_current_sel); - temp_cdrom_drives[cdlv_current_sel].scsi_device_lun = SendMessage(h, CB_GETCURSEL, 0, 0); + b = SendMessage(h, CB_GETCURSEL, 0, 0); + temp_cdrom_drives[cdlv_current_sel].scsi_device_lun = (uint8_t)b; cdrom_track(cdlv_current_sel); h = GetDlgItem(hdlg, IDC_LIST_CDROM_DRIVES); cdrom_update_item(h, cdlv_current_sel); @@ -976,7 +875,8 @@ cdrom_bus_skip: rd_ignore_change = 1; h = GetDlgItem(hdlg, IDC_COMBO_CD_CHANNEL_IDE); cdrom_untrack(cdlv_current_sel); - temp_cdrom_drives[cdlv_current_sel].ide_channel = SendMessage(h, CB_GETCURSEL, 0, 0) & 0xff; + b = SendMessage(h, CB_GETCURSEL, 0, 0); + temp_cdrom_drives[cdlv_current_sel].ide_channel = (uint8_t)b; cdrom_track(cdlv_current_sel); h = GetDlgItem(hdlg, IDC_LIST_CDROM_DRIVES); cdrom_update_item(h, cdlv_current_sel); @@ -989,7 +889,8 @@ cdrom_bus_skip: rd_ignore_change = 1; h = GetDlgItem(hdlg, IDC_COMBO_CD_SPEED); - temp_cdrom_drives[cdlv_current_sel].speed_idx = (uint8_t)SendMessage(h, CB_GETCURSEL, 0, 0); + b = SendMessage(h, CB_GETCURSEL, 0, 0); + temp_cdrom_drives[cdlv_current_sel].speed_idx = (uint8_t)b; h = GetDlgItem(hdlg, IDC_LIST_CDROM_DRIVES); cdrom_update_item(h, cdlv_current_sel); rd_ignore_change = 0; @@ -1002,29 +903,11 @@ cdrom_bus_skip: rd_ignore_change = 1; h = GetDlgItem(hdlg, IDC_COMBO_ZIP_BUS); b = SendMessage(h, CB_GETCURSEL, 0, 0); - switch (b) { - case 0: - b2 = ZIP_BUS_DISABLED; - break; - case 1: - b2 = ZIP_BUS_ATAPI_PIO_ONLY; - break; - case 2: - b2 = ZIP_BUS_ATAPI_PIO_AND_DMA; - break; - case 3: - b2 = ZIP_BUS_SCSI; - break; - } - if (b2 == temp_zip_drives[zdlv_current_sel].bus_type) + if (temp_zip_drives[zdlv_current_sel].bus_type == b) goto zip_bus_skip; zip_untrack(zdlv_current_sel); - assign = (temp_zip_drives[zdlv_current_sel].bus_type == b2) ? 0 : 1; - if ((b2 == ZIP_BUS_ATAPI_PIO_ONLY) && (temp_zip_drives[zdlv_current_sel].bus_type == ZIP_BUS_ATAPI_PIO_AND_DMA)) - assign = 0; - else if ((b2 == ZIP_BUS_ATAPI_PIO_AND_DMA) && (temp_zip_drives[cdlv_current_sel].bus_type == ZIP_BUS_ATAPI_PIO_ONLY)) - assign = 0; - temp_zip_drives[zdlv_current_sel].bus_type = b2; + assign = (temp_zip_drives[zdlv_current_sel].bus_type == b) ? 0 : 1; + temp_zip_drives[zdlv_current_sel].bus_type = b; zip_recalc_location_controls(hdlg, assign); zip_track(zdlv_current_sel); h = GetDlgItem(hdlg, IDC_LIST_ZIP_DRIVES); @@ -1040,7 +923,8 @@ zip_bus_skip: rd_ignore_change = 1; h = GetDlgItem(hdlg, IDC_COMBO_ZIP_ID); zip_untrack(zdlv_current_sel); - temp_zip_drives[zdlv_current_sel].scsi_device_id = SendMessage(h, CB_GETCURSEL, 0, 0); + b = SendMessage(h, CB_GETCURSEL, 0, 0); + temp_zip_drives[zdlv_current_sel].scsi_device_id = (uint8_t)b; zip_track(zdlv_current_sel); h = GetDlgItem(hdlg, IDC_LIST_ZIP_DRIVES); zip_update_item(h, zdlv_current_sel); @@ -1054,7 +938,8 @@ zip_bus_skip: rd_ignore_change = 1; h = GetDlgItem(hdlg, IDC_COMBO_ZIP_LUN); zip_untrack(zdlv_current_sel); - temp_zip_drives[zdlv_current_sel].scsi_device_lun = SendMessage(h, CB_GETCURSEL, 0, 0); + b = SendMessage(h, CB_GETCURSEL, 0, 0); + temp_zip_drives[zdlv_current_sel].scsi_device_lun = (uint8_t)b; zip_track(zdlv_current_sel); h = GetDlgItem(hdlg, IDC_LIST_ZIP_DRIVES); zip_update_item(h, zdlv_current_sel); @@ -1068,7 +953,8 @@ zip_bus_skip: rd_ignore_change = 1; h = GetDlgItem(hdlg, IDC_COMBO_ZIP_CHANNEL_IDE); zip_untrack(zdlv_current_sel); - temp_zip_drives[zdlv_current_sel].ide_channel = SendMessage(h, CB_GETCURSEL, 0, 0) & 0xff; + b = SendMessage(h, CB_GETCURSEL, 0, 0); + temp_zip_drives[zdlv_current_sel].ide_channel = (uint8_t)b; zip_track(zdlv_current_sel); h = GetDlgItem(hdlg, IDC_LIST_ZIP_DRIVES); zip_update_item(h, zdlv_current_sel); @@ -1081,7 +967,8 @@ zip_bus_skip: rd_ignore_change = 1; h = GetDlgItem(hdlg, IDC_CHECK250); - temp_zip_drives[zdlv_current_sel].is_250 = SendMessage(h, BM_GETCHECK, 0, 0); + b = SendMessage(h, BM_GETCHECK, 0, 0); + temp_zip_drives[zdlv_current_sel].is_250 = (int8_t)b; h = GetDlgItem(hdlg, IDC_LIST_ZIP_DRIVES); zip_update_item(h, zdlv_current_sel); rd_ignore_change = 0; diff --git a/src/win/win_settings_sound.h b/src/win/win_settings_sound.h index 3bfe222..fb9a0df 100644 --- a/src/win/win_settings_sound.h +++ b/src/win/win_settings_sound.h @@ -8,7 +8,7 @@ * * Implementation of the Settings dialog. * - * Version: @(#)win_settings_sound.h 1.0.10 2018/09/03 + * Version: @(#)win_settings_sound.h 1.0.11 2018/09/29 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -53,15 +53,6 @@ static int midi_to_list[NUM_MIDI], list_to_midi[NUM_MIDI]; static int mpu401_present(void) { - const char *stransi; - - stransi = sound_card_get_internal_name(temp_sound_card); - if (stransi != NULL) { - if (!strcmp(stransi, "sb16") || - !strcmp(stransi, "sbawe32") || - !strcmp(stransi, "replysb16")) return 1; - } - return temp_mpu401 ? 1 : 0; } @@ -69,16 +60,9 @@ mpu401_present(void) static int mpu401_standalone_allow(void) { - const char *n, *md; + const char *md; - n = sound_card_get_internal_name(temp_sound_card); md = midi_device_get_internal_name(temp_midi_device); - if (n != NULL) { - if (!strcmp(n, "sb16") || - !strcmp(n, "sbawe32") || - !strcmp(n, "replysb16")) return 0; - } - if (md != NULL) { if (! strcmp(md, "none")) return 0; @@ -96,6 +80,7 @@ static BOOL CALLBACK sound_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) { WCHAR temp[128]; + char tempA[128]; const char *stransi; const device_t *dev; HWND h; @@ -106,20 +91,39 @@ sound_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) h = GetDlgItem(hdlg, IDC_COMBO_SOUND); c = d = 0; while (1) { - stransi = sound_card_getname(c); + stransi = sound_card_get_internal_name(c); if (stransi == NULL) break; sound_to_list[c] = d; - if (sound_card_available(c)) { - dev = sound_card_getdevice(c); - if (device_is_valid(dev, machines[temp_machine].flags)) { - mbstowcs(temp, stransi, sizeof_w(temp)); + dev = sound_card_getdevice(c); + + if (sound_card_available(c) && + device_is_valid(dev, machines[temp_machine].flags)) { + if (c == 0) { + /* Translate "None". */ + SendMessage(h, CB_ADDSTRING, 0, + win_string(IDS_NONE)); + } else if (c == 1) { + if (! (machines[temp_machine].flags&MACHINE_SOUND)) { + c++; + continue; + } + + /* Translate "Internal". */ + SendMessage(h, CB_ADDSTRING, 0, + win_string(IDS_INTERNAL)); + } else { + sprintf(tempA, "[%s] %s", + device_get_bus_name(dev), + sound_card_getname(c)); + mbstowcs(temp, tempA, sizeof_w(temp)); SendMessage(h, CB_ADDSTRING, 0, (LPARAM)temp); - list_to_sound[d] = c; - d++; } + + list_to_sound[d] = c; + d++; } c++; @@ -128,7 +132,7 @@ sound_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) EnableWindow(h, d ? TRUE : FALSE); - h = GetDlgItem(hdlg, IDC_CONFIGURE_SND); + h = GetDlgItem(hdlg, IDC_CONFIGURE_SOUND); if (sound_card_has_config(temp_sound_card)) EnableWindow(h, TRUE); else @@ -137,15 +141,22 @@ sound_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) h = GetDlgItem(hdlg, IDC_COMBO_MIDI); c = d = 0; while (1) { - stransi = midi_device_getname(c); + stransi = midi_device_get_internal_name(c); if (stransi == NULL) break; midi_to_list[c] = d; if (midi_device_available(c)) { - mbstowcs(temp, stransi, sizeof_w(temp)); - SendMessage(h, CB_ADDSTRING, 0, (LPARAM)temp); + if (d == 0) { + /* Translate "None". */ + SendMessage(h, CB_ADDSTRING, 0, + win_string(IDS_NONE)); + } else { + stransi = midi_device_getname(c); + mbstowcs(temp, stransi, sizeof_w(temp)); + SendMessage(h, CB_ADDSTRING, 0, (LPARAM)temp); + } list_to_midi[d] = c; d++; @@ -169,7 +180,7 @@ sound_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) EnableWindow(h, (mpu401_standalone_allow() && temp_mpu401) ? TRUE : FALSE); h = GetDlgItem(hdlg, IDC_CHECK_NUKEDOPL); - SendMessage(h, BM_SETCHECK, temp_opl3_type, 0); + SendMessage(h, BM_SETCHECK, temp_opl_type, 0); h = GetDlgItem(hdlg, IDC_CHECK_FLOAT); SendMessage(h, BM_SETCHECK, temp_float, 0); @@ -182,7 +193,7 @@ sound_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) h = GetDlgItem(hdlg, IDC_COMBO_SOUND); temp_sound_card = list_to_sound[SendMessage(h, CB_GETCURSEL, 0, 0)]; - h = GetDlgItem(hdlg, IDC_CONFIGURE_SND); + h = GetDlgItem(hdlg, IDC_CONFIGURE_SOUND); if (sound_card_has_config(temp_sound_card)) EnableWindow(h, TRUE); else @@ -196,11 +207,11 @@ sound_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) EnableWindow(h, (mpu401_standalone_allow() && temp_mpu401) ? TRUE : FALSE); break; - case IDC_CONFIGURE_SND: + case IDC_CONFIGURE_SOUND: h = GetDlgItem(hdlg, IDC_COMBO_SOUND); temp_sound_card = list_to_sound[SendMessage(h, CB_GETCURSEL, 0, 0)]; - temp_deviceconfig |= dlg_devconf(hdlg, (void *)sound_card_getdevice(temp_sound_card)); + temp_deviceconfig |= dlg_devconf(hdlg, sound_card_getdevice(temp_sound_card)); break; case IDC_COMBO_MIDI: @@ -225,7 +236,7 @@ sound_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) h = GetDlgItem(hdlg, IDC_COMBO_MIDI); temp_midi_device = list_to_midi[SendMessage(h, CB_GETCURSEL, 0, 0)]; - temp_deviceconfig |= dlg_devconf(hdlg, (void *)midi_device_getdevice(temp_midi_device)); + temp_deviceconfig |= dlg_devconf(hdlg, midi_device_getdevice(temp_midi_device)); break; case IDC_CHECK_MPU401: @@ -237,23 +248,15 @@ sound_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) break; case IDC_CONFIGURE_MPU401: - stransi = sound_card_get_internal_name(temp_sound_card); - if (stransi != NULL) { - if (! strcmp(stransi, "ncraudio")) - mca_version = 1; - else - mca_version = 0; - } - - temp_deviceconfig |= dlg_devconf(hdlg, mca_version ? (void *)&mpu401_mca_device : (void *)&mpu401_device); + temp_deviceconfig |= dlg_devconf(hdlg, (machines[temp_machine].flags & MACHINE_MCA) ? + &mpu401_mca_device : &mpu401_device); break; } return FALSE; - case WM_SAVESETTINGS: + case WM_SAVE_CFG: h = GetDlgItem(hdlg, IDC_COMBO_SOUND); temp_sound_card = list_to_sound[SendMessage(h, CB_GETCURSEL, 0, 0)]; -pclog("SND SAVE: temp_sound_card = %d (%d)\n", temp_sound_card, list_to_sound[SendMessage(h, CB_GETCURSEL, 0, 0)]); h = GetDlgItem(hdlg, IDC_COMBO_MIDI); temp_midi_device = list_to_midi[SendMessage(h, CB_GETCURSEL, 0, 0)]; @@ -262,7 +265,7 @@ pclog("SND SAVE: temp_sound_card = %d (%d)\n", temp_sound_card, list_to_sound[Se temp_mpu401 = SendMessage(h, BM_GETCHECK, 0, 0); h = GetDlgItem(hdlg, IDC_CHECK_NUKEDOPL); - temp_opl3_type = SendMessage(h, BM_GETCHECK, 0, 0); + temp_opl_type = SendMessage(h, BM_GETCHECK, 0, 0); h = GetDlgItem(hdlg, IDC_CHECK_FLOAT); temp_float = SendMessage(h, BM_GETCHECK, 0, 0); diff --git a/src/win/win_settings_video.h b/src/win/win_settings_video.h index 59186fb..90826a8 100644 --- a/src/win/win_settings_video.h +++ b/src/win/win_settings_video.h @@ -8,7 +8,7 @@ * * Implementation of the Settings dialog. * - * Version: @(#)win_settings_video.h 1.0.6 2018/05/24 + * Version: @(#)win_settings_video.h 1.0.7 2018/09/29 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -42,54 +42,8 @@ * * ************************************************************************/ -static void -recalc_vid_list(HWND hdlg) -{ - WCHAR temp[128]; - const char *stransi; - HWND h = GetDlgItem(hdlg, IDC_COMBO_VIDEO); - int c = 0, d = 0; - int found_card = 0; - - SendMessage(h, CB_RESETCONTENT, 0, 0); - SendMessage(h, CB_SETCURSEL, 0, 0); - - while (1) { - /* Skip "internal" if machine doesn't have it. */ - if (c == 1 && !(machines[temp_machine].flags&MACHINE_VIDEO)) { - c++; - continue; - } - - stransi = video_card_getname(c); - if (! *stransi) - break; - - if (video_card_available(c) && vid_present[video_new_to_old(c)] && - device_is_valid(video_card_getdevice(c), machines[temp_machine].flags)) { - mbstowcs(temp, stransi, sizeof_w(temp)); - SendMessage(h, CB_ADDSTRING, 0, (LPARAM)temp); - if (video_new_to_old(c) == temp_video_card) { - SendMessage(h, CB_SETCURSEL, d, 0); - found_card = 1; - } - - d++; - } - - c++; - } - if (! found_card) - SendMessage(h, CB_SETCURSEL, 0, 0); - - EnableWindow(h, machines[temp_machine].fixed_vidcard ? FALSE : TRUE); - - h = GetDlgItem(hdlg, IDC_CHECK_VOODOO); - EnableWindow(h, (machines[temp_machine].flags & MACHINE_PCI) ? TRUE:FALSE); - - h = GetDlgItem(hdlg, IDC_BUTTON_VOODOO); - EnableWindow(h, ((machines[temp_machine].flags & MACHINE_PCI) && temp_voodoo) ? TRUE : FALSE); -} +static int list_to_vid[100], + vid_to_list[100]; #ifdef __amd64__ @@ -99,35 +53,81 @@ static BOOL CALLBACK #endif video_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) { - WCHAR temp[128]; char tempA[128]; - int vid, i; + WCHAR temp[128]; + const char *stransi; + const device_t *dev; + int c, d; + int vid; HWND h; switch (message) { case WM_INITDIALOG: - recalc_vid_list(hdlg); - - h = GetDlgItem(hdlg, IDC_COMBO_VIDEO_SPEED); - SendMessage(h, CB_ADDSTRING, 0, (LPARAM)get_string(IDS_3353)); - for (i = 0; i < 6; i++) - SendMessage(h, CB_ADDSTRING, 0, - (LPARAM)get_string(IDS_3354 + i)); - SendMessage(h, CB_SETCURSEL, temp_video_speed+1, 0); - - h = GetDlgItem(hdlg, IDC_CHECK_VOODOO); - SendMessage(h, BM_SETCHECK, temp_voodoo, 0); - + /* Clear the video cards combo. */ + h = GetDlgItem(hdlg, IDC_CONFIGURE_VIDEO); + EnableWindow(h, FALSE); h = GetDlgItem(hdlg, IDC_COMBO_VIDEO); - SendMessage(h, CB_GETLBTEXT, SendMessage(h, CB_GETCURSEL, 0, 0), (LPARAM)temp); - wcstombs(tempA, temp, sizeof(tempA)); - vid = video_card_getid(tempA); + SendMessage(h, CB_RESETCONTENT, 0, 0); + SendMessage(h, CB_SETCURSEL, 0, 0); - h = GetDlgItem(hdlg, IDC_CONFIGURE_VID); - if (video_card_has_config(vid)) - EnableWindow(h, TRUE); - else - EnableWindow(h, FALSE); + /* Populate the video cards combo. */ + c = d = 0; + while (1) { + stransi = video_get_internal_name(c); + if (stransi == NULL) break; + + /* Skip "internal" if machine doesn't have it. */ + if (c == VID_INTERNAL && + !(machines[temp_machine].flags&MACHINE_VIDEO)) { + c++; + continue; + } + + dev = video_card_getdevice(c); + + if (c == 0) { + /* Translate "None". */ + wcscpy(temp, get_string(IDS_NONE)); + } else if (c == 1) { + /* Translate "Internal". */ + wcscpy(temp, get_string(IDS_INTERNAL)); + } else if (video_card_available(c) && + device_is_valid(dev, machines[temp_machine].flags)) { + sprintf(tempA, "[%s] %s", + device_get_bus_name(dev), + video_card_getname(c)); + mbstowcs(temp, tempA, sizeof_w(temp)); + } else { + c++; + continue; + } + + /* Add entry to combo. */ + SendMessage(h, CB_ADDSTRING, 0, (LPARAM)temp); + + vid_to_list[c] = d; + list_to_vid[d++] = c++; + } + INFO("A total of %i video cards are available.\n", d); + + /* Select the current card. */ + vid = vid_to_list[temp_video_card]; + if (vid < d) { + SendMessage(h, CB_SETCURSEL, vid, 0); + if (video_card_has_config(vid)) { + h = GetDlgItem(hdlg, IDC_CONFIGURE_VIDEO); + EnableWindow(h, TRUE); + } + } + + /* Machine with fixed video card have this disabled. */ + EnableWindow(h, machines[temp_machine].fixed_vidcard ? FALSE : TRUE); + + /* Disable Voodoo on PCI machine? */ + h = GetDlgItem(hdlg, IDC_CHECK_VOODOO); + EnableWindow(h, (machines[temp_machine].flags & MACHINE_PCI) ? TRUE:FALSE); + h = GetDlgItem(hdlg, IDC_CONFIGURE_VOODOO); + EnableWindow(h, ((machines[temp_machine].flags & MACHINE_PCI) && temp_voodoo) ? TRUE : FALSE); return TRUE; @@ -135,13 +135,11 @@ video_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) switch (LOWORD(wParam)) { case IDC_COMBO_VIDEO: h = GetDlgItem(hdlg, IDC_COMBO_VIDEO); - SendMessage(h, CB_GETLBTEXT, SendMessage(h, CB_GETCURSEL, 0, 0), (LPARAM)temp); - wcstombs(tempA, temp, sizeof(tempA)); - vid = video_card_getid(tempA); - temp_video_card = video_new_to_old(vid); + c = SendMessage(h, CB_GETCURSEL, 0, 0); + temp_video_card = list_to_vid[c]; - h = GetDlgItem(hdlg, IDC_CONFIGURE_VID); - if (video_card_has_config(vid)) + h = GetDlgItem(hdlg, IDC_CONFIGURE_VIDEO); + if (video_card_has_config(temp_video_card)) EnableWindow(h, TRUE); else EnableWindow(h, FALSE); @@ -151,32 +149,27 @@ video_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) h = GetDlgItem(hdlg, IDC_CHECK_VOODOO); temp_voodoo = SendMessage(h, BM_GETCHECK, 0, 0); - h = GetDlgItem(hdlg, IDC_BUTTON_VOODOO); + h = GetDlgItem(hdlg, IDC_CONFIGURE_VOODOO); EnableWindow(h, temp_voodoo ? TRUE : FALSE); break; - case IDC_BUTTON_VOODOO: - temp_deviceconfig |= dlg_devconf(hdlg, (void *)&voodoo_device); + case IDC_CONFIGURE_VOODOO: + temp_deviceconfig |= dlg_devconf(hdlg, &voodoo_device); break; - case IDC_CONFIGURE_VID: + case IDC_CONFIGURE_VIDEO: h = GetDlgItem(hdlg, IDC_COMBO_VIDEO); - SendMessage(h, CB_GETLBTEXT, SendMessage(h, CB_GETCURSEL, 0, 0), (LPARAM)temp); - wcstombs(tempA, temp, sizeof(temp)); - temp_deviceconfig |= dlg_devconf(hdlg, (void *)video_card_getdevice(video_card_getid(tempA))); + c = list_to_vid[SendMessage(h, CB_GETCURSEL, 0, 0)]; + temp_deviceconfig |= dlg_devconf(hdlg, video_card_getdevice(c)); break; } return FALSE; - case WM_SAVESETTINGS: + case WM_SAVE_CFG: h = GetDlgItem(hdlg, IDC_COMBO_VIDEO); - SendMessage(h, CB_GETLBTEXT, SendMessage(h, CB_GETCURSEL, 0, 0), (LPARAM)temp); - wcstombs(tempA, temp, sizeof(tempA)); - temp_video_card = video_new_to_old(video_card_getid(tempA)); - - h = GetDlgItem(hdlg, IDC_COMBO_VIDEO_SPEED); - temp_video_speed = SendMessage(h, CB_GETCURSEL, 0, 0) - 1; + c = SendMessage(h, CB_GETCURSEL, 0, 0); + temp_video_card = list_to_vid[c]; h = GetDlgItem(hdlg, IDC_CHECK_VOODOO); temp_voodoo = SendMessage(h, BM_GETCHECK, 0, 0); diff --git a/src/win/win_snd_gain.c b/src/win/win_snd_gain.c index 0f4170d..152da4e 100644 --- a/src/win/win_snd_gain.c +++ b/src/win/win_snd_gain.c @@ -8,7 +8,7 @@ * * Implementation of the Sound Gain dialog. * - * Version: @(#)win_snd_gain.c 1.0.7 2018/05/19 + * Version: @(#)win_snd_gain.c 1.0.8 2018/10/05 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -49,6 +49,7 @@ #include "../plat.h" #include "../devices/sound/sound.h" #include "win.h" +#include "resource.h" static uint8_t old_gain; diff --git a/src/win/win_status.c b/src/win/win_status.c deleted file mode 100644 index ceaece3..0000000 --- a/src/win/win_status.c +++ /dev/null @@ -1,158 +0,0 @@ -/* - * VARCem Virtual ARchaeological Computer EMulator. - * An emulator of (mostly) x86-based PC systems and devices, - * using the ISA,EISA,VLB,MCA and PCI system buses, roughly - * spanning the era between 1981 and 1995. - * - * This file is part of the VARCem Project. - * - * Implementation of the Status Window dialog. - * - * Version: @(#)win_status.c 1.0.7 2018/05/19 - * - * Authors: Fred N. van Kempen, - * Miran Grca, - * Sarah Walker, - * - * Copyright 2017,2018 Fred N. van Kempen. - * Copyright 2016-2018 Miran Grca. - * Copyright 2008-2018 Sarah Walker. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the: - * - * Free Software Foundation, Inc. - * 59 Temple Place - Suite 330 - * Boston, MA 02111-1307 - * USA. - */ -#define WIN32_LEAN_AND_MEAN -#include -#include -#include -#include -#include -#include "../emu.h" -#include "../mem.h" -#include "../cpu/cpu.h" -#include "../cpu/x86_ops.h" -#ifdef USE_DYNAREC -# include "../cpu/codegen.h" -#endif -#include "../device.h" -#include "../ui/ui.h" -#include "../plat.h" -#include "../devices/system/pit.h" -#include "win.h" - - - -static HWND hwndStatus = NULL; - - -extern int sreadlnum, swritelnum, segareads, segawrites, scycles_lost; -extern uint64_t main_time; -static uint64_t status_time; - - -#ifdef __amd64__ -static LRESULT CALLBACK -#else -static BOOL CALLBACK -#endif -dlg_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) -{ - char temp[4096]; - uint64_t new_time; - uint64_t status_diff; - - switch (message) { - case WM_INITDIALOG: - hwndStatus = hdlg; - /*FALLTHROUGH*/ - - case WM_USER: - new_time = plat_timer_read(); - status_diff = new_time - status_time; - status_time = new_time; - sprintf(temp, - "CPU speed : %f MIPS\n" - "FPU speed : %f MFLOPS\n\n" - - "Video throughput (read) : %i bytes/sec\n" - "Video throughput (write) : %i bytes/sec\n\n" - "Effective clockspeed : %iHz\n\n" - "Timer 0 frequency : %fHz\n\n" - "CPU time : %f%% (%f%%)\n" - -#ifdef USE_DYNAREC - "New blocks : %i\nOld blocks : %i\nRecompiled speed : %f MIPS\nAverage size : %f\n" - "Flushes : %i\nEvicted : %i\nReused : %i\nRemoved : %i" -#endif - ,mips, - flops, - segareads, - segawrites, - clockrate - scycles_lost, - pit_timer0_freq(), - ((double)main_time * 100.0) / status_diff, - ((double)main_time * 100.0) / timer_freq - -#ifdef USE_DYNAREC - , cpu_new_blocks_latched, cpu_recomp_blocks_latched, (double)cpu_recomp_ins_latched / 1000000.0, (double)cpu_recomp_ins_latched/cpu_recomp_blocks_latched, - cpu_recomp_flushes_latched, cpu_recomp_evicted_latched, - cpu_recomp_reuse_latched, cpu_recomp_removed_latched -#endif - ); - main_time = 0; - SendDlgItemMessage(hdlg, IDT_SDEVICE, WM_SETTEXT, - (WPARAM)NULL, (LPARAM)temp); - - temp[0] = 0; - device_add_status_info(temp, 4096); - SendDlgItemMessage(hdlg, IDT_STEXT, WM_SETTEXT, - (WPARAM)NULL, (LPARAM)temp); - return(TRUE); - - case WM_COMMAND: - switch (LOWORD(wParam)) { - case IDOK: - case IDCANCEL: - hwndStatus = NULL; - EndDialog(hdlg, 0); - return(TRUE); - } - break; - } - - return(FALSE); -} - - -void -dlg_status(void) -{ - HWND hwnd; - - hwnd = CreateDialog(plat_lang_dll(), (LPCSTR)DLG_STATUS, hwndMain, dlg_proc); - - ShowWindow(hwnd, SW_SHOW); -} - - -/* Tell the Status window to update. */ -void -dlg_status_update(void) -{ - SendMessage(hwndStatus, WM_USER, 0, 0); -} diff --git a/src/win/win_thread.c b/src/win/win_thread.c index a1af567..1107f93 100644 --- a/src/win/win_thread.c +++ b/src/win/win_thread.c @@ -8,7 +8,7 @@ * * Implement threads and mutexes for the Win32 platform. * - * Version: @(#)win_thread.c 1.0.5 2018/05/06 + * Version: @(#)win_thread.c 1.0.6 2018/10/05 * * Authors: Fred N. van Kempen, * Sarah Walker, @@ -55,7 +55,11 @@ typedef struct { thread_t * thread_create(void (*func)(void *param), void *param) { - return((thread_t *)_beginthread(func, 0, param)); + uintptr_t tid; + + tid = _beginthread(func, 0, param); + + return((thread_t *)tid); } @@ -85,7 +89,7 @@ thread_wait(thread_t *arg, int timeout) event_t * thread_create_event(void) { - win_event_t *ev = malloc(sizeof(win_event_t)); + win_event_t *ev = (win_event_t *)mem_alloc(sizeof(win_event_t)); ev->handle = CreateEvent(NULL, FALSE, FALSE, NULL); diff --git a/src/win/win_ui.c b/src/win/win_ui.c index 7fb19f5..3c8d2ce 100644 --- a/src/win/win_ui.c +++ b/src/win/win_ui.c @@ -8,7 +8,7 @@ * * Implement the user Interface module. * - * Version: @(#)win_ui.c 1.0.25 2018/05/27 + * Version: @(#)win_ui.c 1.0.26 2018/10/05 * * Authors: Fred N. van Kempen, * Miran Grca, @@ -56,6 +56,7 @@ #include "../devices/input/mouse.h" #include "../devices/video/video.h" #include "win.h" +#include "resource.h" #ifndef GWL_WNDPROC @@ -64,14 +65,14 @@ #define TIMER_1SEC 1 /* ID of the one-second timer */ +#define ICONS_MAX 256 /* number of icons we can cache */ /* Platform Public data, specific. */ HWND hwndMain = NULL, /* application main window */ hwndRender = NULL; /* machine render window */ -HICON hIcon[512]; /* icon data loaded from resources */ +HICON hIcon[ICONS_MAX]; /* icon data loaded from resources */ RECT oldclip; /* mouse rect */ -int infocus = 1; /* Local data. */ @@ -84,7 +85,9 @@ static HWND input_orig_hwnd = NULL, static HMENU menuMain = NULL, /* application menu bar */ menuSBAR = NULL, /* status bar menu bar */ *sb_menu = NULL; -static int sb_nparts; +static int sb_nparts = 0; +static const sbpart_t *sb_parts = NULL; +static int infocus = 1; static int hook_enabled = 0; static int save_window_pos = 0; static int cruft_x = 0, @@ -155,7 +158,7 @@ sb_dlg_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) /* Create and set up the Status Bar window. */ -void +static void StatusBarCreate(uintptr_t id) { int borders[3]; @@ -164,44 +167,17 @@ StatusBarCreate(uintptr_t id) RECT r; /* Load our icons into the cache for faster access. */ - for (i = 128; i < 130; i++) - hIcon[i] = LoadIconEx((PCTSTR)i); - for (i = 144; i < 146; i++) - hIcon[i] = LoadIconEx((PCTSTR)i); - for (i = 160; i < 162; i++) - hIcon[i] = LoadIconEx((PCTSTR)i); - for (i = 176; i < 178; i++) - hIcon[i] = LoadIconEx((PCTSTR)i); - for (i = 192; i < 194; i++) - hIcon[i] = LoadIconEx((PCTSTR)i); - for (i = 208; i < 210; i++) - hIcon[i] = LoadIconEx((PCTSTR)i); - for (i = 224; i < 226; i++) - hIcon[i] = LoadIconEx((PCTSTR)i); - for (i = 259; i < 260; i++) - hIcon[i] = LoadIconEx((PCTSTR)i); - for (i = 384; i < 386; i++) - hIcon[i] = LoadIconEx((PCTSTR)i); - for (i = 400; i < 402; i++) - hIcon[i] = LoadIconEx((PCTSTR)i); - for (i = 416; i < 418; i++) - hIcon[i] = LoadIconEx((PCTSTR)i); - for (i = 432; i < 434; i++) - hIcon[i] = LoadIconEx((PCTSTR)i); - for (i = 448; i < 450; i++) + for (i = 0; i < ICONS_MAX; i++) hIcon[i] = LoadIconEx((PCTSTR)i); GetWindowRect(hwndMain, &r); dw = r.right - r.left; dh = r.bottom - r.top; - /* Load the Common Controls DLL if needed. */ - InitCommonControls(); - - /* Create the window, and make sure it's using the STATUS class. */ - hwndSBAR = CreateWindow(STATUSCLASSNAME, + /* Create the window. */ + hwndSBAR = CreateWindow(STATUSCLASSNAME, NULL, - SBARS_SIZEGRIP|WS_CHILD|WS_VISIBLE|SBT_TOOLTIPS, + WS_CHILD|WS_VISIBLE|SBT_TOOLTIPS|SBARS_SIZEGRIP, 0, dh, dw, SB_HEIGHT, hwndMain, @@ -223,7 +199,7 @@ StatusBarCreate(uintptr_t id) SendMessage(hwndSBAR, SB_SETMINHEIGHT, (WPARAM)SB_HEIGHT, (LPARAM)0); /* Load the dummy menu for this window. */ - menuSBAR = LoadMenu(hInstance, SB_MENU_NAME); + menuSBAR = LoadMenu(hInstance, MENU_SB_NAME); /* Clear the menus, just in case.. */ sb_nparts = 0; @@ -231,13 +207,80 @@ StatusBarCreate(uintptr_t id) } +/* + * Calculate the edges of all status bar parts. + * + * We do it here, and in the platform module, because not all + * systems implement them the same way Microsoft did. For that + * reason, the UI code actually specifies widths for all the + * parts, which we "convert" here. + */ +static void +StatusBarResize(int w) +{ + int i, *edges; + int j, k, x; + int grippy; + + /* If no parts yet, bail out. */ + if (sb_nparts == 0) return; + + /* Create local 'edges' array and populate it. */ + edges = (int *)mem_alloc(sb_nparts * sizeof(int)); + memset(edges, 0x00, sb_nparts * sizeof(int)); + + /* If we have a grippy on the status bar... */ + //FIXME: how to determine this programmatically? --FvK + grippy = 8; + + /* + * We start at the leftmost edge of the window, and + * then move towards the right. The parameter given + * to Windows is the *right* side edge! + * + * No variable-part offset yet. + */ + k = x = 0; + for (i = 0; i < sb_nparts; i++) { + if (sb_parts[i].width == 0) { + /* + * This is the variable-length part, which + * extends to the right edge of the window. + * So, we must get the window length, and + * then calculate length for this part, and + * then the position for all parts following. + * + * First, see how much space we need for the + * parts following this one. + */ + k = w - x - grippy; + for (j = i + 1; j < sb_nparts; j++) + k -= sb_parts[j].width; + + /* OK, now we know how wide this part can be. */ + edges[i] = x + k; + } else { + x += sb_parts[i].width; + if (i == (sb_nparts - 1)) + x += grippy; + edges[i] = k + x; + } + } + + /* Send the list to the status bar window. */ + SendMessage(hwndSBAR, SB_SETPARTS, (WPARAM)sb_nparts, (LPARAM)edges); + + free(edges); +} + + static LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam) { BOOL bControlKeyDown; KBDLLHOOKSTRUCT *p; - if (nCode < 0 || nCode != HC_ACTION) + if (nCode < 0 || nCode != HC_ACTION || (!mouse_capture && !vid_fullscreen)) return(CallNextHookEx(hKeyboardHook, nCode, wParam, lParam)); p = (KBDLLHOOKSTRUCT*)lParam; @@ -301,28 +344,11 @@ MainWindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) /* Main Window. */ GetWindowRect(hwnd, &rect); + get_screen_size_natural(&x, &y); MoveWindow(hwnd, rect.left, rect.top, - unscaled_size_x + cruft_x, - unscaled_size_y + cruft_y + cruft_sb, - TRUE); - -#if 0 - /* Render window. */ - MoveWindow(hwndRender, 0, 0, - unscaled_size_x, - unscaled_size_y, + x + cruft_x, y + cruft_y + cruft_sb, TRUE); - /* Status bar. */ - GetWindowRect(hwndRender, &rect); - MoveWindow(hwndSBAR, - - if (mouse_capture) { - GetWindowRect(hwndRender, &rect); - - ClipCursor(&rect); - } -#endif break; case IDM_REMEMBER: @@ -369,6 +395,7 @@ MainWindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) /* Update the Status bar. */ MoveWindow(hwndSBAR, 0, scrnsz_y, scrnsz_x, cruft_sb, TRUE); + StatusBarResize(scrnsz_x); /* Update the renderer if needed. */ vidapi_resize(scrnsz_x, scrnsz_y); @@ -417,14 +444,14 @@ MainWindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) pc_onesec(); break; - case WM_RESETD3D: + case WM_RESET_D3D: plat_startblit(); vidapi_reset(); plat_endblit(); break; - case WM_LEAVEFULLSCREEN: - plat_setfullscreen(0); + case WM_LEAVE_FS: + ui_fullscreen(0); config_save(); break; @@ -440,15 +467,15 @@ MainWindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) PostQuitMessage(0); break; - case WM_SHOWSETTINGS: - plat_pause(1); + case WM_SHOW_CFG: + pc_pause(1); if (dlg_settings(1) == 2) pc_reset_hard_init(); - plat_pause(0); + pc_pause(0); break; case WM_PAUSE: - plat_pause(dopause ^ 1); + pc_pause(dopause ^ 1); menu_set_item(IDM_PAUSE, dopause); break; @@ -478,22 +505,107 @@ SubWindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) } -/* Initialize the Win32 User Interface module. */ +/* Catch WM_INPUT messages for 'current focus' window. */ +#ifdef __amd64__ +static LRESULT CALLBACK +#else +static BOOL CALLBACK +#endif +input_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + switch (message) { + case WM_INPUT: + keyboard_handle(lParam, infocus); + break; + + case WM_SETFOCUS: + infocus = 1; + if (! hook_enabled) { + hKeyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL, + LowLevelKeyboardProc, + GetModuleHandle(NULL), + 0); + hook_enabled = 1; + } + break; + + case WM_KILLFOCUS: + infocus = 0; + ui_mouse_capture(0); + if (hook_enabled) { + UnhookWindowsHookEx(hKeyboardHook); + hook_enabled = 0; + } + break; + + case WM_LBUTTONUP: + if (! vid_fullscreen) + ui_mouse_capture(1); + break; + + case WM_MBUTTONUP: + if (mouse_get_buttons() < 3) + ui_mouse_capture(0); + break; + + default: + return(CallWindowProc((WNDPROC)input_orig_proc, + hwnd, message, wParam, lParam)); + } + + return(0); +} + + +/* Set up a handler for the 'currently active' window. */ +void +plat_set_input(HWND h) +{ + /* If needed, rest the old one first. */ + if (input_orig_hwnd != NULL) { + SetWindowLongPtr(input_orig_hwnd, GWL_WNDPROC, + (LONG_PTR)input_orig_proc); + } + + /* Redirect the window procedure so we can catch WM_INPUT. */ + input_orig_proc = GetWindowLongPtr(h, GWLP_WNDPROC); + input_orig_hwnd = h; + SetWindowLongPtr(h, GWL_WNDPROC, (LONG_PTR)input_proc); +} + + +/* UI: reset the lowlevel (platform) UI. */ +void +ui_plat_reset(void) +{ + /* Load the main menu from the appropriate DLL. */ + menuMain = LoadMenu(plat_lang_dll(), MENU_MAIN_NAME); + + SetMenu(hwndMain, menuMain); + + /* Load the statusbar menu. */ + menuSBAR = LoadMenu(hInstance, MENU_SB_NAME); +} + + +/* UI: initialize the Win32 User Interface module. */ int ui_init(int nCmdShow) { WCHAR title[200]; WNDCLASSEX wincl; /* buffer for main window's class */ + INITCOMMONCONTROLSEX icex; /* common controls, new style */ RAWINPUTDEVICE ridev; /* RawInput device */ MSG messages; /* received-messages buffer */ HACCEL haccel; /* handle to accelerator table */ DWORD flags; int ret; -#if 0 - /* We should have an application-wide at_exit catcher. */ - atexit(plat_mouse_capture); -#endif + /* Register the new version of the Common Controls. */ + memset(&icex, 0x00, sizeof(INITCOMMONCONTROLSEX)); + icex.dwSize = sizeof(INITCOMMONCONTROLSEX); + icex.dwICC = ICC_LISTVIEW_CLASSES; + InitCommonControlsEx(&icex); if (settings_only) { if (! pc_init()) { @@ -513,8 +625,8 @@ ui_init(int nCmdShow) wincl.lpfnWndProc = MainWindowProcedure; wincl.style = CS_DBLCLKS; /* Catch double-clicks */ wincl.cbSize = sizeof(WNDCLASSEX); - wincl.hIcon = LoadIcon(hInstance, (LPCTSTR)100); - wincl.hIconSm = LoadIcon(hInstance, (LPCTSTR)100); + wincl.hIcon = LoadIcon(hInstance, (LPCTSTR)ICON_MAIN); + wincl.hIconSm = LoadIcon(hInstance, (LPCTSTR)ICON_MAIN); wincl.hCursor = NULL; wincl.lpszMenuName = NULL; wincl.cbClsExtra = 0; @@ -529,12 +641,6 @@ ui_init(int nCmdShow) if (! RegisterClassEx(&wincl)) return(2); - /* Load the Window Menu(s) from the resources. */ - menuMain = LoadMenu(plat_lang_dll(), MENU_NAME); - - /* Load the Languages into the current menu. */ - plat_lang_menu(); - /* Set up main window for resizing if configured. */ flags = WS_OVERLAPPEDWINDOW; if (! vid_resize) @@ -547,16 +653,16 @@ ui_init(int nCmdShow) * size (default 640x480), and we have no idea what * our window decorations are, size-wise. * - * Rather than depending on the GetSYstemMetrics API - * calls (which return incorrect data of Vista+), the - * simplest trick is to just set the desired window + * Rather than depending on the GetSystemMetrics API + * calls (which return incorrect data as of Vista+), + * the simplest trick is to just set the desired window * size, and create the window. The first WM_SIZE * message will indicate the client size left after * creating all the decorations, and the difference * is the decoration overhead ('cruft') we need to * always keep in mind when changing the window size. */ - wsprintf(title, L"%S", emu_version, sizeof_w(title)); + swprintf(title, sizeof_w(title), L"%s %s", EMU_NAME, emu_version); hwndMain = CreateWindow( CLASS_NAME, /* class name */ title, /* Title Text */ @@ -564,19 +670,22 @@ ui_init(int nCmdShow) CW_USEDEFAULT, CW_USEDEFAULT, /* no preset position */ scrnsz_x, scrnsz_y, /* window size in pixels */ HWND_DESKTOP, /* child of desktop */ - menuMain, /* menu */ + NULL, /* menu */ hInstance, /* Program Instance handler */ NULL); /* no Window Creation data */ + /* Create the status bar window. */ + StatusBarCreate(IDC_STATBAR); + ui_window_title(title); + /* Reset all menus to their defaults. */ + ui_reset(); + /* Move to the last-saved position if needed. */ if (window_remember) MoveWindow(hwndMain, window_x, window_y, window_w, window_h, FALSE); - /* Reset all menus to their defaults. */ - ui_menu_reset_all(); - /* Load the accelerator table */ haccel = LoadAccelerators(hInstance, ACCEL_NAME); if (haccel == NULL) { @@ -639,9 +748,6 @@ ui_init(int nCmdShow) if (hwndRender != NULL) MoveWindow(hwndRender, 0, 0, scrnsz_x, scrnsz_y, TRUE); - /* Create the status bar window. */ - StatusBarCreate(IDC_STATBAR); - /* Initialize the configured Video API. */ again: if (! vidapi_set(vid_api)) { @@ -655,8 +761,8 @@ again: * Inform the user, and ask if they want to reset * to the system default one instead. */ - _swprintf(title, get_string(IDS_ERR_NORENDR), - vidapi_internal_name(vid_api)); + swprintf(title, sizeof_w(title), + get_string(IDS_ERR_NORENDR), vidapi_internal_name(vid_api)); if (ui_msgbox(MBX_CONFIG, title) != 0) { /* Nope, they don't, so just exit. */ return(5); @@ -669,7 +775,7 @@ again: /* Initialize the rendering window, or fullscreen. */ if (start_in_fullscreen) - plat_setfullscreen(1); + ui_fullscreen(1); /* Initialize the mouse module. */ win_mouse_init(); @@ -678,7 +784,7 @@ again: pc_reset_hard(); /* Set the PAUSE mode depending on the renderer. */ - plat_pause(0); + pc_pause(0); /* * Everything has been configured, and all seems to work, @@ -709,20 +815,20 @@ again: if (mouse_capture && keyboard_ismsexit()) { /* Release the in-app mouse. */ - plat_mouse_capture(0); + ui_mouse_capture(0); } if (vid_fullscreen && keyboard_isfsexit()) { /* Signal "exit fullscreen mode". */ - /* pclog("leave full screen though key combination\n"); */ - plat_setfullscreen(0); + /* INFO("leave full screen though key combination\n"); */ + ui_fullscreen(0); } } timeEndPeriod(1); if (mouse_capture) - plat_mouse_capture(0); + ui_mouse_capture(0); /* Close down the emulator. */ plat_stop(); @@ -736,91 +842,7 @@ again: } -/* Catch WM_INPUT messages for 'current focus' window. */ -#ifdef __amd64__ -static LRESULT CALLBACK -#else -static BOOL CALLBACK -#endif -input_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) -{ - switch (message) { - case WM_INPUT: -#if defined(WALTJE) && defined(_DEBUG) && defined(USE_SDL) -pclog("UI: hwnd=%08lx WM_INPUT (infocus=%d) !\n", hwnd, infocus); -#endif - keyboard_handle(lParam, infocus); - break; - - case WM_SETFOCUS: -#if defined(WALTJE) && defined(_DEBUG) && defined(USE_SDL) -pclog("UI: hwnd=%08lx WM_SETFOCUS (infocus=%d) !\n", hwnd, infocus); -#endif - infocus = 1; - if (! hook_enabled) { - hKeyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL, - LowLevelKeyboardProc, - GetModuleHandle(NULL), - 0); - hook_enabled = 1; - } - break; - - case WM_KILLFOCUS: -#if defined(WALTJE) && defined(_DEBUG) && defined(USE_SDL) -pclog("UI: hwnd=%08lx WM_KILLFOCUS (infocus=%d) !\n", hwnd, infocus); -#endif - infocus = 0; - plat_mouse_capture(0); - if (hook_enabled) { - UnhookWindowsHookEx(hKeyboardHook); - hook_enabled = 0; - } - break; - - case WM_LBUTTONUP: -#if defined(WALTJE) && defined(_DEBUG) && defined(USE_SDL) -pclog("UI: hwnd=%08lx WM_LBUTTONUP (infocus=%d) !\n", hwnd, infocus); -#endif - if (! vid_fullscreen) - plat_mouse_capture(1); - break; - - case WM_MBUTTONUP: -#if defined(WALTJE) && defined(_DEBUG) && defined(USE_SDL) -pclog("UI: hwnd=%08lx WM_MBUTTONUP (infocus=%d) !\n", hwnd, infocus); -#endif - if (mouse_get_buttons() < 3) - plat_mouse_capture(0); - break; - - default: - return(CallWindowProc((WNDPROC)input_orig_proc, - hwnd, message, wParam, lParam)); - } - - return(0); -} - - -/* Set up a handler for the 'currently active' window. */ -void -plat_set_input(HWND h) -{ - /* If needed, rest the old one first. */ - if (input_orig_hwnd != NULL) { - SetWindowLongPtr(input_orig_hwnd, GWL_WNDPROC, - (LONG_PTR)input_orig_proc); - } - - /* Redirect the window procedure so we can catch WM_INPUT. */ - input_orig_proc = GetWindowLongPtr(h, GWLP_WNDPROC); - input_orig_hwnd = h; - SetWindowLongPtr(h, GWL_WNDPROC, (LONG_PTR)input_proc); -} - - -/* Tell the UI about a new screen resolution. */ +/* UI support: tell the UI about a new screen resolution. */ void ui_resize(int x, int y) { @@ -838,40 +860,7 @@ ui_resize(int x, int y) } -/* - * Re-load and reset the entire UI. - * - * This is needed after we change the language. - */ -void -ui_update(void) -{ - int i; - - /* Load the main menu from the appropriate DLL. */ - menuMain = LoadMenu(plat_lang_dll(), MENU_NAME); - SetMenu(hwndMain, menuMain); - - /* Load the statusbar menu. */ - menuSBAR = LoadMenu(hInstance, SB_MENU_NAME); - - /* Reset all main menu items. */ - ui_menu_reset_all(); - - /* Load the Languages into the current menu. */ - plat_lang_menu(); - - /* Update the statusbar menus. */ - ui_sb_update(); - - /* Reset the mouse-capture message. */ - i = mouse_capture; - mouse_capture = !mouse_capture; - plat_mouse_capture(i); -} - - -/* Update the application's title bar. */ +/* UI support: update the application's title bar. */ wchar_t * ui_window_title(const wchar_t *s) { @@ -891,7 +880,7 @@ ui_window_title(const wchar_t *s) } -/* Set cursor visible or not. */ +/* UI support: set cursor visible or not. */ void ui_show_cursor(int val) { @@ -912,7 +901,7 @@ ui_show_cursor(int val) } -/* Show or hide the render window. */ +/* UI support: show or hide the render window. */ void ui_show_render(int on) { @@ -927,124 +916,63 @@ ui_show_render(int on) /* Set the desired fullscreen/windowed mode. */ void -plat_setfullscreen(int on) +plat_fullscreen(int on) { - /* Want off and already off? */ - if (!on && !vid_fullscreen) return; - - /* Want on and already on? */ - if (on && vid_fullscreen) return; - - if (on && vid_fullscreen_first) { - vid_fullscreen_first = 0; - ui_msgbox(MBX_INFO, (wchar_t *)IDS_MSG_WINDOW); - } - - /* OK, claim the video. */ - plat_startblit(); - video_wait_for_blit(); - win_mouse_close(); - /* Close the current mode, and open the new one. */ - plat_vidapis[vid_api]->close(); - vid_fullscreen = on; - plat_vidapis[vid_api]->init(vid_fullscreen); - #ifdef USE_WX wx_set_fullscreen(on); #endif win_mouse_init(); - - /* Release video and make it redraw the screen. */ - plat_endblit(); - device_force_redraw(); - - /* Finally, handle the host's mouse cursor. */ - ui_show_cursor(vid_fullscreen ? 0 : -1); } -/* Pause or unpause the emulator. */ -void -plat_pause(int p) +/* Grab the current keyboard state. */ +int +plat_kbd_state(void) { - static wchar_t oldtitle[512]; - wchar_t title[512]; + BYTE kbdata[256]; + int ret = 0x00; - /* If un-pausing, as the renderer if that's OK. */ - if (p == 0) - p = vidapi_pause(); + /* Grab the system keyboard state. */ + memset(kbdata, 0x00, sizeof(kbdata)); + GetKeyboardState(kbdata); - /* If already so, done. */ - if (dopause == p) return; + /* Pick out the keys we are interested in. */ + if (kbdata[VK_NUMLOCK]) ret |= KBD_FLAG_NUM; + if (kbdata[VK_CAPITAL]) ret |= KBD_FLAG_CAPS; + if (kbdata[VK_SCROLL]) ret |= KBD_FLAG_SCROLL; + if (kbdata[VK_PAUSE]) ret |= KBD_FLAG_PAUSE; - if (p) { - wcscpy(oldtitle, ui_window_title(NULL)); - wcscpy(title, oldtitle); - wcscat(title, L" - PAUSED -"); - ui_window_title(title); - } else { - ui_window_title(oldtitle); - } - - dopause = p; - - /* Update the actual menu item. */ - menu_set_item(IDM_PAUSE, dopause); + return(ret); } -/* Enable or disable mouse clipping. */ +/* UI support: enable or disable mouse clipping. */ void plat_mouse_capture(int on) { - const wchar_t *str = NULL; RECT rect; - /* Do not try to capture the mouse if no mouse configured. */ - if (mouse_type == MOUSE_NONE) return; - - if ((on == -1) || (!on && mouse_capture)) { + if ((on == -1) || !on) { /* Disable the in-app mouse. */ if (on == -1) GetClipCursor(&oldclip); else ClipCursor(&oldclip); - - ui_show_cursor(-1); - - str = get_string(IDS_MSG_CAPTURE); - - /* We no longer have the mouse. */ - mouse_capture = 0; } else if (on && !mouse_capture) { /* Enable the in-app mouse. */ GetClipCursor(&oldclip); GetWindowRect(hwndRender, &rect); ClipCursor(&rect); - - ui_show_cursor(0); - - if (mouse_get_buttons() > 2) - str = get_string(IDS_MSG_MRLS_1); - else - str = get_string(IDS_MSG_MRLS_2); - - /* We got the mouse. */ - mouse_capture = 1; } - - /* Set the correct message on the status bar. */ - if (str != NULL) - ui_sb_text_set_w(str); } -/* Add an item to a menu. */ +/* UI support: add an item to a menu. */ void -menu_add_item(int idm, int new_id, const wchar_t *str) +menu_add_item(int idm, int type, int new_id, const wchar_t *str) { MENUITEMINFO info; HMENU menu; @@ -1054,22 +982,26 @@ menu_add_item(int idm, int new_id, const wchar_t *str) info.cbSize = sizeof(info); info.fMask = MIIM_SUBMENU; if (! GetMenuItemInfo(menuMain, idm, FALSE, &info)) { - pclog("UI: cannot find submenu %d\n", idm); + ERRLOG("UI: cannot find submenu %d\n", idm); return; } menu = info.hSubMenu; - if (new_id >= 0) - AppendMenu(menu, MF_STRING, new_id, str); - else - AppendMenu(menu, MF_SEPARATOR, 0, NULL); + switch(type) { + case ITEM_SEPARATOR: + AppendMenu(menu, MF_SEPARATOR, 0, NULL); + break; + + default: + AppendMenu(menu, MF_STRING, new_id, str); + } /* We changed the menu bar, so redraw it. */ DrawMenuBar(hwndMain); } -/* Enable or disable a menu item. */ +/* UI support: enable or disable a menu item. */ void menu_enable_item(int idm, int val) { @@ -1077,7 +1009,7 @@ menu_enable_item(int idm, int val) } -/* Set (check) or clear (uncheck) a menu item. */ +/* UI support: set/check a menu item. */ void menu_set_item(int idm, int val) { @@ -1085,7 +1017,7 @@ menu_set_item(int idm, int val) } -/* Set a radio group menu item. */ +/* UI support: set a radio group menu item. */ void menu_set_radio_item(int idm, int num, int val) { @@ -1100,25 +1032,9 @@ menu_set_radio_item(int idm, int num, int val) } -/* Initialize the status bar. */ -void -sb_setup(int parts, const int *widths) -{ - SendMessage(hwndSBAR, SB_SETPARTS, (WPARAM)parts, (LPARAM)widths); - - if (sb_menu != NULL) - sb_menu_destroy(); - - sb_menu = (HMENU *)malloc(parts * sizeof(HMENU)); - memset(sb_menu, 0x00, parts * sizeof(HMENU)); - - sb_nparts = parts; -} - - -/* Delete all menus from the status bar. */ -void -sb_menu_destroy(void) +/* UI support: delete all menus from the status bar. */ +static void +menu_destroy(void) { int i; @@ -1135,7 +1051,68 @@ sb_menu_destroy(void) } -/* Create a menu for a status bar part. */ +/* UI support: reset the status bar. */ +void +sb_setup(int nparts, const sbpart_t *data) +{ + RECT r; + + /* Set the info. */ + sb_nparts = nparts; + sb_parts = data; + + if (sb_menu != NULL) { + menu_destroy(); + } + + /* First, get width of the status bar window. */ + if (nparts > 0) { + /* Calculate and set up the parts. */ + GetWindowRect(hwndSBAR, &r); + StatusBarResize(r.right - r.left); + + /* Allocate and clear a new menu. */ + sb_menu = (HMENU *)mem_alloc(nparts * sizeof(HMENU)); + memset(sb_menu, 0x00, nparts * sizeof(HMENU)); + } +} + + +/* UI support: set the icon ID for a status bar field. */ +void +sb_set_icon(int part, int icon) +{ + HANDLE ptr; + + if (icon == 255) ptr = NULL; + else ptr = hIcon[(intptr_t)icon]; + + SendMessage(hwndSBAR, SB_SETICON, part, (LPARAM)ptr); +} + + +/* UI support: set a text label for a status bar field. */ +void +sb_set_text(int part, const wchar_t *str) +{ + int flags; + +// flags = (part < (sb_nparts - 2)) ? SBT_NOBORDERS : SBT_POPOUT; + flags = (part < (sb_nparts - 2)) ? SBT_NOBORDERS : 0; + + SendMessage(hwndSBAR, SB_SETTEXT, part | flags, (LPARAM)str); +} + + +/* UI support: set a tooltip for a status bar field. */ +void +sb_set_tooltip(int part, const wchar_t *str) +{ + SendMessage(hwndSBAR, SB_SETTIPTEXT, part, (LPARAM)str); +} + + +/* UI support: create a menu for a status bar part. */ void sb_menu_create(int part) { @@ -1147,7 +1124,7 @@ sb_menu_create(int part) } -/* Add an item to a (status bar) menu. */ +/* UI support: add an item to a (status bar) menu. */ void sb_menu_add_item(int part, int idm, const wchar_t *str) { @@ -1158,7 +1135,7 @@ sb_menu_add_item(int part, int idm, const wchar_t *str) } -/* Enable or disable a status bar menu item. */ +/* UI support: enable or disable a status bar menu item. */ void sb_menu_enable_item(int part, int idm, int val) { @@ -1167,38 +1144,9 @@ sb_menu_enable_item(int part, int idm, int val) } -/* Set or reset a status bar menu item. */ +/* UI support: set or reset a status bar menu item. */ void sb_menu_set_item(int part, int idm, int val) { CheckMenuItem(sb_menu[part], idm, val ? MF_CHECKED : MF_UNCHECKED); } - - -/* Set the icon ID for a status bar field. */ -void -sb_set_icon(int part, int icon) -{ - HANDLE ptr; - - if (icon == -1) ptr = NULL; - else ptr = hIcon[(intptr_t)icon]; - - SendMessage(hwndSBAR, SB_SETICON, part, (LPARAM)ptr); -} - - -/* Set a text label for a status bar field. */ -void -sb_set_text(int part, const wchar_t *str) -{ - SendMessage(hwndSBAR, SB_SETTEXT, part | SBT_NOBORDERS, (LPARAM)str); -} - - -/* Set a tooltip for a status bar field. */ -void -sb_set_tooltip(int part, const wchar_t *str) -{ - SendMessage(hwndSBAR, SB_SETTIPTEXT, part, (LPARAM)str); -}