diff --git a/.github/workflows/bgfxshaders.yml b/.github/workflows/bgfxshaders.yml
deleted file mode 100644
index bff5085e509..00000000000
--- a/.github/workflows/bgfxshaders.yml
+++ /dev/null
@@ -1,44 +0,0 @@
-name: Rebuild BGFX shaders
-
-on:
- push:
- paths:
- - '.github/workflows/**'
- - 'src/osd/modules/render/bgfx/shaders/**'
- pull_request:
- paths:
- - '.github/workflows/**'
- - 'src/osd/modules/render/bgfx/shaders/**'
-
-permissions:
- contents: read
-
-jobs:
- rebuild:
- runs-on: windows-latest
- defaults:
- run:
- shell: msys2 {0}
- steps:
- - uses: msys2/setup-msys2@v2
- with:
- install: git make mingw-w64-x86_64-gcc mingw-w64-x86_64-python mingw-w64-x86_64-libc++
- - uses: actions/checkout@main
- with:
- fetch-depth: 0
- - name: Prevent make from rebuilding GLSL parser source
- run: |
- touch 3rdparty/bgfx/3rdparty/glsl-optimizer/src/glsl/glcpp/glcpp-lex.c
- touch 3rdparty/bgfx/3rdparty/glsl-optimizer/src/glsl/glcpp/glcpp-parse.c
- touch 3rdparty/bgfx/3rdparty/glsl-optimizer/src/glsl/glcpp/glcpp-parse.h
- touch 3rdparty/bgfx/3rdparty/glslang/glslang/MachineIndependent/glslang_tab.cpp
- touch 3rdparty/bgfx/3rdparty/glslang/glslang/MachineIndependent/glslang_tab.cpp.h
- - name: Build
- env:
- MINGW64: "/mingw64"
- run: make shaders
- - uses: actions/upload-artifact@main
- with:
- name: mame-bgfx-${{ github.sha }}
- path: bgfx/shaders
- if-no-files-found: error
diff --git a/.github/workflows/ci-emscripten.yml b/.github/workflows/ci-emscripten.yml
new file mode 100644
index 00000000000..65e0ca6c7f8
--- /dev/null
+++ b/.github/workflows/ci-emscripten.yml
@@ -0,0 +1,73 @@
+name: CI (Emscripten)
+
+on:
+ push:
+ paths:
+ - '.github/workflows/**'
+ - '3rdparty/**'
+ - 'hash/**'
+ - 'scripts/**'
+ - 'src/**'
+ - 'COPYING'
+ - 'makefile'
+ pull_request:
+ paths:
+ - '.github/workflows/**'
+ - '3rdparty/**'
+ - 'hash/**'
+ - 'scripts/**'
+ - 'src/**'
+ - 'COPYING'
+ - 'makefile'
+
+permissions:
+ contents: read
+
+jobs:
+ build-linux:
+ runs-on: ubuntu-latest
+ strategy:
+ matrix:
+ compiler: [emscripten]
+ include:
+ - compiler: emscripten
+ subtarget: mame
+ emver: 3.1.25
+ name: mame-web
+ steps:
+ - uses: actions/checkout@main
+ with:
+ fetch-depth: 0
+ - name: Apply patch-web
+ run: |
+ git config --global user.email "actions@github.com"
+ git config --global user.name "GitHub Actions"
+ git merge origin/patch-web
+ - name: Install dependencies
+ run: |
+ sudo apt-get update
+ sudo apt-get install -y libsdl2-dev libsdl2-ttf-dev libasound2-dev libxinerama-dev libxi-dev qtbase5-dev qtbase5-dev-tools
+ - name: Install emscripten
+ run: |
+ git clone --filter=tree:0 https://github.com/emscripten-core/emsdk.git
+ cd emsdk
+ ./emsdk install ${{ matrix.emver }}
+ ./emsdk activate ${{ matrix.emver }}
+ source ./emsdk_env.sh
+ cd ..
+ - name: Build
+ env:
+ SUBTARGET: ${{ matrix.subtarget }}
+ SOURCES: sinclair/sprinter.cpp,sinclair/tsconf.cpp,sinclair/scorpion.cpp,sinclair/chloe.cpp
+ TOOLS: 0
+ run: |
+ source emsdk/emsdk_env.sh
+ emmake make -j$(nproc)
+ - uses: actions/upload-artifact@main
+ with:
+ name: ${{ matrix.name }}-${{ matrix.compiler }}-${{ github.sha }}
+ path: |
+ mame.html
+ mame.js
+ mame.wasm
+ if-no-files-found: error
diff --git a/.github/workflows/ci-linux.yml b/.github/workflows/ci-linux.yml
deleted file mode 100644
index ab8601406dd..00000000000
--- a/.github/workflows/ci-linux.yml
+++ /dev/null
@@ -1,76 +0,0 @@
-name: CI (Linux)
-
-on:
- push:
- paths:
- - '.github/workflows/**'
- - '3rdparty/**'
- - 'hash/**'
- - 'scripts/**'
- - 'src/**'
- - 'COPYING'
- - 'makefile'
- pull_request:
- paths:
- - '.github/workflows/**'
- - '3rdparty/**'
- - 'hash/**'
- - 'scripts/**'
- - 'src/**'
- - 'COPYING'
- - 'makefile'
-
-permissions:
- contents: read
-
-jobs:
- build-linux:
- runs-on: ubuntu-latest
- strategy:
- matrix:
- compiler: [gcc, clang]
- include:
- - compiler: gcc
- cc: gcc
- cxx: g++
- archopts: -U_FORTIFY_SOURCE
- subtarget: tiny
- executable: mametiny
- - compiler: clang
- cc: clang
- cxx: clang++
- subtarget: mame
- executable: mame
- steps:
- - uses: actions/checkout@main
- with:
- fetch-depth: 0
- - name: Install dependencies
- run: |
- sudo apt-get update
- sudo apt-get install -y libsdl2-dev libsdl2-ttf-dev libasound2-dev libxinerama-dev libxi-dev qtbase5-dev qtbase5-dev-tools
- - name: Install clang
- if: matrix.compiler == 'clang'
- run: sudo apt-get install -y clang
- - name: Build
- env:
- OVERRIDE_CC: ${{ matrix.cc }}
- OVERRIDE_CXX: ${{ matrix.cxx }}
- ARCHOPTS: ${{ matrix.archopts }}
- SUBTARGET: ${{ matrix.subtarget }}
- TOOLS: 1
- run: make -j3
- - name: Validate
- run: ./${{ matrix.executable }} -validate
- - name: Reconcile driver list
- run: ./${{ matrix.executable }} -listxml | python scripts/build/makedep.py reconcilelist -l src/mame/${{ matrix.subtarget }}.lst -
- - name: ORM check
- run: python scripts/minimaws/minimaws.py load --executable ./${{ matrix.executable }} --softwarepath hash
- - uses: actions/upload-artifact@main
- with:
- name: ${{ matrix.executable }}-linux-${{ matrix.compiler }}-${{ github.sha }}
- path: |
- ${{ matrix.executable }}
- chdman
- unidasm
- if-no-files-found: error
diff --git a/.github/workflows/ci-macos.yml b/.github/workflows/ci-macos.yml
deleted file mode 100644
index ba56880902e..00000000000
--- a/.github/workflows/ci-macos.yml
+++ /dev/null
@@ -1,47 +0,0 @@
-name: CI (macOS)
-
-on:
- push:
- paths:
- - '.github/workflows/**'
- - '3rdparty/**'
- - 'scripts/**'
- - 'src/**'
- - 'COPYING'
- - 'makefile'
- pull_request:
- paths:
- - '.github/workflows/**'
- - '3rdparty/**'
- - 'scripts/**'
- - 'src/**'
- - 'COPYING'
- - 'makefile'
-
-permissions:
- contents: read
-
-jobs:
- build-macos:
- runs-on: macOS-latest
- steps:
- - uses: actions/checkout@main
- with:
- fetch-depth: 0
- - name: Install dependencies
- run: brew install python3 sdl2
- - name: Build
- env:
- USE_LIBSDL: 1
- TOOLS: 1
- run: make -j2
- - name: Validate
- run: ./mame -validate
- - uses: actions/upload-artifact@main
- with:
- name: mame-macos-${{ github.sha }}
- path: |
- mame
- chdman
- unidasm
- if-no-files-found: error
diff --git a/.github/workflows/ci-windows.yml b/.github/workflows/ci-windows.yml
index 8d537fab236..165ace9e489 100644
--- a/.github/workflows/ci-windows.yml
+++ b/.github/workflows/ci-windows.yml
@@ -29,18 +29,13 @@ jobs:
shell: msys2 {0}
strategy:
matrix:
- compiler: [gcc, clang]
+ compiler: [gcc]
include:
- compiler: gcc
cc: gcc
cxx: g++
subtarget: mame
executable: mame
- - compiler: clang
- cc: clang
- cxx: clang++
- subtarget: tiny
- executable: mametiny
steps:
- uses: msys2/setup-msys2@v2
with:
@@ -56,15 +51,12 @@ jobs:
OVERRIDE_CXX: ${{ matrix.cxx }}
ARCHOPTS: "-fuse-ld=lld"
SUBTARGET: ${{ matrix.subtarget }}
- TOOLS: 1
- run: make -j3
- - name: Validate
- run: ./${{ matrix.executable }}.exe -validate
+ SOURCES: sinclair/sprinter.cpp,sinclair/tsconf.cpp
+ TOOLS: 0
+ run: make -j$(nproc)
- uses: actions/upload-artifact@main
with:
name: ${{ matrix.executable }}-windows-${{ matrix.compiler }}-${{ github.sha }}
path: |
${{ matrix.executable }}.exe
- chdman.exe
- unidasm.exe
if-no-files-found: error
diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml
deleted file mode 100644
index 0b80859804e..00000000000
--- a/.github/workflows/docs.yml
+++ /dev/null
@@ -1,38 +0,0 @@
-name: Build documentation
-
-on:
- push:
- paths:
- - '.github/workflows/**'
- - 'docs/**'
- pull_request:
- paths:
- - '.github/workflows/**'
- - 'docs/**'
-
-permissions:
- contents: read
-
-jobs:
- build-docs:
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@main
- with:
- fetch-depth: 0
- - name: Install dependencies
- run: |
- sudo apt-get update
- sudo apt-get install -y librsvg2-bin latexmk python3-pip python3-sphinx texlive texlive-formats-extra texlive-science
- pip3 install sphinxcontrib-svg2pdfconverter
- - name: Build HTML
- run: make -C docs html
- - name: Build PDF
- run: make -C docs latexpdf
- - uses: actions/upload-artifact@main
- with:
- name: mame-docs-${{ github.sha }}
- path: |
- docs/build/html
- docs/build/latex/MAME.pdf
- if-no-files-found: error
diff --git a/.github/workflows/hash.yml b/.github/workflows/hash.yml
deleted file mode 100644
index 5e55145422e..00000000000
--- a/.github/workflows/hash.yml
+++ /dev/null
@@ -1,38 +0,0 @@
-name: XML/JSON validation
-
-on:
- push:
- paths:
- - '.github/workflows/**'
- - 'ctrlr/*'
- - 'hash/*'
- - 'plugins/**'
- pull_request:
- paths:
- - '.github/workflows/**'
- - 'ctrlr/*'
- - 'hash/*'
- - 'plugins/**'
-
-permissions:
- contents: read
-
-jobs:
- validate:
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@main
- with:
- fetch-depth: 0
- - name: Install dependencies
- run: |
- sudo apt-get update
- sudo apt-get install -y libxml2-utils python3-jsonschema
- - name: Validate (controller configuration)
- run: for x in ctrlr/*.cfg ; do xmllint --noout "$x" ; done
- - name: Validate (HSI)
- run: for x in hash/*.hsi ; do xmllint --noout "$x" ; done
- - name: Validate (software list)
- run: for x in hash/*.xml ; do xmllint --noout --valid "$x" ; done
- - name: Validate (plugin properties)
- run: for x in plugins/*/plugin.json ; do jsonschema -i "$x" plugins/plugin.schema ; done
diff --git a/.github/workflows/language.yml b/.github/workflows/language.yml
deleted file mode 100644
index a5c6eaf358f..00000000000
--- a/.github/workflows/language.yml
+++ /dev/null
@@ -1,29 +0,0 @@
-name: Compile UI translations
-
-on:
- push:
- paths:
- - '.github/workflows/**'
- - 'language/**'
- pull_request:
- paths:
- - '.github/workflows/**'
- - 'language/**'
-
-permissions:
- contents: read
-
-jobs:
- build-language:
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@main
- with:
- fetch-depth: 0
- - name: Compile message catalogs
- run: for x in language/*/*.po ; do python scripts/build/msgfmt.py --output-file "`dirname "$x"`/`basename "$x" .po`.mo" "$x" ; done
- - uses: actions/upload-artifact@main
- with:
- name: mame-language-${{ github.sha }}
- path: language/*/*.mo
- if-no-files-found: error
diff --git a/hash/tsconf.xml b/hash/tsconf.xml
new file mode 100644
index 00000000000..357777d345e
--- /dev/null
+++ b/hash/tsconf.xml
@@ -0,0 +1,456 @@
+
+
+
+
+
+
+ Alter Ego
+ 2011
+ <homebrew>
+
+
+
+
+
+
+
+
+
+
+
+ Bomberman
+ 2012
+ <homebrew>
+
+
+
+
+
+
+
+
+
+
+
+
+ Bruce Lee
+ 2015
+ <homebrew>
+
+
+
+
+
+
+
+
+
+ Chase
+ 2012
+ <homebrew>
+
+
+
+
+
+
+
+
+
+
+ Copter v0.1
+ 2012
+ <homebrew>
+
+
+
+
+
+
+
+
+
+ Digger
+ 2016
+ <homebrew>
+
+
+
+
+
+
+
+
+
+
+
+ Edge Grinder v1.01
+ 2018
+ <homebrew>
+
+
+
+
+
+
+
+
+
+
+
+ Jim Power Test
+ 201?
+ <homebrew>
+
+
+
+
+
+
+
+
+
+ Lirus
+ 201?
+ <homebrew>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Touhou Zero. Lost Donation Box Incident
+ 201?
+ <homebrew>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ MultiDude
+ 2014
+ <homebrew>
+
+
+
+
+
+
+
+
+
+
+
+
+ Ninja Gaiden
+ 201?
+ <homebrew>
+
+
+
+
+
+
+
+
+
+ Otter & Smoker
+ 201?
+ <homebrew>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Ottifants
+ 201?
+ <homebrew>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Once Upon a Time in a Kingdom
+ 201?
+ <homebrew>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ PacPack
+ 2018
+ <homebrew>
+
+
+
+
+
+
+
+
+
+ Cannon Fodder Parallax
+ 201?
+ <homebrew>
+
+
+
+
+
+
+
+
+
+ Sir Ababol
+ 201?
+ <homebrew>
+
+
+
+
+
+
+
+
+
+
+
+ Socoban
+ 2015
+ <homebrew>
+
+
+
+
+
+
+
+
+
+ Sonic the Hedgehog
+ 201?
+ <homebrew>
+
+
+
+
+
+
+
+
+
+
+ Street Fighter 2 (v1.1)
+ 2023
+ <homebrew>
+
+
+
+
+
+
+
+
+
+
+
+ Synchronization
+ 201?
+ Robus
+
+
+
+
+
+
+
+
+
+
+
+
+ T-circles
+ 201?
+ <homebrew>
+
+
+
+
+
+
+
+
+
+ Tetris
+ 201?
+ <homebrew>
+
+
+
+
+
+
+
+
+
+ TS-TechDemo
+ 2013
+ Wizart/DT
+
+
+
+
+
+
+
+
+
+ TSolitaire
+ 201?
+ ERA Creative Group (Multinational)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Uwol - Quest for Money
+ 2012
+ <homebrew>
+
+
+
+
+
+
+
+
+
+
+ Wonder Boy
+ 201?
+ <homebrew>
+
+
+
+
+
+
+
+
+
+ Xonix
+ 2012
+ <homebrew>
+
+
+
+
+
+
+
+
+
+ Zen Loops
+ 201?
+ <homebrew>
+
+
+
+
+
+
+
+
+
+ ZX Battle City v1.4 (NoVDAC)
+ 2020
+ <homebrew>
+
+
+
+
+
+
+
+
+
+
diff --git a/hash/tsconf_betadisc_flop.xml b/hash/tsconf_betadisc_flop.xml
deleted file mode 100644
index d315425839e..00000000000
--- a/hash/tsconf_betadisc_flop.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-
-
-
-
-
-
- Copter v0.1
- 2012
- Wizart/DT
-
-
-
-
-
-
-
-
- ZX Battle City v1.4 (NoVDAC)
- 2020
- Marie Slip / n1k-o
-
-
-
-
-
-
-
-
diff --git a/src/devices/bus/isa/com.cpp b/src/devices/bus/isa/com.cpp
index 4a1cc1ebd00..659cb3a226d 100644
--- a/src/devices/bus/isa/com.cpp
+++ b/src/devices/bus/isa/com.cpp
@@ -41,7 +41,7 @@ DEFINE_DEVICE_TYPE(ISA8_COM, isa8_com_device, "isa_com", "Communications Adapter
void isa8_com_device::device_add_mconfig(machine_config &config)
{
- ins8250_device &uart0(INS8250(config, "uart_0", XTAL(1'843'200)));
+ ns16550_device &uart0(NS16550(config, "uart_0", XTAL(1'843'200)));
uart0.out_tx_callback().set("serport0", FUNC(rs232_port_device::write_txd));
uart0.out_dtr_callback().set("serport0", FUNC(rs232_port_device::write_dtr));
uart0.out_rts_callback().set("serport0", FUNC(rs232_port_device::write_rts));
@@ -118,7 +118,7 @@ isa8_com_device::isa8_com_device(const machine_config &mconfig, device_type type
void isa8_com_device::device_start()
{
set_isa_device();
- m_isa->install_device(0x03f8, 0x03ff, read8sm_delegate(*subdevice("uart_0"), FUNC(ins8250_device::ins8250_r)), write8sm_delegate(*subdevice("uart_0"), FUNC(ins8250_device::ins8250_w)));
+ m_isa->install_device(0x03e8, 0x03ef, read8sm_delegate(*subdevice("uart_0"), FUNC(ins8250_device::ins8250_r)), write8sm_delegate(*subdevice("uart_0"), FUNC(ins8250_device::ins8250_w)));
m_isa->install_device(0x02f8, 0x02ff, read8sm_delegate(*subdevice("uart_1"), FUNC(ins8250_device::ins8250_r)), write8sm_delegate(*subdevice("uart_1"), FUNC(ins8250_device::ins8250_w)));
// m_isa->install_device(0x03e8, 0x03ef, read8sm_delegate(*subdevice("uart_2"), FUNC(ins8250_device::ins8250_r)), write8sm_delegate(*subdevice("uart_2"), FUNC(ins8250_device::ins8250_w)));
// m_isa->install_device(0x02e8, 0x02ef, read8sm_delegate(*subdevice("uart_3"), FUNC(ins8250_device::ins8250_r)), write8sm_delegate(*subdevice("uart_3"), FUNC(ins8250_device::ins8250_w)));
diff --git a/src/devices/bus/isa/isa_cards.cpp b/src/devices/bus/isa/isa_cards.cpp
index 786c9bf1010..184fcf2af18 100644
--- a/src/devices/bus/isa/isa_cards.cpp
+++ b/src/devices/bus/isa/isa_cards.cpp
@@ -9,6 +9,7 @@
#include "emu.h"
#include "isa_cards.h"
+/*
// video
#include "aga.h"
#include "cga.h"
@@ -90,10 +91,11 @@
#include "finalchs.h"
#include "hpblp.h"
#include "opus100pm.h"
-
+*/
void pc_isa8_cards(device_slot_interface &device)
{
+/*
device.option_add("mda", ISA8_MDA);
device.option_add("cga", ISA8_CGA);
device.option_add("cga_ec1841", ISA8_EC1841_0002);
@@ -148,10 +150,12 @@ void pc_isa8_cards(device_slot_interface &device)
device.option_add("acb2072", ACB2072);
device.option_add("3xtwin", ISA8_3XTWIN);
device.option_add("opus108pm", ISA8_OPUS108PM);
+*/
}
void pc_isa16_cards(device_slot_interface &device)
{
+/*
// 8-bit
device.option_add("mda", ISA8_MDA);
device.option_add("cga", ISA8_CGA);
@@ -253,4 +257,5 @@ void pc_isa16_cards(device_slot_interface &device)
device.option_add("omti8621", ISA16_OMTI8621);
device.option_add("lrk331", LRK331);
device.option_add("hpblp", HPBLP);
+*/
}
diff --git a/src/devices/bus/pc_kbd/msnat.cpp b/src/devices/bus/pc_kbd/msnat.cpp
index bc6310c9465..12ca536bc9f 100644
--- a/src/devices/bus/pc_kbd/msnat.cpp
+++ b/src/devices/bus/pc_kbd/msnat.cpp
@@ -201,7 +201,13 @@ DEFINE_DEVICE_TYPE(PC_KBD_MICROSOFT_NATURAL, pc_kbd_microsoft_natural_device, "k
ROM_START( microsoft_natural )
ROM_REGION(0x1000, "ms_natrl_cpu", 0)
- ROM_LOAD("natural.bin", 0x0000, 0x1000, CRC(aa8243ab) SHA1(72134882a5c03e785db07cc54dfb7572c0a730d9))
+ ROM_DEFAULT_BIOS("orig")
+
+ ROM_SYSTEM_BIOS(0, "orig", "Original")
+ ROMX_LOAD("natural.bin", 0x0000, 0x1000, CRC(aa8243ab) SHA1(72134882a5c03e785db07cc54dfb7572c0a730d9), ROM_BIOS(0))
+
+ ROM_SYSTEM_BIOS(1, "sp2k", "Sprinter 2k Fix")
+ ROMX_LOAD("natural-sp2k.bin", 0x0000, 0x1000, CRC(16c21ab2) SHA1(72c6ebe8fd88a81a6c9622ff968ad2d0eb04a629), ROM_BIOS(1))
ROM_END
diff --git a/src/devices/machine/atastorage.h b/src/devices/machine/atastorage.h
index 08a3d901b98..27b433b8b28 100644
--- a/src/devices/machine/atastorage.h
+++ b/src/devices/machine/atastorage.h
@@ -61,7 +61,7 @@ protected:
virtual void signature() override;
int m_can_identify_device;
- uint16_t m_num_cylinders;
+ uint32_t m_num_cylinders;
uint8_t m_num_sectors;
uint8_t m_num_heads;
diff --git a/src/devices/machine/z80dma.cpp b/src/devices/machine/z80dma.cpp
index 534546d47d6..2615c4e3b57 100644
--- a/src/devices/machine/z80dma.cpp
+++ b/src/devices/machine/z80dma.cpp
@@ -131,17 +131,20 @@ enum
****************************************************************************/
DEFINE_DEVICE_TYPE(Z80DMA, z80dma_device, "z80dma", "Z80 DMA Controller")
+ALLOW_SAVE_TYPE(z80dma_device::dma_mode);
+
/****************************************************************************
* z80dma_device - constructor
****************************************************************************/
z80dma_device::z80dma_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
- : z80dma_device(mconfig, Z80DMA, tag, owner, clock)
+ : z80dma_device(mconfig, Z80DMA, tag, owner, clock, dma_mode::ZILOG)
{
}
-z80dma_device::z80dma_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock)
+z80dma_device::z80dma_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, dma_mode dma_mode)
: device_t(mconfig, type, tag, owner, clock)
, device_z80daisy_interface(mconfig, *this)
+ , m_dma_mode(dma_mode)
, m_out_busreq_cb(*this)
, m_out_int_cb(*this)
, m_out_ieo_cb(*this)
@@ -162,6 +165,7 @@ void z80dma_device::device_start()
m_timer = timer_alloc(FUNC(z80dma_device::clock_w), this);
// register for state saving
+ save_item(NAME(m_dma_mode));
save_item(NAME(m_regs));
save_item(NAME(m_regs_follow));
save_item(NAME(m_num_follow));
@@ -445,10 +449,9 @@ void z80dma_device::do_write()
break;
}
+ m_byte_counter++;
m_addressA += PORTA_FIXED ? 0 : PORTA_INC ? 1 : -1;
m_addressB += PORTB_FIXED ? 0 : PORTB_INC ? 1 : -1;
-
- m_byte_counter++;
}
/****************************************************************************
@@ -670,7 +673,7 @@ void z80dma_device::write(u8 data)
if (data & 0x10)
m_regs_follow[m_num_follow++] = GET_REGNUM(MATCH_BYTE);
- if (BIT(data, 6))
+ if (BIT(data, 6) && m_dma_mode != dma_mode::UA858D)
{
enable();
}
@@ -875,7 +878,7 @@ TIMER_CALLBACK_MEMBER(z80dma_device::rdy_write_callback)
void z80dma_device::rdy_w(int state)
{
LOG("Z80DMA RDY: %d Active High: %d\n", state, READY_ACTIVE_HIGH);
- machine().scheduler().synchronize(timer_expired_delegate(FUNC(z80dma_device::rdy_write_callback),this), state);
+ machine().scheduler().synchronize(timer_expired_delegate(FUNC(z80dma_device::rdy_write_callback), this), state);
}
/****************************************************************************
@@ -885,3 +888,11 @@ void z80dma_device::bai_w(int state)
{
m_busrq_ack = state;
}
+
+
+DEFINE_DEVICE_TYPE(UA858D, ua858d_device, "ua858d", "UA858D DMA Controller")
+
+ua858d_device::ua858d_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : z80dma_device(mconfig, UA858D, tag, owner, clock, dma_mode::UA858D)
+{
+}
diff --git a/src/devices/machine/z80dma.h b/src/devices/machine/z80dma.h
index b461330eab0..11466cd197f 100644
--- a/src/devices/machine/z80dma.h
+++ b/src/devices/machine/z80dma.h
@@ -48,6 +48,12 @@ class z80dma_device : public device_t,
public device_z80daisy_interface
{
public:
+ enum class dma_mode : u8
+ {
+ ZILOG = 0,
+ UA858D = 1
+ };
+
// construction/destruction
z80dma_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
@@ -60,6 +66,7 @@ public:
auto in_iorq_callback() { return m_in_iorq_cb.bind(); }
auto out_iorq_callback() { return m_out_iorq_cb.bind(); }
+ void set_dma_mode(dma_mode dma_mode) { m_dma_mode = dma_mode; }
u8 read();
virtual void write(u8 data);
@@ -90,7 +97,7 @@ protected:
static inline constexpr int TM_SEARCH = 0x02;
static inline constexpr int TM_SEARCH_TRANSFER = 0x03;
- z80dma_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
+ z80dma_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, dma_mode dma_mode);
// device_t implementation
virtual void device_start() override ATTR_COLD;
@@ -112,6 +119,7 @@ protected:
static constexpr unsigned REGNUM(unsigned m, unsigned s) { return (m << 3) + s; }
+ dma_mode m_dma_mode;
u16 m_addressA;
u16 m_addressB;
u16 m_count;
@@ -164,8 +172,14 @@ private:
u8 m_vector; // interrupt vector
};
+class ua858d_device : public z80dma_device
+{
+public:
+ ua858d_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+};
// device type definition
DECLARE_DEVICE_TYPE(Z80DMA, z80dma_device)
+DECLARE_DEVICE_TYPE(UA858D, ua858d_device)
#endif // MAME_MACHINE_Z80DMA_H
diff --git a/src/mame/sinclair/atm.cpp b/src/mame/sinclair/atm.cpp
index 9d5452d5041..466e2d371b5 100644
--- a/src/mame/sinclair/atm.cpp
+++ b/src/mame/sinclair/atm.cpp
@@ -517,7 +517,7 @@ void atm_state::atm(machine_config &config)
output_latch_device ¢_data_out(OUTPUT_LATCH(config, "cent_data_out"));
m_centronics->set_output_latch(cent_data_out);
- config.device_remove("exp");
+ //config.device_remove("exp");
}
@@ -589,6 +589,12 @@ ROM_START( atmtb2plus )
ROM_SYSTEM_BIOS(3, "v1.37", "Dual eXtra v1.37XT: BIOS v1.07.15, CP/M v2.2, TR-DOS v5.04R")
ROMX_LOAD( "atmtb2x37xt.rom", 0x010000, 0x20000, CRC(e5ef44d9) SHA1(3fbb9ace7cb031e7365c19e4f8b67ed366e24064), ROM_BIOS(3))
+ ROM_SYSTEM_BIOS(4, "gluk", "Gluk")
+ ROMX_LOAD( "glukatm.rom", 0x020000, 0x10000, CRC(7a017f0d) SHA1(301d9195ecaeeba31b7a7d6b7c4037b8cc72a240), ROM_BIOS(4))
+ ROM_SYSTEM_BIOS(5, "gluk2", "Gluk2")
+ ROMX_LOAD( "glukatm2.rom", 0x020000, 0x10000, CRC(64cfee77) SHA1(cd180493e6c3ae4b0a0f753f0efff2debd43a329), ROM_BIOS(5))
+
+
ROM_REGION(0x01000, "keyboard", ROMREGION_ERASEFF)
ROM_LOAD( "rf2ve3.rom", 0x0000, 0x0580, CRC(35e0f9ec) SHA1(adcf14758fab8472cfa0167af7e8326c66416416)) // XT Keyboard
ROM_LOAD( "rfat710.rom", 0x0600, 0x0680, CRC(03734365) SHA1(6cb6311727fad9bc4ccb18919c3c39b37529b8e6)) // AT Keyboard
diff --git a/src/mame/sinclair/chloe.cpp b/src/mame/sinclair/chloe.cpp
index f7fdade4a09..787ef31f0af 100644
--- a/src/mame/sinclair/chloe.cpp
+++ b/src/mame/sinclair/chloe.cpp
@@ -992,11 +992,18 @@ void chloe_state::chloe(machine_config &config)
ROM_START(chloe)
ROM_REGION(0xc000, "maincpu", ROMREGION_ERASEFF)
+ ROM_DEFAULT_BIOS("v101b")
- // SE/OS 1.0
- ROM_LOAD( "10_boot.rom", 0x0000, 0x4000, CRC(efbfe46e) SHA1(f5a86b56955661f72fa416e7e644de0b3afe6509))
- ROM_LOAD( "10_basic_42.rom", 0x4000, 0x4000, CRC(c6273eaa) SHA1(f09a26c50f5cfe454e4d56c920cdcc62bc4f90cb))
- ROM_LOAD( "10_dos_31.rom", 0x8000, 0x2000, CRC(67dfef09) SHA1(ba9616494071dfe65834d7db657e0d3bcce0b732))
+ ROM_SYSTEM_BIOS(0, "v10", "System 1.0") // 05.01.2024 - SE/OS 1.0
+ ROMX_LOAD( "10_boot.rom", 0x0000, 0x4000, CRC(efbfe46e) SHA1(f5a86b56955661f72fa416e7e644de0b3afe6509), ROM_BIOS(0))
+ ROMX_LOAD( "10_basic_42.rom", 0x4000, 0x4000, CRC(c6273eaa) SHA1(f09a26c50f5cfe454e4d56c920cdcc62bc4f90cb), ROM_BIOS(0))
+ ROMX_LOAD( "10_dos_31.rom", 0x8000, 0x2000, CRC(67dfef09) SHA1(ba9616494071dfe65834d7db657e0d3bcce0b732), ROM_BIOS(0))
+
+ // SE/OS 1.1
+ ROM_SYSTEM_BIOS(1, "v101b", "System 1.0.1b") // 05.xx.2024 - SE/OS 1.0.1b
+ ROMX_LOAD( "101_boot.rom", 0x0000, 0x4000, CRC(26c57f5a) SHA1(6680aaeac288c688f0400080faf07214959d5a1c), ROM_BIOS(1))
+ ROMX_LOAD( "101_basic_42.rom", 0x4000, 0x4000, CRC(0f8658ba) SHA1(b6975e66c029165a39a1ee85ebec50c8e7f4ec1e), ROM_BIOS(1))
+ ROMX_LOAD( "10_dos_31.rom", 0x8000, 0x2000, CRC(67dfef09) SHA1(ba9616494071dfe65834d7db657e0d3bcce0b732), ROM_BIOS(1))
ROM_END
} // Anonymous namespace
diff --git a/src/mame/sinclair/spec128.cpp b/src/mame/sinclair/spec128.cpp
index 8895627ffcb..e45f0a8621e 100644
--- a/src/mame/sinclair/spec128.cpp
+++ b/src/mame/sinclair/spec128.cpp
@@ -161,9 +161,9 @@ resulting mess can be seen in the F4 viewer display.
#include "formats/tzx_cas.h"
-/****************************************************************************************************/
-/* Spectrum 128 specific functions */
-
+/****************************************************************************
+ * Spectrum 128 specific functions
+ ****************************************************************************/
void spectrum_128_state::video_start()
{
spectrum_state::video_start();
@@ -221,27 +221,34 @@ void spectrum_128_state::spectrum_128_port_7ffd_w(offs_t offset, uint8_t data)
if (is_contended(offset)) content_early();
content_early(1);
- /* D0-D2: RAM page located at 0x0c000-0x0ffff */
- /* D3 - Screen select (screen 0 in ram page 5, screen 1 in ram page 7 */
- /* D4 - ROM select - which rom paged into 0x0000-0x03fff */
- /* D5 - Disable paging */
+ // D0-D2: RAM page located at 0x0c000-0x0ffff
+ // D3 - Screen select (screen 0 in ram page 5, screen 1 in ram page 7
+ // D4 - ROM select - which rom paged into 0x0000-0x03fff
+ // D5 - Disable paging
- /* disable paging? */
+ // disable paging?
if (m_port_7ffd_data & 0x20) return;
- /* store new state */
+ // store new state
m_port_7ffd_data = data;
- /* update memory */
+ // update memory
spectrum_128_update_memory();
m_exp->iorq_w(offset | 1, data);
}
+void spectrum_128_state::bank3_set_page(u8 page)
+{
+ m_port_7ffd_data &= 0xf8;
+ m_port_7ffd_data |= page & 0x07;
+ spectrum_128_update_memory();
+}
+
void spectrum_128_state::spectrum_128_update_memory()
{
m_bank_rom[0]->set_entry(BIT(m_port_7ffd_data, 4));
- /* select ram at 0x0c000-0x0ffff */
+ // select ram at 0x0c000-0x0ffff
m_bank_ram[3]->set_entry(m_port_7ffd_data & 0x07);
m_screen->update_now();
@@ -288,13 +295,80 @@ void spectrum_128_state::spectrum_128_fetch(address_map &map)
map(0x0000, 0xffff).r(FUNC(spectrum_128_state::spectrum_128_pre_opcode_fetch_r));
}
+static INPUT_PORTS_START( spec_plus_joys )
+ PORT_START("JOY2") // 0xF7FE
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT) PORT_8WAY PORT_PLAYER(2) PORT_CODE(JOYCODE_X_LEFT_SWITCH)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT) PORT_8WAY PORT_PLAYER(2) PORT_CODE(JOYCODE_X_RIGHT_SWITCH)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN) PORT_8WAY PORT_PLAYER(2) PORT_CODE(JOYCODE_Y_DOWN_SWITCH)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_UP) PORT_8WAY PORT_PLAYER(2) PORT_CODE(JOYCODE_Y_UP_SWITCH)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_BUTTON1) PORT_PLAYER(2) PORT_CODE(JOYCODE_BUTTON1)
+
+ PORT_START("JOY1") // 0xEFFE
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_BUTTON1) PORT_PLAYER(1) PORT_CODE(JOYCODE_BUTTON1)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_UP) PORT_8WAY PORT_PLAYER(1) PORT_CODE(JOYCODE_Y_UP_SWITCH)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN) PORT_8WAY PORT_PLAYER(1) PORT_CODE(JOYCODE_Y_DOWN_SWITCH)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT) PORT_8WAY PORT_PLAYER(1) PORT_CODE(JOYCODE_X_RIGHT_SWITCH)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT) PORT_8WAY PORT_PLAYER(1) PORT_CODE(JOYCODE_X_LEFT_SWITCH)
+INPUT_PORTS_END
+
+/* These keys need not to be mapped in natural mode because Spectrum+ supports both these and the Spectrum sequences above.
+ Hence, we can simply keep using such sequences in natural keyboard emulation */
+INPUT_PORTS_START( spec128 )
+ PORT_INCLUDE( spectrum )
+
+ PORT_START("PLUS0") // Spectrum+ Keys (Same as CAPS + 1-5)
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("EDIT") PORT_CODE(KEYCODE_INSERT)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("CAPS LOCK") PORT_CODE(KEYCODE_CAPSLOCK)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("TRUE VID") PORT_CODE(KEYCODE_HOME)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("INV VID") PORT_CODE(KEYCODE_END)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Cursor Left") PORT_CODE(KEYCODE_LEFT)
+ PORT_BIT(0xe0, IP_ACTIVE_LOW, IPT_UNUSED)
+
+ PORT_START("PLUS1") // Spectrum+ Keys (Same as CAPS + 6-0)
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("DEL") PORT_CODE(KEYCODE_BACKSPACE) PORT_CHAR(8)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("GRAPH") PORT_CODE(KEYCODE_LALT)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Cursor Right") PORT_CODE(KEYCODE_RIGHT)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Cursor Up") PORT_CODE(KEYCODE_UP)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Cursor Down") PORT_CODE(KEYCODE_DOWN)
+ PORT_BIT(0xe0, IP_ACTIVE_LOW, IPT_UNUSED)
+
+ PORT_START("PLUS2") // Spectrum+ Keys (Same as CAPS + SPACE and CAPS + SYMBOL)
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("BREAK") PORT_CODE(KEYCODE_PAUSE)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("EXT MODE") PORT_CODE(KEYCODE_LCONTROL)
+ PORT_BIT(0xfc, IP_ACTIVE_LOW, IPT_UNUSED)
+
+ PORT_START("PLUS3") // Spectrum+ Keys (Same as SYMBOL SHIFT + O/P)
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("\"") PORT_CODE(KEYCODE_QUOTE)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME(";") PORT_CODE(KEYCODE_COLON)
+ PORT_BIT(0xfc, IP_ACTIVE_LOW, IPT_UNUSED)
+
+ PORT_START("PLUS4") // Spectrum+ Keys (Same as SYMBOL SHIFT + N/M)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME(".") PORT_CODE(KEYCODE_STOP)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME(",") PORT_CODE(KEYCODE_COMMA)
+ PORT_BIT(0xf3, IP_ACTIVE_LOW, IPT_UNUSED)
+INPUT_PORTS_END
+
+INPUT_PORTS_START( spec_plus )
+ PORT_INCLUDE( spec128 )
+ PORT_INCLUDE( spec_plus_joys )
+
+ PORT_START("MOD_DMA")
+ PORT_CONFNAME( 0x03, 0x00, "DMA")
+ PORT_CONFSETTING( 0x00, DEF_STR( No ))
+ PORT_CONFSETTING( 0x01, "UA858D")
+ PORT_CONFSETTING( 0x03, "Zilog")
+ PORT_CONFNAME( 0x04, 0x00, "DMA Port") PORT_CONDITION("MOD_DMA", 0x01, EQUALS, 0x01)
+ PORT_CONFSETTING( 0x00, "11: MB02+")
+ PORT_CONFSETTING( 0x04, "107: DATAGEAR")
+INPUT_PORTS_END
+
void spectrum_128_state::machine_start()
{
spectrum_state::machine_start();
save_item(NAME(m_port_7ffd_data));
- /* rom 0 is 128K rom, rom 1 is 48 BASIC */
+ // rom 0 is 128K rom, rom 1 is 48 BASIC
memory_region *rom = memregion("maincpu");
m_bank_rom[0]->configure_entries(0, 2, rom->base() + 0x10000, 0x4000);
@@ -302,17 +376,26 @@ void spectrum_128_state::machine_start()
for (auto i = 1; i < 4; i++)
m_bank_ram[i]->configure_entries(0, ram_entries, m_ram->pointer(), 0x4000);
- m_bank_ram[1]->set_entry(ram_entries > 5 ? 5 : (ram_entries - 1)); /* Bank 5 is always in 0x4000 - 0x7fff */
- m_bank_ram[2]->set_entry(2); /* Bank 2 is always in 0x8000 - 0xbfff */
+ m_bank_ram[1]->set_entry(ram_entries > 5 ? 5 : (ram_entries - 1)); // Bank 5 is always in 0x4000 - 0x7fff
+ m_bank_ram[2]->set_entry(2); // Bank 2 is always in 0x8000 - 0xbfff
}
void spectrum_128_state::machine_reset()
{
spectrum_state::machine_reset();
- /* set initial ram config */
+ // set initial ram config
m_port_7ffd_data = 0;
spectrum_128_update_memory();
+
+ const u8 mod_dma = m_mod_dma.read_safe(0);
+ if (mod_dma & 1)
+ {
+ m_dma->set_dma_mode(mod_dma & 2 ? z80dma_device::dma_mode::ZILOG : z80dma_device::dma_mode::UA858D);
+
+ const u8 port = mod_dma & 4 ? 0x6b : 0x0b;
+ m_maincpu->space(AS_IO).install_readwrite_handler(port, port, 0, 0xff00, 0, read8smo_delegate(*m_dma, FUNC(z80dma_device::read)), write8smo_delegate(*m_dma, FUNC(z80dma_device::write)));
+ }
}
bool spectrum_128_state::is_vram_write(offs_t offset) {
@@ -329,13 +412,13 @@ bool spectrum_128_state::is_contended(offs_t offset) {
static const gfx_layout spectrum_charlayout =
{
- 8, 8, /* 8 x 8 characters */
- 96, /* 96 characters */
- 1, /* 1 bits per pixel */
- { 0 }, /* no bitplanes */
- {STEP8(0, 1)}, /* x offsets */
- {STEP8(0, 8)}, /* y offsets */
- 8*8 /* every char takes 8 bytes */
+ 8, 8, // 8 x 8 characters
+ 96, // 96 characters
+ 1, // 1 bits per pixel
+ { 0 }, // no bitplanes
+ {STEP8(0, 1)}, // x offsets
+ {STEP8(0, 8)}, // y offsets
+ 8*8 // every char takes 8 bytes
};
static GFXDECODE_START( spec128 )
@@ -358,26 +441,35 @@ void spectrum_128_state::spectrum_128(machine_config &config)
m_maincpu->set_m1_map(&spectrum_128_state::spectrum_128_fetch);
m_maincpu->set_vblank_int("screen", FUNC(spectrum_128_state::spec_interrupt));
m_maincpu->nomreq_cb().set(FUNC(spectrum_128_state::spectrum_nomreq));
+ m_maincpu->busack_cb().set(m_dma, FUNC(z80dma_device::bai_w));
config.set_maximum_quantum(attotime::from_hz(60));
- /* video hardware */
+ Z80DMA(config, m_dma, X1_128_SINCLAIR / 10);
+ m_dma->out_busreq_callback().set_inputline(m_maincpu, Z80_INPUT_LINE_BUSRQ);
+ m_dma->out_int_callback().set_inputline(m_maincpu, INPUT_LINE_IRQ0);
+ m_dma->in_mreq_callback().set([this](offs_t offset) { return m_maincpu->space(AS_PROGRAM).read_byte(offset); });
+ m_dma->out_mreq_callback().set([this](offs_t offset, u8 data) { m_maincpu->space(AS_PROGRAM).write_byte(offset, data); });
+ m_dma->in_iorq_callback().set([this](offs_t offset) { return m_maincpu->space(AS_IO).read_byte(offset); });
+ m_dma->out_iorq_callback().set([this](offs_t offset, u8 data) { m_maincpu->space(AS_IO).write_byte(offset, data); });
+
+ // video hardware
rectangle visarea = { get_screen_area().left() - SPEC_LEFT_BORDER, get_screen_area().right() + SPEC_RIGHT_BORDER,
get_screen_area().top() - SPEC_TOP_BORDER, get_screen_area().bottom() + SPEC_BOTTOM_BORDER };
m_screen->set_raw(X1_128_SINCLAIR / 5, SPEC128_CYCLES_PER_LINE * 2, SPEC128_UNSEEN_LINES + SPEC_SCREEN_HEIGHT, visarea);
subdevice("gfxdecode")->set_info(spec128);
- /* sound hardware */
+ // sound hardware
AY8912(config, "ay8912", X1_128_SINCLAIR / 20).add_route(ALL_OUTPUTS, "mono", 0.25);
- /* expansion port */
+ // expansion port
SPECTRUM_EXPANSION_SLOT(config.replace(), m_exp, spec128_expansion_devices, nullptr);
m_exp->irq_handler().set_inputline(m_maincpu, INPUT_LINE_IRQ0);
m_exp->nmi_handler().set_inputline(m_maincpu, INPUT_LINE_NMI);
m_exp->fb_r_handler().set(FUNC(spectrum_128_state::floating_bus_r));
- /* internal ram */
+ // internal ram
m_ram->set_default_size("128K");
}
diff --git a/src/mame/sinclair/spec128.h b/src/mame/sinclair/spec128.h
index 819a7502978..f748fb9563b 100644
--- a/src/mame/sinclair/spec128.h
+++ b/src/mame/sinclair/spec128.h
@@ -13,14 +13,18 @@
#include "spectrum.h"
+#include "machine/z80dma.h"
+
class spectrum_128_state : public spectrum_state
{
public:
spectrum_128_state(const machine_config &mconfig, device_type type, const char *tag) :
- spectrum_state(mconfig, type, tag),
- m_bank_rom(*this, "bank_rom%u", 0U),
- m_bank_ram(*this, "bank_ram%u", 0U)
+ spectrum_state(mconfig, type, tag)
+ , m_bank_rom(*this, "bank_rom%u", 0U)
+ , m_bank_ram(*this, "bank_ram%u", 0U)
+ , m_dma(*this, "dma_ext")
+ , m_mod_dma(*this, "MOD_DMA")
{ }
void spectrum_128(machine_config &config);
@@ -33,6 +37,7 @@ protected:
virtual void machine_start() override ATTR_COLD;
virtual void machine_reset() override ATTR_COLD;
+ virtual void bank3_set_page(u8 page) override;
virtual void spectrum_128_update_memory() override;
virtual rectangle get_screen_area() override;
@@ -55,12 +60,16 @@ private:
void spectrum_128_io(address_map &map) ATTR_COLD;
void spectrum_128_mem(address_map &map) ATTR_COLD;
void spectrum_128_fetch(address_map &map) ATTR_COLD;
+
+ optional_device m_dma;
+
+ optional_ioport m_mod_dma;
};
#define X1_128_AMSTRAD 35'469'000 // Main clock (Amstrad 128K model, +2A?)
#define X1_128_SINCLAIR 35.469_MHz_XTAL // Main clock (Sinclair 128K model)
-/* 128K machines take an extra 4 cycles per scan line - add this to retrace */
+// 128K machines take an extra 4 cycles per scan line - add this to retrace
#define SPEC128_UNSEEN_LINES 15
#define SPEC128_RETRACE_CYCLES 52
#define SPEC128_CYCLES_PER_LINE 228
diff --git a/src/mame/sinclair/spec_snqk.cpp b/src/mame/sinclair/spec_snqk.cpp
index 93db167cb22..6a6b69708c5 100644
--- a/src/mame/sinclair/spec_snqk.cpp
+++ b/src/mame/sinclair/spec_snqk.cpp
@@ -206,6 +206,15 @@ SNAPSHOT_LOAD_MEMBER(spectrum_state::snapshot_cb)
setup_frz(&snapshot_data[0], snapshot_size);
}
+ else if (image.is_filetype("spg"))
+ {
+ if (snapshot_data[32] != 'S' || snapshot_data[33] != 'p' || snapshot_data[34] != 'e' || snapshot_data[35] != 'c'
+ || snapshot_data[36] != 't' || snapshot_data[37] != 'r' || snapshot_data[38] != 'u' || snapshot_data[39] != 'm'
+ || snapshot_data[40] != 'P' || snapshot_data[41] != 'r' ||snapshot_data[42] != 'o' || snapshot_data[43] != 'g')
+ return std::make_pair(image_error::INVALIDIMAGE, "Invalid .SPG file header.");
+
+ setup_spg(&snapshot_data[0], snapshot_size);
+ }
else
{
setup_z80(&snapshot_data[0], snapshot_size);
@@ -2396,6 +2405,449 @@ void spectrum_state::setup_z80(const uint8_t *snapdata, uint32_t snapsize)
}
}
+void spectrum_state::hrust_decompress_block(address_space &space, const u8 *source, u16 dest, u16 size)
+{
+ class bb_stream
+ {
+ private:
+ const u8 *m_base;
+ const u8 *m_read;
+ int m_offset;
+ int m_length;
+ bool m_eof;
+ u16 m_buffer;
+
+ public:
+ bb_stream(const u8 *src, int src_length)
+ {
+ m_base = m_read = src;
+
+ m_length = src_length;
+ m_offset = 0;
+ m_eof = false;
+
+ m_buffer = get_byte();
+ m_buffer += get_byte() << 8;
+ }
+
+ u8 get_byte()
+ {
+ m_eof |= ((m_read - m_base) == m_length);
+ return m_eof ? 0 : *m_read++;
+ }
+
+ u8 get_bit()
+ {
+ u8 bit = BIT(m_buffer, 15 - m_offset);
+ if (m_offset == 15)
+ {
+ m_buffer = get_byte();
+ m_buffer += get_byte() << 8;
+ }
+ m_offset = (m_offset + 1) & 0xf;
+
+ return bit;
+ }
+
+ u8 get_bits(u8 n)
+ {
+ u8 r = 0;
+ do
+ {
+ r = (r << 1) + get_bit();
+ } while (--n);
+
+ return r;
+ }
+
+ bool overflow() { return m_eof; }
+ };
+
+ constexpr u8 mask[] = { 0, 0, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, 0 };
+ u8 no_bits = 2;
+ bb_stream bitbuf(source, size);
+
+ space.write_byte(dest++, bitbuf.get_byte());
+
+ while (!bitbuf.overflow())
+ {
+ while (bitbuf.get_bit())
+ {
+ space.write_byte(dest++, bitbuf.get_byte());
+ }
+
+ u16 len = 0;
+ u8 bb;
+ do
+ {
+ bb = bitbuf.get_bits(2);
+ len += bb;
+
+ } while (bb == 0x03 && len != 0x0f);
+
+ s16 offset = 0;
+ if (len == 0)
+ {
+ offset = 0xfff8 + bitbuf.get_bits(3);
+ space.write_byte(dest, space.read_byte(dest + offset));
+ ++dest;
+ continue;
+ }
+ else if (len == 1)
+ {
+ const u8 code = bitbuf.get_bits(2);
+ if (code == 0 || code == 1)
+ {
+ offset = bitbuf.get_byte();
+ offset += (code ? 0xfe : 0xfd) << 8;
+ }
+ else if (code == 2)
+ {
+ u8 b = bitbuf.get_byte();
+ if (b >= 0xe0)
+ {
+ b <<= 1;
+ ++b; // rlca
+ b ^= 2; // xor c
+
+ if (b == 0xff)
+ {
+ ++no_bits;
+ continue;
+ }
+
+ offset = 0xff00 + b - 0x0f;
+ space.write_byte(dest, space.read_byte(dest + offset));
+ ++dest;
+ space.write_byte(dest++, bitbuf.get_byte());
+ space.write_byte(dest, space.read_byte(dest + offset));
+ ++dest;
+ continue;
+ }
+ offset = 0xff00 + b;
+ }
+ else if (code == 3)
+ {
+ offset = 0xffe0 + bitbuf.get_bits(5);
+ }
+
+ for (auto i = 0; i < 2; ++i)
+ {
+ space.write_byte(dest, space.read_byte(dest + offset));
+ ++dest;
+ }
+ continue;
+ }
+ else if (len == 3)
+ {
+ if (bitbuf.get_bit())
+ {
+ offset = 0xfff0 + bitbuf.get_bits(4);
+ space.write_byte(dest, space.read_byte(dest + offset));
+ ++dest;
+ space.write_byte(dest++, bitbuf.get_byte());
+ space.write_byte(dest, space.read_byte(dest + offset));
+ ++dest;
+ continue;
+ }
+
+ if (bitbuf.get_bit())
+ {
+ u8 bytes_no = 6 + bitbuf.get_bits(4);
+ for (u8 i = 0; i < (bytes_no << 1); ++i)
+ space.write_byte(dest++, bitbuf.get_byte());
+ continue;
+ }
+
+ len = bitbuf.get_bits(7);
+ if (len == 0x0f)
+ {
+ break; // EOF
+ }
+ if (len < 0x0f)
+ {
+ len = (len << 8) + bitbuf.get_byte();
+ }
+ }
+
+ if (len == 2)
+ {
+ ++len;
+ }
+
+
+ const u8 code = bitbuf.get_bits(2);
+ if (code == 0)
+ {
+ offset = 0xfe00 + bitbuf.get_byte();
+ }
+ else if (code == 1)
+ {
+ u8 b = bitbuf.get_byte();
+
+ if (b >= 0xe0)
+ {
+ if (len > 3)
+ {
+ // logerror
+ break;
+ }
+
+ b <<= 1;
+ ++b; // rlca
+ b ^= 3; // xor c
+
+ offset = 0xff00 + b - 0x0f;
+
+ space.write_byte(dest, space.read_byte(dest + offset));
+ ++dest;
+ space.write_byte(dest++, bitbuf.get_byte());
+ space.write_byte(dest, space.read_byte(dest + offset));
+ ++dest;
+ continue;
+ }
+ offset = 0xff00 + b;
+ }
+ else if (code == 2)
+ {
+ offset = 0xffe0 + bitbuf.get_bits(5);
+ }
+ else if (code == 3)
+ {
+ offset = (mask[no_bits] + bitbuf.get_bits(no_bits)) << 8;
+ offset += bitbuf.get_byte();
+ }
+
+ for (u16 i = 0; i < len; ++i)
+ {
+ space.write_byte(dest, space.read_byte(dest + offset));
+ ++dest;
+ }
+ }
+}
+
+void spectrum_state::mlz_decompress_block(address_space &space, const u8 *source, u16 dest, u16 size)
+{
+ class de_mlz
+ {
+ private:
+ address_space &m_space;
+ const u8 *m_src;
+ u16 m_to;
+ u8 m_buffer;
+ int m_buffer_size;
+
+ public:
+ de_mlz(address_space &space, const u8 *src, u16 dst) : m_space(space)
+ {
+ m_src = src;
+ m_to = dst;
+ }
+
+ void init_bitstream()
+ {
+ m_buffer = get_byte();
+ m_buffer_size = 8;
+ }
+
+ u8 get_byte()
+ {
+ return *m_src++;
+ }
+
+ void put_byte(u8 val)
+ {
+ m_space.write_byte(m_to++, val);
+ }
+
+ void repeat(u32 disp, int num)
+ {
+ for (int i = 0; i < num; i++)
+ {
+ u8 val = m_space.read_byte(m_to - disp);
+ put_byte(val);
+ }
+ }
+
+ // gets specified number of bits from bitstream
+ // returns them LSB-aligned
+ u32 get_bits(int count)
+ {
+ u32 bits = 0;
+ while (count--)
+ {
+ if (m_buffer_size--)
+ {
+ bits <<= 1;
+ bits |= 1 & (m_buffer >> 7);
+ m_buffer <<= 1;
+ }
+ else
+ {
+ init_bitstream();
+ count++; // repeat loop once more
+ }
+ }
+
+ return bits;
+ }
+
+ int get_bigdisp()
+ {
+ u32 bits;
+
+ // inter displacement
+ if (get_bits(1))
+ {
+ bits = get_bits(4);
+ return 0x1100 - (bits << 8) - get_byte();
+ }
+
+ // shorter displacement
+ else
+ return 256 - get_byte();
+ }
+ };
+
+ de_mlz s(space, source, dest);
+ u32 done = 0;
+ int i;
+
+ // get first byte of packed file and write to output
+ s.put_byte(s.get_byte());
+
+ // second byte goes to bitstream
+ s.init_bitstream();
+
+ // actual depacking loop!
+ do
+ {
+ // get 1st bit - either OUTBYTE or beginning of LZ code
+ // OUTBYTE
+ if (s.get_bits(1))
+ s.put_byte(s.get_byte());
+
+ // LZ code
+ else
+ {
+ switch (s.get_bits(2))
+ {
+ case 0: // 000
+ s.repeat(8 - s.get_bits(3), 1);
+ break;
+
+ case 1: // 001
+ s.repeat(256 - s.get_byte(), 2);
+ break;
+
+ case 2: // 010
+ s.repeat(s.get_bigdisp(), 3);
+ break;
+
+ case 3: // 011
+ // extract num of length bits
+ for (i = 1; !s.get_bits(1); i++)
+ ;
+
+ // check for exit code
+ if (i == 9)
+ {
+ done = 1;
+ }
+ else if (i <= 7)
+ {
+ // get length bits itself
+ int bits = s.get_bits(i);
+ s.repeat(s.get_bigdisp(), 2 + (1 << i) + bits);
+ }
+ break;
+ }
+ }
+ } while (!done);
+}
+
+/*
+ Load a .SPG (Spectrum Prog) file.
+
+ v1.1: https://raw.githubusercontent.com/tslabs/zx-evo/master/pentevo/docs/Formats/SPGv1_1.txt
+ v1.0: https://raw.githubusercontent.com/tslabs/zx-evo/master/pentevo/docs/Formats/SPGv1_0.txt
+ v0.2 https://raw.githubusercontent.com/tslabs/zx-evo/master/pentevo/docs/Formats/SPGv0_2.txt
+*/
+void spectrum_state::setup_spg(const u8 *snapdata, u32 snapsize)
+{
+ u16 data;
+ address_space &space = m_maincpu->space(AS_PROGRAM);
+
+ data = snapdata[SPG_OFFSET + 0x2c];
+ if (BIT(data, 4, 4) != 1 || BIT(data, 0, 4) != 0) // just v1.0 for now
+ {
+ logerror("Can't load .SPG file v%d.%d\n", BIT(data, 4, 4), BIT(data, 0, 4));
+ return;
+ }
+
+ m_maincpu->set_state_int(Z80_IY, 0x5c3a);
+ m_maincpu->set_state_int(Z80_HL2, 0x2758);
+ m_maincpu->set_state_int(Z80_I, 0x3f);
+ m_maincpu->set_state_int(Z80_IM, 1);
+ m_port_7ffd_data = 16;
+
+ data = (snapdata[SPG_OFFSET + 0x31] << 8) | snapdata[SPG_OFFSET + 0x30];
+ if (data < 0x4000)
+ {
+ logerror("PC(%04x) < 0x4000 is not allowed\n", data);
+ }
+ m_maincpu->set_state_int(Z80_PC, data);
+
+ data = (snapdata[SPG_OFFSET + 0x33] << 8) | snapdata[SPG_OFFSET + 0x32];
+ m_maincpu->set_state_int(Z80_SP, data);
+
+ const u8 page3 = snapdata[SPG_OFFSET + 0x34];
+
+ data = snapdata[SPG_OFFSET + 0x35];
+ m_maincpu->set_state_int(Z80_IFF1, BIT(data, 2));
+
+ offs_t data_offset = SPG_DATA;
+ for (auto b = 0; b < 0x100; b++)
+ {
+ data = snapdata[SPG_BLOCK_INFO(b) + 0];
+ const u16 offs = BIT(data, 0, 5) * 512;
+ const bool is_last = BIT(data, 7);
+
+ data = snapdata[SPG_BLOCK_INFO(b) + 1];
+ const u16 size = (BIT(data, 0, 5) + 1) * 512;
+ const u8 compression = BIT(data, 6, 2);
+
+ data = snapdata[SPG_BLOCK_INFO(b) + 2];
+ bank3_set_page(data);
+
+ switch (compression)
+ {
+ case 0x00:
+ for (auto i = 0; i < size; i++)
+ space.write_byte(0xc000 + offs + i, snapdata[data_offset + i]);
+ break;
+
+ case 0x01:
+ mlz_decompress_block(space, &snapdata[data_offset], 0xc000 + offs, size);
+ break;
+
+ case 0x02:
+ hrust_decompress_block(space, &snapdata[data_offset], 0xc000 + offs, size);
+ break;
+
+ default:
+ logerror("Unsupported compression: %d\n", compression);
+ return;
+ }
+
+ data_offset += size;
+ if (is_last)
+ break;
+ }
+
+ bank3_set_page(page3);
+}
+
QUICKLOAD_LOAD_MEMBER(spectrum_state::quickload_cb)
{
size_t quickload_size = image.length();
diff --git a/src/mame/sinclair/spec_snqk.h b/src/mame/sinclair/spec_snqk.h
index 419820aba0d..587b7e92460 100644
--- a/src/mame/sinclair/spec_snqk.h
+++ b/src/mame/sinclair/spec_snqk.h
@@ -119,6 +119,15 @@
#define SNX_COMPRESSED 0xff
#define SNX_UNCOMPRESSED 0x00
+/*****************************************************************************
+ *
+ * .SPG format (used by TS-Conf, BASECONF, Next)
+ *
+ ****************************************************************************/
+#define SPG_OFFSET 0
+#define SPG_BLOCK_INFO(_n) (SPG_OFFSET + 0x100 + (3 * _n))
+#define SPG_DATA SPG_BLOCK_INFO(256)
+
/*****************************************************************************
*
* .FRZ format (used by CBSpeccy, ZX-Live and ASp)
diff --git a/src/mame/sinclair/specnext.cpp b/src/mame/sinclair/specnext.cpp
index c34a1628494..da0e8739f51 100644
--- a/src/mame/sinclair/specnext.cpp
+++ b/src/mame/sinclair/specnext.cpp
@@ -80,7 +80,7 @@ public:
, m_view7(*this, "mem_view7")
, m_copper(*this, "copper")
, m_ctc(*this, "ctc")
- , m_dma(*this, "ndma")
+ , m_dma(*this, "dma")
, m_i2cmem(*this, "i2cmem")
, m_sdcard(*this, "sdcard")
, m_ay(*this, "ay%u", 0U)
@@ -2256,7 +2256,7 @@ void specnext_state::nr_1a_ula_clip_y2_w(u8 data)
static const z80_daisy_config z80_daisy_chain[] =
{
- { "ndma" },
+ { "dma" },
{ "ctc" },
{ nullptr }
};
diff --git a/src/mame/sinclair/specnext_dma.cpp b/src/mame/sinclair/specnext_dma.cpp
index 7fbcae4f9cf..4c2b29a7d85 100644
--- a/src/mame/sinclair/specnext_dma.cpp
+++ b/src/mame/sinclair/specnext_dma.cpp
@@ -33,33 +33,22 @@ DEFINE_DEVICE_TYPE(SPECNEXT_DMA, specnext_dma_device, "specnext_dma", "Spectrum
specnext_dma_device::specnext_dma_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
- : z80dma_device(mconfig, SPECNEXT_DMA, tag, owner, clock)
+ : z80dma_device(mconfig, SPECNEXT_DMA, tag, owner, clock, dma_mode::ZILOG)
{
}
void specnext_dma_device::write(u8 data)
{
- z80dma_device::write(data);
-
- if (num_follow() == 0)
+ if (!m_ndma_mode && data == COMMAND_ENABLE_DMA && num_follow() == 0)
{
- if ((data & 0x83) == 0x83) // WR6
- {
- switch (data)
- {
- case COMMAND_ENABLE_DMA:
- m_byte_counter = 0;
- break;
- default:
- break;
- }
- }
+ m_byte_counter = 0;
}
+ z80dma_device::write(data);
}
void specnext_dma_device::do_write()
{
- if (m_dma_mode)
+ if (m_ndma_mode)
{
z80dma_device::do_write();
return;
@@ -101,12 +90,12 @@ void specnext_dma_device::device_start()
{
z80dma_device::device_start();
- save_item(NAME(m_dma_mode));
+ save_item(NAME(m_ndma_mode));
}
void specnext_dma_device::device_reset()
{
z80dma_device::device_reset();
- m_dma_mode = 0;
+ m_ndma_mode = 0;
}
diff --git a/src/mame/sinclair/specnext_dma.h b/src/mame/sinclair/specnext_dma.h
index e1bc1fa19f7..66225b3c456 100644
--- a/src/mame/sinclair/specnext_dma.h
+++ b/src/mame/sinclair/specnext_dma.h
@@ -12,7 +12,7 @@ class specnext_dma_device : public z80dma_device
public:
specnext_dma_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- void dma_mode_w(bool dma_mode) { m_dma_mode = dma_mode; }
+ void dma_mode_w(bool dma_mode) { m_ndma_mode = dma_mode; }
virtual void write(u8 data) override;
@@ -23,7 +23,7 @@ protected:
virtual void do_write() override;
private:
- bool m_dma_mode; // 0 = zxn dma, 1 = z80 dma
+ bool m_ndma_mode; // 0 = zxn dma, 1 = z80 dma
};
DECLARE_DEVICE_TYPE(SPECNEXT_DMA, specnext_dma_device)
diff --git a/src/mame/sinclair/spectrum.cpp b/src/mame/sinclair/spectrum.cpp
index 25a0b41df8b..e0870c351a0 100644
--- a/src/mame/sinclair/spectrum.cpp
+++ b/src/mame/sinclair/spectrum.cpp
@@ -580,25 +580,7 @@ void spectrum_state::spectrum_clone_io(address_map &map)
/* Input ports */
-/****************************************************************************************************/
-
-static INPUT_PORTS_START( spec_plus_joys )
- PORT_START("JOY2") /* 0xF7FE */
- PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT) PORT_8WAY PORT_PLAYER(2) PORT_CODE(JOYCODE_X_LEFT_SWITCH)
- PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT) PORT_8WAY PORT_PLAYER(2) PORT_CODE(JOYCODE_X_RIGHT_SWITCH)
- PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN) PORT_8WAY PORT_PLAYER(2) PORT_CODE(JOYCODE_Y_DOWN_SWITCH)
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_UP) PORT_8WAY PORT_PLAYER(2) PORT_CODE(JOYCODE_Y_UP_SWITCH)
- PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_BUTTON1) PORT_PLAYER(2) PORT_CODE(JOYCODE_BUTTON1)
-
- PORT_START("JOY1") /* 0xEFFE */
- PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_BUTTON1) PORT_PLAYER(1) PORT_CODE(JOYCODE_BUTTON1)
- PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_UP) PORT_8WAY PORT_PLAYER(1) PORT_CODE(JOYCODE_Y_UP_SWITCH)
- PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN) PORT_8WAY PORT_PLAYER(1) PORT_CODE(JOYCODE_Y_DOWN_SWITCH)
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT) PORT_8WAY PORT_PLAYER(1) PORT_CODE(JOYCODE_X_RIGHT_SWITCH)
- PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT) PORT_8WAY PORT_PLAYER(1) PORT_CODE(JOYCODE_X_LEFT_SWITCH)
-INPUT_PORTS_END
-
-/*
+/****************************************************************************************************
Spectrum keyboard is quite complicate to emulate. Each key can have 5 or 6 different functions, depending on which input mode we are in:
-------------------------------------------------------------------------------------------------------------------
@@ -693,48 +675,6 @@ INPUT_PORTS_START( spectrum )
PORT_BIT(0x7f, IP_ACTIVE_LOW, IPT_UNUSED)
INPUT_PORTS_END
-/* These keys need not to be mapped in natural mode because Spectrum+ supports both these and the Spectrum sequences above.
- Hence, we can simply keep using such sequences in natural keyboard emulation */
-INPUT_PORTS_START( spec128 )
- PORT_INCLUDE( spectrum )
-
- PORT_START("PLUS0") /* Spectrum+ Keys (Same as CAPS + 1-5) */
- PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("EDIT") PORT_CODE(KEYCODE_INSERT)
- PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("CAPS LOCK") PORT_CODE(KEYCODE_CAPSLOCK)
- PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("TRUE VID") PORT_CODE(KEYCODE_HOME)
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("INV VID") PORT_CODE(KEYCODE_END)
- PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Cursor Left") PORT_CODE(KEYCODE_LEFT)
- PORT_BIT(0xe0, IP_ACTIVE_LOW, IPT_UNUSED)
-
- PORT_START("PLUS1") /* Spectrum+ Keys (Same as CAPS + 6-0) */
- PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("DEL") PORT_CODE(KEYCODE_BACKSPACE) PORT_CHAR(8)
- PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("GRAPH") PORT_CODE(KEYCODE_LALT)
- PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Cursor Right") PORT_CODE(KEYCODE_RIGHT)
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Cursor Up") PORT_CODE(KEYCODE_UP)
- PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Cursor Down") PORT_CODE(KEYCODE_DOWN)
- PORT_BIT(0xe0, IP_ACTIVE_LOW, IPT_UNUSED)
-
- PORT_START("PLUS2") /* Spectrum+ Keys (Same as CAPS + SPACE and CAPS + SYMBOL) */
- PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("BREAK") PORT_CODE(KEYCODE_PAUSE)
- PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("EXT MODE") PORT_CODE(KEYCODE_LCONTROL)
- PORT_BIT(0xfc, IP_ACTIVE_LOW, IPT_UNUSED)
-
- PORT_START("PLUS3") /* Spectrum+ Keys (Same as SYMBOL SHIFT + O/P) */
- PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("\"") PORT_CODE(KEYCODE_QUOTE)
- PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME(";") PORT_CODE(KEYCODE_COLON)
- PORT_BIT(0xfc, IP_ACTIVE_LOW, IPT_UNUSED)
-
- PORT_START("PLUS4") /* Spectrum+ Keys (Same as SYMBOL SHIFT + N/M) */
- PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME(".") PORT_CODE(KEYCODE_STOP)
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME(",") PORT_CODE(KEYCODE_COMMA)
- PORT_BIT(0xf3, IP_ACTIVE_LOW, IPT_UNUSED)
-INPUT_PORTS_END
-
-INPUT_PORTS_START( spec_plus )
- PORT_INCLUDE( spec128 )
- PORT_INCLUDE( spec_plus_joys )
-INPUT_PORTS_END
-
/* Machine initialization */
void spectrum_state::init_spectrum()
{
@@ -835,7 +775,9 @@ void spectrum_state::spectrum_common(machine_config &config)
m_exp->fb_r_handler().set(FUNC(spectrum_state::floating_bus_r));
/* devices */
- SNAPSHOT(config, "snapshot", "ach,frz,plusd,prg,sem,sit,sna,snp,snx,sp,z80,zx").set_load_callback(FUNC(spectrum_state::snapshot_cb));
+ snapshot_image_device &snapshot(SNAPSHOT(config, "snapshot", "ach,frz,plusd,prg,sem,sit,sna,snp,snx,sp,spg,z80,zx"));
+ snapshot.set_load_callback(FUNC(spectrum_state::snapshot_cb));
+ snapshot.set_interface("spectrum_snapshot");
QUICKLOAD(config, "quickload", "raw,scr", attotime::from_seconds(2)).set_load_callback(FUNC(spectrum_state::quickload_cb)); // The delay prevents the screen from being cleared by the RAM test at boot
CASSETTE(config, m_cassette);
diff --git a/src/mame/sinclair/spectrum.h b/src/mame/sinclair/spectrum.h
index f14ed0fe4e9..efd1eca56c5 100644
--- a/src/mame/sinclair/spectrum.h
+++ b/src/mame/sinclair/spectrum.h
@@ -90,6 +90,7 @@ protected:
virtual void video_start() override ATTR_COLD;
// until machine/spec_snqk.cpp gets somehow disentangled
+ virtual void bank3_set_page(u8 page) { }
virtual void plus3_update_memory() { }
virtual void spectrum_128_update_memory() { }
virtual void ts2068_update_memory() { }
@@ -207,7 +208,9 @@ protected:
void setup_frz(const uint8_t *snapdata, uint32_t snapsize);
void z80_decompress_block(address_space &space, const uint8_t *source, uint16_t dest, uint16_t size);
void setup_z80(const uint8_t *snapdata, uint32_t snapsize);
-
+ void hrust_decompress_block(address_space &space, const u8 *source, u16 dest, u16 size);
+ void mlz_decompress_block(address_space &space, const u8 *source, u16 dest, u16 size);
+ void setup_spg(const u8 *snapdata, u32 snapsize);
// quickload helpers
void log_quickload(const char *type, uint32_t start, uint32_t length, uint32_t exec, const char *exec_format);
void setup_scr(const uint8_t *quickdata, uint32_t quicksize);
diff --git a/src/mame/sinclair/sprinter.cpp b/src/mame/sinclair/sprinter.cpp
index 63ed92f6234..48a80727e98 100644
--- a/src/mame/sinclair/sprinter.cpp
+++ b/src/mame/sinclair/sprinter.cpp
@@ -103,6 +103,7 @@ public:
void sprinter(machine_config &config);
INPUT_CHANGED_MEMBER(turbo_changed);
+ INPUT_CHANGED_MEMBER(on_nmi);
protected:
virtual void machine_start() override ATTR_COLD;
@@ -259,6 +260,7 @@ private:
bool m_turbo;
bool m_turbo_hard;
bool m_arom16;
+ bool m_nmi_ena;
u8 m_rom_rg;
u8 m_pn;
u8 m_sc;
@@ -317,7 +319,7 @@ void sprinter_state::update_memory()
else
{
const bool cash_on = 0;
- const bool nmi_ena = 1;
+ const bool nmi_ena = m_nmi_ena;
const bool sc0 = BIT(m_sc, 0);
const bool sc_lc = !(sc0 && m_ram_sys) && !cash_on;
const u8 spr_ = BIT(m_sc, 1) ? 0 : ((m_dos << 1) | (BIT(m_pn, 4) || !m_dos));
@@ -1428,6 +1430,7 @@ void sprinter_state::machine_start()
save_item(NAME(m_turbo));
save_item(NAME(m_turbo_hard));
save_item(NAME(m_arom16));
+ save_item(NAME(m_nmi_ena));
save_item(NAME(m_rom_rg));
save_item(NAME(m_pn));
save_item(NAME(m_sc));
@@ -1471,6 +1474,13 @@ void sprinter_state::machine_start()
m_dcp_location = m_ram->pointer() + (0x40 << 14);
m_maincpu->space(AS_PROGRAM).specific(m_program);
+ for (int addr = 0; addr < m_fastram.bytes(); ++addr)
+ m_fastram.target()[addr] = machine().rand();
+ for (int addr = 0; addr < m_vram.bytes(); ++addr)
+ m_vram.target()[addr] = machine().rand();
+ for (int addr = 0; addr < m_ram->size(); ++addr)
+ m_ram->pointer()[addr] = machine().rand();
+
const u8 port_default[0x40] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Cx - SYS PORTS COPIES
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, // Dx - RAM PAGES
@@ -1485,6 +1495,31 @@ void sprinter_state::machine_start()
m_hold = {0, 0}; // cb
m_conf_loading = 1;
m_conf = 0;
+
+ int idx = Z84_MCR + 1;
+ m_maincpu->state_add_divider(-1);
+ m_maincpu->state_add(idx++, "PG0", m_pages[0]);
+ m_maincpu->state_add(idx++, "PG1", m_pages[1]);
+ m_maincpu->state_add(idx++, "PG2", m_pages[2]);
+ m_maincpu->state_add(idx++, "PG3", m_pages[3]);
+ m_maincpu->state_add(idx++, "7FFD", m_pn);
+ m_maincpu->state_add(idx++, "1FFD", m_sc);
+
+ m_maincpu->state_add_divider(-1);
+
+ m_maincpu->state_add(idx++, "DOS OFF", m_dos);
+ m_maincpu->state_add(idx++, "CNF", m_cnf);
+ m_maincpu->state_add(idx++, "PORT_Y", m_port_y);
+ m_maincpu->state_add(idx++, "RGMOD", m_rgmod);
+
+ m_maincpu->state_add_divider(-1);
+ m_maincpu->state_add(idx++, "ACC MODE", m_acc_dir);
+ m_maincpu->state_add(idx++, "ACC Buffer", m_rgacc);
+ m_maincpu->state_add(idx++, "Ext ACC", m_alt_acc);
+ m_maincpu->state_add(idx++, "ACC Counter", m_acc_cnt);
+
+ m_maincpu->state_add_divider(-1);
+ m_maincpu->state_add(idx++, "ISA_ADDR_EXT", m_isa_addr_ext);
}
void sprinter_state::machine_reset()
@@ -1502,6 +1537,7 @@ void sprinter_state::machine_reset()
m_ram_sys = 0;
m_sys_pg = 0;
m_arom16 = 0;
+ m_nmi_ena = 1; // off
m_cnf = 0x00;
m_pn = 0x00;
m_sc = 0x00;
@@ -1703,13 +1739,25 @@ INPUT_CHANGED_MEMBER(sprinter_state::turbo_changed)
update_cpu();
}
+INPUT_CHANGED_MEMBER(sprinter_state::on_nmi)
+{
+ if ((m_io_nmi->read() & 0x01) && m_nmi_ena)
+ {
+ m_nmi_ena = false;
+ update_memory();
+ m_maincpu->pulse_input_line(INPUT_LINE_NMI, attotime::zero);
+ machine().debug_break();
+ }
+}
+
+
INPUT_PORTS_START( sprinter )
/* PORT_NAME = KEY Mode CAPS Mode SYMBOL Mode EXT Mode EXT+Shift Mode BASIC Mode */
PORT_START("IO_LINE0") /* 0xFEFE */
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("CAPS SHIFT") PORT_CODE(KEYCODE_LSHIFT) PORT_CODE(KEYCODE_RSHIFT) PORT_CHAR(UCHAR_SHIFT_1) PORT_CHAR(UCHAR_SHIFT_2)
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("z Z : LN BEEP COPY") PORT_CODE(KEYCODE_Z) PORT_CHAR('z') PORT_CHAR('Z') PORT_CHAR(':')
PORT_CODE(KEYCODE_BACKSLASH)
- PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME(u8"x X £ EXP INK CLEAR") PORT_CODE(KEYCODE_X) PORT_CHAR('x') PORT_CHAR('X') PORT_CHAR(U'£')
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("x X $ EXP INK CLEAR") PORT_CODE(KEYCODE_X) PORT_CHAR('x') PORT_CHAR('X') PORT_CHAR('$')
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("c C ? LPRINT PAPER CONT") PORT_CODE(KEYCODE_C) PORT_CHAR('c') PORT_CHAR('C') PORT_CHAR('?')
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("v V / LLIST FLASH CLS") PORT_CODE(KEYCODE_V) PORT_CHAR('v') PORT_CHAR('V') PORT_CHAR('/')
PORT_CODE(KEYCODE_SLASH) PORT_CODE(KEYCODE_SLASH_PAD)
@@ -1871,6 +1919,9 @@ INPUT_PORTS_START( sprinter )
PORT_BIT(0x8000, IP_ACTIVE_HIGH, IPT_BUTTON6) PORT_PLAYER(2) PORT_CODE(JOYCODE_BUTTON6) PORT_NAME("%p Z")
+ PORT_START("NMI")
+ PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_OTHER) PORT_NAME("NMI") PORT_CODE(KEYCODE_F11) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(sprinter_state::on_nmi), 0)
+
PORT_START("TURBO")
PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_OTHER) PORT_NAME("TURBO") PORT_CODE(KEYCODE_F12) PORT_TOGGLE PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(sprinter_state::turbo_changed), 0)
INPUT_PORTS_END
@@ -1969,6 +2020,12 @@ ROM_START( sprinter )
ROM_SYSTEM_BIOS(4, "v3.04.253", "BIOS v3.04, SETUP v253") // 06.16.2003
ROMX_LOAD( "sp2k-3.04.253.rom", 0x000000, 0x40000, CRC(1729cb5c) SHA1(fb4c9f80651aa87526f141839fb4d6cb86b654c7), ROM_BIOS(4))
+
+ ROM_SYSTEM_BIOS(5, "v3.05.254", "BIOS v3.05, SETUP v254") // 01.01.2022
+ ROMX_LOAD( "sp2k-3.05.254.rom", 0x000000, 0x40000, CRC(fe1c2685) SHA1(10e4e29bdc058cd4380837fb8831ce4f5977f6b8), ROM_BIOS(5))
+
+ ROM_SYSTEM_BIOS(6, "dev", "BIOS v3.06 beta9") // 24.10.2024
+ ROMX_LOAD( "_sprin.bin", 0x000000, 0x40000, CRC(c8e8ca64) SHA1(51757b7953f8260b412286a659647c58426e5283), ROM_BIOS(6))
ROM_END
} // Anonymous namespace
diff --git a/src/mame/sinclair/tsconf.cpp b/src/mame/sinclair/tsconf.cpp
index ebe7ec88a71..44c0d43f9b3 100644
--- a/src/mame/sinclair/tsconf.cpp
+++ b/src/mame/sinclair/tsconf.cpp
@@ -58,8 +58,7 @@ TILE_GET_INFO_MEMBER(tsconf_state::get_tile_info_16c)
u8 *tile_info_addr = &m_ram->pointer()[(m_regs[T_MAP_PAGE] << 14) + row_offset + col_offset];
u8 hi = tile_info_addr[1];
- u32 /*u16*/ tile = ((u16(hi) & 0x0f) << 8) | tile_info_addr[0];
- tile = tile / tilemap.cols() * 64 * 8 + (tile % tilemap.cols()); // same as: tmp_tile_oversized_to_code()
+ u16 tile = ((u16(hi) & 0x0f) << 8) | tile_info_addr[0];
u8 pal = (BIT(m_regs[PAL_SEL], 4 + Layer * 2, 2) << 2) | BIT(hi, 4, 2);
tileinfo.set(TM_TILES0 + Layer, tile, pal, TILE_FLIPYX(BIT(hi, 6, 2)));
tileinfo.category = tile == 0 ? 2 : 1;
@@ -135,23 +134,11 @@ static const gfx_layout tsconf_charlayout =
8 * 8
};
-static const gfx_layout tsconf_tile_16cpp_layout =
-{
- 8,
- 8,
- 64 * 64 * 8,
- 4,
- {STEP4(0, 1)},
- {STEP8(0, 4)},
- {STEP8(0, 256 * 8)}, // Much more tiles when needed. Because tiles are in RAW format but we don't know region properties.
- 8 * 4
-};
-
static GFXDECODE_START(gfx_tsconf)
GFXDECODE_ENTRY("maincpu", 0, tsconf_charlayout, 0xf7, 1) // TM_TS_CHAR : TXT
- GFXDECODE_ENTRY("maincpu", 0, tsconf_tile_16cpp_layout, 0, 16) // TM_TILES0 : T0 16cpp
- GFXDECODE_ENTRY("maincpu", 0, tsconf_tile_16cpp_layout, 0, 16) // TM_TILES1 : T1 16cpp
- GFXDECODE_ENTRY("maincpu", 0, tsconf_tile_16cpp_layout, 0, 16) // TM_SPRITES : Sprites 16cpp
+ GFXDECODE_RAM("tiles0_raw", 0, gfx_8x8x8_raw, 0, 16) // TM_TILES0 : T0 16cpp
+ GFXDECODE_RAM("tiles1_raw", 0, gfx_8x8x8_raw, 0, 16) // TM_TILES1 : T1 16cpp
+ GFXDECODE_RAM("sprites_raw", 0, gfx_8x8x8_raw, 0, 16) // TM_SPRITES : Sprites 16cpp
GFXDECODE_ENTRY("maincpu", 0x1fd00, spectrum_charlayout, 0xf7, 1) // TM_ZX_CHAR
GFXDECODE_END
@@ -164,9 +151,13 @@ void tsconf_state::video_start()
m_ts_tilemap[TM_TILES0] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(tsconf_state::get_tile_info_16c<0>)), TILEMAP_SCAN_ROWS, 8, 8, 64, 64);
m_ts_tilemap[TM_TILES0]->set_transparent_pen(0);
+ m_gfxdecode->gfx(TM_TILES0)->set_granularity(16);
m_ts_tilemap[TM_TILES1] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(tsconf_state::get_tile_info_16c<1>)), TILEMAP_SCAN_ROWS, 8, 8, 64, 64);
m_ts_tilemap[TM_TILES1]->set_transparent_pen(0);
+ m_gfxdecode->gfx(TM_TILES1)->set_granularity(16);
+
+ m_gfxdecode->gfx(TM_SPRITES)->set_granularity(16);
m_frame_irq_timer = timer_alloc(FUNC(tsconf_state::irq_frame), this);
m_scanline_irq_timer = timer_alloc(FUNC(tsconf_state::irq_scanline), this);
@@ -314,7 +305,7 @@ void tsconf_state::tsconf(machine_config &config)
DAC_8BIT_R2R(config, m_dac, 0).add_route(ALL_OUTPUTS, "mono", 0.75);;
- PALETTE(config, "palette", FUNC(tsconf_state::tsconf_palette), 256);
+ PALETTE(config, "palette", palette_device::BLACK, 256);
m_screen->set_raw(14_MHz_XTAL / 2, 448, with_hblank(0), 448, 320, with_vblank(0), 320);
m_screen->set_screen_update(FUNC(tsconf_state::screen_update));
m_screen->set_no_palette();
@@ -326,7 +317,7 @@ void tsconf_state::tsconf(machine_config &config)
AT_KEYB(config, m_keyboard, pc_keyboard_device::KEYBOARD_TYPE::AT, 3);
SOFTWARE_LIST(config, "betadisc_list_pent").set_original("spectrum_betadisc_flop");
- SOFTWARE_LIST(config, "betadisc_list_tsconf").set_original("tsconf_betadisc_flop");
+ SOFTWARE_LIST(config, "tsconf_list").set_original("tsconf");
}
ROM_START(tsconf)
diff --git a/src/mame/sinclair/tsconf.h b/src/mame/sinclair/tsconf.h
index 37dfe65b808..32f98c32700 100644
--- a/src/mame/sinclair/tsconf.h
+++ b/src/mame/sinclair/tsconf.h
@@ -29,6 +29,8 @@ public:
tsconf_state(const machine_config &mconfig, device_type type, const char *tag)
: spectrum_128_state(mconfig, type, tag)
, m_bank0_rom(*this, "bank0_rom")
+ , m_tiles_raw(*this, "tiles%u_raw", 0U, 64U * 64 * 8 * 8, ENDIANNESS_LITTLE)
+ , m_sprites_raw(*this, "sprites_raw", 64U * 64 * 8 * 8, ENDIANNESS_LITTLE)
, m_keyboard(*this, "pc_keyboard")
, m_io_mouse(*this, "mouse_input%u", 1U)
, m_beta(*this, BETA_DISK_TAG)
@@ -56,6 +58,8 @@ protected:
virtual void machine_reset() override ATTR_COLD;
virtual void device_post_load() override ATTR_COLD;
+ virtual void bank3_set_page(u8 page) override;
+
virtual TIMER_CALLBACK_MEMBER(irq_off) override;
TIMER_CALLBACK_MEMBER(irq_frame);
TIMER_CALLBACK_MEMBER(irq_scanline);
@@ -170,7 +174,6 @@ private:
void tsconf_draw_txt(bitmap_rgb32 &bitmap, const rectangle &cliprect);
void tsconf_draw_gfx(bitmap_rgb32 &bitmap, const rectangle &cliprect);
void draw_sprites(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
- void tsconf_palette(palette_device &palette) const;
void tsconf_update_video_mode();
u8 tsconf_port_xx1f_r(offs_t offset);
@@ -214,6 +217,8 @@ private:
memory_access<16, 0, 0, ENDIANNESS_LITTLE>::specific m_program;
memory_view m_bank0_rom;
+ memory_share_array_creator m_tiles_raw;
+ memory_share_creator m_sprites_raw;
required_device m_keyboard;
required_ioport_array<3> m_io_mouse;
diff --git a/src/mame/sinclair/tsconf_m.cpp b/src/mame/sinclair/tsconf_m.cpp
index 92f9678fd17..80009830862 100644
--- a/src/mame/sinclair/tsconf_m.cpp
+++ b/src/mame/sinclair/tsconf_m.cpp
@@ -29,11 +29,6 @@ enum v_mode : u8
VM_TXT
};
-static constexpr u32 tmp_tile_oversized_to_code(u16 code)
-{
- return code / 64 * 64 * 8 + (code % 64);
-}
-
// https://github.com/tslabs/zx-evo/blob/master/pentevo/vdac/vdac1/cpld/top.v
static constexpr u8 pwm_to_rgb[32] = {
0, 10, 21, 31, 42, 53, 63, 74,
@@ -54,12 +49,6 @@ rectangle tsconf_state::get_screen_area()
return info;
}
-void tsconf_state::tsconf_palette(palette_device &palette) const
-{
- rgb_t colors[256] = {0};
- palette.set_pen_colors(0, colors);
-}
-
void tsconf_state::tsconf_update_bank0()
{
u8 page0 = m_regs[PAGE0];
@@ -364,7 +353,7 @@ void tsconf_state::draw_sprites(screen_device &screen_d, bitmap_rgb32 &bitmap, c
for (auto spr = m_sprites_cache.rbegin(); spr != m_sprites_cache.rend(); ++spr)
{
m_gfxdecode->gfx(TM_SPRITES)->prio_transpen(bitmap, cliprect,
- tmp_tile_oversized_to_code(spr->code), spr->color, spr->flipx, spr->flipy, spr->destx, spr->desty,
+ spr->code, spr->color, spr->flipx, spr->flipy, spr->destx, spr->desty,
screen_d.priority(), spr->pmask, 0);
}
@@ -395,6 +384,15 @@ void tsconf_state::ram_bank_write(u8 bank, offs_t offset, u8 data)
ram_page_write(m_regs[PAGE0 + bank], offset, data);
}
+static int tiles_offset_to_raw(int t_offset)
+{
+ const int x = (t_offset / 4) % 64;
+ const int y = (t_offset / 0x100) / 8;
+ const int dx = t_offset % 4;
+ const int dy = (t_offset / 0x100) % 8;
+ return ((y * 64 + x) * 64) + (dy * 8) + (dx * 2);
+}
+
void tsconf_state::ram_page_write(u8 page, offs_t offset, u8 data)
{
u32 ram_addr = PAGE4K(page) + offset;
@@ -405,15 +403,21 @@ void tsconf_state::ram_page_write(u8 page, offs_t offset, u8 data)
}
else
{
- if (ram_addr >= PAGE4K(m_regs[T0_G_PAGE] & 0xf8) && ram_addr < PAGE4K((m_regs[T0_G_PAGE] & 0xf8) + 8))
+ const int t0_offset = ram_addr - PAGE4K(m_regs[T0_G_PAGE] & 0xf8);
+ if ((t0_offset >= 0) && (t0_offset < PAGE4K(8)))
{
- m_gfxdecode->gfx(TM_TILES0)->mark_all_dirty();
+ const int raw_offset = tiles_offset_to_raw(t0_offset);
+ m_tiles_raw[0][raw_offset] = data >> 4;
+ m_tiles_raw[0][raw_offset + 1] = data & 0x0f;
m_ts_tilemap[TM_TILES0]->mark_all_dirty();
}
- if (ram_addr >= PAGE4K(m_regs[T1_G_PAGE] & 0xf8) && ram_addr < PAGE4K((m_regs[T1_G_PAGE] & 0xf8) + 8))
+ const int t1_offset = ram_addr - PAGE4K(m_regs[T1_G_PAGE] & 0xf8);
+ if ((t1_offset >= 0) && (t1_offset < PAGE4K(8)))
{
- m_gfxdecode->gfx(TM_TILES1)->mark_all_dirty();
+ const int raw_offset = tiles_offset_to_raw(t1_offset);
+ m_tiles_raw[1][raw_offset] = data >> 4;
+ m_tiles_raw[1][raw_offset + 1] = data & 0x0f;
m_ts_tilemap[TM_TILES1]->mark_all_dirty();
}
}
@@ -424,8 +428,13 @@ void tsconf_state::ram_page_write(u8 page, offs_t offset, u8 data)
if (ram_addr >= PAGE4K(m_regs[m_regs[V_PAGE] ^ 0x01]) && ram_addr < PAGE4K(m_regs[m_regs[V_PAGE] ^ 0x01] + 1))
m_gfxdecode->gfx(TM_TS_CHAR)->mark_all_dirty();
- if (ram_addr >= PAGE4K(m_regs[SG_PAGE] & 0xf8) && ram_addr < PAGE4K((m_regs[SG_PAGE] & 0xf8) + 8))
- m_gfxdecode->gfx(TM_SPRITES)->mark_all_dirty();
+ const int spr_offset = ram_addr - PAGE4K(m_regs[SG_PAGE] & 0xf8);
+ if ((spr_offset >= 0) && (spr_offset < PAGE4K(8)))
+ {
+ const int raw_offset = tiles_offset_to_raw(spr_offset);
+ m_sprites_raw[raw_offset] = data >> 4;
+ m_sprites_raw[raw_offset + 1] = data & 0x0f;
+ }
m_ram->pointer()[ram_addr] = data;
}
@@ -438,7 +447,7 @@ u16 tsconf_state::ram_read16(offs_t offset)
void tsconf_state::ram_write16(offs_t offset, u16 data)
{
ram_page_write(0, offset & ~offs_t(1), data >> 8);
- m_ram->pointer()[offset | 1] = data & 0xff;
+ ram_page_write(0, offset | 1, data & 0xff);
}
u16 tsconf_state::spi_read16()
@@ -477,6 +486,11 @@ u8 tsconf_state::tsconf_port_xx1f_r(offs_t offset) {
: 0x00; // TODO kempston read
}
+void tsconf_state::bank3_set_page(u8 page)
+{
+ tsconf_port_xxaf_w(PAGE3 << 8, page);
+}
+
void tsconf_state::tsconf_port_7ffd_w(u8 data)
{
// LOCK? BIT(data, 5);
@@ -534,6 +548,20 @@ u8 tsconf_state::tsconf_port_xxaf_r(offs_t port)
return data;
}
+static void copy_tiles_to_raw(const u8 *tiles_src, u8 *raw_target)
+{
+ for(u32 ln = 0; ln < PAGE4K(8); ln += 4)
+ {
+ int targ = tiles_offset_to_raw(ln);
+ for (u8 x = 0; x < 4; ++x)
+ {
+ const u8 data = tiles_src[ln + x];
+ raw_target[targ + (x << 1)] = data >> 4;
+ raw_target[targ + (x << 1) + 1] = data & 0x0f;
+ }
+ }
+}
+
void tsconf_state::tsconf_port_xxaf_w(offs_t port, u8 data)
{
u8 nreg = port >> 8;
@@ -666,7 +694,7 @@ void tsconf_state::tsconf_port_xxaf_w(offs_t port, u8 data)
break;
case SG_PAGE:
- m_gfxdecode->gfx(TM_SPRITES)->set_source(m_ram->pointer() + PAGE4K(data & 0xf8));
+ copy_tiles_to_raw(m_ram->pointer() + PAGE4K(data & 0xf8), m_sprites_raw.target());
break;
case SYS_CONFIG:
@@ -916,12 +944,12 @@ TIMER_CALLBACK_MEMBER(tsconf_state::irq_scanline)
break;
case T0_G_PAGE:
- m_gfxdecode->gfx(TM_TILES0)->set_source(m_ram->pointer() + PAGE4K(val & 0xf8));
+ copy_tiles_to_raw(m_ram->pointer() + PAGE4K(val & 0xf8), m_tiles_raw[0].target());
m_ts_tilemap[TM_TILES0]->mark_all_dirty();
break;
case T1_G_PAGE:
- m_gfxdecode->gfx(TM_TILES1)->set_source(m_ram->pointer() + PAGE4K(val & 0xf8));
+ copy_tiles_to_raw(m_ram->pointer() + PAGE4K(val & 0xf8), m_tiles_raw[1].target());
m_ts_tilemap[TM_TILES1]->mark_all_dirty();
break;