diff options
| author | 2025-11-23 03:06:56 +1100 | |
|---|---|---|
| committer | 2025-11-23 03:06:56 +1100 | |
| commit | 449dd209023f1cd1277b4efd79b50bf83bd8a804 (patch) | |
| tree | 62fc0bab92da373e2ac9ccfe9b9c02dfbe15594d | |
| parent | 228dbf3e13591698906f0e4fca2b4cb2c0bf167f (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.cpp | 98 | ||||
| -rw-r--r-- | src/mame/pc/ibmpcjr.cpp | 30 | ||||
| -rw-r--r-- | src/mame/pc/pc_t1t.cpp | 183 |
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; |
