diff --git a/.ci/AppImageBuilder.yml b/.ci/AppImageBuilder.yml
index be2a7f1c1..05a7b8fcb 100644
--- a/.ci/AppImageBuilder.yml
+++ b/.ci/AppImageBuilder.yml
@@ -72,19 +72,22 @@ AppDir:
files:
exclude:
- etc
- - lib/udev
- - opt/libc/usr/share
- - usr/[a-km-rt-zA-Z]*
- - usr/lib/*/libasound.so.*
- - usr/lib/*.a
- - usr/lib/cmake
- - usr/lib/pkgconfig
- - usr/s[a-gi-zA-Z]*
- - usr/share/[a-hj-ln-zA-Z]*
- - usr/share/i[a-bd-zA-Z]*
- - usr/share/m[a-df-zA-Z]*
- - usr/share/metainfo/*.metainfo.xml
+ - usr/[!ls]* # * except lib, local, share
+ - usr/lib/*/libasound.so.* # using our own ALSA can cause issues, and the API is pretty stable anyway
+ - usr/lib/*.a # produced by library compilation
+ - usr/lib/cmake # produced by library compilation
+ - usr/lib/pkgconfig # produced by library compilation
+ - usr/s[!h]* # s* except share
+ - usr/share/[!aim]* # * except applications, icons, metainfo
+ - usr/share/a[!p]* # a* except applications
+ - usr/share/ap[!p]* # ap* except applications
+ - usr/share/app[!l]* # app* except applications
+ - usr/share/i[!c]* # i* except icons
+ - usr/share/icons/[!h]* # * except hicolor
+ - usr/share/icons/h[!i]* # h* except hicolor
+ - usr/share/m[!e]* # m* except metainfo
+ - usr/share/metainfo/*.metainfo.xml # metainfo for libraries
- var
AppImage:
arch: !ENV '${arch_appimage}'
- file_name: '-n' # nasty hack to disable metainfo validation
+ file_name: !ENV '${appimage_path}'
diff --git a/.ci/build.sh b/.ci/build.sh
index 320451a83..38cd36c0c 100644
--- a/.ci/build.sh
+++ b/.ci/build.sh
@@ -136,6 +136,7 @@ package_name=
arch=
tarball_name=
skip_archive=0
+dep_report=0
strip=0
cmake_flags=
while [ $# -gt 0 ]
@@ -154,6 +155,11 @@ do
skip_archive=1
;;
+ -p)
+ shift
+ dep_report=1
+ ;;
+
-s)
shift
tarball_name="$1"
@@ -166,19 +172,23 @@ do
;;
*)
- if echo $1 | grep -q " "
- then
- cmake_flag="\"$1\""
- else
- cmake_flag="$1"
- fi
- if [ -z "$cmake_flags" ]
- then
- cmake_flags="$cmake_flag"
- else
- cmake_flags="$cmake_flags $cmake_flag"
- fi
- shift
+ # Consume remaining arguments as CMake flags.
+ while [ $# -gt 0 ]
+ do
+ if echo $1 | grep -q " "
+ then
+ cmake_flag="\"$1\""
+ else
+ cmake_flag="$1"
+ fi
+ if [ -z "$cmake_flags" ]
+ then
+ cmake_flags="$cmake_flag"
+ else
+ cmake_flags="$cmake_flags $cmake_flag"
+ fi
+ shift
+ done
;;
esac
done
@@ -545,8 +555,8 @@ then
# Switch into the correct architecture if required.
case $arch in
- x86_64*) arch_mac="i386";;
- *) arch_mac="$arch";;
+ x86_64*) arch_mac="i386"; arch_cmd="x86_64";;
+ *) arch_mac="$arch"; arch_cmd="$arch";;
esac
if [ "$(arch)" != "$arch" -a "$(arch)" != "$arch_mac" ]
then
@@ -556,7 +566,7 @@ then
args=
[ $strip -ne 0 ] && args="-t $args"
[ $skip_archive -ne 0 ] && args="-n $args"
- arch -"$arch" zsh -lc 'exec "'"$0"'" -b "'"$package_name"'" "'"$arch"'" '"$args""$cmake_flags"
+ arch -"$arch_cmd" zsh -lc 'exec "'"$0"'" -b "'"$package_name"'" "'"$arch"'" '"$args""$cmake_flags"
exit $?
fi
echo [-] Using architecture [$(arch)]
@@ -589,7 +599,21 @@ then
sudo sed -i -e 's/-no-feature-vulkan/-feature-vulkan/g' "$qt5_portfile"
sudo sed -i -e 's/configure.env-append MAKE=/configure.env-append VULKAN_SDK=${prefix} MAKE=/g' "$qt5_portfile"
fi
- sudo "$macports/bin/port" install $(cat .ci/dependencies_macports.txt)
+ while :
+ do
+ # Attempt to install dependencies.
+ sudo "$macports/bin/port" install $(cat .ci/dependencies_macports.txt) 2>&1 | tee macports.log
+
+ # Stop if no port version activation errors were found.
+ stuck_dep=$(grep " cannot be built while another version of " macports.log | cut -d" " -f10)
+ [ -z $stuck_dep ] && break
+
+ # Deactivate the stuck dependency and try again.
+ sudo "$macports/bin/port" -f deactivate $stuck_dep
+ done
+
+ # Remove MacPorts error detection log.
+ rm -f macports.log
# Save build tag to skip this later. Doing it here (once everything is
# in place) is important to avoid potential issues with retried builds.
@@ -609,6 +633,7 @@ else
# Establish general dependencies.
pkgs="cmake ninja-build pkg-config git wget p7zip-full extra-cmake-modules wayland-protocols tar gzip file appstream"
+ [ $dep_report -ne 0 ] && pkgs="$pkgs pax-utils"
if [ "$(dpkg --print-architecture)" = "$arch_deb" ]
then
pkgs="$pkgs build-essential"
@@ -957,7 +982,7 @@ else
sdl_ss=ON
fi
- # Build SDL2 with video systems (and some dependencies) only if the SDL interface is used.
+ # Build SDL2 with video systems (and dependencies) only if the SDL interface is used.
sdl_ui=OFF
grep -qiE "^QT:BOOL=ON" build/CMakeCache.txt || sdl_ui=ON
@@ -1024,11 +1049,18 @@ else
metainfo_base=archive_tmp/usr/share/metainfo
mkdir -p "$metainfo_base"
cp -p "src/unix/assets/$project_id."*".xml" "$metainfo_base/$project_id.appdata.xml"
+ applications_base=archive_tmp/usr/share/applications
+ mkdir -p "$applications_base"
+ cp -p "src/unix/assets/$project_id.desktop" "$applications_base/"
# Archive icons.
- icon_base=archive_tmp/usr/share/icons
- mkdir -p "$icon_base"
- cp -rp src/unix/assets/[0-9]*x[0-9]* "$icon_base/"
+ icon_base=archive_tmp/usr/share/icons/hicolor
+ for icon_size in src/unix/assets/[0-9]*x[0-9]*
+ do
+ icon_dir="$icon_base/$(basename "$icon_size")"
+ mkdir -p "$icon_dir"
+ cp -rp "$icon_size" "$icon_dir/apps"
+ done
project_icon=$(ls "$icon_base/"[0-9]*x[0-9]*/* | head -1 | grep -oP '/\K([^/]+)(?=\.[^\.]+$)')
# Archive executable, while also stripping it if requested.
@@ -1088,7 +1120,7 @@ else
# Generate modified AppImage metadata to suit build requirements.
cat << EOF > AppImageBuilder-generated.yml
-# This file is generated automatically by .ci/build.sh and will be
+# This file is automatically generated by .ci/build.sh and will be
# overwritten if edited. Please edit .ci/AppImageBuilder.yml instead.
EOF
while IFS= read line
@@ -1096,7 +1128,7 @@ EOF
# Skip blank or comment lines.
echo "$line" | grep -qE '^(#|$)' && continue
- # Parse "# if OPTION VALUE" condition lines.
+ # Parse "# if OPTION:TYPE=VALUE" CMake condition lines.
condition=$(echo "$line" | grep -oP '# if \K(.+)')
if [ -n "$condition" ]
then
@@ -1109,7 +1141,7 @@ EOF
done < .ci/AppImageBuilder.yml
# Download appimage-builder if necessary.
- appimage_builder_url="https://github.com/AppImageCrafters/appimage-builder/releases/download/v0.9.2/appimage-builder-0.9.2-35e3eab-x86_64.AppImage"
+ appimage_builder_url="https://github.com/AppImageCrafters/appimage-builder/releases/download/v1.1.0/appimage-builder-1.1.0-$(uname -m).AppImage"
appimage_builder_binary="$cache_dir/$(basename "$appimage_builder_url")"
if [ ! -e "$appimage_builder_binary" ]
then
@@ -1125,18 +1157,23 @@ EOF
ln -s "$cache_dir/appimage-builder-cache" appimage-builder-cache
# Run appimage-builder in extract-and-run mode for Docker compatibility.
+ # --appdir is a workaround for https://github.com/AppImageCrafters/appimage-builder/issues/270
project="$project" project_id="$project_id" project_version="$project_version" project_icon="$project_icon" arch_deb="$arch_deb" \
- arch_appimage="$arch_appimage" APPIMAGE_EXTRACT_AND_RUN=1 ./appimage-builder.AppImage --recipe AppImageBuilder-generated.yml
+ arch_appimage="$arch_appimage" appimage_path="$cwd/$package_name.AppImage" APPIMAGE_EXTRACT_AND_RUN=1 ./appimage-builder.AppImage \
+ --recipe AppImageBuilder-generated.yml --appdir "$(grep -oP '^\s+path: \K(.+)' AppImageBuilder-generated.yml)"
status=$?
- # Rename AppImage to the final name if the build succeeded.
- if [ $status -eq 0 ]
+ # Remove appimage-builder binary on failure, just in case it's corrupted.
+ [ $status -ne 0 ] && rm -f "$appimage_builder_binary"
+
+ # Generate library dependency report if requested.
+ if [ $dep_report -ne 0 ]
then
- mv "$project-"*".AppImage" "$cwd/$package_name.AppImage"
- status=$?
- else
- # Remove appimage-builder binary just in case it's corrupted.
- rm -f "$appimage_builder_binary"
+ echo '[-] Library dependency report:'
+
+ # Run lddtree with AppImage lib directories included in the search path.
+ LD_LIBRARY_PATH=$(find "$(pwd)/archive_tmp" -type d -name lib -o -name lib64 | while read dir; do find "$dir" -type d; done | tr '\n' ':') \
+ lddtree "archive_tmp/usr/local/bin/$project" 2>&1 | tee depreport.txt
fi
fi
diff --git a/src/cdrom/cdrom_image_viso.c b/src/cdrom/cdrom_image_viso.c
index 7d40deb26..9cac65b70 100644
--- a/src/cdrom/cdrom_image_viso.c
+++ b/src/cdrom/cdrom_image_viso.c
@@ -417,9 +417,36 @@ viso_fill_time(uint8_t *data, time_t time, int format, int longform)
{
uint8_t *p = data;
struct tm *time_s = localtime(&time);
- if (!time_s)
- fatal("VISO: localtime(%d) = NULL\n", time);
+ if (!time_s) {
+ /* localtime will return NULL if the time_t is negative (Windows)
+ or way too far into 64-bit space (Linux). Fall back to epoch. */
+ time_t epoch = 0;
+ time_s = localtime(&epoch);
+ if (!time_s)
+ fatal("VISO: localtime(0) = NULL\n");
+ /* Force year clamping if the timestamp is known to be outside the supported ranges. */
+ if (time < (longform ? -62135596800LL : -2208988800LL)) /* 0001-01-01 00:00:00 : 1900-01-01 00:00:00 */
+ time_s->tm_year = -1901;
+ else if (time > (longform ? 253402300799LL : 5869583999LL)) /* 9999-12-31 23:59:59 : 2155-12-31 23:59:59 */
+ time_s->tm_year = 8100;
+ }
+
+ /* Clamp year to the supported ranges, and assume the
+ OS returns valid numbers in the other struct fields. */
+ if (time_s->tm_year < (longform ? -1900 : 0)) {
+ time_s->tm_year = longform ? -1900 : 0;
+ time_s->tm_mon = time_s->tm_hour = time_s->tm_min = time_s->tm_sec = 0;
+ time_s->tm_mday = 1;
+ } else if (time_s->tm_year > (longform ? 8099 : 255)) {
+ time_s->tm_year = longform ? 8099 : 255;
+ time_s->tm_mon = 12;
+ time_s->tm_mday = 31;
+ time_s->tm_hour = 23;
+ time_s->tm_min = time_s->tm_sec = 59;
+ }
+
+ /* Convert timestamp. */
if (longform) {
p += sprintf((char *) p, "%04u%02u%02u%02u%02u%02u00",
1900 + time_s->tm_year, 1 + time_s->tm_mon, time_s->tm_mday,
@@ -443,10 +470,14 @@ viso_fill_dir_record(uint8_t *data, viso_entry_t *entry, int format, int type)
{
uint8_t *p = data, *q, *r;
- *p++ = 0; /* size (filled in later) */
- *p++ = 0; /* extended attribute length */
- VISO_SKIP(p, 8); /* sector offset */
- VISO_LBE_32(p, entry->stats.st_size); /* size (filled in later if this is a directory) */
+ *p++ = 0; /* size (filled in later) */
+ *p++ = 0; /* extended attribute length */
+ VISO_SKIP(p, 8); /* sector offset */
+ VISO_LBE_32(p, entry->stats.st_size); /* size (filled in later if this is a directory) */
+#ifdef _WIN32
+ if (entry->stats.st_mtime < 0)
+ pclog("VISO: Warning: Windows returned st_mtime %lld on file [%s]\n", (long long) entry->stats.st_mtime, entry->path);
+#endif
p += viso_fill_time(p, entry->stats.st_mtime, format, 0); /* time */
*p++ = S_ISDIR(entry->stats.st_mode) ? 0x02 : 0x00; /* flags */
@@ -848,7 +879,7 @@ viso_init(const char *dirname, int *error)
/* Handle file size and El Torito boot code. */
if (!S_ISDIR(entry->stats.st_mode)) {
- /* Limit to 4 GB - 1 byte. */
+ /* Clamp to 4 GB - 1 byte. */
if (entry->stats.st_size > ((uint32_t) -1))
entry->stats.st_size = (uint32_t) -1;
diff --git a/src/chipset/ali1543.c b/src/chipset/ali1543.c
index 04f3f70c8..02910ded8 100644
--- a/src/chipset/ali1543.c
+++ b/src/chipset/ali1543.c
@@ -751,9 +751,15 @@ ali5229_write(int func, int addr, uint8_t val, void *priv)
/* Bus Mastering Base Address */
case 0x20:
case 0x21:
- case 0x22:
- case 0x23:
- dev->ide_conf[addr] = val;
+ /* Datasheet erratum: the PCI BAR's actually have different sizes. */
+ if (addr == 0x20)
+ dev->ide_conf[addr] = (val & 0xe0) | 0x01;
+ else if ((addr & 0x43) == 0x00)
+ dev->ide_conf[addr] = (val & 0xf8) | 0x01;
+ else if ((addr & 0x43) == 0x40)
+ dev->ide_conf[addr] = (val & 0xfc) | 0x01;
+ else
+ dev->ide_conf[addr] = val;
ali5229_ide_handler(dev);
break;
@@ -1568,7 +1574,7 @@ ali1543_init(const device_t *info)
dev->offset = (info->local >> 8) & 0x7f;
if (info->local & 0x8000)
dev->offset = -dev->offset;
- pclog("Offset = %i\n", dev->offset);
+ ali1543_log("Offset = %i\n", dev->offset);
pci_enable_mirq(0);
pci_enable_mirq(1);
diff --git a/src/chipset/intel_piix.c b/src/chipset/intel_piix.c
index 8670de9e0..7347be38e 100644
--- a/src/chipset/intel_piix.c
+++ b/src/chipset/intel_piix.c
@@ -1697,6 +1697,20 @@ const device_t piix_device = {
.config = NULL
};
+const device_t piix_no_mirq_device = {
+ .name = "Intel 82371FB (PIIX) (No MIRQ)",
+ .internal_name = "piix_no_mirq",
+ .flags = DEVICE_PCI,
+ .local = 0x122e1101,
+ .init = piix_init,
+ .close = piix_close,
+ .reset = piix_reset,
+ { .available = NULL },
+ .speed_changed = piix_speed_changed,
+ .force_redraw = NULL,
+ .config = NULL
+};
+
const device_t piix_rev02_device = {
.name = "Intel 82371FB (PIIX) (Faulty BusMastering!!)",
.internal_name = "piix_rev02",
diff --git a/src/codegen/codegen_accumulate_x86-64.c b/src/codegen/codegen_accumulate_x86-64.c
index d2f1e0c3f..ceb751a95 100644
--- a/src/codegen/codegen_accumulate_x86-64.c
+++ b/src/codegen/codegen_accumulate_x86-64.c
@@ -47,8 +47,6 @@ void codegen_accumulate(int acc_reg, int delta)
void codegen_accumulate_flush(void)
{
- intptr_t rip;
-
if (acc_regs[0].count) {
/* To reduce the size of the generated code, we take advantage of
the fact that the target offset points to _cycles within cpu_state,
diff --git a/src/cpu/808x.c b/src/cpu/808x.c
index eed504196..f74fcda52 100644
--- a/src/cpu/808x.c
+++ b/src/cpu/808x.c
@@ -313,7 +313,7 @@ readmemw(uint32_t s, uint16_t a)
else {
wait(4, 1);
ret = read_mem_b(s + a);
- ret |= read_mem_b(s + (is186 ? (a + 1) : (a + 1) & 0xffff)) << 8;
+ ret |= read_mem_b(s + ((is186 && !is_nec) ? (a + 1) : (a + 1) & 0xffff)) << 8;
}
return ret;
@@ -385,7 +385,7 @@ writememw(uint32_t s, uint32_t a, uint16_t v)
else {
write_mem_b(addr, v & 0xff);
wait(4, 1);
- addr = s + (is186 ? (a + 1) : ((a + 1) & 0xffff));
+ addr = s + ((is186 && !is_nec) ? (a + 1) : ((a + 1) & 0xffff));
write_mem_b(addr, v >> 8);
}
@@ -794,7 +794,7 @@ seteaq(uint64_t val)
static void
push(uint16_t *val)
{
- if (is186 && SP == 1) {
+ if ((is186 && !is_nec) && (SP == 1)) {
writememw(ss - 1, 0, *val);
SP = cpu_state.eaaddr = 0xFFFF;
return;
@@ -963,7 +963,7 @@ interrupt(uint16_t addr)
pfq_clear();
ovr_seg = NULL;
access(39, 16);
- tempf = cpu_state.flags & (is_nec && cpu_state.inside_emulation_mode ? 0x8fd7 : 0x0fd7);
+ tempf = cpu_state.flags & ((is_nec && cpu_state.inside_emulation_mode) ? 0x8fd7 : 0x0fd7);
push(&tempf);
cpu_state.flags &= ~(I_FLAG | T_FLAG);
access(40, 16);
@@ -1405,8 +1405,7 @@ set_co_mul(int bits, int carry)
{
set_cf(carry);
set_of(carry);
- if (!is_nec)
- set_zf_ex(!carry);
+ set_zf_ex(!carry);
if (!carry)
wait(1, 0);
}
@@ -1653,7 +1652,8 @@ execx86(int cycs)
int8_t nibble_result_s;
uint16_t addr, tempw, new_cs, new_ip;
uint16_t tempw_int, size, tempbp, lowbound;
- uint16_t highbound, regval;
+ uint16_t highbound, regval, orig_sp, wordtopush;
+ uint16_t immediate, old_flags;
int bits;
uint32_t dest_seg, i, carry, nibble;
uint32_t srcseg, byteaddr;
@@ -1666,6 +1666,7 @@ execx86(int cycs)
if (!repeating) {
cpu_state.oldpc = cpu_state.pc;
opcode = pfq_fetchb();
+ handled = 0;
oldc = cpu_state.flags & C_FLAG;
if (clear_lock) {
in_lock = 0;
@@ -1678,6 +1679,97 @@ execx86(int cycs)
// pclog("[%04X:%04X] Opcode: %02X\n", CS, cpu_state.pc, opcode);
if (is186) {
switch (opcode) {
+ case 0x60: /*PUSHA/PUSH R*/
+ orig_sp = SP;
+ wait(1, 0);
+ push(&AX);
+ push(&CX);
+ push(&DX);
+ push(&BX);
+ push(&orig_sp);
+ push(&BP);
+ push(&SI);
+ push(&DI);
+ handled = 1;
+ break;
+ case 0x61: /*POPA/POP R*/
+ wait(9, 0);
+ DI = pop();
+ SI = pop();
+ BP = pop();
+ (void) pop(); /* former orig_sp */
+ BX = pop();
+ DX = pop();
+ CX = pop();
+ AX = pop();
+ handled = 1;
+ break;
+
+ case 0x62: /* BOUND r/m */
+ lowbound = 0;
+ highbound = 0;
+ regval = 0;
+ do_mod_rm();
+
+ lowbound = readmemw(easeg, cpu_state.eaaddr);
+ highbound = readmemw(easeg, cpu_state.eaaddr + 2);
+ regval = get_reg(cpu_reg);
+ if (lowbound > regval || highbound < regval) {
+ cpu_state.pc = cpu_state.oldpc;
+ interrupt(5);
+ }
+ handled = 1;
+ break;
+
+ case 0x64:
+ case 0x65:
+ if (is_nec) {
+ /* REPC/REPNC */
+ wait(1, 0);
+ in_rep = (opcode == 0x64 ? 1 : 2);
+ rep_c_flag = 1;
+ completed = 0;
+ handled = 1;
+ }
+ break;
+
+ case 0x68:
+ wordtopush = pfq_fetchw();
+ wait(1, 0);
+ push(&wordtopush);
+ handled = 1;
+ break;
+
+ case 0x69:
+ immediate = 0;
+ bits = 16;
+ do_mod_rm();
+ read_ea(0, 16);
+ immediate = pfq_fetchw();
+ mul(cpu_data & 0xFFFF, immediate);
+ set_reg(cpu_reg, cpu_data);
+ set_co_mul(16, cpu_dest != 0);
+ handled = 1;
+ break;
+
+ case 0x6a:
+ wordtopush = sign_extend(pfq_fetchb());
+ push(&wordtopush);
+ handled = 1;
+ break;
+
+ case 0x6b: /* IMUL reg16,reg16/mem16,imm8 */
+ immediate = 0;
+ bits = 16;
+ do_mod_rm();
+ read_ea(0, 16);
+ immediate = pfq_fetchb();
+ mul(cpu_data & 0xFFFF, immediate);
+ set_reg(cpu_reg, cpu_data);
+ set_co_mul(16, cpu_dest != 0);
+ handled = 1;
+ break;
+
case 0x6c:
case 0x6d: /* INM dst, DW/INS dst, DX */
bits = 8 << (opcode & 1);
@@ -1756,28 +1848,6 @@ execx86(int cycs)
handled = 1;
break;
- case 0xc9: /* LEAVE/DISPOSE */
- SP = BP;
- BP = pop();
- handled = 1;
- break;
-
- case 0x62: /* BOUND r/m */
- lowbound = 0;
- highbound = 0;
- regval = 0;
- do_mod_rm();
-
- lowbound = readmemw(easeg, cpu_state.eaaddr);
- highbound = readmemw(easeg, cpu_state.eaaddr + 2);
- regval = get_reg(cpu_reg);
- if (lowbound > regval || highbound < regval) {
- cpu_state.pc = cpu_state.oldpc;
- interrupt(5);
- }
- handled = 1;
- break;
-
case 0xc0:
case 0xc1: /*rot imm8 */
bits = 8 << (opcode & 1);
@@ -1867,6 +1937,12 @@ execx86(int cycs)
set_ea(cpu_data);
handled = 1;
break;
+
+ case 0xc9: /* LEAVE/DISPOSE */
+ SP = BP;
+ BP = pop();
+ handled = 1;
+ break;
}
}
if (!handled) {
@@ -1882,7 +1958,7 @@ execx86(int cycs)
case 0x0F:
case 0x17:
case 0x1F: /* POP seg */
- if (is_nec && opcode == 0x0F) {
+ if (is_nec && (opcode == 0x0F)) {
uint8_t orig_opcode = opcode;
opcode = pfq_fetchb();
switch (opcode) {
@@ -2422,34 +2498,8 @@ execx86(int cycs)
break;
case 0x60: /*JO alias*/
- if (is186) { /* PUSHA/PUSH R*/
- uint16_t orig_sp = SP;
- wait(1, 0);
- push(&AX);
- push(&CX);
- push(&DX);
- push(&BX);
- push(&orig_sp);
- push(&BP);
- push(&SI);
- push(&DI);
- } else
- jcc(opcode, cpu_state.flags & V_FLAG);
- break;
case 0x70: /*JO*/
case 0x61: /*JNO alias*/
- if (is186) { /* POPA/POP R*/
- wait(9, 0);
- DI = pop();
- SI = pop();
- BP = pop();
- (void) pop(); /* former orig_sp */
- BX = pop();
- DX = pop();
- CX = pop();
- AX = pop();
- break;
- }
case 0x71: /*JNO*/
jcc(opcode, cpu_state.flags & V_FLAG);
break;
@@ -2463,14 +2513,7 @@ execx86(int cycs)
case 0x74: /*JE*/
case 0x65: /*JNE alias*/
case 0x75: /*JNE*/
- if (is_nec && (opcode & 0xFE) == 0x64) {
- /* REPC/REPNC */
- wait(1, 0);
- in_rep = (opcode == 0x64 ? 1 : 2);
- rep_c_flag = 1;
- completed = 0;
- } else
- jcc(opcode, cpu_state.flags & Z_FLAG);
+ jcc(opcode, cpu_state.flags & Z_FLAG);
break;
case 0x66: /*JBE alias*/
case 0x76: /*JBE*/
@@ -2479,47 +2522,14 @@ execx86(int cycs)
jcc(opcode, cpu_state.flags & (C_FLAG | Z_FLAG));
break;
case 0x68: /*JS alias*/
- if (is186) { /* PUSH imm16 */
- uint16_t wordtopush = pfq_fetchw();
- wait(1, 0);
- push(&wordtopush);
- break;
- }
case 0x78: /*JS*/
case 0x69: /*JNS alias*/
- if (is186 && opcode == 0x69) { /* IMUL reg16,reg16/mem16,imm16 */
- uint16_t immediate = 0;
- bits = 16;
- do_mod_rm();
- read_ea(0, 16);
- immediate = pfq_fetchw();
- mul(cpu_data & 0xFFFF, immediate);
- set_reg(cpu_reg, cpu_data);
- set_co_mul(16, cpu_dest != 0);
- break;
- }
case 0x79: /*JNS*/
jcc(opcode, cpu_state.flags & N_FLAG);
break;
case 0x6A: /*JP alias*/
- if (is186) { /* PUSH imm8 */
- uint16_t wordtopush = sign_extend(pfq_fetchb());
- push(&wordtopush);
- break;
- }
case 0x7A: /*JP*/
case 0x6B: /*JNP alias*/
- if (is186 && opcode == 0x6B) { /* IMUL reg16,reg16/mem16,imm8 */
- uint16_t immediate = 0;
- bits = 16;
- do_mod_rm();
- read_ea(0, 16);
- immediate = pfq_fetchb();
- mul(cpu_data & 0xFFFF, immediate);
- set_reg(cpu_reg, cpu_data);
- set_co_mul(16, cpu_dest != 0);
- break;
- }
case 0x7B: /*JNP*/
jcc(opcode, cpu_state.flags & P_FLAG);
break;
@@ -2733,7 +2743,7 @@ execx86(int cycs)
break;
case 0x9C: /*PUSHF*/
access(33, 16);
- tempw = cpu_state.flags & (is_nec && cpu_state.inside_emulation_mode ? MD_FLAG | 0x0fd7 : 0x0fd7);
+ tempw = cpu_state.flags & ((is_nec && cpu_state.inside_emulation_mode) ? (MD_FLAG | 0x0fd7) : 0x0fd7);
push(&tempw);
break;
case 0x9D: /*POPF*/
@@ -3108,13 +3118,21 @@ execx86(int cycs)
case 0xD4: /*AAM*/
wait(1, 0);
- cpu_src = pfq_fetchb();
+ if (is_nec) {
+ (void) pfq_fetchb();
+ cpu_src = 10;
+ } else
+ cpu_src = pfq_fetchb();
if (x86_div(AL, 0))
set_pzs(16);
break;
case 0xD5: /*AAD*/
wait(1, 0);
- mul(pfq_fetchb(), AH);
+ if (is_nec) {
+ (void) pfq_fetchb();
+ mul(10, AH);
+ } else
+ mul(pfq_fetchb(), AH);
cpu_dest = AL;
cpu_src = cpu_data;
add(8);
@@ -3340,6 +3358,7 @@ execx86(int cycs)
break;
case 0x20: /* MUL */
case 0x28: /* IMUL */
+ old_flags = cpu_state.flags;
wait(1, 0);
mul(get_accum(bits), cpu_data);
if (opcode & 1) {
@@ -3354,12 +3373,14 @@ execx86(int cycs)
if (!is_nec)
cpu_data = AH;
}
- /* NOTE: When implementing the V20, care should be taken to not change
- the zero flag. */
set_sf(bits);
set_pf();
if (cpu_mod != 3)
wait(1, 0);
+ /* NOTE: When implementing the V20, care should be taken to not change
+ the zero flag. */
+ if (is_nec)
+ cpu_state.flags = (cpu_state.flags & ~Z_FLAG) | (old_flags & Z_FLAG);
break;
case 0x30: /* DIV */
case 0x38: /* IDIV */
diff --git a/src/cpu/cpu.c b/src/cpu/cpu.c
index 8bb61b81a..a2c06bc1f 100644
--- a/src/cpu/cpu.c
+++ b/src/cpu/cpu.c
@@ -367,7 +367,7 @@ cpu_set(void)
unmask_a20_in_smm = 0;
CPUID = cpu_s->cpuid_model;
- is8086 = (cpu_s->cpu_type > CPU_8088) && !(cpu_s->cpu_type == CPU_V20);
+ is8086 = (cpu_s->cpu_type > CPU_8088) && (cpu_s->cpu_type != CPU_V20) && (cpu_s->cpu_type != CPU_188);
is_nec = (cpu_s->cpu_type == CPU_V20) || (cpu_s->cpu_type == CPU_V30);
is186 = (cpu_s->cpu_type == CPU_186) || (cpu_s->cpu_type == CPU_188) || (cpu_s->cpu_type == CPU_V20) || (cpu_s->cpu_type == CPU_V30);
is286 = (cpu_s->cpu_type >= CPU_286);
diff --git a/src/cpu/cpu_table.c b/src/cpu/cpu_table.c
index 97e832ed1..0e805a702 100644
--- a/src/cpu/cpu_table.c
+++ b/src/cpu/cpu_table.c
@@ -165,7 +165,7 @@ const cpu_family_t cpu_families[] = {
{"", 0}
}
}, {
- .package = CPU_PKG_186,
+ .package = CPU_PKG_8086,
.manufacturer = "NEC",
.name = "V30",
.internal_name = "necv30",
diff --git a/src/device/keyboard_xt.c b/src/device/keyboard_xt.c
index 69720d9b1..2d78e1a74 100644
--- a/src/device/keyboard_xt.c
+++ b/src/device/keyboard_xt.c
@@ -72,7 +72,7 @@ typedef struct {
int blocked;
int tandy;
- uint8_t pa, pb, pd;
+ uint8_t pa, pb, pd, clock;
uint8_t key_waiting;
uint8_t type, pravetz_flags;
@@ -514,17 +514,22 @@ static void
kbd_write(uint16_t port, uint8_t val, void *priv)
{
xtkbd_t *kbd = (xtkbd_t *) priv;
- uint8_t bit, set;
+ uint8_t bit, set, new_clock;
switch (port) {
case 0x61: /* Keyboard Control Register (aka Port B) */
- if (!(kbd->pb & 0x40) && (val & 0x40)) {
- key_queue_start = key_queue_end = 0;
- kbd->want_irq = 0;
- kbd->blocked = 0;
- kbd_adddata(0xaa);
+ if (!(val & 0x80)) {
+ new_clock = !!(val & 0x40);
+ if (!kbd->clock && new_clock) {
+ key_queue_start = key_queue_end = 0;
+ kbd->want_irq = 0;
+ kbd->blocked = 0;
+ kbd_adddata(0xaa);
+ }
}
kbd->pb = val;
+ if (!(kbd->pb & 0x80))
+ kbd->clock = !!(kbd->pb & 0x40);
ppi.pb = val;
timer_process();
diff --git a/src/disk/hdc_ide.c b/src/disk/hdc_ide.c
index 7bf834a37..8cb9fd951 100644
--- a/src/disk/hdc_ide.c
+++ b/src/disk/hdc_ide.c
@@ -887,6 +887,9 @@ ide_atapi_attach(ide_t *ide)
ide->mdma_mode = (1 << ide->get_max(ide_boards[ide->board]->force_ata3 || !ide_bm[ide->board], TYPE_PIO));
ide->error = 1;
ide->cfg_spt = ide->cfg_hpc = 0;
+#ifndef EARLY_ATAPI
+ ide->sc->status = 0;
+#endif
}
void
@@ -1628,12 +1631,16 @@ ide_writeb(uint16_t addr, uint8_t val, void *priv)
double seek_time = hdd_timing_read(&hdd[ide->hdd_num], ide_get_sector(ide), sec_count);
double xfer_time = ide_get_xfer_time(ide, 512 * sec_count);
wait_time = seek_time > xfer_time ? seek_time : xfer_time;
- } else if (val == WIN_READ_MULTIPLE) {
- sec_count = (ide->secount < ide->blocksize) ? ide->secount : ide->blocksize;
+ } else if ((val == WIN_READ_MULTIPLE) && (ide->blocksize > 0)) {
+ sec_count = ide->secount ? ide->secount : 256;
+ if (sec_count > ide->blocksize)
+ sec_count = ide->blocksize;
double seek_time = hdd_timing_read(&hdd[ide->hdd_num], ide_get_sector(ide), sec_count);
double xfer_time = ide_get_xfer_time(ide, 512 * sec_count);
wait_time = seek_time + xfer_time;
- } else {
+ } else if ((val == WIN_READ_MULTIPLE) && (ide->blocksize == 0))
+ wait_time = 200.0;
+ else {
sec_count = 1;
double seek_time = hdd_timing_read(&hdd[ide->hdd_num], ide_get_sector(ide), sec_count);
double xfer_time = ide_get_xfer_time(ide, 512 * sec_count);
@@ -1684,9 +1691,10 @@ ide_writeb(uint16_t addr, uint8_t val, void *priv)
double wait_time = seek_time > xfer_time ? seek_time : xfer_time;
ide_set_callback(ide, wait_time);
} else if ((ide->type == IDE_HDD) && ((val == WIN_VERIFY) || (val == WIN_VERIFY_ONCE))) {
- double seek_time = hdd_timing_read(&hdd[ide->hdd_num], ide_get_sector(ide), ide->secount);
+ uint32_t sec_count = ide->secount ? ide->secount : 256;
+ double seek_time = hdd_timing_read(&hdd[ide->hdd_num], ide_get_sector(ide), sec_count);
ide_set_callback(ide, seek_time + ide_get_xfer_time(ide, 2));
- } else if (val == WIN_IDENTIFY)
+ } else if ((val == WIN_IDENTIFY) || (val == WIN_SET_FEATURES))
ide_callback(ide);
else
ide_set_callback(ide, 200.0 * IDE_TIME);
@@ -1854,7 +1862,9 @@ ide_read_data(ide_t *ide, int length)
ide->atastat = BSY_STAT | READY_STAT | DSC_STAT;
if (ide->command == WIN_READ_MULTIPLE) {
if (!ide->blockcount) {
- uint32_t sec_count = (ide->secount < ide->blocksize) ? ide->secount : ide->blocksize;
+ uint32_t sec_count = ide->secount ? ide->secount : 256;
+ if (sec_count > ide->blocksize)
+ sec_count = ide->blocksize;
double seek_time = hdd_timing_read(&hdd[ide->hdd_num], ide_get_sector(ide), sec_count);
double xfer_time = ide_get_xfer_time(ide, 512 * sec_count);
ide_set_callback(ide, seek_time + xfer_time);
@@ -2147,7 +2157,11 @@ ide_callback(void *priv)
ide_set_signature(ide);
if (ide->type == IDE_ATAPI) {
+#ifdef EARLY_ATAPI
ide->sc->status = DRDY_STAT | DSC_STAT;
+#else
+ ide->sc->status = 0;
+#endif
ide->sc->error = 1;
if (ide->device_reset)
ide->device_reset(ide->sc);
@@ -2443,6 +2457,8 @@ ide_callback(void *priv)
case WIN_SET_MULTIPLE_MODE:
if (ide->type == IDE_ATAPI)
goto abort_cmd;
+ if ((ide->secount < 2) || (ide->secount > hdd[ide->hdd_num].max_multiple_block))
+ goto abort_cmd;
ide->blocksize = ide->secount;
ide->atastat = DRDY_STAT | DSC_STAT;
ide_irq_raise(ide);
@@ -2787,6 +2803,8 @@ ide_board_setup(int board)
dev->error = 1;
if (dev->type != IDE_HDD)
dev->cfg_spt = dev->cfg_hpc = 0;
+ if (dev->type == IDE_HDD)
+ dev->blocksize = hdd[dev->hdd_num].max_multiple_block;
}
}
diff --git a/src/include/86box/chipset.h b/src/include/86box/chipset.h
index f7ae00f87..6cd49b2f1 100644
--- a/src/include/86box/chipset.h
+++ b/src/include/86box/chipset.h
@@ -91,6 +91,7 @@ extern const device_t sio_device;
extern const device_t sio_zb_device;
extern const device_t piix_device;
+extern const device_t piix_no_mirq_device;
extern const device_t piix_old_device;
extern const device_t piix_rev02_device;
extern const device_t piix3_device;
diff --git a/src/machine/m_amstrad.c b/src/machine/m_amstrad.c
index 63efbed50..023f94d5b 100644
--- a/src/machine/m_amstrad.c
+++ b/src/machine/m_amstrad.c
@@ -2410,6 +2410,7 @@ machine_amstrad_init(const machine_t *model, int type)
if (mouse_type == MOUSE_TYPE_INTERNAL) {
/* Tell mouse driver about our internal mouse. */
mouse_reset();
+ mouse_set_buttons(2);
mouse_set_poll(ms_poll, ams);
}
diff --git a/src/machine/m_at_socket5.c b/src/machine/m_at_socket5.c
index 3d233d41c..4e51acb47 100644
--- a/src/machine/m_at_socket5.c
+++ b/src/machine/m_at_socket5.c
@@ -265,7 +265,7 @@ machine_at_mb500n_init(const machine_t *model)
pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0);
device_add(&keyboard_ps2_pci_device);
device_add(&i430fx_device);
- device_add(&piix_device);
+ device_add(&piix_no_mirq_device);
device_add(&fdc37c665_device);
device_add(&intel_flash_bxt_device);
diff --git a/src/machine/m_at_socket7_3v.c b/src/machine/m_at_socket7_3v.c
index 2827c43ef..3a7505a38 100644
--- a/src/machine/m_at_socket7_3v.c
+++ b/src/machine/m_at_socket7_3v.c
@@ -287,8 +287,8 @@ machine_at_fmb_init(const machine_t *model)
pci_register_slot(0x11, PCI_CARD_NORMAL, 4, 3, 2, 1);
device_add(&i430fx_device);
- device_add(&piix_device);
- device_add(&keyboard_ps2_ami_pci_device);
+ device_add(&piix_no_mirq_device);
+ device_add(&keyboard_at_ami_device);
device_add(&w83787f_device);
device_add(&intel_flash_bxt_device);
diff --git a/src/machine/m_v86p.c b/src/machine/m_v86p.c
index 4642d6b80..5f115dab3 100644
--- a/src/machine/m_v86p.c
+++ b/src/machine/m_v86p.c
@@ -42,6 +42,7 @@
#include <86box/fdd.h>
#include <86box/fdc.h>
#include <86box/fdc_ext.h>
+#include <86box/hdc.h>
#include <86box/keyboard.h>
#include <86box/chipset.h>
#include <86box/sio.h>
@@ -92,5 +93,8 @@ machine_v86p_init(const machine_t *model)
if (gfxcard == VID_INTERNAL)
device_add(&f82c425_video_device);
+ if (hdc_current <= 1)
+ device_add(&st506_xt_victor_v86p_device);
+
return ret;
}
diff --git a/src/machine/m_xt_olivetti.c b/src/machine/m_xt_olivetti.c
index 1d53a588e..014b13d12 100644
--- a/src/machine/m_xt_olivetti.c
+++ b/src/machine/m_xt_olivetti.c
@@ -8,7 +8,7 @@
*
* Emulation of the Olivetti XT-compatible machines.
*
- *
+ * - Supports MM58174 real-time clock emulation
*
* Authors: Sarah Walker,
* Miran Grca,
@@ -69,6 +69,28 @@
#define CGA_RGB 0
#define CGA_COMPOSITE 1
+enum MM58174_ADDR {
+ /* Registers */
+ MM58174_TEST, /* TEST register, write only */
+ MM58174_TENTHS, /* Tenths of second, read only */
+ MM58174_SECOND1, /* Units of seconds, read only */
+ MM58174_SECOND10, /* Tens of seconds, read only */
+ MM58174_MINUTE1,
+ MM58174_MINUTE10,
+ MM58174_HOUR1,
+ MM58174_HOUR10,
+ MM58174_DAY1,
+ MM58174_DAY10,
+ MM58174_WEEKDAY,
+ MM58174_MONTH1,
+ MM58174_MONTH10,
+ MM58174_LEAPYEAR, /* Leap year status, write only */
+ MM58174_RESET, /* RESET register, write only */
+ MM58174_IRQ /* Interrupt register, read / write */
+};
+
+static struct tm intclk;
+
typedef struct {
/* Keyboard stuff. */
int wantirq;
@@ -120,6 +142,170 @@ m24_log(const char *fmt, ...)
# define m24_log(fmt, ...)
#endif
+/* Set the chip time. */
+static void
+mm58174_time_set(uint8_t *regs, struct tm *tm)
+{
+ regs[MM58174_SECOND1] = (tm->tm_sec % 10);
+ regs[MM58174_SECOND10] = (tm->tm_sec / 10);
+ regs[MM58174_MINUTE1] = (tm->tm_min % 10);
+ regs[MM58174_MINUTE10] = (tm->tm_min / 10);
+ regs[MM58174_HOUR1] = (tm->tm_hour % 10);
+ regs[MM58174_HOUR10] = (tm->tm_hour / 10);
+ regs[MM58174_WEEKDAY] = (tm->tm_wday + 1);
+ regs[MM58174_DAY1] = (tm->tm_mday % 10);
+ regs[MM58174_DAY10] = (tm->tm_mday / 10);
+ regs[MM58174_MONTH1] = ((tm->tm_mon + 1) % 10);
+ regs[MM58174_MONTH10] = ((tm->tm_mon + 1) / 10);
+ /* MM87174 does not store the year, M24 uses the IRQ register to count 8 years from leap year */
+ regs[MM58174_IRQ] = ((tm->tm_year + 1900) % 8);
+ regs[MM58174_LEAPYEAR] = 8 >> ((regs[MM58174_IRQ] & 0x07) & 0x03);
+}
+
+/* Get the chip time. */
+#define nibbles(a) (regs[(a##1)] + 10 * regs[(a##10)])
+static void
+mm58174_time_get(uint8_t *regs, struct tm *tm)
+{
+ tm->tm_sec = nibbles(MM58174_SECOND);
+ tm->tm_min = nibbles(MM58174_MINUTE);
+ tm->tm_hour = nibbles(MM58174_HOUR);
+ tm->tm_wday = (regs[MM58174_WEEKDAY] - 1);
+ tm->tm_mday = nibbles(MM58174_DAY);
+ tm->tm_mon = (nibbles(MM58174_MONTH) - 1);
+ /* MM87174AN does not store the year */
+ tm->tm_year = (1984 + (regs[MM58174_IRQ] & 0x07) - 1900);
+}
+
+/* One more second has passed, update the internal clock. */
+static void
+mm58174_recalc()
+{
+ /* Ping the internal clock. */
+ if (++intclk.tm_sec == 60) {
+ intclk.tm_sec = 0;
+ if (++intclk.tm_min == 60) {
+ intclk.tm_min = 0;
+ if (++intclk.tm_hour == 24) {
+ intclk.tm_hour = 0;
+ if (++intclk.tm_mday == (nvr_get_days(intclk.tm_mon, intclk.tm_year) + 1)) {
+ intclk.tm_mday = 1;
+ if (++intclk.tm_mon == 13) {
+ intclk.tm_mon = 1;
+ intclk.tm_year++;
+ }
+ }
+ }
+ }
+ }
+}
+
+/* This is called every second through the NVR/RTC hook. */
+static void
+mm58174_tick(nvr_t *nvr)
+{
+ mm58174_recalc();
+ mm58174_time_set(nvr->regs, &intclk);
+}
+
+static void
+mm58174_start(nvr_t *nvr)
+{
+ struct tm tm;
+
+ /* Initialize the internal and chip times. */
+ if (time_sync & TIME_SYNC_ENABLED) {
+ /* Use the internal clock's time. */
+ nvr_time_get(&tm);
+ mm58174_time_set(nvr->regs, &tm);
+ } else {
+ /* Set the internal clock from the chip time. */
+ mm58174_time_get(nvr->regs, &tm);
+ nvr_time_set(&tm);
+ }
+ mm58174_time_get(nvr->regs, &intclk);
+}
+
+/* Write to one of the chip registers. */
+static void
+mm58174_write(uint16_t addr, uint8_t val, void *priv)
+{
+ nvr_t *nvr = (nvr_t *) priv;
+
+ addr &= 0x0f;
+ val &= 0x0f;
+
+ /* Update non-read-only changed values if not synchronizing time to host */
+ if ((addr != MM58174_TENTHS) && (addr != MM58174_SECOND1) && (addr != MM58174_SECOND10))
+ if ((nvr->regs[addr] != val) && !(time_sync & TIME_SYNC_ENABLED))
+ nvr_dosave = 1;
+
+ if ((addr == MM58174_RESET) && (val & 0x01)) {
+ /* When timer starts, MM58174 sets seconds and tenths of second to 0 */
+ nvr->regs[MM58174_TENTHS] = 0;
+ if (!(time_sync & TIME_SYNC_ENABLED)) {
+ /* Only set seconds to 0 if not synchronizing time to host clock */
+ nvr->regs[MM58174_SECOND1] = 0;
+ nvr->regs[MM58174_SECOND10] = 0;
+ }
+ }
+
+ /* Store the new value */
+ nvr->regs[addr] = val;
+
+ /* Update internal clock with MM58174 time */
+ mm58174_time_get(nvr->regs, &intclk);
+}
+
+/* Read from one of the chip registers. */
+static uint8_t
+mm58174_read(uint16_t addr, void *priv)
+{
+ nvr_t *nvr = (nvr_t *) priv;
+
+ addr &= 0x0f;
+
+ /* Set IRQ control bit to 0 upon read */
+ if (addr == 0x0f)
+ nvr->regs[addr] &= 0x07;
+
+ /* Grab and return the desired value */
+ return (nvr->regs[addr]);
+}
+
+/* Reset the MM58174 to a default state. */
+static void
+mm58174_reset(nvr_t *nvr)
+{
+ /* Clear the NVRAM. */
+ memset(nvr->regs, 0xff, nvr->size);
+
+ /* Reset the RTC registers. */
+ memset(nvr->regs, 0x00, 16);
+ nvr->regs[MM58174_WEEKDAY] = 0x01;
+ nvr->regs[MM58174_DAY1] = 0x01;
+ nvr->regs[MM58174_MONTH1] = 0x01;
+}
+
+static void
+mm58174_init(nvr_t *nvr, int size)
+{
+ /* This is machine specific. */
+ nvr->size = size;
+ nvr->irq = -1;
+
+ /* Set up any local handlers here. */
+ nvr->reset = mm58174_reset;
+ nvr->start = mm58174_start;
+ nvr->tick = mm58174_tick;
+
+ /* Initialize the actual NVR. */
+ nvr_init(nvr);
+
+ io_sethandler(0x0070, 16,
+ mm58174_read, NULL, NULL, mm58174_write, NULL, NULL, nvr);
+}
+
static void
m24_kbd_poll(void *priv)
{
@@ -426,6 +612,7 @@ m24_kbd_init(m24_kbd_t *kbd)
/* Tell mouse driver about our internal mouse. */
mouse_reset();
+ mouse_set_buttons(2);
mouse_set_poll(ms_poll, kbd);
keyboard_set_table(scancode_xt);
@@ -667,7 +854,7 @@ m24_read(uint16_t port, void *priv)
ret |= 0x1;
break;
case 256:
- ret |= 0x2 | 0x80;
+ ret |= 0x2;
break;
case 384:
ret |= 0x1 | 0x2 | 0x80;
@@ -676,10 +863,12 @@ m24_read(uint16_t port, void *priv)
ret |= 0x8;
break;
case 640:
- default:
ret |= 0x1 | 0x8 | 0x80;
break;
+ default:
+ break;
}
+ break;
/*
* port 67:
* DIPSW-1 on mainboard (off=present=1)
@@ -721,6 +910,8 @@ m24_read(uint16_t port, void *priv)
/* Switch 2 - Set fast startup */
ret |= 0x2;
+
+ break;
}
return (ret);
@@ -731,6 +922,7 @@ machine_xt_m24_init(const machine_t *model)
{
int ret;
m24_kbd_t *m24_kbd;
+ nvr_t *nvr;
ret = bios_load_interleaved("roms/machines/m24/olivetti_m24_bios_version_1.44_low_even.bin",
"roms/machines/m24/olivetti_m24_bios_version_1.44_high_odd.bin",
@@ -751,13 +943,18 @@ machine_xt_m24_init(const machine_t *model)
/* Address 66-67 = mainboard dip-switch settings */
io_sethandler(0x0066, 2, m24_read, NULL, NULL, NULL, NULL, NULL, NULL);
- /* FIXME: make sure this is correct?? */
- device_add(&at_nvr_device);
-
standalone_gameport_type = &gameport_device;
nmi_init();
+ /* Allocate an NVR for this machine. */
+ nvr = (nvr_t *) malloc(sizeof(nvr_t));
+ if (nvr == NULL)
+ return (0);
+ memset(nvr, 0x00, sizeof(nvr_t));
+
+ mm58174_init(nvr, model->nvrmask + 1);
+
video_reset(gfxcard);
if (gfxcard == VID_INTERNAL)
diff --git a/src/machine/m_xt_t1000.c b/src/machine/m_xt_t1000.c
index 3b45dcdcb..c467b1c91 100644
--- a/src/machine/m_xt_t1000.c
+++ b/src/machine/m_xt_t1000.c
@@ -103,6 +103,7 @@
#include <86box/fdd.h>
#include <86box/fdc.h>
#include <86box/gameport.h>
+#include <86box/hdc.h>
#include <86box/video.h>
#include <86box/plat.h>
#include <86box/machine.h>
@@ -959,6 +960,9 @@ machine_xt_t1200_init(const machine_t *model)
if (gfxcard == VID_INTERNAL)
device_add(&t1200_video_device);
+ if (hdc_current <= 1)
+ device_add(&st506_xt_victor_v86p_device);
+
return ret;
}
diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c
index 729935e4b..52be7a08a 100644
--- a/src/machine/machine_table.c
+++ b/src/machine/machine_table.c
@@ -2066,7 +2066,7 @@ const machine_t machines[] = {
.max_multi = 0
},
.bus_flags = MACHINE_PC,
- .flags = MACHINE_VIDEO,
+ .flags = MACHINE_VIDEO | MACHINE_MFM,
.ram = {
.min = 512,
.max = 1024,
@@ -2102,7 +2102,7 @@ const machine_t machines[] = {
.max_multi = 0
},
.bus_flags = MACHINE_PC,
- .flags = MACHINE_VIDEO,
+ .flags = MACHINE_VIDEO | MACHINE_MFM,
.ram = {
.min = 1024,
.max = 2048,
@@ -8263,7 +8263,7 @@ const machine_t machines[] = {
.min_multi = 1.5,
.max_multi = 3.0
},
- .bus_flags = MACHINE_PS2_PCI,
+ .bus_flags = MACHINE_PCI,
.flags = MACHINE_IDE_DUAL,
.ram = {
.min = 8192,
diff --git a/src/nvr_at.c b/src/nvr_at.c
index d839295ba..174cd74e4 100644
--- a/src/nvr_at.c
+++ b/src/nvr_at.c
@@ -1247,29 +1247,31 @@ const device_t piix4_nvr_device = {
};
const device_t ps_no_nmi_nvr_device = {
- "PS/1 or PS/2 NVRAM (No NMI)",
- "ps1_nvr",
- DEVICE_PS2,
- 10,
- nvr_at_init,
- nvr_at_close,
- nvr_at_reset,
- { NULL },
- nvr_at_speed_changed,
- NULL
+ .name = "PS/1 or PS/2 NVRAM (No NMI)",
+ .internal_name = "ps1_nvr",
+ .flags = DEVICE_PS2,
+ .local = 0x10 | 2,
+ .init = nvr_at_init,
+ .close = nvr_at_close,
+ .reset = nvr_at_reset,
+ { .available = NULL },
+ .speed_changed = nvr_at_speed_changed,
+ .force_redraw = NULL,
+ .config = NULL
};
const device_t amstrad_no_nmi_nvr_device = {
- "Amstrad NVRAM (No NMI)",
- "amstrad_nvr",
- DEVICE_ISA | DEVICE_AT,
- 11,
- nvr_at_init,
- nvr_at_close,
- nvr_at_reset,
- { NULL },
- nvr_at_speed_changed,
- NULL
+ .name = "Amstrad NVRAM (No NMI)",
+ .internal_name = "amstrad_nvr",
+ .flags = DEVICE_ISA | DEVICE_AT,
+ .local = 0x10 | 3,
+ .init = nvr_at_init,
+ .close = nvr_at_close,
+ .reset = nvr_at_reset,
+ { .available = NULL },
+ .speed_changed = nvr_at_speed_changed,
+ .force_redraw = NULL,
+ .config = NULL
};
const device_t ami_1992_nvr_device = {
diff --git a/src/qt/qt_mainwindow.cpp b/src/qt/qt_mainwindow.cpp
index fd2294415..2a41f4316 100644
--- a/src/qt/qt_mainwindow.cpp
+++ b/src/qt/qt_mainwindow.cpp
@@ -1620,7 +1620,18 @@ void MainWindow::keyPressEvent(QKeyEvent* event)
if (send_keyboard_input && !(kbd_req_capture && !mouse_capture && !video_fullscreen))
{
// Windows keys in Qt have one-to-one mapping.
- if (event->key() == Qt::Key_Super_L || event->key() == Qt::Key_Super_R) {
+ if (event->key() == Qt::Key_Pause && !keyboard_recv(0x38) && !keyboard_recv(0x138)) {
+ if ((keyboard_recv(0x1D) || keyboard_recv(0x11D))) {
+ keyboard_input(1, 0x46);
+ } else {
+ keyboard_input(0, 0xE1);
+ keyboard_input(0, 0x1D);
+ keyboard_input(0, 0x45);
+ keyboard_input(0, 0xE1);
+ keyboard_input(1, 0x1D);
+ keyboard_input(1, 0x45);
+ }
+ } else if (event->key() == Qt::Key_Super_L || event->key() == Qt::Key_Super_R) {
keyboard_input(1, event->key() == Qt::Key_Super_L ? 0x15B : 0x15C);
} else
#ifdef Q_OS_MACOS
@@ -1637,6 +1648,12 @@ void MainWindow::keyPressEvent(QKeyEvent* event)
if (keyboard_ismsexit()) {
plat_mouse_capture(0);
}
+
+ if ((video_fullscreen > 0) && (keyboard_recv(0x1D) || keyboard_recv(0x11D))) {
+ if (keyboard_recv(0x57)) ui->actionTake_screenshot->trigger();
+ else if (keyboard_recv(0x58)) pc_send_cad();
+ }
+
event->accept();
}
@@ -1651,6 +1668,11 @@ void MainWindow::blitToWidget(int x, int y, int w, int h, int monitor_index)
void MainWindow::keyReleaseEvent(QKeyEvent* event)
{
+ if (event->key() == Qt::Key_Pause) {
+ if (keyboard_recv(0x38) && keyboard_recv(0x138)) {
+ plat_pause(dopause ^ 1);
+ }
+ }
if (!send_keyboard_input)
return;
diff --git a/src/qt/qt_mediamenu.cpp b/src/qt/qt_mediamenu.cpp
index d11a14c96..bea1af22f 100644
--- a/src/qt/qt_mediamenu.cpp
+++ b/src/qt/qt_mediamenu.cpp
@@ -19,13 +19,15 @@
* Copyright 2021-2022 Teemu Korhonen
*/
#include "qt_mediamenu.hpp"
-
+#include "qt_progsettings.hpp"
#include "qt_machinestatus.hpp"
#include
#include
#include
#include
+#include
+#include
extern "C" {
#include <86box/86box.h>
@@ -123,10 +125,10 @@ void MediaMenu::refresh(QMenu *parentMenu) {
MachineStatus::iterateCDROM([this, parentMenu](int i) {
auto* menu = parentMenu->addMenu("");
cdromMutePos = menu->children().count();
- menu->addAction(tr("&Mute"), [this, i]() { cdromMute(i); })->setCheckable(true);
+ menu->addAction(QApplication::style()->standardIcon(QStyle::SP_MediaVolumeMuted), tr("&Mute"), [this, i]() { cdromMute(i); })->setCheckable(true);
menu->addSeparator();
- menu->addAction(tr("&Image..."), [this, i]() { cdromMount(i, 0); })->setCheckable(false);
- menu->addAction(tr("&Folder..."), [this, i]() { cdromMount(i, 1); })->setCheckable(false);
+ menu->addAction(ProgSettings::loadIcon("/cdrom.ico"), tr("&Image..."), [this, i]() { cdromMount(i, 0); })->setCheckable(false);
+ menu->addAction(QApplication::style()->standardIcon(QStyle::SP_DirIcon), tr("&Folder..."), [this, i]() { cdromMount(i, 1); })->setCheckable(false);
menu->addSeparator();
for (int slot = 0; slot < MAX_PREV_IMAGES; slot++) {
cdromImageHistoryPos[slot] = menu->children().count();
@@ -478,8 +480,9 @@ void MediaMenu::cdromReload(int index, int slot) {
void MediaMenu::updateImageHistory(int index, int slot, ui::MediaType type) {
QMenu* menu;
QAction* imageHistoryUpdatePos;
- QString image_path;
QObjectList children;
+ QFileInfo fi;
+ QIcon menu_icon;
switch (type) {
case ui::MediaType::Optical:
@@ -488,7 +491,9 @@ void MediaMenu::updateImageHistory(int index, int slot, ui::MediaType type) {
menu = cdromMenus[index];
children = menu->children();
imageHistoryUpdatePos = dynamic_cast(children[cdromImageHistoryPos[slot]]);
- image_path = mhm.getImageForSlot(index, slot, type);
+ fi.setFile(mhm.getImageForSlot(index, slot, type));
+ menu_icon = fi.isDir() ? QApplication::style()->standardIcon(QStyle::SP_DirIcon) : ProgSettings::loadIcon("/cdrom.ico");
+ imageHistoryUpdatePos->setIcon(menu_icon);
break;
case ui::MediaType::Floppy:
if (!floppyMenus.contains(index))
@@ -496,15 +501,15 @@ void MediaMenu::updateImageHistory(int index, int slot, ui::MediaType type) {
menu = floppyMenus[index];
children = menu->children();
imageHistoryUpdatePos = dynamic_cast(children[floppyImageHistoryPos[slot]]);
- image_path = mhm.getImageForSlot(index, slot, type);
+ fi.setFile(mhm.getImageForSlot(index, slot, type));
break;
default:
pclog("History not yet implemented for media type %s\n", qPrintable(mhm.mediaTypeToString(type)));
return;
}
- QFileInfo fi(image_path);
- imageHistoryUpdatePos->setText(QString::asprintf(tr("%s").toUtf8().constData(), fi.fileName().isEmpty() ? tr("previous image").toUtf8().constData() : fi.fileName().toUtf8().constData()));
+ QString menu_item_name = fi.fileName().isEmpty() ? tr("previous image").toUtf8().constData() : fi.fileName().toUtf8().constData();
+ imageHistoryUpdatePos->setText(QString::asprintf(tr("%s").toUtf8().constData(), menu_item_name.toUtf8().constData()));
imageHistoryUpdatePos->setVisible(!fi.fileName().isEmpty());
}
@@ -527,7 +532,10 @@ void MediaMenu::cdromUpdateMenu(int i) {
auto* imageMenu = dynamic_cast(childs[cdromImagePos]);
imageMenu->setEnabled(!name.isEmpty());
- imageMenu->setText(QString::asprintf(tr("Eject %s").toUtf8().constData(), name.isEmpty() ? QString().toUtf8().constData() : fi.fileName().toUtf8().constData()));
+ QString menu_item_name = name.isEmpty() ? QString().toUtf8().constData() : fi.fileName().toUtf8().constData();
+ auto menu_icon = fi.isDir() ? QApplication::style()->standardIcon(QStyle::SP_DirIcon) : ProgSettings::loadIcon("/cdrom.ico");
+ imageMenu->setIcon(menu_icon);
+ imageMenu->setText(QString::asprintf(tr("Eject %s").toUtf8().constData(), menu_item_name.toUtf8().constData()));
for (int slot = 0; slot < MAX_PREV_IMAGES; slot++) {
updateImageHistory(i, slot, ui::MediaType::Optical);
diff --git a/src/qt/qt_rendererstack.cpp b/src/qt/qt_rendererstack.cpp
index f0e5b12e0..670a0d0da 100644
--- a/src/qt/qt_rendererstack.cpp
+++ b/src/qt/qt_rendererstack.cpp
@@ -166,7 +166,7 @@ int ignoreNextMouseEvent = 1;
void
RendererStack::mouseReleaseEvent(QMouseEvent *event)
{
- if (this->geometry().contains(event->pos()) && event->button() == Qt::LeftButton && !mouse_capture && (isMouseDown & 1) && mouse_get_buttons() != 0) {
+ if (this->geometry().contains(event->pos()) && event->button() == Qt::LeftButton && !mouse_capture && (isMouseDown & 1) && (mouse_get_buttons() != 0)) {
plat_mouse_capture(1);
this->setCursor(Qt::BlankCursor);
if (!ignoreNextMouseEvent)
@@ -174,7 +174,7 @@ RendererStack::mouseReleaseEvent(QMouseEvent *event)
isMouseDown &= ~1;
return;
}
- if (mouse_capture && event->button() == Qt::MiddleButton && mouse_get_buttons() < 3) {
+ if (mouse_capture && (event->button() == Qt::MiddleButton) && (mouse_get_buttons() < 3)) {
plat_mouse_capture(0);
this->setCursor(Qt::ArrowCursor);
isMouseDown &= ~1;
diff --git a/src/scsi/scsi_cdrom.c b/src/scsi/scsi_cdrom.c
index b4b91cce8..f57cfd9c5 100644
--- a/src/scsi/scsi_cdrom.c
+++ b/src/scsi/scsi_cdrom.c
@@ -349,7 +349,11 @@ scsi_cdrom_init(scsi_cdrom_t *dev)
dev->sense[0] = 0xf0;
dev->sense[7] = 10;
+#ifdef POSSIBLE_EARLY_ATAPI
dev->status = READY_STAT | DSC_STAT;
+#else
+ dev->status = 0;
+#endif
dev->pos = 0;
dev->packet_status = PHASE_NONE;
scsi_cdrom_sense_key = scsi_cdrom_asc = scsi_cdrom_ascq = dev->unit_attention = 0;
@@ -685,6 +689,7 @@ scsi_cdrom_command_complete(scsi_cdrom_t *dev)
ui_sb_update_icon(SB_CDROM | dev->id, 0);
dev->packet_status = PHASE_COMPLETE;
scsi_cdrom_command_common(dev);
+ dev->phase = 3;
}
static void
@@ -692,6 +697,7 @@ scsi_cdrom_command_read(scsi_cdrom_t *dev)
{
dev->packet_status = PHASE_DATA_IN;
scsi_cdrom_command_common(dev);
+ dev->phase = !(dev->packet_status & 0x01) << 1;
}
static void
@@ -706,6 +712,7 @@ scsi_cdrom_command_write(scsi_cdrom_t *dev)
{
dev->packet_status = PHASE_DATA_OUT;
scsi_cdrom_command_common(dev);
+ dev->phase = !(dev->packet_status & 0x01) << 1;
}
static void
@@ -1352,8 +1359,10 @@ scsi_cdrom_command(scsi_common_t *sc, uint8_t *cdb)
int toc_format, block_desc = 0;
int ret, format = 0;
int real_pos, track = 0;
+#ifdef USE_86BOX_CD
char device_identify[9] = { '8', '6', 'B', '_', 'C', 'D', '0', '0', 0 };
char device_identify_ex[15] = { '8', '6', 'B', '_', 'C', 'D', '0', '0', ' ', 'v', '1', '.', '0', '0', 0 };
+#endif
int32_t blen = 0, *BufLen;
uint8_t *b;
uint32_t profiles[2] = { MMC_PROFILE_CD_ROM, MMC_PROFILE_DVD_ROM };
@@ -1371,12 +1380,14 @@ scsi_cdrom_command(scsi_common_t *sc, uint8_t *cdb)
dev->packet_len = 0;
dev->request_pos = 0;
+#ifdef USE_86BOX_CD
device_identify[7] = dev->id + 0x30;
device_identify_ex[7] = dev->id + 0x30;
device_identify_ex[10] = EMU_VERSION_EX[0];
device_identify_ex[12] = EMU_VERSION_EX[2];
device_identify_ex[13] = EMU_VERSION_EX[3];
+#endif
memcpy(dev->current_cdb, cdb, 12);
@@ -2301,16 +2312,25 @@ scsi_cdrom_command(scsi_common_t *sc, uint8_t *cdb)
if (dev->drv->bus_type == CDROM_BUS_SCSI)
ide_padstr8(dev->buffer + idx, 8, "TOSHIBA"); /* Vendor */
else
+#ifdef USE_86BOX_CD
ide_padstr8(dev->buffer + idx, 8, EMU_NAME); /* Vendor */
+#else
+ ide_padstr8(dev->buffer + idx, 8, "HITACHI"); /* Vendor */
+#endif
idx += 8;
if (dev->drv->bus_type == CDROM_BUS_SCSI)
ide_padstr8(dev->buffer + idx, 40, "XM6201TASUN32XCD1103"); /* Product */
else
+#ifdef USE_86BOX_CD
ide_padstr8(dev->buffer + idx, 40, device_identify_ex); /* Product */
+#else
+ ide_padstr8(dev->buffer + idx, 40, "CDR-8130"); /* Product */
+#endif
idx += 40;
ide_padstr8(dev->buffer + idx, 20, "53R141"); /* Product */
idx += 20;
break;
+
default:
scsi_cdrom_log("INQUIRY: Invalid page: %02X\n", cdb[2]);
scsi_cdrom_invalid_field(dev);
@@ -2344,9 +2364,15 @@ scsi_cdrom_command(scsi_common_t *sc, uint8_t *cdb)
ide_padstr8(dev->buffer + 16, 16, "XM6201TASUN32XCD"); /* Product */
ide_padstr8(dev->buffer + 32, 4, "1103"); /* Revision */
} else {
+#ifdef USE_86BOX_CD
ide_padstr8(dev->buffer + 8, 8, EMU_NAME); /* Vendor */
ide_padstr8(dev->buffer + 16, 16, device_identify); /* Product */
ide_padstr8(dev->buffer + 32, 4, EMU_VERSION_EX); /* Revision */
+#else
+ ide_padstr8(dev->buffer + 8, 8, "HITACHI"); /* Vendor */
+ ide_padstr8(dev->buffer + 16, 16, "CDR-8130"); /* Product */
+ ide_padstr8(dev->buffer + 32, 4, "0020"); /* Revision */
+#endif
}
idx = 36;
@@ -2615,7 +2641,7 @@ scsi_cdrom_get_timings(int ide_has_dma, int type)
static void
scsi_cdrom_identify(ide_t *ide, int ide_has_dma)
{
-#if 0
+#ifdef USE_86BOX_CD
scsi_cdrom_t *dev;
char device_identify[9] = { '8', '6', 'B', '_', 'C', 'D', '0', '0', 0 };
@@ -2627,12 +2653,17 @@ scsi_cdrom_identify(ide_t *ide, int ide_has_dma)
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 */
-#if 0
+#ifdef USE_86BOX_CD
ide_padstr((char *) (ide->buffer + 23), EMU_VERSION_EX, 8); /* Firmware */
ide_padstr((char *) (ide->buffer + 27), device_identify, 40); /* Model */
#else
+ #ifdef USE_NEC_CD
ide_padstr((char *) (ide->buffer + 23), "4.20 ", 8); /* Firmware */
ide_padstr((char *) (ide->buffer + 27), "NEC CD-ROM DRIVE:273 ", 40); /* Model */
+ #else
+ ide_padstr((char *) (ide->buffer + 23), "0020 ", 8); /* Firmware */
+ ide_padstr((char *) (ide->buffer + 27), "HITACHI CDR-8130 ", 40); /* Model */
+ #endif
#endif
ide->buffer[49] = 0x200; /* LBA supported */
ide->buffer[126] = 0xfffe; /* Interpret zero byte count limit as maximum length */
diff --git a/src/win/Makefile.mingw b/src/win/Makefile.mingw
index 27b601f2c..1773198a6 100644
--- a/src/win/Makefile.mingw
+++ b/src/win/Makefile.mingw
@@ -534,7 +534,7 @@ MEMOBJ := catalyst_flash.o i2c_eeprom.o intel_flash.o mem.o rom.o smram.o spd.o
CPUOBJ := $(DYNARECOBJ) \
$(CGTOBJ) \
cpu.o cpu_table.o fpu.o x86.o \
- 808x.o 386.o 386_common.o 386_dynarec.o 386_dynarec_ops.o \
+ 8080.o 808x.o 386.o 386_common.o 386_dynarec.o 386_dynarec_ops.o \
x86seg.o x87.o x87_timings.o
CHIPSETOBJ := 82c100.o acc2168.o \
diff --git a/src/win/win_settings.c b/src/win/win_settings.c
index ff4eaf3b0..a1c83ca52 100644
--- a/src/win/win_settings.c
+++ b/src/win/win_settings.c
@@ -2136,12 +2136,9 @@ recalc_next_free_id(HWND hdlg)
enable_add = enable_add || (next_free_id >= 0);
enable_add = enable_add && ((c_mfm < MFM_NUM) || (c_esdi < ESDI_NUM) || (c_xta < XTA_NUM) || (c_ide < IDE_NUM) || (c_ide < ATAPI_NUM) || (c_scsi < SCSI_NUM));
- enable_add = enable_add && !bus_full(&mfm_tracking, 2);
- enable_add = enable_add && !bus_full(&esdi_tracking, 2);
- enable_add = enable_add && !bus_full(&xta_tracking, 2);
- enable_add = enable_add && !bus_full(&ide_tracking, IDE_CHAN_MAX);
- for (i = 0; i < 2; i++)
- enable_add = enable_add && !bus_full(&(scsi_tracking[i]), 8);
+ enable_add = enable_add && (!bus_full(&mfm_tracking, 2) || !bus_full(&esdi_tracking, 2) || !bus_full(&xta_tracking, 2) || !bus_full(&ide_tracking, IDE_CHAN_MAX * IDE_BUS_MAX) ||
+ !bus_full(&(scsi_tracking[0]), 8) || !bus_full(&(scsi_tracking[1]), 8) || !bus_full(&(scsi_tracking[2]), 8) || !bus_full(&(scsi_tracking[3]), 8) ||
+ !bus_full(&(scsi_tracking[4]), 8) || !bus_full(&(scsi_tracking[5]), 8) || !bus_full(&(scsi_tracking[6]), 8) || !bus_full(&(scsi_tracking[7]), 8));
settings_enable_window(hdlg, IDC_BUTTON_HDD_ADD_NEW, enable_add);
settings_enable_window(hdlg, IDC_BUTTON_HDD_ADD, enable_add);