update 0.8.0

This commit is contained in:
Rupert Hausberger 2013-01-16 19:00:33 +01:00
commit eda41a625b
20 changed files with 9833 additions and 4280 deletions

View file

@ -5,11 +5,13 @@ a:hover { color:#2040c0; text-decoration:underline; }
.alt { text-align:left; vertical-align:top; }
.alm { text-align:left; vertical-align:middle; }
.almsg { text-align:left; vertical-align:middle; font-size:x-small; color:gray; }
.alb { text-align:left; vertical-align:bottom; }
.act { text-align:center; vertical-align:top; }
.acm { text-align:center; vertical-align:middle; }
.acmsb { text-align:center; vertical-align:middle; font-size:x-small; font-weight:bold; }
.acmsg { text-align:center; vertical-align:middle; font-size:x-small; color:gray; }
.acb { text-align:center; vertical-align:bottom; }
.art { text-align:right; vertical-align:top; }
@ -17,6 +19,7 @@ a:hover { color:#2040c0; text-decoration:underline; }
.armb { text-align:right; vertical-align:middle; font-weight:bold; }
.arms { text-align:right; vertical-align:middle; font-size:x-small; }
.armsb { text-align:right; vertical-align:middle; font-size:x-small; font-weight:bold; }
.armsg { text-align:right; vertical-align:middle; font-size:x-small; color:gray; }
.arb { text-align:right; vertical-align:bottom; }
.fsxs { font-size:x-small; }
@ -61,7 +64,6 @@ body {
width:100%;
margin:auto;
text-align:center;
background-color:#f8f8f8;
}
.foot {
@ -71,18 +73,16 @@ body {
font-size:x-small;
}
#config {
width:800px;
#xconfig {
width:400px;
margin:auto;
background-color:#fcfcfc;
}
#config_simple {
width:760px;
padding:20px;
border:1px solid #ccc;
width:380px;
margin:auto;
}
.config_simple_hof {
width:50%;
margin:auto;
padding:10px;
border:1px solid #ccc;
@ -93,9 +93,11 @@ body {
}
#config_advanced {
width:760px;
padding:20px;
width:780px;
margin:auto;
padding:10px;
border:1px solid #ccc;
background-color:#f8f8f8;
display:none;
}
#config_advanced table {
@ -185,7 +187,7 @@ body {
margin:auto;
padding:10px;
border:1px solid #ccc;
background-color:#fcfcfc;
background-color:#f8f8f8;
}
.readme table {
width:100%;

208
index.htm
View file

@ -6,7 +6,7 @@
<meta name="author" content="Rupert Hausberger" />
<meta name="publisher" content="Rupert Hausberger" />
<meta name="description" content="Experimental Amiga Classic Emulator in Javascript" />
<meta name="keywords" content="SAE,Javascript,HTML5,Amiga,AmigaOS,Emulator,Online" />
<meta name="keywords" content="SAE,Javascript,Scripted,Script,HTML5,Amiga,AmigaOS,Emulator,Online" />
<meta name="robots" content="index,nofollow" />
<link rel="icon" type="image/x-icon" href="http://scriptedamigaemulator.net/favicon.ico" />
<link rel="stylesheet" type="text/css" href="index.css" />
@ -30,37 +30,46 @@
<script type="text/javascript" src="sae/cpu.js"></script>
<script type="text/javascript" src="sae/amiga.js"></script>
<script type="text/javascript" src="index.js"></script>
<script type="text/javascript" src="ga.js"></script>
<script type="text/javascript" src="ga.js"></script>
</head>
<body onload="init()">
<body onload="init()">
<div id="base">
<div id="head" class="head">
<div style="height:8px"></div>
<img src="images/logo.png" alt="Scripted Amiga Emulator" />
<noscript>
<div class="noscript">This site does require javascript, obviously :)</div>
</noscript>
<div class="hr"></div>
</div>
<div style="height:20px"></div>
<div id="config">
<div id="config_simple">
<div class="arm">
<button class="button" onclick="switchCfg(1)">Advanced</button>
</div>
<div style="line-height:20px">
<h3>Welcome!</h3>
This site is a demonstration of the '<a href="javascript:openNewTab('https://github.com/naTmeg/ScriptedAmigaEmulator')">SAE</a>' project,
an experimental <a href="javascript:openNewTab('http://en.wikipedia.org/wiki/Amiga')">Amiga</a> emulator in pure javascript and HTML5.<br />
For details, please refer to the <a href="javascript:openNewTab('readme.htm')">readme</a> file.<br /><br />
Below you find a small collection of games and demos to play...<br />
<span class="info">(Use Google Chrome for best results)</span>
</div>
<div style="height:20px"></div>
<div style="height:8px"></div>
<img src="images/logo.png" alt="Scripted Amiga Emulator" />
<div class="acmsg" style="line-height:16px">
<i>Experimental</i> <a href="javascript:openNewTab('http://en.wikipedia.org/wiki/Amiga')">Amiga</a> emulator in pure JavaScript and HTML5<br />
based on <a href="javascript:openNewTab('http://www.amigaemulator.org')">UAE</a>/<a href="javascript:openNewTab('http://winuae.net')">WinUAE</a>,
powered by <a href="javascript:openNewTab('http://aros.org')">AROS</a>
</div>
</div>
<div style="height:8px"></div>
<div id="config">
<div id="config_simple">
<div class="config_simple_hof">
<div class="acm">
<span class="fwb">Browser</span>
</div>
<table>
<tr>
<td class="arms">Supported video-modes:</td>
<td><span id="info_video">-</span></td>
</tr>
<tr>
<td class="arms">Supported audio-modes:</td>
<td><span id="info_audio">-</span></td>
</tr>
<tr>
<td class="arms">SAE-Version:</td>
<td><span id="info_version">-</span></td>
</tr>
</table>
<div style="height:10px"></div>
<div class="hr"></div>
<div style="height:10px"></div>
<div class="acm">
<span class="fwb">Hall of fame</span>
</div>
@ -82,13 +91,17 @@
</td>
</tr>
<tr>
<td class="arms">Audio</td>
<td><input id="cfg_audio_enabled_1" type="checkbox" checked="checked" /></td>
<td class="arms">Audio/Video</td>
<td><input id="cfg_audio_enabled_1" type="checkbox" checked="checked" /><input id="cfg_video_enabled_1" type="checkbox" checked="checked" /></td>
</tr>
<tr>
<td class="arms">Frameskip</td>
<td><input id="cfg_video_skip_1" type="checkbox" checked="checked" /><span class="info">(25 instead of 50 fps)</span></td>
</tr>
<tr>
<td class="arms">Scale 4x</td>
<td><input id="cfg_video_scale_1" type="checkbox" /><span class="info">(1140 x 1152, press F11 for fullscreen)</span></td>
</tr>
<td class="arms">Extra scale</td>
<td><input id="cfg_video_scale_1" type="checkbox" /><span class="info">(double video-size via hardware)</span></td>
</tr>
</table>
<div class="hr"></div>
<table id="cfg_info">
@ -116,28 +129,43 @@
<div style="height:10px"></div>
<div class="acm">
<button class="sbutton" id="cfg_simple_start" onclick="simpleStart()">Play</button>
<button class="button" onclick="switchCfg(1)">Config</button>
</div>
</div>
</div>
</div>
<div id="config_advanced">
<div class="arm">
<button class="button" onclick="switchCfg(0)">Simple</button>
</div>
<div class="acm"><button class="button" onclick="switchCfg(0)">Back</button></div>
<table>
<tr>
<td class="armsb">CPU</td>
<td class="bl">
<table class="wauto">
<tr>
<td class="arm">Speed:</td>
<td>
<select id="cfg_cpu_speed" size="1">
<option value="0">Original</option>
<option value="-1">Maximum</option>
</select>
</td>
</tr>
</table>
Speed
<select id="cfg_cpu_speed" size="1">
<option value="0">Original</option>
<option value="-1">Maximum</option>
</select>
</td>
</tr>
<tr>
<td class="armsb">Chipset</td>
<td class="bl">
Type
<select id="cfg_chipset_type" size="1">
<option value="1">Original Chip Set (OCS Agnus)</option>
<option value="2">Enhanced Chip Set (ECS Agnus only)</option>
<option value="3">Enhanced Chip Set (ECS Agnus, ECS Denise)</option>
</select><br />
<input id="cfg_chipset_cl_enabled" type="checkbox" onchange="spritesUpdate()" />Collisions
<span id="cfg_chipset_cl_grp">
<select id="cfg_chipset_cl" size="1">
<option value="1">Sprites only</option>
<option value="2">Sprites & Playfield (recommended)</option>
<option value="3">Full</option>
</select>
</span><br />
<input id="cfg_video_ntsc" type="checkbox" />NTSC<br />
<input id="cfg_chipset_agnus_dip" type="checkbox" />A1000 OCS Agnus (8361/8367)<br />
<input id="cfg_blitter_immediate" type="checkbox" />Blit immediate
</td>
</tr>
<tr>
@ -309,14 +337,13 @@
<option value="500">5x</option>
<option value="1000">10x</option>
</select>
<span class="gray"> ('Turbo' mode is fastest, but not very compatible)</span>
<span class="gray"> ('Turbo' mode is fastest, but not always compatible. All other modes are very slow)</span>
</td>
</tr>
<tr>
<td class="armsb">Audio</td>
<td class="bl">
<input id="cfg_audio_enabled" type="checkbox" onchange="audioUpdate()" />
Enabled
<input id="cfg_audio_enabled" type="checkbox" onchange="audioUpdate()" />Enabled
<table id="cfg_audio_grp" class="wauto">
<tr>
<td class="arm">Mode:</td>
@ -327,17 +354,6 @@
<option value="2">On (best)</option>
</select>
</td>
</tr>
<tr>
<td class="arm">Channels:</td>
<td>
<select id="cfg_audio_channels" size="1">
<option value="1">1 - Mono</option>
<option value="2">2 - Stereo</option>
</select>
</td>
</tr>
<tr>
<td class="arm">Samplerate:</td>
<td>
<select id="cfg_audio_rate" size="1">
@ -349,36 +365,45 @@
Hz
</td>
</tr>
<tr>
<td class="arm">Channels:</td>
<td>
<select id="cfg_audio_channels" size="1">
<option value="1">1 - Mono</option>
<option value="2">2 - Stereo</option>
</select>
</td>
<td class="arm">Lowpass-filter:</td>
<td><input id="cfg_audio_filter" type="checkbox" /></td>
</tr>
</table>
</td>
</tr>
<tr>
<td class="armsb">Video</td>
<td class="bl">
<input id="cfg_video_enabled" type="checkbox" onchange="videoUpdate()" />
Enabled
<div id="cfg_video_grp">
<input id="cfg_chipset_cl_enabled" type="checkbox" onchange="spritesUpdate()" />
Sprite collisions
<span id="cfg_chipset_cl_grp">
<select id="cfg_chipset_cl" size="1">
<option value="1">Sprite/Sprite</option>
<option value="2">Sprite/Sprite + Sprite/Playfield</option>
</select>
</span>
<br />
<input id="cfg_video_scale" type="checkbox" />
Scale 4x <span class="gray">(1440 x 1152)</span>
<br />
<input id="cfg_video_ntsc" type="checkbox" />
NTSC
<br />
<input id="cfg_video_skip" type="checkbox" />
Frameskip<span class="gray"> (if the emulation is too slow, up to 4 frames will be skipped)</span>
<!--<br />
<input id="cfg_video_drop" type="checkbox" />
Framedrop<span class="gray"> (if the emulation is too fast, a (unprecise) delay is initiated)</span>-->
</div>
<input id="cfg_video_enabled" type="checkbox" onchange="videoUpdate()" />Enabled
<div id="cfg_video_grp">
<!--Driver
<select id="cfg_video_mode" size="1">
<option value="1">Canvas 2D</option>
<option value="2">WebGL</option>
</select><br />
H-Resolution
<select id="cfg_video_hres" size="1">
<option value="0">320 pixel (Lores)</option>
<option value="1">640 pixel (Hires)</option>
<option value="2">1280 pixel (SuperHires, ECS)</option>
</select><br />
V-Resolution
<select id="cfg_video_vres" size="1">
<option value="0">200/256 pixel (Normal)</option>
<option value="1">400/512 pixel (Double)</option>
<option value="2">400/512 pixel (Scanlines)</option>
</select><br />-->
<input id="cfg_video_skip" type="checkbox" />Frameskip <span class="gray">(25 instead of 50 fps)</span><br />
<input id="cfg_video_scale" type="checkbox" />Extra scale <span class="gray">(double video-size via hardware)</span>
</div>
</td>
</tr>
<tr>
@ -559,15 +584,14 @@
<div class="acm">
<button class="sbutton" id="cfg_start" onclick="advandedStart()">Start</button>
</div>
</div>
</div>
<div style="height:10px"></div>
<div id="foot" class="foot">
<span class="gray">&#169;2012-2013 Rupert Hausberger</span> |
<a href="javascript:openNewTab('https://github.com/naTmeg/ScriptedAmigaEmulator')">Source</a> |
<a href="javascript:openNewTab('readme.htm')">Readme</a>
</div>
</div>
</div>
<div style="height:6px"></div>
<div id="foot" class="foot" style="line-height:14px">
<span class="gray">2012-2013 Rupert Hausberger</span> |
<a href="javascript:openNewTab('https://github.com/naTmeg/ScriptedAmigaEmulator')">Source-code</a> |
<a href="javascript:openNewTab('readme.htm')">Description</a>
</div>
</div>
<div id="emul">

412
index.js
View file

@ -13,219 +13,242 @@
**************************************************************************/
const db = [
/* name company year [disks] change [en,f1,f2,map] load [keys] */
/* name company year [disks] [change, turbo] [en,f1,f2,map] load [keys] immediate */
[
['Agony', 'Psygnosis', '1992',
['Agony (Disk 1).adf',
'Agony (Disk 2).adf',
'Agony (Disk 3).adf',
false], false,
false], [false, true],
[true, 16, 17, false],
['Press the LMB to skip the intro.'], [['Weapon menu', 'Space']]
['Press the LMB to skip the intro.'], [['Weapon menu', 'Space']], false
],
['Alien Breed', 'Team 17', '1991',
['Alien Breed (Disk 1).adf',
'Alien Breed (Disk 2).adf',
false, false], true,
false, false], [true, true],
[true, 16, 17, false],
['Insert the 2nd disk manualy and HOLD the fire button.'], [['Show map', 'M']]
['Insert the 2nd disk manualy and HOLD the fire button.'], [['Show map', 'M']], false
],
['Alien Breed II - The Horror Continues', 'Team 17', '1993',
['Alien Breed II - The Horror Continues (Disk 1).adf',
'Alien Breed II - The Horror Continues (Disk 2).adf',
'Alien Breed II - The Horror Continues (Disk 3).adf', false], [false, false],
[true, 16, 17, false],
['Press the LMB to skip the intro.'], [['Show map', 'M']], false
],
['Alien Breed - Tower Assault', 'Team 17', '1994',
['Alien Breed - Tower Assault (Disk 1).adf',
'Alien Breed - Tower Assault (Disk 2).adf',
'Alien Breed - Tower Assault (Disk 3).adf',
'Alien Breed - Tower Assault (Disk 4).adf'], false,
'Alien Breed - Tower Assault (Disk 4).adf'], [false, true],
[true, 8, 17, false],
['Press ESC to skip the intro.'], [['Show map', 'M']]
['Press ESC to skip the intro.'], [['Show map', 'M']], false
],
['Another World', 'Delphine - U.S. Gold', '1991',
/*['Another World', 'Delphine - U.S. Gold', '1991',
['Another World (Disk 1).adf',
'Another World (Disk 2).adf',
false, false], false,
[true, 16, 17, false], [], []
],
false, false], [false, true],
[true, 16, 17, false], ['Select 2x OK when asked.'], [], true
],*/
['Blood Money', 'DMA Design', '1989',
['Blood Money (Disk 1).adf',
'Blood Money (Disk 2).adf',
false, false], true,
false, false], [true, false],
[true, 16, 17, false],
['Press the LMB until the main-nemu<br />and insert the 2nd disk manualy.'], []
['Press the LMB until the main-nemu<br />and insert the 2nd disk manualy.'], [], false
],
['Body Blows Galactic', 'Team 17', '1993',
['Body Blows Galactic (Disk 1).adf',
'Body Blows Galactic (Disk 2).adf',
'Body Blows Galactic (Disk 3).adf',
false], false,
[true, 16, 17, false], ['Press the LMB to skip the intro.'], []
false], [false, false],
[true, 16, 17, false], ['Press the LMB to skip the intro.'], [], false
],
['Dyna Blaster', 'Ubi Soft', '1992',
/*['Dyna Blaster', 'Ubi Soft', '1992',
['Dyna Blaster.adf',
false, false, false], false,
[true, 16, 17, false], ['Press the LMB to skip the intro.'], []
false, false, false], [false, false],
[true, 16, 17, false], ['Press the LMB to skip the intro.'], [], false
],*/
['Lemmings', 'Psygnosis', '1991',
['Lemmings (Disk 1).adf',
'Lemmings (Disk 2).adf',
false, false], [false, true],
[false, 0, 0, false], [], [['with','Mouse']], false
],
['Lotus Turbo Challenge 2', 'Gremlin', '1991',
['Lotus Turbo Challenge 2.adf',
false, false, false], false,
[true, 16, 17, false], ['Press the LMB to skip the intro.'], []
false, false, false], [false, true],
[true, 16, 17, false], ['Press the LMB to skip the intro.'], [], false
],
['Pac-Mania', 'Grandslam', '1988',
['Pac-Mania.adf',
false, false, false], [false, true],
[true, 16, 17, false], [], [], false
],
['Pinball Dreams', 'DICE', '1992',
['Pinball Dreams (Disk 1).adf',
'Pinball Dreams (Disk 2).adf',
false, false], false,
[false, 0, 0, true], [], [['Select table','F1-F4'],['Start game','F1-F8'],['Shoot Ball','Down-Arrow'],['Flip','L/R-Arrows'],['Shake table','Space'],['Change table','ESC and then y/z'],['En/Disable music','M']]
false, false], [false, true],
[false, 0, 0, true], [], [['Select table','F1-F4'],['Start game','F1-F8'],['Shoot Ball','Down-Arrow'],['Flip','L/R-Arrows'],['Shake table','Space'],['Change table','ESC and then y/z'],['En/Disable music','M']], false
],
/*['Pinball Fantasies', 'DICE', '1992',
['Pinball Fantasies', 'DICE', '1992',
['Pinball Fantasies (Disk 1).adf',
'Pinball Fantasies (Disk 2).adf',
'Pinball Fantasies (Disk 3).adf',
false, false], true,
false], [true, true],
[false, 0, 0, true],
['When asked to remove write protection from disk, press the LMB.'],
[['Select table','F1-F4'],['Start game','F1-F8'],['Shoot Ball','Down-Arrow'],['Flip','L/R-Arrows'],['Shake table','Space'],['Change table','ESC and then y/z'],['En/Disable music','M']]
],*/
[['Select table','F1-F4'],['Start game','F1-F8'],['Shoot Ball','Down-Arrow'],['Flip','L/R-Arrows'],['Shake table','Space'],['Change table','ESC and then y/z'],['En/Disable music','M']], false
],
['Prince of Persia', 'Domark', '1991',
['Prince of Persia.adf',
false, false, false], false,
[true, 16, 17, false], ['Press the LMB to skip the intro.'], []
false, false, false], [false, true],
[true, 16, 17, false], ['Press the LMB to skip the intro.'], [], false
],
['Project-X - Special Edition 93', 'Team 17', '1993',
['Project-X - Special Edition 93 (Disk 1).adf',
'Project-X - Special Edition 93 (Disk 2).adf',
'Project-X - Special Edition 93 (Disk 3).adf',
false], false,
false], [false, true],
[true, 16, 17, false],
['Press the LMB to skip the intro.'], [['Select weapon', 'Space (not in trainer mode)']]
['Press the LMB to skip the intro.'], [['Select weapon', 'Space (not in trainer mode)']], false
],
['Rick Dangerous', 'Firebird', '1989',
['Rick Dangerous.adf',
false, false, false], false,
[true, 16, 17, false], [], []
false, false, false], [false, true],
[true, 16, 17, false], [], [], false
],
['Shadow of the Beast II', 'Reflections', '1990',
['Shadow of the Beast II (Disk 1).adf',
'Shadow of the Beast II (Disk 2).adf',
'Shadow of the Beast II (Disk 3).adf',
false], true,
false], [true, true],
[true, 16, 17, false],
['Change the disks manualy when asked.'], []
['Change the disks manualy when asked.'], [], false
],
['Superfrog', 'Team 17', '1993',
['Superfrog (Disk 1).adf',
'Superfrog (Disk 2).adf',
'Superfrog (Disk 3).adf',
'Superfrog (Disk 4).adf'], true,
'Superfrog (Disk 4).adf'], [true, false],
[true, 16, 17, false],
['Change the disks manualy when asked.'], []
['Change the disks manualy when asked.'], [], false
],
/*['Terminator 2 - Judgment Day', 'Ocean', '1991',
['Terminator 2 - Judgment Day', 'Ocean', '1991',
['Terminator 2 - Judgment Day (Disk 1).adf',
'Terminator 2 - Judgment Day (Disk 2).adf',
false, false], true,
false, false], [true, false],
[true, 16, 17, false],
['Press the LMB to skip the intro<br />and insert the 2nd disk manualy.'], []
],*/
['Press the LMB to skip the intro<br />and insert the 2nd disk manualy.'], [], true
],
['Turrican II - The Final Fight', 'Rainbow Arts', '1991',
['Turrican II - The Final Fight (Disk 1).adf',
'Turrican II - The Final Fight (Disk 2).adf',
false, false], false,
[true, 16, 17, false], [], [['Fire-beam','Hold Fire 1'],['Roll on floor', 'Down-arrow + Fire 1'],['Bomb', 'Fire 2'],['Super-Bomb', 'Fire 1 + Fire 2']]
false, false], [false, true],
[true, 16, 17, false], [], [['Fire-beam','Hold Fire 1'],['Roll on floor', 'Down-arrow + Fire 1'],['Bomb', 'Fire 2'],['Super-Bomb', 'Fire 1 + Fire 2']], false
],
['Wings of Death', 'Thalion', '1990',
['Wings of Death (Disk 1).adf',
'Wings of Death (Disk 2).adf',
false, false], true,
false, false], [true, true],
[true, 16, 17, false],
['Press the LMB until the main-nemu<br />and insert the 2nd disk manualy.'], []
['Press the LMB until the main-menu<br />and insert the 2nd disk manualy.'], [], false
],
],
[
['242', 'Virtual Dreams', '1992',
['242.adf',false,false,false], false,
[true, 16, 17, false], [], []
['242.adf',false,false,false], [false, true],
[true, 16, 17, false], [], [], false
],
['9 Fingers', 'Spaceballs', '1993',
['9 Fingers (Disk 1).adf',
'9 Fingers (Disk 2).adf',false,false], false,
[true, 16, 17, false], [], []
'9 Fingers (Disk 2).adf',false,false], [false, true],
[true, 16, 17, false], [], [], false
],
['Alpha and Omega', 'Pure Metal Coders', '1991',
['Alpha and Omega.adf',
false,false,false], true,
[true, 16, 17, false], [], []
false,false,false], [false, false],
[true, 16, 17, false], [], [], false
],
['Copper Master', 'Angels', '1990',
['Copper Master.adf',false,false,false], false,
[true, 16, 17, false], [], []
['Copper Master.adf',false,false,false], [false, true],
[true, 16, 17, false], [], [], false
],
['Deja Vu', 'Anarchy', '1992',
['Deja Vu.adf',false,false,false], false,
[true, 16, 17, false], [], []
['Deja Vu.adf',false,false,false], [false, true],
[true, 16, 17, false], [], [], false
],
['Elysium', 'Sanity', '1991',
['Elysium.adf',false,false,false], false,
[true, 16, 17, false], [], []
['Elysium.adf',false,false,false], [false, true],
[true, 16, 17, false], [], [], false
],
['Ecliptica', 'TRSI', '1991',
['Ecliptica.adf',false,false,false], false,
[true, 16, 17, false], [], []
['Ecliptica.adf',false,false,false], [false, true],
[true, 16, 17, false], [], [], false
],
['Enigma', 'Phenomena', '1991',
['Enigma.adf',false,false,false], false,
[true, 16, 17, false], [], []
['Enigma.adf',false,false,false], [false, true],
[true, 16, 17, false], [], [], false
],
['Global Trash', 'Silents', '1992',
['Global Trash.adf',false,false,false], false,
[true, 16, 17, false], [], []
['Global Trash.adf',false,false,false], [false, true],
[true, 16, 17, false], [], [], false
],
['Hardwired', 'Crionics, Silents', '1992',
['Hardwired (Disk 1).adf',
'Hardwired (Disk 2).adf',
false,false], true,
false,false], [true, true],
[true, 16, 17, false],
['Insert the 2nd disk manualy,<br />click RMB when done.'], []
['Insert the 2nd disk manualy,<br />click RMB when done.'], [], true
],
['Ice', 'Silents', '1991',
['Ice.adf',false,false,false], false,
[true, 16, 17, false], ['Press LMB at the intro-screen'], []
['Ice.adf',false,false,false], [false, true],
[true, 16, 17, false], ['Press LMB at the intro-screen'], [], false
],
['Lost World', 'Balance DK', '1992',
['Lost World.adf',false,false,false], false,
[true, 16, 17, false], ['Press LMB at the intro-screen'], []
['Lost World.adf',false,false,false], [false, true],
[true, 16, 17, false], ['Press LMB at the intro-screen'], [], false
],
['Mental Hangover', 'Scoopex', '1992',
['Mental Hangover.adf',false,false,false], false,
[true, 16, 17, false], ['Press LMB at the intro-screen'], []
['Mental Hangover.adf',false,false,false], [false, true],
[true, 16, 17, false], [], [], false
],
['Multica', 'Andromeda', '1992',
['Multica.adf',false,false,false], false,
[true, 16, 17, false], ['Press LMB at the intro-screen'], []
['Multica.adf',false,false,false], [false, true],
[true, 16, 17, false], ['Press LMB at the intro-screen'], [], false
],
['Project-X (demo rolling)', 'Team 17', '1992',
['Project-X (demo-rolling).adf',false,false,false], false,
[true, 16, 17, false], [], [['Skip level','Fire']]
['Project-X (demo-rolling).adf',false,false,false], [false, true],
[true, 16, 17, false], [], [['Skip level','Fire']], false
],
['Rampage', 'TEK', '1994',
['Rampage.adf',false,false,false], false,
[true, 16, 17, false], ['Press LMB at the intro-screen'], []
['Rampage.adf',false,false,false], [false, false],
[true, 16, 17, false], ['Press LMB at the intro-screen'], [], false
],
['State of the Art', 'Spaceballs', '1992',
['State of the Art.adf',false,false,false], false,
[true, 16, 17, false], [], []
['State of the Art.adf',false,false,false], [false, true],
[true, 16, 17, false], [], [], false
],
['Static Chaos', 'Silents', '1992',
['Static Chaos.adf',false,false,false], false,
[true, 16, 17, false], [], []
['Static Chaos.adf',false,false,false], [false, true],
[true, 16, 17, false], [], [], false
],
['Technological Death', 'Mad Elks', '1993',
['Technological Death.adf',false,false,false], [false, true],
[true, 16, 17, false], [], [], true
],
['Total Destruction', 'Crionics', '1990',
['Total Destruction.adf',false,false,false], false,
[true, 16, 17, false], [], []
['Total Destruction.adf',false,false,false], [false, true],
[true, 16, 17, false], [], [], false
],
['Wayfarer', 'Spaceballs', '1992',
['Wayfarer.adf',false,false,false], false,
[true, 16, 17, false], [], []
['Wayfarer.adf',false,false,false], [false, true],
[true, 16, 17, false], [], [], false
],
['World of Commodore', 'Sanity', '1992',
['World of Commodore.adf',false,false,false], false,
[true, 16, 17, false], [], []
['World of Commodore.adf',false,false,false], [false, true],
[true, 16, 17, false], [], [], false
],
]
];
@ -247,11 +270,18 @@ var dskchg = false;
var dskchgList = [];
var cache = null;
var info = null;
var config = null;
/*-----------------------------------------------------------------------*/
function dechex(dec) { return dec.toString(16); }
function urldecode(url) {
return decodeURIComponent(url.replace(/\+/g, ' '));
}
function dechex(dec) {
return dec.toString(16);
}
function Cache() {
var roms = [null,null];
@ -488,6 +518,32 @@ function loadRemoteSync(url) {
/* simple config */
function setSimpleConfig() {
//document.getElementById('info_name').innerHTML = info.browser_name+' '+info.browser_version+' ('+info.os+')';
var e = document.getElementById('info_video');
if (info.video) {
var t = '';
if (info.video & SAEI_Video_WebGL) t += 'WebGL, ';
if (info.video & SAEI_Video_Canvas2D) t += 'Canvas, ';
e.innerHTML = t.substr(0, t.length - 2);
e.style.color = (info.video & SAEI_Video_WebGL) ? 'green' : 'orange';
} else {
e.innerHTML = 'None';
e.style.color = 'orange';
}
e = document.getElementById('info_audio');
if (info.audio) {
var t = '';
if (info.audio & SAEI_Audio_Webkit) t += 'Webkit, ';
if (info.audio & SAEI_Audio_Mozilla) t += 'Mozilla, ';
e.innerHTML = t.substr(0, t.length - 2);
e.style.color = 'green';
} else {
e.innerHTML = 'None';
e.style.color = 'orange';
}
e = document.getElementById('info_version').innerHTML = info.version;
var s = document.getElementById('cfg_game');
if (s.length == 1) {
for (var i = 0; i < db[0].length; i++) {
@ -507,7 +563,9 @@ function setSimpleConfig() {
}
}
styleDisplayBlock('config_simple', 1);
document.getElementById('cfg_audio_enabled_1').checked = true;
document.getElementById('cfg_audio_enabled_1').checked = config.audio.enabled;
document.getElementById('cfg_video_enabled_1').checked = config.video.enabled;
document.getElementById('cfg_video_skip_1').checked = config.video.framerate != 1;
document.getElementById('cfg_video_scale_1').checked = false;
unselect(document.getElementById('cfg_demo'));
unselect(document.getElementById('cfg_game'));
@ -519,13 +577,11 @@ function setSimpleConfig() {
function getSimpleFloppy() {
//console.log('loadDisks() %d %d', dbGrp, dbNum);
config.floppy.speed = 1000; /* 1000 percent == x10 */
if (dbNum == 0) {
if (dbNum == 0) { /* nothing selected */
config.floppy.drive[0].type = SAEV_Config_Floppy_Type_35_DD;
config.floppy.drive[0].name = null;
config.floppy.drive[0].data = null;
config.floppy.drive[1].type = SAEV_Config_Floppy_Type_35_DD;
config.floppy.drive[1].type = SAEV_Config_Floppy_Type_None;
config.floppy.drive[1].name = null;
config.floppy.drive[1].data = null;
config.floppy.drive[2].type = SAEV_Config_Floppy_Type_None;
@ -534,6 +590,7 @@ function getSimpleFloppy() {
config.floppy.drive[3].type = SAEV_Config_Floppy_Type_None;
config.floppy.drive[3].name = null;
config.floppy.drive[3].data = null;
config.floppy.speed = SAEV_Config_Floppy_Speed_Original;
return true;
}
@ -548,7 +605,7 @@ function getSimpleFloppy() {
dskchgList = [];
if (item[4]) {
if (item[4][0]) {
var i, filename, url;
for (i = 0; i < 4; i++) {
@ -594,21 +651,26 @@ function getSimpleFloppy() {
}
}
}
config.floppy.speed = item[4][1] ? SAEV_Config_Floppy_Speed_Turbo : SAEV_Config_Floppy_Speed_Original;
return true;
}
function getSimpleConfig() {
var item = dbNum > 0 ? db[dbGrp - 1][dbNum - 1] : null;
var e, num;
config.cpu.speed = SAEV_Config_CPU_Speed_Original;
//config.cpu.speed = SAEV_Config_Floppy_Speed_Turbo;
config.cpu.compatible = true;
//config.chipset.type = SAEV_Config_Chipset_Type_OCS;
config.chipset.colLevel = SAEV_Config_Chipset_ColLevel_None;
config.chipset.mask = SAEV_Config_Chipset_Mask_OCS;
config.chipset.agnus_dip = false; /* A1000 */
config.chipset.collision_level = SAEV_Config_Chipset_ColLevel_None;
config.blitter.immediate = (item !== null && item[8]) ? true : false;
config.blitter.waiting = config.blitter.immediate ? 0 : 1;
config.ram.chip.size = SAEV_Config_RAM_Chip_Size_512K;
config.ram.slow.size = SAEV_Config_RAM_Slow_Size_512K;
config.ram.fast.size = SAEV_Config_RAM_Fast_Size_512K;
config.ram.fast.size = SAEV_Config_RAM_Fast_Size_1M;
config.rom.name = aros_rom_file;
config.rom.size = SAEV_Config_ROM_Size_512K;
@ -624,21 +686,22 @@ function getSimpleConfig() {
if (!getSimpleFloppy())
return false;
e = document.getElementById('cfg_audio_enabled_1');
config.audio.enabled = e.checked ? true : false;
config.audio.enabled = document.getElementById('cfg_audio_enabled_1').checked ? true : false;
if (config.audio.enabled) {
config.audio.mode = SAEV_Config_Audio_Mode_Play_Best;
config.audio.channels = SAEV_Config_Audio_Channels_Stereo;
//config.audio.rate = SAEV_Config_Audio_Rate_48000;
config.audio.rate = SAEV_Config_Audio_Rate_44100;
}
/*if (info.audio == 0) {
config.audio.enabled = false;
document.getElementById('cfg_audio_enabled_1').checked = config.audio.enabled;
}*/
config.video.enabled = true;
e = document.getElementById('cfg_video_scale_1');
config.video.scale = e.checked ? true : false;
config.video.ntsc = false;
config.video.skip = true;
config.video.id = 'myVideo';
config.video.enabled = document.getElementById('cfg_video_enabled_1').checked ? true : false;
config.video.scale = document.getElementById('cfg_video_scale_1').checked ? true : false;
config.video.framerate = document.getElementById('cfg_video_skip_1').checked ? 2 : 1;
config.video.ntsc = false;
config.keyboard.enabled = true;
config.keyboard.mapShift = (item !== null && item[5][3]) ? true : false;
@ -667,6 +730,7 @@ function getSimpleConfig() {
config.hooks.floppy_step = hooks_floppy_step;
config.hooks.fps = hooks_fps;
config.hooks.cpu = hooks_cpu;
return true;
}
@ -777,8 +841,24 @@ function setConfig() {
switch (config.cpu.speed) {
case SAEV_Config_CPU_Speed_Original: e[0].selected = true; break;
case SAEV_Config_CPU_Speed_Maximum: e[1].selected = true; break;
}
}
e = document.getElementById('cfg_chipset_type');
switch (config.chipset.mask) {
case SAEV_Config_Chipset_Mask_OCS: e[0].selected = true; break
case SAEV_Config_Chipset_Mask_ECS_AGNUS: e[1].selected = true; break
case SAEV_Config_Chipset_Mask_ECS_DENISE: e[2].selected = true; break
}
document.getElementById('cfg_chipset_cl_enabled').checked = config.chipset.collision_level != SAEV_Config_Chipset_ColLevel_None;
switch (config.chipset.collision_level) {
case SAEV_Config_Chipset_ColLevel_Sprite_Sprite: document.getElementById('cfg_chipset_cl')[0].selected = true; break;
case SAEV_Config_Chipset_ColLevel_Sprite_Playfield: document.getElementById('cfg_chipset_cl')[1].selected = true; break;
case SAEV_Config_Chipset_ColLevel_Full: document.getElementById('cfg_chipset_cl')[2].selected = true; break;
}
document.getElementById('cfg_chipset_agnus_dip').checked = config.chipset.agnus_dip != 0;
document.getElementById('cfg_blitter_immediate').checked = config.blitter.immediate != 0;
styleDisplayInline('cfg_chipset_cl_grp', config.chipset.collision_level != SAEV_Config_Chipset_ColLevel_None);
var e = document.getElementById('cfg_mem_chip');
switch (config.ram.chip.size) {
case SAEV_Config_RAM_Chip_Size_256K: e[0].selected = true; break;
@ -839,18 +919,13 @@ function setConfig() {
case SAEV_Config_Audio_Rate_44100: document.getElementById('cfg_audio_rate')[2].selected = true; break;
case SAEV_Config_Audio_Rate_48000: document.getElementById('cfg_audio_rate')[3].selected = true; break;
}
document.getElementById('cfg_audio_filter').checked = config.audio.filter != 0;
styleDisplayTable('cfg_audio_grp', config.audio.enabled);
document.getElementById('cfg_video_enabled').checked = config.video.enabled != 0;
document.getElementById('cfg_chipset_cl_enabled').checked = config.chipset.colLevel != SAEV_Config_Chipset_ColLevel_None;
switch (config.chipset.colLevel) {
case SAEV_Config_Chipset_ColLevel_Sprite_Sprite: document.getElementById('cfg_chipset_cl')[0].selected = true; break;
case SAEV_Config_Chipset_ColLevel_Sprite_Playfield: document.getElementById('cfg_chipset_cl')[1].selected = true; break;
}
styleDisplayInline('cfg_chipset_cl_grp', config.chipset.colLevel != SAEV_Config_Chipset_ColLevel_None);
document.getElementById('cfg_video_scale').checked = config.video.scale;
document.getElementById('cfg_video_ntsc').checked = config.video.ntsc != 0;
document.getElementById('cfg_video_skip').checked = config.video.skip != 0;
document.getElementById('cfg_video_skip').checked = config.video.framerate != 1;
styleDisplayBlock('cfg_video_grp', config.video.enabled != 0);
document.getElementById('cfg_keyborad_enabled').checked = config.keyboard.enabled != 0;
@ -892,21 +967,32 @@ function setConfig() {
styleDisplayInline('dskchg_grp', 1);
}
function getMask(type) {
switch (type) {
case SAEV_Config_Chipset_Type_OCS: return SAEV_Config_Chipset_Mask_OCS;
case SAEV_Config_Chipset_Type_ECS_AGNUS: return SAEV_Config_Chipset_Mask_ECS_AGNUS;
case SAEV_Config_Chipset_Type_ECS_DENISE: return SAEV_Config_Chipset_Mask_ECS_DENISE;
}
}
function getConfig() {
var e;
e = document.getElementById('cfg_cpu_speed');
config.cpu.speed = parseInt(getSelectValue(e));
//e = document.getElementById('cfg_chipset_type');
//config.chipset.type = parseInt(getSelectValue(e));
e = document.getElementById('cfg_chipset_type');
config.chipset.mask = getMask(parseInt(getSelectValue(e)));
e = document.getElementById('cfg_chipset_cl_enabled');
if (e.checked) {
e = document.getElementById('cfg_chipset_cl');
config.chipset.colLevel = parseInt(getSelectValue(e));
config.chipset.collision_level = parseInt(getSelectValue(e));
} else
config.chipset.colLevel = SAEV_Config_Chipset_ColLevel_None;
config.chipset.collision_level = SAEV_Config_Chipset_ColLevel_None;
config.chipset.agnus_dip = document.getElementById('cfg_chipset_agnus_dip').checked ? true : false;
config.blitter.immediate = document.getElementById('cfg_blitter_immediate').checked ? true : false;
config.blitter.waiting = config.blitter.immediate ? 0: 1;
e = document.getElementById('cfg_mem_chip');
config.ram.chip.size = parseInt(getSelectValue(e));
e = document.getElementById('cfg_mem_slow');
@ -918,35 +1004,31 @@ function getConfig() {
alert('No Kickstart ROM.');
return false;
}
e = document.getElementById('cfg_ext_addr');
config.ext.addr = parseInt(getSelectValue(e));
e = document.getElementById('cfg_floppy_speed');
config.floppy.speed = parseInt(getSelectValue(e));
e = document.getElementById('cfg_audio_enabled');
config.audio.enabled = e.checked ? true : false;
config.audio.enabled = document.getElementById('cfg_audio_enabled').checked ? true : false;
if (config.audio.enabled) {
e = document.getElementById('cfg_audio_mode');
config.audio.mode = parseInt(getSelectValue(e));
e = document.getElementById('cfg_audio_channels');
config.audio.channels = parseInt(getSelectValue(e));
e = document.getElementById('cfg_audio_rate');
config.audio.rate = parseInt(getSelectValue(e));
config.audio.rate = parseInt(getSelectValue(e));
config.audio.filter = document.getElementById('cfg_audio_filter').checked ? true : false;
}
e = document.getElementById('cfg_video_enabled');
config.video.enabled = e.checked ? true : false;
e = document.getElementById('cfg_video_scale');
config.video.scale = e.checked ? true : false;
e = document.getElementById('cfg_video_ntsc');
config.video.ntsc = e.checked ? true : false;
e = document.getElementById('cfg_video_skip');
config.video.skip = e.checked ? true : false;
config.video.id = 'myVideo';
config.video.enabled = document.getElementById('cfg_video_enabled').checked ? true : false;
config.video.scale = document.getElementById('cfg_video_scale').checked ? true : false;
config.video.ntsc = document.getElementById('cfg_video_ntsc').checked ? true : false;
config.video.framerate = document.getElementById('cfg_video_skip').checked ? 2 : 1;
e = document.getElementById('cfg_keyborad_enabled');
config.keyboard.enabled = e.checked ? true : false;
e = document.getElementById('cfg_keyborad_mapshift');
config.keyboard.mapShift = e.checked ? true : false;
config.keyboard.enabled = document.getElementById('cfg_keyborad_enabled').checked ? true : false;
config.keyboard.mapShift = document.getElementById('cfg_keyborad_mapshift').checked ? true : false;
e = document.getElementById('cfg_ports_0');
config.ports[0].type = parseInt(getSelectValue(e));
@ -977,15 +1059,18 @@ function getConfig() {
}
}
e = document.getElementById('cfg_serial_enabled');
config.serial.enabled = e.checked ? true : false;
config.serial.enabled = document.getElementById('cfg_serial_enabled').checked ? true : false;
config.hooks.error = hooks_error;
config.hooks.power_led = hooks_power_led;
config.hooks.floppy_motor = hooks_floppy_motor;
config.hooks.floppy_step = hooks_floppy_step;
config.hooks.fps = hooks_fps;
config.hooks.cpu = hooks_cpu;
config.hooks.cpu = hooks_cpu;
if (config.chipset.mask != SAEV_Config_Chipset_Mask_OCS)
config.chipset.agnus_dip = false;
return true;
}
@ -995,10 +1080,40 @@ function getConfig() {
function init() {
cache = new Cache();
config = SAE({cmd:'init'});
//config = SAE({cmd:'getConfig'});
SAE({cmd:'init'});
info = SAE({cmd:'getInfo'});
config = SAE({cmd:'getConfig'});
//console.log(info);
//console.log(config);
setSimpleConfig();
if (window.location.hash.length > 0) {
var name = urldecode(window.location.hash.substr(1));
var start = false;
for (var i = 0; i < db[0].length; i++) {
if (db[0][i][0] == name) {
document.getElementById('cfg_game')[i+1].selected = true;
preSelect(1);
start = true;
break;
}
}
if (!start) {
for (var i = 0; i < db[1].length; i++) {
if (db[1][i][0] == name) {
document.getElementById('cfg_demo')[i+1].selected = true;
preSelect(2);
start = true;
break;
}
}
}
if (start)
simpleStart();
}
}
function start() {
@ -1006,6 +1121,15 @@ function start() {
styleDisplayBlock('base', 0);
styleDisplayBlock('emul', 1);
if (mode == 0) {
var item = dbNum > 0 ? db[dbGrp - 1][dbNum - 1] : null;
if (item)
window.location.hash = item[0];
else
window.location.hash = '';
} else
window.location.hash = '';
//SAE({cmd:'setConfig',data:config});
/*var result = SAE({cmd:'start'});
if (result.error != SAEE_None) {
@ -1123,7 +1247,7 @@ function preSelect(grp)
document.getElementById('cfg_info_comp').innerHTML = item[1];
document.getElementById('cfg_info_year').innerHTML = item[2];
styleDisplayTable('cfg_info', 1);
styleDisplayInline('dskchg_grp', item[4] ? 1 : 0);
styleDisplayInline('dskchg_grp', item[4][0] ? 1 : 0);
if (item[6].length) {
document.getElementById('cfg_info_load').innerHTML = item[6];
@ -1245,6 +1369,7 @@ function floppyUpdate(n) {
var e = document.getElementById('cfg_df'+n+'_type');
config.floppy.drive[n].type = parseInt(getSelectValue(e));
floppyEject(n);
} else {
styleDisplayInline('cfg_df'+n+'_grp', 0);
floppyEject(n);
@ -1325,7 +1450,8 @@ function portUpdate2() {
function hooks_error(err, msg) {
stop();
alert(msg);
if (msg !== null)
alert(msg);
}
function hooks_power_led(on) {

View file

@ -14,14 +14,16 @@
</head>
<body>
<div class="head">
<div style="height:8px"></div>
<img src="images/logo.png" alt="Scripted Amiga Emulator" />
<noscript>
<div class="noscript">This site does require javascript, obviously :)</div>
</noscript>
<div class="hr"></div>
</div>
<div style="height:20px"></div>
<div style="height:8px"></div>
<img src="images/logo.png" alt="Scripted Amiga Emulator" />
<div class="acmsg">
<i>Experimental</i> <a href="javascript:openNewTab('http://en.wikipedia.org/wiki/Amiga')">Amiga</a> emulator in pure JavaScript and HTML5
</div>
</div>
<div style="height:8px"></div>
<div class="readme">
<table>
<tr>
@ -32,20 +34,20 @@
<li>A very fast computer</li>
<li>A browser capable of HTML5 with:
<ul>
<li>WegGL</li>
<li>WebAudio</li>
<li>WegGL or Canvas 2D <span class="gray">(optional)</span></li>
<li>WebAudio <span class="gray">(optional)</span></li>
<li>FileReader <span class="gray">(GUI)</span></li>
<li>Typed arrays</li>
<li>FileReader (GUI)</li>
</ul>
</li>
<li>A ROM:
<ul>
<li>Amiga Kickstart 1.x-2.04 (not included for copyright reasons)</li>
<li>AROS Kickstart (included)</li>
<li>Amiga Kickstart 1.0-2.05 <span class="gray">(not included for copyright reasons)</span></li>
<li>AROS Kickstart <span class="gray">(included)</span></li>
</ul>
</li>
<li style="list-style-type:none"><br /></li>
<li>And a bunch of ADF-files to test (optional)</li>
<li>And a bunch of ADF-files to test <span class="gray">(optional)</span></li>
</ul>
</li>
</ul>
@ -53,8 +55,8 @@
<td>
<table>
<tr><td colspan="2"><span class="fwb">Supported browsers</span></td></tr>
<tr><td class="armb" style="color:green">Chrome</td><td>Fastest</td></tr>
<tr><td class="armb" style="color:green">Firefox</td><td>Medium speed</td></tr>
<tr><td class="armb" style="color:green">Chrome</td><td>Very fast</td></tr>
<tr><td class="armb" style="color:orange">Firefox</td><td>Medium speed</td></tr>
<tr><td class="armb" style="color:orange">Opera</td><td>Slow speed, no audio</td></tr>
<tr><td class="armb" style="color:red">IE</td><td>No support</td></tr>
<tr><td class="armb">Other</td><td>Untested</td></tr>
@ -86,30 +88,17 @@
<li><span class="fwb">Usage/Hints</span>
<ul>
<li>Press F11 for fullscreen. Most browsers support that.</li>
<li>If something does crash, try another memory setting or a different ROM. The original kickstart (1.3) work's best.</li>
<li>If something does crash, try another memory setting or a different ROM.<br />
The original kickstart (1.3) does work best.</li>
</ul>
</li>
</ul>
<ul>
<li><span class="fwb">Known bugs/problems</span>
<ul>
<li>There may be graphics-errors:
<ul>
<li>Graphics may be at a wrong position or a wrong color.</li>
<li>Fast blinking sprites are not displayed if 'Frameskip' is active.</li>
<li>Copper initiated color-changes within a scanline are not recognized.</li>
<li>The next update (0.8) will deal with this.</li>
</ul>
</li>
<li>Left/right shift/alt/ctrl are the same. That's a browser 'feature' and can't be fixed.</li>
</ul>
</li>
</ul>
<ul>
<li><span class="fwb">Missing features</span>
<ul>
<li>User-config</li>
<li>Maybe ECS support</li>
<li>Blinking sprites are not shown if "Frameskip" is active.</li>
<li>There may be short and heavy speed-fluctuations in the beginning of the emulation.</li>
<li>Left/right shift/alt/ctrl are the same. That's a browser "feature" and can't be fixed.</li>
</ul>
</li>
</ul>
@ -121,7 +110,7 @@
</li>
</ul>
<ul>
<li><span class="fwb">Source code</span>
<li><span class="fwb">Source-code</span>
<ul>
<li><a href="javascript:openNewTab('https://github.com/naTmeg/ScriptedAmigaEmulator')">github.com/naTmeg/ScriptedAmigaEmulator</a></li>
</ul>
@ -130,24 +119,25 @@
<ul>
<li><span class="fwb">Thanks</span>
<ul>
<li>Bernd Schmidt</li>
<li>WinUAE and AROS team.</li>
<li><a href="javascript:openNewTab('http://www.amigaemulator.org')">Bernd Schmidt</a></li>
<li><a href="javascript:openNewTab('http://winuae.net')">WinUAE</a> team</li>
<li><a href="javascript:openNewTab('http://aros.org')">AROS</a> team</li>
</ul>
</li>
</ul>
<ul>
<li><span class="fwb">License</span>
<ul>
<li>This is a <b>free</b> project.</li>
<li>This is a free project.</li>
<li>You may use the emulator in your own website.</li>
<li>If you use the emulator in your own website, you <b>must</b> provide a link to this homepage.</li>
<li>If you use the emulator in your own website, you <b>must not</b> change the copyright header in the source-files.</li>
<li>Commercial use <b>in any form</b> is prohibited. This includes donations.</li>
<li>If you use the emulator in your own website, you must provide a link to this homepage.</li>
<li>If you use the emulator in your own website, you must not change the copyright header in the source-files.</li>
<li>Commercial use in any form is prohibited. This includes donations.</li>
<li>No warranty expressed or implied. Use at your own risk.</li>
</ul>
</li>
</ul>
<div class="hr"></div>
<!--<div class="hr"></div>
<table>
<tr><td colspan="3" class="acm"><span class="fwb">Fully working...</span></td></tr>
<tr>
@ -158,7 +148,6 @@
<li>Alien Breed</li>
<li>Alien Breed Special Edition 92<span class="fwb"> (0.7)</span></li>
<li>Alien Breed Tower Assault<span class="fwb"> (0.6)</span></li>
<li>Alien Breed II - The horror continues<span class="fwb"> (0.7)</span></li>
<li>Boby Blows Galactic<span class="fwb"> (0.7)</span></li>
<li>Agony<span class="fwb"> (0.6.1)</span></li>
<li>Another World</li>
@ -169,7 +158,7 @@
<li>Dynablaster<span class="fwb"> (0.7)</span></li>
<li>Firepower</li>
<li>Lotus Turbo Challenge 1/2<span class="fwb"> (0.6)</span></li>
<li>NorthPrince of Persia<span class="fwb"> (0.7)</span></li>
<li>North'n South<span class="fwb"> (0.7)</span></li>
<li>Pinball Dreams</li>
<li>Pinball Fantasies (the demo with 1 desk)</li>
<li>Prince of Persia<span class="fwb"> (0.7)</span></li>
@ -217,10 +206,66 @@
</tr>
<tr><td colspan="3" class="acm"><span class="fwb">Note:</span> The lists corresponds to Kickstart 1.3</td></tr>
</table>
<div class="hr"></div>
<div class="hr"></div>-->
<ul>
<li><span class="fwb">History</span>
<ul>
<li>0.8.0 (16.01.2013):
<ul>
<li>Display
<ul>
<li>Ported and optimized playfield-code from WinUAE.<br />
This adds ECS and AGA support and fixes graphics-errors.<br />
The AGA part is commented out, because there is no 68020 yet.</li>
<li>Added support for drawing via 'Canvas 2D' if 'WebGL' is not avail.</li>
<li>Added support for auto-driver detection.</li>
</ul>
</li>
<li>Audio
<ul>
<li>While disk access, audio performance is much better now.</li>
<li>Added support for the A500 lowpass-filter. Not enabled by default.</li>
<li>Added support for auto-driver detection.</li>
</ul>
</li>
<li>Memory
<ul>
<li>To gain speed, all memory is now accessed directly and not via functions.<br />
So, don't care for a possible illegal memory access.</li>
<li>Fixed bug, where kickstart 1.2 failed to load.</li>
<li>Fixed incorrect extended-address bug.</li>
</ul>
</li>
<li>CPU
<ul>
<li>Splitted address-types of ADDQ/SUBQ into separate functions for more speed.</li>
<li>Added bus-read/write cycles tables. For internal use only.</li>
</ul>
</li>
<li>CIA
<ul>
<li>I decided to port the latest cia-code from WinUAE while i was trying to find a bug.<br />
Well, the bug is still there. Let's keep the code nevertheless.</li>
</ul>
</li>
<li>GUI
<ul>
<li>Added info box of supported drivers.</li>
<li>Added a 'Chipset'-section and various options.</li>
<li>Packed the main GUI.</li>
</ul>
</li>
<li>Common
<ul>
<li>Added support for easy URL sharing. E.g. to show the Multica-demo to a friend,<br />
one may send the link "http://scriptedamigaemulator.net/#Multica"<br />
and the demo will start immediately. (thanks mrdoob)</li>
<li>Many small optimizations.</li>
</ul>
</li>
</ul>
</li>
<li style="list-style-type:none"><br/></li>
<li>0.7.0 (24.12.2012):
<ul>
<li>Common
@ -246,7 +291,8 @@
<li>Audio
<ul>
<li>Added a ring-buffer before output. No more "bagpipe"-like audio.</li>
<li>Added a option to just emulate the hardware, but not to play any sound, e.g. "Agony" was not starting, if audio was disabled.</li>
<li>Added a option to just emulate the hardware, but not to play any sound,<br />
e.g. "Agony" was not starting, if audio was disabled.</li>
</ul>
</li>
<li>Display

View file

@ -12,6 +12,14 @@ function set_special(x) { AMIGA.spcflags |= x; }
function clr_special(x) { AMIGA.spcflags &= ~x; }
function Amiga() {
this.info = {
version: SAEV_Version+'.'+SAEV_Revision+'.'+SAEV_Revision_Sub,
browser_name: BrowserDetect.browser,
browser_version: BrowserDetect.version,
os: BrowserDetect.OS,
video:0,
audio:0
};
this.config = new Config();
this.mem = new Memory();
this.expansion = new Expansion();
@ -29,35 +37,31 @@ function Amiga() {
this.audio = new Audi0();
this.cpu = new CPU();
this.state = CMD_STOP;
this.state = ST_STOP;
this.delay = 0;
this.spcflags = 0;
//this.loading = 0;
this.intena = 0;
this.intena_internal = 0;
this.intreq = 0;
this.intreq_internal = 0;
this.dmacon = 0;
this.adkcon = 0;
configSetDefaults(this.config);
this.info.video = this.video.available;
this.info.audio = this.audio.available;
/*---------------------------------*/
this.setup = function() {
if (this.config.chipset.type == SAEV_Config_Chipset_Type_OCS)
this.config.chipset.agnus = this.config.video.ntsc ? AGNUS_8370 : AGNUS_8371;
this.mem.setup();
this.expansion.setup();
this.events.setup();
this.playfield.setup();
this.video.setup();
this.cia.setup();
this.rtc.setup();
this.input.setup();
this.disk.setup();
this.playfield.setup();
this.video.setup();
this.audio.setup();
this.custom.setup();
this.cpu.setup();
@ -72,26 +76,25 @@ function Amiga() {
this.reset = function() {
BUG.info('Amiga.reset()');
this.delay = 0;
this.spcflags = 0;
//this.loading = 0;
this.intena = 0;
this.intena_internal = 0;
this.intreq = 0;
this.intreq_internal = 0;
this.dmacon = 0;
this.adkcon = 0;
this.expansion.reset();
this.events.reset();
this.playfield.reset();
this.cia.reset();
this.disk.reset();
this.input.reset();
this.serial.reset();
this.blitter.reset();
this.copper.reset();
this.playfield.reset();
this.audio.reset();
this.custom.reset();
this.cpu.reset(this.mem.rom.lower);
@ -109,7 +112,7 @@ function Amiga() {
setTimeout('AMIGA.waitForStart()', 10);
else {
this.reset();
this.state = CMD_CYCLE;
this.state = ST_CYCLE;
setTimeout('AMIGA.cycle()', 0);
}
}
@ -120,24 +123,24 @@ function Amiga() {
this.start = function() {
if (this.state == CMD_STOP) {
if (this.state == ST_STOP) {
this.setup();
this.reset();
this.state = CMD_CYCLE;
this.state = ST_CYCLE;
setTimeout('AMIGA.cycle()', 0);
}
}
this.stop = function() {
if (this.state != CMD_STOP) {
this.state = CMD_STOP;
if (this.state != ST_STOP) {
this.state = ST_STOP;
this.cleanup();
}
}
this.pause = function(state) {
if (this.state != CMD_STOP) {
this.state = state ? CMD_PAUSE : CMD_CYCLE;
if (this.state != ST_STOP) {
this.state = state ? ST_PAUSE : ST_CYCLE;
this.audio.pauseResume(state);
}
}
@ -159,97 +162,100 @@ function Amiga() {
*/
this.insert = function(unit) {
if (this.state != CMD_STOP)
if (this.state != ST_STOP)
this.disk.insert(unit);
}
this.eject = function(unit) {
if (this.state != CMD_STOP)
if (this.state != ST_STOP)
this.disk.eject(unit);
}
/*---------------------------------*/
/* mainloop */
/* mainloop */
this.cycle = function() {
try {
while (this.state == CMD_CYCLE)
this.cpu.cycle();
this.cpu.cycle();
} catch (e) {
if (e instanceof VSync) {
//console.log(e.error, e.message);
this.state = ST_IDLE;
} else
if (e instanceof FatalError) {
this.state = ST_STOP;
this.stop();
this.config.hooks.error(e.error, e.message);
} else
} else /* normal exception */ {
this.state = ST_STOP;
this.stop();
console.log(e);
}
}
if (this.state == CMD_IDLE) {
this.state = CMD_CYCLE;
if (this.state == ST_IDLE) {
this.state = ST_CYCLE;
setTimeout('AMIGA.cycle()', this.delay);
}
else if (this.state == CMD_PAUSE)
setTimeout('AMIGA.cyclePause()', 0);
else if (this.state == ST_PAUSE)
AMIGA.cyclePause();
else
setTimeout('AMIGA.cycleExit()', 0);
AMIGA.cycleExit();
}
this.cyclePause = function() {
if (this.state == CMD_CYCLE)
if (this.state == ST_CYCLE)
setTimeout('AMIGA.cycle()', 0);
else if (this.state == CMD_PAUSE)
else if (this.state == ST_PAUSE)
setTimeout('AMIGA.cyclePause()', 500);
else
setTimeout('AMIGA.cycleExit()', 0);
AMIGA.cycleExit();
}
this.cycleExit = function() {
this.dump();
//this.cia.dump();
}
/*---------------------------------*/
this.dmaen = function (dmamask) {
return ((this.dmacon & DMAF_DMAEN) && (this.dmacon & dmamask));
return ((this.dmacon & DMAF_DMAEN) != 0 && (this.dmacon & dmamask) != 0);
}
this.DMACONR = function(hpos) {
this.playfield.decide_line(hpos);
this.playfield.decide_fetch(hpos);
this.dmacon &= ~(0x4000 | 0x2000);
//this.dmacon |= (this.blitter.state == BLT_STOP ? 0 : 0x4000) | (this.blitter.zero ? 0x2000 : 0); //old
//this.dmacon |= ((blit_interrupt || (!blit_interrupt && currprefs.cs_agnusbltbusybug && !blt_info.got_cycle)) ? 0 : 0x4000) | (blt_info.blitzero ? 0x2000 : 0); //new org
var iz = this.blitter.getIntZero();
this.dmacon |= (iz[0] ? 0 : 0x4000) | (iz[1] ? 0x2000 : 0);
this.dmacon |= ((iz[0] ? 0 : 0x4000) | (iz[1] ? 0x2000 : 0));
return this.dmacon;
}
this.DMACON = function (v, hpos) {
var oldcon = this.dmacon;
this.playfield.decide_line(hpos);
this.playfield.decide_fetch(hpos);
if (v & INTF_SETCLR)
this.dmacon |= v & ~INTF_SETCLR;
else
this.dmacon &= ~v;
this.dmacon &= 0x1fff;
var changed = this.dmacon ^ oldcon;
var oldcop = (oldcon & DMAF_COPEN) && (oldcon & DMAF_DMAEN);
var newcop = (this.dmacon & DMAF_COPEN) && (this.dmacon & DMAF_DMAEN);
var oldcop = (oldcon & DMAF_COPEN) != 0 && (oldcon & DMAF_DMAEN) != 0;
var newcop = (this.dmacon & DMAF_COPEN) != 0 && (this.dmacon & DMAF_DMAEN) != 0;
if (oldcop != newcop) {
if (newcop && !oldcop) {
this.copper.compute_spcflag_copper(this.events.hpos());
} else if (!newcop) {
this.copper.enabled_thisline = false;
clr_special (SPCFLAG_COPPER);
clr_special(SPCFLAG_COPPER);
}
}
//if ((this.dmacon & DMAF_COPEN) > (oldcon & DMAF_COPEN))
//this.copper.COPJMP(1, 0);
if ((this.dmacon & DMAF_SPREN) > (oldcon & DMAF_SPREN)) {
for (var i = 0; i < 8; i++)
this.playfield.sprites.sprite[i].dmastate = 1;
}
if ((this.dmacon & DMAF_BLTPRI) > (oldcon & DMAF_BLTPRI) && this.blitter.getState() != BLT_done)
set_special(SPCFLAG_BLTNASTY);
if (this.dmaen(DMAF_BLTEN) && this.blitter.getState() == BLT_init)
@ -260,12 +266,12 @@ function Amiga() {
if (changed & (DMAF_DMAEN | 0x0f))
this.audio.state_machine();
/*if (this.copper.active && !this.events.eventtab[EV_COPPER].active) {
this.events.eventtab[EV_COPPER].active = true;
this.events.eventtab[EV_COPPER].oldcycles = this.events.currcycle;
this.events.eventtab[EV_COPPER].evtime = 1 * CYCLE_UNIT + this.events.currcycle;
this.events.schedule();
}*/
if (changed & (DMAF_DMAEN | DMAF_BPLEN)) {
this.playfield.update_ddf_change();
if (this.dmaen(DMAF_BPLEN))
this.playfield.maybe_start_bpl_dma(hpos);
}
this.events.schedule();
}
/*---------------------------------*/
@ -296,27 +302,13 @@ function Amiga() {
}
this.INTENA = function(v) {
var old = this.intena;
if (v & INTF_SETCLR)
this.intena |= v & ~INTF_SETCLR;
else
this.intena &= ~v;
if (!(v & INTF_SETCLR) && old == this.intena)
return;
if (AMIGA.config.cpu.exact) {
this.events.event2_newevent_xx(-1, INT_PROCESSING_DELAY, this.intena, function(v) {
//console.log('INTENA()', v);
AMIGA.intena_internal = v;
AMIGA.doint();
});
} else {
this.intena_internal = this.intena;
if (v & INTF_SETCLR)
this.doint();
}
if (v & INTF_SETCLR)
this.doint();
}
/*---------------------------------*/
@ -333,64 +325,36 @@ function Amiga() {
else
this.intreq &= ~v;
if (AMIGA.config.cpu.exact) {
if (old == this.intreq && this.intreq_internal == this.intreq)
return;
this.events.event2_newevent_xx(-1, INT_PROCESSING_DELAY, this.intreq, function(v) {
//console.log('INTREQ_0()', v);
AMIGA.intreq_internal = v;
AMIGA.doint();
});
} else {
this.intreq_internal = this.intreq;
if (this.intreq == old)
return;
if (v & INTF_SETCLR)
this.doint();
}
if ((v & INTF_SETCLR) && this.intreq != old)
this.doint();
}
this.INTREQ = function(v) {
this.INTREQ_0(v);
this.cia.reThink();
this.cia.rethink();
}
/*---------------------------------*/
this.intlev = function() {
var imask = this.intreq_internal & this.intena_internal;
if (imask && (this.intena_internal & INTF_INTEN)) {
var imask = this.intreq & this.intena;
if (imask && (this.intena & INTF_INTEN)) {
if (imask & 0x2000) return 6;
if (imask & (0x1000 | 0x0800)) return 5;
if (imask & (0x0400 | 0x0200 | 0x0100 | 0x0080)) return 4;
if (imask & (0x0040 | 0x0020 | 0x0010)) return 3;
if (imask & 0x1800) return 5;
if (imask & 0x0780) return 4;
if (imask & 0x0070) return 3;
if (imask & 0x0008) return 2;
if (imask & (0x0001 | 0x0002 | 0x0004)) return 1;
if (imask & 0x0007) return 1;
}
return -1;
}
this.doint = function() {
if (AMIGA.config.cpu.exact) {
this.cpu.setIPL(this.intlev());
clr_special(SPCFLAG_INT);
return;
}
if (AMIGA.config.cpu.compatible)
set_special(SPCFLAG_INT);
else
set_special(SPCFLAG_DOINT);
}
this.send_interrupt = function(num, delay) {
if (AMIGA.config.cpu.exact && delay > 0) {
if (!(this.intreq & (1 << num))) {
this.events.event2_newevent_xx(-1, delay, num, function(v) {
AMIGA.INTREQ_0(INTF_SETCLR | (1 << v));
});
}
} else
this.INTREQ_0(INTF_SETCLR | (1 << num));
set_special(SPCFLAG_DOINT);
}
}
@ -405,7 +369,8 @@ function SAE(x) {
BUG.info('API.init() SEA %d.%d.%d', SAEV_Version, SAEV_Revision, SAEV_Revision_Sub);
AMIGA = new Amiga();
return AMIGA.config;
//return AMIGA.config;
break;
case 'reset':
BUG.info('API.reset()');
AMIGA.reset();
@ -438,10 +403,13 @@ function SAE(x) {
BUG.info('API.eject() DF%d', x.unit);
AMIGA.eject(x.unit);
break;
/*case 'getConfig':
case 'getInfo':
BUG.info('API.getInfo()');
return AMIGA.info;
case 'getConfig':
BUG.info('API.getConfig()');
return AMIGA.config;
case 'setConfig':
/*case 'setConfig':
BUG.info('API.setConfig() size '+x.data.ext.size);
AMIGA.config = x.data;
break;*/

View file

@ -6,6 +6,9 @@
* ©2012 Rupert Hausberger
* Commercial use is prohibited.
*
***************************************************************************
* Notes: Ported from WinUAE 2.5.0
*
**************************************************************************/
/*const DEBUG_CHANNEL_MASK = 15
@ -70,9 +73,7 @@ function Filter() {
}
this.filter = function(input, state) {
if (!this.on)
return input;
//if (!this.on) return input;
var o, fs = filter_state[state];
fs.rc1 = filter1_a0 * input + (1 - filter1_a0) * fs.rc1 + DENORMAL_OFFSET;
@ -83,12 +84,11 @@ function Filter() {
fs.rc3 = filter_a0 * no + (1 - filter_a0) * fs.rc3;
fs.rc4 = filter_a0 * fs.rc3 + (1 - filter_a0) * fs.rc4;
fs.rc5 = filter_a0 * fs.rc4 + (1 - filter_a0) * fs.rc5;
o = fs.rc5;
o = Math.floor(fs.rc5);
} else
o = no;
o = Math.floor(no);
if (o > 32767) o = 32767; else if (o < -32768) o = -32768;
return o;
return o > 32767 ? 32767 : (o < -32768 ? -32768 : o);
}
}
@ -367,6 +367,9 @@ function Channel(num) {
}
function Audi0() {
const SAMPLE_BUFFER_SIZE = 8192 >> 0;
this.available = 0;
var channel = null;
var last_cycles = 0;
@ -410,6 +413,35 @@ function Audi0() {
/*---------------------------------*/
//this.init = function()
{
var test;
/*try {
test = new AudioContext();
test = null;
this.available |= SAEI_Audio_Default;
} catch (e) {}*/
try {
test = new webkitAudioContext();
if (test && test.createJavaScriptNode)
this.available |= SAEI_Audio_Webkit;
test = null;
} catch (e) {}
try {
test = new Audio();
if (test && test.mozSetup)
this.available |= SAEI_Audio_Mozilla;
test = null;
} catch (e) {}
//console.log(this.available);
}
/*---------------------------------*/
function getRate(v) {
switch (v) {
case SAEV_Config_Audio_Rate_11025: return 11025;
@ -420,30 +452,29 @@ function Audi0() {
}
}
this.recalc_sample_evtime = function() {
var hpos, lines = 0;
this.calc_sample_evtime = function(freq, longframe, linetoggle) {
var lines = 0.0;
var hpos;
if (AMIGA.config.video.ntsc) {
hpos = 227.5;
if (linetoggle) {
hpos = AMIGA.playfield.maxhpos_short + 0.5;
lines += 0.5;
} else {
var longframe = (AMIGA.playfield.bplcon0 & 4) ? -1 : AMIGA.events.lofStore;
hpos = 227;
hpos = AMIGA.playfield.maxhpos_short + 0.0;
if (longframe < 0)
lines += 0.5;
else if (longframe > 0)
lines += 1.0;
}
lines += AMIGA.events.maxvpos;
scaled_sample_evtime_orig = Math.floor(hpos * lines * AMIGA.events.hz * CYCLE_UNIT / getRate(AMIGA.config.audio.rate));
lines += AMIGA.playfield.maxvpos_nom;
scaled_sample_evtime_orig = Math.floor(hpos * lines * freq * CYCLE_UNIT / getRate(AMIGA.config.audio.rate));
scaled_sample_evtime = scaled_sample_evtime_orig;
//sampler_evtime = hpos * lines * AMIGA.events.hz * CYCLE_UNIT;
//scaled_sample_evtime = Math.floor((AMIGA.events.maxhpos * AMIGA.events.maxvpos * AMIGA.events.hz + getRate(AMIGA.config.audio.rate) - 1) / getRate(AMIGA.config.audio.rate)) * CYCLE_UNIT;
console.log('Audio.recalc_sample_evtime() scaled_sample_evtime %f (%f) | hpos %d, lines %d', scaled_sample_evtime, scaled_sample_evtime * CYCLE_UNIT_INV, hpos, lines);
}
/*#if 0
lines -= AMIGA.playfield.maxvpos_nom;
BUG.info('%d.%d %d.%d %.2f', maxhpos_short, linetoggle ? 5 : 0, maxvpos_nom + (lines == 1.0 ? 1 : 0), lines > 0 && lines < 1 ? 5 : 0, scaled_sample_evtime);
#endif*/
BUG.info('Audio.calc_sample_evtime() scaled_sample_evtime %f (%f) | hpos %d, lines %d', scaled_sample_evtime, scaled_sample_evtime * CYCLE_UNIT_INV, hpos, lines);
}
this.setup = function() {
if (channel === null) {
@ -455,53 +486,32 @@ function Audi0() {
return;
if (driver.ctx === null) {
if (BrowserDetect.browser == 'Firefox') {
try {
driver.ctx = new Audio();
BUG.info('Audio.setup() using "Audio()"');
} catch (e) {}
} else {
try {
driver.ctx = new AudioContext();
BUG.info('Audio.setup() using "AudioContext()"');
} catch (e) {
try {
driver.ctx = new webkitAudioContext();
BUG.info('Audio.setup() using "webkitAudioContext()"');
} catch (e) {}
}
}
if (this.available & SAEI_Audio_Webkit)
driver.ctx = new webkitAudioContext();
else if (this.available & SAEI_Audio_Mozilla)
driver.ctx = new Audio();
}
if (driver.ctx === null) {
if (confirm('Can\'t initialise WebAudio. Continue without audio-playback?')) {
AMIGA.config.audio.mode = SAEV_Config_Audio_Mode_Emul;
return;
} else
Fatal(SAEE_Audio_WebAudio_Not_Avail, 'Can\'t initialise WebAudio.');
Fatal(SAEE_Audio_WebAudio_Not_Avail, null);
}
this.filter.setup(0);
this.filter.setup(AMIGA.config.audio.filter); /* A500 lowpass-filter */
this.recalc_sample_evtime();
var hz = AMIGA.config.video.ntsc ? 60 : 50;
this.calc_sample_evtime(hz, 1, AMIGA.config.video.ntsc);
sampleBuffer.size = 8192 >> 0;
sampleBuffer.size = SAMPLE_BUFFER_SIZE;
sampleBuffer.realSize = sampleBuffer.size << 1;
sampleBuffer.data = new Float32Array(sampleBuffer.realSize << (AMIGA.config.audio.channels - 1));
ringBuffer.size = sampleBuffer.size << 1;
ringBuffer.size = sampleBuffer.size + (sampleBuffer.size >> 1);
ringBuffer.data = new Float32Array(ringBuffer.size << (AMIGA.config.audio.channels - 1));
if (BrowserDetect.browser == 'Firefox') {
driver.ctx.mozSetup(AMIGA.config.audio.channels, getRate(AMIGA.config.audio.rate));
/*driver.moz.currentWritePosition = 0;
driver.moz.prebufferSize = getRate(AMIGA.config.audio.rate) >> 1; //prebuffer 500ms
driver.moz.tail = null;*/
//driver.moz.interval = setInterval(mozHandler, Math.floor(1000 / (getRate(AMIGA.config.audio.rate) / sampleBuffer.size)));
driver.moz.interval = setInterval(mozHandler, Math.floor(1000 / AMIGA.events.hz * (sampleBuffer.size / (getRate(AMIGA.config.audio.rate) / AMIGA.events.hz))));
BUG.info('Audio.setup() enabled mozilla audio, channels %d, rate %d', AMIGA.config.audio.channels, getRate(AMIGA.config.audio.rate));
} else {
if (this.available & SAEI_Audio_Webkit) {
var inputs = BrowserDetect.browser == 'Safari' ? 1 : 0;
//if (inputs == 1) BUG.info('Audio.setup() Safari fix enabled.');
@ -510,32 +520,36 @@ function Audi0() {
driver.def.node.connect(driver.ctx.destination);
BUG.info('Audio.setup() enabled webkit audio, channels %d, rate %d', AMIGA.config.audio.channels, getRate(AMIGA.config.audio.rate));
}
else if (this.available & SAEI_Audio_Mozilla) {
driver.ctx.mozSetup(AMIGA.config.audio.channels, getRate(AMIGA.config.audio.rate));
/*driver.moz.currentWritePosition = 0;
driver.moz.prebufferSize = getRate(AMIGA.config.audio.rate) >> 1; //prebuffer 500ms
driver.moz.tail = null;*/
//driver.moz.interval = setInterval(mozHandler, Math.floor(1000 / (getRate(AMIGA.config.audio.rate) / sampleBuffer.size)));
driver.moz.interval = setInterval(mozHandler, Math.floor(1000 / hz * (sampleBuffer.size / (getRate(AMIGA.config.audio.rate) / hz))));
BUG.info('Audio.setup() enabled mozilla audio, channels %d, rate %d', AMIGA.config.audio.channels, getRate(AMIGA.config.audio.rate));
}
}
this.cleanup = function() {
if (driver.ctx !== null) {
if (BrowserDetect.browser == 'Firefox') {
clearInterval(driver.moz.interval);
} else {
if (this.available & SAEI_Audio_Webkit) {
driver.def.node.disconnect(0);
driver.def.node = null;
}
else if (this.available & SAEI_Audio_Mozilla) {
clearInterval(driver.moz.interval);
}
}
}
this.pauseResume = function(pause) {
if (!AMIGA.config.audio.enabled || AMIGA.config.audio.mode == SAEV_Config_Audio_Mode_Emul) return;
if (driver.ctx !== null) {
if (BrowserDetect.browser == 'Firefox') {
if (pause && !driver.paused) {
clearInterval(driver.moz.interval);
driver.paused = true;
} else if (!pause && driver.paused) {
driver.moz.interval = setInterval(mozHandler, 100);
driver.paused = false;
}
} else {
if (this.available & SAEI_Audio_Webkit) {
if (driver.def.node) {
if (pause && !driver.paused) {
driver.def.node.disconnect(0);
@ -546,20 +560,29 @@ function Audi0() {
}
}
}
else if (this.available & SAEI_Audio_Mozilla) {
if (pause && !driver.paused) {
clearInterval(driver.moz.interval);
driver.paused = true;
} else if (!pause && driver.paused) {
driver.moz.interval = setInterval(mozHandler, 100);
driver.paused = false;
}
}
}
}
this.reset = function() {
for (var i = 0; i < 4; i++)
channel[i].reset();
last_cycles = AMIGA.events.currcycle;
next_sample_evtime = scaled_sample_evtime;
this.schedule();
AMIGA.events.schedule();
work_to_do = 0;
prevcon = -1;
prevcon = 0;
sampleBuffer.pos = 0;
sampleBuffer.rate.clr();
@ -592,7 +615,7 @@ function Audi0() {
ret = 1;
this.event_reset();
}
work_to_do = 4 * AMIGA.events.maxvpos * 50;
work_to_do = 4 * AMIGA.playfield.maxvpos_nom * 50;
return ret;
}
@ -716,16 +739,16 @@ function Audi0() {
}
this.hsync = function() {
//if (!AMIGA.config.audio.enabled) return; /* done in events.hSyncPre() */
if (work_to_do > 0) {
work_to_do--;
if (work_to_do == 0)
//work_to_do--;
if (--work_to_do == 0)
this.deactivate();
}
this.update();
}
this.vsync = function() { }
/*---------------------------------*/
this.AUDxDAT = function(nr, v) {
@ -763,7 +786,7 @@ function Audi0() {
if (per < PERIOD_MIN * CYCLE_UNIT)
per = PERIOD_MIN * CYCLE_UNIT;
if (per < PERIOD_MIN_NONCE * CYCLE_UNIT && !AMIGA.config.cpu.exact && channel[nr].dmaenstore)
if (per < PERIOD_MIN_NONCE * CYCLE_UNIT && channel[nr].dmaenstore)
per = PERIOD_MIN_NONCE * CYCLE_UNIT;
if (channel[nr].per == PERIOD_MAX - 1 && per != PERIOD_MAX - 1) {
@ -853,8 +876,10 @@ function Audi0() {
data1 += data2;
data2 = data0 << 1;
data3 = data1 << 1;
data2 = this.filter.filter(data2, 0);
data3 = this.filter.filter(data3, 1);
if (AMIGA.config.audio.filter) {
data2 = this.filter.filter(data2, 0);
data3 = this.filter.filter(data3, 1);
}
if (sampleBuffer.pos < sampleBuffer.realSize) {
if (AMIGA.config.audio.channels == SAEV_Config_Audio_Channels_Stereo) {
@ -910,8 +935,10 @@ function Audi0() {
data1 += data2;
data2 = data0 << 1;
data3 = data1 << 1;
data2 = this.filter.filter(data2, 0);
data3 = this.filter.filter(data3, 1);
if (AMIGA.config.audio.filter) {
data2 = this.filter.filter(data2, 0);
data3 = this.filter.filter(data3, 1);
}
if (sampleBuffer.pos < sampleBuffer.realSize) {
if (AMIGA.config.audio.channels == SAEV_Config_Audio_Channels_Stereo) {
@ -921,7 +948,7 @@ function Audi0() {
} else
sampleBuffer.data[sampleBuffer.pos++] = inv32768 * ((data2 + data3) * 0.5);
} else
BUG.info('Audio.sample_handler() audio buffer over-run!');
BUG.info('Audio.sample_handler_crux() audio buffer over-run!');
}
this.sample_handler_rh = function() {
@ -938,23 +965,25 @@ function Audi0() {
var delta, ratio;
delta = channel[0].per;
ratio = ((channel[0].evtime % delta) << 8) / delta;
ratio = Math.floor(((channel[0].evtime % delta) << 8) / delta);
data0 = (data0 * (256 - ratio) + data0p * ratio) >> 8;
delta = channel[1].per;
ratio = ((channel[1].evtime % delta) << 8) / delta;
ratio = Math.floor(((channel[1].evtime % delta) << 8) / delta);
data1 = (data1 * (256 - ratio) + data1p * ratio) >> 8;
delta = channel[2].per;
ratio = ((channel[2].evtime % delta) << 8) / delta;
ratio = Math.floor(((channel[2].evtime % delta) << 8) / delta);
data1 += (data2 * (256 - ratio) + data2p * ratio) >> 8;
delta = channel[3].per;
ratio = ((channel[3].evtime % delta) << 8) / delta;
ratio = Math.floor(((channel[3].evtime % delta) << 8) / delta);
data0 += (data3 * (256 - ratio) + data3p * ratio) >> 8;
}
data2 = data0 << 1;
data3 = data1 << 1;
data2 = this.filter.filter(data2, 0);
data3 = this.filter.filter(data3, 1);
if (AMIGA.config.audio.filter) {
data2 = this.filter.filter(data2, 0);
data3 = this.filter.filter(data3, 1);
}
if (sampleBuffer.pos < sampleBuffer.realSize) {
if (AMIGA.config.audio.channels == SAEV_Config_Audio_Channels_Stereo) {
@ -964,13 +993,13 @@ function Audi0() {
} else
sampleBuffer.data[sampleBuffer.pos++] = inv32768 * ((data2 + data3) * 0.5);
} else
BUG.info('Audio.sample_handler() audio buffer over-run!');
BUG.info('Audio.sample_handler_rh() audio buffer over-run!');
}
/*---------------------------------*/
//var avg = 0, cnt = 0;
function fillRingBuffer() {
if (sampleBuffer.pos == 0) return false;
@ -1042,10 +1071,8 @@ function Audi0() {
ringBuffer.usage = 0;
}
}
//console.log(sampleBuffer.pos, ringBuffer.usage, rate);
sampleBuffer.pos = 0;
return [playBuffer, rate];
}

File diff suppressed because it is too large Load diff

1816
sae/cia.js

File diff suppressed because it is too large Load diff

View file

@ -12,23 +12,22 @@ function Config() {
this.init = false;
this.cpu = {
model: 68000,
speed: 0, /* 0 if cpu.exact */
exact: false,
compatible: true
model: 0,
speed: 0,
compatible: false
};
this.blitter = {
exact: false, /* do not change */
immediate: false, /* false if blitter.exact */
waiting: 1 /* 0 if cpu.exact or blitter.immediate */
immediate: false,
waiting: 0
};
this.chipset = {
type: 0,
agnus: 0,
mask: 0,
agnus_dip: 0,
agnus_rev: 0,
denise: 0,
paula: 0,
colLevel: 0
denise_rev: 0,
collision_level: 0,
genlock: false,
refreshrate: 0
};
this.ram = {
chip: {
@ -71,17 +70,25 @@ function Config() {
speed:0
};
this.video = {
id: '',
enabled: false,
scale: false,
ntsc: false,
skip: false,
id: ''
ntsc: false, //~
framerate: 0,
hresolution: 0,
vresolution: 0,
scandoubler: false,
scanlines: false,
extrawidth: 0,
xcenter: 0,
ycenter: 0
};
this.audio = {
enabled: false,
mode:0,
channels: 0,
rate: 0
rate: 0,
filter: false
};
this.ports = [{
type: 0,
@ -102,6 +109,10 @@ function Config() {
this.rtc = {
type: 0
};
this.cia = {
tod: 0,
tod_hack: 0
};
this.hooks = {
error: null,
power_led: null,
@ -110,79 +121,94 @@ function Config() {
fps: null,
cpu: null
};
}
function configSetDefaults(c) {
c.init = true;
function configSetDefaults(c) {
c.init = true;
c.cpu.speed = SAEV_Config_CPU_Speed_Original;
c.cpu.model = 68000;
c.cpu.speed = SAEV_Config_CPU_Speed_Original;
c.cpu.compatible = false;
c.chipset.type = SAEV_Config_Chipset_Type_OCS;
if (c.chipset.type == SAEV_Config_Chipset_Type_OCS) {
c.chipset.agnus = c.video.ntsc ? AGNUS_8370 : AGNUS_8371;
c.chipset.agnus_rev = 0;
c.chipset.denise = DENISE_8362;
} else if (c.chipset.type == SAEV_Config_Chipset_Type_ECS) {
c.chipset.agnus = AGNUS_8372;
c.chipset.agnus_rev = 5;
c.chipset.denise = DENISE_8373;
//c.chipset.mask = CSMASK_ECS_AGNUS | CSMASK_ECS_DENISE;
//c.chipset.mask = CSMASK_ECS_AGNUS;
c.chipset.mask = 0;
c.chipset.agnus_dip = false; /* A1000 */
c.chipset.agnus_rev = -1;
c.chipset.denise_rev = -1;
c.chipset.collision_level = SAEV_Config_Chipset_ColLevel_None;
c.chipset.genlock = false;
c.chipset.refreshrate = -1;
c.blitter.immediate = 0 ? true : false;
c.blitter.waiting = 1; /* 0 if blitter.immediate */
c.ram.chip.size = SAEV_Config_RAM_Chip_Size_512K;
c.ram.slow.size = SAEV_Config_RAM_Slow_Size_512K;
c.ram.fast.size = SAEV_Config_RAM_Fast_Size_1M;
c.rom.size = SAEV_Config_ROM_Size_None;
c.rom.data = null;
c.ext.addr = SAEV_Config_EXT_Addr_E0;
c.ext.size = SAEV_Config_EXT_Size_None;
c.ext.data = null;
c.floppy.drive[0].type = SAEV_Config_Floppy_Type_35_DD;
c.floppy.drive[0].name = null;
c.floppy.drive[0].data = null;
c.floppy.drive[1].type = SAEV_Config_Floppy_Type_35_DD;
c.floppy.drive[1].name = null;
c.floppy.drive[1].data = null;
c.floppy.drive[2].type = SAEV_Config_Floppy_Type_None;
c.floppy.drive[2].name = null;
c.floppy.drive[2].data = null;
c.floppy.drive[3].type = SAEV_Config_Floppy_Type_None;
c.floppy.drive[3].name = null;
c.floppy.drive[3].data = null;
c.floppy.speed = SAEV_Config_Floppy_Speed_Original;
c.video.id = 'video';
c.video.enabled = true;
c.video.scale = false;
c.video.ntsc = false;
c.video.framerate = 2;
c.video.hresolution = 1 ? RES_HIRES : RES_LORES;
c.video.vresolution = 1 ? VRES_DOUBLE : VRES_NONDOUBLE;
c.video.scandoubler = 0 ? true : false;
c.video.scanlines = 0 ? true : false;
c.video.extrawidth = 0;
c.video.xcenter = 0;
c.video.ycenter = 0
c.audio.enabled = true;
//c.audio.mode = SAEV_Config_Audio_Mode_Play_Best;
c.audio.mode = SAEV_Config_Audio_Mode_Play;
c.audio.channels = SAEV_Config_Audio_Channels_Stereo;
c.audio.rate = SAEV_Config_Audio_Rate_44100;
c.audio.filter = false;
c.ports[0].type = SAEV_Config_Ports_Type_Mouse;
c.ports[0].move = SAEV_Config_Ports_Move_WASD;
c.ports[0].fire[0] = 49;
c.ports[0].fire[1] = 50;
c.ports[1].type = SAEV_Config_Ports_Type_Joy1;
c.ports[1].move = SAEV_Config_Ports_Move_Arrows;
c.ports[1].fire[0] = 16;
c.ports[1].fire[1] = 17;
c.keyboard.enabled = true;
c.keyboard.mapShift = false;
c.rtc.type = 1 ? SAEV_Config_RTC_Type_MSM6242B : SAEV_Config_RTC_Type_RF5C01A;
c.cia.tod = 0;
c.cia.tod_hack = true;
c.hooks.error = function(err, msg) {}
c.hooks.power_led = function(on) {}
c.hooks.floppy_motor = function(unit, on) {}
c.hooks.floppy_step = function(unit, cyl) {}
c.hooks.fps = function(fps) {}
c.hooks.cpu = function(usage) {}
}
c.chipset.paula = PAULA_8364;
c.chipset.colLevel = SAEV_Config_Chipset_ColLevel_None;
c.ram.chip.size = SAEV_Config_RAM_Chip_Size_512K;
c.ram.slow.size = SAEV_Config_RAM_Slow_Size_512K;
c.ram.fast.size = SAEV_Config_RAM_Fast_Size_512K;
c.rom.size = SAEV_Config_ROM_Size_None;
c.rom.data = null;
c.ext.addr = SAEV_Config_EXT_Addr_E0;
c.ext.size = SAEV_Config_EXT_Size_None;
c.ext.data = null;
c.floppy.drive[0].type = SAEV_Config_Floppy_Type_35_DD;
c.floppy.drive[0].name = null;
c.floppy.drive[0].data = null;
c.floppy.drive[1].type = SAEV_Config_Floppy_Type_35_DD;
c.floppy.drive[1].name = null;
c.floppy.drive[1].data = null;
c.floppy.drive[2].type = SAEV_Config_Floppy_Type_None;
c.floppy.drive[2].name = null;
c.floppy.drive[2].data = null;
c.floppy.drive[3].type = SAEV_Config_Floppy_Type_None;
c.floppy.drive[3].name = null;
c.floppy.drive[3].data = null;
c.floppy.speed = SAEV_Config_Floppy_Speed_Original;
c.video.enabled = true;
c.video.scale = false;
c.video.ntsc = false;
c.video.skip = true;
c.video.id = 'video';
c.audio.enabled = true;
c.audio.mode = SAEV_Config_Audio_Mode_Play_Best;
c.audio.channels = SAEV_Config_Audio_Channels_Stereo;
c.audio.rate = SAEV_Config_Audio_Rate_44100;
c.ports[0].type = SAEV_Config_Ports_Type_Mouse;
c.ports[0].move = SAEV_Config_Ports_Move_WASD;
c.ports[0].fire[0] = 49;
c.ports[0].fire[1] = 50;
c.ports[1].type = SAEV_Config_Ports_Type_Joy1;
c.ports[1].move = SAEV_Config_Ports_Move_Arrows;
c.ports[1].fire[0] = 16;
c.ports[1].fire[1] = 17;
c.keyboard.enabled = true;
c.keyboard.mapShift = false;
c.rtc.type = 1 ? SAEV_Config_RTC_Type_MSM6242B : SAEV_Config_RTC_Type_RF5C01A;
c.hooks.error = function(err, msg) {}
c.hooks.power_led = function(on) {}
c.hooks.floppy_motor = function(unit, on) {}
c.hooks.floppy_step = function(unit, cyl) {}
c.hooks.fps = function(fps) {}
c.hooks.cpu = function(usage) {}
configSetDefaults(this);
}

View file

@ -9,7 +9,7 @@
**************************************************************************/
const SAEV_Version = 0;
const SAEV_Revision = 7;
const SAEV_Revision = 8;
const SAEV_Revision_Sub = 0;
/*-----------------------------------------------------------------------*/
@ -19,6 +19,15 @@ const SAEV_Null = null;
const SAEV_True = true;
const SAEV_False = false;
/*-----------------------------------------------------------------------*/
/* info */
const SAEI_Audio_Webkit = 1;
const SAEI_Audio_Mozilla = 2;
const SAEI_Video_Canvas2D = 1;
const SAEI_Video_WebGL = 2;
/*-----------------------------------------------------------------------*/
/* cpu */
@ -29,11 +38,18 @@ const SAEV_Config_CPU_Speed_Original = 0;
/* chipset */
const SAEV_Config_Chipset_Type_OCS = 1;
const SAEV_Config_Chipset_Type_ECS = 2;
const SAEV_Config_Chipset_Type_ECS_AGNUS = 2;
const SAEV_Config_Chipset_Type_ECS_DENISE = 3;
const SAEV_Config_Chipset_Mask_OCS = 0;
const SAEV_Config_Chipset_Mask_ECS_AGNUS = 1;
const SAEV_Config_Chipset_Mask_ECS_DENISE = 1 | 2;
const SAEV_Config_Chipset_ColLevel_None = 0;
const SAEV_Config_Chipset_ColLevel_Sprite_Sprite = 1;
const SAEV_Config_Chipset_ColLevel_Sprite_Playfield = 2;
const SAEV_Config_Chipset_ColLevel_Full = 3;
/*-----------------------------------------------------------------------*/
/* ram */
@ -158,10 +174,10 @@ var BUG = null;
var AMIGA = null;
const CMD_STOP = 0;
const CMD_CYCLE = 1;
const CMD_PAUSE = 2;
const CMD_IDLE = 3;
const ST_STOP = 0;
const ST_CYCLE = 1;
const ST_PAUSE = 2;
const ST_IDLE = 3;
/*-----------------------------------------------------------------------*/
/* events */
@ -171,51 +187,18 @@ const EV_AUDIO = 1;
const EV_MISC = 2;
const EV_HSYNC = 3;
const EV_MAX = 4;
//const EV_COPPER = ;
//const EV_BLITTER = ;
//const EV_RENDER = ;
const EV2_BLITTER = 0;
const EV2_DISK = 1;
const EV2_MISC = 2;
const EV2_MAX = 12;
const EV2_DMAL = 2;
const EV2_MISC = 3;
const EV2_MAX = 3 + 10;
const CYCLE_UNIT = 512;
const CYCLE_UNIT_INV = 1.0 / CYCLE_UNIT; /* mul is always faster than div */
const CYCLE_MAX = 0xffffffff * CYCLE_UNIT;
/*-----------------------------------------------------------------------*/
/* cia */
const CIA_A = 1;
const CIA_B = 2;
const ECLOCK_DATA_CYCLE = 4;
const ECLOCK_WAIT_CYCLE = 6;
const DIV10 = ((ECLOCK_DATA_CYCLE + ECLOCK_WAIT_CYCLE) * CYCLE_UNIT) >> 1;
const CIA_RETHINK_DELAY = (CYCLE_UNIT << 1) + (CYCLE_UNIT >> 1);
/*-----------------------------------------------------------------------*/
/* config */
//OCS
const AGNUS_8361 = 1; /* Amiga 1000 NTSC */
const AGNUS_8367 = 2; /* Amiga 1000 PAL */
const AGNUS_8370 = 3; /* OCS NTSC */
const AGNUS_8371 = 4; /* OCS PAL */
//ECS
const AGNUS_8372 = 5; /* ECS */
//AGA
const AGNUS_8374 = 6; /* AGA */
const DENISE_8362 = 1; /* OCS */
const DENISE_8373 = 2; /* ECS */
const PAULA_8364 = 1;
/*-----------------------------------------------------------------------*/
/* cpu */
@ -227,9 +210,7 @@ const SPCFLAG_TRACE = 64;
const SPCFLAG_DOTRACE = 128;
const SPCFLAG_DOINT = 256;
const SPCFLAG_BLTNASTY = 512;
//const SPCFLAG_EXEC = 1024;
//const SPCFLAG_ACTION_REPLAY = 2048;
//const SPCFLAG_TRAP = 4096;
const SPCFLAG_TRAP = 1024;
/*-----------------------------------------------------------------------*/
/* amiga */
@ -272,25 +253,9 @@ const DMAF_SETCLR = 1 << 15;
const INT_PROCESSING_DELAY = 3 * CYCLE_UNIT;
/*-----------------------------------------------------------------------*/
/* copper */
/*const COP_STOP = 0;
const COP_READ = 1;
const COP_MOVE = 2;
const COP_WAIT = 3;
const COP_SKIP = 4;*/
/*-----------------------------------------------------------------------*/
/* blitter */
/*const BLT_STOP = 0;
const BLT_INIT = 1;
const BLT_READ = 2;
const BLT_WORK = 3;
const BLT_WRITE = 4;
const BLT_NEXT = 5;*/
const BLT_done = 0;
const BLT_init = 1;
const BLT_read = 2;
@ -302,16 +267,124 @@ const BLT_next = 5;
/* video */
const VIDEO_WIDTH = 720; /* == 360*2 */
const VIDEO_HEIGHT = 576; /* == 288*2 */
/*-----------------------------------------------------------------------*/
/* playfield */
const MAX_FRAMESKIP_COUNT = 4;
const VIDEO_HEIGHT = 568; /* == 284*2 */
const VIDEO_DEPTH = 32;
/*-----------------------------------------------------------------------*/
/* audio */
const PERIOD_MIN = 4;
const PERIOD_MIN_NONCE = 60;
const PERIOD_MAX = 0xffffffff;
const PERIOD_MAX = 0xffffffff * CYCLE_UNIT;
/*-----------------------------------------------------------------------*/
/* playfield, sprites */
const CUSTOM_SIMPLE = 0;
const SMART_UPDATE = 0;
const MAXHPOS = 227;
const MAXHPOS_PAL = 227;
const MAXHPOS_NTSC = 227;
const MAXVPOS = 312;
const MAXVPOS_PAL = 312;
const MAXVPOS_NTSC = 262;
const VBLANK_ENDLINE_PAL = 26;
const VBLANK_ENDLINE_NTSC = 21;
const VBLANK_SPRITE_PAL = 25;
const VBLANK_SPRITE_NTSC = 20;
const VBLANK_HZ_PAL = 50;
const VBLANK_HZ_NTSC = 60;
const EQU_ENDLINE_PAL = 8;
const EQU_ENDLINE_NTSC = 10;
const CSMASK_ECS_AGNUS = 1;
const CSMASK_ECS_DENISE = 2;
const CSMASK_AGA = 4;
const CSMASK_MASK = (CSMASK_ECS_AGNUS | CSMASK_ECS_DENISE | CSMASK_AGA);
const CHIPSET_CLOCK_PAL = 3546895;
const CHIPSET_CLOCK_NTSC = 3579545;
const RES_LORES = 0;
const RES_HIRES = 1;
const RES_SUPERHIRES = 2;
const RES_MAX = 2;
const VRES_NONDOUBLE = 0;
const VRES_DOUBLE = 1;
const VRES_QUAD = 2;
const VRES_MAX = 1;
const DIW_WAITING_START = 0;
const DIW_WAITING_STOP = 1;
const LINE_UNDECIDED = 1;
const LINE_DECIDED = 2;
const LINE_DECIDED_DOUBLE = 3;
const LINE_AS_PREVIOUS = 4;
const LINE_BLACK = 5;
const LINE_REMEMBERED_AS_BLACK = 6;
const LINE_DONE = 7;
const LINE_DONE_AS_PREVIOUS = 8;
const LINE_REMEMBERED_AS_PREVIOUS = 9;
const LOF_TOGGLES_NEEDED = 4;
const NLACE_CNT_NEEDED = 50;
const HARD_DDF_STOP = 0xd4;
const HARD_DDF_START = 0x18;
const MAX_PLANES = 6; /* 8 = AGA */
const AMIGA_WIDTH_MAX = 752 / 2;
const AMIGA_HEIGHT_MAX = 574 / 2;
const DIW_DDF_OFFSET = 1;
const HBLANK_OFFSET = 9;
const DISPLAY_LEFT_SHIFT = 0x38;
const NLN_NORMAL = 0;
const NLN_DOUBLED = 1;
const NLN_UPPER = 2;
const NLN_LOWER = 3;
const NLN_NBLACK = 4;
const PLF_IDLE = 0;
const PLF_START = 1;
const PLF_ACTIVE = 2;
const PLF_PASSED_STOP = 3;
const PLF_PASSED_STOP2 = 4;
const PLF_END = 5;
const FETCH_NOT_STARTED = 0;
const FETCH_STARTED = 1;
const FETCH_WAS_PLANE0 = 2;
const COLOR_TABLE_SIZE = (MAXVPOS + 2) * 2;
const COLOR_CHANGE_BRDBLANK = 0x80000000;
const BPLCON_DENISE_DELAY = 1;
const SPRITE_DEBUG = 0;
const SPRITE_DEBUG_MINY = 0x0;
const SPRITE_DEBUG_MAXY = 0x100;
const SPR0_HPOS = 0x15;
const MAX_SPRITES = 8;
//const AUTOSCALE_SPRITES = 1;
//const SPRBORDER = 0;
const MAX_PIXELS_PER_LINE = 1760;
const MAX_SPR_PIXELS = (((MAXVPOS + 1) * 2 + 1) * MAX_PIXELS_PER_LINE);
const MAX_REG_CHANGE = ((MAXVPOS + 1) * 2 * MAXHPOS);
const MAX_STOP = 30000;
const NO_BLOCK = -3;
const FRAMES_UNTIL_RES_SWITCH = 1;
const MAX_WORDS_PER_LINE = 100;
const DO_SPRITES = 1;
const FAST_COLORS = 0;

View file

@ -6,6 +6,9 @@
* ©2012 Rupert Hausberger
* Commercial use is prohibited.
*
***************************************************************************
* Notes: Ported from WinUAE 2.5.0
*
**************************************************************************/
//copper_states
@ -27,11 +30,31 @@ const COP_strobe_extra = 14;
const COP_start_delay = 15;
function Copper() {
const customdelay = [
1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,1,1,1,1,0,0,0,0,0,0,0,0, /* 32 0x00 - 0x3e */
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x40 - 0x5e */
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x60 - 0x7e */
0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0, /* 0x80 - 0x9e */
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 32 0xa0 - 0xde */
/* BPLxPTH/BPLxPTL */
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 16 */
/* BPLCON0-3,BPLMOD1-2 */
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 16 */
/* SPRxPTH/SPRxPTL */
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 16 */
/* SPRxPOS/SPRxCTL/SPRxDATA/SPRxDATB */
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
/* COLORxx */
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
/* RESERVED */
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
];
this.cop1lc = 0;
this.cop2lc = 0,
this.copcon = 0;
this.enabled_thisline = false;
this.access = false;
this.last_copper_hpos = 0;
var cop_state = {
/* The current instruction words. */
@ -48,8 +71,6 @@ function Copper() {
last_write:0, last_write_hpos:0,
moveaddr:0, movedata:0, movedelay:0
};
var last_copper_hpos = 0;
this.reset = function () {
this.copcon = 0;
@ -59,7 +80,7 @@ function Copper() {
this.reset2 = function () {
cop_state.hpos = 0;
cop_state.last_write = 0;
this.compute_spcflag_copper(AMIGA.events.maxhpos);
this.compute_spcflag_copper(AMIGA.playfield.maxhpos);
}
this.COPCON = function (v) {
@ -96,18 +117,18 @@ function Copper() {
//BUG.info('COPJMP(%d) %d', num, cop_state.state);
cop_state.vpos = AMIGA.events.vpos;
cop_state.hpos = AMIGA.events.hpos() & ~1;
this.enabled_thisline = false;
cop_state.vpos = AMIGA.playfield.vpos;
cop_state.hpos = AMIGA.playfield.hpos() & ~1;
cop_state.strobe = num;
this.enabled_thisline = false;
if (0) {
this.immediate_copper(num);
return;
}
if (AMIGA.dmaen(DMAF_COPEN))
this.compute_spcflag_copper(AMIGA.events.hpos());
this.compute_spcflag_copper(AMIGA.playfield.hpos());
else if (oldstrobe > 0 && oldstrobe != num && cop_state.state_prev == COP_wait) {
/* dma disabled, copper idle and accessed both COPxJMPs -> copper stops! */
cop_state.state = COP_stop;
@ -126,7 +147,7 @@ function Copper() {
this.test_copper_dangerous = function (address) {
var addr = address & 0x1fe;
if (addr < ((this.copcon & 2) ? ((AMIGA.config.chipset.type == SAEV_Config_Chipset_Type_ECS) ? 0 : 0x40) : 0x80)) {
if (addr < ((this.copcon & 2) ? ((AMIGA.config.chipset.mask & CSMASK_ECS_AGNUS) ? 0 : 0x40) : 0x80)) {
cop_state.state = COP_stop;
this.enabled_thisline = false;
clr_special(SPCFLAG_COPPER);
@ -140,11 +161,11 @@ function Copper() {
var oldpos = 0;
cop_state.state = COP_stop;
cop_state.vpos = AMIGA.events.vpos;
cop_state.hpos = AMIGA.events.hpos() & ~1;
cop_state.vpos = AMIGA.playfield.vpos;
cop_state.hpos = AMIGA.playfield.hpos() & ~1;
cop_state.ip = num == 1 ? this.cop1lc : this.cop2lc;
while (pos < (AMIGA.events.maxvpos << 5)) {
while (pos < (AMIGA.playfield.maxvpos << 5)) {
if (oldpos > pos)
pos = oldpos;
if (!AMIGA.dmaen(DMAF_COPEN))
@ -153,8 +174,11 @@ function Copper() {
break;
pos++;
oldpos = pos;
cop_state.i1 = AMIGA.mem.load16_chip(cop_state.ip);
cop_state.i2 = AMIGA.mem.load16_chip(cop_state.ip + 2);
//cop_state.i1 = AMIGA.mem.load16_chip(cop_state.ip);
//cop_state.i2 = AMIGA.mem.load16_chip(cop_state.ip + 2);
cop_state.i1 = AMIGA.mem.chip.data[cop_state.ip >>> 1];
cop_state.i2 = AMIGA.mem.chip.data[(cop_state.ip + 2) >>> 1];
AMIGA.custom.last_value = cop_state.i2;
cop_state.ip += 4;
if (!(cop_state.i1 & 1)) { // move
cop_state.i1 &= 0x1fe;
@ -181,25 +205,18 @@ function Copper() {
}
this.copper_cant_read = function (hpos, alloc) {
//BUG.info('copper_cant_read2() hpos %d / %d', hpos, AMIGA.events.maxhpos);
if (hpos + 1 >= AMIGA.events.maxhpos) // first refresh slot
//BUG.info('copper_cant_read2() hpos %d / %d', hpos, AMIGA.playfield.maxhpos);
if (hpos + 1 >= AMIGA.playfield.maxhpos) // first refresh slot
return 1;
if ((hpos == AMIGA.events.maxhpos - 3) && (AMIGA.events.maxhpos & 1) && alloc >= 0) {
//if (alloc) alloc_cycle (hpos, CYCLE_COPPER);
if ((hpos == AMIGA.playfield.maxhpos - 3) && (AMIGA.playfield.maxhpos & 1) && alloc >= 0) {
return -1;
}
return AMIGA.playfield.is_bitplane_dma(hpos);
}
/*this.copper_cant_read = function (hpos, alloc) {
var cant = this.copper_cant_read2(hpos, alloc);
//if (cant && debug_dma) record_dma_event (DMA_EVENT_COPPERWANTED, hpos, vpos);
return cant;
}*/
this.custom_store16_copper = function (hpos, addr, value, noget) {
//if (addr == 0x88 || addr == 0x8a)
//BUG.info('custom_store16_copper() addr %08x, value %04x | vpos %d hpos %d %d cvcmp %d chcmp %d chpos %d cvpos %d', addr, value, AMIGA.events.vpos, AMIGA.events.hpos(), hpos, cop_state.vcmp, cop_state.hcmp, cop_state.hpos, cop_state.vpos);
//BUG.info('custom_store16_copper() addr %08x, value %04x | vpos %d hpos %d %d cvcmp %d chcmp %d chpos %d cvpos %d', addr, value, AMIGA.playfield.vpos, AMIGA.playfield.hpos(), hpos, cop_state.vcmp, cop_state.hcmp, cop_state.hpos, cop_state.vpos);
//value = debug_wputpeekdma (0xdff000 + addr, value);
this.access = true;
var v = AMIGA.custom.store16_real(hpos, addr, value, noget);
@ -209,44 +226,17 @@ function Copper() {
this.dump_copper = function (error, until_hpos) {
BUG.info('\n');
BUG.info('%s: vpos=%d until_hpos=%d vp=%d', error, AMIGA.events.vpos, until_hpos, AMIGA.events.vpos & (((cop_state.saved_i2 >> 8) & 0x7f) | 0x80));
BUG.info('%s: vpos=%d until_hpos=%d vp=%d', error, AMIGA.playfield.vpos, until_hpos, AMIGA.playfield.vpos & (((cop_state.saved_i2 >> 8) & 0x7f) | 0x80));
BUG.info('cvcmp=%d chcmp=%d chpos=%d cvpos=%d ci1=%04X ci2=%04X', cop_state.vcmp, cop_state.hcmp, cop_state.hpos, cop_state.vpos, cop_state.saved_i1, cop_state.saved_i2);
BUG.info('cstate=%d ip=%x SPCFLAGS=%x iscline=%d', cop_state.state, cop_state.ip, AMIGA.spcflags, this.enabled_thisline?1:0);
BUG.info('\n');
}
// 'emulate' chip internal delays, not the right place but fast and 99.9% programs
// use only copper to write BPLCON1 etc.. (exception is HulkaMania/TSP..)
// this table should be filled with zeros and done somewhere else..
var customdelay = [
1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,1,1,1,1,0,0,0,0,0,0,0,0, /* 32 0x00 - 0x3e */
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x40 - 0x5e */
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x60 - 0x7e */
0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0, /* 0x80 - 0x9e */
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 32 0xa0 - 0xde */
/* BPLxPTH/BPLxPTL */
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 16 */
/* BPLCON0-3,BPLMOD1-2 */
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 16 */
/* SPRxPTH/SPRxPTL */
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 16 */
/* SPRxPOS/SPRxCTL/SPRxDATA/SPRxDATB */
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
/* COLORxx */
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
/* RESERVED */
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
];
/*this.copper_write = function (v) {
this.custom_store16_copper(AMIGA.events.hpos(), v >> 16, v & 0xffff, 0);
}*/
this.update_copper = function (until_hpos) {
var vp = AMIGA.events.vpos & (((cop_state.saved_i2 >> 8) & 0x7f) | 0x80);
this.update = function (until_hpos) {
var vp = AMIGA.playfield.vpos & (((cop_state.saved_i2 >> 8) & 0x7f) | 0x80);
var c_hpos = cop_state.hpos;
//BUG.info('update_copper() until_hpos %d, vp %d', until_hpos, vp);
//BUG.info('update() until_hpos %d, vp %d', until_hpos, vp);
if (cop_state.state == COP_wait && vp < cop_state.vcmp) {
this.dump_copper('error2', until_hpos);
@ -256,11 +246,11 @@ function Copper() {
return;
}
if (until_hpos <= last_copper_hpos)
if (until_hpos <= this.last_copper_hpos)
return;
if (until_hpos > (AMIGA.events.maxhpos & ~1))
until_hpos = AMIGA.events.maxhpos & ~1;
if (until_hpos > (AMIGA.playfield.maxhpos & ~1))
until_hpos = AMIGA.playfield.maxhpos & ~1;
for (;;) {
var old_hpos = c_hpos;
@ -270,8 +260,8 @@ function Copper() {
break;
/* So we know about the fetch state. */
//decide_line (c_hpos);
//decide_fetch (c_hpos);
AMIGA.playfield.decide_line(c_hpos);
AMIGA.playfield.decide_fetch(c_hpos);
if (cop_state.movedelay > 0) {
cop_state.movedelay--;
@ -280,7 +270,7 @@ function Copper() {
}
}
if ((c_hpos == AMIGA.events.maxhpos - 3) && (AMIGA.events.maxhpos & 1))
if ((c_hpos == AMIGA.playfield.maxhpos - 3) && (AMIGA.playfield.maxhpos & 1))
c_hpos += 1;
else
c_hpos += 2;
@ -309,8 +299,6 @@ function Copper() {
if (this.copper_cant_read(old_hpos, 1))
continue;
cop_state.state = COP_strobe_delay2;
//alloc_cycle(old_hpos, CYCLE_COPPER);
//if (debug_dma) record_dma (0x8c, AMIGA.mem.load16_chip(cop_state.ip), cop_state.ip, old_hpos, vpos, DMARECORD_COPPER);
cop_state.ip += 2;
break;
}
@ -318,10 +306,6 @@ function Copper() {
// Second cycle after COPJMP. This is the strange one.
// This cycle does not need to be free
// But it still gets allocated by copper if it is free = CPU and blitter can't use it.
/*if (this.copper_cant_read(old_hpos, 1)) {
alloc_cycle (old_hpos, CYCLE_COPPER);
if (debug_dma) record_dma (0x1fe, AMIGA.mem.load16_chip(cop_state.ip), cop_state.ip, old_hpos, vpos, DMARECORD_COPPER);
}*/
cop_state.state = COP_read1;
// Next cycle finally reads from new pointer
if (cop_state.strobe == 1)
@ -343,8 +327,6 @@ function Copper() {
// but is not allocated, blitter or cpu can still use it.
if (this.copper_cant_read(old_hpos, 1))
continue;
//cycle_line[old_hpos] |= CYCLE_COPPER_SPECIAL;
//if (debug_dma) record_dma (0x1fe, AMIGA.mem.load16_chip(cop_state.ip), cop_state.ip, old_hpos, vpos, DMARECORD_COPPER);
cop_state.state = COP_read1;
// Next cycle finally reads from new pointer
if (cop_state.strobe == 1)
@ -358,8 +340,6 @@ function Copper() {
if (this.copper_cant_read(old_hpos, 1))
continue;
cop_state.state = COP_read1;
//alloc_cycle(old_hpos, CYCLE_COPPER);
//if (debug_dma) record_dma (0x1fe, 0, 0xffffffff, old_hpos, vpos, DMARECORD_COPPER);
cop_state.ip = this.cop1lc;
break;
}
@ -374,9 +354,8 @@ function Copper() {
clr_special(SPCFLAG_COPPER);
return;
}
cop_state.i1 = AMIGA.mem.load16_chip(cop_state.ip);
//alloc_cycle(old_hpos, CYCLE_COPPER);
//if (debug_dma) record_dma (0x8c, cop_state.i1, cop_state.ip, old_hpos, vpos, DMARECORD_COPPER);
//cop_state.i1 = AMIGA.mem.load16_chip(cop_state.ip);
cop_state.i1 = AMIGA.custom.last_value = AMIGA.mem.chip.data[cop_state.ip >>> 1];
cop_state.ip += 2;
cop_state.state = COP_read2;
break;
@ -384,8 +363,8 @@ function Copper() {
case COP_read2: {
if (this.copper_cant_read(old_hpos, 1))
continue;
cop_state.i2 = AMIGA.mem.load16_chip(cop_state.ip);
//alloc_cycle(old_hpos, CYCLE_COPPER);
//cop_state.i2 = AMIGA.mem.load16_chip(cop_state.ip);
cop_state.i2 = AMIGA.custom.last_value = AMIGA.mem.chip.data[cop_state.ip >>> 1];
cop_state.ip += 2;
cop_state.saved_i1 = cop_state.i1;
cop_state.saved_i2 = cop_state.i2;
@ -397,18 +376,16 @@ function Copper() {
cop_state.state = COP_skip_in2;
else
cop_state.state = COP_wait_in2;
//if (debug_dma) record_dma (0x8c, cop_state.i2, cop_state.ip - 2, old_hpos, vpos, DMARECORD_COPPER);
} else { // MOVE
//uaecptr debugip = cop_state.ip;
var reg = cop_state.i1 & 0x1fe;
var data = cop_state.i2;
cop_state.state = COP_read1;
//if (debug_dma) record_dma (reg, data, cop_state.ip - 2, old_hpos, vpos, DMARECORD_COPPER);
this.test_copper_dangerous(reg);
if (!this.enabled_thisline) {
//goto out; // was 'dangerous' register -> copper stopped
cop_state.hpos = c_hpos;
last_copper_hpos = until_hpos;
this.last_copper_hpos = until_hpos;
return;
}
if (cop_state.ignore_next)
@ -423,37 +400,41 @@ function Copper() {
cop_state.strobe = 2;
cop_state.state = COP_strobe_delay1;
} else {
/*#if 0
event2_newevent2 (1, (reg << 16) | data, copper_write);
#else*/
// FIX: all copper writes happen 1 cycle later than CPU writes
if (customdelay[reg >> 1]) {
cop_state.moveaddr = reg;
cop_state.movedata = data;
cop_state.movedelay = customdelay[cop_state.moveaddr >> 1];
} else {
var hpos2 = old_hpos;
this.custom_store16_copper(hpos2, reg, data, 0);
hpos2++;
//if (reg >= 0x140 && reg < 0x180 && hpos2 >= SPR0_HPOS && hpos2 < SPR0_HPOS + 4 * MAX_SPRITES) do_sprites(hpos2);
/*if (0) {
AMIGA.events.newevent2(1, (reg << 16) | data, function(v) { //copper_write);
AMIGA.copper.custom_store16_copper(AMIGA.playfield.hpos(), v >>> 16, v & 0xffff, 0);
});
//this.custom_store16_copper(old_hpos, reg, data, 0);
} else*/
{
// FIX: all copper writes happen 1 cycle later than CPU writes
if (customdelay[reg >> 1]) {
cop_state.moveaddr = reg;
cop_state.movedata = data;
cop_state.movedelay = customdelay[cop_state.moveaddr >> 1];
} else {
var hpos2 = old_hpos;
this.custom_store16_copper(hpos2, reg, data, 0);
hpos2++;
if (reg >= 0x140 && reg < 0x180 && hpos2 >= SPR0_HPOS && hpos2 < SPR0_HPOS + 4 * MAX_SPRITES)
AMIGA.playfield.do_sprites(hpos2);
}
}
//#endif
}
//if (debug_copper && !cop_state.ignore_next) record_copper (debugip - 4, old_hpos, vpos);
cop_state.ignore_next = 0;
}
break;
}
case COP_wait1: {
/*#if 0
if (c_hpos >= (AMIGA.events.maxhpos & ~1) || (c_hpos & 1)) break;
#endif*/
/*#if 0
if (c_hpos >= (AMIGA.playfield.maxhpos & ~1) || (c_hpos & 1)) break;
#endif*/
cop_state.state = COP_wait;
cop_state.vcmp = (cop_state.saved_i1 & (cop_state.saved_i2 | 0x8000)) >> 8;
cop_state.hcmp = (cop_state.saved_i1 & cop_state.saved_i2 & 0xfe);
vp = AMIGA.events.vpos & (((cop_state.saved_i2 >> 8) & 0x7f) | 0x80);
vp = AMIGA.playfield.vpos & (((cop_state.saved_i2 >> 8) & 0x7f) | 0x80);
if (cop_state.saved_i1 == 0xffff && cop_state.saved_i2 == 0xfffe) {
cop_state.state = COP_waitforever;
@ -461,7 +442,7 @@ function Copper() {
clr_special(SPCFLAG_COPPER);
//goto out;
cop_state.hpos = c_hpos;
last_copper_hpos = until_hpos;
this.last_copper_hpos = until_hpos;
return;
}
if (vp < cop_state.vcmp) {
@ -469,7 +450,7 @@ function Copper() {
clr_special(SPCFLAG_COPPER);
//goto out;
cop_state.hpos = c_hpos;
last_copper_hpos = until_hpos;
this.last_copper_hpos = until_hpos;
return;
}
}
@ -488,7 +469,6 @@ function Copper() {
/* Now we know that the comparisons were successful. We might still have to wait for the blitter though. */
if ((cop_state.saved_i2 & 0x8000) == 0) {
//decide_blitter (old_hpos);
if (AMIGA.blitter.getState() != BLT_done) {
//We need to wait for the blitter.
cop_state.state = COP_bltwait;
@ -496,20 +476,17 @@ function Copper() {
clr_special(SPCFLAG_COPPER);
//goto out;
cop_state.hpos = c_hpos;
last_copper_hpos = until_hpos;
this.last_copper_hpos = until_hpos;
return;
} /*else {
if (debug_dma) record_dma_event (DMA_EVENT_COPPERWAKE, old_hpos, vp);
}*/
}
}
//if (debug_copper) record_copper (cop_state.ip - 4, old_hpos, vpos);
cop_state.state = COP_read1;
break;
}
case COP_skip1: {
var vcmp, hcmp, vp1, hp1;
if (c_hpos >= (AMIGA.events.maxhpos & ~1) || (c_hpos & 1))
if (c_hpos >= (AMIGA.playfield.maxhpos & ~1) || (c_hpos & 1))
break;
if (this.copper_cant_read(old_hpos, 0))
@ -517,14 +494,13 @@ function Copper() {
vcmp = (cop_state.saved_i1 & (cop_state.saved_i2 | 0x8000)) >> 8;
hcmp = (cop_state.saved_i1 & cop_state.saved_i2 & 0xfe);
vp1 = AMIGA.events.vpos & (((cop_state.saved_i2 >> 8) & 0x7f) | 0x80);
vp1 = AMIGA.playfield.vpos & (((cop_state.saved_i2 >> 8) & 0x7f) | 0x80);
hp1 = c_hpos & (cop_state.saved_i2 & 0xfe);
if ((vp1 > vcmp || (vp1 == vcmp && hp1 >= hcmp)) && ((cop_state.saved_i2 & 0x8000) != 0 || AMIGA.blitter.getState() == BLT_done))
cop_state.ignore_next = 1;
cop_state.state = COP_read1;
//if (debug_copper) record_copper (cop_state.ip - 4, old_hpos, vpos);
break;
}
}
@ -532,7 +508,7 @@ function Copper() {
//out:
cop_state.hpos = c_hpos;
last_copper_hpos = until_hpos;
this.last_copper_hpos = until_hpos;
}
this.compute_spcflag_copper = function (hpos) {
@ -545,18 +521,19 @@ function Copper() {
return;
if (cop_state.state == COP_wait) {
var vp = AMIGA.events.vpos & (((cop_state.saved_i2 >> 8) & 0x7f) | 0x80);
var vp = AMIGA.playfield.vpos & (((cop_state.saved_i2 >> 8) & 0x7f) | 0x80);
if (vp < cop_state.vcmp)
return;
}
// do not use past cycles if starting for the first time in this line
// (write to DMACON for example) hpos+1 for long lines
if (!wasenabled && cop_state.hpos < hpos && hpos < AMIGA.events.maxhpos) {
if (!wasenabled && cop_state.hpos < hpos && hpos < AMIGA.playfield.maxhpos) {
hpos = (hpos + 2) & ~1;
if (hpos > 226)
hpos = 226;
if (hpos > AMIGA.playfield.maxhpos_short)
hpos = AMIGA.playfield.maxhpos_short;
cop_state.hpos = hpos;
//BUG.info('compute_spcflag_copper() hpos %d %d', hpos, AMIGA.playfield.maxhpos_short);
}
// if COPJMPx was written while DMA was disabled, advance to next state,
@ -575,40 +552,39 @@ function Copper() {
//BUG.info('blitter_done_notify() hpos %d', hpos);
var vp = AMIGA.events.vpos;
var vp = AMIGA.playfield.vpos;
hpos += 3;
hpos &= ~1;
if (hpos >= AMIGA.events.maxhpos) {
hpos -= AMIGA.events.maxhpos;
if (hpos >= AMIGA.playfield.maxhpos) {
hpos -= AMIGA.playfield.maxhpos;
vp++;
}
cop_state.hpos = hpos;
cop_state.vpos = vp;
cop_state.state = COP_read1;
//if (debug_dma) record_dma_event (DMA_EVENT_COPPERWAKE, hpos, vp);
if (AMIGA.dmaen(DMAF_COPEN) && vp == AMIGA.events.vpos) {
if (AMIGA.dmaen(DMAF_COPEN) && vp == AMIGA.playfield.vpos) {
this.enabled_thisline = true;
set_special(SPCFLAG_COPPER);
}
}
this.cycle = function () {
this.update_copper(AMIGA.events.hpos());
this.update(AMIGA.playfield.hpos());
}
this.sync_copper_with_cpu = function (hpos, do_schedule) {
/* Need to let the copper advance to the current position. */
if (this.enabled_thisline)
this.update_copper(hpos);
this.update(hpos);
}
this.check = function (n) {
if (cop_state.state == COP_wait) {
var vp = AMIGA.events.vpos & (((cop_state.saved_i2 >> 8) & 0x7f) | 0x80);
var vp = AMIGA.playfield.vpos & (((cop_state.saved_i2 >> 8) & 0x7f) | 0x80);
if (vp < cop_state.vcmp) {
if (this.enabled_thisline)
BUG.info('COPPER BUG %d: vp=%d vpos=%d vcmp=%d thisline=%d', n, vp, AMIGA.events.vpos, cop_state.vcmp, this.enabled_thisline?1:0);
BUG.info('COPPER BUG %d: vp=%d vpos=%d vcmp=%d thisline=%d', n, vp, AMIGA.playfield.vpos, cop_state.vcmp, this.enabled_thisline?1:0);
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -24,12 +24,12 @@ function Custom() {
switch (addr & 0x1fe) {
case 0x002: v = AMIGA.DMACONR(hpos); break;
case 0x004: v = AMIGA.events.VPOSR(); break;
case 0x006: v = AMIGA.events.VHPOSR(); break;
case 0x004: v = AMIGA.playfield.VPOSR(); break;
case 0x006: v = AMIGA.playfield.VHPOSR(); break;
case 0x00A: v = AMIGA.input.JOY0DAT(); break;
case 0x00C: v = AMIGA.input.JOY1DAT(); break;
case 0x00E: v = AMIGA.playfield.sprites.CLXDAT(); break;
case 0x00E: v = AMIGA.playfield.CLXDAT(); break;
case 0x010: v = AMIGA.ADKCONR(); break;
case 0x012: v = AMIGA.input.POT0DAT(); break;
@ -48,18 +48,18 @@ function Custom() {
break;
}
/*#ifdef AGA
/*#ifdef AGA
case 0x180: case 0x182: case 0x184: case 0x186: case 0x188: case 0x18A:
case 0x18C: case 0x18E: case 0x190: case 0x192: case 0x194: case 0x196:
case 0x198: case 0x19A: case 0x19C: case 0x19E: case 0x1A0: case 0x1A2:
case 0x1A4: case 0x1A6: case 0x1A8: case 0x1AA: case 0x1AC: case 0x1AE:
case 0x1B0: case 0x1B2: case 0x1B4: case 0x1B6: case 0x1B8: case 0x1BA:
case 0x1BC: case 0x1BE:
if (AMIGA.config.chipset.type != SAEV_Config_Chipset_Type_AGA)
if (!(AMIGA.config.chipset.mask & CSMASK_AGA))
writeonly = true;
v = COLOR_READ ((addr & 0x3E) / 2);
v = COLOR_READ ((addr & 0x3E) >> 1);
break;
#endif*/
#endif*/
default:
writeonly = true;
@ -68,22 +68,24 @@ function Custom() {
if (writeonly) {
v = this.last_value;
if (!noput) {
var old = this.last_value;
var l = 0xffff;
var l = 0xffff; //AMIGA.config.cpu.compatible && AMIGA.config.cpu.model == 68000 ? regs.irc : 0xffff;
AMIGA.playfield.decide_line(hpos);
AMIGA.playfield.decide_fetch(hpos);
var r = this.store16_real(hpos, addr, l, 1);
if (r) { // register don't exist
if (AMIGA.config.chipset.type == SAEV_Config_Chipset_Type_ECS) {
if (r) { /* register don't exist */
if (AMIGA.config.chipset.mask & CSMASK_ECS_AGNUS) {
v = l;
} else {
if ((addr & 0x1fe) == 0) {
/*if (is_cycle_ce())
v = this.last_value;
v = this.last_value;
else*/
v = l;
v = l;
}
}
} else {
if (AMIGA.config.chipset.type == SAEV_Config_Chipset_Type_ECS)
if (AMIGA.config.chipset.mask & CSMASK_ECS_AGNUS)
v = 0xffff;
else
v = l;
@ -98,7 +100,7 @@ function Custom() {
}
this.load16_2 = function (addr) {
var hpos = AMIGA.events.hpos();
var hpos = AMIGA.playfield.hpos();
AMIGA.copper.sync_copper_with_cpu (hpos, 1);
return this.load16_real(hpos, addr, 0);
@ -129,15 +131,15 @@ function Custom() {
value &= 0xffff;
switch (addr) {
//case 0x00E: CLXDAT (); break;
case 0x00E: AMIGA.playfield.CLXDAT(); break;
case 0x020: AMIGA.disk.DSKPTH(value); break;
case 0x022: AMIGA.disk.DSKPTL(value); break;
case 0x024: AMIGA.disk.DSKLEN(value, hpos); break;
case 0x026: /* AMIGA.disk.DSKDAT(value). Writing to DMA write registers won't do anything */; break;
case 0x02A: AMIGA.events.VPOSW(value); break;
case 0x02C: AMIGA.events.VHPOSW(value); break;
case 0x02A: AMIGA.playfield.VPOSW(value); break;
case 0x02C: AMIGA.playfield.VHPOSW(value); break;
case 0x02E: AMIGA.copper.COPCON(value); break;
case 0x030: AMIGA.serial.SERDAT(value); break;
case 0x032: AMIGA.serial.SERPER(value); break;
@ -179,13 +181,13 @@ function Custom() {
case 0x088: AMIGA.copper.COPJMP(1, 0); break;
case 0x08A: AMIGA.copper.COPJMP(2, 0); break;
case 0x08E: AMIGA.playfield.DIWSTRT(value); break;
case 0x090: AMIGA.playfield.DIWSTOP(value); break;
case 0x092: AMIGA.playfield.DDFSTRT(value); break;
case 0x094: AMIGA.playfield.DDFSTOP(value); break;
case 0x08E: AMIGA.playfield.DIWSTRT(hpos, value); break;
case 0x090: AMIGA.playfield.DIWSTOP(hpos, value); break;
case 0x092: AMIGA.playfield.DDFSTRT(hpos, value); break;
case 0x094: AMIGA.playfield.DDFSTOP(hpos, value); break;
case 0x096: AMIGA.DMACON(value, hpos); break;
case 0x098: AMIGA.playfield.sprites.CLXCON(value); break;
case 0x098: AMIGA.playfield.CLXCON(value); break;
case 0x09A: AMIGA.INTENA(value); break;
case 0x09C: AMIGA.INTREQ(value); break;
case 0x09E: AMIGA.ADKCON(value, hpos); break;
@ -218,40 +220,40 @@ function Custom() {
case 0x0D8: AMIGA.audio.AUDxVOL(3, value); break;
case 0x0DA: AMIGA.audio.AUDxDAT(3, value); break;
case 0x0E0: AMIGA.playfield.BPLxPTx(value, 0, 1); break;
case 0x0E2: AMIGA.playfield.BPLxPTx(value, 0, 0); break;
case 0x0E4: AMIGA.playfield.BPLxPTx(value, 1, 1); break;
case 0x0E6: AMIGA.playfield.BPLxPTx(value, 1, 0); break;
case 0x0E8: AMIGA.playfield.BPLxPTx(value, 2, 1); break;
case 0x0EA: AMIGA.playfield.BPLxPTx(value, 2, 0); break;
case 0x0EC: AMIGA.playfield.BPLxPTx(value, 3, 1); break;
case 0x0EE: AMIGA.playfield.BPLxPTx(value, 3, 0); break;
case 0x0F0: AMIGA.playfield.BPLxPTx(value, 4, 1); break;
case 0x0F2: AMIGA.playfield.BPLxPTx(value, 4, 0); break;
case 0x0F4: AMIGA.playfield.BPLxPTx(value, 5, 1); break;
case 0x0F6: AMIGA.playfield.BPLxPTx(value, 5, 0); break;
/*case 0x0F8: AMIGA.playfield.BPLxPTx(value, 6, 1); break;
case 0x0FA: AMIGA.playfield.BPLxPTx(value, 6, 0); break;
case 0x0FC: AMIGA.playfield.BPLxPTx(value, 7, 1); break;
case 0x0FE: AMIGA.playfield.BPLxPTx(value, 7, 0); break;*/
case 0x0E0: AMIGA.playfield.BPLxPTH(hpos, value, 0); break;
case 0x0E2: AMIGA.playfield.BPLxPTL(hpos, value, 0); break;
case 0x0E4: AMIGA.playfield.BPLxPTH(hpos, value, 1); break;
case 0x0E6: AMIGA.playfield.BPLxPTL(hpos, value, 1); break;
case 0x0E8: AMIGA.playfield.BPLxPTH(hpos, value, 2); break;
case 0x0EA: AMIGA.playfield.BPLxPTL(hpos, value, 2); break;
case 0x0EC: AMIGA.playfield.BPLxPTH(hpos, value, 3); break;
case 0x0EE: AMIGA.playfield.BPLxPTL(hpos, value, 3); break;
case 0x0F0: AMIGA.playfield.BPLxPTH(hpos, value, 4); break;
case 0x0F2: AMIGA.playfield.BPLxPTL(hpos, value, 4); break;
case 0x0F4: AMIGA.playfield.BPLxPTH(hpos, value, 5); break;
case 0x0F6: AMIGA.playfield.BPLxPTL(hpos, value, 5); break;
case 0x0F8: AMIGA.playfield.BPLxPTH(hpos, value, 6); break;
case 0x0FA: AMIGA.playfield.BPLxPTL(hpos, value, 6); break;
case 0x0FC: AMIGA.playfield.BPLxPTH(hpos, value, 7); break;
case 0x0FE: AMIGA.playfield.BPLxPTL(hpos, value, 7); break;
case 0x100: AMIGA.playfield.BPLCON0(value); break;
case 0x102: AMIGA.playfield.BPLCON1(value); break;
case 0x104: AMIGA.playfield.BPLCON2(value); break;
//case 0x106: AMIGA.playfield.BPLCON3(value); break; //ECS_DENISE
case 0x100: AMIGA.playfield.BPLCON0(hpos, value); break;
case 0x102: AMIGA.playfield.BPLCON1(hpos, value); break;
case 0x104: AMIGA.playfield.BPLCON2(hpos, value); break;
case 0x106: AMIGA.playfield.BPLCON3(hpos, value); break;
case 0x108: AMIGA.playfield.BPL1MOD(value); break;
case 0x10A: AMIGA.playfield.BPL2MOD(value); break;
//case 0x10E: AMIGA.playfield.sprites.CLXCON2 (value); break; //AGA
case 0x108: AMIGA.playfield.BPL1MOD(hpos, value); break;
case 0x10A: AMIGA.playfield.BPL2MOD(hpos, value); break;
//case 0x10E: AMIGA.playfield.CLXCON2(value); break; //AGA
case 0x110: AMIGA.playfield.BPLxDAT(value, 0); break;
case 0x112: AMIGA.playfield.BPLxDAT(value, 1); break;
case 0x114: AMIGA.playfield.BPLxDAT(value, 2); break;
case 0x116: AMIGA.playfield.BPLxDAT(value, 3); break;
case 0x118: AMIGA.playfield.BPLxDAT(value, 4); break;
case 0x11A: AMIGA.playfield.BPLxDAT(value, 5); break;
//case 0x11C: AMIGA.playfield.BPLxDAT(value, 6); break;
//case 0x11E: AMIGA.playfield.BPLxDAT(value, 7); break;
case 0x110: AMIGA.playfield.BPLxDAT(hpos, value, 0); break;
case 0x112: AMIGA.playfield.BPLxDAT(hpos, value, 1); break;
case 0x114: AMIGA.playfield.BPLxDAT(hpos, value, 2); break;
case 0x116: AMIGA.playfield.BPLxDAT(hpos, value, 3); break;
case 0x118: AMIGA.playfield.BPLxDAT(hpos, value, 4); break;
case 0x11A: AMIGA.playfield.BPLxDAT(hpos, value, 5); break;
case 0x11C: AMIGA.playfield.BPLxDAT(hpos, value, 6); break;
case 0x11E: AMIGA.playfield.BPLxDAT(hpos, value, 7); break;
case 0x180: case 0x182: case 0x184: case 0x186: case 0x188: case 0x18A:
case 0x18C: case 0x18E: case 0x190: case 0x192: case 0x194: case 0x196:
@ -259,58 +261,55 @@ function Custom() {
case 0x1A4: case 0x1A6: case 0x1A8: case 0x1AA: case 0x1AC: case 0x1AE:
case 0x1B0: case 0x1B2: case 0x1B4: case 0x1B6: case 0x1B8: case 0x1BA:
case 0x1BC: case 0x1BE:
AMIGA.playfield.COLORxx(value & 0xfff, (addr & 0x3E) >> 1);
AMIGA.playfield.COLOR_WRITE(hpos, value & 0xFFF, (addr & 0x3E) >> 1);
break;
case 0x120: case 0x124: case 0x128: case 0x12C:
case 0x130: case 0x134: case 0x138: case 0x13C:
AMIGA.playfield.sprites.SPRxPTH(value, (addr - 0x120) >> 2);
AMIGA.playfield.SPRxPTH(hpos, value, (addr - 0x120) >> 2);
break;
case 0x122: case 0x126: case 0x12A: case 0x12E:
case 0x132: case 0x136: case 0x13A: case 0x13E:
AMIGA.playfield.sprites.SPRxPTL(value, (addr - 0x122) >> 2);
AMIGA.playfield.SPRxPTL(hpos, value, (addr - 0x122) >> 2);
break;
case 0x140: case 0x148: case 0x150: case 0x158:
case 0x160: case 0x168: case 0x170: case 0x178:
AMIGA.playfield.sprites.SPRxPOS(value, (addr - 0x140) >> 3);
AMIGA.playfield.SPRxPOS(hpos, value, (addr - 0x140) >> 3);
break;
case 0x142: case 0x14A: case 0x152: case 0x15A:
case 0x162: case 0x16A: case 0x172: case 0x17A:
AMIGA.playfield.sprites.SPRxCTL(value, (addr - 0x142) >> 3);
AMIGA.playfield.SPRxCTL(hpos, value, (addr - 0x142) >> 3);
break;
case 0x144: case 0x14C: case 0x154: case 0x15C:
case 0x164: case 0x16C: case 0x174: case 0x17C:
AMIGA.playfield.sprites.SPRxDATA(value, (addr - 0x144) >> 3);
AMIGA.playfield.SPRxDATA(hpos, value, (addr - 0x144) >> 3);
break;
case 0x146: case 0x14E: case 0x156: case 0x15E:
case 0x166: case 0x16E: case 0x176: case 0x17E:
AMIGA.playfield.sprites.SPRxDATB(value, (addr - 0x146) >> 3);
break;
AMIGA.playfield.SPRxDATB(hpos, value, (addr - 0x146) >> 3);
break;
case 0x36: AMIGA.input.JOYTEST(value); break;
case 0x5A: AMIGA.blitter.BLTCON0L(hpos, value); break; //ECS
case 0x5C: AMIGA.blitter.BLTSIZV(hpos, value); break; //ECS
case 0x5E: AMIGA.blitter.BLTSIZH(hpos, value); break; //ECS
//case 0x1E4: AMIGA.playfield.DIWHIGH(value); break; //ECS
//case 0x10C: AMIGA.playfield.BPLCON4(value); break; //AGA
case 0x5A: AMIGA.blitter.BLTCON0L(hpos, value); break;
case 0x5C: AMIGA.blitter.BLTSIZV(hpos, value); break;
case 0x5E: AMIGA.blitter.BLTSIZH(hpos, value); break;
case 0x1E4: AMIGA.playfield.DIWHIGH(hpos, value); break;
//case 0x10C: AMIGA.playfield.BPLCON4(hpos, value); break; //AGA
//#ifndef CUSTOM_SIMPLE
//case 0x1DC: AMIGA.events.BEAMCON0(value); break;
/*#ifdef ECS_DENISE
case 0x1C0: if (htotal != value) { htotal = value; varsync (); } break;
case 0x1C2: if (hsstop != value) { hsstop = value; varsync (); } break;
case 0x1C4: if (hbstrt != value) { hbstrt = value; varsync (); } break;
case 0x1C6: if (hbstop != value) { hbstop = value; varsync (); } break;
case 0x1C8: if (vtotal != value) { vtotal = value; varsync (); } break;
case 0x1CA: if (vsstop != value) { vsstop = value; varsync (); } break;
case 0x1CC: if (vbstrt < value || vbstrt > value + 1) { vbstrt = value; varsync (); } break;
case 0x1CE: if (vbstop < value || vbstop > value + 1) { vbstop = value; varsync (); } break;
case 0x1DE: if (hsstrt != value) { hsstrt = value; varsync (); } break;
case 0x1E0: if (vsstrt != value) { vsstrt = value; varsync (); } break;
case 0x1E2: if (hcenter != value) { hcenter = value; varsync (); } break;
endif*/
//endif
case 0x1DC: AMIGA.playfield.BEAMCON0(value); break;
case 0x1C0: if (AMIGA.playfield.htotal != value) { AMIGA.playfield.htotal = value; AMIGA.playfield.varsync(); } break;
case 0x1C2: if (AMIGA.playfield.hsstop != value) { AMIGA.playfield.hsstop = value; AMIGA.playfield.varsync(); } break;
case 0x1C4: if (AMIGA.playfield.hbstrt != value) { AMIGA.playfield.hbstrt = value; AMIGA.playfield.varsync(); } break;
case 0x1C6: if (AMIGA.playfield.hbstop != value) { AMIGA.playfield.hbstop = value; AMIGA.playfield.varsync(); } break;
case 0x1C8: if (AMIGA.playfield.vtotal != value) { AMIGA.playfield.vtotal = value; AMIGA.playfield.varsync(); } break;
case 0x1CA: if (AMIGA.playfield.vsstop != value) { AMIGA.playfield.vsstop = value; AMIGA.playfield.varsync(); } break;
case 0x1CC: if (AMIGA.playfield.vbstrt < value || AMIGA.playfield.vbstrt > value + 1) { AMIGA.playfield.vbstrt = value; AMIGA.playfield.varsync(); } break;
case 0x1CE: if (AMIGA.playfield.vbstop < value || AMIGA.playfield.vbstop > value + 1) { AMIGA.playfield.vbstop = value; AMIGA.playfield.varsync(); } break;
case 0x1DE: if (AMIGA.playfield.hsstrt != value) { AMIGA.playfield.hsstrt = value; AMIGA.playfield.varsync(); } break;
case 0x1E0: if (AMIGA.playfield.vsstrt != value) { AMIGA.playfield.vsstrt = value; AMIGA.playfield.varsync(); } break;
case 0x1E2: if (AMIGA.playfield.hcenter != value) { AMIGA.playfield.hcenter = value; AMIGA.playfield.varsync(); } break;
//case 0x1FC: FMODE (hpos, value); break; //AGA
//case 0x1FC: AMIGA.playfield.FMODE(hpos, value); break; //AGA
//case 0x1FE: FNULL (value); break;
case 0x1FE: break;
@ -327,7 +326,7 @@ function Custom() {
}
this.store16 = function (addr, value) {
var hpos = AMIGA.events.hpos();
var hpos = AMIGA.playfield.hpos();
AMIGA.copper.sync_copper_with_cpu(hpos, 1);
if (addr & 1) {
addr &= ~1;
@ -339,7 +338,24 @@ function Custom() {
}
this.store8 = function (addr, value) {
this.store16(addr & ~1, ((value << 8) | (value & 0xff)) & 0xffff);
var rval;
/*if (AMIGA.config.chipset.mask & CSMASK_AGA) {
if (addr & 1) {
rval = value & 0xff;
} else {
rval = (value << 8) | (value & 0xFF);
}
} else*/
rval = (value << 8) | (value & 0xff);
/*if (AMIGA.config.cpu.model == 68060) {
if (addr & 1)
this.store16(addr & ~1, rval);
else
this.store16(addr, value << 8);
} else*/
this.store16(addr & ~1, rval);
}
this.store32 = function (addr, value) {

View file

@ -6,6 +6,9 @@
* ©2012 Rupert Hausberger
* Commercial use is prohibited.
*
***************************************************************************
* Notes: Ported from WinUAE 2.5.0
*
**************************************************************************/
const LONGWRITEMODE = 0;
@ -88,7 +91,7 @@ function Drive(number) {
this.cyl = 0;
this.motoroff = true;
this.motordelay = false; /* dskrdy needs some clock cycles before it changes after switching off motor */
this.state = 0;
//this.state = 0;
this.wrprot = false;
this.bigmfmbuf = new Uint16Array(0x4000 * DDHDMULT); for (var i = 0; i < 0x4000 * DDHDMULT; i++) this.bigmfmbuf[i] = 0;
this.tracktiming = new Uint16Array(0x4000 * DDHDMULT); for (var i = 0; i < 0x4000 * DDHDMULT; i++) this.tracktiming[i] = 0;
@ -436,7 +439,7 @@ function Drive(number) {
if (AMIGA.config.cpu.model <= 68010 && AMIGA.config.cpu.speed == SAEV_Config_CPU_Speed_Original) {
this.motordelay = true;
AMIGA.events.event2_newevent2(30, this.num, function(v) { AMIGA.disk.motordelay_func(v); });
AMIGA.events.newevent2(30, this.num, function(v) { AMIGA.disk.motordelay_func(v); });
}
}
this.motoroff = off;
@ -847,6 +850,7 @@ function Disk() {
AMIGA.config.hooks.floppy_motor(i, false);
AMIGA.config.hooks.floppy_step(i, floppy[i].cyl);
}
this.DSKLEN(0, 0);
for (var i = 0; i < MAX_FLOPPY_DRIVES; i++) {
this.eject(i);
this.insert(i);
@ -1022,9 +1026,8 @@ function Disk() {
var disk_sync_cycle = data >> 8;
//BUG.info('Disk.handler() data $%x, flag %d, disk_sync_cycle %d', data, flag, disk_sync_cycle);
//AMIGA.events.eventtab[EV_DISK].active = false;
AMIGA.events.event2_remevent(EV2_DISK);
AMIGA.events.remevent(EV2_DISK);
this.update(disk_sync_cycle);
if (flag & (DISK_REVOLUTION << 0)) this.fetchnextrevolution(0);
@ -1036,7 +1039,9 @@ function Disk() {
if (flag & DISK_INDEXSYNC) {
if (!indexdecay) {
indexdecay = 2;
AMIGA.cia.setICR(CIA_B, 0x10, null);
//AMIGA.cia.setICR(CIA_B, 0x10, null);
//AMIGA.cia.diskindex();
AMIGA.cia.SetICRB(0x10, null);
}
}
}
@ -1239,7 +1244,7 @@ function Disk() {
this.doupdate_predict = function(startcycle) {
//BUG.info('Disk.doupdate_predict() startcycle %d', startcycle);
var finaleventcycle = AMIGA.events.maxhpos << 8;
var finaleventcycle = AMIGA.playfield.maxhpos << 8;
var finaleventflag = 0;
for (var dr = 0; dr < MAX_FLOPPY_DRIVES; dr++) {
@ -1252,7 +1257,7 @@ function Disk() {
var tword = word;
var countcycle = startcycle + (floppy[dr].floppybitcounter % floppy[dr].trackspeed);
var mfmpos = floppy[dr].mfmpos;
while (countcycle < (AMIGA.events.maxhpos << 8)) {
while (countcycle < (AMIGA.playfield.maxhpos << 8)) {
if (floppy[dr].tracktiming[0])
this.updatetrackspeed(dr, mfmpos);
if (dskdmaen != DSKDMA_WRITE || (dskdmaen == DSKDMA_WRITE && !dma_enable)) {
@ -1297,18 +1302,8 @@ function Disk() {
}
}
if (finaleventflag && (finaleventcycle >>> 8) < AMIGA.events.maxhpos) {
AMIGA.events.event2_newevent(EV2_DISK, (finaleventcycle - startcycle) >>> 8, ((finaleventcycle >>> 8) << 8) | finaleventflag);
/*var evtime = (finaleventcycle - startcycle) >>> 8;
if (evtime == 0) evtime = 1;
AMIGA.events.eventtab[EV_DISK].active = true;
AMIGA.events.eventtab[EV_DISK].oldcycles = AMIGA.events.currcycle;
AMIGA.events.eventtab[EV_DISK].evtime = AMIGA.events.currcycle + (evtime * CYCLE_UNIT);
AMIGA.events.eventtab[EV_DISK].data = ((finaleventcycle >>> 8) << 8) | finaleventflag;
AMIGA.events.schedule();
*/
}
if (finaleventflag && (finaleventcycle >>> 8) < AMIGA.playfield.maxhpos)
AMIGA.events.newevent(EV2_DISK, (finaleventcycle - startcycle) >>> 8, ((finaleventcycle >>> 8) << 8) | finaleventflag);
}
this.update = function(tohpos) {
@ -1326,7 +1321,7 @@ function Disk() {
return;
disk_hpos += cycles;
if (disk_hpos >= (AMIGA.events.maxhpos << 8))
if (disk_hpos >= (AMIGA.playfield.maxhpos << 8))
disk_hpos %= (1 << 8);
for (dr = 0; dr < MAX_FLOPPY_DRIVES; dr++) {
@ -1429,7 +1424,7 @@ function Disk() {
this.dmafinished();
return;
}
this.update(AMIGA.events.maxhpos);
this.update(AMIGA.playfield.maxhpos);
}
this.update_adkcon = function(v) {

File diff suppressed because it is too large Load diff

View file

@ -666,9 +666,10 @@ function Keyboard() {
}
this.keyReq = function() {
this.lostsynccnt = 8 * AMIGA.events.maxvpos * 8; /* 8 frames * 8 bits */
this.lostsynccnt = 8 * AMIGA.playfield.maxvpos * 8; /* 8 frames * 8 bits */
AMIGA.cia.setICR(CIA_A, 8, code);
//AMIGA.cia.setICR(CIA_A, 8, code);
AMIGA.cia.SetICRA(8, code);
}
this.hsync = function() {
@ -696,7 +697,7 @@ function Keyboard() {
this.vsync = function() {
if (this.lostsynccnt > 0) {
this.lostsynccnt -= AMIGA.events.maxvpos;
this.lostsynccnt -= AMIGA.playfield.maxvpos;
if (this.lostsynccnt <= 0) {
this.lostsynccnt = 0;
this.keyReq();

View file

@ -197,14 +197,15 @@ function Memory() {
this.res_e0.data = new Uint16Array(this.res_e0.align); for (var i = 0; i < this.res_e0.align; i++) this.res_e0.data[i] = 0;
this.res_f0.data = new Uint16Array(this.res_f0.align); for (var i = 0; i < this.res_f0.align; i++) this.res_f0.data[i] = 0;
AMIGA.mem.copy_rom(AMIGA.config.rom.data);
this.copy_rom(AMIGA.config.rom.data);
if (AMIGA.config.ext.size != SAEV_Config_EXT_Size_None) {
if (AMIGA.config.ext.addr == SAEV_Config_EXT_Addr_E0)
AMIGA.mem.copy_e0(AMIGA.config.ext.data);
this.copy_e0(AMIGA.config.ext.data);
else if (AMIGA.config.ext.addr == SAEV_Config_EXT_Addr_F0)
AMIGA.mem.copy_f0(AMIGA.config.ext.data);
this.copy_f0(AMIGA.config.ext.data);
}
//this.mirror_rom_to_chipram();
/*if (AMIGA.config.rom.mode == 1) {
if (!this.aros.cached) {
@ -281,7 +282,7 @@ function Memory() {
return (addr & 1) ? (this.res_f0.data[(addr - this.res_f0.lower) >>> 1] & 0xff) : (this.res_f0.data[(addr - this.res_f0.lower) >>> 1] >> 8);
}
else if (addr >= this.res_d8.lower && addr < this.res_d8.upper) {
return (addr & 1) ? (this.res_d0.data[(addr - this.res_d0.lower) >>> 1] & 0xff) : (this.res_d0.data[(addr - this.res_d0.lower) >>> 1] >> 8);
return (addr & 1) ? (this.res_d8.data[(addr - this.res_d8.lower) >>> 1] & 0xff) : (this.res_d8.data[(addr - this.res_d8.lower) >>> 1] >> 8);
}
else if (addr >= this.ac_z2.lower && addr < this.ac_z2.upper) {
return AMIGA.expansion.load8(addr);
@ -325,7 +326,7 @@ function Memory() {
return this.res_f0.data[(addr - this.res_f0.lower) >>> 1];
}
else if (addr >= this.res_d8.lower && addr < this.res_d8.upper - 1) {
return this.res_d0.data[(addr - this.res_d0.lower) >>> 1];
return this.res_d8.data[(addr - this.res_d8.lower) >>> 1];
}
//else BUG.info('Memory.load16() ILLEGAL MEMORY ACCESS addr $%08x', addr);
@ -372,8 +373,8 @@ function Memory() {
return ((this.res_f0.data[addr] << 16) | this.res_f0.data[addr + 1]) >>> 0;
}
else if (addr >= this.res_d8.lower && addr < this.res_d8.upper - 3) {
addr = (addr - this.res_d0.lower) >>> 1;
return ((this.res_d0.data[addr] << 16) | this.res_d0.data[addr + 1]) >>> 0;
addr = (addr - this.res_d8.lower) >>> 1;
return ((this.res_d8.data[addr] << 16) | this.res_d8.data[addr + 1]) >>> 0;
}
//else BUG.info('Memory.load32() ILLEGAL MEMORY ACCESS addr $%08x', addr);
@ -442,11 +443,11 @@ function Memory() {
}
else if (addr >= this.res_d8.lower && addr < this.res_d8.upper) {
if (addr & 1) {
addr = (addr - this.res_d0.lower) >>> 1;
this.res_d0.data[addr] = (this.res_d0.data[addr] & 0xff00) | value;
addr = (addr - this.res_d8.lower) >>> 1;
this.res_d8.data[addr] = (this.res_d8.data[addr] & 0xff00) | value;
} else {
addr = (addr - this.res_d0.lower) >>> 1;
this.res_d0.data[addr] = (value << 8) | (this.res_d0.data[addr] & 0x00ff);
addr = (addr - this.res_d8.lower) >>> 1;
this.res_d8.data[addr] = (value << 8) | (this.res_d8.data[addr] & 0x00ff);
}
}
else if (addr >= this.ac_z2.lower && addr < this.ac_z2.upper) {
@ -486,7 +487,7 @@ function Memory() {
this.res_f0.data[(addr - this.res_f0.lower) >>> 1] = value;
}
else if (addr >= this.res_d8.lower && addr < this.res_d8.upper - 1) {
this.res_d0.data[(addr - this.res_d0.lower) >>> 1] = value;
this.res_d8.data[(addr - this.res_d8.lower) >>> 1] = value;
}
//else BUG.info('Memory.store16() ILLEGAL MEMORY ACCESS addr $%08x, val %04x', addr, value);
}
@ -532,9 +533,9 @@ function Memory() {
this.res_f0.data[addr + 1] = value & 0xffff;
}
else if (addr >= this.res_d8.lower && addr < this.res_d8.upper - 3) {
addr = (addr - this.res_d0.lower) >>> 1;
this.res_d0.data[addr] = value >>> 16;
this.res_d0.data[addr + 1] = value & 0xffff;
addr = (addr - this.res_d8.lower) >>> 1;
this.res_d8.data[addr] = value >>> 16;
this.res_d8.data[addr + 1] = value & 0xffff;
}
//else if (!(addr & 0xc80000)) BUG.info('Memory.store32() ILLEGAL MEMORY ACCESS addr $%08x, val %08x', addr, value);
}
@ -555,7 +556,7 @@ function Memory() {
this.chip.data[addr >>> 1] = value;
AMIGA.custom.last_value = value;
} else BUG.info('store16_chip() ILLEGAL MEMORY ACCESS addr %x, value %x', addr, value);
}*/
}
this.load16_chip = function (addr) {
if (addr < this.chip.size - 1)
AMIGA.custom.last_value = this.chip.data[addr >>> 1];
@ -569,7 +570,7 @@ function Memory() {
this.chip.data[addr >>> 1] = AMIGA.custom.last_value = value;
else
AMIGA.custom.last_value = 0xffff;
}
}*/
this.copy_rom = function(data) {
//BUG.info('copyrom() size %d', data.length);
@ -640,13 +641,13 @@ function Memory() {
}
}
/*this.mirror_rom_to_chipram = function() {
this.mirror_rom_to_chipram = function() {
for (var i = 0; i < this.rom.size; i++)
this.chip.data[i] = this.rom.data[i];
if (this.ext.size > 0) {
/*if (this.ext.size > 0) {
for (var i = 0; i < this.ext.size; i++)
this.chip.data[this.rom.size + i] = this.ext.data[i];
}
}*/
}*/
}
}

File diff suppressed because it is too large Load diff

View file

@ -337,6 +337,12 @@ function dump(obj) {
/*-----------------------------------------------------------------------*/
function VSync(err, msg) {
this.error = err;
this.message = msg;
}
VSync.prototype = new Error;
function FatalError(err, msg) {
this.error = err;
this.message = msg;
@ -417,3 +423,59 @@ function Debug() {
}
}
}
/*-----------------------------------------------------------------------*/
function Uint64(hi, lo) {
this.hi = hi;
this.lo = lo;
this.or = function(v) {
this.hi = (this.hi | v.hi) >>> 0;
this.lo = (this.lo | v.lo) >>> 0;
}
this.lshift = function(n) {
if (n) {
if (n < 32) {
var m = Math.pow(2, n) - 1;
var t = this.lo & m;
this.hi = ((this.hi << n) | t) >>> 0;
this.lo = (this.lo << n) >>> 0;
//BUG.info('lshift %d %x', n, m, t);
} else {
var t = this.lo;
this.hi = (t << (n-32)) >>> 0;
this.lo = 0;
//BUG.info('lshift %d %x', n, t);
}
}
}
this.rshift = function(n) {
if (n) {
if (n < 32) {
var m = Math.pow(2, n) - 1;
var t = this.hi & m;
this.hi = (this.hi >>> n) >>> 0;
this.lo = ((t << (32 - n)) | (this.lo >>> n)) >>> 0;
//BUG.info('rshift %d %x %x', n, m, t);
} else {
var t = this.hi;
this.hi = 0;
this.lo = (t >>> (n-32)) >>> 0;
//BUG.info('rshift %d %x %x', n, t);
}
}
}
this.print = function() {
BUG.info('$%08x%08x', this.hi, this.lo);
}
}

View file

@ -34,130 +34,168 @@ function Vide0() {
antialias: false
};
this.available = 0;
var width = 0;
var height = 0;
var size = 0;
var scale = false;
var pixels = null;
var div = null;
var canvas = null;
var gl = null;
var ctx = null;
var imagedata = null;
var video = null;
var open = false;
/*---------------------------------*/
function getShader(gl, id) {
//this.init = function()
{
var test = document.createElement('canvas');
if (test && test.getContext) {
var test2 = test.getContext('2d');
if (test2) {
this.available |= SAEI_Video_Canvas2D;
test2 = null;
}
test = null;
}
test = document.createElement('canvas');
if (test && test.getContext) {
test2 = test.getContext('experimental-webgl', glParams) || test.getContext('webgl', glParams);
if (test2) {
this.available |= SAEI_Video_WebGL;
test2 = null;
}
test = null;
}
//console.log(this.available);
}
/*---------------------------------*/
function getShader(ctx, id) {
var shader, source;
if (id == 'vertex') {
shader = gl.createShader(gl.VERTEX_SHADER);
shader = ctx.createShader(ctx.VERTEX_SHADER);
source = vertexShader;
} else if (id == 'fragment') {
shader = gl.createShader(gl.FRAGMENT_SHADER);
shader = ctx.createShader(ctx.FRAGMENT_SHADER);
source = fragmentShader;
}
gl.shaderSource(shader, source);
gl.compileShader(shader);
ctx.shaderSource(shader, source);
ctx.compileShader(shader);
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS))
Fatal(SAEE_Video_Shader_Error, gl.getShaderInfoLog(shader));
if (!ctx.getShaderParameter(shader, ctx.COMPILE_STATUS))
Fatal(SAEE_Video_Shader_Error, ctx.getShaderInfoLog(shader));
return shader;
}
function initGL() {
var vertexShader = getShader(gl, 'vertex');
var fragmentShader = getShader(gl, 'fragment');
var program = gl.createProgram();
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
gl.linkProgram(program);
if (!gl.getProgramParameter(program, gl.LINK_STATUS))
var vertexShader = getShader(ctx, 'vertex');
var fragmentShader = getShader(ctx, 'fragment');
var program = ctx.createProgram();
ctx.attachShader(program, vertexShader);
ctx.attachShader(program, fragmentShader);
ctx.linkProgram(program);
if (!ctx.getProgramParameter(program, ctx.LINK_STATUS))
Fatal(SAEE_Video_Shader_Error, 'Can\'t initialise the shaders for WebGL.');
gl.useProgram(program);
ctx.useProgram(program);
var positionLocation = gl.getAttribLocation(program, "a_position");
var texCoordLocation = gl.getAttribLocation(program, "a_texCoord");
var positionLocation = ctx.getAttribLocation(program, "a_position");
var texCoordLocation = ctx.getAttribLocation(program, "a_texCoord");
var texCoordBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, texCoordBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
var texCoordBuffer = ctx.createBuffer();
ctx.bindBuffer(ctx.ARRAY_BUFFER, texCoordBuffer);
ctx.bufferData(ctx.ARRAY_BUFFER, new Float32Array([
0.0, 0.0,
1.0, 0.0,
0.0, 1.0,
0.0, 1.0,
1.0, 0.0,
1.0, 1.0]), gl.STATIC_DRAW);
gl.enableVertexAttribArray(texCoordLocation);
gl.vertexAttribPointer(texCoordLocation, 2, gl.FLOAT, false, 0, 0);
1.0, 1.0]), ctx.STATIC_DRAW);
ctx.enableVertexAttribArray(texCoordLocation);
ctx.vertexAttribPointer(texCoordLocation, 2, ctx.FLOAT, false, 0, 0);
var texture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, texture);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
var texture = ctx.createTexture();
ctx.bindTexture(ctx.TEXTURE_2D, texture);
ctx.texParameteri(ctx.TEXTURE_2D, ctx.TEXTURE_WRAP_S, ctx.CLAMP_TO_EDGE);
ctx.texParameteri(ctx.TEXTURE_2D, ctx.TEXTURE_WRAP_T, ctx.CLAMP_TO_EDGE);
ctx.texParameteri(ctx.TEXTURE_2D, ctx.TEXTURE_MIN_FILTER, ctx.NEAREST);
ctx.texParameteri(ctx.TEXTURE_2D, ctx.TEXTURE_MAG_FILTER, ctx.NEAREST);
var resolutionLocation = gl.getUniformLocation(program, "u_resolution");
gl.uniform2f(resolutionLocation, width, height);
var resolutionLocation = ctx.getUniformLocation(program, "u_resolution");
ctx.uniform2f(resolutionLocation, width, height);
var buffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
gl.enableVertexAttribArray(positionLocation);
gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0);
var buffer = ctx.createBuffer();
ctx.bindBuffer(ctx.ARRAY_BUFFER, buffer);
ctx.enableVertexAttribArray(positionLocation);
ctx.vertexAttribPointer(positionLocation, 2, ctx.FLOAT, false, 0, 0);
gl.viewport(0, 0, width, height);
gl.clearColor(0, 0, 0, 1);
gl.clear(gl.COLOR_BUFFER_BIT);
gl.colorMask(true, true, true, false);
ctx.viewport(0, 0, width, height);
ctx.clearColor(0, 0, 0, 1);
ctx.clear(ctx.COLOR_BUFFER_BIT);
ctx.colorMask(true, true, true, false);
}
this.setup = function() {
if (!AMIGA.config.video.enabled) return;
if (open) this.cleanup();
width = AMIGA.config.video.scale ? VIDEO_WIDTH << 1 : VIDEO_WIDTH;
height = AMIGA.config.video.scale ? VIDEO_HEIGHT << 1 : VIDEO_WIDTH;
size = width * height;
//BUG.info('Video.init() %d x %d, %s mode', width, height, AMIGA.config.video.ntsc ? 'ntsc' : 'pal');
div = document.getElementById(AMIGA.config.video.id);
if (!div)
Fatal(SAEE_Video_ID_Not_Found, 'Video DIV-element not found. Check your code. (Malformed-DIV-name: '+AMIGA.config.video.id+')');
if ((canvas = document.createElement('canvas'))) {
canvas.width = width;
scale = (this.available & SAEI_Video_WebGL) ? AMIGA.config.video.scale : false;
width = VIDEO_WIDTH << (scale ? 1 : 0);
height = VIDEO_HEIGHT << (scale ? 1 : 0);
size = width * height;
//BUG.info('Video.init() %d x %d, %s mode', width, height, AMIGA.config.video.ntsc ? 'ntsc' : 'pal');
if (this.available & SAEI_Video_Canvas2D) {
canvas = document.createElement('canvas');
canvas.width = width;
canvas.height = height;
} else {
if (confirm('Can\'t create a CANVAS-element. Continue without video-playback?'))
AMIGA.config.video.enabled = false;
else
Fatal(SAEE_Video_Canvas_Not_Supported, 'Can\'t create a CANVAS-element. Please update the browser.');
}
if (AMIGA.config.video.enabled) {
if ((gl = canvas.getContext('experimental-webgl', glParams) || canvas.getContext('webgl', glParams)))
canvas.oncontextmenu = function() { return false; }
if (AMIGA.config.ports[0].type == SAEV_Config_Ports_Type_Mouse) {
canvas.onmousedown = function(e) { AMIGA.input.mouse.mousedown(e); }
canvas.onmouseup = function(e) { AMIGA.input.mouse.mouseup(e); }
canvas.onmouseover = function(e) { AMIGA.input.mouse.mouseover(e); }
canvas.onmouseout = function(e) { AMIGA.input.mouse.mouseout(e); }
canvas.onmousemove = function(e) { AMIGA.input.mouse.mousemove(e); }
}
if (this.available & SAEI_Video_WebGL) {
ctx = canvas.getContext('experimental-webgl', glParams) || canvas.getContext('webgl', glParams);
initGL();
pixels = new Uint16Array(size);
for (var i = 0; i < size; i++) pixels[i] = 0;
this.drawpixel = drawpixel_gl;
this.drawline = drawline_gl;
this.render = render_gl;
this.show = show_gl;
} else {
ctx = canvas.getContext('2d');
imagedata = ctx.createImageData(width, height);
pixels = imagedata.data;
this.drawpixel = drawpixel_2d;
this.drawline = drawline_2d;
this.render = render_2d;
this.show = show_2d;
}
} else {
if (!confirm('Cant\'t initialise "WebGL" nor "Canvas 2D". Continue without video-playback?'))
Fatal(SAEE_Video_Canvas_Not_Supported, null);
else
if (confirm('Can\'t initialise WebGL. Continue without video-playback?'))
AMIGA.config.video.enabled = false;
else
Fatal(SAEE_Video_WebGL_Not_Avail, 'Can\'t initialise WebGL. Is WebGL enabled in the browser-config?');
AMIGA.config.video.enabled = false;
}
if (AMIGA.config.video.enabled) {
pixels = new Uint16Array(size);
for (var i = 0; i < size; i++) pixels[i] = 0;
}
if (AMIGA.config.ports[0].type == SAEV_Config_Ports_Type_Mouse) {
canvas.onmousedown = function(e) { AMIGA.input.mouse.mousedown(e); }
canvas.onmouseup = function(e) { AMIGA.input.mouse.mouseup(e); }
canvas.onmouseover = function(e) { AMIGA.input.mouse.mouseover(e); }
canvas.onmouseout = function(e) { AMIGA.input.mouse.mouseout(e); }
canvas.onmousemove = function(e) { AMIGA.input.mouse.mousemove(e); }
}
canvas.oncontextmenu = function() { return false; }
video = document.createElement('div');
video.style.width = width + 'px';
video.style.height = height + 'px';
@ -168,15 +206,18 @@ function Vide0() {
video.style.mozUserSelect = 'none';
video.style.msUserSelect = 'none';
video.style.userSelect = 'none';
video.appendChild(canvas);
if (AMIGA.config.video.enabled)
video.appendChild(canvas);
div.appendChild(video);
open = true;
open = true;
}
this.cleanup = function() {
if (open) {
div.removeChild(video);
canvas = null;
imagedata = null;
pixels = null;
video = null;
open = false;
@ -189,57 +230,59 @@ function Vide0() {
canvas.style.cursor = hide ? 'none' : 'auto';
}
this.clear_pixels = function () {
/*this.clear_pixels = function () {
for (var i = 0; i < size; i++)
pixels[i] = 0;
}
}*/
this.drawpixel = function (x, y, rgb) {
/*---------------------------------*/
/* Canvas 2D */
function drawpixel_2d(x, y, rgb) {
pixels[y * width + x] = rgb;
}
this.draw2pixel = function (x, y, rgb) {
var ptr = y * width + x;
pixels[ptr] = pixels[ptr + 1] = rgb;
}
this.drawline = function (y, rgb) {
var ptr = y * width;
for (var i = 0; i < width; i++)
pixels[ptr++] = rgb;
}
this.drawline_from_to = function (x1, x2, y, rgb) {
var ptr = y * width + x1;
for (var i = 0; i < x2 - x1; i++)
pixels[ptr++] = rgb;
}
this.draw = function (rgb, scalex, scaley, colorOnly) {
var r = 0.0625 * (((rgb >> 11) & 31) >> 1);
var g = 0.0625 * (((rgb >> 5) & 63) >> 2);
var b = 0.0625 * ((rgb & 31) >> 1);
gl.viewport(0, 0, width, height);
gl.clearColor(r, g, b, 1);
gl.clear(gl.COLOR_BUFFER_BIT);
if (!colorOnly) {
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, width, height, 0, gl.RGB, gl.UNSIGNED_SHORT_5_6_5, pixels);
var s = AMIGA.config.video.scale ? 1 : 0;
var x1 = 0;
//var x2 = 0 + (width << (scalex ? (s+1) : s));
var x2 = 0 + (width << s);
var y1 = 0;
var y2 = 0 + (height << (scaley ? (s+1) : s));
//var y2 = 0 + (height << s);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
x1, y1, x2, y1, x1, y2,
x1, y2, x2, y1, x2, y2]), gl.STATIC_DRAW);
gl.drawArrays(gl.TRIANGLES, 0, 6);
function drawline_2d(y, data, offs) {
var yoffs = (y * width) << 2;
for (var x = 0, d = 0; x < width << 2; x += 4, d++) {
pixels[yoffs + x ] = ((data[offs + d] >> 8) & 0xf) << 4;
pixels[yoffs + x + 1] = ((data[offs + d] >> 4) & 0xf) << 4;
pixels[yoffs + x + 2] = ((data[offs + d] >> 0) & 0xf) << 4;
pixels[yoffs + x + 3] = 255;
}
}
function render_2d() {
ctx.putImageData(imagedata, 0, 0);
}
function show_2d() {}
/*---------------------------------*/
/* WebGL */
function drawpixel_gl(x, y, rgb) {
pixels[y * width + x] = rgb;
}
function drawline_gl(y, data, offs) {
var yoffs = y * width;
for (var x = 0; x < width; x++)
pixels[yoffs + x] = data[offs + x] & 0xffff;
}
function render_gl() {
ctx.texImage2D(ctx.TEXTURE_2D, 0, ctx.RGB, width, height, 0, ctx.RGB, ctx.UNSIGNED_SHORT_5_6_5, pixels);
var x1 = 0;
var x2 = width << (scale ? 1 : 0);
var y1 = 0;
var y2 = height << (scale ? 1 : 0);
ctx.bufferData(ctx.ARRAY_BUFFER, new Float32Array([x1, y1, x2, y1, x1, y2, x1, y2, x2, y1, x2, y2]), ctx.STATIC_DRAW);
}
function show_gl() {
ctx.drawArrays(ctx.TRIANGLES, 0, 6);
}
}