mirror of
https://github.com/holub/mame
synced 2025-06-06 12:53:46 +03:00
Merge branch 'master' of https://github.com/mamedev/mame
This commit is contained in:
commit
a89e7c6c5b
81
hash/k28.xml
Normal file
81
hash/k28.xml
Normal file
@ -0,0 +1,81 @@
|
||||
<?xml version="1.0"?>
|
||||
<!DOCTYPE softwarelist SYSTEM "softwarelist.dtd">
|
||||
|
||||
<softwarelist name="k28" description="Tiger K28 modules">
|
||||
|
||||
<software name="m1">
|
||||
<description>Expansion Module 1</description>
|
||||
<year>1986?</year>
|
||||
<publisher>Tiger Electronics</publisher>
|
||||
<info name="serial" value="CM62086"/>
|
||||
<part name="cart" interface="k28">
|
||||
<dataarea name="rom" size="0x4000">
|
||||
<rom name="cm62086.vsm" size="0x4000" crc="0349798b" sha1="afdad242f9c7dec0c5fd83670e3d8f1637140e76" offset="0" />
|
||||
</dataarea>
|
||||
</part>
|
||||
</software>
|
||||
|
||||
<software name="m2">
|
||||
<description>Expansion Module 2</description>
|
||||
<year>1986</year>
|
||||
<publisher>Tiger Electronics</publisher>
|
||||
<info name="serial" value="CM62216"/>
|
||||
<part name="cart" interface="k28">
|
||||
<dataarea name="rom" size="0x4000">
|
||||
<rom name="cm62216.vsm" size="0x4000" crc="1c99306f" sha1="7bfadeec79bdc231c4e3447149e2f6542cfe077d" offset="0" />
|
||||
</dataarea>
|
||||
</part>
|
||||
</software>
|
||||
|
||||
<software name="m3">
|
||||
<description>Expansion Module 3</description>
|
||||
<year>1986</year>
|
||||
<publisher>Tiger Electronics</publisher>
|
||||
<info name="serial" value="CM62215"/>
|
||||
<part name="cart" interface="k28">
|
||||
<dataarea name="rom" size="0x4000">
|
||||
<rom name="cm62215.vsm" size="0x4000" crc="f2deb9a2" sha1="9fb264b869d1298ebd76811931bed83ac122fe4b" offset="0" />
|
||||
</dataarea>
|
||||
</part>
|
||||
</software>
|
||||
|
||||
<software name="m4">
|
||||
<description>Expansion Module 4</description>
|
||||
<year>1986</year>
|
||||
<publisher>Tiger Electronics</publisher>
|
||||
<info name="serial" value="CM62217"/>
|
||||
<part name="cart" interface="k28">
|
||||
<dataarea name="rom" size="0x4000">
|
||||
<rom name="cm62217.vsm" size="0x4000" crc="995936b2" sha1="8bd0fea4ade9972d1d6cb521f9367c971c7eead6" offset="0" />
|
||||
</dataarea>
|
||||
</part>
|
||||
</software>
|
||||
|
||||
<!--
|
||||
<software name="m5">
|
||||
<description>Expansion Module 5</description>
|
||||
<year>1987</year>
|
||||
<publisher>Tiger Electronics</publisher>
|
||||
<info name="serial" value="CM62218"/>
|
||||
<part name="cart" interface="k28">
|
||||
<dataarea name="rom" size="0x4000">
|
||||
<rom name="cm62217.vsm" size="0x4000" crc="x" sha1="x" offset="0" />
|
||||
</dataarea>
|
||||
</part>
|
||||
</software>
|
||||
-->
|
||||
|
||||
<software name="m6">
|
||||
<description>Expansion Module 6</description>
|
||||
<year>1987</year>
|
||||
<publisher>Tiger Electronics</publisher>
|
||||
<info name="serial" value="CM62219"/>
|
||||
<part name="cart" interface="k28">
|
||||
<dataarea name="rom" size="0x4000">
|
||||
<rom name="cm62219.vsm" size="0x4000" crc="177b5cb5" sha1="2ed44fea8f931fc8aa46dafdda1c6c30b8c9dc01" offset="0" />
|
||||
</dataarea>
|
||||
</part>
|
||||
</software>
|
||||
|
||||
|
||||
</softwarelist>
|
@ -6367,6 +6367,7 @@ charlien // MBR (c) 1994 Mitchell
|
||||
// MBV ??
|
||||
// MBW ??
|
||||
wcvol95 // MBX (c) 1993 Data East
|
||||
wcvol95x // ?
|
||||
// MBY ??
|
||||
backfire // MBZ (c) 1995
|
||||
backfirea // MBZ (c) 1995
|
||||
|
@ -8,9 +8,6 @@
|
||||
|
||||
See also deco32.c, deco_mlc.c, backfire.c
|
||||
|
||||
Todo:
|
||||
complete co-processor emulation for wcvol95
|
||||
|
||||
Emulation by Bryan McPhail, mish@tendril.co.uk
|
||||
*/
|
||||
|
||||
@ -628,8 +625,36 @@ ROM_START( wcvol95 )
|
||||
|
||||
// ROM_REGION( 0x80, "user1", 0 ) /* eeprom */
|
||||
// ROM_LOAD( "93c46.3k", 0x00, 0x80, CRC(88f8e270) SHA1(cb82203ad38e0c12ea998562b7b785979726afe5) )
|
||||
|
||||
ROM_REGION( 0x200, "gals", 0 )
|
||||
ROM_LOAD( "GAL16V8B.10J.bin", 0x000, 0x117, CRC(06bbcbd5) SHA1(f7adb4bca13bb799bc42411eb178edfdc11a76c7) )
|
||||
ROM_LOAD( "GAL16V8B.5D.bin", 0x000, 0x117, CRC(117784f0) SHA1(daf3720740621fc3af49333c96795718b693f4d2))
|
||||
ROM_END
|
||||
|
||||
|
||||
|
||||
ROM_START( wcvol95x )
|
||||
ROM_REGION( 0x100000, "maincpu", 0 ) /* DE156 code (encrypted) */
|
||||
// no label markings were present
|
||||
ROM_LOAD32_WORD( "2f.bin", 0x000002, 0x080000, CRC(ac06633d) SHA1(5d37ca3050f35d5fc06f70e91b1522e325471585) )
|
||||
ROM_LOAD32_WORD( "4f.bin", 0x000000, 0x080000, CRC(e211f67a) SHA1(d008c2b809482f17ada608134357fa1205d767d4) )
|
||||
|
||||
ROM_REGION( 0x080000, "gfx1", 0 )
|
||||
ROM_LOAD( "mbx-00.9a", 0x000000, 0x080000, CRC(a0b24204) SHA1(cec8089c6c635f23b3a4aeeef2c43f519568ad70) )
|
||||
|
||||
ROM_REGION( 0x200000, "gfx2", 0 )
|
||||
ROM_LOAD16_BYTE( "mbx-01.12a", 0x000000, 0x100000, CRC(73deb3f1) SHA1(c0cabecfd88695afe0f27c5bb115b4973907207d) )
|
||||
ROM_LOAD16_BYTE( "mbx-02.13a", 0x000001, 0x100000, CRC(3204d324) SHA1(44102f71bae44bf3a9bd2de7e5791d959a2c9bdd) )
|
||||
|
||||
ROM_REGION( 0x200000, "ymz", 0 ) /* YMZ280B-F samples */
|
||||
ROM_LOAD( "mbx-03.13j", 0x00000, 0x200000, CRC(061632bc) SHA1(7900ac56e59f4a4e5768ce72f4a4b7c5875f5ae8) )
|
||||
|
||||
ROM_REGION( 0x200, "gals", 0 )
|
||||
ROM_LOAD( "GAL16V8B.10J.bin", 0x000, 0x117, CRC(06bbcbd5) SHA1(f7adb4bca13bb799bc42411eb178edfdc11a76c7) )
|
||||
ROM_LOAD( "GAL16V8B.5D.bin", 0x000, 0x117, CRC(117784f0) SHA1(daf3720740621fc3af49333c96795718b693f4d2))
|
||||
ROM_END
|
||||
|
||||
|
||||
/**********************************************************************************/
|
||||
|
||||
void deco156_state::descramble_sound( const char *tag )
|
||||
@ -677,3 +702,4 @@ GAME( 1993, hvysmsh, 0, hvysmsh, hvysmsh, deco156_state, hvysmsh, ROT0,
|
||||
GAME( 1993, hvysmsha, hvysmsh, hvysmsh, hvysmsh, deco156_state, hvysmsh, ROT0, "Data East Corporation", "Heavy Smash (Asia version -4)", MACHINE_SUPPORTS_SAVE )
|
||||
GAME( 1993, hvysmshj, hvysmsh, hvysmsh, hvysmsh, deco156_state, hvysmsh, ROT0, "Data East Corporation", "Heavy Smash (Japan version -2)", MACHINE_SUPPORTS_SAVE )
|
||||
GAME( 1995, wcvol95, 0, wcvol95, wcvol95, deco156_state, wcvol95, ROT0, "Data East Corporation", "World Cup Volley '95 (Japan v1.0)", MACHINE_SUPPORTS_SAVE )
|
||||
GAME( 1995, wcvol95x, wcvol95, wcvol95, wcvol95, deco156_state, wcvol95, ROT0, "Data East Corporation", "World Cup Volley '95 Extra Version (Asia v2.0B)", MACHINE_SUPPORTS_SAVE )
|
||||
|
@ -74,7 +74,7 @@
|
||||
*MP7303 TMS1400? 19??, Tiger 7-in-1 Sports Stadium
|
||||
@MP7313 TMS1400 1980, Parker Brothers Bank Shot
|
||||
@MP7314 TMS1400 1980, Parker Brothers Split Second
|
||||
MP7324 TMS1400 1985, Coleco Talking Teacher -> tispeak.cpp
|
||||
MP7324 TMS1400 1985, Tiger K28/Coleco Talking Teacher -> tispeak.cpp
|
||||
MP7332 TMS1400 1981, Milton Bradley Dark Tower -> mbdtower.cpp
|
||||
@MP7334 TMS1400 1981, Coleco Total Control 4
|
||||
@MP7351 TMS1400CR 1982, Parker Brothers Master Merlin
|
||||
|
@ -353,26 +353,36 @@ Language Tutor modules:
|
||||
|
||||
Other manufacturers:
|
||||
|
||||
Coleco Talking Teacher:
|
||||
Tiger Electronics K28 (model 7-232) Sold in Hong Kong, distributed in US as:
|
||||
- Coleco: Talking Teacher
|
||||
- Sears: Talkatron - Learning Computer
|
||||
|
||||
Earlier K28 models 7-230 and 7-231 are on different hardware, showing a different keyboard,
|
||||
VFD display, and presumed to use the SC-01 speech chip.
|
||||
|
||||
K28 model 7-232 (HK), 1985
|
||||
- MCU: TMS1400 MP7324
|
||||
- TMS51xx: TMS5110A
|
||||
- VSM: 16KB CM62084
|
||||
- LCD: unknown 8*16-seg
|
||||
- known releases:
|
||||
+ Coleco: Talking Teacher
|
||||
+ Sears: Talkatron - Learning Computer
|
||||
+ Tiger Electronics(Hong Kong): K-2-8
|
||||
|
||||
An earlier revision used the SC-01 speech chip?
|
||||
|
||||
modules:
|
||||
- x
|
||||
K28 modules:
|
||||
|
||||
- Spelling I: VSM: 16KB CM62086
|
||||
- Spelling II: VSM: 16KB CM62085?
|
||||
- Spelling III: VSM: 16KB CM62087
|
||||
- Expansion Module 1: VSM: 16KB CM62214? - assumed same VSM as CM62086
|
||||
- Expansion Module 2: VSM: 16KB CM62216 - assumed same VSM as the one in Spelling II
|
||||
- Expansion Module 3: VSM: 16KB CM62215 - same VSM as CM62087
|
||||
- Expansion Module 4: VSM: 16KB CM62217
|
||||
- Expansion Module 5: VSM: 16KB CM62218*
|
||||
- Expansion Module 6: VSM: 16KB CM62219
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
TODO:
|
||||
- why doesn't lantutor work?
|
||||
- identify and emulate ctteach LCD
|
||||
- identify and emulate k28 LCD
|
||||
- emulate other known devices
|
||||
|
||||
|
||||
@ -386,7 +396,7 @@ Other manufacturers:
|
||||
#include "softlist.h"
|
||||
|
||||
// internal artwork
|
||||
#include "ctteach.lh"
|
||||
#include "k28.lh"
|
||||
#include "lantutor.lh"
|
||||
#include "snmath.lh"
|
||||
#include "snspell.lh"
|
||||
@ -431,10 +441,10 @@ public:
|
||||
DECLARE_WRITE16_MEMBER(snspellc_write_r);
|
||||
DECLARE_READ8_MEMBER(tntell_read_k);
|
||||
|
||||
void ctteach_prepare_display(UINT8 old, UINT8 data);
|
||||
DECLARE_READ8_MEMBER(ctteach_read_k);
|
||||
DECLARE_WRITE16_MEMBER(ctteach_write_o);
|
||||
DECLARE_WRITE16_MEMBER(ctteach_write_r);
|
||||
void k28_prepare_display(UINT8 old, UINT8 data);
|
||||
DECLARE_READ8_MEMBER(k28_read_k);
|
||||
DECLARE_WRITE16_MEMBER(k28_write_o);
|
||||
DECLARE_WRITE16_MEMBER(k28_write_r);
|
||||
|
||||
// cartridge
|
||||
UINT32 m_cart_max_size;
|
||||
@ -655,15 +665,14 @@ TIMER_DEVICE_CALLBACK_MEMBER(tispeak_state::tntell_get_overlay)
|
||||
}
|
||||
|
||||
|
||||
// ctteach specific
|
||||
// k28 specific
|
||||
|
||||
void tispeak_state::ctteach_prepare_display(UINT8 old, UINT8 data)
|
||||
void tispeak_state::k28_prepare_display(UINT8 old, UINT8 data)
|
||||
{
|
||||
if (data == old)
|
||||
return;
|
||||
// ?
|
||||
}
|
||||
|
||||
WRITE16_MEMBER(tispeak_state::ctteach_write_r)
|
||||
WRITE16_MEMBER(tispeak_state::k28_write_r)
|
||||
{
|
||||
// R1234: TMS5100 CTL8421
|
||||
m_tms5100->ctl_w(space, 0, BITSWAP8(data,0,0,0,0,1,2,3,4) & 0xf);
|
||||
@ -679,17 +688,17 @@ WRITE16_MEMBER(tispeak_state::ctteach_write_r)
|
||||
power_off();
|
||||
|
||||
// R7-R10: LCD data
|
||||
ctteach_prepare_display(m_r >> 7 & 0xf, data >> 7 & 0xf);
|
||||
k28_prepare_display(m_r >> 7 & 0xf, data >> 7 & 0xf);
|
||||
m_r = data;
|
||||
}
|
||||
|
||||
WRITE16_MEMBER(tispeak_state::ctteach_write_o)
|
||||
WRITE16_MEMBER(tispeak_state::k28_write_o)
|
||||
{
|
||||
// O0-O7: input mux low
|
||||
m_inp_mux = (m_inp_mux & ~0xff) | data;
|
||||
}
|
||||
|
||||
READ8_MEMBER(tispeak_state::ctteach_read_k)
|
||||
READ8_MEMBER(tispeak_state::k28_read_k)
|
||||
{
|
||||
// K: TMS5100 CTL, multiplexed inputs
|
||||
return m_tms5100->ctl_r(space, 0) | read_inputs(9);
|
||||
@ -1096,7 +1105,7 @@ static INPUT_PORTS_START( tntell )
|
||||
INPUT_PORTS_END
|
||||
|
||||
|
||||
static INPUT_PORTS_START( ctteach )
|
||||
static INPUT_PORTS_START( k28 )
|
||||
PORT_START("IN.0") // O0
|
||||
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_PGDN) PORT_NAME("Off") // -> auto_power_off
|
||||
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_A) PORT_CODE(KEYCODE_1) PORT_CODE(KEYCODE_1_PAD) PORT_CHAR('A') PORT_NAME("A/1")
|
||||
@ -1332,16 +1341,16 @@ static MACHINE_CONFIG_DERIVED( tntell, vocaid )
|
||||
MACHINE_CONFIG_END
|
||||
|
||||
|
||||
static MACHINE_CONFIG_START( ctteach, tispeak_state )
|
||||
static MACHINE_CONFIG_START( k28, tispeak_state )
|
||||
|
||||
/* basic machine hardware */
|
||||
MCFG_CPU_ADD("maincpu", TMS1400, MASTER_CLOCK/2)
|
||||
MCFG_TMS1XXX_READ_K_CB(READ8(tispeak_state, ctteach_read_k))
|
||||
MCFG_TMS1XXX_WRITE_O_CB(WRITE16(tispeak_state, ctteach_write_o))
|
||||
MCFG_TMS1XXX_WRITE_R_CB(WRITE16(tispeak_state, ctteach_write_r))
|
||||
MCFG_TMS1XXX_READ_K_CB(READ8(tispeak_state, k28_read_k))
|
||||
MCFG_TMS1XXX_WRITE_O_CB(WRITE16(tispeak_state, k28_write_o))
|
||||
MCFG_TMS1XXX_WRITE_R_CB(WRITE16(tispeak_state, k28_write_r))
|
||||
|
||||
MCFG_TIMER_DRIVER_ADD_PERIODIC("display_decay", hh_tms1k_state, display_decay_tick, attotime::from_msec(1))
|
||||
MCFG_DEFAULT_LAYOUT(layout_ctteach)
|
||||
MCFG_DEFAULT_LAYOUT(layout_k28)
|
||||
|
||||
/* sound hardware */
|
||||
MCFG_DEVICE_ADD("tms6100", TMS6100, MASTER_CLOCK/4)
|
||||
@ -1349,6 +1358,13 @@ static MACHINE_CONFIG_START( ctteach, tispeak_state )
|
||||
MCFG_SPEAKER_STANDARD_MONO("mono")
|
||||
MCFG_SOUND_ADD("tms5100", TMS5110A, MASTER_CLOCK)
|
||||
MCFG_FRAGMENT_ADD(tms5110_route)
|
||||
|
||||
/* cartridge */
|
||||
MCFG_GENERIC_CARTSLOT_ADD("cartslot", generic_plain_slot, "k28")
|
||||
MCFG_GENERIC_EXTENSIONS("vsm")
|
||||
MCFG_GENERIC_LOAD(tispeak_state, tispeak_cartridge)
|
||||
|
||||
MCFG_SOFTWARE_LIST_ADD("cart_list", "k28")
|
||||
MACHINE_CONFIG_END
|
||||
|
||||
|
||||
@ -1693,16 +1709,16 @@ ROM_START( vocaid )
|
||||
ROM_END
|
||||
|
||||
|
||||
ROM_START( ctteach )
|
||||
ROM_START( k28 )
|
||||
ROM_REGION( 0x1000, "maincpu", 0 )
|
||||
ROM_LOAD( "mp7324", 0x0000, 0x1000, CRC(08d15ab6) SHA1(5b0f6c53e6732a362c4bb25d966d4072fdd33db8) )
|
||||
|
||||
ROM_REGION( 867, "maincpu:mpla", 0 )
|
||||
ROM_LOAD( "tms1100_common1_micro.pla", 0, 867, CRC(62445fc9) SHA1(d6297f2a4bc7a870b76cc498d19dbb0ce7d69fec) )
|
||||
ROM_REGION( 557, "maincpu:opla", 0 )
|
||||
ROM_LOAD( "tms1400_ctteach_output.pla", 0, 557, CRC(3a5c7005) SHA1(3fe5819c138a90e7fc12817415f2622ca81b40b2) )
|
||||
ROM_LOAD( "tms1400_k28_output.pla", 0, 557, CRC(3a5c7005) SHA1(3fe5819c138a90e7fc12817415f2622ca81b40b2) )
|
||||
|
||||
ROM_REGION( 0x8000, "tms6100", ROMREGION_ERASEFF )
|
||||
ROM_REGION( 0x10000, "tms6100", ROMREGION_ERASEFF ) // 8000-bfff = space reserved for cartridge?
|
||||
ROM_LOAD( "cm62084.vsm", 0x0000, 0x4000, CRC(cd1376f7) SHA1(96fa484c392c451599bc083b8376cad9c998df7d) )
|
||||
ROM_END
|
||||
|
||||
@ -1738,4 +1754,4 @@ COMP( 1981, tntellfr, tntell, 0, tntell, tntell, tispeak_state, tn
|
||||
|
||||
COMP( 1982, vocaid, 0, 0, vocaid, tntell, driver_device, 0, "Texas Instruments", "Vocaid", MACHINE_SUPPORTS_SAVE | MACHINE_IMPERFECT_SOUND | MACHINE_REQUIRES_ARTWORK )
|
||||
|
||||
COMP( 1985, ctteach, 0, 0, ctteach, ctteach, driver_device, 0, "Coleco", "Talking Teacher", MACHINE_SUPPORTS_SAVE | MACHINE_IMPERFECT_SOUND | MACHINE_NOT_WORKING )
|
||||
COMP( 1985, k28, 0, 0, k28, k28, tispeak_state, snspell, "Tiger Electronics", "K28: Talking Learning Computer (model 7-232)", MACHINE_SUPPORTS_SAVE | MACHINE_IMPERFECT_SOUND | MACHINE_NOT_WORKING )
|
||||
|
@ -2359,7 +2359,7 @@ tntelluk
|
||||
tntellfr
|
||||
tntellp
|
||||
vocaid
|
||||
ctteach // Coleco
|
||||
k28 // Tiger Electronics
|
||||
|
||||
// hh_ucom4
|
||||
ufombs // Bambino
|
||||
|
@ -2,10 +2,10 @@
|
||||
// copyright-holders:Grant Galitz, Katelyn Gadd
|
||||
/***************************************************************************
|
||||
|
||||
JSMAME web audio backend v0.3
|
||||
JSMAME web audio backend v0.3
|
||||
|
||||
Original by katelyn gadd - kg at luminance dot org ; @antumbral on twitter
|
||||
Substantial changes by taisel
|
||||
Original by katelyn gadd - kg at luminance dot org ; @antumbral on twitter
|
||||
Substantial changes by taisel
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
@ -23,187 +23,187 @@ var watchDogDateLast = null;
|
||||
var watchDogTimerEvent = null;
|
||||
|
||||
function lazy_init () {
|
||||
//Make
|
||||
if (context) {
|
||||
//Return if already created:
|
||||
return;
|
||||
}
|
||||
if (typeof AudioContext != "undefined") {
|
||||
//Standard context creation:
|
||||
context = new AudioContext();
|
||||
}
|
||||
else if (typeof webkitAudioContext != "undefined") {
|
||||
//Older webkit context creation:
|
||||
context = new webkitAudioContext();
|
||||
}
|
||||
else {
|
||||
//API not found!
|
||||
return;
|
||||
}
|
||||
//Generate a volume control node:
|
||||
gain_node = context.createGain();
|
||||
//Set initial volume to 1:
|
||||
gain_node.gain.value = 1.0;
|
||||
//Connect volume node to output:
|
||||
gain_node.connect(context.destination);
|
||||
//Initialize the streaming event:
|
||||
init_event();
|
||||
//Make
|
||||
if (context) {
|
||||
//Return if already created:
|
||||
return;
|
||||
}
|
||||
if (typeof AudioContext != "undefined") {
|
||||
//Standard context creation:
|
||||
context = new AudioContext();
|
||||
}
|
||||
else if (typeof webkitAudioContext != "undefined") {
|
||||
//Older webkit context creation:
|
||||
context = new webkitAudioContext();
|
||||
}
|
||||
else {
|
||||
//API not found!
|
||||
return;
|
||||
}
|
||||
//Generate a volume control node:
|
||||
gain_node = context.createGain();
|
||||
//Set initial volume to 1:
|
||||
gain_node.gain.value = 1.0;
|
||||
//Connect volume node to output:
|
||||
gain_node.connect(context.destination);
|
||||
//Initialize the streaming event:
|
||||
init_event();
|
||||
};
|
||||
|
||||
function init_event() {
|
||||
//Generate a streaming node point:
|
||||
if (typeof context.createScriptProcessor == "function") {
|
||||
//Current standard compliant way:
|
||||
eventNode = context.createScriptProcessor(4096, 0, 2);
|
||||
}
|
||||
else {
|
||||
//Deprecated way:
|
||||
eventNode = context.createJavaScriptNode(4096, 0, 2);
|
||||
}
|
||||
//Make our tick function the audio callback function:
|
||||
eventNode.onaudioprocess = tick;
|
||||
//Connect stream to volume control node:
|
||||
eventNode.connect(gain_node);
|
||||
//WORKAROUND FOR FIREFOX BUG:
|
||||
initializeWatchDogForFirefoxBug();
|
||||
//Generate a streaming node point:
|
||||
if (typeof context.createScriptProcessor == "function") {
|
||||
//Current standard compliant way:
|
||||
eventNode = context.createScriptProcessor(4096, 0, 2);
|
||||
}
|
||||
else {
|
||||
//Deprecated way:
|
||||
eventNode = context.createJavaScriptNode(4096, 0, 2);
|
||||
}
|
||||
//Make our tick function the audio callback function:
|
||||
eventNode.onaudioprocess = tick;
|
||||
//Connect stream to volume control node:
|
||||
eventNode.connect(gain_node);
|
||||
//WORKAROUND FOR FIREFOX BUG:
|
||||
initializeWatchDogForFirefoxBug();
|
||||
};
|
||||
|
||||
function initializeWatchDogForFirefoxBug() {
|
||||
//TODO: decide if we want to user agent sniff firefox here,
|
||||
//since Google Chrome doesn't need this:
|
||||
watchDogDateLast = (new Date()).getTime();
|
||||
if (watchDogTimerEvent === null) {
|
||||
watchDogTimerEvent = setInterval(function () {
|
||||
var timeDiff = (new Date()).getTime() - watchDogDateLast;
|
||||
if (timeDiff > 500) {
|
||||
disconnect_old_event();
|
||||
init_event();
|
||||
}
|
||||
}, 500);
|
||||
}
|
||||
//TODO: decide if we want to user agent sniff firefox here,
|
||||
//since Google Chrome doesn't need this:
|
||||
watchDogDateLast = (new Date()).getTime();
|
||||
if (watchDogTimerEvent === null) {
|
||||
watchDogTimerEvent = setInterval(function () {
|
||||
var timeDiff = (new Date()).getTime() - watchDogDateLast;
|
||||
if (timeDiff > 500) {
|
||||
disconnect_old_event();
|
||||
init_event();
|
||||
}
|
||||
}, 500);
|
||||
}
|
||||
};
|
||||
|
||||
function disconnect_old_event() {
|
||||
//Disconnect from audio graph:
|
||||
eventNode.disconnect();
|
||||
//IIRC there was a firefox bug that did not GC this event when nulling the node itself:
|
||||
eventNode.onaudioprocess = null;
|
||||
//Null the glitched/unused node:
|
||||
eventNode = null;
|
||||
//Disconnect from audio graph:
|
||||
eventNode.disconnect();
|
||||
//IIRC there was a firefox bug that did not GC this event when nulling the node itself:
|
||||
eventNode.onaudioprocess = null;
|
||||
//Null the glitched/unused node:
|
||||
eventNode = null;
|
||||
};
|
||||
|
||||
function set_mastervolume (
|
||||
// even though it's 'attenuation' the value is negative, so...
|
||||
attenuation_in_decibels
|
||||
// even though it's 'attenuation' the value is negative, so...
|
||||
attenuation_in_decibels
|
||||
) {
|
||||
lazy_init();
|
||||
if (!context) return;
|
||||
lazy_init();
|
||||
if (!context) return;
|
||||
|
||||
// http://stackoverflow.com/questions/22604500/web-audio-api-working-with-decibels
|
||||
// seemingly incorrect/broken. figures. welcome to Web Audio
|
||||
// var gain_web_audio = 1.0 - Math.pow(10, 10 / attenuation_in_decibels);
|
||||
// http://stackoverflow.com/questions/22604500/web-audio-api-working-with-decibels
|
||||
// seemingly incorrect/broken. figures. welcome to Web Audio
|
||||
// var gain_web_audio = 1.0 - Math.pow(10, 10 / attenuation_in_decibels);
|
||||
|
||||
// HACK: Max attenuation in JSMESS appears to be 32.
|
||||
// Hit ' then left/right arrow to test.
|
||||
// FIXME: This is linear instead of log10 scale.
|
||||
var gain_web_audio = 1.0 + (+attenuation_in_decibels / +32);
|
||||
if (gain_web_audio < +0)
|
||||
gain_web_audio = +0;
|
||||
else if (gain_web_audio > +1)
|
||||
gain_web_audio = +1;
|
||||
// HACK: Max attenuation in JSMESS appears to be 32.
|
||||
// Hit ' then left/right arrow to test.
|
||||
// FIXME: This is linear instead of log10 scale.
|
||||
var gain_web_audio = 1.0 + (+attenuation_in_decibels / +32);
|
||||
if (gain_web_audio < +0)
|
||||
gain_web_audio = +0;
|
||||
else if (gain_web_audio > +1)
|
||||
gain_web_audio = +1;
|
||||
|
||||
gain_node.gain.value = gain_web_audio;
|
||||
gain_node.gain.value = gain_web_audio;
|
||||
};
|
||||
|
||||
function update_audio_stream (
|
||||
pBuffer, // pointer into emscripten heap. int16 samples
|
||||
samples_this_frame // int. number of samples at pBuffer address.
|
||||
pBuffer, // pointer into emscripten heap. int16 samples
|
||||
samples_this_frame // int. number of samples at pBuffer address.
|
||||
) {
|
||||
lazy_init();
|
||||
if (!context) return;
|
||||
lazy_init();
|
||||
if (!context) return;
|
||||
|
||||
for (
|
||||
var i = 0,
|
||||
l = samples_this_frame | 0;
|
||||
i < l;
|
||||
i++
|
||||
) {
|
||||
var offset =
|
||||
// divide by sizeof(INT16) since pBuffer is offset
|
||||
// in bytes
|
||||
((pBuffer / 2) | 0) +
|
||||
((i * 2) | 0);
|
||||
for (
|
||||
var i = 0,
|
||||
l = samples_this_frame | 0;
|
||||
i < l;
|
||||
i++
|
||||
) {
|
||||
var offset =
|
||||
// divide by sizeof(INT16) since pBuffer is offset
|
||||
// in bytes
|
||||
((pBuffer / 2) | 0) +
|
||||
((i * 2) | 0);
|
||||
|
||||
var left_sample = HEAP16[offset];
|
||||
var right_sample = HEAP16[(offset + 1) | 0];
|
||||
var left_sample = HEAP16[offset];
|
||||
var right_sample = HEAP16[(offset + 1) | 0];
|
||||
|
||||
// normalize from signed int16 to signed float
|
||||
var left_sample_float = left_sample / sampleScale;
|
||||
var right_sample_float = right_sample / sampleScale;
|
||||
// normalize from signed int16 to signed float
|
||||
var left_sample_float = left_sample / sampleScale;
|
||||
var right_sample_float = right_sample / sampleScale;
|
||||
|
||||
inputBuffer[rear++] = left_sample_float;
|
||||
inputBuffer[rear++] = right_sample_float;
|
||||
if (rear == bufferSize) {
|
||||
rear = 0;
|
||||
}
|
||||
if (start == rear) {
|
||||
start += 2;
|
||||
if (start == bufferSize) {
|
||||
start = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
inputBuffer[rear++] = left_sample_float;
|
||||
inputBuffer[rear++] = right_sample_float;
|
||||
if (rear == bufferSize) {
|
||||
rear = 0;
|
||||
}
|
||||
if (start == rear) {
|
||||
start += 2;
|
||||
if (start == bufferSize) {
|
||||
start = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
function tick (event) {
|
||||
//Find all output channels:
|
||||
for (var bufferCount = 0, buffers = []; bufferCount < 2; ++bufferCount) {
|
||||
buffers[bufferCount] = event.outputBuffer.getChannelData(bufferCount);
|
||||
}
|
||||
//Copy samples from the input buffer to the Web Audio API:
|
||||
for (var index = 0; index < 4096 && start != rear; ++index) {
|
||||
buffers[0][index] = inputBuffer[start++];
|
||||
buffers[1][index] = inputBuffer[start++];
|
||||
if (start == bufferSize) {
|
||||
start = 0;
|
||||
}
|
||||
}
|
||||
//Pad with silence if we're underrunning:
|
||||
while (index < 4096) {
|
||||
buffers[0][index] = 0;
|
||||
buffers[1][index++] = 0;
|
||||
}
|
||||
//Deep inside the bowels of vendors bugs,
|
||||
//we're using watchdog for a firefox bug,
|
||||
//where the user agent decides to stop firing events
|
||||
//if the user agent lags out due to system load.
|
||||
//Don't even ask....
|
||||
watchDogDateLast = (new Date()).getTime();
|
||||
//Find all output channels:
|
||||
for (var bufferCount = 0, buffers = []; bufferCount < 2; ++bufferCount) {
|
||||
buffers[bufferCount] = event.outputBuffer.getChannelData(bufferCount);
|
||||
}
|
||||
//Copy samples from the input buffer to the Web Audio API:
|
||||
for (var index = 0; index < 4096 && start != rear; ++index) {
|
||||
buffers[0][index] = inputBuffer[start++];
|
||||
buffers[1][index] = inputBuffer[start++];
|
||||
if (start == bufferSize) {
|
||||
start = 0;
|
||||
}
|
||||
}
|
||||
//Pad with silence if we're underrunning:
|
||||
while (index < 4096) {
|
||||
buffers[0][index] = 0;
|
||||
buffers[1][index++] = 0;
|
||||
}
|
||||
//Deep inside the bowels of vendors bugs,
|
||||
//we're using watchdog for a firefox bug,
|
||||
//where the user agent decides to stop firing events
|
||||
//if the user agent lags out due to system load.
|
||||
//Don't even ask....
|
||||
watchDogDateLast = (new Date()).getTime();
|
||||
}
|
||||
|
||||
function get_context() {
|
||||
return context;
|
||||
return context;
|
||||
};
|
||||
|
||||
function sample_count() {
|
||||
//TODO get someone to call this from the emulator,
|
||||
//so the emulator can do proper audio buffering by
|
||||
//knowing how many samples are left:
|
||||
if (!context) {
|
||||
//Use impossible value as an error code:
|
||||
return -1;
|
||||
}
|
||||
var count = rear - start;
|
||||
if (start > rear) {
|
||||
count += bufferSize;
|
||||
}
|
||||
return count;
|
||||
//TODO get someone to call this from the emulator,
|
||||
//so the emulator can do proper audio buffering by
|
||||
//knowing how many samples are left:
|
||||
if (!context) {
|
||||
//Use impossible value as an error code:
|
||||
return -1;
|
||||
}
|
||||
var count = rear - start;
|
||||
if (start > rear) {
|
||||
count += bufferSize;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
return {
|
||||
set_mastervolume: set_mastervolume,
|
||||
update_audio_stream: update_audio_stream,
|
||||
get_context: get_context,
|
||||
sample_count: sample_count
|
||||
set_mastervolume: set_mastervolume,
|
||||
update_audio_stream: update_audio_stream,
|
||||
get_context: get_context,
|
||||
sample_count: sample_count
|
||||
};
|
||||
|
||||
})();
|
||||
|
Loading…
Reference in New Issue
Block a user