summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author Vas Crabb <vas@vastheman.com>2025-11-23 03:06:56 +1100
committer Vas Crabb <vas@vastheman.com>2025-11-23 03:06:56 +1100
commit449dd209023f1cd1277b4efd79b50bf83bd8a804 (patch)
tree62fc0bab92da373e2ac9ccfe9b9c02dfbe15594d
parent228dbf3e13591698906f0e4fca2b4cb2c0bf167f (diff)
-pc/pc_t1t.cpp: Fixed emulation of PCjr high-bandwith video modes with 64K RAM.
* The 64kought now correctly shows bad graphics in these modes when run with 64K RAM. Doing this requires tricking the BIOS into thinking 128K RAM is present. -igs/igs_m027.cpp: Fixed inputs for Chong Chong Leyuan. Systems promoted to working --------------------------- Chong Chong Leyuan (V100CN) [David Haywood, Vas Crabb] Huangpai Zuqiu Plus / Chaoji Shuangxing Plus (V103CN) [David Haywood]
-rw-r--r--src/mame/igs/igs_m027.cpp98
-rw-r--r--src/mame/pc/ibmpcjr.cpp30
-rw-r--r--src/mame/pc/pc_t1t.cpp183
3 files changed, 246 insertions, 65 deletions
diff --git a/src/mame/igs/igs_m027.cpp b/src/mame/igs/igs_m027.cpp
index d069070391f..06c5953b4c2 100644
--- a/src/mame/igs/igs_m027.cpp
+++ b/src/mame/igs/igs_m027.cpp
@@ -1963,51 +1963,49 @@ INPUT_PORTS_START( tripslot )
INPUT_PORTS_END
INPUT_PORTS_START( ccly )
- // preliminary - game seems to lack an input test
- // To access sound test, hold Service Mode and reset, then press Service Mode and Book-Keeping simultaneously
-
PORT_START("PORTB")
- PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNKNOWN )
- PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_SLOT_STOP2 ) PORT_CONDITION("DSW2", 0x01, EQUALS, 0x01)
- PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_GAMBLE_BOOK ) PORT_CONDITION("DSW2", 0x01, EQUALS, 0x01)
- PORT_SERVICE_NO_TOGGLE( 0x08, IP_ACTIVE_LOW ) PORT_CONDITION("DSW2", 0x01, EQUALS, 0x01)
- PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_GAMBLE_BET ) PORT_CONDITION("DSW2", 0x01, EQUALS, 0x00)
- PORT_SERVICE_NO_TOGGLE( 0x04, IP_ACTIVE_LOW ) PORT_CONDITION("DSW2", 0x01, EQUALS, 0x00)
- PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_GAMBLE_BOOK ) PORT_CONDITION("DSW2", 0x01, EQUALS, 0x00)
- PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_COIN1 )
- PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_GAMBLE_KEYOUT ) PORT_CONDITION("DSW2", 0x01, EQUALS, 0x01)
- PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_GAMBLE_PAYOUT ) PORT_CONDITION("DSW2", 0x01, EQUALS, 0x00)
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNKNOWN ) PORT_CONDITION("DSW2", 0x01, EQUALS, 0x01)
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_SLOT_STOP2 ) PORT_CONDITION("DSW2", 0x01, EQUALS, 0x01) // 停二键
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_GAMBLE_BOOK ) PORT_CONDITION("DSW2", 0x01, EQUALS, 0x01) // 查帐
+ PORT_SERVICE_NO_TOGGLE( 0x08, IP_ACTIVE_LOW ) PORT_CONDITION("DSW2", 0x01, EQUALS, 0x01) // 测试
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_CUSTOM ) PORT_CONDITION("DSW2", 0x01, EQUALS, 0x00) PORT_READ_LINE_DEVICE_MEMBER("hopper", FUNC(hopper_device::line_r)) // 哈巴
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_GAMBLE_BET ) PORT_CONDITION("DSW2", 0x01, EQUALS, 0x00) // 押注键
+ PORT_SERVICE_NO_TOGGLE( 0x04, IP_ACTIVE_LOW ) PORT_CONDITION("DSW2", 0x01, EQUALS, 0x00) // 测试
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_GAMBLE_BOOK ) PORT_CONDITION("DSW2", 0x01, EQUALS, 0x00) // 查帐
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_COIN1 ) // 投币A
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_GAMBLE_KEYOUT ) PORT_CONDITION("DSW2", 0x01, EQUALS, 0x01) // 洗分
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_GAMBLE_PAYOUT ) PORT_CONDITION("DSW2", 0x01, EQUALS, 0x00) // 退币
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNKNOWN )
- PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_GAMBLE_LOW ) PORT_CONDITION("DSW2", 0x01, EQUALS, 0x01) PORT_NAME("Small / Half Gamble / Show Odds")
- PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_GAMBLE_HIGH ) PORT_CONDITION("DSW2", 0x01, EQUALS, 0x00) PORT_NAME("Big")
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_GAMBLE_LOW ) PORT_CONDITION("DSW2", 0x01, EQUALS, 0x01) PORT_NAME("Small / Half Gamble / Show Odds") // 小键/半续玩
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_GAMBLE_HIGH ) PORT_CONDITION("DSW2", 0x01, EQUALS, 0x00) PORT_NAME("Big") // 大键/双续玩
PORT_START("PORTC")
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_GAMBLE_KEYIN )
- PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_UNKNOWN ) PORT_CONDITION("DSW2", 0x01, EQUALS, 0x01)
- PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_GAMBLE_BET ) PORT_CONDITION("DSW2", 0x01, EQUALS, 0x01) PORT_NAME("Bet / Double Up")
- PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_GAMBLE_HIGH ) PORT_CONDITION("DSW2", 0x01, EQUALS, 0x01) PORT_NAME("Big")
- PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_START1 ) PORT_CONDITION("DSW2", 0x01, EQUALS, 0x01) PORT_NAME("Start / Take Score")
- PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_CUSTOM ) PORT_CONDITION("DSW2", 0x01, EQUALS, 0x01) PORT_READ_LINE_DEVICE_MEMBER("hopper", FUNC(hopper_device::line_r))
- PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_GAMBLE_PAYOUT ) PORT_CONDITION("DSW2", 0x01, EQUALS, 0x01)
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_UNKNOWN ) PORT_CONDITION("DSW2", 0x01, EQUALS, 0x01) // 开分
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_GAMBLE_BET ) PORT_CONDITION("DSW2", 0x01, EQUALS, 0x01) PORT_NAME("Bet / Double Up") // 押注键/续玩键
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_GAMBLE_HIGH ) PORT_CONDITION("DSW2", 0x01, EQUALS, 0x01) PORT_NAME("Big") // 大键/双续玩
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_START1 ) PORT_CONDITION("DSW2", 0x01, EQUALS, 0x01) PORT_NAME("Start / Take Score") // 开始键
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_CUSTOM ) PORT_CONDITION("DSW2", 0x01, EQUALS, 0x01) PORT_READ_LINE_DEVICE_MEMBER("hopper", FUNC(hopper_device::line_r)) // 哈巴
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_GAMBLE_PAYOUT ) PORT_CONDITION("DSW2", 0x01, EQUALS, 0x01) // 退币
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNKNOWN ) PORT_CONDITION("DSW2", 0x01, EQUALS, 0x01)
- PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_GAMBLE_KEYOUT ) PORT_CONDITION("DSW2", 0x01, EQUALS, 0x00)
- PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_START1 ) PORT_CONDITION("DSW2", 0x01, EQUALS, 0x00) PORT_NAME("Start / Take Score")
- PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNKNOWN ) PORT_CONDITION("DSW2", 0x01, EQUALS, 0x00)
- PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_CUSTOM ) PORT_CONDITION("DSW2", 0x01, EQUALS, 0x00) PORT_READ_LINE_DEVICE_MEMBER("hopper", FUNC(hopper_device::line_r))
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_GAMBLE_KEYOUT ) PORT_CONDITION("DSW2", 0x01, EQUALS, 0x00) // 洗分
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_START1 ) PORT_CONDITION("DSW2", 0x01, EQUALS, 0x00) PORT_NAME("Start / Take Score") // 开始键
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_SLOT_STOP_ALL ) PORT_CONDITION("DSW2", 0x01, EQUALS, 0x00) // 全停键
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNKNOWN ) PORT_CONDITION("DSW2", 0x01, EQUALS, 0x00)
PORT_BIT( 0x60, IP_ACTIVE_LOW, IPT_UNKNOWN ) PORT_CONDITION("DSW2", 0x01, EQUALS, 0x00)
- PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_COIN2 ) PORT_CONDITION("DSW2", 0x01, EQUALS, 0x00)
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_COIN2 ) PORT_CONDITION("DSW2", 0x01, EQUALS, 0x00) // 投币C
PORT_START("PLAYER")
PORT_BIT( 0x00001, IP_ACTIVE_LOW, IPT_UNKNOWN ) PORT_CONDITION("DSW2", 0x01, EQUALS, 0x01)
- PORT_BIT( 0x00002, IP_ACTIVE_LOW, IPT_SLOT_STOP3 ) PORT_CONDITION("DSW2", 0x01, EQUALS, 0x01)
- PORT_BIT( 0x00004, IP_ACTIVE_LOW, IPT_SLOT_STOP1 ) PORT_CONDITION("DSW2", 0x01, EQUALS, 0x01)
+ PORT_BIT( 0x00002, IP_ACTIVE_LOW, IPT_SLOT_STOP3 ) PORT_CONDITION("DSW2", 0x01, EQUALS, 0x01) // 停三键
+ PORT_BIT( 0x00004, IP_ACTIVE_LOW, IPT_SLOT_STOP1 ) PORT_CONDITION("DSW2", 0x01, EQUALS, 0x01) // 停一键
PORT_BIT( 0x00038, IP_ACTIVE_LOW, IPT_UNKNOWN ) PORT_CONDITION("DSW2", 0x01, EQUALS, 0x01)
- PORT_BIT( 0x00001, IP_ACTIVE_LOW, IPT_SLOT_STOP1 ) PORT_CONDITION("DSW2", 0x01, EQUALS, 0x00)
- PORT_BIT( 0x00002, IP_ACTIVE_LOW, IPT_SLOT_STOP2 ) PORT_CONDITION("DSW2", 0x01, EQUALS, 0x00)
- PORT_BIT( 0x00004, IP_ACTIVE_LOW, IPT_SLOT_STOP3 ) PORT_CONDITION("DSW2", 0x01, EQUALS, 0x00)
- PORT_BIT( 0x00008, IP_ACTIVE_LOW, IPT_GAMBLE_LOW ) PORT_CONDITION("DSW2", 0x01, EQUALS, 0x00) PORT_NAME("Small / Half Gamble / Show Odds")
- PORT_BIT( 0x00010, IP_ACTIVE_LOW, IPT_GAMBLE_TAKE ) PORT_CONDITION("DSW2", 0x01, EQUALS, 0x00)
- PORT_BIT( 0x00020, IP_ACTIVE_LOW, IPT_GAMBLE_D_UP ) PORT_CONDITION("DSW2", 0x01, EQUALS, 0x00)
+ PORT_BIT( 0x00001, IP_ACTIVE_LOW, IPT_SLOT_STOP1 ) PORT_CONDITION("DSW2", 0x01, EQUALS, 0x00) // 停一键
+ PORT_BIT( 0x00002, IP_ACTIVE_LOW, IPT_SLOT_STOP2 ) PORT_CONDITION("DSW2", 0x01, EQUALS, 0x00) // 停二键
+ PORT_BIT( 0x00004, IP_ACTIVE_LOW, IPT_SLOT_STOP3 ) PORT_CONDITION("DSW2", 0x01, EQUALS, 0x00) // 停三键
+ PORT_BIT( 0x00008, IP_ACTIVE_LOW, IPT_GAMBLE_LOW ) PORT_CONDITION("DSW2", 0x01, EQUALS, 0x00) PORT_NAME("Small / Half Gamble / Show Odds") // 小键/半续玩
+ PORT_BIT( 0x00010, IP_ACTIVE_LOW, IPT_GAMBLE_TAKE ) PORT_CONDITION("DSW2", 0x01, EQUALS, 0x00) // 得分键
+ PORT_BIT( 0x00020, IP_ACTIVE_LOW, IPT_GAMBLE_D_UP ) PORT_CONDITION("DSW2", 0x01, EQUALS, 0x00) // 续玩键
PORT_BIT( 0x000c0, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_BIT( 0x00100, IP_ACTIVE_HIGH, IPT_UNKNOWN ) // must be low or most inputs are ignored
PORT_BIT( 0xffe00, IP_ACTIVE_LOW, IPT_UNKNOWN )
@@ -2066,7 +2064,7 @@ INPUT_PORTS_END
INPUT_PORTS_START( cjsxp )
// preliminary
- // input test and settings display are not working so everything is guessed
+ // game seems to lack an input test so controls are guessed
PORT_START("PORTB")
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNKNOWN )
@@ -2134,35 +2132,37 @@ INPUT_PORTS_START( cjsxp )
PORT_START("DSW1")
PORT_DIPNAME( 0x01, 0x01, DEF_STR(Controls) ) PORT_DIPLOCATION("SW1:1") // 操作面版
PORT_DIPSETTING( 0x01, "Amusement" ) // 娱乐
- PORT_DIPSETTING( 0x00, "Fruit Machine" )
- PORT_DIPNAME( 0x02, 0x02, "Playing Card Display" ) PORT_DIPLOCATION("SW1:2")
- PORT_DIPSETTING( 0x02, "Soccer Balls" ) PORT_CONDITION("DSW1", 0x04, EQUALS, 0x04)
- PORT_DIPSETTING( 0x00, "Soccer Jerseys" ) PORT_CONDITION("DSW1", 0x04, EQUALS, 0x04)
- PORT_DIPSETTING( 0x02, "Playing Cards" ) PORT_CONDITION("DSW1", 0x04, EQUALS, 0x00)
- PORT_DIPSETTING( 0x00, "Tiles" ) PORT_CONDITION("DSW1", 0x04, EQUALS, 0x00)
+ PORT_DIPSETTING( 0x00, "Poker" ) // 扑克
+ PORT_DIPNAME( 0x02, 0x02, "Playing Card Display" ) PORT_DIPLOCATION("SW1:2") // 牌面
+ PORT_DIPSETTING( 0x02, "Soccer Balls" ) PORT_CONDITION("DSW1", 0x04, EQUALS, 0x04) // 足球
+ PORT_DIPSETTING( 0x00, "Soccer Jerseys" ) PORT_CONDITION("DSW1", 0x04, EQUALS, 0x04) // 球衣
+ PORT_DIPSETTING( 0x02, "Playing Cards" ) PORT_CONDITION("DSW1", 0x04, EQUALS, 0x00) // 扑克
+ PORT_DIPSETTING( 0x00, "Cubes" ) PORT_CONDITION("DSW1", 0x04, EQUALS, 0x00) // 方块
PORT_DIPNAME( 0x04, 0x04, "Game Title" ) PORT_DIPLOCATION("SW1:3")
PORT_DIPSETTING( 0x04, "Huangpai Zuqiu Plus" ) // 皇牌足球 PLUS (Huángpái Zúqiú Plus) - soccer theme
PORT_DIPSETTING( 0x00, "Chaoji Shuangxing Plus" ) // 超级双星 PLUS (Chāojí Shuāngxīng Plus) - casino theme
PORT_DIPNAME( 0x08, 0x08, "Double Up Game" ) PORT_DIPLOCATION("SW1:4") // 比倍游戏
- PORT_DIPSETTING( 0x00, DEF_STR(Off) )
+ PORT_DIPSETTING( 0x00, DEF_STR(Off) ) // 无
PORT_DIPSETTING( 0x08, DEF_STR(On) ) // 有
PORT_DIPNAME( 0x10, 0x10, "Double Up Game Name" ) PORT_DIPLOCATION("SW1:5") // 比倍续玩
PORT_DIPSETTING( 0x10, "Double Up" ) // 比倍
PORT_DIPSETTING( 0x00, "Continue Play" ) // 续玩
PORT_DIPNAME( 0x20, 0x20, DEF_STR(Demo_Sounds) ) PORT_DIPLOCATION("SW1:6") // 示范音乐
- PORT_DIPSETTING( 0x00, DEF_STR(Off) )
+ PORT_DIPSETTING( 0x00, DEF_STR(Off) ) // 无
PORT_DIPSETTING( 0x20, DEF_STR(On) ) // 有
- PORT_DIPNAME( 0x40, 0x40, "Face Card Display" ) PORT_DIPLOCATION("SW1:7") // 扑克牌面 (affects balls, jerseys and tiles, but not playing cards)
+ PORT_DIPNAME( 0x40, 0x40, "Face Card Display" ) PORT_DIPLOCATION("SW1:7") // 扑克牌面 (affects balls, jerseys and cubes, but not playing cards)
PORT_DIPSETTING( 0x40, "Numbers" ) // 数字 (11, 12, 13, 1)
- PORT_DIPSETTING( 0x00, "Letters" ) // (J, Q, K, A)
- PORT_DIPUNKNOWN_DIPLOC( 0x80, 0x80, "SW1:8" ) // 系统破台 (what does this actually do?)
+ PORT_DIPSETTING( 0x00, "Letters" ) // AJQK (J, Q, K, A)
+ PORT_DIPNAME( 0x80, 0x80, DEF_STR(Unknown) ) PORT_DIPLOCATION("SW1:8") // 系统破台 (what does this actually do? does it enable a "fever mode"?)
+ PORT_DIPSETTING( 0x00, DEF_STR(Off) ) // 无
+ PORT_DIPSETTING( 0x80, DEF_STR(On) ) // 有
PORT_START("DSW2")
PORT_DIPNAME( 0x01, 0x01, "Credit Mode" ) PORT_DIPLOCATION("SW2:1") // 进分方式 (sets coin input function in amusement mode)
PORT_DIPSETTING( 0x01, "Coin Acceptor" ) // 投币 (ignores key-in in fruit machine mode)
PORT_DIPSETTING( 0x00, "Key-In" ) // 开分 (ignores coin input in fruit machine mode)
PORT_DIPNAME( 0x02, 0x02, "Payout Mode" ) PORT_DIPLOCATION("SW2:2") // 退分方式 (sets payout button function in amusement mode)
- PORT_DIPSETTING( 0x02, "Return Coins" ) // 退币 (uses hopper to pay out credits, ignores key-out in fruit machine mode)
+ PORT_DIPSETTING( 0x02, "Return Coins" ) // 对币 (uses hopper to pay out credits, ignores key-out in fruit machine mode)
PORT_DIPSETTING( 0x00, "Key-Out" ) // 洗分 (just clears credits)
PORT_DIPUNKNOWN_DIPLOC( 0x04, 0x04, "SW2:3" ) // remaining DIP switches not shown in test mode
PORT_DIPUNKNOWN_DIPLOC( 0x08, 0x08, "SW2:4" )
@@ -4824,8 +4824,8 @@ GAME( 2005, cjtljp, 0, xypdk, lhzb4, igs_m027_stat
GAME( 2005, xypdk, 0, xypdk, lhzb4, igs_m027_state, init_xypdk, ROT0, "IGS", "Xingyun Pao De Kuai (V106CN)", 0 )
GAMEL( 2005, royal5p, 0, royal5p, royal5p, igs_m027_state, init_royal5p, ROT0, "IGS", "Royal 5+ / X'mas 5 (V101US)", 0, layout_royal5p )
GAMEL( 2007, tripslot, 0, tripslot, tripslot, igs_m027_state, init_tripslot, ROT0, "IGS", "Triple Slot (V200VE)", 0, layout_tripslot ) // 2007 date in internal ROM at least, could be later, default settings password is all 'start 1'
-GAMEL( 2005, ccly, crzybugs, ccly, ccly, igs_m027_state, init_ccly, ROT0, "IGS", "Chong Chong Leyuan (V100CN)", MACHINE_NOT_WORKING, layout_ccly )
-GAME( 2001, cjsxp, 0, cjsxp, cjsxp, igs_m027_state, init_klxyj, ROT0, "IGS", "Huangpai Zuqiu Plus / Chaoji Shuangxing Plus (V103CN)", MACHINE_NOT_WORKING )
+GAMEL( 2005, ccly, crzybugs, ccly, ccly, igs_m027_state, init_ccly, ROT0, "IGS", "Chong Chong Leyuan (V100CN)", 0, layout_ccly )
+GAME( 2001, cjsxp, 0, cjsxp, cjsxp, igs_m027_state, init_klxyj, ROT0, "IGS", "Huangpai Zuqiu Plus / Chaoji Shuangxing Plus (V103CN)", 0 )
GAME( 2000, tshs, 0, zhongguo, tshs, igs_m027_state, init_slqz3, ROT0, "IGS", "Tiansheng Haoshou (V201CN)", 0 )
GAME( 2000, tshs101, tshs, tshs101, tshs101, igs_m027_state, init_slqz3, ROT0, "IGS", "Tiansheng Haoshou (V101CN)", MACHINE_NOT_WORKING | MACHINE_NO_SOUND ) // unemulated sound chips
GAME( 2006, tswxp, 0, tct2p, tswxp, igs_m027_state, init_tswxp, ROT0, "IGS", "Taishan Wuxian Jiaqiang Ban (V101CN)", 0 )
diff --git a/src/mame/pc/ibmpcjr.cpp b/src/mame/pc/ibmpcjr.cpp
index 60f10370a2b..4c4855246b4 100644
--- a/src/mame/pc/ibmpcjr.cpp
+++ b/src/mame/pc/ibmpcjr.cpp
@@ -1,5 +1,17 @@
// license:BSD-3-Clause
// copyright-holders:Wilbert Pol
+/*
+TODO:
+* POST gives "ERROR H" with 64K RAM (you can press Enter to get past
+ it).
+* Cartridge BASIC always rejects "SCREEN 4" (320*200 4BPP) and
+ "SCREEN 5" (640*200 2BPP). These are graphics modes that require at
+ least 128K RAM. However, it does accept "WIDTH 80" when 128K or more
+ RAM is present, so it isn't just failing to detect the RAM size
+ altogether.
+* IBM JX (5510) is a completely different machine and should be moved
+ out of this driver and emulated properly.
+*/
#include "emu.h"
#include "pc_t1t.h"
@@ -142,17 +154,21 @@ void pcjr_state::machine_start()
m_pcjr_watchdog = timer_alloc(FUNC(pcjr_state::watchdog_expired), this);
m_keyb_signal_timer = timer_alloc(FUNC(pcjr_state::kb_signal), this);
- // TODO: JX isn't emulated properly at all, and should probably be moved to a separate driver
- // TODO: PCjr video RAM maps to main RAM differently when only 64K is present
- // * ERROR H on boot with 64K RAM due to incorrect mapping
- // * 64kought should have glitches in 320*200*4 and 640*200*2 scenes with 64K RAM
+ // TODO: JX isn't emulated properly at all, and should be moved to a separate driver
memory_share *const vram = memshare("vram");
if (vram)
+ {
+ m_video->set_16bit(true);
vram_space.install_ram(0, std::min<offs_t>((128 * 1024) - 1, vram->bytes() - 1), &vram[0]);
- else if (ramsize > (64 * 1024))
- vram_space.install_ram(0, std::min<offs_t>((128 * 1024) - 1, ramsize - 1), m_ram->pointer());
+ }
else
- vram_space.install_ram(0, ramsize - 1, 0x010000, m_ram->pointer());
+ {
+ m_video->set_16bit(ramsize > (64 * 1024));
+ if (ramsize > (64 * 1024))
+ vram_space.install_ram(0, std::min<offs_t>((128 * 1024) - 1, ramsize - 1), m_ram->pointer());
+ else
+ vram_space.install_ram(0, ramsize - 1, 0x010000, m_ram->pointer());
+ }
}
void pcjr_state::machine_reset()
diff --git a/src/mame/pc/pc_t1t.cpp b/src/mame/pc/pc_t1t.cpp
index f6f6de34bdc..0b8a554f4a9 100644
--- a/src/mame/pc/pc_t1t.cpp
+++ b/src/mame/pc/pc_t1t.cpp
@@ -4,6 +4,50 @@
IBM PCjr and Tandy 1000 graphics emulation
+ The PCjr and Tandy 1000 map video RAM directly into the CPU's memory
+ space as well as proving a 32K window into video RAM in the CPU's
+ address space at B8000. The PCjr always maps video RAM at 00000, while
+ the Tandy 1000 can map it at any multiple of 20000. The video hardware
+ has priority when accessing video RAM.Wait states will be generated if
+ the CPU attempts to access video RAM while it is in use by the video
+ hardware. This means it is safe to access video RAM during active
+ display, with no side effects besides the performance penalty. This
+ allows a minimally configured system to use only video RAM, with no
+ additional RAM connected to the CPU.
+
+ The PCjr can have one or two 64K banks of video RAM. If only one bank
+ is present, it is mirrored at 10000. If two banks are present, one
+ bank stores even bytes while the other stores odd bytes, and the video
+ hardware reads both banks in parallel, doubling the bandwidth and
+ reducing the chance of wait states being required when the CPU accesses
+ video RAM.
+
+ The Tandy 1000 supports a single 128K bank of video RAM. The
+ Tandy 1000A theoretically supports 128K of video RAM using 64K*1 DRAMs,
+ or 512K of video RAM using 256K*1 DRAMs, but the board is only wired
+ for the first option. The data path to the video RAM is eight bits
+ wide in both cases.
+
+ The Tandy 1000 SX and Tandy 1000 HX support up to 256K of video RAM
+ using 64K*4 DRAMs (256K DRAMs are theoretically supported, but the
+ boards are not wired for this option). The data path to the video RAM
+ is sixteen bits wide, doubling the bandwidth compared to the early
+ models, and reducing the performance impact of accessing video RAM from
+ the CPU.
+
+ The PCjr and Tandy 1000 support the same resolutions, pixel formats and
+ video RAM layouts as each other. However, only the MC6845 registers,
+ status register, lightpen registers and page register are compatible.
+ The registers for configuring the video chip and setting the palette
+ are not compatible. Software must use the BIOS to set video modes or
+ deal with the differences.
+
+ The PCjr and Tandy 1000 provide CGA compatibility in different ways.
+ The PCjr allows CGA-compatible video modes to be selected using BIOS
+ calls and configures the video chip appropriately. The Tandy 1000
+ provides CGA-compatible configuration registers to cater to software
+ that accesses a CGA card directly.
+
Note that in the IBM PC Junior world, the term VGA refers to the Video
Gate Array, which is unrelated to the more well-known Video Graphics
Array introduced with the PS/2.
@@ -46,6 +90,10 @@ enum
T1000_GFX_2BPP,
T1000_GFX_2BPP_HIGH,
T1000_GFX_4BPP,
+ PCJR_TEXT_INTEN_HIGH_8BIT,
+ PCJR_TEXT_BLINK_HIGH_8BIT,
+ PCJR_GFX_2BPP_HIGH_8BIT,
+ PCJR_GFX_4BPP_HIGH_8BIT,
PCJX_TEXT
};
@@ -189,6 +237,7 @@ pcvideo_pcjr_device::pcvideo_pcjr_device(
pc_t1t_device(mconfig, PCVIDEO_PCJR, tag, owner, clock, 8, 17, 3, 0),
m_jxkanji(*this, finder_base::DUMMY_TAG),
m_vsync_cb(*this),
+ m_16bit(false),
m_address_data_ff(0),
m_mode_ctrl_1(0),
m_mode_ctrl_2(0)
@@ -294,7 +343,7 @@ void pcvideo_pcjr_device::device_post_load()
pc_t1t_device::device_post_load();
// ensure correct video update function is selected;
- pc_pcjr_mode_switch();
+ mode_switch();
}
@@ -373,7 +422,6 @@ MC6845_UPDATE_ROW( pc_t1t_device::text_inten_update_row )
uint32_t const rowbase = row_base(ra);
uint32_t *p = &bitmap.pix(y);
- if (y == 0) logerror("t1000_text_inten_update_row\n");
for (int i = 0; i < x_count; i++)
{
uint16_t const offset = ((ma + i) << 1) & m_offset_mask;
@@ -398,6 +446,35 @@ MC6845_UPDATE_ROW( pc_t1t_device::text_inten_update_row )
}
}
+MC6845_UPDATE_ROW( pcvideo_pcjr_device::text_inten_high_8bit_update_row )
+{
+ // insufficient bandwidth to read both bytes, so the attribute becomes the character as well
+ uint32_t const rowbase = row_base(ra);
+ uint32_t *p = &bitmap.pix(y);
+
+ for (int i = 0; i < x_count; i++)
+ {
+ uint16_t const offset = ((ma + i) << 1) & m_offset_mask;
+ uint8_t const attr = space(0).read_byte(rowbase | offset | 1);
+ uint8_t const chr = attr;
+ auto const fg = palette_r(BIT(attr, 0, 4));
+ auto const bg = palette_r(BIT(attr, 4, 4));
+
+ uint8_t data = chr_gen_r(chr, ra);
+ if (i == cursor_x && (m_pc_framecnt & 0x08))
+ data = 0xff;
+
+ *p++ = BIT(data, 7) ? fg : bg;
+ *p++ = BIT(data, 6) ? fg : bg;
+ *p++ = BIT(data, 5) ? fg : bg;
+ *p++ = BIT(data, 4) ? fg : bg;
+ *p++ = BIT(data, 3) ? fg : bg;
+ *p++ = BIT(data, 2) ? fg : bg;
+ *p++ = BIT(data, 1) ? fg : bg;
+ *p++ = BIT(data, 0) ? fg : bg;
+ }
+}
+
MC6845_UPDATE_ROW( pcvideo_t1000_device::text_blink_update_row )
{
@@ -478,6 +555,42 @@ MC6845_UPDATE_ROW( pcvideo_pcjr_device::text_blink_update_row )
}
}
+MC6845_UPDATE_ROW( pcvideo_pcjr_device::text_blink_high_8bit_update_row )
+{
+ uint32_t const rowbase = row_base(ra);
+ uint32_t *p = &bitmap.pix(y);
+
+ for (int i = 0; i < x_count; i++)
+ {
+ uint16_t const offset = ((ma + i) << 1) & m_offset_mask;
+ uint8_t const attr = space(0).read_byte(rowbase | offset | 1);
+ uint8_t const chr = attr;
+ auto const fg = palette_r(BIT(attr, 0, 4));
+ auto const bg = palette_r(BIT(attr, 4, 3));
+
+ uint8_t data = chr_gen_r(chr, ra);
+ if (i == cursor_x)
+ {
+ if (m_pc_framecnt & 0x08)
+ data = 0xff;
+ }
+ else
+ {
+ if ((attr & 0x80) && (m_pc_framecnt & 0x10))
+ data = 0x00;
+ }
+
+ *p++ = BIT(data, 7) ? fg : bg;
+ *p++ = BIT(data, 6) ? fg : bg;
+ *p++ = BIT(data, 5) ? fg : bg;
+ *p++ = BIT(data, 4) ? fg : bg;
+ *p++ = BIT(data, 3) ? fg : bg;
+ *p++ = BIT(data, 2) ? fg : bg;
+ *p++ = BIT(data, 1) ? fg : bg;
+ *p++ = BIT(data, 0) ? fg : bg;
+ }
+}
+
MC6845_UPDATE_ROW( pcvideo_pcjr_device::pcjx_text_update_row )
{
@@ -536,6 +649,24 @@ MC6845_UPDATE_ROW( pc_t1t_device::gfx_4bpp_update_row )
}
}
+MC6845_UPDATE_ROW( pcvideo_pcjr_device::gfx_4bpp_high_8bit_update_row )
+{
+ // insufficient bandwidth to read both bytes, so pairs of columns get duplicated
+ uint32_t *p = &bitmap.pix(y);
+ uint32_t const rowbase = row_base(ra);
+
+ for (int i = 0; i < x_count; i++)
+ {
+ uint16_t const offset = ((ma + i) << 1) & m_offset_mask;
+ uint8_t const data = space(0).read_byte(rowbase | offset | 1);
+
+ *p++ = palette_r(BIT(data, 4, 4));
+ *p++ = palette_r(BIT(data, 0, 4));
+ *p++ = palette_r(BIT(data, 4, 4));
+ *p++ = palette_r(BIT(data, 0, 4));
+ }
+}
+
MC6845_UPDATE_ROW( pcvideo_t1000_device::gfx_2bpp_update_row )
{
@@ -603,6 +734,28 @@ MC6845_UPDATE_ROW( pc_t1t_device::gfx_2bpp_high_update_row )
}
}
+MC6845_UPDATE_ROW( pcvideo_pcjr_device::gfx_2bpp_high_8bit_update_row )
+{
+ // insufficient bandwidth to read both bytes, so the image end up monochrome
+ uint32_t *p = &bitmap.pix(y);
+ uint32_t const rowbase = row_base(ra);
+
+ for (int i = 0; i < x_count; i++)
+ {
+ uint16_t const offset = ((ma + i) << 1) & m_offset_mask;
+ uint8_t const data = space(0).read_byte(rowbase | offset | 1);
+
+ *p++ = palette_r(bitswap<2>(data, 7, 7));
+ *p++ = palette_r(bitswap<2>(data, 6, 6));
+ *p++ = palette_r(bitswap<2>(data, 5, 5));
+ *p++ = palette_r(bitswap<2>(data, 4, 4));
+ *p++ = palette_r(bitswap<2>(data, 3, 3));
+ *p++ = palette_r(bitswap<2>(data, 2, 2));
+ *p++ = palette_r(bitswap<2>(data, 1, 1));
+ *p++ = palette_r(bitswap<2>(data, 0, 0));
+ }
+}
+
MC6845_UPDATE_ROW( pcvideo_t1000_device::gfx_1bpp_update_row )
{
@@ -717,6 +870,18 @@ MC6845_UPDATE_ROW( pcvideo_pcjr_device::crtc_update_row )
case T1000_GFX_2BPP:
gfx_2bpp_update_row(bitmap, cliprect, ma, ra, y, x_count, cursor_x, de, hbp, vbp);
break;
+ case PCJR_TEXT_INTEN_HIGH_8BIT:
+ text_inten_high_8bit_update_row(bitmap, cliprect, ma, ra, y, x_count, cursor_x, de, hbp, vbp);
+ break;
+ case PCJR_TEXT_BLINK_HIGH_8BIT:
+ text_blink_high_8bit_update_row(bitmap, cliprect, ma, ra, y, x_count, cursor_x, de, hbp, vbp);
+ break;
+ case PCJR_GFX_2BPP_HIGH_8BIT:
+ gfx_2bpp_high_8bit_update_row(bitmap, cliprect, ma, ra, y, x_count, cursor_x, de, hbp, vbp);
+ break;
+ case PCJR_GFX_4BPP_HIGH_8BIT:
+ gfx_4bpp_high_8bit_update_row(bitmap, cliprect, ma, ra, y, x_count, cursor_x, de, hbp, vbp);
+ break;
case PCJX_TEXT:
pcjx_text_update_row(bitmap, cliprect, ma, ra, y, x_count, cursor_x, de, hbp, vbp);
break;
@@ -793,7 +958,7 @@ void pcvideo_t1000_device::mode_switch()
// bit1 - 1 = enable blink
// bit3 - 1 = 2 color graphics
-void pcvideo_pcjr_device::pc_pcjr_mode_switch()
+void pcvideo_pcjr_device::mode_switch()
{
bool const high_bw = BIT(m_mode_ctrl_1, 0);
bool const graphics = BIT(m_mode_ctrl_1, 1);
@@ -813,13 +978,13 @@ void pcvideo_pcjr_device::pc_pcjr_mode_switch()
if (m_jxkanji)
m_update_row_type = PCJX_TEXT;
else if (blink)
- m_update_row_type = T1000_TEXT_BLINK;
+ m_update_row_type = (!high_bw || m_16bit) ? T1000_TEXT_BLINK : PCJR_TEXT_BLINK_HIGH_8BIT;
else
- m_update_row_type = T1000_TEXT_INTEN;
+ m_update_row_type = (!high_bw || m_16bit) ? T1000_TEXT_INTEN : PCJR_TEXT_INTEN_HIGH_8BIT;
}
else if (color16)
{
- m_update_row_type = T1000_GFX_4BPP;
+ m_update_row_type = (!high_bw || m_16bit) ? T1000_GFX_4BPP : PCJR_GFX_4BPP_HIGH_8BIT;
}
else if (color2)
{
@@ -827,7 +992,7 @@ void pcvideo_pcjr_device::pc_pcjr_mode_switch()
}
else if (high_bw)
{
- m_update_row_type = T1000_GFX_2BPP_HIGH;
+ m_update_row_type = m_16bit ? T1000_GFX_2BPP_HIGH : PCJR_GFX_2BPP_HIGH_8BIT;
}
else
{
@@ -946,11 +1111,11 @@ void pcvideo_pcjr_device::vga_data_w(uint8_t data)
{
case 0x00:
m_mode_ctrl_1 = data & 0x1f;
- pc_pcjr_mode_switch();
+ mode_switch();
break;
case 0x03:
m_mode_ctrl_2 = data & 0x0f;
- pc_pcjr_mode_switch();
+ mode_switch();
break;
case 0x04: // reset register
break;