diff --git a/index.css b/index.css index 7d623f5..275bc82 100644 --- a/index.css +++ b/index.css @@ -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%; diff --git a/index.htm b/index.htm index 354655c..9804402 100644 --- a/index.htm +++ b/index.htm @@ -6,7 +6,7 @@ - + @@ -30,37 +30,46 @@ - + - - +
- -
- -
-
-
- -
-
-

Welcome!

- This site is a demonstration of the 'SAE' project, - an experimental Amiga emulator in pure javascript and HTML5.
- For details, please refer to the readme file.

- Below you find a small collection of games and demos to play...
- (Use Google Chrome for best results) -
-
+
+ Scripted Amiga Emulator +
+ Experimental Amiga emulator in pure JavaScript and HTML5
+ based on UAE/WinUAE, + powered by AROS +
+
+
+
+
+
+ Browser +
+ + + + + + + + + + + + + +
Supported video-modes:-
Supported audio-modes:-
SAE-Version:-
+
+
+
Hall of fame
@@ -82,13 +91,17 @@ - Audio - + Audio/Video + + + + Frameskip + (25 instead of 50 fps) - Scale 4x - (1140 x 1152, press F11 for fullscreen) - + Extra scale + (double video-size via hardware) +
@@ -116,28 +129,43 @@
+
- +
-
- -
+
+ + + + @@ -309,14 +337,13 @@ - ('Turbo' mode is fastest, but not very compatible) + ('Turbo' mode is fastest, but not always compatible. All other modes are very slow) @@ -559,15 +584,14 @@
- - - -
- + + +
+
diff --git a/index.js b/index.js index b57106c..fd119e8 100644 --- a/index.js +++ b/index.js @@ -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
and insert the 2nd disk manualy.'], [] + ['Press the LMB until the main-nemu
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
and insert the 2nd disk manualy.'], [] - ],*/ + ['Press the LMB to skip the intro
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
and insert the 2nd disk manualy.'], [] + ['Press the LMB until the main-menu
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,
click RMB when done.'], [] + ['Insert the 2nd disk manualy,
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) { diff --git a/readme.htm b/readme.htm index f83aec8..31c0ce4 100644 --- a/readme.htm +++ b/readme.htm @@ -14,14 +14,16 @@
-
- Scripted Amiga Emulator -
-
-
+
+ Scripted Amiga Emulator +
+ Experimental Amiga emulator in pure JavaScript and HTML5 +
+
+
CPU - - - - - -
Speed: - -
+ Speed + +
Chipset + Type +
+ Collisions + + +
+ NTSC
+ A1000 OCS Agnus (8361/8367)
+ Blit immediate
Audio - - Enabled + Enabled @@ -327,17 +354,6 @@ - - - - - - + + + + + +
Mode:
Channels: - -
Samplerate:
Channels: + + Lowpass-filter:
Video - - Enabled -
- - Sprite collisions - - - -
- - Scale 4x (1440 x 1152) -
- - NTSC -
- - Frameskip (if the emulation is too slow, up to 4 frames will be skipped) - -
+ Enabled +
+ + Frameskip (25 instead of 50 fps)
+ Extra scale (double video-size via hardware) +
@@ -32,20 +34,20 @@
  • A very fast computer
  • A browser capable of HTML5 with:
      -
    • WegGL
    • -
    • WebAudio
    • +
    • WegGL or Canvas 2D (optional)
    • +
    • WebAudio (optional)
    • +
    • FileReader (GUI)
    • Typed arrays
    • -
    • FileReader (GUI)
  • A ROM:
      -
    • Amiga Kickstart 1.x-2.04 (not included for copyright reasons)
    • -
    • AROS Kickstart (included)
    • +
    • Amiga Kickstart 1.0-2.05 (not included for copyright reasons)
    • +
    • AROS Kickstart (included)

  • -
  • And a bunch of ADF-files to test (optional)
  • +
  • And a bunch of ADF-files to test (optional)
  • @@ -53,8 +55,8 @@
    - - + + @@ -86,30 +88,17 @@
  • Usage/Hints
    • Press F11 for fullscreen. Most browsers support that.
    • -
    • If something does crash, try another memory setting or a different ROM. The original kickstart (1.3) work's best.
    • +
    • If something does crash, try another memory setting or a different ROM.
      + The original kickstart (1.3) does work best.
    • Known bugs/problems
        -
      • There may be graphics-errors: -
          -
        • Graphics may be at a wrong position or a wrong color.
        • -
        • Fast blinking sprites are not displayed if 'Frameskip' is active.
        • -
        • Copper initiated color-changes within a scanline are not recognized.
        • -
        • The next update (0.8) will deal with this.
        • -
        -
      • -
      • Left/right shift/alt/ctrl are the same. That's a browser 'feature' and can't be fixed.
      • -
      -
    • -
    -
      -
    • Missing features -
        -
      • User-config
      • -
      • Maybe ECS support
      • +
      • Blinking sprites are not shown if "Frameskip" is active.
      • +
      • There may be short and heavy speed-fluctuations in the beginning of the emulation.
      • +
      • Left/right shift/alt/ctrl are the same. That's a browser "feature" and can't be fixed.
    @@ -121,7 +110,7 @@
      -
    • Source code +
    • Source-code @@ -130,24 +119,25 @@
      • License
          -
        • This is a free project.
        • +
        • This is a free project.
        • You may use the emulator in your own website.
        • -
        • If you use the emulator in your own website, you must provide a link to this homepage.
        • -
        • If you use the emulator in your own website, you must not change the copyright header in the source-files.
        • -
        • Commercial use in any form is prohibited. This includes donations.
        • +
        • If you use the emulator in your own website, you must provide a link to this homepage.
        • +
        • If you use the emulator in your own website, you must not change the copyright header in the source-files.
        • +
        • Commercial use in any form is prohibited. This includes donations.
        • No warranty expressed or implied. Use at your own risk.
      -
      +
      • History
          +
        • 0.8.0 (16.01.2013): +
            +
          • Display +
              +
            • Ported and optimized playfield-code from WinUAE.
              + This adds ECS and AGA support and fixes graphics-errors.
              + The AGA part is commented out, because there is no 68020 yet.
            • +
            • Added support for drawing via 'Canvas 2D' if 'WebGL' is not avail.
            • +
            • Added support for auto-driver detection.
            • +
            +
          • +
          • Audio +
              +
            • While disk access, audio performance is much better now.
            • +
            • Added support for the A500 lowpass-filter. Not enabled by default.
            • +
            • Added support for auto-driver detection.
            • +
            +
          • +
          • Memory +
              +
            • To gain speed, all memory is now accessed directly and not via functions.
              + So, don't care for a possible illegal memory access.
            • +
            • Fixed bug, where kickstart 1.2 failed to load.
            • +
            • Fixed incorrect extended-address bug.
            • +
            +
          • +
          • CPU +
              +
            • Splitted address-types of ADDQ/SUBQ into separate functions for more speed.
            • +
            • Added bus-read/write cycles tables. For internal use only.
            • +
            +
          • +
          • CIA +
              +
            • I decided to port the latest cia-code from WinUAE while i was trying to find a bug.
              + Well, the bug is still there. Let's keep the code nevertheless.
            • +
            +
          • +
          • GUI +
              +
            • Added info box of supported drivers.
            • +
            • Added a 'Chipset'-section and various options.
            • +
            • Packed the main GUI.
            • +
            +
          • +
          • Common +
              +
            • Added support for easy URL sharing. E.g. to show the Multica-demo to a friend,
              + one may send the link "http://scriptedamigaemulator.net/#Multica"
              + and the demo will start immediately. (thanks mrdoob)
            • +
            • Many small optimizations.
            • +
            +
          • +
          +
        • +

        • 0.7.0 (24.12.2012):
          • Common @@ -246,7 +291,8 @@
          • Audio
            • Added a ring-buffer before output. No more "bagpipe"-like audio.
            • -
            • Added a option to just emulate the hardware, but not to play any sound, e.g. "Agony" was not starting, if audio was disabled.
            • +
            • Added a option to just emulate the hardware, but not to play any sound,
              + e.g. "Agony" was not starting, if audio was disabled.
          • Display diff --git a/sae/amiga.js b/sae/amiga.js index 84b8fc7..41ac979 100644 --- a/sae/amiga.js +++ b/sae/amiga.js @@ -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;*/ diff --git a/sae/audio.js b/sae/audio.js index b5945ef..a1e98f0 100644 --- a/sae/audio.js +++ b/sae/audio.js @@ -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]; } diff --git a/sae/blitter.js b/sae/blitter.js index e34b4a9..0b39b76 100644 --- a/sae/blitter.js +++ b/sae/blitter.js @@ -3,27 +3,79 @@ * * https://github.com/naTmeg/ScriptedAmigaEmulator * -* ©2012 Rupert Hausberger +* ©2012 Rupert Hausberger * Commercial use is prohibited. * +*************************************************************************** +* Notes: Ported from WinUAE 2.5.0 +* **************************************************************************/ function Blitter() { + const FAST = true; const BLITTER_MAX_WORDS = 2048; - /*const BLITTER_STARTUP_CYCLES = 2; - const BLIT_MODE_IMMEDIATE = -1; - const BLIT_MODE_APPROXIMATE = 0; - const BLIT_MODE_COMPATIBLE = 1; - const BLIT_MODE_EXACT = 2;*/ + const blit_cycle_diagram = [ + [2, 0,0, 0,0 ], /* 0 -- */ + [2, 0,0, 0,4 ], /* 1 -D */ + [2, 0,3, 0,3 ], /* 2 -C */ + [3, 0,3,0, 0,3,4 ], /* 3 -CD */ + [3, 0,2,0, 0,2,0 ], /* 4 -B- */ + [3, 0,2,0, 0,2,4 ], /* 5 -BD */ + [3, 0,2,3, 0,2,3 ], /* 6 -BC */ + [4, 0,2,3,0, 0,2,3,4], /* 7 -BCD */ + [2, 1,0, 1,0 ], /* 8 A- */ + [2, 1,0, 1,4 ], /* 9 AD */ + [2, 1,3, 1,3 ], /* A AC */ + [3, 1,3,0, 1,3,4 ], /* B ACD */ + [3, 1,2,0, 1,2,0 ], /* C AB- */ + [3, 1,2,0, 1,2,4 ], /* D ABD */ + [3, 1,2,3, 1,2,3 ], /* E ABC */ + [4, 1,2,3,0, 1,2,3,4] /* F ABCD */ + ]; + const blit_cycle_diagram_fill = [ + [0 ], /* 0 */ + [3, 0,0,0, 0,4,0 ], /* 1 */ + [0 ], /* 2 */ + [0 ], /* 3 */ + [0 ], /* 4 */ + [4, 0,2,0,0, 0,2,4,0], /* 5 */ + [0 ], /* 6 */ + [0 ], /* 7 */ + [0 ], /* 8 */ + [3, 1,0,0, 1,4,0 ], /* 9 */ + [0 ], /* A */ + [0 ], /* B */ + [0 ], /* C */ + [4, 1,2,0,0, 1,2,4,0], /* D */ + [0 ], /* E */ + [0 ] /* F */ + ]; + const blit_cycle_diagram_line = [4, 0,3,5,4, 0,3,5,4]; + const blit_cycle_diagram_finald = [2, 0,4, 0,4]; + const blit_cycle_diagram_finalld = [2, 0,0, 0,0]; var blit_filltable = []; var blit_masktable = []; + var blit_interrupt = true; + var blit_ch = 0; + var blit_slowdown = 0; + var blit_stuck = 0; + var blit_cyclecounter = 0; + var blit_firstline_cycles = 0; + var blit_first_cycle = 0; + var blit_last_cycle = 0, blit_dmacount = 0, blit_dmacount2 = 0; + var blit_nod = 0; + var blit_diag = []; + var blit_faulty = 0; + var original_ch = 0, original_fill = 0, original_line = 0; + + var bltstate = BLT_done; var bltcon0 = 0; var bltcon1 = 0; var bltapt = 0; - var bltapt_line = 0; + var bltapt_line = null; var bltbpt = 0; var bltcpt = 0; var bltdpt = 0; @@ -32,10 +84,11 @@ function Blitter() { var blinea = 0, blineb = 0; var blitline = 0, blitfc = 0, blitfill = 0, blitife = 0, blitsing = 0, blitdesc = 0; var blitonedot = 0, blitsign = 0, blitlinepixel = 0; - //var blit_add = 0; - //var blit_modadda = 0, blit_modaddb = 0, blit_modaddc = 0, blit_modaddd = 0; - var blit_ch = 0; - + + var ddat1 = 0, ddat2 = 0; + var ddat1use = 0, ddat2use = 0; + var last_blitter_hpos = 0; + var blt_info = { blitzero:0, blitashift:0, blitbshift:0, blitdownashift:0, blitdownbshift:0, @@ -46,75 +99,6 @@ function Blitter() { got_cycle:0 }; - var bltstate = BLT_done; - - var original_ch = 0, original_fill = 0, original_line = 0; - var blit_interrupt = true; - var blitter_cycle_exact = false; - - var blit_cyclecounter = 0; - //var blit_waitcyclecounter = 0; - //var blit_maxcyclecounter = 0; - //var blit_totalcyclecounter = 0; - //var blit_startcycles = 0; - //var blit_misscyclecounter = 0; - var blit_slowdown = 0; - //var last_blitter_hpos = 0; - var blit_stuck = 0; - - var blit_firstline_cycles = 0; - var blit_first_cycle = 0; - var blit_last_cycle = 0, blit_dmacount = 0, blit_dmacount2 = 0; - //var blit_linecycles = 0, blit_extracycles = 0 - var blit_nod = 0; - var blit_diag = []; - //var blit_frozen = 0; - var blit_faulty = 0; - var blit_final = 0; - //var blt_delayed_irq = 0; - var ddat1 = 0, ddat2 = 0; - var ddat1use = 0, ddat2use = 0; - - const blit_cycle_diagram = [ - [ 2, 0,0, 0,0 ], /* 0 -- */ - [ 2, 0,0, 0,4 ], /* 1 -D */ - [ 2, 0,3, 0,3 ], /* 2 -C */ - [ 3, 0,3,0, 0,3,4 ], /* 3 -CD */ - [ 3, 0,2,0, 0,2,0 ], /* 4 -B- */ - [ 3, 0,2,0, 0,2,4 ], /* 5 -BD */ - [ 3, 0,2,3, 0,2,3 ], /* 6 -BC */ - [ 4, 0,2,3,0, 0,2,3,4 ], /* 7 -BCD */ - [ 2, 1,0, 1,0 ], /* 8 A- */ - [ 2, 1,0, 1,4 ], /* 9 AD */ - [ 2, 1,3, 1,3 ], /* A AC */ - [ 3, 1,3,0, 1,3,4, ], /* B ACD */ - [ 3, 1,2,0, 1,2,0 ], /* C AB- */ - [ 3, 1,2,0, 1,2,4 ], /* D ABD */ - [ 3, 1,2,3, 1,2,3 ], /* E ABC */ - [ 4, 1,2,3,0, 1,2,3,4 ] /* F ABCD */ - ]; - const blit_cycle_diagram_fill = [ - [ 0 ], /* 0 */ - [ 3, 0,0,0, 0,4,0 ], /* 1 */ - [ 0 ], /* 2 */ - [ 0 ], /* 3 */ - [ 0 ], /* 4 */ - [ 4, 0,2,0,0, 0,2,4,0 ], /* 5 */ - [ 0 ], /* 6 */ - [ 0 ], /* 7 */ - [ 0 ], /* 8 */ - [ 3, 1,0,0, 1,4,0 ], /* 9 */ - [ 0 ], /* A */ - [ 0 ], /* B */ - [ 0 ], /* C */ - [ 4, 1,2,0,0, 1,2,4,0 ], /* D */ - [ 0 ], /* E */ - [ 0 ] /* F */ - ]; - const blit_cycle_diagram_line = [4, 0,3,5,4, 0,3,5,4]; - const blit_cycle_diagram_finald = [2, 0,4, 0,4]; - const blit_cycle_diagram_finalld = [2, 0,0, 0,0]; - //function build_blitfilltable() { var blit_masktable = new Uint16Array(BLITTER_MAX_WORDS); @@ -165,12 +149,9 @@ function Blitter() { function get_ch() { if (blit_faulty) { - console.log('get_ch() blit_faulty'); - //FIXME + console.log('get_ch() blit_faulty'); return blit_cycle_diagram[0]; //&blit_diag[0]; } - if (blit_final) - return blitline ? blit_cycle_diagram_finalld : blit_cycle_diagram_finald; return blit_diag; } @@ -186,7 +167,7 @@ function Blitter() { return diag[1 + diag[0] + cycles]; } - /*function channel_pos(cycles) { + function channel_pos(cycles) { if (cycles < 0) return 0; var diag = get_ch(); @@ -195,58 +176,45 @@ function Blitter() { cycles -= diag[0]; cycles %= diag[0]; return cycles; - }*/ + } - /*function canblit(hpos) { - if (is_bitplane_dma (hpos)) - return 0; - if (cycle_line[hpos] & CYCLE_MASK) return 0; - return 1; - }*/ - - function blitter_interrupt(hpos, done) { + function blitter_interrupt() { if (blit_interrupt) return; - if (!done && (!AMIGA.config.blitter.exact || AMIGA.config.cpu.model >= 68020)) - return; blit_interrupt = true; - AMIGA.send_interrupt(6, 3 * CYCLE_UNIT); - //if (debug_dma) record_dma_event (DMA_EVENT_BLITIRQ, hpos, vpos); + AMIGA.INTREQ_0(INT_BLIT); } function blitter_done(hpos) { ddat1use = ddat2use = 0; - //bltstate = blit_startcycles == 0 || !AMIGA.config.blitter.exact ? BLT_done : BLT_init; - bltstate = !AMIGA.config.blitter.exact ? BLT_done : BLT_init; - blitter_interrupt(hpos, 1); + bltstate = BLT_done; + blitter_interrupt(); AMIGA.copper.blitter_done_notify(hpos); - //if (debug_dma) record_dma_event (DMA_EVENT_BLITFINISHED, hpos, vpos); - AMIGA.events.event2_remevent(EV2_BLITTER); - clr_special (SPCFLAG_BLTNASTY); - //BUG.info('blitter_done() cycles %d, missed %d, total %d', blit_totalcyclecounter, blit_misscyclecounter, blit_totalcyclecounter + blit_misscyclecounter); + AMIGA.events.remevent(EV2_BLITTER); + clr_special(SPCFLAG_BLTNASTY); } /*---------------------------------*/ - /* ~1500 lines of auto-generated functions are folling... */ + /* ~1500 lines of auto-generated functions are follwing... */ /*---------------------------------*/ function blitdofast_0(pta, ptb, ptc, ptd, b) { var i,j; var totald = 0; - var dstd=0; + var dstd = 0; var dstp = 0; for (j = 0; j < b.vblitsize; j++) { for (i = 0; i < b.hblitsize; i++) { var bltadat, srca; - if (dstp) AMIGA.mem.store16_chip(dstp, dstd); + if (dstp) AMIGA.mem.chip.data[dstp >>> 1] = dstd; dstd = (0) & 0xffff; totald |= dstd; if (ptd) { dstp = ptd; ptd += 2; } } if (ptd) ptd += b.bltdmod; } - if (dstp) AMIGA.mem.store16_chip(dstp, dstd); + if (dstp) AMIGA.mem.chip.data[dstp >>> 1] = dstd; if (totald != 0) b.blitzero = 0; } @@ -258,14 +226,14 @@ function Blitter() { for (j = 0; j < b.vblitsize; j++) { for (i = 0; i < b.hblitsize; i++) { var bltadat, srca; - if (dstp) AMIGA.mem.store16_chip(dstp, dstd); + if (dstp) AMIGA.mem.chip.data[dstp >>> 1] = dstd; dstd = (0) & 0xffff; totald |= dstd; if (ptd) { dstp = ptd; ptd -= 2; } } if (ptd) ptd -= b.bltdmod; } - if (dstp) AMIGA.mem.store16_chip(dstp, dstd); + if (dstp) AMIGA.mem.chip.data[dstp >>> 1] = dstd; if (totald != 0) b.blitzero = 0; } @@ -274,18 +242,18 @@ function Blitter() { var totald = 0; var preva = 0; var srcc = b.bltcdat; - var dstd=0; + var dstd = 0; var dstp = 0; for (j = 0; j < b.vblitsize; j++) { for (i = 0; i < b.hblitsize; i++) { var bltadat, srca; - if (ptc) { srcc = AMIGA.mem.load16_chip(ptc); ptc += 2; } - if (pta) { bltadat = blt_info.bltadat = AMIGA.mem.load16_chip(pta); pta += 2; } else { bltadat = blt_info.bltadat; } + if (ptc) { srcc = AMIGA.mem.chip.data[ptc >>> 1]; ptc += 2; } + if (pta) { bltadat = blt_info.bltadat = AMIGA.mem.chip.data[pta >>> 1]; pta += 2; } else { bltadat = blt_info.bltadat; } bltadat &= blit_masktable[i]; srca = ((((preva << 16) | bltadat) >>> 0) >>> b.blitashift) & 0xffff; preva = bltadat; - if (dstp) AMIGA.mem.store16_chip(dstp, dstd); + if (dstp) AMIGA.mem.chip.data[dstp >>> 1] = dstd; dstd = ((~srca & srcc)) & 0xffff; totald |= dstd; if (ptd) { dstp = ptd; ptd += 2; } @@ -295,7 +263,7 @@ function Blitter() { if (ptd) ptd += b.bltdmod; } b.bltcdat = srcc; - if (dstp) AMIGA.mem.store16_chip(dstp, dstd); + if (dstp) AMIGA.mem.chip.data[dstp >>> 1] = dstd; if (totald != 0) b.blitzero = 0; } @@ -309,12 +277,12 @@ function Blitter() { for (j = 0; j < b.vblitsize; j++) { for (i = 0; i < b.hblitsize; i++) { var bltadat, srca; - if (ptc) { srcc = AMIGA.mem.load16_chip(ptc); ptc -= 2; } - if (pta) { bltadat = blt_info.bltadat = AMIGA.mem.load16_chip(pta); pta -= 2; } else { bltadat = blt_info.bltadat; } + if (ptc) { srcc = AMIGA.mem.chip.data[ptc >>> 1]; ptc -= 2; } + if (pta) { bltadat = blt_info.bltadat = AMIGA.mem.chip.data[pta >>> 1]; pta -= 2; } else { bltadat = blt_info.bltadat; } bltadat &= blit_masktable[i]; srca = ((((bltadat << 16) | preva) >>> 0) >>> b.blitdownashift) & 0xffff; preva = bltadat; - if (dstp) AMIGA.mem.store16_chip(dstp, dstd); + if (dstp) AMIGA.mem.chip.data[dstp >>> 1] = dstd; dstd = ((~srca & srcc)) & 0xffff; totald |= dstd; if (ptd) { dstp = ptd; ptd -= 2; } @@ -324,7 +292,7 @@ function Blitter() { if (ptd) ptd -= b.bltdmod; } b.bltcdat = srcc; - if (dstp) AMIGA.mem.store16_chip(dstp, dstd); + if (dstp) AMIGA.mem.chip.data[dstp >>> 1] = dstd; if (totald != 0) b.blitzero = 0; } @@ -334,23 +302,23 @@ function Blitter() { var preva = 0; var prevb = 0, srcb = b.bltbhold; var srcc = b.bltcdat; - var dstd=0; + var dstd = 0; var dstp = 0; for (j = 0; j < b.vblitsize; j++) { for (i = 0; i < b.hblitsize; i++) { var bltadat, srca; - if (ptc) { srcc = AMIGA.mem.load16_chip(ptc); ptc += 2; } + if (ptc) { srcc = AMIGA.mem.chip.data[ptc >>> 1]; ptc += 2; } if (ptb) { - var bltbdat = blt_info.bltbdat = AMIGA.mem.load16_chip(ptb); ptb += 2; + var bltbdat = blt_info.bltbdat = AMIGA.mem.chip.data[ptb >>> 1]; ptb += 2; srcb = ((((prevb << 16) | bltbdat) >>> 0) >>> b.blitbshift) & 0xffff; prevb = bltbdat; } - if (pta) { bltadat = blt_info.bltadat = AMIGA.mem.load16_chip(pta); pta += 2; } else { bltadat = blt_info.bltadat; } + if (pta) { bltadat = blt_info.bltadat = AMIGA.mem.chip.data[pta >>> 1]; pta += 2; } else { bltadat = blt_info.bltadat; } bltadat &= blit_masktable[i]; srca = ((((preva << 16) | bltadat) >>> 0) >>> b.blitashift) & 0xffff; preva = bltadat; - if (dstp) AMIGA.mem.store16_chip(dstp, dstd); + if (dstp) AMIGA.mem.chip.data[dstp >>> 1] = dstd; dstd = ((srcc & ~(srca & srcb))) & 0xffff; totald |= dstd; if (ptd) { dstp = ptd; ptd += 2; } @@ -362,7 +330,7 @@ function Blitter() { } b.bltbhold = srcb; b.bltcdat = srcc; - if (dstp) AMIGA.mem.store16_chip(dstp, dstd); + if (dstp) AMIGA.mem.chip.data[dstp >>> 1] = dstd; if (totald != 0) b.blitzero = 0; } @@ -377,17 +345,17 @@ function Blitter() { for (j = 0; j < b.vblitsize; j++) { for (i = 0; i < b.hblitsize; i++) { var bltadat, srca; - if (ptc) { srcc = AMIGA.mem.load16_chip(ptc); ptc -= 2; } + if (ptc) { srcc = AMIGA.mem.chip.data[ptc >>> 1]; ptc -= 2; } if (ptb) { - var bltbdat = blt_info.bltbdat = AMIGA.mem.load16_chip(ptb); ptb -= 2; + var bltbdat = blt_info.bltbdat = AMIGA.mem.chip.data[ptb >>> 1]; ptb -= 2; srcb = ((((bltbdat << 16) | prevb) >>> 0) >>> b.blitdownbshift) & 0xffff; prevb = bltbdat; } - if (pta) { bltadat = blt_info.bltadat = AMIGA.mem.load16_chip(pta); pta -= 2; } else { bltadat = blt_info.bltadat; } + if (pta) { bltadat = blt_info.bltadat = AMIGA.mem.chip.data[pta >>> 1]; pta -= 2; } else { bltadat = blt_info.bltadat; } bltadat &= blit_masktable[i]; srca = ((((bltadat << 16) | preva) >>> 0) >>> b.blitdownashift) & 0xffff; preva = bltadat; - if (dstp) AMIGA.mem.store16_chip(dstp, dstd); + if (dstp) AMIGA.mem.chip.data[dstp >>> 1] = dstd; dstd = ((srcc & ~(srca & srcb))) & 0xffff; totald |= dstd; if (ptd) { dstp = ptd; ptd -= 2; } @@ -399,7 +367,7 @@ function Blitter() { } b.bltbhold = srcb; b.bltcdat = srcc; - if (dstp) AMIGA.mem.store16_chip(dstp, dstd); + if (dstp) AMIGA.mem.chip.data[dstp >>> 1] = dstd; if (totald != 0) b.blitzero = 0; } @@ -408,22 +376,22 @@ function Blitter() { var totald = 0; var preva = 0; var prevb = 0, srcb = b.bltbhold; - var dstd=0; + var dstd = 0; var dstp = 0; for (j = 0; j < b.vblitsize; j++) { for (i = 0; i < b.hblitsize; i++) { var bltadat, srca; if (ptb) { - var bltbdat = blt_info.bltbdat = AMIGA.mem.load16_chip(ptb); ptb += 2; + var bltbdat = blt_info.bltbdat = AMIGA.mem.chip.data[ptb >>> 1]; ptb += 2; srcb = ((((prevb << 16) | bltbdat) >>> 0) >>> b.blitbshift) & 0xffff; prevb = bltbdat; } - if (pta) { bltadat = blt_info.bltadat = AMIGA.mem.load16_chip(pta); pta += 2; } else { bltadat = blt_info.bltadat; } + if (pta) { bltadat = blt_info.bltadat = AMIGA.mem.chip.data[pta >>> 1]; pta += 2; } else { bltadat = blt_info.bltadat; } bltadat &= blit_masktable[i]; srca = ((((preva << 16) | bltadat) >>> 0) >>> b.blitashift) & 0xffff; preva = bltadat; - if (dstp) AMIGA.mem.store16_chip(dstp, dstd); + if (dstp) AMIGA.mem.chip.data[dstp >>> 1] = dstd; dstd = ((srca & ~srcb)) & 0xffff; totald |= dstd; if (ptd) { dstp = ptd; ptd += 2; } @@ -433,7 +401,7 @@ function Blitter() { if (ptd) ptd += b.bltdmod; } b.bltbhold = srcb; - if (dstp) AMIGA.mem.store16_chip(dstp, dstd); + if (dstp) AMIGA.mem.chip.data[dstp >>> 1] = dstd; if (totald != 0) b.blitzero = 0; } @@ -448,15 +416,15 @@ function Blitter() { for (i = 0; i < b.hblitsize; i++) { var bltadat, srca; if (ptb) { - var bltbdat = blt_info.bltbdat = AMIGA.mem.load16_chip(ptb); ptb -= 2; + var bltbdat = blt_info.bltbdat = AMIGA.mem.chip.data[ptb >>> 1]; ptb -= 2; srcb = ((((bltbdat << 16) | prevb) >>> 0) >>> b.blitdownbshift) & 0xffff; prevb = bltbdat; } - if (pta) { bltadat = blt_info.bltadat = AMIGA.mem.load16_chip(pta); pta -= 2; } else { bltadat = blt_info.bltadat; } + if (pta) { bltadat = blt_info.bltadat = AMIGA.mem.chip.data[pta >>> 1]; pta -= 2; } else { bltadat = blt_info.bltadat; } bltadat &= blit_masktable[i]; srca = ((((bltadat << 16) | preva) >>> 0) >>> b.blitdownashift) & 0xffff; preva = bltadat; - if (dstp) AMIGA.mem.store16_chip(dstp, dstd); + if (dstp) AMIGA.mem.chip.data[dstp >>> 1] = dstd; dstd = ((srca & ~srcb)) & 0xffff; totald |= dstd; if (ptd) { dstp = ptd; ptd -= 2; } @@ -466,7 +434,7 @@ function Blitter() { if (ptd) ptd -= b.bltdmod; } b.bltbhold = srcb; - if (dstp) AMIGA.mem.store16_chip(dstp, dstd); + if (dstp) AMIGA.mem.chip.data[dstp >>> 1] = dstd; if (totald != 0) b.blitzero = 0; } @@ -476,23 +444,23 @@ function Blitter() { var preva = 0; var prevb = 0, srcb = b.bltbhold; var srcc = b.bltcdat; - var dstd=0; + var dstd = 0; var dstp = 0; for (j = 0; j < b.vblitsize; j++) { for (i = 0; i < b.hblitsize; i++) { var bltadat, srca; - if (ptc) { srcc = AMIGA.mem.load16_chip(ptc); ptc += 2; } + if (ptc) { srcc = AMIGA.mem.chip.data[ptc >>> 1]; ptc += 2; } if (ptb) { - var bltbdat = blt_info.bltbdat = AMIGA.mem.load16_chip(ptb); ptb += 2; + var bltbdat = blt_info.bltbdat = AMIGA.mem.chip.data[ptb >>> 1]; ptb += 2; srcb = ((((prevb << 16) | bltbdat) >>> 0) >>> b.blitbshift) & 0xffff; prevb = bltbdat; } - if (pta) { bltadat = blt_info.bltadat = AMIGA.mem.load16_chip(pta); pta += 2; } else { bltadat = blt_info.bltadat; } + if (pta) { bltadat = blt_info.bltadat = AMIGA.mem.chip.data[pta >>> 1]; pta += 2; } else { bltadat = blt_info.bltadat; } bltadat &= blit_masktable[i]; srca = ((((preva << 16) | bltadat) >>> 0) >>> b.blitashift) & 0xffff; preva = bltadat; - if (dstp) AMIGA.mem.store16_chip(dstp, dstd); + if (dstp) AMIGA.mem.chip.data[dstp >>> 1] = dstd; dstd = ((srcb ^ (srca | (srcb ^ srcc)))) & 0xffff; totald |= dstd; if (ptd) { dstp = ptd; ptd += 2; } @@ -504,7 +472,7 @@ function Blitter() { } b.bltbhold = srcb; b.bltcdat = srcc; - if (dstp) AMIGA.mem.store16_chip(dstp, dstd); + if (dstp) AMIGA.mem.chip.data[dstp >>> 1] = dstd; if (totald != 0) b.blitzero = 0; } @@ -519,17 +487,17 @@ function Blitter() { for (j = 0; j < b.vblitsize; j++) { for (i = 0; i < b.hblitsize; i++) { var bltadat, srca; - if (ptc) { srcc = AMIGA.mem.load16_chip(ptc); ptc -= 2; } + if (ptc) { srcc = AMIGA.mem.chip.data[ptc >>> 1]; ptc -= 2; } if (ptb) { - var bltbdat = blt_info.bltbdat = AMIGA.mem.load16_chip(ptb); ptb -= 2; + var bltbdat = blt_info.bltbdat = AMIGA.mem.chip.data[ptb >>> 1]; ptb -= 2; srcb = ((((bltbdat << 16) | prevb) >>> 0) >>> b.blitdownbshift) & 0xffff; prevb = bltbdat; } - if (pta) { bltadat = blt_info.bltadat = AMIGA.mem.load16_chip(pta); pta -= 2; } else { bltadat = blt_info.bltadat; } + if (pta) { bltadat = blt_info.bltadat = AMIGA.mem.chip.data[pta >>> 1]; pta -= 2; } else { bltadat = blt_info.bltadat; } bltadat &= blit_masktable[i]; srca = ((((bltadat << 16) | preva) >>> 0) >>> b.blitdownashift) & 0xffff; preva = bltadat; - if (dstp) AMIGA.mem.store16_chip(dstp, dstd); + if (dstp) AMIGA.mem.chip.data[dstp >>> 1] = dstd; dstd = ((srcb ^ (srca | (srcb ^ srcc)))) & 0xffff; totald |= dstd; if (ptd) { dstp = ptd; ptd -= 2; } @@ -541,7 +509,7 @@ function Blitter() { } b.bltbhold = srcb; b.bltcdat = srcc; - if (dstp) AMIGA.mem.store16_chip(dstp, dstd); + if (dstp) AMIGA.mem.chip.data[dstp >>> 1] = dstd; if (totald != 0) b.blitzero = 0; } @@ -550,22 +518,22 @@ function Blitter() { var totald = 0; var preva = 0; var prevb = 0, srcb = b.bltbhold; - var dstd=0; + var dstd = 0; var dstp = 0; for (j = 0; j < b.vblitsize; j++) { for (i = 0; i < b.hblitsize; i++) { var bltadat, srca; if (ptb) { - var bltbdat = blt_info.bltbdat = AMIGA.mem.load16_chip(ptb); ptb += 2; + var bltbdat = blt_info.bltbdat = AMIGA.mem.chip.data[ptb >>> 1]; ptb += 2; srcb = ((((prevb << 16) | bltbdat) >>> 0) >>> b.blitbshift) & 0xffff; prevb = bltbdat; } - if (pta) { bltadat = blt_info.bltadat = AMIGA.mem.load16_chip(pta); pta += 2; } else { bltadat = blt_info.bltadat; } + if (pta) { bltadat = blt_info.bltadat = AMIGA.mem.chip.data[pta >>> 1]; pta += 2; } else { bltadat = blt_info.bltadat; } bltadat &= blit_masktable[i]; srca = ((((preva << 16) | bltadat) >>> 0) >>> b.blitashift) & 0xffff; preva = bltadat; - if (dstp) AMIGA.mem.store16_chip(dstp, dstd); + if (dstp) AMIGA.mem.chip.data[dstp >>> 1] = dstd; dstd = ((srca ^ srcb)) & 0xffff; totald |= dstd; if (ptd) { dstp = ptd; ptd += 2; } @@ -575,7 +543,7 @@ function Blitter() { if (ptd) ptd += b.bltdmod; } b.bltbhold = srcb; - if (dstp) AMIGA.mem.store16_chip(dstp, dstd); + if (dstp) AMIGA.mem.chip.data[dstp >>> 1] = dstd; if (totald != 0) b.blitzero = 0; } @@ -590,15 +558,15 @@ function Blitter() { for (i = 0; i < b.hblitsize; i++) { var bltadat, srca; if (ptb) { - var bltbdat = blt_info.bltbdat = AMIGA.mem.load16_chip(ptb); ptb -= 2; + var bltbdat = blt_info.bltbdat = AMIGA.mem.chip.data[ptb >>> 1]; ptb -= 2; srcb = ((((bltbdat << 16) | prevb) >>> 0) >>> b.blitdownbshift) & 0xffff; prevb = bltbdat; } - if (pta) { bltadat = blt_info.bltadat = AMIGA.mem.load16_chip(pta); pta -= 2; } else { bltadat = blt_info.bltadat; } + if (pta) { bltadat = blt_info.bltadat = AMIGA.mem.chip.data[pta >>> 1]; pta -= 2; } else { bltadat = blt_info.bltadat; } bltadat &= blit_masktable[i]; srca = ((((bltadat << 16) | preva) >>> 0) >>> b.blitdownashift) & 0xffff; preva = bltadat; - if (dstp) AMIGA.mem.store16_chip(dstp, dstd); + if (dstp) AMIGA.mem.chip.data[dstp >>> 1] = dstd; dstd = ((srca ^ srcb)) & 0xffff; totald |= dstd; if (ptd) { dstp = ptd; ptd -= 2; } @@ -608,7 +576,7 @@ function Blitter() { if (ptd) ptd -= b.bltdmod; } b.bltbhold = srcb; - if (dstp) AMIGA.mem.store16_chip(dstp, dstd); + if (dstp) AMIGA.mem.chip.data[dstp >>> 1] = dstd; if (totald != 0) b.blitzero = 0; } @@ -618,23 +586,23 @@ function Blitter() { var preva = 0; var prevb = 0, srcb = b.bltbhold; var srcc = b.bltcdat; - var dstd=0; + var dstd = 0; var dstp = 0; for (j = 0; j < b.vblitsize; j++) { for (i = 0; i < b.hblitsize; i++) { var bltadat, srca; - if (ptc) { srcc = AMIGA.mem.load16_chip(ptc); ptc += 2; } + if (ptc) { srcc = AMIGA.mem.chip.data[ptc >>> 1]; ptc += 2; } if (ptb) { - var bltbdat = blt_info.bltbdat = AMIGA.mem.load16_chip(ptb); ptb += 2; + var bltbdat = blt_info.bltbdat = AMIGA.mem.chip.data[ptb >>> 1]; ptb += 2; srcb = ((((prevb << 16) | bltbdat) >>> 0) >>> b.blitbshift) & 0xffff; prevb = bltbdat; } - if (pta) { bltadat = blt_info.bltadat = AMIGA.mem.load16_chip(pta); pta += 2; } else { bltadat = blt_info.bltadat; } + if (pta) { bltadat = blt_info.bltadat = AMIGA.mem.chip.data[pta >>> 1]; pta += 2; } else { bltadat = blt_info.bltadat; } bltadat &= blit_masktable[i]; srca = ((((preva << 16) | bltadat) >>> 0) >>> b.blitashift) & 0xffff; preva = bltadat; - if (dstp) AMIGA.mem.store16_chip(dstp, dstd); + if (dstp) AMIGA.mem.chip.data[dstp >>> 1] = dstd; dstd = ((srcc ^ (srca & (srcb | srcc)))) & 0xffff; totald |= dstd; if (ptd) { dstp = ptd; ptd += 2; } @@ -646,7 +614,7 @@ function Blitter() { } b.bltbhold = srcb; b.bltcdat = srcc; - if (dstp) AMIGA.mem.store16_chip(dstp, dstd); + if (dstp) AMIGA.mem.chip.data[dstp >>> 1] = dstd; if (totald != 0) b.blitzero = 0; } @@ -661,17 +629,17 @@ function Blitter() { for (j = 0; j < b.vblitsize; j++) { for (i = 0; i < b.hblitsize; i++) { var bltadat, srca; - if (ptc) { srcc = AMIGA.mem.load16_chip(ptc); ptc -= 2; } + if (ptc) { srcc = AMIGA.mem.chip.data[ptc >>> 1]; ptc -= 2; } if (ptb) { - var bltbdat = blt_info.bltbdat = AMIGA.mem.load16_chip(ptb); ptb -= 2; + var bltbdat = blt_info.bltbdat = AMIGA.mem.chip.data[ptb >>> 1]; ptb -= 2; srcb = ((((bltbdat << 16) | prevb) >>> 0) >>> b.blitdownbshift) & 0xffff; prevb = bltbdat; } - if (pta) { bltadat = blt_info.bltadat = AMIGA.mem.load16_chip(pta); pta -= 2; } else { bltadat = blt_info.bltadat; } + if (pta) { bltadat = blt_info.bltadat = AMIGA.mem.chip.data[pta >>> 1]; pta -= 2; } else { bltadat = blt_info.bltadat; } bltadat &= blit_masktable[i]; srca = ((((bltadat << 16) | preva) >>> 0) >>> b.blitdownashift) & 0xffff; preva = bltadat; - if (dstp) AMIGA.mem.store16_chip(dstp, dstd); + if (dstp) AMIGA.mem.chip.data[dstp >>> 1] = dstd; dstd = ((srcc ^ (srca & (srcb | srcc)))) & 0xffff; totald |= dstd; if (ptd) { dstp = ptd; ptd -= 2; } @@ -683,7 +651,7 @@ function Blitter() { } b.bltbhold = srcb; b.bltcdat = srcc; - if (dstp) AMIGA.mem.store16_chip(dstp, dstd); + if (dstp) AMIGA.mem.chip.data[dstp >>> 1] = dstd; if (totald != 0) b.blitzero = 0; } @@ -693,23 +661,23 @@ function Blitter() { var preva = 0; var prevb = 0, srcb = b.bltbhold; var srcc = b.bltcdat; - var dstd=0; + var dstd = 0; var dstp = 0; for (j = 0; j < b.vblitsize; j++) { for (i = 0; i < b.hblitsize; i++) { var bltadat, srca; - if (ptc) { srcc = AMIGA.mem.load16_chip(ptc); ptc += 2; } + if (ptc) { srcc = AMIGA.mem.chip.data[ptc >>> 1]; ptc += 2; } if (ptb) { - var bltbdat = blt_info.bltbdat = AMIGA.mem.load16_chip(ptb); ptb += 2; + var bltbdat = blt_info.bltbdat = AMIGA.mem.chip.data[ptb >>> 1]; ptb += 2; srcb = ((((prevb << 16) | bltbdat) >>> 0) >>> b.blitbshift) & 0xffff; prevb = bltbdat; } - if (pta) { bltadat = blt_info.bltadat = AMIGA.mem.load16_chip(pta); pta += 2; } else { bltadat = blt_info.bltadat; } + if (pta) { bltadat = blt_info.bltadat = AMIGA.mem.chip.data[pta >>> 1]; pta += 2; } else { bltadat = blt_info.bltadat; } bltadat &= blit_masktable[i]; srca = ((((preva << 16) | bltadat) >>> 0) >>> b.blitashift) & 0xffff; preva = bltadat; - if (dstp) AMIGA.mem.store16_chip(dstp, dstd); + if (dstp) AMIGA.mem.chip.data[dstp >>> 1] = dstd; dstd = ((srcc ^ (srca & srcb))) & 0xffff; totald |= dstd; if (ptd) { dstp = ptd; ptd += 2; } @@ -721,7 +689,7 @@ function Blitter() { } b.bltbhold = srcb; b.bltcdat = srcc; - if (dstp) AMIGA.mem.store16_chip(dstp, dstd); + if (dstp) AMIGA.mem.chip.data[dstp >>> 1] = dstd; if (totald != 0) b.blitzero = 0; } @@ -736,17 +704,17 @@ function Blitter() { for (j = 0; j < b.vblitsize; j++) { for (i = 0; i < b.hblitsize; i++) { var bltadat, srca; - if (ptc) { srcc = AMIGA.mem.load16_chip(ptc); ptc -= 2; } + if (ptc) { srcc = AMIGA.mem.chip.data[ptc >>> 1]; ptc -= 2; } if (ptb) { - var bltbdat = blt_info.bltbdat = AMIGA.mem.load16_chip(ptb); ptb -= 2; + var bltbdat = blt_info.bltbdat = AMIGA.mem.chip.data[ptb >>> 1]; ptb -= 2; srcb = ((((bltbdat << 16) | prevb) >>> 0) >>> b.blitdownbshift) & 0xffff; prevb = bltbdat; } - if (pta) { bltadat = blt_info.bltadat = AMIGA.mem.load16_chip(pta); pta -= 2; } else { bltadat = blt_info.bltadat; } + if (pta) { bltadat = blt_info.bltadat = AMIGA.mem.chip.data[pta >>> 1]; pta -= 2; } else { bltadat = blt_info.bltadat; } bltadat &= blit_masktable[i]; srca = ((((bltadat << 16) | preva) >>> 0) >>> b.blitdownashift) & 0xffff; preva = bltadat; - if (dstp) AMIGA.mem.store16_chip(dstp, dstd); + if (dstp) AMIGA.mem.chip.data[dstp >>> 1] = dstd; dstd = ((srcc ^ (srca & srcb))) & 0xffff; totald |= dstd; if (ptd) { dstp = ptd; ptd -= 2; } @@ -758,7 +726,7 @@ function Blitter() { } b.bltbhold = srcb; b.bltcdat = srcc; - if (dstp) AMIGA.mem.store16_chip(dstp, dstd); + if (dstp) AMIGA.mem.chip.data[dstp >>> 1] = dstd; if (totald != 0) b.blitzero = 0; } @@ -768,23 +736,23 @@ function Blitter() { var preva = 0; var prevb = 0, srcb = b.bltbhold; var srcc = b.bltcdat; - var dstd=0; + var dstd = 0; var dstp = 0; for (j = 0; j < b.vblitsize; j++) { for (i = 0; i < b.hblitsize; i++) { var bltadat, srca; - if (ptc) { srcc = AMIGA.mem.load16_chip(ptc); ptc += 2; } + if (ptc) { srcc = AMIGA.mem.chip.data[ptc >>> 1]; ptc += 2; } if (ptb) { - var bltbdat = blt_info.bltbdat = AMIGA.mem.load16_chip(ptb); ptb += 2; + var bltbdat = blt_info.bltbdat = AMIGA.mem.chip.data[ptb >>> 1]; ptb += 2; srcb = ((((prevb << 16) | bltbdat) >>> 0) >>> b.blitbshift) & 0xffff; prevb = bltbdat; } - if (pta) { bltadat = blt_info.bltadat = AMIGA.mem.load16_chip(pta); pta += 2; } else { bltadat = blt_info.bltadat; } + if (pta) { bltadat = blt_info.bltadat = AMIGA.mem.chip.data[pta >>> 1]; pta += 2; } else { bltadat = blt_info.bltadat; } bltadat &= blit_masktable[i]; srca = ((((preva << 16) | bltadat) >>> 0) >>> b.blitashift) & 0xffff; preva = bltadat; - if (dstp) AMIGA.mem.store16_chip(dstp, dstd); + if (dstp) AMIGA.mem.chip.data[dstp >>> 1] = dstd; dstd = ((srcc & (~srca | srcb))) & 0xffff; totald |= dstd; if (ptd) { dstp = ptd; ptd += 2; } @@ -796,7 +764,7 @@ function Blitter() { } b.bltbhold = srcb; b.bltcdat = srcc; - if (dstp) AMIGA.mem.store16_chip(dstp, dstd); + if (dstp) AMIGA.mem.chip.data[dstp >>> 1] = dstd; if (totald != 0) b.blitzero = 0; } @@ -811,17 +779,17 @@ function Blitter() { for (j = 0; j < b.vblitsize; j++) { for (i = 0; i < b.hblitsize; i++) { var bltadat, srca; - if (ptc) { srcc = AMIGA.mem.load16_chip(ptc); ptc -= 2; } + if (ptc) { srcc = AMIGA.mem.chip.data[ptc >>> 1]; ptc -= 2; } if (ptb) { - var bltbdat = blt_info.bltbdat = AMIGA.mem.load16_chip(ptb); ptb -= 2; + var bltbdat = blt_info.bltbdat = AMIGA.mem.chip.data[ptb >>> 1]; ptb -= 2; srcb = ((((bltbdat << 16) | prevb) >>> 0) >>> b.blitdownbshift) & 0xffff; prevb = bltbdat; } - if (pta) { bltadat = blt_info.bltadat = AMIGA.mem.load16_chip(pta); pta -= 2; } else { bltadat = blt_info.bltadat; } + if (pta) { bltadat = blt_info.bltadat = AMIGA.mem.chip.data[pta >>> 1]; pta -= 2; } else { bltadat = blt_info.bltadat; } bltadat &= blit_masktable[i]; srca = ((((bltadat << 16) | preva) >>> 0) >>> b.blitdownashift) & 0xffff; preva = bltadat; - if (dstp) AMIGA.mem.store16_chip(dstp, dstd); + if (dstp) AMIGA.mem.chip.data[dstp >>> 1] = dstd; dstd = ((srcc & (~srca | srcb))) & 0xffff; totald |= dstd; if (ptd) { dstp = ptd; ptd -= 2; } @@ -833,7 +801,7 @@ function Blitter() { } b.bltbhold = srcb; b.bltcdat = srcc; - if (dstp) AMIGA.mem.store16_chip(dstp, dstd); + if (dstp) AMIGA.mem.chip.data[dstp >>> 1] = dstd; if (totald != 0) b.blitzero = 0; } @@ -843,23 +811,23 @@ function Blitter() { var preva = 0; var prevb = 0, srcb = b.bltbhold; var srcc = b.bltcdat; - var dstd=0; + var dstd = 0; var dstp = 0; for (j = 0; j < b.vblitsize; j++) { for (i = 0; i < b.hblitsize; i++) { var bltadat, srca; - if (ptc) { srcc = AMIGA.mem.load16_chip(ptc); ptc += 2; } + if (ptc) { srcc = AMIGA.mem.chip.data[ptc >>> 1]; ptc += 2; } if (ptb) { - var bltbdat = blt_info.bltbdat = AMIGA.mem.load16_chip(ptb); ptb += 2; + var bltbdat = blt_info.bltbdat = AMIGA.mem.chip.data[ptb >>> 1]; ptb += 2; srcb = ((((prevb << 16) | bltbdat) >>> 0) >>> b.blitbshift) & 0xffff; prevb = bltbdat; } - if (pta) { bltadat = blt_info.bltadat = AMIGA.mem.load16_chip(pta); pta += 2; } else { bltadat = blt_info.bltadat; } + if (pta) { bltadat = blt_info.bltadat = AMIGA.mem.chip.data[pta >>> 1]; pta += 2; } else { bltadat = blt_info.bltadat; } bltadat &= blit_masktable[i]; srca = ((((preva << 16) | bltadat) >>> 0) >>> b.blitashift) & 0xffff; preva = bltadat; - if (dstp) AMIGA.mem.store16_chip(dstp, dstd); + if (dstp) AMIGA.mem.chip.data[dstp >>> 1] = dstd; dstd = ((srcb & (~srca | srcc))) & 0xffff; totald |= dstd; if (ptd) { dstp = ptd; ptd += 2; } @@ -871,7 +839,7 @@ function Blitter() { } b.bltbhold = srcb; b.bltcdat = srcc; - if (dstp) AMIGA.mem.store16_chip(dstp, dstd); + if (dstp) AMIGA.mem.chip.data[dstp >>> 1] = dstd; if (totald != 0) b.blitzero = 0; } @@ -886,17 +854,17 @@ function Blitter() { for (j = 0; j < b.vblitsize; j++) { for (i = 0; i < b.hblitsize; i++) { var bltadat, srca; - if (ptc) { srcc = AMIGA.mem.load16_chip(ptc); ptc -= 2; } + if (ptc) { srcc = AMIGA.mem.chip.data[ptc >>> 1]; ptc -= 2; } if (ptb) { - var bltbdat = blt_info.bltbdat = AMIGA.mem.load16_chip(ptb); ptb -= 2; + var bltbdat = blt_info.bltbdat = AMIGA.mem.chip.data[ptb >>> 1]; ptb -= 2; srcb = ((((bltbdat << 16) | prevb) >>> 0) >>> b.blitdownbshift) & 0xffff; prevb = bltbdat; } - if (pta) { bltadat = blt_info.bltadat = AMIGA.mem.load16_chip(pta); pta -= 2; } else { bltadat = blt_info.bltadat; } + if (pta) { bltadat = blt_info.bltadat = AMIGA.mem.chip.data[pta >>> 1]; pta -= 2; } else { bltadat = blt_info.bltadat; } bltadat &= blit_masktable[i]; srca = ((((bltadat << 16) | preva) >>> 0) >>> b.blitdownashift) & 0xffff; preva = bltadat; - if (dstp) AMIGA.mem.store16_chip(dstp, dstd); + if (dstp) AMIGA.mem.chip.data[dstp >>> 1] = dstd; dstd = ((srcb & (~srca | srcc))) & 0xffff; totald |= dstd; if (ptd) { dstp = ptd; ptd -= 2; } @@ -908,7 +876,7 @@ function Blitter() { } b.bltbhold = srcb; b.bltcdat = srcc; - if (dstp) AMIGA.mem.store16_chip(dstp, dstd); + if (dstp) AMIGA.mem.chip.data[dstp >>> 1] = dstd; if (totald != 0) b.blitzero = 0; } @@ -918,23 +886,23 @@ function Blitter() { var preva = 0; var prevb = 0, srcb = b.bltbhold; var srcc = b.bltcdat; - var dstd=0; + var dstd = 0; var dstp = 0; for (j = 0; j < b.vblitsize; j++) { for (i = 0; i < b.hblitsize; i++) { var bltadat, srca; - if (ptc) { srcc = AMIGA.mem.load16_chip(ptc); ptc += 2; } + if (ptc) { srcc = AMIGA.mem.chip.data[ptc >>> 1]; ptc += 2; } if (ptb) { - var bltbdat = blt_info.bltbdat = AMIGA.mem.load16_chip(ptb); ptb += 2; + var bltbdat = blt_info.bltbdat = AMIGA.mem.chip.data[ptb >>> 1]; ptb += 2; srcb = ((((prevb << 16) | bltbdat) >>> 0) >>> b.blitbshift) & 0xffff; prevb = bltbdat; } - if (pta) { bltadat = blt_info.bltadat = AMIGA.mem.load16_chip(pta); pta += 2; } else { bltadat = blt_info.bltadat; } + if (pta) { bltadat = blt_info.bltadat = AMIGA.mem.chip.data[pta >>> 1]; pta += 2; } else { bltadat = blt_info.bltadat; } bltadat &= blit_masktable[i]; srca = ((((preva << 16) | bltadat) >>> 0) >>> b.blitashift) & 0xffff; preva = bltadat; - if (dstp) AMIGA.mem.store16_chip(dstp, dstd); + if (dstp) AMIGA.mem.chip.data[dstp >>> 1] = dstd; dstd = ((srcc ^ (srca & ~srcb))) & 0xffff; totald |= dstd; if (ptd) { dstp = ptd; ptd += 2; } @@ -946,7 +914,7 @@ function Blitter() { } b.bltbhold = srcb; b.bltcdat = srcc; - if (dstp) AMIGA.mem.store16_chip(dstp, dstd); + if (dstp) AMIGA.mem.chip.data[dstp >>> 1] = dstd; if (totald != 0) b.blitzero = 0; } @@ -961,17 +929,17 @@ function Blitter() { for (j = 0; j < b.vblitsize; j++) { for (i = 0; i < b.hblitsize; i++) { var bltadat, srca; - if (ptc) { srcc = AMIGA.mem.load16_chip(ptc); ptc -= 2; } + if (ptc) { srcc = AMIGA.mem.chip.data[ptc >>> 1]; ptc -= 2; } if (ptb) { - var bltbdat = blt_info.bltbdat = AMIGA.mem.load16_chip(ptb); ptb -= 2; + var bltbdat = blt_info.bltbdat = AMIGA.mem.chip.data[ptb >>> 1]; ptb -= 2; srcb = ((((bltbdat << 16) | prevb) >>> 0) >>> b.blitdownbshift) & 0xffff; prevb = bltbdat; } - if (pta) { bltadat = blt_info.bltadat = AMIGA.mem.load16_chip(pta); pta -= 2; } else { bltadat = blt_info.bltadat; } + if (pta) { bltadat = blt_info.bltadat = AMIGA.mem.chip.data[pta >>> 1]; pta -= 2; } else { bltadat = blt_info.bltadat; } bltadat &= blit_masktable[i]; srca = ((((bltadat << 16) | preva) >>> 0) >>> b.blitdownashift) & 0xffff; preva = bltadat; - if (dstp) AMIGA.mem.store16_chip(dstp, dstd); + if (dstp) AMIGA.mem.chip.data[dstp >>> 1] = dstd; dstd = ((srcc ^ (srca & ~srcb))) & 0xffff; totald |= dstd; if (ptd) { dstp = ptd; ptd -= 2; } @@ -983,7 +951,7 @@ function Blitter() { } b.bltbhold = srcb; b.bltcdat = srcc; - if (dstp) AMIGA.mem.store16_chip(dstp, dstd); + if (dstp) AMIGA.mem.chip.data[dstp >>> 1] = dstd; if (totald != 0) b.blitzero = 0; } @@ -993,23 +961,23 @@ function Blitter() { var preva = 0; var prevb = 0, srcb = b.bltbhold; var srcc = b.bltcdat; - var dstd=0; + var dstd = 0; var dstp = 0; for (j = 0; j < b.vblitsize; j++) { for (i = 0; i < b.hblitsize; i++) { var bltadat, srca; - if (ptc) { srcc = AMIGA.mem.load16_chip(ptc); ptc += 2; } + if (ptc) { srcc = AMIGA.mem.chip.data[ptc >>> 1]; ptc += 2; } if (ptb) { - var bltbdat = blt_info.bltbdat = AMIGA.mem.load16_chip(ptb); ptb += 2; + var bltbdat = blt_info.bltbdat = AMIGA.mem.chip.data[ptb >>> 1]; ptb += 2; srcb = ((((prevb << 16) | bltbdat) >>> 0) >>> b.blitbshift) & 0xffff; prevb = bltbdat; } - if (pta) { bltadat = blt_info.bltadat = AMIGA.mem.load16_chip(pta); pta += 2; } else { bltadat = blt_info.bltadat; } + if (pta) { bltadat = blt_info.bltadat = AMIGA.mem.chip.data[pta >>> 1]; pta += 2; } else { bltadat = blt_info.bltadat; } bltadat &= blit_masktable[i]; srca = ((((preva << 16) | bltadat) >>> 0) >>> b.blitashift) & 0xffff; preva = bltadat; - if (dstp) AMIGA.mem.store16_chip(dstp, dstd); + if (dstp) AMIGA.mem.chip.data[dstp >>> 1] = dstd; dstd = ((srcc & (srca | srcb))) & 0xffff; totald |= dstd; if (ptd) { dstp = ptd; ptd += 2; } @@ -1021,7 +989,7 @@ function Blitter() { } b.bltbhold = srcb; b.bltcdat = srcc; - if (dstp) AMIGA.mem.store16_chip(dstp, dstd); + if (dstp) AMIGA.mem.chip.data[dstp >>> 1] = dstd; if (totald != 0) b.blitzero = 0; } @@ -1036,17 +1004,17 @@ function Blitter() { for (j = 0; j < b.vblitsize; j++) { for (i = 0; i < b.hblitsize; i++) { var bltadat, srca; - if (ptc) { srcc = AMIGA.mem.load16_chip(ptc); ptc -= 2; } + if (ptc) { srcc = AMIGA.mem.chip.data[ptc >>> 1]; ptc -= 2; } if (ptb) { - var bltbdat = blt_info.bltbdat = AMIGA.mem.load16_chip(ptb); ptb -= 2; + var bltbdat = blt_info.bltbdat = AMIGA.mem.chip.data[ptb >>> 1]; ptb -= 2; srcb = ((((bltbdat << 16) | prevb) >>> 0) >>> b.blitdownbshift) & 0xffff; prevb = bltbdat; } - if (pta) { bltadat = blt_info.bltadat = AMIGA.mem.load16_chip(pta); pta -= 2; } else { bltadat = blt_info.bltadat; } + if (pta) { bltadat = blt_info.bltadat = AMIGA.mem.chip.data[pta >>> 1]; pta -= 2; } else { bltadat = blt_info.bltadat; } bltadat &= blit_masktable[i]; srca = ((((bltadat << 16) | preva) >>> 0) >>> b.blitdownashift) & 0xffff; preva = bltadat; - if (dstp) AMIGA.mem.store16_chip(dstp, dstd); + if (dstp) AMIGA.mem.chip.data[dstp >>> 1] = dstd; dstd = ((srcc & (srca | srcb))) & 0xffff; totald |= dstd; if (ptd) { dstp = ptd; ptd -= 2; } @@ -1058,7 +1026,7 @@ function Blitter() { } b.bltbhold = srcb; b.bltcdat = srcc; - if (dstp) AMIGA.mem.store16_chip(dstp, dstd); + if (dstp) AMIGA.mem.chip.data[dstp >>> 1] = dstd; if (totald != 0) b.blitzero = 0; } @@ -1066,14 +1034,14 @@ function Blitter() { var i,j; var totald = 0; var srcc = b.bltcdat; - var dstd=0; + var dstd = 0; var dstp = 0; for (j = 0; j < b.vblitsize; j++) { for (i = 0; i < b.hblitsize; i++) { var bltadat, srca; - if (ptc) { srcc = AMIGA.mem.load16_chip(ptc); ptc += 2; } - if (dstp) AMIGA.mem.store16_chip(dstp, dstd); + if (ptc) { srcc = AMIGA.mem.chip.data[ptc >>> 1]; ptc += 2; } + if (dstp) AMIGA.mem.chip.data[dstp >>> 1] = dstd; dstd = (srcc) & 0xffff; totald |= dstd; if (ptd) { dstp = ptd; ptd += 2; } @@ -1082,7 +1050,7 @@ function Blitter() { if (ptd) ptd += b.bltdmod; } b.bltcdat = srcc; - if (dstp) AMIGA.mem.store16_chip(dstp, dstd); + if (dstp) AMIGA.mem.chip.data[dstp >>> 1] = dstd; if (totald != 0) b.blitzero = 0; } @@ -1095,8 +1063,8 @@ function Blitter() { for (j = 0; j < b.vblitsize; j++) { for (i = 0; i < b.hblitsize; i++) { var bltadat, srca; - if (ptc) { srcc = AMIGA.mem.load16_chip(ptc); ptc -= 2; } - if (dstp) AMIGA.mem.store16_chip(dstp, dstd); + if (ptc) { srcc = AMIGA.mem.chip.data[ptc >>> 1]; ptc -= 2; } + if (dstp) AMIGA.mem.chip.data[dstp >>> 1] = dstd; dstd = (srcc) & 0xffff; totald |= dstd; if (ptd) { dstp = ptd; ptd -= 2; } @@ -1105,7 +1073,7 @@ function Blitter() { if (ptd) ptd -= b.bltdmod; } b.bltcdat = srcc; - if (dstp) AMIGA.mem.store16_chip(dstp, dstd); + if (dstp) AMIGA.mem.chip.data[dstp >>> 1] = dstd; if (totald != 0) b.blitzero = 0; } @@ -1115,23 +1083,23 @@ function Blitter() { var preva = 0; var prevb = 0, srcb = b.bltbhold; var srcc = b.bltcdat; - var dstd=0; + var dstd = 0; var dstp = 0; for (j = 0; j < b.vblitsize; j++) { for (i = 0; i < b.hblitsize; i++) { var bltadat, srca; - if (ptc) { srcc = AMIGA.mem.load16_chip(ptc); ptc += 2; } + if (ptc) { srcc = AMIGA.mem.chip.data[ptc >>> 1]; ptc += 2; } if (ptb) { - var bltbdat = blt_info.bltbdat = AMIGA.mem.load16_chip(ptb); ptb += 2; + var bltbdat = blt_info.bltbdat = AMIGA.mem.chip.data[ptb >>> 1]; ptb += 2; srcb = ((((prevb << 16) | bltbdat) >>> 0) >>> b.blitbshift) & 0xffff; prevb = bltbdat; } - if (pta) { bltadat = blt_info.bltadat = AMIGA.mem.load16_chip(pta); pta += 2; } else { bltadat = blt_info.bltadat; } + if (pta) { bltadat = blt_info.bltadat = AMIGA.mem.chip.data[pta >>> 1]; pta += 2; } else { bltadat = blt_info.bltadat; } bltadat &= blit_masktable[i]; srca = ((((preva << 16) | bltadat) >>> 0) >>> b.blitashift) & 0xffff; preva = bltadat; - if (dstp) AMIGA.mem.store16_chip(dstp, dstd); + if (dstp) AMIGA.mem.chip.data[dstp >>> 1] = dstd; dstd = (~(srca ^ (srcc | (srca ^ srcb)))) & 0xffff; totald |= dstd; if (ptd) { dstp = ptd; ptd += 2; } @@ -1143,7 +1111,7 @@ function Blitter() { } b.bltbhold = srcb; b.bltcdat = srcc; - if (dstp) AMIGA.mem.store16_chip(dstp, dstd); + if (dstp) AMIGA.mem.chip.data[dstp >>> 1] = dstd; if (totald != 0) b.blitzero = 0; } @@ -1158,17 +1126,17 @@ function Blitter() { for (j = 0; j < b.vblitsize; j++) { for (i = 0; i < b.hblitsize; i++) { var bltadat, srca; - if (ptc) { srcc = AMIGA.mem.load16_chip(ptc); ptc -= 2; } + if (ptc) { srcc = AMIGA.mem.chip.data[ptc >>> 1]; ptc -= 2; } if (ptb) { - var bltbdat = blt_info.bltbdat = AMIGA.mem.load16_chip(ptb); ptb -= 2; + var bltbdat = blt_info.bltbdat = AMIGA.mem.chip.data[ptb >>> 1]; ptb -= 2; srcb = ((((bltbdat << 16) | prevb) >>> 0) >>> b.blitdownbshift) & 0xffff; prevb = bltbdat; } - if (pta) { bltadat = blt_info.bltadat = AMIGA.mem.load16_chip(pta); pta -= 2; } else { bltadat = blt_info.bltadat; } + if (pta) { bltadat = blt_info.bltadat = AMIGA.mem.chip.data[pta >>> 1]; pta -= 2; } else { bltadat = blt_info.bltadat; } bltadat &= blit_masktable[i]; srca = ((((bltadat << 16) | preva) >>> 0) >>> b.blitdownashift) & 0xffff; preva = bltadat; - if (dstp) AMIGA.mem.store16_chip(dstp, dstd); + if (dstp) AMIGA.mem.chip.data[dstp >>> 1] = dstd; dstd = (~(srca ^ (srcc | (srca ^ srcb)))) & 0xffff; totald |= dstd; if (ptd) { dstp = ptd; ptd -= 2; } @@ -1180,7 +1148,7 @@ function Blitter() { } b.bltbhold = srcb; b.bltcdat = srcc; - if (dstp) AMIGA.mem.store16_chip(dstp, dstd); + if (dstp) AMIGA.mem.chip.data[dstp >>> 1] = dstd; if (totald != 0) b.blitzero = 0; } @@ -1190,23 +1158,23 @@ function Blitter() { var preva = 0; var prevb = 0, srcb = b.bltbhold; var srcc = b.bltcdat; - var dstd=0; + var dstd = 0; var dstp = 0; for (j = 0; j < b.vblitsize; j++) { for (i = 0; i < b.hblitsize; i++) { var bltadat, srca; - if (ptc) { srcc = AMIGA.mem.load16_chip(ptc); ptc += 2; } + if (ptc) { srcc = AMIGA.mem.chip.data[ptc >>> 1]; ptc += 2; } if (ptb) { - var bltbdat = blt_info.bltbdat = AMIGA.mem.load16_chip(ptb); ptb += 2; + var bltbdat = blt_info.bltbdat = AMIGA.mem.chip.data[ptb >>> 1]; ptb += 2; srcb = ((((prevb << 16) | bltbdat) >>> 0) >>> b.blitbshift) & 0xffff; prevb = bltbdat; } - if (pta) { bltadat = blt_info.bltadat = AMIGA.mem.load16_chip(pta); pta += 2; } else { bltadat = blt_info.bltadat; } + if (pta) { bltadat = blt_info.bltadat = AMIGA.mem.chip.data[pta >>> 1]; pta += 2; } else { bltadat = blt_info.bltadat; } bltadat &= blit_masktable[i]; srca = ((((preva << 16) | bltadat) >>> 0) >>> b.blitashift) & 0xffff; preva = bltadat; - if (dstp) AMIGA.mem.store16_chip(dstp, dstd); + if (dstp) AMIGA.mem.chip.data[dstp >>> 1] = dstd; dstd = ((srcc ^ (srca & (srcb ^ srcc)))) & 0xffff; totald |= dstd; if (ptd) { dstp = ptd; ptd += 2; } @@ -1218,7 +1186,7 @@ function Blitter() { } b.bltbhold = srcb; b.bltcdat = srcc; - if (dstp) AMIGA.mem.store16_chip(dstp, dstd); + if (dstp) AMIGA.mem.chip.data[dstp >>> 1] = dstd; if (totald != 0) b.blitzero = 0; } @@ -1233,17 +1201,17 @@ function Blitter() { for (j = 0; j < b.vblitsize; j++) { for (i = 0; i < b.hblitsize; i++) { var bltadat, srca; - if (ptc) { srcc = AMIGA.mem.load16_chip(ptc); ptc -= 2; } + if (ptc) { srcc = AMIGA.mem.chip.data[ptc >>> 1]; ptc -= 2; } if (ptb) { - var bltbdat = blt_info.bltbdat = AMIGA.mem.load16_chip(ptb); ptb -= 2; + var bltbdat = blt_info.bltbdat = AMIGA.mem.chip.data[ptb >>> 1]; ptb -= 2; srcb = ((((bltbdat << 16) | prevb) >>> 0) >>> b.blitdownbshift) & 0xffff; prevb = bltbdat; } - if (pta) { bltadat = blt_info.bltadat = AMIGA.mem.load16_chip(pta); pta -= 2; } else { bltadat = blt_info.bltadat; } + if (pta) { bltadat = blt_info.bltadat = AMIGA.mem.chip.data[pta >>> 1]; pta -= 2; } else { bltadat = blt_info.bltadat; } bltadat &= blit_masktable[i]; srca = ((((bltadat << 16) | preva) >>> 0) >>> b.blitdownashift) & 0xffff; preva = bltadat; - if (dstp) AMIGA.mem.store16_chip(dstp, dstd); + if (dstp) AMIGA.mem.chip.data[dstp >>> 1] = dstd; dstd = ((srcc ^ (srca & (srcb ^ srcc)))) & 0xffff; totald |= dstd; if (ptd) { dstp = ptd; ptd -= 2; } @@ -1255,7 +1223,7 @@ function Blitter() { } b.bltbhold = srcb; b.bltcdat = srcc; - if (dstp) AMIGA.mem.store16_chip(dstp, dstd); + if (dstp) AMIGA.mem.chip.data[dstp >>> 1] = dstd; if (totald != 0) b.blitzero = 0; } @@ -1263,18 +1231,18 @@ function Blitter() { var i,j; var totald = 0; var prevb = 0, srcb = b.bltbhold; - var dstd=0; + var dstd = 0; var dstp = 0; for (j = 0; j < b.vblitsize; j++) { for (i = 0; i < b.hblitsize; i++) { var bltadat, srca; if (ptb) { - var bltbdat = blt_info.bltbdat = AMIGA.mem.load16_chip(ptb); ptb += 2; + var bltbdat = blt_info.bltbdat = AMIGA.mem.chip.data[ptb >>> 1]; ptb += 2; srcb = ((((prevb << 16) | bltbdat) >>> 0) >>> b.blitbshift) & 0xffff; prevb = bltbdat; } - if (dstp) AMIGA.mem.store16_chip(dstp, dstd); + if (dstp) AMIGA.mem.chip.data[dstp >>> 1] = dstd; dstd = (srcb) & 0xffff; totald |= dstd; if (ptd) { dstp = ptd; ptd += 2; } @@ -1283,7 +1251,7 @@ function Blitter() { if (ptd) ptd += b.bltdmod; } b.bltbhold = srcb; - if (dstp) AMIGA.mem.store16_chip(dstp, dstd); + if (dstp) AMIGA.mem.chip.data[dstp >>> 1] = dstd; if (totald != 0) b.blitzero = 0; } @@ -1297,11 +1265,11 @@ function Blitter() { for (i = 0; i < b.hblitsize; i++) { var bltadat, srca; if (ptb) { - var bltbdat = blt_info.bltbdat = AMIGA.mem.load16_chip(ptb); ptb -= 2; + var bltbdat = blt_info.bltbdat = AMIGA.mem.chip.data[ptb >>> 1]; ptb -= 2; srcb = ((((bltbdat << 16) | prevb) >>> 0) >>> b.blitdownbshift) & 0xffff; prevb = bltbdat; } - if (dstp) AMIGA.mem.store16_chip(dstp, dstd); + if (dstp) AMIGA.mem.chip.data[dstp >>> 1] = dstd; dstd = (srcb) & 0xffff; totald |= dstd; if (ptd) { dstp = ptd; ptd -= 2; } @@ -1310,7 +1278,7 @@ function Blitter() { if (ptd) ptd -= b.bltdmod; } b.bltbhold = srcb; - if (dstp) AMIGA.mem.store16_chip(dstp, dstd); + if (dstp) AMIGA.mem.chip.data[dstp >>> 1] = dstd; if (totald != 0) b.blitzero = 0; } @@ -1320,23 +1288,23 @@ function Blitter() { var preva = 0; var prevb = 0, srcb = b.bltbhold; var srcc = b.bltcdat; - var dstd=0; + var dstd = 0; var dstp = 0; for (j = 0; j < b.vblitsize; j++) { for (i = 0; i < b.hblitsize; i++) { var bltadat, srca; - if (ptc) { srcc = AMIGA.mem.load16_chip(ptc); ptc += 2; } + if (ptc) { srcc = AMIGA.mem.chip.data[ptc >>> 1]; ptc += 2; } if (ptb) { - var bltbdat = blt_info.bltbdat = AMIGA.mem.load16_chip(ptb); ptb += 2; + var bltbdat = blt_info.bltbdat = AMIGA.mem.chip.data[ptb >>> 1]; ptb += 2; srcb = ((((prevb << 16) | bltbdat) >>> 0) >>> b.blitbshift) & 0xffff; prevb = bltbdat; } - if (pta) { bltadat = blt_info.bltadat = AMIGA.mem.load16_chip(pta); pta += 2; } else { bltadat = blt_info.bltadat; } + if (pta) { bltadat = blt_info.bltadat = AMIGA.mem.chip.data[pta >>> 1]; pta += 2; } else { bltadat = blt_info.bltadat; } bltadat &= blit_masktable[i]; srca = ((((preva << 16) | bltadat) >>> 0) >>> b.blitashift) & 0xffff; preva = bltadat; - if (dstp) AMIGA.mem.store16_chip(dstp, dstd); + if (dstp) AMIGA.mem.chip.data[dstp >>> 1] = dstd; dstd = ((srca ^ (srcc & (srca ^ srcb)))) & 0xffff; totald |= dstd; if (ptd) { dstp = ptd; ptd += 2; } @@ -1348,7 +1316,7 @@ function Blitter() { } b.bltbhold = srcb; b.bltcdat = srcc; - if (dstp) AMIGA.mem.store16_chip(dstp, dstd); + if (dstp) AMIGA.mem.chip.data[dstp >>> 1] = dstd; if (totald != 0) b.blitzero = 0; } @@ -1363,17 +1331,17 @@ function Blitter() { for (j = 0; j < b.vblitsize; j++) { for (i = 0; i < b.hblitsize; i++) { var bltadat, srca; - if (ptc) { srcc = AMIGA.mem.load16_chip(ptc); ptc -= 2; } + if (ptc) { srcc = AMIGA.mem.chip.data[ptc >>> 1]; ptc -= 2; } if (ptb) { - var bltbdat = blt_info.bltbdat = AMIGA.mem.load16_chip(ptb); ptb -= 2; + var bltbdat = blt_info.bltbdat = AMIGA.mem.chip.data[ptb >>> 1]; ptb -= 2; srcb = ((((bltbdat << 16) | prevb) >>> 0) >>> b.blitdownbshift) & 0xffff; prevb = bltbdat; } - if (pta) { bltadat = blt_info.bltadat = AMIGA.mem.load16_chip(pta); pta -= 2; } else { bltadat = blt_info.bltadat; } + if (pta) { bltadat = blt_info.bltadat = AMIGA.mem.chip.data[pta >>> 1]; pta -= 2; } else { bltadat = blt_info.bltadat; } bltadat &= blit_masktable[i]; srca = ((((bltadat << 16) | preva) >>> 0) >>> b.blitdownashift) & 0xffff; preva = bltadat; - if (dstp) AMIGA.mem.store16_chip(dstp, dstd); + if (dstp) AMIGA.mem.chip.data[dstp >>> 1] = dstd; dstd = ((srca ^ (srcc & (srca ^ srcb)))) & 0xffff; totald |= dstd; if (ptd) { dstp = ptd; ptd -= 2; } @@ -1385,7 +1353,7 @@ function Blitter() { } b.bltbhold = srcb; b.bltcdat = srcc; - if (dstp) AMIGA.mem.store16_chip(dstp, dstd); + if (dstp) AMIGA.mem.chip.data[dstp >>> 1] = dstd; if (totald != 0) b.blitzero = 0; } @@ -1395,23 +1363,23 @@ function Blitter() { var preva = 0; var prevb = 0, srcb = b.bltbhold; var srcc = b.bltcdat; - var dstd=0; + var dstd = 0; var dstp = 0; for (j = 0; j < b.vblitsize; j++) { for (i = 0; i < b.hblitsize; i++) { var bltadat, srca; - if (ptc) { srcc = AMIGA.mem.load16_chip(ptc); ptc += 2; } + if (ptc) { srcc = AMIGA.mem.chip.data[ptc >>> 1]; ptc += 2; } if (ptb) { - var bltbdat = blt_info.bltbdat = AMIGA.mem.load16_chip(ptb); ptb += 2; + var bltbdat = blt_info.bltbdat = AMIGA.mem.chip.data[ptb >>> 1]; ptb += 2; srcb = ((((prevb << 16) | bltbdat) >>> 0) >>> b.blitbshift) & 0xffff; prevb = bltbdat; } - if (pta) { bltadat = blt_info.bltadat = AMIGA.mem.load16_chip(pta); pta += 2; } else { bltadat = blt_info.bltadat; } + if (pta) { bltadat = blt_info.bltadat = AMIGA.mem.chip.data[pta >>> 1]; pta += 2; } else { bltadat = blt_info.bltadat; } bltadat &= blit_masktable[i]; srca = ((((preva << 16) | bltadat) >>> 0) >>> b.blitashift) & 0xffff; preva = bltadat; - if (dstp) AMIGA.mem.store16_chip(dstp, dstd); + if (dstp) AMIGA.mem.chip.data[dstp >>> 1] = dstd; dstd = ((srcc ^ (srcb & (srca ^ srcc)))) & 0xffff; totald |= dstd; if (ptd) { dstp = ptd; ptd += 2; } @@ -1423,7 +1391,7 @@ function Blitter() { } b.bltbhold = srcb; b.bltcdat = srcc; - if (dstp) AMIGA.mem.store16_chip(dstp, dstd); + if (dstp) AMIGA.mem.chip.data[dstp >>> 1] = dstd; if (totald != 0) b.blitzero = 0; } @@ -1438,17 +1406,17 @@ function Blitter() { for (j = 0; j < b.vblitsize; j++) { for (i = 0; i < b.hblitsize; i++) { var bltadat, srca; - if (ptc) { srcc = AMIGA.mem.load16_chip(ptc); ptc -= 2; } + if (ptc) { srcc = AMIGA.mem.chip.data[ptc >>> 1]; ptc -= 2; } if (ptb) { - var bltbdat = blt_info.bltbdat = AMIGA.mem.load16_chip(ptb); ptb -= 2; + var bltbdat = blt_info.bltbdat = AMIGA.mem.chip.data[ptb >>> 1]; ptb -= 2; srcb = ((((bltbdat << 16) | prevb) >>> 0) >>> b.blitdownbshift) & 0xffff; prevb = bltbdat; } - if (pta) { bltadat = blt_info.bltadat = AMIGA.mem.load16_chip(pta); pta -= 2; } else { bltadat = blt_info.bltadat; } + if (pta) { bltadat = blt_info.bltadat = AMIGA.mem.chip.data[pta >>> 1]; pta -= 2; } else { bltadat = blt_info.bltadat; } bltadat &= blit_masktable[i]; srca = ((((bltadat << 16) | preva) >>> 0) >>> b.blitdownashift) & 0xffff; preva = bltadat; - if (dstp) AMIGA.mem.store16_chip(dstp, dstd); + if (dstp) AMIGA.mem.chip.data[dstp >>> 1] = dstd; dstd = ((srcc ^ (srcb & (srca ^ srcc)))) & 0xffff; totald |= dstd; if (ptd) { dstp = ptd; ptd -= 2; } @@ -1460,7 +1428,7 @@ function Blitter() { } b.bltbhold = srcb; b.bltcdat = srcc; - if (dstp) AMIGA.mem.store16_chip(dstp, dstd); + if (dstp) AMIGA.mem.chip.data[dstp >>> 1] = dstd; if (totald != 0) b.blitzero = 0; } @@ -1470,23 +1438,23 @@ function Blitter() { var preva = 0; var prevb = 0, srcb = b.bltbhold; var srcc = b.bltcdat; - var dstd=0; + var dstd = 0; var dstp = 0; for (j = 0; j < b.vblitsize; j++) { for (i = 0; i < b.hblitsize; i++) { var bltadat, srca; - if (ptc) { srcc = AMIGA.mem.load16_chip(ptc); ptc += 2; } + if (ptc) { srcc = AMIGA.mem.chip.data[ptc >>> 1]; ptc += 2; } if (ptb) { - var bltbdat = blt_info.bltbdat = AMIGA.mem.load16_chip(ptb); ptb += 2; + var bltbdat = blt_info.bltbdat = AMIGA.mem.chip.data[ptb >>> 1]; ptb += 2; srcb = ((((prevb << 16) | bltbdat) >>> 0) >>> b.blitbshift) & 0xffff; prevb = bltbdat; } - if (pta) { bltadat = blt_info.bltadat = AMIGA.mem.load16_chip(pta); pta += 2; } else { bltadat = blt_info.bltadat; } + if (pta) { bltadat = blt_info.bltadat = AMIGA.mem.chip.data[pta >>> 1]; pta += 2; } else { bltadat = blt_info.bltadat; } bltadat &= blit_masktable[i]; srca = ((((preva << 16) | bltadat) >>> 0) >>> b.blitashift) & 0xffff; preva = bltadat; - if (dstp) AMIGA.mem.store16_chip(dstp, dstd); + if (dstp) AMIGA.mem.chip.data[dstp >>> 1] = dstd; dstd = ((srcc | (srca & srcb))) & 0xffff; totald |= dstd; if (ptd) { dstp = ptd; ptd += 2; } @@ -1498,7 +1466,7 @@ function Blitter() { } b.bltbhold = srcb; b.bltcdat = srcc; - if (dstp) AMIGA.mem.store16_chip(dstp, dstd); + if (dstp) AMIGA.mem.chip.data[dstp >>> 1] = dstd; if (totald != 0) b.blitzero = 0; } @@ -1513,17 +1481,17 @@ function Blitter() { for (j = 0; j < b.vblitsize; j++) { for (i = 0; i < b.hblitsize; i++) { var bltadat, srca; - if (ptc) { srcc = AMIGA.mem.load16_chip(ptc); ptc -= 2; } + if (ptc) { srcc = AMIGA.mem.chip.data[ptc >>> 1]; ptc -= 2; } if (ptb) { - var bltbdat = blt_info.bltbdat = AMIGA.mem.load16_chip(ptb); ptb -= 2; + var bltbdat = blt_info.bltbdat = AMIGA.mem.chip.data[ptb >>> 1]; ptb -= 2; srcb = ((((bltbdat << 16) | prevb) >>> 0) >>> b.blitdownbshift) & 0xffff; prevb = bltbdat; } - if (pta) { bltadat = blt_info.bltadat = AMIGA.mem.load16_chip(pta); pta -= 2; } else { bltadat = blt_info.bltadat; } + if (pta) { bltadat = blt_info.bltadat = AMIGA.mem.chip.data[pta >>> 1]; pta -= 2; } else { bltadat = blt_info.bltadat; } bltadat &= blit_masktable[i]; srca = ((((bltadat << 16) | preva) >>> 0) >>> b.blitdownashift) & 0xffff; preva = bltadat; - if (dstp) AMIGA.mem.store16_chip(dstp, dstd); + if (dstp) AMIGA.mem.chip.data[dstp >>> 1] = dstd; dstd = ((srcc | (srca & srcb))) & 0xffff; totald |= dstd; if (ptd) { dstp = ptd; ptd -= 2; } @@ -1535,7 +1503,7 @@ function Blitter() { } b.bltbhold = srcb; b.bltcdat = srcc; - if (dstp) AMIGA.mem.store16_chip(dstp, dstd); + if (dstp) AMIGA.mem.chip.data[dstp >>> 1] = dstd; if (totald != 0) b.blitzero = 0; } @@ -1543,17 +1511,17 @@ function Blitter() { var i,j; var totald = 0; var preva = 0; - var dstd=0; + var dstd = 0; var dstp = 0; for (j = 0; j < b.vblitsize; j++) { for (i = 0; i < b.hblitsize; i++) { var bltadat, srca; - if (pta) { bltadat = blt_info.bltadat = AMIGA.mem.load16_chip(pta); pta += 2; } else { bltadat = blt_info.bltadat; } + if (pta) { bltadat = blt_info.bltadat = AMIGA.mem.chip.data[pta >>> 1]; pta += 2; } else { bltadat = blt_info.bltadat; } bltadat &= blit_masktable[i]; srca = ((((preva << 16) | bltadat) >>> 0) >>> b.blitashift) & 0xffff; preva = bltadat; - if (dstp) AMIGA.mem.store16_chip(dstp, dstd); + if (dstp) AMIGA.mem.chip.data[dstp >>> 1] = dstd; dstd = (srca) & 0xffff; totald |= dstd; if (ptd) { dstp = ptd; ptd += 2; } @@ -1561,7 +1529,7 @@ function Blitter() { if (pta) pta += b.bltamod; if (ptd) ptd += b.bltdmod; } - if (dstp) AMIGA.mem.store16_chip(dstp, dstd); + if (dstp) AMIGA.mem.chip.data[dstp >>> 1] = dstd; if (totald != 0) b.blitzero = 0; } @@ -1574,11 +1542,11 @@ function Blitter() { for (j = 0; j < b.vblitsize; j++) { for (i = 0; i < b.hblitsize; i++) { var bltadat, srca; - if (pta) { bltadat = blt_info.bltadat = AMIGA.mem.load16_chip(pta); pta -= 2; } else { bltadat = blt_info.bltadat; } + if (pta) { bltadat = blt_info.bltadat = AMIGA.mem.chip.data[pta >>> 1]; pta -= 2; } else { bltadat = blt_info.bltadat; } bltadat &= blit_masktable[i]; srca = ((((bltadat << 16) | preva) >>> 0) >>> b.blitdownashift) & 0xffff; preva = bltadat; - if (dstp) AMIGA.mem.store16_chip(dstp, dstd); + if (dstp) AMIGA.mem.chip.data[dstp >>> 1] = dstd; dstd = (srca) & 0xffff; totald |= dstd; if (ptd) { dstp = ptd; ptd -= 2; } @@ -1586,7 +1554,7 @@ function Blitter() { if (pta) pta -= b.bltamod; if (ptd) ptd -= b.bltdmod; } - if (dstp) AMIGA.mem.store16_chip(dstp, dstd); + if (dstp) AMIGA.mem.chip.data[dstp >>> 1] = dstd; if (totald != 0) b.blitzero = 0; } @@ -1595,18 +1563,18 @@ function Blitter() { var totald = 0; var preva = 0; var srcc = b.bltcdat; - var dstd=0; + var dstd = 0; var dstp = 0; for (j = 0; j < b.vblitsize; j++) { for (i = 0; i < b.hblitsize; i++) { var bltadat, srca; - if (ptc) { srcc = AMIGA.mem.load16_chip(ptc); ptc += 2; } - if (pta) { bltadat = blt_info.bltadat = AMIGA.mem.load16_chip(pta); pta += 2; } else { bltadat = blt_info.bltadat; } + if (ptc) { srcc = AMIGA.mem.chip.data[ptc >>> 1]; ptc += 2; } + if (pta) { bltadat = blt_info.bltadat = AMIGA.mem.chip.data[pta >>> 1]; pta += 2; } else { bltadat = blt_info.bltadat; } bltadat &= blit_masktable[i]; srca = ((((preva << 16) | bltadat) >>> 0) >>> b.blitashift) & 0xffff; preva = bltadat; - if (dstp) AMIGA.mem.store16_chip(dstp, dstd); + if (dstp) AMIGA.mem.chip.data[dstp >>> 1] = dstd; dstd = ((srca | srcc)) & 0xffff; totald |= dstd; if (ptd) { dstp = ptd; ptd += 2; } @@ -1616,7 +1584,7 @@ function Blitter() { if (ptd) ptd += b.bltdmod; } b.bltcdat = srcc; - if (dstp) AMIGA.mem.store16_chip(dstp, dstd); + if (dstp) AMIGA.mem.chip.data[dstp >>> 1] = dstd; if (totald != 0) b.blitzero = 0; } @@ -1630,12 +1598,12 @@ function Blitter() { for (j = 0; j < b.vblitsize; j++) { for (i = 0; i < b.hblitsize; i++) { var bltadat, srca; - if (ptc) { srcc = AMIGA.mem.load16_chip(ptc); ptc -= 2; } - if (pta) { bltadat = blt_info.bltadat = AMIGA.mem.load16_chip(pta); pta -= 2; } else { bltadat = blt_info.bltadat; } + if (ptc) { srcc = AMIGA.mem.chip.data[ptc >>> 1]; ptc -= 2; } + if (pta) { bltadat = blt_info.bltadat = AMIGA.mem.chip.data[pta >>> 1]; pta -= 2; } else { bltadat = blt_info.bltadat; } bltadat &= blit_masktable[i]; srca = ((((bltadat << 16) | preva) >>> 0) >>> b.blitdownashift) & 0xffff; preva = bltadat; - if (dstp) AMIGA.mem.store16_chip(dstp, dstd); + if (dstp) AMIGA.mem.chip.data[dstp >>> 1] = dstd; dstd = ((srca | srcc)) & 0xffff; totald |= dstd; if (ptd) { dstp = ptd; ptd -= 2; } @@ -1645,7 +1613,7 @@ function Blitter() { if (ptd) ptd -= b.bltdmod; } b.bltcdat = srcc; - if (dstp) AMIGA.mem.store16_chip(dstp, dstd); + if (dstp) AMIGA.mem.chip.data[dstp >>> 1] = dstd; if (totald != 0) b.blitzero = 0; } @@ -1654,22 +1622,22 @@ function Blitter() { var totald = 0; var preva = 0; var prevb = 0, srcb = b.bltbhold; - var dstd=0; + var dstd = 0; var dstp = 0; for (j = 0; j < b.vblitsize; j++) { for (i = 0; i < b.hblitsize; i++) { var bltadat, srca; if (ptb) { - var bltbdat = blt_info.bltbdat = AMIGA.mem.load16_chip(ptb); ptb += 2; + var bltbdat = blt_info.bltbdat = AMIGA.mem.chip.data[ptb >>> 1]; ptb += 2; srcb = ((((prevb << 16) | bltbdat) >>> 0) >>> b.blitbshift) & 0xffff; prevb = bltbdat; } - if (pta) { bltadat = blt_info.bltadat = AMIGA.mem.load16_chip(pta); pta += 2; } else { bltadat = blt_info.bltadat; } + if (pta) { bltadat = blt_info.bltadat = AMIGA.mem.chip.data[pta >>> 1]; pta += 2; } else { bltadat = blt_info.bltadat; } bltadat &= blit_masktable[i]; srca = ((((preva << 16) | bltadat) >>> 0) >>> b.blitashift) & 0xffff; preva = bltadat; - if (dstp) AMIGA.mem.store16_chip(dstp, dstd); + if (dstp) AMIGA.mem.chip.data[dstp >>> 1] = dstd; dstd = ((srca | srcb)) & 0xffff; totald |= dstd; if (ptd) { dstp = ptd; ptd += 2; } @@ -1679,7 +1647,7 @@ function Blitter() { if (ptd) ptd += b.bltdmod; } b.bltbhold = srcb; - if (dstp) AMIGA.mem.store16_chip(dstp, dstd); + if (dstp) AMIGA.mem.chip.data[dstp >>> 1] = dstd; if (totald != 0) b.blitzero = 0; } @@ -1694,15 +1662,15 @@ function Blitter() { for (i = 0; i < b.hblitsize; i++) { var bltadat, srca; if (ptb) { - var bltbdat = blt_info.bltbdat = AMIGA.mem.load16_chip(ptb); ptb -= 2; + var bltbdat = blt_info.bltbdat = AMIGA.mem.chip.data[ptb >>> 1]; ptb -= 2; srcb = ((((bltbdat << 16) | prevb) >>> 0) >>> b.blitdownbshift) & 0xffff; prevb = bltbdat; } - if (pta) { bltadat = blt_info.bltadat = AMIGA.mem.load16_chip(pta); pta -= 2; } else { bltadat = blt_info.bltadat; } + if (pta) { bltadat = blt_info.bltadat = AMIGA.mem.chip.data[pta >>> 1]; pta -= 2; } else { bltadat = blt_info.bltadat; } bltadat &= blit_masktable[i]; srca = ((((bltadat << 16) | preva) >>> 0) >>> b.blitdownashift) & 0xffff; preva = bltadat; - if (dstp) AMIGA.mem.store16_chip(dstp, dstd); + if (dstp) AMIGA.mem.chip.data[dstp >>> 1] = dstd; dstd = ((srca | srcb)) & 0xffff; totald |= dstd; if (ptd) { dstp = ptd; ptd -= 2; } @@ -1712,7 +1680,7 @@ function Blitter() { if (ptd) ptd -= b.bltdmod; } b.bltbhold = srcb; - if (dstp) AMIGA.mem.store16_chip(dstp, dstd); + if (dstp) AMIGA.mem.chip.data[dstp >>> 1] = dstd; if (totald != 0) b.blitzero = 0; } @@ -2048,6 +2016,7 @@ function Blitter() { } function blitter_dofast() { + //console.log('blitter_dofast'); var i,j; var bltadatptr = 0, bltbdatptr = 0, bltcdatptr = 0, bltddatptr = 0; var mt = bltcon0 & 0xFF; @@ -2072,7 +2041,7 @@ function Blitter() { bltdpt += (blt_info.hblitsize * 2 + blt_info.bltdmod) * blt_info.vblitsize; } - if (blitfunc_dofast[mt] !== 0 && !blitfill) + if (FAST && blitfunc_dofast[mt] !== 0 && !blitfill) blitfunc_dofast[mt](bltadatptr, bltbdatptr, bltcdatptr, bltddatptr, blt_info); else { var blitbhold = blt_info.bltbhold; @@ -2086,7 +2055,8 @@ function Blitter() { var bltadat, blitahold; var bltbdat; if (bltadatptr) { - blt_info.bltadat = bltadat = AMIGA.mem.load16_chip(bltadatptr); + //blt_info.bltadat = bltadat = AMIGA.mem.load16_chip(bltadatptr); + blt_info.bltadat = bltadat = AMIGA.mem.chip.data[bltadatptr >>> 1]; bltadatptr += 2; } else bltadat = blt_info.bltadat; @@ -2095,19 +2065,23 @@ function Blitter() { preva = bltadat; if (bltbdatptr) { - blt_info.bltbdat = bltbdat = AMIGA.mem.load16_chip(bltbdatptr); + //blt_info.bltbdat = bltbdat = AMIGA.mem.load16_chip(bltbdatptr); + blt_info.bltbdat = bltbdat = AMIGA.mem.chip.data[bltbdatptr >>> 1]; bltbdatptr += 2; blitbhold = (((prevb << 16) | bltbdat) >>> 0) >>> blt_info.blitbshift; prevb = bltbdat; } if (bltcdatptr) { - blt_info.bltcdat = AMIGA.mem.load16_chip(bltcdatptr); + //blt_info.bltcdat = AMIGA.mem.load16_chip(bltcdatptr); + blt_info.bltcdat = AMIGA.mem.chip.data[bltcdatptr >>> 1]; bltcdatptr += 2; } if (dodst) - AMIGA.mem.store16_chip(dstp, blt_info.bltddat); - blt_info.bltddat = blit_func (blitahold, blitbhold, blt_info.bltcdat, mt) & 0xffff; + //AMIGA.mem.store16_chip(dstp, blt_info.bltddat); + AMIGA.mem.chip.data[dstp >>> 1] = blt_info.bltddat; + + blt_info.bltddat = (blit_func(blitahold & 0xffff, blitbhold & 0xffff, blt_info.bltcdat & 0xffff, mt) >>> 0) & 0xffff; if (blitfill) { var d = blt_info.bltddat; var ifemode = blitife ? 2 : 0; @@ -2129,7 +2103,9 @@ function Blitter() { if (bltddatptr) bltddatptr += blt_info.bltdmod; } if (dodst) - AMIGA.mem.store16_chip(dstp, blt_info.bltddat); + //AMIGA.mem.store16_chip(dstp, blt_info.bltddat); + AMIGA.mem.chip.data[dstp >>> 1] = blt_info.bltddat; + blt_info.bltbhold = blitbhold; } blit_masktable[0] = 0xffff; @@ -2139,6 +2115,7 @@ function Blitter() { } function blitter_dofast_desc() { + //console.log('blitter_dofast_desc'); var i,j; var bltadatptr = 0, bltbdatptr = 0, bltcdatptr = 0, bltddatptr = 0; var mt = bltcon0 & 0xFF; @@ -2163,7 +2140,7 @@ function Blitter() { bltdpt -= (blt_info.hblitsize * 2 + blt_info.bltdmod) * blt_info.vblitsize; } - if (blitfunc_dofast_desc[mt] !== 0 && !blitfill) + if (FAST && blitfunc_dofast_desc[mt] !== 0 && !blitfill) blitfunc_dofast_desc[mt](bltadatptr, bltbdatptr, bltcdatptr, bltddatptr, blt_info); else { var blitbhold = blt_info.bltbhold; @@ -2177,7 +2154,8 @@ function Blitter() { var bltadat, blitahold; var bltbdat; if (bltadatptr) { - bltadat = blt_info.bltadat = AMIGA.mem.load16_chip(bltadatptr); + //blt_info.bltadat = bltadat = AMIGA.mem.load16_chip(bltadatptr); + blt_info.bltadat = bltadat = AMIGA.mem.chip.data[bltadatptr >>> 1]; bltadatptr -= 2; } else bltadat = blt_info.bltadat; @@ -2186,19 +2164,23 @@ function Blitter() { preva = bltadat; if (bltbdatptr) { - blt_info.bltbdat = bltbdat = AMIGA.mem.load16_chip(bltbdatptr); + //blt_info.bltbdat = bltbdat = AMIGA.mem.load16_chip(bltbdatptr); + blt_info.bltbdat = bltbdat = AMIGA.mem.chip.data[bltbdatptr >>> 1]; bltbdatptr -= 2; blitbhold = (((bltbdat << 16) | prevb) >>> 0) >> blt_info.blitdownbshift; prevb = bltbdat; } if (bltcdatptr) { - blt_info.bltcdat = blt_info.bltbdat = AMIGA.mem.load16_chip(bltcdatptr); + //blt_info.bltcdat = blt_info.bltbdat = AMIGA.mem.load16_chip(bltcdatptr); + blt_info.bltcdat = blt_info.bltbdat = AMIGA.mem.chip.data[bltcdatptr >>> 1]; bltcdatptr -= 2; } if (dodst) - AMIGA.mem.store16_chip(dstp, blt_info.bltddat); - blt_info.bltddat = blit_func (blitahold, blitbhold, blt_info.bltcdat, mt) & 0xffff; + //AMIGA.mem.store16_chip(dstp, blt_info.bltddat); + AMIGA.mem.chip.data[dstp >>> 1] = blt_info.bltddat; + + blt_info.bltddat = (blit_func(blitahold & 0xffff, blitbhold & 0xffff, blt_info.bltcdat & 0xffff, mt) >>> 0) & 0xffff; if (blitfill) { var d = blt_info.bltddat; var ifemode = blitife ? 2 : 0; @@ -2220,7 +2202,9 @@ function Blitter() { if (bltddatptr) bltddatptr -= blt_info.bltdmod; } if (dodst) - AMIGA.mem.store16_chip(dstp, blt_info.bltddat); + //AMIGA.mem.store16_chip(dstp, blt_info.bltddat); + AMIGA.mem.chip.data[dstp >>> 1] = blt_info.bltddat; + blt_info.bltbhold = blitbhold; } blit_masktable[0] = 0xffff; @@ -2232,7 +2216,8 @@ function Blitter() { function blitter_read() { if (bltcon0 & 0x200) { if (AMIGA.dmaen(DMAF_BLTEN)) - blt_info.bltcdat = AMIGA.mem.load16_chip(bltcpt); + //blt_info.bltcdat = AMIGA.mem.load16_chip(bltcpt); + blt_info.bltcdat = dat = AMIGA.mem.chip.data[bltcpt >>> 1]; } bltstate = BLT_work; } @@ -2243,7 +2228,8 @@ function Blitter() { if (bltcon0 & 0x200) { if (AMIGA.dmaen(DMAF_BLTEN)) - AMIGA.mem.store16_chip(bltdpt, blt_info.bltddat); + //AMIGA.mem.store16_chip(bltdpt, blt_info.bltddat); + AMIGA.mem.chip.data[bltdpt >>> 1] = blt_info.bltddat; } bltstate = BLT_next; } @@ -2254,7 +2240,7 @@ function Blitter() { blt_info.bltbhold = (blineb & 1) ? 0xffff : 0; blitlinepixel = !blitsing || (blitsing && !blitonedot); - blt_info.bltddat = blit_func (blitahold, blt_info.bltbhold, blitchold, bltcon0 & 0xFF); + blt_info.bltddat = blit_func(blitahold, blt_info.bltbhold, blitchold, bltcon0 & 0xff); blitonedot++; } @@ -2396,26 +2382,27 @@ function Blitter() { if (blt_info.vblitsize <= 0) bltstate = BLT_done; } while (bltstate != BLT_done); + bltapt_line = null; bltdpt = bltcpt; } else { if (blitdesc) blitter_dofast_desc(); else - blitter_dofast(); + blitter_dofast(); bltstate = BLT_done; } } - function blitter_doit() { + function blitter_do() { actually_do_blit(); - blitter_done(AMIGA.events.hpos()); + blitter_done(AMIGA.playfield.hpos()); } /*---------------------------------*/ this.handler = function(data) { if (!AMIGA.dmaen(DMAF_BLTEN)) { - AMIGA.events.event2_newevent(EV2_BLITTER, 10, 0); + AMIGA.events.newevent(EV2_BLITTER, 10, 0); if (++blit_stuck < 20000 || !AMIGA.config.blitter.immediate) return; @@ -2423,40 +2410,15 @@ function Blitter() { } blit_stuck = 0; if (blit_slowdown > 0 && !AMIGA.config.blitter.immediate) { - AMIGA.events.event2_newevent(EV2_BLITTER, blit_slowdown, 0); + //console.log('Blitter.handler () slowdown', blit_slowdown); + AMIGA.events.newevent(EV2_BLITTER, blit_slowdown, 0); blit_slowdown = -1; return; } - blitter_doit(); + blitter_do(); } - /*function blitter_force_finish() { - if (bltstate == BLT_done) - return; - if (bltstate != BLT_done) { - var odmacon = AMIGA.dmacon; - AMIGA.dmacon |= DMAF_DMAEN | DMAF_BLTEN; - BUG.info('forcing blitter finish'); - - if (blitter_cycle_exact) { - var rounds = 10000; - while (bltstate != BLT_done && rounds > 0) { - memset (cycle_line, 0, sizeof cycle_line); - decide_blitter (-1); - rounds--; - } - if (rounds == 0) BUG.info('blitter froze!?'); - blit_startcycles = 0; - } else { - actually_do_blit(); - } - blitter_done(AMIGA.events.hpos()); - AMIGA.dmacon = odmacon; - } - }*/ - - /*var changetable = new Uint8Array(32 * 32); - for (var i = 0; i < changetable.length; i++) changetable[i] = 0;*/ + var changetable = new Uint8Array(32 * 32); for (var i = 0; i < changetable.length; i++) changetable[i] = 0; var freezes = 10; function blit_bltset(con) { if (con & 2) { @@ -2498,50 +2460,25 @@ function Blitter() { blit_diag = blitfill && blit_cycle_diagram_fill[blit_ch][0] ? blit_cycle_diagram_fill[blit_ch] : blit_cycle_diagram[blit_ch]; } - if ((bltcon1 & 0x80) && (AMIGA.config.chipset.type == SAEV_Config_Chipset_Type_ECS)) + if ((bltcon1 & 0x80) && (AMIGA.config.chipset.mask & CSMASK_ECS_AGNUS)) BUG.info('blit_bltset() ECS BLTCON1 DOFF-bit set'); - /*on the fly switching fillmode from extra cycle to non-extra: blitter freezes - non-extra cycle to extra cycle: does not freeze but cycle diagram goes weird, - extra free cycle changes to another D write.. - (Absolute Inebriation vector cube inside semi-filled vector object requires freezing blitter.)*/ - /*if (bltstate != BLT_done) { - var olddiag = blit_diag; - var isen = blit_diag >= &blit_cycle_diagram_fill[0][0] && blit_diag <= &blit_cycle_diagram_fill[15][0]; - var iseo = olddiag >= &blit_cycle_diagram_fill[0][0] && olddiag <= &blit_cycle_diagram_fill[15][0]; - if (iseo != isen) { - if (freezes > 0) { - BUG.info('BLITTER: on the fly %d (%d) -> %d (%d) switch!', original_ch, iseo, blit_ch, isen); - freezes--; - } - } - if (original_fill == isen) { - blit_frozen = 0; - } else if (iseo && !isen) { - blit_frozen = 1; - BUG.info('BLITTER: frozen! %d (%d) -> %d (%d)', original_ch, iseo, blit_ch, isen); - } else if (!iseo && isen) { - BUG.info('BLITTER: on the fly %d (%d) -> %d (%d) switch', original_ch, iseo, blit_ch, isen); - } - }*/ - // on the fly switching from CH=1 to CH=D -> blitter stops writing (Rampage/TEK) // currently just switch to no-channels mode, better than crashing the demo.. if (bltstate != BLT_done) { - /*var o = original_ch + (original_fill ? 16 : 0); + var o = original_ch + (original_fill ? 16 : 0); var n = blit_ch + (blitfill ? 16 : 0); if (o != n) { if (changetable[o * 32 + n] < 10) { changetable[o * 32 + n]++; BUG.info('blit_bltset() channel mode changed while active (%02x->%02x)', o, n); } - }*/ + } if (blit_ch == 13 && original_ch == 1) blit_faulty = 1; } - if (blit_faulty) { - //BUG.info('blit_bltset() blit_faulty!'); + BUG.info('blit_bltset() blitter faulty!'); blit_ch = 0; blit_diag = blit_cycle_diagram[blit_ch]; } @@ -2559,15 +2496,6 @@ function Blitter() { } } - /*function blit_modset() { - blit_add = blitdesc ? -2 : 2; - var mult = blitdesc ? -1 : 1; - blit_modadda = mult * blt_info.bltamod; - blit_modaddb = mult * blt_info.bltbmod; - blit_modaddc = mult * blt_info.bltcmod; - blit_modaddd = mult * blt_info.bltdmod; - }*/ - function reset_blit(bltcon) { if (bltcon & 1) blinea_shift = bltcon0 >> 12; @@ -2577,7 +2505,6 @@ function Blitter() { return; if (bltcon) blit_bltset(bltcon); - //blit_modset(); } var warned1 = 10; @@ -2596,14 +2523,9 @@ function Blitter() { return false; } - function do_blitter2(hpos, copper) { + function do_blitter(hpos, copper) { var cycles; - //#ifdef BLITTER_DEBUG_NOWAIT - if (bltstate != BLT_done) { - if (blit_final) BUG.info('do_blitter2() blitter was already active!'); - } - //#endif var cleanstart = 0; if (bltstate == BLT_done) { if (blit_faulty > 0) @@ -2613,23 +2535,17 @@ function Blitter() { bltstate = BLT_done; - blitter_cycle_exact = AMIGA.config.blitter.exact; blt_info.blitzero = 1; preva = 0; prevb = 0; blt_info.got_cycle = 0; - //blit_frozen = 0; blit_firstline_cycles = blit_first_cycle = AMIGA.events.currcycle; - //blit_misscyclecounter = 0; blit_last_cycle = 0; - //blit_maxcyclecounter = 0; - //last_blitter_hpos = hpos + 1; + last_blitter_hpos = hpos + 1; blit_cyclecounter = 0; - //blit_totalcyclecounter = 0; blit_bltset(1 | 2); - //blit_modset(); ddat1use = ddat2use = 0; blit_interrupt = false; @@ -2643,7 +2559,6 @@ function Blitter() { } else { blit_firstline_cycles = blit_first_cycle + (blit_diag[0] * blt_info.hblitsize + AMIGA.cpu.cycles) * CYCLE_UNIT; cycles = blt_info.vblitsize * blt_info.hblitsize; - //console.log('blit_firstline_cycles', blit_firstline_cycles, cycles); } if (cleanstart) { @@ -2654,14 +2569,10 @@ function Blitter() { /*if (0) { var ch = 0; - if (blit_ch & 1) - ch++; - if (blit_ch & 2) - ch++; - if (blit_ch & 4) - ch++; - if (blit_ch & 8) - ch++; + if (blit_ch & 1) ch++; + if (blit_ch & 2) ch++; + if (blit_ch & 4) ch++; + if (blit_ch & 8) ch++; BUG.info('do_blitter2() %dx%d ch=%d %d*%d=%d d=%d f=%d n=%d l=%d dma=%04x %s', blt_info.hblitsize, blt_info.vblitsize, ch, blit_diag[0], cycles, blit_diag[0] * cycles, blitdesc ? 1 : 0, blitfill ? 1 : 0, AMIGA.dmaen(DMAF_BLTPRI) ? 1 : 0, blitline ? 1 : 0, @@ -2672,43 +2583,29 @@ function Blitter() { bltstate = BLT_init; blit_slowdown = 0; - clr_special (SPCFLAG_BLTNASTY); + clr_special(SPCFLAG_BLTNASTY); if (AMIGA.dmaen(DMAF_BLTPRI)) - set_special (SPCFLAG_BLTNASTY); + set_special(SPCFLAG_BLTNASTY); if (AMIGA.dmaen(DMAF_BLTEN)) bltstate = BLT_work; - /*blit_maxcyclecounter = 0x7fffffff; - if (blitter_cycle_exact) { - blitter_hcounter1 = blitter_hcounter2 = 0; - blitter_vcounter1 = blitter_vcounter2 = 0; - if (blit_nod) - blitter_vcounter2 = blt_info.vblitsize; - blit_cyclecounter = -BLITTER_STARTUP_CYCLES; - blit_waitcyclecounter = copper; - blit_startcycles = 0; - blit_maxcyclecounter = blt_info.hblitsize * blt_info.vblitsize + 2; - return; - }*/ - if (blt_info.vblitsize == 0 || (blitline && blt_info.hblitsize != 2)) { blitter_done(hpos); return; } - blt_info.got_cycle = 1; - //blit_waitcyclecounter = 0; if (AMIGA.config.blitter.immediate) { - blitter_doit(); + blitter_do(); return; } - blit_cyclecounter = cycles * (blit_dmacount2 + (blit_nod ? 0 : 1)); - AMIGA.events.event2_newevent(EV2_BLITTER, blit_cyclecounter, 0); + blit_cyclecounter = cycles * (blit_dmacount2 + (blit_nod ? 0 : 1)); - if (AMIGA.dmaen(DMAF_BLTEN) && (AMIGA.config.cpu.model >= 68020 || !AMIGA.config.cpu.exact)) { + AMIGA.events.newevent(EV2_BLITTER, blit_cyclecounter, 0); + + if (AMIGA.dmaen(DMAF_BLTEN)) { if (AMIGA.config.blitter.waiting) { // wait immediately if all cycles in use and blitter nastry if (blit_dmacount == blit_diag[0] && (AMIGA.spcflags & SPCFLAG_BLTNASTY)) @@ -2717,28 +2614,16 @@ function Blitter() { } } - function do_blitter(hpos, copper) { - if (bltstate == BLT_done || !AMIGA.config.blitter.exact) { - do_blitter2(hpos, copper); - return; - } - if (!AMIGA.dmaen(DMAF_BLTEN) || !blt_info.got_cycle) - return; - - //blit_startcycles = BLITTER_STARTUP_CYCLES; - //blit_waitcyclecounter = copper; - } - var warned2 = 10; - function maybe_blit(hpos, hack) { + this.maybe_blit = function(hpos, hack) { if (bltstate == BLT_done) return; - if (AMIGA.dmaen(DMAF_BLTEN) && (AMIGA.config.cpu.model >= 68020 || !AMIGA.config.cpu.exact)) { + if (AMIGA.dmaen(DMAF_BLTEN)) { var doit = false; if (AMIGA.config.blitter.waiting == 3) { // always doit = true; - } else if (AMIGA.config.blitter.waiting == 2) { // noidle + } else if (AMIGA.config.blitter.waiting == 2) { // no idle if (blit_dmacount == blit_diag[0] && (AMIGA.spcflags & SPCFLAG_BLTNASTY)) doit = true; } else if (AMIGA.config.blitter.waiting == 1) { // automatic @@ -2748,7 +2633,7 @@ function Blitter() { doit = true; } if (doit) { - if (waitingblits ()) + if (waitingblits()) return; } } @@ -2758,10 +2643,6 @@ function Blitter() { BUG.info('maybe_blit() program does not wait for blitter tc=%d', blit_cyclecounter); } - /*if (blitter_cycle_exact) { - decide_blitter (hpos); - return; - }*/ if (hack == 1 && AMIGA.events.currcycle < blit_firstline_cycles) return; @@ -2769,22 +2650,15 @@ function Blitter() { } this.blitnasty = function() { - var cycles, ccnt; - if (bltstate == BLT_done) + if (bltstate == BLT_done || !AMIGA.dmaen(DMAF_BLTEN)) return 0; - if (!AMIGA.dmaen(DMAF_BLTEN)) - return 0; - /*if (blitter_cycle_exact) { - blitter_force_finish(); - return -1; - }*/ if (blit_last_cycle >= blit_diag[0] && blit_dmacount == blit_diag[0]) return 0; - cycles = Math.floor((AMIGA.events.currcycle - blit_first_cycle) / CYCLE_UNIT); - ccnt = 0; + + var cycles = Math.floor((AMIGA.events.currcycle - blit_first_cycle) * CYCLE_UNIT_INV); + var ccnt = 0; while (blit_last_cycle < cycles) { - var c = channel_state(blit_last_cycle++); - if (!c) + if (!channel_state(blit_last_cycle++)) ccnt++; } return ccnt; @@ -2794,7 +2668,7 @@ function Blitter() { var oddfstrt = 0, oddfstop = 0, ototal = 0, ofree = 0, slow = 0; this.slowdown = function() { - var data = AMIGA.playfield.get_data(); + var data = AMIGA.playfield.getData(); var ddfstrt = data[0]; var ddfstop = data[1]; var totalcycles = data[2]; @@ -2803,9 +2677,10 @@ function Blitter() { if (!totalcycles || ddfstrt < 0 || ddfstop < 0) return; if (ddfstrt != oddfstrt || ddfstop != oddfstop || totalcycles != ototal || ofree != freecycles) { - var linecycles = Math.floor(((ddfstop - ddfstrt + totalcycles - 1) / totalcycles) * totalcycles); - var freelinecycles = Math.floor(((ddfstop - ddfstrt + totalcycles - 1) / totalcycles) * freecycles); + var linecycles = Math.floor(((ddfstop - ddfstrt + totalcycles - 1) / totalcycles) * totalcycles); + var freelinecycles = Math.floor(((ddfstop - ddfstrt + totalcycles - 1) / totalcycles) * freecycles); var dmacycles = Math.floor((linecycles * blit_dmacount) / blit_diag[0]); + oddfstrt = ddfstrt; oddfstop = ddfstop; ototal = totalcycles; @@ -2818,15 +2693,13 @@ function Blitter() { return; blit_slowdown += slow; - //blit_misscyclecounter += slow; - //console.log('Blitter.slowdown()', data, blit_slowdown); } /*---------------------------------*/ - this.BLTADAT = function(hpos, v) { maybe_blit(hpos, 0); blt_info.bltadat = v; } + this.BLTADAT = function(hpos, v) { this.maybe_blit(hpos, 0); blt_info.bltadat = v; } this.BLTBDAT = function(hpos, v) { - maybe_blit(hpos, 0); + this.maybe_blit(hpos, 0); if (bltcon1 & 2) blt_info.bltbhold = (v << (bltcon1 >> 12)) & 0xffff; else @@ -2834,35 +2707,35 @@ function Blitter() { blt_info.bltbdat = v; } - this.BLTCDAT = function(hpos, v) { maybe_blit(hpos, 0); blt_info.bltcdat = v; reset_blit(0); } + this.BLTCDAT = function(hpos, v) { this.maybe_blit(hpos, 0); blt_info.bltcdat = v; reset_blit(0); } - this.BLTAMOD = function(hpos, v) { maybe_blit(hpos, 1); blt_info.bltamod = castWord(v & 0xfffe); reset_blit(0); } - this.BLTBMOD = function(hpos, v) { maybe_blit(hpos, 1); blt_info.bltbmod = castWord(v & 0xfffe); reset_blit(0); } - this.BLTCMOD = function(hpos, v) { maybe_blit(hpos, 1); blt_info.bltcmod = castWord(v & 0xfffe); reset_blit(0); } - this.BLTDMOD = function(hpos, v) { maybe_blit(hpos, 1); blt_info.bltdmod = castWord(v & 0xfffe); reset_blit(0); } + this.BLTAMOD = function(hpos, v) { this.maybe_blit(hpos, 1); blt_info.bltamod = castWord(v & 0xfffe); reset_blit(0); } + this.BLTBMOD = function(hpos, v) { this.maybe_blit(hpos, 1); blt_info.bltbmod = castWord(v & 0xfffe); reset_blit(0); } + this.BLTCMOD = function(hpos, v) { this.maybe_blit(hpos, 1); blt_info.bltcmod = castWord(v & 0xfffe); reset_blit(0); } + this.BLTDMOD = function(hpos, v) { this.maybe_blit(hpos, 1); blt_info.bltdmod = castWord(v & 0xfffe); reset_blit(0); } - this.BLTCON0 = function(hpos, v) { maybe_blit(hpos, 2); bltcon0 = v; reset_blit(1); } + this.BLTCON0 = function(hpos, v) { this.maybe_blit(hpos, 2); bltcon0 = v; reset_blit(1); } this.BLTCON0L = function( hpos, v) { - if (AMIGA.config.chipset.type == SAEV_Config_Chipset_Type_OCS) return; - maybe_blit(hpos, 2); bltcon0 = (bltcon0 & 0xFF00) | (v & 0xFF); + if (!(AMIGA.config.chipset.mask & CSMASK_ECS_AGNUS)) return; + this.maybe_blit(hpos, 2); bltcon0 = (bltcon0 & 0xFF00) | (v & 0xFF); reset_blit(1); } - this.BLTCON1 = function(hpos, v) { maybe_blit(hpos, 2); bltcon1 = v; reset_blit(2); } + this.BLTCON1 = function(hpos, v) { this.maybe_blit(hpos, 2); bltcon1 = v; reset_blit(2); } - this.BLTAFWM = function(hpos, v) { maybe_blit(hpos, 2); blt_info.bltafwm = v; reset_blit(0); } - this.BLTALWM = function(hpos, v) { maybe_blit(hpos, 2); blt_info.bltalwm = v; reset_blit(0); } + this.BLTAFWM = function(hpos, v) { this.maybe_blit(hpos, 2); blt_info.bltafwm = v; reset_blit(0); } + this.BLTALWM = function(hpos, v) { this.maybe_blit(hpos, 2); blt_info.bltalwm = v; reset_blit(0); } - this.BLTAPTH = function(hpos, v) { maybe_blit(hpos, 0); bltapt = ((bltapt & 0xffff) | (v << 16)) >>> 0; } - this.BLTAPTL = function(hpos, v) { maybe_blit(hpos, 0); bltapt = ((bltapt & ~0xffff) | (v & 0xfffe)) >>> 0; } - this.BLTBPTH = function(hpos, v) { maybe_blit(hpos, 0); bltbpt = ((bltbpt & 0xffff) | (v << 16)) >>> 0; } - this.BLTBPTL = function(hpos, v) { maybe_blit(hpos, 0); bltbpt = ((bltbpt & ~0xffff) | (v & 0xfffe)) >>> 0; } - this.BLTCPTH = function(hpos, v) { maybe_blit(hpos, 0); bltcpt = ((bltcpt & 0xffff) | (v << 16)) >>> 0; } - this.BLTCPTL = function(hpos, v) { maybe_blit(hpos, 0); bltcpt = ((bltcpt & ~0xffff) | (v & 0xfffe)) >>> 0; } - this.BLTDPTH = function(hpos, v) { maybe_blit(hpos, 0); bltdpt = ((bltdpt & 0xffff) | (v << 16)) >>> 0; } - this.BLTDPTL = function(hpos, v) { maybe_blit(hpos, 0); bltdpt = ((bltdpt & ~0xffff) | (v & 0xfffe)) >>> 0; } + this.BLTAPTH = function(hpos, v) { this.maybe_blit(hpos, 0); bltapt = ((bltapt & 0xffff) | (v << 16)) >>> 0; } + this.BLTAPTL = function(hpos, v) { this.maybe_blit(hpos, 0); bltapt = ((bltapt & ~0xffff) | (v & 0xfffe)) >>> 0; } + this.BLTBPTH = function(hpos, v) { this.maybe_blit(hpos, 0); bltbpt = ((bltbpt & 0xffff) | (v << 16)) >>> 0; } + this.BLTBPTL = function(hpos, v) { this.maybe_blit(hpos, 0); bltbpt = ((bltbpt & ~0xffff) | (v & 0xfffe)) >>> 0; } + this.BLTCPTH = function(hpos, v) { this.maybe_blit(hpos, 0); bltcpt = ((bltcpt & 0xffff) | (v << 16)) >>> 0; } + this.BLTCPTL = function(hpos, v) { this.maybe_blit(hpos, 0); bltcpt = ((bltcpt & ~0xffff) | (v & 0xfffe)) >>> 0; } + this.BLTDPTH = function(hpos, v) { this.maybe_blit(hpos, 0); bltdpt = ((bltdpt & 0xffff) | (v << 16)) >>> 0; } + this.BLTDPTL = function(hpos, v) { this.maybe_blit(hpos, 0); bltdpt = ((bltdpt & ~0xffff) | (v & 0xfffe)) >>> 0; } this.BLTSIZE = function(hpos, v) { - maybe_blit(hpos, 0); + this.maybe_blit(hpos, 0); blt_info.vblitsize = v >> 6; blt_info.hblitsize = v & 0x3F; @@ -2870,23 +2743,25 @@ function Blitter() { blt_info.vblitsize = 1024; if (!blt_info.hblitsize) blt_info.hblitsize = 64; + do_blitter(hpos, AMIGA.copper.access); } this.BLTSIZV = function(hpos, v) { - if (AMIGA.config.chipset.type == SAEV_Config_Chipset_Type_OCS) return; - maybe_blit(hpos, 0); + if (!(AMIGA.config.chipset.mask & CSMASK_ECS_AGNUS)) return; + this.maybe_blit(hpos, 0); blt_info.vblitsize = v & 0x7FFF; } this.BLTSIZH = function(hpos, v) { - if (AMIGA.config.chipset.type == SAEV_Config_Chipset_Type_OCS) return; - maybe_blit(hpos, 0); + if (!(AMIGA.config.chipset.mask & CSMASK_ECS_AGNUS)) return; + this.maybe_blit(hpos, 0); blt_info.hblitsize = v & 0x7FF; if (!blt_info.vblitsize) blt_info.vblitsize = 0x8000; if (!blt_info.hblitsize) blt_info.hblitsize = 0x0800; + do_blitter(hpos, AMIGA.copper.access); } diff --git a/sae/cia.js b/sae/cia.js index 1b742e4..d386eaf 100644 --- a/sae/cia.js +++ b/sae/cia.js @@ -6,733 +6,1315 @@ * ©2012 Rupert Hausberger * Commercial use is prohibited. * +*************************************************************************** +* Notes: Ported from WinUAE 2.5.0 +* **************************************************************************/ -function CIA_8520(type) { - const STARTCYCLESHI = 3; - const STARTCYCLESCRA = 2; +const CIAA_DEBUG_R = 0; +const CIAA_DEBUG_W = 0; +const CIAB_DEBUG_R = 0; +const CIAB_DEBUG_W = 0; +const DONGLE_DEBUG = 0; +const KB_DEBUG = 0; +const CLOCK_DEBUG = 0; - this.type = type; +const TOD_HACK = 1; - this.icr = 0; - this.icrReg = 0; - this.iMask = 0; - this.iFlag = type == CIA_A ? INTF_PORTS : INTF_EXTER; /* 0x0008 : 0x2000 */ +/* e-clock is 10 CPU cycles, 4 cycles high, 6 low data transfer happens during 4 high cycles */ +const ECLOCK_DATA_CYCLE = 4; +const ECLOCK_WAIT_CYCLE = 6; - this.cra = 0; - this.crb = 0; - this.dra = 0; - this.drb = 0; - this.pra = 0; - this.prb = 0; - this.sdr = 0; - this.sdrCnt = 0; +const DIV10 = ((ECLOCK_DATA_CYCLE + ECLOCK_WAIT_CYCLE) * CYCLE_UNIT / 2); /* Yes, a bad identifier. */ +const CIASTARTCYCLESHI = 3; +const CIASTARTCYCLESCRA = 2; - this.ta = 0; - this.tb = 0; - this.taPassed = 0; - this.tbPassed = 0; - this.la = 0; - this.lb = 0; - this.starta = 0; - this.startb = 0; - - this.todOn = false; - this.tod = 0; - this.tol = 0; - this.tlatch = 0; - this.alarm = 0; - - this.reset = function() { - this.icr = this.iMask = 0; - this.cra = this.crb = 0x4; - this.dra = this.drb = 0; - this.pra = this.type == CIA_A ? 0 : 0x8c; - this.sdr = 0; - this.sdrCnt = 0; - this.la = this.lb = this.ta = this.tb = 0xffff; - this.taPassed = this.tbPassed = 0; - this.tod = 0; - this.todOn = false; - this.tlatch = 0; - this.alarm = 0; - } - - this.dump = function() { - BUG.info('CIA_8520.dump() %s | pra $%02x prb $%02x | dra $%02x drb $%02x | ta %5d (la %5d) tb %5d (lb %5d) | tod %5d (tol %5d) alarm %5d latch %d | sdr $%02x | icr $%02x iMask $%02x | cra $%02x crb $%02x', - this.type == CIA_A ? 'A' : 'B', this.pra, this.prb, this.dra, this.drb, this.ta, this.la, this.tb, this.lb, this.tod, this.tol, this.alarm, this.latch ? 1 : 0, this.sdr, this.icr, this.iMask, this.cra, this.crb); - } - - this.setClr = function (val) { - if (val & 0x80) this.iMask |= val & 0x7f; - else this.iMask &= ~val; - } - - this.setICR = function (icr, sdr) { - if (sdr !== null) - this.sdr = sdr; - - this.icr |= icr; - this.reThink(); - } - - this.ICR = function() { - if (this.iMask & this.icr) { - this.icr |= 0x80; - AMIGA.INTREQ_0(INTF_SETCLR | this.iFlag); - } - this.icrReg |= this.icr; - } - - this.reThink = function() { - if (this.icr) { - if (AMIGA.config.cpu.exact) - AMIGA.events.event2_newevent_xx(-1, CIA_RETHINK_DELAY, this.type, function(v) { AMIGA.cia.ICR(v); }); - else - this.ICR(); - } - } - - this.updateCheck = function (ciaclocks) { - var ovfla = false; - var ovflb = false; - var sp = false; - var needReThink = false; - - if ((this.cra & 0x21) == 0x01) { - //BUG.info('CIA.updateCheck() ciaclocks %d, starta %d, ta %d', ciaclocks, this.starta, this.ta); - var check = true; - var cc = ciaclocks; - if (this.starta > 0) { - if (cc > this.starta) { - cc -= this.starta; - this.starta = 0; - } else { - this.starta -= cc; - check = false; - } - } - if (check) { - //assert ((this.ta + 1) >= cc); - if ((this.ta + 1) == cc) { - if ((this.cra & 0x48) == 0x40 && this.sdrCnt > 0 && --this.sdrCnt == 0) sp = true; - - ovfla = true; - if ((this.crb & 0x61) == 0x41 || (this.crb & 0x61) == 0x61) { - if (this.tb-- == 0) ovflb = true; - } - } - this.ta -= cc; - } - } - if ((this.crb & 0x61) == 0x01) { - //BUG.info('CIA.updateCheck() ciaclocks %d, startb %d, tb %d', ciaclocks, this.startb, this.tb); - var check = true; - var cc = ciaclocks; - if (this.startb > 0) { - if (cc > this.startb) { - cc -= this.startb; - this.startb = 0; - } else { - this.startb -= cc; - check = false; - } - } - if (check) { - //assert ((this.tb + 1) >= cc); - if ((this.tb + 1) == cc) ovflb = true; - this.tb -= cc; - } - } - - if (ovfla) { - this.icr |= 1; - needReThink = true; - this.ta = this.la; - if (this.cra & 0x8) { - this.cra &= ~1; - } - } - if (ovflb) { - this.icr |= 2; - needReThink = true; - this.tb = this.lb; - if (this.crb & 0x8) { - this.crb &= ~1; - } - } - if (sp) { - this.icr |= 8; - needReThink = true; - } - return needReThink; - } - - this.calcTimers = function (div10diff) { - var time = [-1, -1]; - - if ((this.cra & 0x21) == 0x01) time[0] = div10diff + DIV10 * (this.ta + this.starta); - if ((this.crb & 0x61) == 0x01) time[1] = div10diff + DIV10 * (this.tb + this.startb); - - //if (time[0] != -1 || time[1] != -1) BUG.info('CIA.calcTimers() div10diff %d, timea %d, timeb %d', div10diff, time[0], time[1]); - return time; - } - - this.checkAlarm = function (inc) { - var alarm; - - if (this.tod == this.alarm) alarm = true; - else if (!inc) alarm = false; - else if (this.tod & 0x000fff) alarm = false; - else if (((this.tod - 1) & 0xfff000) == this.alarm) alarm = true; - else alarm = false; - - if (alarm) { - this.icr |= 4; - this.reThink(); - } - } - - this.calcPassedTime = function() { - var ccount = AMIGA.events.currcycle - AMIGA.events.eventtab[EV_CIA].oldcycles + AMIGA.cia.div10; - var ciaclocks = Math.floor(ccount / DIV10); - - this.taPassed = this.tbPassed = 0; - - if ((this.cra & 0x21) == 0x01) { - var cc = ciaclocks; - if (cc > this.starta) cc -= this.starta; - else cc = 0; - //assert ((this.ta + 1) >= cc); - this.taPassed = cc; - } - if ((this.crb & 0x61) == 0x01) { - var cc = ciaclocks; - if (cc > this.startb) cc -= this.startb; - else cc = 0; - //assert ((this.tb + 1) >= cc); - this.tbPassed = cc; - } - } - - this.read = function (addr) { - var reg = addr & 15; - var tmp; - - this.calcPassedTime(); - - switch (reg) { - case 0: { - if (this.type == CIA_A) { - tmp = AMIGA.disk.status() & 0x3c; - - if (AMIGA.config.ports[0].type == SAEV_Config_Ports_Type_Mouse) { - if (!AMIGA.input.mouse.button[0]) tmp |= 0x40; - if (this.dra & 0x40) tmp = (tmp & ~0x40) | (this.pra & 0x40); - } else if (AMIGA.config.ports[0].type == SAEV_Config_Ports_Type_Joy0) { - if (!AMIGA.input.joystick[0].button[0]) tmp |= 0x40; - if (this.dra & 0x40) tmp = (tmp & ~0x40) | (this.pra & 0x40); - } else tmp |= 0x40; - - if (AMIGA.config.ports[1].type == SAEV_Config_Ports_Type_Joy1) { - if (!AMIGA.input.joystick[1].button[0]) tmp |= 0x80; - if (this.dra & 0x80) tmp = (tmp & ~0x80) | (this.pra & 0x80); - } else tmp |= 0x80; - - tmp |= (this.pra | (this.dra ^ 3)) & 3; - } else { - //tmp = 0xf8; - tmp = AMIGA.serial.readStatus(this.dra); - } - return tmp; - } - case 1: { - if (this.type == CIA_A) { - tmp = 0; - } else { - tmp = this.prb; - } - if (this.crb & 2) { - var pb7 = 0; - if (this.crb & 4) pb7 = this.crb & 1; - tmp &= ~0x80; - tmp |= pb7 ? 0x80 : 0; - } - if (this.cra & 2) { - var pb6 = 0; - if (this.cra & 4) pb6 = this.cra & 1; - tmp &= ~0x40; - tmp |= pb6 ? 0x40 : 0; - } - return tmp; - } - case 2: - return this.dra; - case 3: - return this.drb; - case 4: - return ((this.ta - this.taPassed) & 0xff); - case 5: - return ((this.ta - this.taPassed) >> 8) & 0xff; - case 6: - return ((this.tb - this.tbPassed) & 0xff); - case 7: - return ((this.tb - this.tbPassed) >> 8) & 0xff; - case 8: { - if (this.tlatch) { - this.tlatch = 0; - return this.tol & 0xff; - } else return this.tod & 0xff; - } - case 9: { - if (this.tlatch) return (this.tol >> 8) & 0xff; - else return (this.tod >> 8) & 0xff; - } - case 10: { - if (!this.tlatch) { - if (!(this.crb & 0x80)) this.tlatch = 1; - this.tol = this.tod; - } - return (this.tol >>> 16) & 0xff; - } - case 12: - return this.sdr; - case 13: { - tmp = this.icrReg; - this.icr &= ~this.icrReg; - this.icrReg = 0; - this.reThink(); - return tmp; - } - case 14: - return this.cra; - case 15: - return this.crb; - } - } - - this.write = function (addr, val) { - var reg = addr & 15; - - switch (reg) { - case 0: { - if (this.type == CIA_A) { - this.pra = (this.pra & 0x3c) | (val & 0xc3); - AMIGA.cia.handlePowerLED(this.pra, this.dra); - } else { - this.pra = val; - AMIGA.serial.writeStatus(this.pra, this.dra); - } - break; - } - case 1: { - if (this.type == CIA_A) { - this.prb = val; - } else { - this.prb = val; - AMIGA.disk.select(val); - } - break; - } - case 2: { - if (this.type == CIA_A) { - this.dra = val; - AMIGA.cia.handlePowerLED(this.pra, this.dra); - } else { - this.dra = val; - AMIGA.serial.writeStatus(this.pra, this.dra); - } - break; - } - case 3: { - if (this.type == CIA_A) { - this.drb = val; - } else { - this.drb = val; - } - break; - } - case 4: { - AMIGA.cia.update(); - this.la = (this.la & 0xff00) | val; - AMIGA.cia.calcTimers(); - break; - } - case 5: { - AMIGA.cia.update(); - this.la = (this.la & 0x00ff) | (val << 8); - if ((this.cra & 1) == 0) this.ta = this.la; - if (this.cra & 8) { - this.ta = this.la; - this.cra |= 1; - this.starta = STARTCYCLESHI; - } - AMIGA.cia.calcTimers(); - break; - } - case 6: { - AMIGA.cia.update(); - this.lb = (this.lb & 0xff00) | val; - AMIGA.cia.calcTimers(); - break; - } - case 7: { - AMIGA.cia.update(); - this.lb = (this.lb & 0x00ff) | (val << 8); - if ((this.crb & 1) == 0) this.tb = this.lb; - if (this.crb & 8) { - this.tb = this.lb; - this.crb |= 1; - this.startb = STARTCYCLESHI; - } - AMIGA.cia.calcTimers(); - break; - } - case 8: { - if (this.crb & 0x80) { - this.alarm = (this.alarm & 0xffff00) | val; - } else { - this.tod = (this.tod & 0xffff00) | val; - this.todOn = true; - this.checkAlarm(0); - } - break; - } - case 9: { - if (this.crb & 0x80) { - this.alarm = (this.alarm & 0xff00ff) | (val << 8); - } else { - this.tod = (this.tod & 0xff00ff) | (val << 8); - } - break; - } - case 10: { - if (this.crb & 0x80) { - this.alarm = (this.alarm & 0x00ffff) | (val << 16); - } else { - this.tod = (this.tod & 0x00ffff) | (val << 16); - this.todOn = false; - } - break; - } - case 12: { - AMIGA.cia.update(); - this.sdr = val; - if (this.type == CIA_B && (this.cra & 0x40) == 0) this.sdrCnt = 0; - if ((this.cra & 0x41) == 0x41 && this.sdrCnt == 0) this.sdrCnt = 8 * 2; - AMIGA.cia.calcTimers(); - break; - } - case 13: { - this.setClr(val); - break; - } - case 14: { - AMIGA.cia.update(); - val &= 0x7f; - if ((val & 1) && !(this.cra & 1)) this.starta = STARTCYCLESCRA; - if (this.type == CIA_A && (val & 0x40) != (this.cra & 0x40)) { - AMIGA.input.keyboard.lostsynccnt = 0; - //BUG.info('KB_ACK %02x to %02x', val, this.cra); - } - this.cra = val; - if (this.cra & 0x10) { - this.cra &= ~0x10; - this.ta = this.la; - } - AMIGA.cia.calcTimers(); - break; - } - case 15: { - AMIGA.cia.update(); - if ((val & 1) && !(this.crb & 1)) this.startb = STARTCYCLESCRA; - this.crb = val; - if (this.crb & 0x10) { - this.crb &= ~0x10; - this.tb = this.lb; - } - AMIGA.cia.calcTimers(); - break; - } - } - } -} +//console.log('DIV10', CYCLE_UNIT, DIV10); function CIA() { - this.A = new CIA_8520(CIA_A); - this.B = new CIA_8520(CIA_B); - this.div10 = 0; + var ciaaicr = 0, ciaaimask = 0, ciabicr = 0, ciabimask = 0; + var ciaacra = 0, ciaacrb = 0, ciabcra = 0, ciabcrb = 0; + var ciaastarta = 0, ciaastartb = 0, ciabstarta = 0, ciabstartb = 0; + var ciaaicr_reg = 0, ciabicr_reg = 0; - var led = true; + var ciaata = 0, ciaatb = 0, ciabta = 0, ciabtb = 0; + var ciaata_passed = 0, ciaatb_passed = 0, ciabta_passed = 0, ciabtb_passed = 0; - var todHack = { - active: true, - enabled: false, - rate: 0.0, - tv: 0.0 - }; + var ciaatod = 0, ciabtod = 0, ciaatol = 0, ciabtol = 0, ciaaalarm = 0, ciabalarm = 0; + var ciaatlatch = 0, ciabtlatch = 0; + var oldled = false;//, oldovl = false, oldcd32mute = false; + var led = false; + var led_old_brightness = 0; + var led_cycles_on = 0, led_cycles_off = 0, led_cycle = 0; - this.setup = function() { - if (todHack.active) todHack.rate = 1000.0 / AMIGA.events.hz; + var ciaala = 0, ciaalb = 0, ciabla = 0, ciablb = 0; + var ciaatodon = 0, ciabtodon = 0; + var ciaapra = 0, ciaaprb = 0, ciaadra = 0, ciaadrb = 0, ciaasdr = 0, ciaasdr_cnt = 0; + var ciabpra = 0, ciabprb = 0, ciabdra = 0, ciabdrb = 0, ciabsdr = 0, ciabsdr_cnt = 0; + var div10 = 0; + //var kbstate = 0, kblostsynccnt = 0, kbcode = 0; + + var serbits = 0; + var warned = 10; + //var rtc_delayed_write = 0; + + /*function setclr (unsigned int *p, unsigned int val) { + if (val & 0x80) { + *p |= val & 0x7F; + } else { + *p &= ~val; + } + }*/ + + function setclra(val) { + if (val & 0x80) { + ciaaimask |= val & 0x7F; + } else { + ciaaimask &= ~val; + } } - - this.reset = function() { - this.A.reset(); - this.B.reset(); - this.div10 = 0; - this.calcTimers(); - - led = true; - AMIGA.disk.select_set(this.B.prb); - - if (todHack.active) { - todHack.enabled = AMIGA.events.maxvpos * AMIGA.events.hz * 10; - todHack.tv = 0.0; + function setclrb(val) { + if (val & 0x80) { + ciabimask |= val & 0x7F; + } else { + ciabimask &= ~val; } } - this.dump = function() { - this.A.dump(); - this.B.dump(); - } - - this.handlePowerLED = function (pra, dra) { - var v = pra | (~dra & 0xff); - var newled = (v & 2) ? 0 : 1; - - if (led != newled) { - led = newled; - AMIGA.audio.filter.led_filter_on = led; - AMIGA.config.hooks.power_led(led); + function RethinkICRA() { + if (ciaaicr) { + if (ciaaimask & ciaaicr) { + ciaaicr |= 0x80; + AMIGA.INTREQ_0(0x8000 | 0x0008); + } + ciaaicr_reg |= ciaaicr; } } - this.setICR = function (type, icr, sdr) { - if (type == CIA_A) - this.A.setICR(icr, sdr); - else - this.B.setICR(icr, sdr); + function RethinkICRB() { + if (ciabicr) { + if (ciabimask & ciabicr) { + ciabicr |= 0x80; + AMIGA.INTREQ_0(0x8000 | 0x2000); + } + ciabicr_reg |= ciabicr; + } } - this.ICR = function(type) { - if (type == CIA_A) - this.A.ICR(); - else - this.B.ICR(); + this.SetICRA = function(icr, sdr) { + ciaaicr |= icr; + ciaasdr = sdr; + RethinkICRA(); + } + + this.SetICRB = function(icr, sdr) { + ciabicr |= icr; + if (sdr !== null) + ciabsdr = sdr; + RethinkICRB(); + } + + this.rethink = function() { + RethinkICRA(); + RethinkICRB(); } - this.reThink = function() { - this.A.reThink(); - this.B.reThink(); - } - - this.update = function() { - var ccount = AMIGA.events.currcycle - AMIGA.events.eventtab[EV_CIA].oldcycles + this.div10; + /* Figure out how many CIA timer cycles have passed for each timer since the last call of CIA_calctimers. */ + function compute_passed_time() { + var ccount = (AMIGA.events.currcycle - AMIGA.events.eventtab[EV_CIA].oldcycles + div10); var ciaclocks = Math.floor(ccount / DIV10); - this.div10 = ccount % DIV10; + ciaata_passed = ciaatb_passed = ciabta_passed = ciabtb_passed = 0; - //BUG.info('CIA.update() %d %d', ciaclocks, this.div10); + /* CIA A timers */ + if ((ciaacra & 0x21) == 0x01) { + var cc = ciaclocks; + if (cc > ciaastarta) + cc -= ciaastarta; + else + cc = 0; + //assert((ciaata + 1) >= cc); + ciaata_passed = cc; + } + if ((ciaacrb & 0x61) == 0x01) { + var cc = ciaclocks; + if (cc > ciaastartb) + cc -= ciaastartb; + else + cc = 0; + //assert((ciaatb + 1) >= cc); + ciaatb_passed = cc; + } - var a = this.A.updateCheck(ciaclocks); - var b = this.B.updateCheck(ciaclocks); - if (a) this.A.reThink(); - if (b) this.B.reThink(); + /* CIA B timers */ + if ((ciabcra & 0x21) == 0x01) { + var cc = ciaclocks; + if (cc > ciabstarta) + cc -= ciabstarta; + else + cc = 0; + //assert((ciabta + 1) >= cc); + ciabta_passed = cc; + } + if ((ciabcrb & 0x61) == 0x01) { + var cc = ciaclocks; + if (cc > ciabstartb) + cc -= ciabstartb; + else + cc = 0; + //assert((ciabtb + 1) >= cc); + ciabtb_passed = cc; + } } - this.calcTimers = function() { + /* Called to advance all CIA timers to the current time. This expects that + one of the timer values will be modified, and CIA_calctimers will be called + in the same cycle. */ + + function CIA_update_check() { + var ccount = (AMIGA.events.currcycle - AMIGA.events.eventtab[EV_CIA].oldcycles + div10); + var ciaclocks = Math.floor(ccount / DIV10); + + var aovfla = 0, aovflb = 0, asp = 0, bovfla = 0, bovflb = 0, bsp = 0; + var icr = 0; + + div10 = ccount % DIV10; + + /* CIA A timers */ + if ((ciaacra & 0x21) == 0x01) { + var check = true; + var cc = ciaclocks; + if (ciaastarta > 0) { + if (cc > ciaastarta) { + cc -= ciaastarta; + ciaastarta = 0; + } else { + ciaastarta -= cc; + check = false; + } + } + if (check) { + //assert((ciaata + 1) >= cc); + if ((ciaata + 1) == cc) { + if ((ciaacra & 0x48) == 0x40 && ciaasdr_cnt > 0 && --ciaasdr_cnt == 0) + asp = 1; + aovfla = 1; + if ((ciaacrb & 0x61) == 0x41 || (ciaacrb & 0x61) == 0x61) { + if (ciaatb-- == 0) + aovflb = 1; + } + } + ciaata -= cc; + } + } + if ((ciaacrb & 0x61) == 0x01) { + var check = true; + var cc = ciaclocks; + if (ciaastartb > 0) { + if (cc > ciaastartb) { + cc -= ciaastartb; + ciaastartb = 0; + } else { + ciaastartb -= cc; + check = false; + } + } + if (check) { + //assert((ciaatb + 1) >= cc); + if ((ciaatb + 1) == cc) + aovflb = 1; + ciaatb -= cc; + } + } + + /* CIA B timers */ + if ((ciabcra & 0x21) == 0x01) { + var check = true; + var cc = ciaclocks; + if (ciabstarta > 0) { + if (cc > ciabstarta) { + cc -= ciabstarta; + ciabstarta = 0; + } else { + ciabstarta -= cc; + check = false; + } + } + if (check) { + //assert((ciabta + 1) >= cc); + if ((ciabta + 1) == cc) { + if ((ciabcra & 0x48) == 0x40 && ciabsdr_cnt > 0 && --ciabsdr_cnt == 0) + bsp = 1; + bovfla = 1; + if ((ciabcrb & 0x61) == 0x41 || (ciabcrb & 0x61) == 0x61) { + if (ciabtb-- == 0) + bovflb = 1; + } + } + ciabta -= cc; + } + } + if ((ciabcrb & 0x61) == 0x01) { + var check = true; + var cc = ciaclocks; + if (ciabstartb > 0) { + if (cc > ciabstartb) { + cc -= ciabstartb; + ciabstartb = 0; + } else { + ciabstartb -= cc; + check = false; + } + } + if (check) { + //assert((ciabtb + 1) >= cc); + if ((ciabtb + 1) == cc) + bovflb = 1; + ciabtb -= cc; + } + } + + if (aovfla) { + ciaaicr |= 1; icr = 1; + ciaata = ciaala; + if (ciaacra & 0x8) { + ciaacra &= ~1; + } + } + if (aovflb) { + ciaaicr |= 2; icr = 1; + ciaatb = ciaalb; + if (ciaacrb & 0x8) { + ciaacrb &= ~1; + } + } + if (asp) { + ciaaicr |= 8; icr = 1; + } + if (bovfla) { + ciabicr |= 1; icr |= 2; + ciabta = ciabla; + if (ciabcra & 0x8) { + ciabcra &= ~1; + } + } + if (bovflb) { + ciabicr |= 2; icr |= 2; + ciabtb = ciablb; + if (ciabcrb & 0x8) { + ciabcrb &= ~1; + } + } + if (bsp) { + ciabicr |= 8; icr |= 2; + } + return icr; + } + + function CIA_update() { + var icr = CIA_update_check (); + if (icr & 1) + RethinkICRA(); + if (icr & 2) + RethinkICRB(); + } + + /* Call this only after CIA_update has been called in the same cycle. */ + function CIA_calctimers() { + var ciaatimea = -1, ciaatimeb = -1, ciabtimea = -1, ciabtimeb = -1; + var div10diff = DIV10 - div10; + + if ((ciaacra & 0x21) == 0x01) ciaatimea = div10diff + DIV10 * (ciaata + ciaastarta); + if ((ciaacrb & 0x61) == 0x01) ciaatimeb = div10diff + DIV10 * (ciaatb + ciaastartb); + if ((ciabcra & 0x21) == 0x01) ciabtimea = div10diff + DIV10 * (ciabta + ciabstarta); + if ((ciabcrb & 0x61) == 0x01) ciabtimeb = div10diff + DIV10 * (ciabtb + ciabstartb); + AMIGA.events.eventtab[EV_CIA].oldcycles = AMIGA.events.currcycle; + AMIGA.events.eventtab[EV_CIA].active = (ciaatimea != -1 || ciaatimeb != -1 || ciabtimea != -1 || ciabtimeb != -1); - var div10diff = DIV10 - this.div10; - var a = this.A.calcTimers(div10diff); - var b = this.B.calcTimers(div10diff); - - AMIGA.events.eventtab[EV_CIA].active = (a[0] != -1 || a[1] != -1 || b[0] != -1 || b[1] != -1); if (AMIGA.events.eventtab[EV_CIA].active) { - var evtime = 0xffffffff; - - if (a[0] != -1) evtime = a[0]; - if (a[1] != -1 && a[1] < evtime) evtime = a[1]; - if (b[0] != -1 && b[0] < evtime) evtime = b[0]; - if (b[1] != -1 && b[1] < evtime) evtime = b[1]; - - AMIGA.events.eventtab[EV_CIA].evtime = evtime + AMIGA.events.currcycle; - //BUG.info('CIA.calcTimers() evtime %d', evtime); + var ciatime = CYCLE_MAX; + if (ciaatimea != -1) ciatime = ciaatimea; + if (ciaatimeb != -1 && ciaatimeb < ciatime) ciatime = ciaatimeb; + if (ciabtimea != -1 && ciabtimea < ciatime) ciatime = ciabtimea; + if (ciabtimeb != -1 && ciabtimeb < ciatime) ciatime = ciabtimeb; + AMIGA.events.eventtab[EV_CIA].evtime = ciatime + AMIGA.events.currcycle; } AMIGA.events.schedule(); } this.handler = function() { - this.update(); - this.calcTimers(); + CIA_update(); + CIA_calctimers(); } - this.handleTodHack = function() { - if (todHack.enabled > 1) { - todHack.enabled--; - if (todHack.enabled == 1) { - todHack.tv = new Date().getTime(); - BUG.info('CIA.handleTodHack() enabled'); + /*this.diskindex = function() { + ciabicr |= 0x10; + RethinkICRB(); + } + this.parallelack = function() { + ciaaicr |= 0x10; + RethinkICRA(); + }*/ + + function checkalarm (tod, alarm, inc) { + if (tod == alarm) + return 1; + if (!inc) + return 0; + /* emulate buggy TODMED counter. + * it counts: .. 29 2A 2B 2C 2D 2E 2F 20 30 31 32 .. + * (2F->20->30 only takes couple of cycles but it will trigger alarm.. + */ + if (tod & 0x000fff) + return 0; + if (((tod - 1) & 0xfff000) == alarm) + return 1; + return 0; + } + + function ciab_checkalarm(inc) { + if (checkalarm(ciabtod, ciabalarm, inc)) { + ciabicr |= 4; + RethinkICRB(); + } + } + + function ciaa_checkalarm(inc) { + if (checkalarm(ciaatod, ciaaalarm, inc)) { + ciaaicr |= 4; + RethinkICRA(); + } + } + + function gettimeofday() { + return Math.floor(new Date().getTime()); + } + +//#ifdef TOD_HACK + var tod_hack_tv = 0, tod_hack_tod = 0, tod_hack_tod_last = 0; + var tod_hack_enabled = -1; + const TOD_HACK_TIME = 312 * 50 * 10; + function tod_hack_reset() { + //var tv; + //gettimeofday (&tv, NULL); + //tod_hack_tv = (uae_u64)tv.tv_sec * 1000000 + tv.tv_usec; + tod_hack_tv = gettimeofday(); + tod_hack_tod = ciaatod; + tod_hack_tod_last = tod_hack_tod; + } +//#endif + + /*var heartbeat_cnt = 0; + function cia_heartbeat() { + heartbeat_cnt = 10; + }*/ + + var oldrate = 0; + function do_tod_hack(dotod) { + //console.log('tod',tod_hack_enabled); + //var tv; + var t; + var rate; + var docount = 0; + + if (tod_hack_enabled == 0) + return; + /*if (!heartbeat_cnt) { + if (tod_hack_enabled > 0) + tod_hack_enabled = -1; + return; + }*/ + if (tod_hack_enabled < 0) { + tod_hack_enabled = TOD_HACK_TIME; + return; + } + if (tod_hack_enabled > 1) { + tod_hack_enabled--; + if (tod_hack_enabled == 1) { + BUG.info('TOD HACK enabled'); + tod_hack_reset(); } return; } - if (new Date().getTime() - todHack.tv >= todHack.rate) { - this.A.tod++; - this.A.tod &= 0xffffff; - this.A.checkAlarm(0); - todHack.tv += todHack.rate; + + if (AMIGA.config.cia.tod == 0) + rate = Math.floor(AMIGA.playfield.vblank_hz + 0.5); + else if (AMIGA.config.cia.tod == 1) + rate = 50; + else + rate = 60; + if (rate <= 0) + return; + if (rate != oldrate || ciaatod != tod_hack_tod_last) { + if (ciaatod != 0) BUG.info('TOD HACK reset %d,%d %d,%d', rate, oldrate, ciaatod, tod_hack_tod_last); + tod_hack_reset(); + oldrate = rate; + docount = 1; + } + if (!dotod && AMIGA.config.cia.tod == 0) + return; + + /*gettimeofday (&tv, NULL); + t = (uae_u64)tv.tv_sec * 1000000 + tv.tv_usec; + if (t - tod_hack_tv >= 1000000 / rate) { + tod_hack_tv += 1000000 / rate; + docount = 1; + }*/ + t = gettimeofday(); + if (t - tod_hack_tv >= Math.floor(1000 / rate)) { + tod_hack_tv += Math.floor(1000 / rate); + docount = 1; + } + if (docount) { + ciaatod++; + ciaatod &= 0x00ffffff; + tod_hack_tod_last = ciaatod; + ciaa_checkalarm(0); } } - this.hSyncPre = function() { + //this.hsync_prehandler = function() {} - } - - this.hSyncPost = function (doTod) { - if (this.B.todOn && doTod) { - this.B.tod++; - this.B.tod &= 0xffffff; - this.B.checkAlarm(1); + this.hsync_posthandler = function(dotod) { + if (ciabtodon && dotod) { + ciabtod++; + ciabtod &= 0xFFFFFF; + ciab_checkalarm(1); } + if (AMIGA.config.cia.tod_hack && ciaatodon) + do_tod_hack(dotod); - if (todHack.active && this.A.todOn) this.handleTodHack(); - + /*if (resetwarning_phase) { + resetwarning_check (); + while (keys_available ()) + get_next_key (); + } else if ((keys_available () || kbstate < 3) && !kblostsynccnt && (hsync_counter & 15) == 0) { + switch (kbstate) { + case 0: + kbcode = 0; + kbstate++; + break; + case 1: + setcode(AK_INIT_POWERUP); + kbstate++; + break; + case 2: + setcode(AK_TERM_POWERUP); + kbstate++; + break; + case 3: + kbcode = ~get_next_key(); + break; + } + keyreq(); + }*/ AMIGA.input.keyboard.hsync(); } - this.vSyncPre = function() { + function calc_led(old_led) { + var c = AMIGA.events.currcycle; + var t = Math.floor((c - led_cycle) * CYCLE_UNIT_INV); + if (old_led) + led_cycles_on += t; + else + led_cycles_off += t; + led_cycle = c; + } + + var powerled_brightness = 255; + var powerled = true; + function led_vsync() { + var v; + + calc_led(led); + if (led_cycles_on && !led_cycles_off) + v = 255; + else if (led_cycles_off && !led_cycles_on) + v = 0; + else if (led_cycles_off) + v = Math.floor(led_cycles_on * 255 / (led_cycles_on + led_cycles_off)); + else + v = 255; + if (v < 0) v = 0; + if (v > 255) v = 255; + + /*gui_data.powerled_brightness = v; + if (led_old_brightness != gui_data.powerled_brightness) { + gui_data.powerled = gui_data.powerled_brightness > 127; + gui_led (LED_POWER, gui_data.powerled); + led_filter_audio (); + } + led_old_brightness = gui_data.powerled_brightness;*/ + + powerled_brightness = v; + if (led_old_brightness != powerled_brightness) { + powerled = powerled_brightness > 127; + AMIGA.config.hooks.power_led(powerled); + AMIGA.audio.filter.led_filter_on = powerled; + } + led_old_brightness = powerled_brightness; + + led_cycle = AMIGA.events.currcycle; + led_cycles_on = 0; + led_cycles_off = 0; + } + + this.vsync_prehandler = function() { + /*if (rtc_delayed_write < 0) { + rtc_delayed_write = 50; + } else if (rtc_delayed_write > 0) { + rtc_delayed_write--; + if (rtc_delayed_write == 0) + write_battclock (); + }*/ + led_vsync(); this.handler(); + /*if (kblostsynccnt > 0) { + kblostsynccnt -= maxvpos; + if (kblostsynccnt <= 0) { + kblostsynccnt = 0; + keyreq (); + write_log (_T('lostsync\n')); + } + }*/ AMIGA.input.keyboard.vsync(); } - this.vSyncPost = function (doTod) { - if (todHack.active && todHack.enabled == 1) return; - - if (this.A.todOn && doTod) { - this.A.tod++; - this.A.tod &= 0xffffff; - this.A.checkAlarm(1); + this.vsync_posthandler = function(dotod) { + //if (heartbeat_cnt > 0) heartbeat_cnt--; + if (TOD_HACK) { + if (AMIGA.config.cia.tod_hack && tod_hack_enabled == 1) + return; } - } - - this.waitPre = function() { - //if (AMIGA.config.cpu.cachesize) return; - -//#ifndef CUSTOM_SIMPLE - /*var div = (AMIGA.events.currcycle - AMIGA.events.eventtab[EV_CIA].oldcycles) % DIV10; - var div2 = Math.floor(DIV10 * ECLOCK_DATA_CYCLE / 10); - var cycles; - - if (div >= div2) - cycles = DIV10 - div + div2; - else if (div) - cycles = DIV10 + div2 - div; - else - cycles = div2 - div; - - //BUG.info('CIA.waitPre() %d %d', div, cycles); - - if (cycles) { - if (AMIGA.config.cpu.exact) - AMIGA.events.cycle(cycles); - else - AMIGA.events.cycle(cycles); + if (ciaatodon && dotod) { + ciaatod++; + ciaatod &= 0xFFFFFF; + ciaa_checkalarm (1); + } + /*if (vpos == 0) { + write_log ('%d', vsync_counter); + this.dump(); }*/ -//#endif } - this.waitPost = function () { - AMIGA.events.cycle(6 * CYCLE_UNIT / 2); + function bfe001_change() { + var v = ciaapra; + var led2; - /*if (AMIGA.config.cpu.cachesize) - AMIGA.events.cycle(8 * CYCLE_UNIT /2); - else*/ { - var c = 6 * CYCLE_UNIT / 2; - if (AMIGA.config.cpu.exact) - AMIGA.events.cycle(c); + v |= ~ciaadra; /* output is high when pin's direction is input */ + led2 = (v & 2) ? 0 : 1; + if (led2 != led) { + calc_led(led); + led = led2; + led_old_brightness = -1; + } + /*if (currprefs.cs_ciaoverlay && (v & 1) != oldovl) { + oldovl = v & 1; + if (!oldovl) { + map_overlay (1); + } else { + //activate_debugger (); + map_overlay (0); + } + } + if (currprefs.cs_cd32cd && (v & 1) != oldcd32mute) { + oldcd32mute = v & 1; + akiko_mute (oldcd32mute ? 0 : 1); + }*/ + } + + function handle_joystick_buttons(pra, dra) { + var tmp = 0; + if (AMIGA.config.ports[0].type == SAEV_Config_Ports_Type_Mouse) { + if (!AMIGA.input.mouse.button[0]) tmp |= 0x40; + if (dra & 0x40) tmp = (tmp & ~0x40) | (pra & 0x40); + } else if (AMIGA.config.ports[0].type == SAEV_Config_Ports_Type_Joy0) { + if (!AMIGA.input.joystick[0].button[0]) tmp |= 0x40; + if (dra & 0x40) tmp = (tmp & ~0x40) | (pra & 0x40); + } else tmp |= 0x40; + + if (AMIGA.config.ports[1].type == SAEV_Config_Ports_Type_Joy1) { + if (!AMIGA.input.joystick[1].button[0]) tmp |= 0x80; + if (dra & 0x80) tmp = (tmp & ~0x80) | (pra & 0x80); + } else tmp |= 0x80; + + return tmp; + } + + function handle_parport_joystick (port, pra, dra) { + var v; + switch (port) { + case 0: + v = (pra & dra) | (dra ^ 0xff); + return v; + case 1: + v = ((pra & dra) | (dra ^ 0xff)) & 0x7; + return v; + default: + return 0; + } + } + + function ReadCIAA(addr) { + var tmp; + var reg = addr & 15; + + compute_passed_time(); + + //if (CIAA_DEBUG_R) write_log (_T('R_CIAA: bfe%x01 %08X\n'), reg, M68K_GETPC); + + switch (reg) { + case 0: + tmp = AMIGA.disk.status() & 0x3c; + tmp |= handle_joystick_buttons(ciaapra, ciaadra); + tmp |= (ciaapra | (ciaadra ^ 3)) & 0x03; + //tmp = dongle_cia_read (0, reg, tmp); + //if (DONGLE_DEBUG && notinrom()) write_log (_T('BFE001 R %02X %s\n'), tmp, debuginfo(0)); + return tmp; + case 1: +/*#ifdef PARALLEL_PORT + if (isprinter () > 0) { + tmp = ciaaprb; + } else if (isprinter () < 0) { + uae_u8 v; + parallel_direct_read_data (&v); + tmp = v; + } else if (currprefs.win32_samplersoundcard >= 0) { + tmp = sampler_getsample ((ciabpra & 4) ? 1 : 0); + } else +#endif*/ + { + tmp = handle_parport_joystick(0, ciaaprb, ciaadrb); + //tmp = dongle_cia_read (1, reg, tmp); + //if (DONGLE_DEBUG && notinrom()) write_log (_T('BFE101 R %02X %s\n'), tmp, debuginfo(0)); + } + if (ciaacrb & 2) { + var pb7 = 0; + if (ciaacrb & 4) + pb7 = ciaacrb & 1; + tmp &= ~0x80; + tmp |= pb7 ? 0x80 : 0; + } + if (ciaacra & 2) { + var pb6 = 0; + if (ciaacra & 4) + pb6 = ciaacra & 1; + tmp &= ~0x40; + tmp |= pb6 ? 0x40 : 0; + } + return tmp; + case 2: + //if (DONGLE_DEBUG && notinrom()) write_log (_T('BFE201 R %02X %s\n'), ciaadra, debuginfo(0)); + return ciaadra; + case 3: + //if (DONGLE_DEBUG && notinrom()) write_log (_T('BFE301 R %02X %s\n'), ciaadrb, debuginfo(0)); + return ciaadrb; + case 4: + return (ciaata - ciaata_passed) & 0xff; + case 5: + return ((ciaata - ciaata_passed) >> 8) & 0xff; + case 6: + return (ciaatb - ciaatb_passed) & 0xff; + case 7: + return ((ciaatb - ciaatb_passed) >> 8) & 0xff; + case 8: + if (ciaatlatch) { + ciaatlatch = 0; + return ciaatol & 0xff; + } else + return ciaatod & 0xff; + case 9: + if (ciaatlatch) + return (ciaatol >> 8) & 0xff; else - AMIGA.events.cycle(c); + return (ciaatod >> 8) & 0xff; + case 10: + if (!ciaatlatch) { + if (!(ciaacrb & 0x80)) + ciaatlatch = 1; + ciaatol = ciaatod; + } + return (ciaatol >> 16) & 0xff; + case 12: + return ciaasdr; + case 13: + tmp = ciaaicr_reg; + ciaaicr &= ~ciaaicr_reg; + ciaaicr_reg = 0; + RethinkICRA(); + return tmp; + case 14: + return ciaacra; + case 15: + return ciaacrb; + } + return 0; + } + + function ReadCIAB(addr) { + var tmp; + var reg = addr & 15; + + //if ((addr >= 8 && addr <= 10) || CIAB_DEBUG_R > 1) write_log (_T('R_CIAB: bfd%x00 %08X\n'), reg, M68K_GETPC); + + compute_passed_time (); + + switch (reg) { + case 0: + //if (currprefs.use_serial) + tmp = AMIGA.serial.readStatus(ciabdra); +/*#ifdef PARALLEL_PORT + if (isprinter () > 0) { + //tmp |= ciabpra & (0x04 | 0x02 | 0x01); + tmp &= ~3; // clear BUSY and PAPEROUT + tmp |= 4; // set SELECT + } else if (isprinter () < 0) { + uae_u8 v; + parallel_direct_read_status (&v); + tmp |= v & 7; + } else +#endif*/ + { + tmp |= handle_parport_joystick(1, ciabpra, ciabdra); + //tmp = dongle_cia_read (1, reg, tmp); + //if (DONGLE_DEBUG && notinrom()) write_log (_T('BFD000 R %02X %s\n'), tmp, debuginfo(0)); + } + return tmp; + case 1: + if (DONGLE_DEBUG && notinrom()) write_log (_T('BFD100 R %02X %s\n'), ciabprb, debuginfo(0)); + tmp = ciabprb; + //tmp = dongle_cia_read(1, reg, tmp); + if (ciabcrb & 2) { + var pb7 = 0; + if (ciabcrb & 4) + pb7 = ciabcrb & 1; + tmp &= ~0x80; + tmp |= pb7 ? 0x80 : 00; + } + if (ciabcra & 2) { + var pb6 = 0; + if (ciabcra & 4) + pb6 = ciabcra & 1; + tmp &= ~0x40; + tmp |= pb6 ? 0x40 : 00; + } + return tmp; + case 2: + return ciabdra; + case 3: + return ciabdrb; + case 4: + return (ciabta - ciabta_passed) & 0xff; + case 5: + return ((ciabta - ciabta_passed) >> 8) & 0xff; + case 6: + return (ciabtb - ciabtb_passed) & 0xff; + case 7: + return ((ciabtb - ciabtb_passed) >> 8) & 0xff; + case 8: + if (ciabtlatch) { + ciabtlatch = 0; + return ciabtol & 0xff; + } else + return ciabtod & 0xff; + case 9: + if (ciabtlatch) + return (ciabtol >> 8) & 0xff; + else + return (ciabtod >> 8) & 0xff; + case 10: + if (!ciabtlatch) { + if (!(ciabcrb & 0x80)) + ciabtlatch = 1; + ciabtol = ciabtod; + } + return (ciabtol >> 16) & 0xff; + case 12: + return ciabsdr; + case 13: + tmp = ciabicr_reg; + ciabicr &= ~ciabicr_reg; + ciabicr_reg = 0; + RethinkICRB(); + return tmp; + case 14: + //write_log (_T('CIABCRA READ %d %x\n'), ciabcra, M68K_GETPC); + return ciabcra; + case 15: + return ciabcrb; + } + return 0; + } + + function WriteCIAA(addr, val) { + var reg = addr & 15; + + //if (CIAA_DEBUG_W) write_log (_T('W_CIAA: bfe%x01 %02X %08X\n'), reg, val, M68K_GETPC); + + /*if (!currprefs.cs_ciaoverlay && oldovl) { + map_overlay (1); + oldovl = 0; + }*/ + switch (reg) { + case 0: + //if (DONGLE_DEBUG && notinrom()) write_log (_T('BFE001 W %02X %s\n'), val, debuginfo(0)); + ciaapra = (ciaapra & ~0xc3) | (val & 0xc3); + bfe001_change(); + //handle_cd32_joystick_cia(ciaapra, ciaadra); + //dongle_cia_write (0, reg, val); + break; + case 1: + //if (DONGLE_DEBUG && notinrom()) write_log (_T('BFE101 W %02X %s\n'), val, debuginfo(0)); + ciaaprb = val; + //dongle_cia_write (0, reg, val); +/*#ifdef PARALLEL_PORT + if (isprinter() > 0) { + doprinter (val); + this.parallelack(); + } else if (isprinter() < 0) { + parallel_direct_write_data (val, ciaadrb); + this.parallelack(); + } +#endif*/ + break; + case 2: + //if (DONGLE_DEBUG && notinrom()) write_log (_T('BFE201 W %02X %s\n'), val, debuginfo(0)); + ciaadra = val; + //dongle_cia_write (0, reg, val); + bfe001_change(); + break; + case 3: + ciaadrb = val; + //dongle_cia_write (0, reg, val); + //if (DONGLE_DEBUG && notinrom()) write_log (_T('BFE301 W %02X %s\n'), val, debuginfo(0)); + break; + case 4: + CIA_update(); + ciaala = (ciaala & 0xff00) | val; + CIA_calctimers(); + break; + case 5: + CIA_update(); + ciaala = (ciaala & 0xff) | (val << 8); + if ((ciaacra & 1) == 0) + ciaata = ciaala; + if (ciaacra & 8) { + ciaata = ciaala; + ciaacra |= 1; + ciaastarta = CIASTARTCYCLESHI; + } + CIA_calctimers(); + break; + case 6: + CIA_update(); + ciaalb = (ciaalb & 0xff00) | val; + CIA_calctimers(); + break; + case 7: + CIA_update(); + ciaalb = (ciaalb & 0xff) | (val << 8); + if ((ciaacrb & 1) == 0) + ciaatb = ciaalb; + if (ciaacrb & 8) { + ciaatb = ciaalb; + ciaacrb |= 1; + ciaastartb = CIASTARTCYCLESHI; + } + CIA_calctimers(); + break; + case 8: + if (ciaacrb & 0x80) { + ciaaalarm = (ciaaalarm & ~0xff) | val; + } else { + ciaatod = (ciaatod & ~0xff) | val; + ciaatodon = 1; + ciaa_checkalarm(0); + } + break; + case 9: + if (ciaacrb & 0x80) { + ciaaalarm = (ciaaalarm & ~0xff00) | (val << 8); + } else { + ciaatod = (ciaatod & ~0xff00) | (val << 8); + } + break; + case 10: + if (ciaacrb & 0x80) { + ciaaalarm = (ciaaalarm & ~0xff0000) | (val << 16); + } else { + ciaatod = (ciaatod & ~0xff0000) | (val << 16); + ciaatodon = 0; + } + break; + case 12: + CIA_update(); + ciaasdr = val; + if ((ciaacra & 0x41) == 0x41 && ciaasdr_cnt == 0) + ciaasdr_cnt = 8 * 2; + CIA_calctimers(); + break; + case 13: + setclra(val); + break; + case 14: + CIA_update(); + val &= 0x7f; /* bit 7 is unused */ + if ((val & 1) && !(ciaacra & 1)) + ciaastarta = CIASTARTCYCLESCRA; + if ((val & 0x40) == 0 && (ciaacra & 0x40) != 0) { + AMIGA.input.keyboard.lostsynccnt = 0; + //if (KB_DEBUG) BUG.info('KB_ACK %02x->%02x', ciaacra, val); + } + ciaacra = val; + if (ciaacra & 0x10) { + ciaacra &= ~0x10; + ciaata = ciaala; + } + CIA_calctimers(); + break; + case 15: + CIA_update(); + if ((val & 1) && !(ciaacrb & 1)) + ciaastartb = CIASTARTCYCLESCRA; + ciaacrb = val; + if (ciaacrb & 0x10) { + ciaacrb &= ~0x10; + ciaatb = ciaalb; + } + CIA_calctimers(); + break; } } - this.load8 = function (addr) { - var v, r = (addr & 0xf00) >> 8; + function WriteCIAB(addr, val) { + var reg = addr & 15; - this.waitPre(); + //if ((addr >= 8 && addr <= 10) || CIAB_DEBUG_W > 1) write_log (_T('W_CIAB: bfd%x00 %02X %08X\n'), reg, val, M68K_GETPC); + switch (reg) { + case 0: + if (DONGLE_DEBUG && notinrom()) write_log (_T('BFD000 W %02X %s\n'), val, debuginfo(0)); + //dongle_cia_write (1, reg, val); + ciabpra = val; + //if (currprefs.use_serial) + AMIGA.serial.writeStatus(ciabpra, ciabdra); +/*#ifdef PARALLEL_PORT + if (isprinter () < 0) + parallel_direct_write_status (val, ciabdra); +#endif*/ + break; + case 1: + //if (DONGLE_DEBUG && notinrom()) write_log (_T('BFD100 W %02X %s\n'), val, debuginfo(0)); + //dongle_cia_write (1, reg, val); + ciabprb = val; + AMIGA.disk.select(val); + break; + case 2: + //if (DONGLE_DEBUG && notinrom()) write_log (_T('BFD200 W %02X %s\n'), val, debuginfo(0)); + //dongle_cia_write (1, reg, val); + ciabdra = val; + //if (currprefs.use_serial) + AMIGA.serial.writeStatus(ciabpra, ciabdra); + break; + case 3: + //if (DONGLE_DEBUG && notinrom()) write_log (_T('BFD300 W %02X %s\n'), val, debuginfo(0)); + //dongle_cia_write (1, reg, val); + ciabdrb = val; + break; + case 4: + CIA_update(); + ciabla = (ciabla & 0xff00) | val; + CIA_calctimers(); + break; + case 5: + CIA_update(); + ciabla = (ciabla & 0xff) | (val << 8); + if ((ciabcra & 1) == 0) + ciabta = ciabla; + if (ciabcra & 8) { + ciabta = ciabla; + ciabcra |= 1; + ciabstarta = CIASTARTCYCLESHI; + } + CIA_calctimers(); + break; + case 6: + CIA_update(); + ciablb = (ciablb & 0xff00) | val; + CIA_calctimers(); + break; + case 7: + CIA_update(); + ciablb = (ciablb & 0xff) | (val << 8); + if ((ciabcrb & 1) == 0) + ciabtb = ciablb; + if (ciabcrb & 8) { + ciabtb = ciablb; + ciabcrb |= 1; + ciabstartb = CIASTARTCYCLESHI; + } + CIA_calctimers(); + break; + case 8: + if (ciabcrb & 0x80) { + ciabalarm = (ciabalarm & ~0xff) | val; + } else { + ciabtod = (ciabtod & ~0xff) | val; + ciabtodon = 1; + ciab_checkalarm (0); + } + break; + case 9: + if (ciabcrb & 0x80) { + ciabalarm = (ciabalarm & ~0xff00) | (val << 8); + } else { + ciabtod = (ciabtod & ~0xff00) | (val << 8); + } + break; + case 10: + if (ciabcrb & 0x80) { + ciabalarm = (ciabalarm & ~0xff0000) | (val << 16); + } else { + ciabtod = (ciabtod & ~0xff0000) | (val << 16); + ciabtodon = 0; + } + break; + case 12: + CIA_update(); + ciabsdr = val; + if ((ciabcra & 0x40) == 0) + ciabsdr_cnt = 0; + if ((ciabcra & 0x41) == 0x41 && ciabsdr_cnt == 0) + ciabsdr_cnt = 8 * 2; + CIA_calctimers(); + break; + case 13: + setclrb(val); + break; + case 14: + CIA_update(); + val &= 0x7f; /* bit 7 is unused */ + if ((val & 1) && !(ciabcra & 1)) + ciabstarta = CIASTARTCYCLESCRA; + ciabcra = val; + if (ciabcra & 0x10) { + ciabcra &= ~0x10; + ciabta = ciabla; + } + CIA_calctimers(); + break; + case 15: + CIA_update(); + if ((val & 1) && !(ciabcrb & 1)) + ciabstartb = CIASTARTCYCLESCRA; + ciabcrb = val; + if (ciabcrb & 0x10) { + ciabcrb &= ~0x10; + ciabtb = ciablb; + } + CIA_calctimers(); + break; + } + } + + this.setup = function() {} + + this.reset = function() { + if (TOD_HACK) { + tod_hack_tv = 0; + tod_hack_tod = 0; + tod_hack_enabled = 0; + if (AMIGA.config.cia.tod_hack) + tod_hack_enabled = TOD_HACK_TIME; + } + //kblostsynccnt = 0; + //serbits = 0; + //oldcd32mute = 1; + oldled = true; + //resetwarning_phase = resetwarning_timer = 0; + //heartbeat_cnt = 0; + + //oldovl = true; + //kbstate = 0; + ciaatlatch = ciabtlatch = 0; + ciaapra = 0; ciaadra = 0; + ciaatod = ciabtod = 0; ciaatodon = ciabtodon = 0; + ciaaicr = ciabicr = ciaaimask = ciabimask = 0; + ciaacra = ciaacrb = ciabcra = ciabcrb = 0x4; /* outmode = toggle; */ + ciaala = ciaalb = ciabla = ciablb = ciaata = ciaatb = ciabta = ciabtb = 0xFFFF; + ciaaalarm = ciabalarm = 0; + ciabpra = 0x8C; ciabdra = 0; + div10 = 0; + ciaasdr_cnt = 0; ciaasdr = 0; + ciabsdr_cnt = 0; ciabsdr = 0; + ciaata_passed = ciaatb_passed = ciabta_passed = ciabtb_passed = 0; + + CIA_calctimers(); + AMIGA.disk.select_set(ciabprb); + + //map_overlay (0); + + //if (currprefs.use_serial) serial_dtr_off (); NI /* Drop DTR at reset */ + } + + this.dump = function() { + BUG.info('A: CRA %02x CRB %02x ICR %02x IM %02x TA %04x (%04x) TB %04x (%04x)', ciaacra, ciaacrb, ciaaicr, ciaaimask, ciaata, ciaala, ciaatb, ciaalb); + BUG.info('TOD %06x (%06x) ALARM %06x %s%s CYC=%.1f', ciaatod, ciaatol, ciaaalarm, ciaatlatch ? 'L' : ' ', ciaatodon ? ' ' : 'S', AMIGA.events.currcycle * CYCLE_UNIT_INV); + BUG.info('B: CRA %02x CRB %02x ICR %02x IM %02x TA %04x (%04x) TB %04x (%04x)', ciabcra, ciabcrb, ciabicr, ciabimask, ciabta, ciabla, ciabtb, ciablb); + BUG.info('TOD %06x (%06x) ALARM %06x %s%s CLK=%.1f', ciabtod, ciabtol, ciabalarm, ciabtlatch ? 'L' : ' ', ciabtodon ? ' ' : 'S', div10 * CYCLE_UNIT_INV); + } + + // Gayle or Fat Gary does not enable CIA /CS lines if both CIAs are selected + // Old Gary based Amigas enable both CIAs in this situation + function issinglecia() { + return false; //currprefs.cs_ide || currprefs.cs_pcmcia || currprefs.cs_mbdmac; + } + function isgayle() { + return false; //currprefs.cs_ide || currprefs.cs_pcmcia; + } + + function cia_wait_pre() { + if (!CUSTOM_SIMPLE) { + var div = (AMIGA.events.currcycle - AMIGA.events.eventtab[EV_CIA].oldcycles) % DIV10; + var tmp = Math.floor(DIV10 * ECLOCK_DATA_CYCLE / 10); + var cycles; + + if (div >= tmp) + cycles = DIV10 - div + tmp; + else if (div) + cycles = DIV10 + tmp - div; + else + cycles = tmp - div; + + if (cycles) + AMIGA.events.cycle(cycles); + } + } + + function cia_wait_post(value) { + AMIGA.events.cycle(6 * CYCLE_UNIT / 2); + } + + function isgaylenocia(addr) { + // gayle CIA region is only 4096 bytes at 0xbfd000 and 0xbfe000 + if (!isgayle()) + return true; + var mask = addr & 0xf000; + return mask == 0xe000 || mask == 0xd000; + } + + this.load8 = function(addr) { + var r = (addr & 0xf00) >> 8; + var v = 0xff; + + if (!isgaylenocia(addr)) + return v; + + cia_wait_pre(); switch ((addr >> 12) & 3) { case 0: - v = (addr & 1) ? this.A.read(r) : this.B.read(r); + if (!issinglecia()) + v = (addr & 1) ? ReadCIAA(r) : ReadCIAB(r); break; case 1: - v = (addr & 1) ? 0xff : this.B.read(r); + v = (addr & 1) ? 0xff : ReadCIAB(r); break; case 2: - v = (addr & 1) ? this.A.read(r) : 0xff; + v = (addr & 1) ? ReadCIAA(r) : 0xff; break; case 3: { - v = 0xff; //if (AMIGA.config.cpu.model == 68000 && AMIGA.config.cpu.compatible) v = (addr & 1) ? regs.irc : regs.irc >> 8; - BUG.info('CIA.load8() unknown CIA address $%08x', addr); + if (warned > 0) { + BUG.info('cia_bget: unknown CIA address %x', addr); + warned--; + } break; } } - this.waitPost(); + cia_wait_post(v); return v; } - this.load16 = function (addr) { - var v, r = (addr & 0xf00) >> 8; + this.load16 = function(addr) { + var r = (addr & 0xf00) >> 8; + var v = 0xffff; - this.waitPre(); + if (!isgaylenocia(addr)) + return v; + + cia_wait_pre(); switch ((addr >> 12) & 3) { case 0: - v = (this.B.read(r) << 8) | this.A.read(r); + if (!issinglecia()) + v = (ReadCIAB(r) << 8) | ReadCIAA(r); break; case 1: - v = (this.B.read(r) << 8) | 0xff; + v = (ReadCIAB(r) << 8) | 0xff; break; case 2: - v = (0xff << 8) | this.A.read(r); + v = (0xff << 8) | ReadCIAA(r); break; case 3: { - v = 0xffff; //if (AMIGA.config.cpu.model == 68000 && AMIGA.config.cpu.compatible) v = regs.irc; - BUG.info('CIA.load16() unknown CIA address $%08x', addr); + if (warned > 0) { + BUG.info('cia_wget: unknown CIA address %x', addr); + warned--; + } break; } } - this.waitPost(); + cia_wait_post(v); return v; } - this.load32 = function (addr) { - return ((this.load16(addr) << 16) | this.load16(addr + 2)) >>> 0; + this.load32 = function(addr) { + var v = this.load16(addr) << 16; + v |= this.load16(addr + 2); + return v >>> 0; } this.store8 = function (addr, value) { var r = (addr & 0xf00) >> 8; - this.waitPre(); - if ((addr & 0x3000) != 0) { - if ((addr & 0x2000) == 0) this.B.write(r, value); - if ((addr & 0x1000) == 0) this.A.write(r, value); + if (!isgaylenocia(addr)) + return; + + cia_wait_pre(); + if (!issinglecia() || (addr & 0x3000) != 0) { + if ((addr & 0x2000) == 0) + WriteCIAB(r, value); + if ((addr & 0x1000) == 0) + WriteCIAA(r, value); + if (((addr & 0x3000) == 0x3000) && warned > 0) { + BUG.info('cia_bput: unknown CIA address %x %x', addr, value); + warned--; + } } - this.waitPost(); + cia_wait_post(value); } this.store16 = function (addr, value) { var r = (addr & 0xf00) >> 8; - this.waitPre(); - if ((addr & 0x3000) != 0) { - if ((addr & 0x2000) == 0) this.B.write(r, value >> 8); - if ((addr & 0x1000) == 0) this.A.write(r, value & 0xff); + if (!isgaylenocia(addr)) + return; + + cia_wait_pre(); + if (!issinglecia() || (addr & 0x3000) != 0) { + if ((addr & 0x2000) == 0) + WriteCIAB(r, value >> 8); + if ((addr & 0x1000) == 0) + WriteCIAA(r, value & 0xff); + if (((addr & 0x3000) == 0x3000) && warned > 0) { + BUG.info('cia_wput: unknown CIA address %x %x', addr, value); + warned--; + } } - this.waitPost(); + cia_wait_post(value); } this.store32 = function (addr, value) { - this.store16(addr, value >>> 16); + this.store16(addr, value >> 16); this.store16(addr + 2, value & 0xffff); } } diff --git a/sae/config.js b/sae/config.js index c501f38..87deb45 100644 --- a/sae/config.js +++ b/sae/config.js @@ -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); } diff --git a/sae/constants.js b/sae/constants.js index 56ce764..5e4407c 100644 --- a/sae/constants.js +++ b/sae/constants.js @@ -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; diff --git a/sae/copper.js b/sae/copper.js index 2bf28e3..d2d630c 100644 --- a/sae/copper.js +++ b/sae/copper.js @@ -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); } } } diff --git a/sae/cpu.js b/sae/cpu.js index a134762..30a58cf 100644 --- a/sae/cpu.js +++ b/sae/cpu.js @@ -6,18 +6,16 @@ * ©2012 Rupert Hausberger * Commercial use is prohibited. * -************************************************************************** +*************************************************************************** * * TODO: * - Faster versions of ASx/LSx/ROx/ROXx and xBCD -* - Complete exception 2/3 handling -* - Explode ADDQ,SUBQ * * Notes: * - Based on M68000PRM.pdf * - Written from scratch. * -*************************************************************************/ +**************************************************************************/ function CPU() { const M_rdd = 1; /* Register Direct Data */ @@ -89,8 +87,10 @@ function CPU() { const undef = false; /* use undef */ var regs = { - d: [0, 0, 0, 0, 0, 0, 0, 0], /* Dn */ - a: [0, 0, 0, 0, 0, 0, 0, 0], /* An */ + //d: [0, 0, 0, 0, 0, 0, 0, 0], /* Dn */ + //a: [0, 0, 0, 0, 0, 0, 0, 0], /* An */ + d: new Uint32Array(8), + a: new Uint32Array(8), /* Status Register (SR) */ t: false, s: false, @@ -104,10 +104,7 @@ function CPU() { usp: 0, /* User Stack Ptr (USP) */ isp: 0, /* Interrupt Stack Ptr (ISP) */ pc: 0, /* Program Counter (PC) */ - /* Interrupts */ - ipl:0, - ipl_pin:0, - stopped:true + stopped:true }; var fault = { op: 0, @@ -116,8 +113,9 @@ function CPU() { ia: false }; var iTab = null; - var doDiss = 0; - + var cpu_cycle_unit = CYCLE_UNIT / 2; + var cpu_cycles = 4 * cpu_cycle_unit; + /*-----------------------------------------------------------------------*/ this.setup = function() { @@ -141,11 +139,8 @@ function CPU() { regs.isp = 0; regs.a[7] = AMIGA.mem.load32(addr); regs.pc = AMIGA.mem.load32(addr + 4); - regs.ipl = regs.ipl_pin = 0; regs.stopped = false; - doDiss = 0; - BUG.say(sprintf('cpu.reset() addr 0x%08x, A7 0x%08x, PC 0x%08x', addr, regs.a[7], regs.pc)); } @@ -225,6 +220,13 @@ function CPU() { } } + function nextOPCode() { + var op = AMIGA.mem.load16(regs.pc); + fault.pc = regs.pc; + fault.op = op; + regs.pc += 2; + return op; + } function nextIWord() { var r = AMIGA.mem.load16(regs.pc); regs.pc += 2; @@ -249,7 +251,7 @@ function CPU() { return add32(add32(base, disp), reg); } } - + function exEA(ea, z) { var dp; @@ -257,23 +259,18 @@ function CPU() { case M_rdd: ea.a = ea.r; ea.t = T_RD; - //ea.c = 0; break; case M_rda: ea.a = ea.r; ea.t = T_RA; - //ea.c = 0; break; case M_ria: ea.a = regs.a[ea.r]; ea.t = T_AD; - //ea.c = z == 4 ? 8 : 4; break; case M_ripo: ea.a = regs.a[ea.r]; ea.t = T_AD; - //ea.c = z == 4 ? 8 : 4; - //regs.a[ea.r] = add32(regs.a[ea.r], z); regs.a[ea.r] += z; if (regs.a[ea.r] > 0xffffffff) { BUG.say(sprintf('exEA() M_ripo A%d > 2^32 ($%x)', ea.r, regs.a[ea.r])); @@ -284,7 +281,6 @@ function CPU() { } break; case M_ripr: - //regs.a[ea.r] = sub32(regs.a[ea.r], z); regs.a[ea.r] -= z; if (regs.a[ea.r] < 0) { BUG.say(sprintf('exEA() M_ripr A%d < 0 ($%x)', ea.r, regs.a[ea.r])); @@ -295,39 +291,32 @@ function CPU() { } ea.a = regs.a[ea.r]; ea.t = T_AD; - //ea.c = z == 4 ? 10 : 6; break; case M_rid: dp = (nextIWord()); ea.a = add32(regs.a[ea.r], extWord(dp)); ea.t = T_AD; - //ea.c = z == 4 ? 12 : 8; break; case M_rii: ea.a = exII(regs.a[ea.r]); ea.t = T_AD; - //ea.c = z == 4 ? 14 : 10; break; case M_pcid: dp = extWord(nextIWord()); ea.a = add32(regs.pc - 2, dp); ea.t = T_AD; - //ea.c = z == 4 ? 12 : 8; break; case M_pcii: ea.a = exII(regs.pc); ea.t = T_AD; - //ea.c = z == 4 ? 14 : 10; break; case M_absw: ea.a = extWord(nextIWord()); ea.t = T_AD; - //ea.c = z == 4 ? 12 : 8; break; case M_absl: ea.a = nextILong(); ea.t = T_AD; - //ea.c = z == 4 ? 16 : 12; break; case M_imm: { if (ea.r == -1) { @@ -341,7 +330,6 @@ function CPU() { } else ea.a = ea.r; ea.t = T_IM; - //ea.c = z == 4 ? 8 : 4; break; } default: @@ -705,15 +693,6 @@ function CPU() { stEA(dea, p.z, sea.a); //ccna //BUG.say(sprintf('I_LEA.%s sea $%08x', szChr(p.z), sea.a)); - /*switch (sea.m) { - case M_ria: return 4; - case M_rid: return 8; - case M_rii: return 12; - case M_pcid: return 8; - case M_pcii: return 12; - case M_absw: return 8; - case M_absl: return 12; - }*/ return p.cyc; } @@ -735,7 +714,7 @@ function CPU() { regs.a[An] = regs.a[7]; regs.a[7] = add32(regs.a[7], dp); //ccna - return p.cyc;//16; + return p.cyc; /*debug var newsp = add32(regs.a[7], dp); @@ -780,7 +759,7 @@ function CPU() { stEA(dea, p.z, s); flgLogical(s, p.z); //BUG.say(sprintf('I_MOVEQ.%s s $%08x', szChr(p.z), s)); - return p.cyc; //4; + return p.cyc; } function I_MOVEM_R2M(p) { @@ -827,8 +806,8 @@ function CPU() { } } //ccna - //BUG.say(sprintf('I_MOVEM_R2M.%s s $%08x d $%08x', szChr(p.z), sea.a, dea.a)); - return p.cyc + (p.z == 2 ? 4 : 8) * n; + //BUG.say(sprintf('I_MOVEM_R2M.%s s $%08x d $%08x', szChr(p.z), sea.a, dea.a)); + return [p.cyc[0] + (p.z == 2 ? 4 : 8) * n, 0,0]; //FIXME } function I_MOVEM_M2R(p) { @@ -858,7 +837,7 @@ function CPU() { } //ccna //BUG.say(sprintf('I_MOVEM_M2R.%s s $%08x d $%08x', szChr(p.z), sea.a, dea.a)); - return p.cyc + (p.z == 2 ? 4 : 8) * n; + return [p.cyc[0] + (p.z == 2 ? 4 : 8) * n, 0,0]; //FIXME } function I_MOVEP(p) { @@ -883,7 +862,7 @@ function CPU() { r += ldEA(sea, 1); r >>>= 0; } - BUG.say(sprintf('I_MOVEP_M2R.%s A%d addr $%08x r $%08x', szChr(p.z), dea.a, sea.a - (p.z == 2 ? 4 : 8), r)); + //BUG.say(sprintf('I_MOVEP_M2R.%s A%d addr $%08x r $%08x', szChr(p.z), dea.a, sea.a - (p.z == 2 ? 4 : 8), r)); stEA(dea, p.z, r); } //R2M @@ -903,10 +882,10 @@ function CPU() { dea.a += 2; stEA(dea, 1, r); } - BUG.say(sprintf('I_MOVEP_R2M.%s A%d addr $%08x r $%08x', szChr(p.z), sea.a, dea.a - (p.z == 2 ? 4 : 8), r)); + //BUG.say(sprintf('I_MOVEP_R2M.%s A%d addr $%08x r $%08x', szChr(p.z), sea.a, dea.a - (p.z == 2 ? 4 : 8), r)); } //ccna - return p.cyc; //p.z == 2 ? 16 : 24; + return p.cyc; } /*-----------------------------------------------------------------------*/ @@ -945,10 +924,10 @@ function CPU() { stEA(dea, p.z, r); flgAdd(s, d, r, p.z, false); //BUG.say(sprintf('I_ADDI.%s s $%08x d $%08x r $%08x', szChr(p.z), s, d, r)); - return p.cyc; //dea.m == M_rdd ? (p.z == 4 ? 16 : 8) : (p.z == 4 ? 20 : 12) + dea.c; + return p.cyc; } - function I_ADDQ(p) { + /*function I_ADDQ(p) { var sea = exEA(p.s, p.z); var s = ldEA(sea, p.z); if (p.d.m == M_rda) { @@ -968,6 +947,29 @@ function CPU() { } //BUG.say(sprintf('I_ADDQ.%s s $%08x d $%08x r $%08x', szChr(p.z), s, d, r)); return p.cyc; + }*/ + + function I_ADDQ(p) { + var sea = exEA(p.s, p.z); + var s = ldEA(sea, p.z); + var dea = exEA(p.d, p.z); + var d = ldEA(dea, p.z); + var r = addAuto(s, d, p.z); + stEA(dea, p.z, r); + flgAdd(s, d, r, p.z, false); + //BUG.say(sprintf('I_ADDQ.%s s $%08x d $%08x r $%08x', szChr(p.z), s, d, r)); + return p.cyc; + } + function I_ADDQA(p) { + var sea = exEA(p.s, p.z); + var s = ldEA(sea, p.z); + var dea = exEA(p.d, 4); + var d = ldEA(dea, 4); + var r = add32(s, d); + stEA(dea, 4, r); + //ccna + //BUG.say(sprintf('I_ADDQA.%s s $%08x d $%08x r $%08x', szChr(p.z), s, d, r)); + return p.cyc; } function I_ADDX(p) { @@ -980,7 +982,7 @@ function CPU() { stEA(dea, p.z, r); flgAdd(s, d, r, p.z, true); //BUG.say(sprintf('I_ADDX.%s s $%08x d $%08x xo %d xn %d r $%08x', szChr(p.z), s, d, _x, regs.x?1:0, r)); - return p.cyc;//dea.m == M_rdd ? (p.z == 4 ? 8 : 4) : (p.z == 4 ? 30 : 18); + return p.cyc; } function I_CLR(p) { @@ -993,7 +995,7 @@ function CPU() { regs.v = false; regs.c = false; //BUG.say(sprintf('I_CLR.%s', szChr(p.z))); - return p.cyc; //dea.m == M_rdd ? (p.z == 4 ? 6 : 4) : (p.z == 4 ? 12 : 8) + dea.c; + return p.cyc; } function I_CMP(p) { @@ -1026,7 +1028,7 @@ function CPU() { var r = subAuto(d, s, p.z); flgCmp(s, d, r, p.z); //BUG.say(sprintf('I_CMPI.%s s $%08x d $%08x r $%08x', szChr(p.z), s, d, r)); - return p.cyc; //dea.m == M_rdd ? (p.z == 4 ? 14 : 8) : (p.z == 4 ? 12 : 8) + dea.c; + return p.cyc; } function I_CMPM(p) { @@ -1037,7 +1039,7 @@ function CPU() { var r = subAuto(d, s, p.z); flgCmp(s, d, r, p.z); //BUG.say(sprintf('I_CMPM.%s s $%08x d $%08x r $%08x | %c', szChr(p.z), s, d, r, s)); - return p.cyc;//p.z == 4 ? 20 : 12; + return p.cyc; } function I_DIVS(p) { @@ -1073,7 +1075,7 @@ function CPU() { stEA(dea, 4, r); //BUG.say(sprintf('I_DIVS.%s $%08x / $%08x = $%08x (quo $%08x | rem $%08x)', szChr(p.z), d, s, r, quo, rem)); } - return p.cyc;// 158 + dea.c; + return p.cyc; } } @@ -1110,7 +1112,7 @@ function CPU() { stEA(dea, 4, r); //BUG.say(sprintf('I_DIVU.%s $%08x / $%08x = $%08x (quo $%08x | rem $%08x)', szChr(p.z), d, s, r, quo, rem)); } - return p.cyc; //140 + dea.c; + return p.cyc; } } @@ -1122,7 +1124,7 @@ function CPU() { stEA(dea, p.z, r); flgLogical(r, p.z); //BUG.say(sprintf('I_EXT.%s d $%08x r $%08x', szChr(p.z), d, r)); - return p.cyc; //4; + return p.cyc; } function I_MULS(p) { @@ -1139,7 +1141,7 @@ function CPU() { regs.n = (r & 0x80000000) != 0; regs.z = r == 0; //BUG.say(sprintf('I_MULS.%s s $%08x d $%08x r $%08x', szChr(p.z), s, d, r)); - return p.cyc; //70 + dea.c; + return p.cyc; } function I_MULU(p) { @@ -1155,7 +1157,7 @@ function CPU() { regs.n = (r & 0x80000000) != 0; regs.z = r == 0; //BUG.say(sprintf('I_MULU.%s s $%08x d $%08x r $%08x', szChr(p.z), s, d, r)); - return p.cyc; //70 + dea.c; + return p.cyc; } function I_NEG(p) { @@ -1165,7 +1167,7 @@ function CPU() { stEA(dea, p.z, r); flgNeg(d, r, p.z, false); //BUG.say(sprintf('I_NEG.%s d $%08x r $%08x', szChr(p.z), d, r)); - return p.cyc; //dea.m == M_rdd ? (p.z == 4 ? 6 : 4) : (p.z == 4 ? 12 : 8) + dea.c; + return p.cyc; } function I_NEGX(p) { @@ -1175,7 +1177,7 @@ function CPU() { stEA(dea, p.z, r); flgNeg(d, r, p.z, true); //BUG.say(sprintf('I_NEGX.%s d $%08x x %d r $%08x', szChr(p.z), d, regs.x ? 1 : 0, r)); - return p.cyc; //dea.m == M_rdd ? (p.z == 4 ? 6 : 4) : (p.z == 4 ? 12 : 8) + dea.c; + return p.cyc; } function I_SUB(p) { @@ -1211,10 +1213,10 @@ function CPU() { stEA(dea, p.z, r); flgSub(s, d, r, p.z, false); //BUG.say(sprintf('I_SUBI.%s s $%08x d $%08x r $%08x', szChr(p.z), s, d, r)); - return p.cyc; //dea.m == M_rdd ? (p.z == 4 ? 16 : 8) : (p.z == 4 ? 20 : 12) + dea.c; + return p.cyc; } - function I_SUBQ(p) { + /*function I_SUBQ(p) { var sea = exEA(p.s, p.z); var s = ldEA(sea, p.z); if (p.d.m == M_rda) { @@ -1234,6 +1236,29 @@ function CPU() { } //BUG.say(sprintf('I_SUBQ.%s s $%08x d $%08x r $%08x', szChr(p.z), s, d, r)); return p.cyc; + }*/ + + function I_SUBQ(p) { + var sea = exEA(p.s, p.z); + var s = ldEA(sea, p.z); + var dea = exEA(p.d, p.z); + var d = ldEA(dea, p.z); + var r = subAuto(d, s, p.z); + stEA(dea, p.z, r); + flgSub(s, d, r, p.z, false); + //BUG.say(sprintf('I_SUBQ.%s s $%08x d $%08x r $%08x', szChr(p.z), s, d, r)); + return p.cyc; + } + function I_SUBQA(p) { + var sea = exEA(p.s, p.z); + var s = ldEA(sea, p.z); + var dea = exEA(p.d, 4); + var d = ldEA(dea, 4); + var r = sub32(d, s); + stEA(dea, 4, r); + //ccna + //BUG.say(sprintf('I_SUBQA.%s s $%08x d $%08x r $%08x', szChr(p.z), s, d, r)); + return p.cyc; } function I_SUBX(p) { @@ -1246,7 +1271,7 @@ function CPU() { stEA(dea, p.z, r); flgSub(s, d, r, p.z, true); //BUG.say(sprintf('I_SUBX.%s s $%08x d $%08x xo %d xn %d r $%08x', szChr(p.z), s, d, _x, regs.x?1:0, r)); - return p.cyc;//dea.m == M_rdd ? (p.z == 4 ? 8 : 4) : (p.z == 4 ? 30 : 18); + return p.cyc; } /*-----------------------------------------------------------------------*/ @@ -1273,7 +1298,7 @@ function CPU() { stEA(dea, p.z, r); flgLogical(r, p.z); //BUG.say(sprintf('I_ANDI.%s s $%08x d $%08x r $%08x', szChr(p.z), s, d, r)); - return p.cyc; //dea.m == M_rdd ? (p.z == 4 ? 16 : 8) : (p.z == 4 ? 20 : 12) + dea.c; + return p.cyc; } function I_EOR(p) { @@ -1297,7 +1322,7 @@ function CPU() { stEA(dea, p.z, r); flgLogical(r, p.z); //BUG.say(sprintf('I_EORI.%s s $%08x d $%08x r $%08x', szChr(p.z), s, d, r)); - return p.cyc; //dea.m == M_rdd ? (p.z == 4 ? 16 : 8) : (p.z == 4 ? 20 : 12) + dea.c; + return p.cyc; } function I_NOT(p) { @@ -1308,7 +1333,7 @@ function CPU() { stEA(dea, p.z, r); flgLogical(r, p.z); //BUG.say(sprintf('I_NOT.%s d $%08x r $%08x', szChr(p.z), d, r)); - return p.cyc;//dea.m == M_rdd ? (p.z == 4 ? 6 : 4) : (p.z == 4 ? 12 : 8) + dea.c; + return p.cyc; } function I_OR(p) { @@ -1332,7 +1357,7 @@ function CPU() { stEA(dea, p.z, r); flgLogical(r, p.z); //BUG.say(sprintf('I_ORI.%s s $%08x d $%08x r $%08x', szChr(p.z), s, d, r)); - return p.cyc; //dea.m == M_rdd ? (p.z == 4 ? 16 : 8) : (p.z == 4 ? 20 : 12) + dea.c; + return p.cyc; } /*-----------------------------------------------------------------------*/ @@ -1364,7 +1389,7 @@ function CPU() { regs.n = (r & p.ms) != 0; regs.z = r == 0; //BUG.say(sprintf('I_ASL.%s num %d d $%08x r $%08x', szChr(p.z), s, d, r)); - return p.cyc + (dea.m == M_rdd ? s << 1 : 0);//dea.m == M_rdd ? (p.z == 4 ? 8+n2 : 6+n2) : 8 + dea.c; + return [p.cyc[0] + (dea.m == M_rdd ? s << 1 : 0), 0,0]; //FIXME } function I_ASR(p) { @@ -1390,7 +1415,7 @@ function CPU() { regs.n = (r & p.ms) != 0; regs.z = r == 0; //BUG.say(sprintf('I_ASR.%s num %d d $%08x r $%08x sign %d', szChr(p.z), s, d, r, sign)); - return p.cyc + (dea.m == M_rdd ? s << 1 : 0);//dea.m == M_rdd ? (p.z == 4 ? 8+n2 : 6+n2) : 8 + dea.c; + return [p.cyc[0] + (dea.m == M_rdd ? s << 1 : 0), 0,0]; //FIXME } function I_LSL(p) { @@ -1416,7 +1441,7 @@ function CPU() { regs.n = (r & p.ms) != 0; regs.z = r == 0; //BUG.say(sprintf('I_LSL.%s num %d d $%08x r $%08x', szChr(p.z), s, d, r)); - return p.cyc + (dea.m == M_rdd ? s << 1 : 0);//dea.m == M_rdd ? (p.z == 4 ? 8+n2 : 6+n2) : 8 + dea.c; + return [p.cyc[0] + (dea.m == M_rdd ? s << 1 : 0), 0,0]; //FIXME } function I_LSR(p) { @@ -1441,7 +1466,7 @@ function CPU() { regs.n = (r & p.ms) != 0; regs.z = r == 0; //BUG.say(sprintf('I_LSR.%s num %d d $%08x r $%08x', szChr(p.z), s, d, r)); - return p.cyc + (dea.m == M_rdd ? s << 1 : 0);//dea.m == M_rdd ? (p.z == 4 ? 8+n2 : 6+n2) : 8 + dea.c; + return [p.cyc[0] + (dea.m == M_rdd ? s << 1 : 0), 0,0]; //FIXME } function I_ROL(p) { @@ -1468,7 +1493,7 @@ function CPU() { regs.n = (r & p.ms) != 0; regs.z = r == 0; //BUG.say(sprintf('I_ROL.%s num %d d $%08x r $%08x', szChr(p.z), s, d, r)); - return p.cyc + (dea.m == M_rdd ? s << 1 : 0);//dea.m == M_rdd ? (p.z == 4 ? 8+n2 : 6+n2) : 8 + dea.c; + return [p.cyc[0] + (dea.m == M_rdd ? s << 1 : 0), 0,0]; //FIXME } function I_ROR(p) { @@ -1494,7 +1519,7 @@ function CPU() { regs.n = (r & p.ms) != 0; regs.z = r == 0; //BUG.say(sprintf('I_ROR.%s num %d d $%08x r $%08x', szChr(p.z), s, d, r)); - return p.cyc + (dea.m == M_rdd ? s << 1 : 0);//dea.m == M_rdd ? (p.z == 4 ? 8+n2 : 6+n2) : 8 + dea.c; + return [p.cyc[0] + (dea.m == M_rdd ? s << 1 : 0), 0,0]; //FIXME } function I_ROXL(p) { @@ -1523,7 +1548,7 @@ function CPU() { regs.n = (r & p.ms) != 0; regs.z = r == 0; //BUG.say(sprintf('I_ROXL.%s num %d d $%08x ox %d nx %d r $%08x', szChr(p.z), s, d, _x, regs.x?1:0, r)); - return p.cyc + (dea.m == M_rdd ? s << 1 : 0);//dea.m == M_rdd ? (p.z == 4 ? 8+n2 : 6+n2) : 8 + dea.c; + return [p.cyc[0] + (dea.m == M_rdd ? s << 1 : 0), 0,0]; //FIXME } function I_ROXR(p) { @@ -1551,7 +1576,7 @@ function CPU() { regs.n = (r & p.ms) != 0; regs.z = r == 0; //BUG.say(sprintf('I_ROXR.%s num %d d $%08x ox %d nx %d r $%08x', szChr(p.z), s, d, _x, regs.x?1:0, r)); - return p.cyc + (dea.m == M_rdd ? s << 1 : 0);//dea.m == M_rdd ? (p.z == 4 ? 8+n2 : 6+n2) : 8 + dea.c; + return [p.cyc[0] + (dea.m == M_rdd ? s << 1 : 0), 0,0]; //FIXME } function I_SWAP(p) { @@ -1565,7 +1590,7 @@ function CPU() { regs.v = false; regs.c = false; //BUG.say(sprintf('I_SWAP.%s d $%08x r $%08x', szChr(p.z), d, r)); - return p.cyc; //4; + return p.cyc; } /*-----------------------------------------------------------------------*/ @@ -1588,7 +1613,7 @@ function CPU() { else BUG.say(sprintf('I_BCHG.%s s $%02x == m $%02x, d $%02x, r $%02x', szChr(p.z), s, m, d, r));*/ - return p.cyc;//dea.m == M_rdd ? 8 : 8 + dea.c; + return p.cyc; } function I_BCLR(p) { @@ -1607,7 +1632,7 @@ function CPU() { BUG.say(sprintf('I_BCLR.%s s $%08x == m $%08x, d $%08x, r $%08x', szChr(p.z), s, m, d, r)); else BUG.say(sprintf('I_BCLR.%s s $%02x == m $%02x, d $%02x, r $%02x', szChr(p.z), s, m, d, r));*/ - return p.cyc;//dea.m == M_rdd ? 10 : 8 + dea.c; + return p.cyc; } function I_BSET(p) { @@ -1626,7 +1651,7 @@ function CPU() { BUG.say(sprintf('I_BSET.%s s $%08x == m $%08x, d $%08x, r $%08x', szChr(p.z), s, m, d, r)); else BUG.say(sprintf('I_BSET.%s s $%02x == m $%02x, d $%02x, r $%02x', szChr(p.z), s, m, d, r));*/ - return p.cyc;//dea.m == M_rdd ? 8 : 8 + dea.c; + return p.cyc; } function I_BTST(p) { @@ -1643,7 +1668,7 @@ function CPU() { BUG.say(sprintf('I_BTST.%s s $%08x == m $%08x, d $%08x, r $%08x', szChr(p.z), s, m, d, r)); else BUG.say(sprintf('I_BTST.%s s $%02x == m $%02x, d $%02x, r $%02x', szChr(p.z), s, m, d, r));*/ - return p.cyc;//dea.m == M_rdd ? 6 : 4 + dea.c; + return p.cyc; } /*-----------------------------------------------------------------------*/ @@ -1684,7 +1709,7 @@ function CPU() { regs.v = !regs.v; //undef } //BUG.say(sprintf('I_ABCD.%s s $%02x d $%02x x %d | s_h %d s_l %d d_h %d d_l %d | r $%02x c %d', szChr(p.z), s, d, x, s_h, s_l, d_h, d_l, r, c?1:0)); - return p.cyc; //dea.m == M_rdd ? 6 : 18; + return p.cyc; } function I_NBCD(p) { @@ -1717,7 +1742,7 @@ function CPU() { regs.v = !regs.v; //undef } //BUG.say(sprintf('I_NBCD.%s s $%02x d $%02x x %d | s_h %d s_l %d d_h %d d_l %d | r $%02x c %d', szChr(p.z), s, d, x, s_h, s_l, d_h, d_l, r, c?1:0)); - return p.cyc; //dea.m == M_rdd ? 6 : 8 + dea.c; + return p.cyc; } function I_SBCD(p) { @@ -1755,7 +1780,7 @@ function CPU() { regs.v = !regs.v; //undef } //BUG.say(sprintf('I_SBCD.%s s $%02x d $%02x x %d | s_h %d s_l %d d_h %d d_l %d | r $%02x c %d', szChr(p.z), s, d, x, s_h, s_l, d_h, d_l, r, c?1:0)); - return p.cyc; //dea.m == M_rdd ? 6 : 18; + return p.cyc; } /*-----------------------------------------------------------------------*/ @@ -1775,10 +1800,10 @@ function CPU() { else pc = add32(regs.pc, extByte(dp)); //BUG.say(sprintf('I_Bcc pc $%08x', pc)); setPC(pc); - return p.cycTaken; //10; + return p.cycTaken; } //ccna - return p.cyc;//dp == 0 ? 12 : 8; + return p.cyc; } function I_DBcc(p) { @@ -1793,13 +1818,13 @@ function CPU() { if (dr--) { var pc = add32(regs.pc - 2, extWord(dp)); setPC(pc); - cyc = p.cycFalseTaken; //10; + cyc = p.cycFalseTaken; } else { dr = 0xffff; - cyc = p.cycFalse; //14; + cyc = p.cycFalse; } stEA(ea, p.z, dr); - } else cyc = p.cycTrue; //12; + } else cyc = p.cycTrue; //ccna return cyc; } @@ -1813,7 +1838,7 @@ function CPU() { stEA(dea, p.z, isTrue ? 0xff : 0); //ccna //BUG.say(sprintf('I_S%s, cc %d, ccTrue %d, cyc %d', ccNames[cc], cc, ccTrue(cc)?1:0, isTrue ? p.cycTrue : p.cycFalse)); - return isTrue ? p.cycTrue : p.cycFalse; //dea.m == M_rdd ? (isTrue ? 6 : 4) : 8 + dea.c; + return isTrue ? p.cycTrue : p.cycFalse; } function I_BRA(p) { @@ -1829,7 +1854,7 @@ function CPU() { setPC(pc); //ccna - return p.cycTaken; //10; + return p.cycTaken; } function I_BSR(p) { @@ -1846,7 +1871,7 @@ function CPU() { stEA(exEA(new effAddr(M_ripr, 7), 4), 4, regs.pc); setPC(pc); //ccna - return p.cycTaken; //18; + return p.cycTaken; } function I_JMP(p) { @@ -1854,15 +1879,6 @@ function CPU() { setPC(dea.a); //ccna //BUG.say(sprintf('I_JMP $%08x', dea.a)); - /*switch (dea.m) { - case M_ria: return 8; - case M_rid: return 10; - case M_rii: return 14; - case M_pcid: return 10; - case M_pcii: return 14; - case M_absw: return 10; - case M_absl: return 12; - }*/ return p.cyc; } @@ -1871,16 +1887,7 @@ function CPU() { stEA(exEA(new effAddr(M_ripr, 7), 4), 4, regs.pc); setPC(dea.a); //ccna - //BUG.say(sprintf('I_JSR $%08x', dea.a)); - /*switch (dea.m) { - case M_ria: return 16; - case M_rid: return 18; - case M_rii: return 22; - case M_pcid: return 18; - case M_pcii: return 22; - case M_absw: return 18; - case M_absl: return 20; - }*/ + //BUG.say(sprintf('I_JSR $%08x', dea.a)); return p.cyc; } @@ -1906,7 +1913,7 @@ function CPU() { var r = ldEA(dea, p.z); //r = extAuto(r, p.z); flgLogical(r, p.z); //BUG.say(sprintf('I_TST.%s r $%08x', szChr(p.z), r)); - return p.cyc; //dea.m == M_rdd || dea.m == M_rda ? 4 : 4 + dea.c; + return p.cyc; } function I_NOP(p) { @@ -2036,7 +2043,7 @@ function CPU() { stEA(dea, p.z, sr); //ccna //BUG.say(sprintf('I_MOVE_SR2.%s sr $%04x', szChr(p.z), sr)); - return p.cyc;//dea.m == M_rdd ? 6 : 8; + return p.cyc; } /*-----------------------------------------------------------------------*/ @@ -2195,7 +2202,7 @@ function CPU() { regs.v = false; regs.c = false; BUG.say(sprintf('I_TAS.%s d $%02x r $%02x', szChr(p.z), d, r)); - return p.cyc; //dea.m == M_rdd ? 4 : 10 + dea.c; + return p.cyc; } /*-----------------------------------------------------------------------*/ @@ -2203,7 +2210,7 @@ function CPU() { /*-----------------------------------------------------------------------*/ function mkCyc(z, m) { - switch (m) { + /*switch (m) { case M_rdd: case M_rda: return 0; case M_ria: return z == 4 ? 8 : 4; @@ -2217,6 +2224,21 @@ function CPU() { case M_absl: return z == 4 ? 16 : 12; case M_imm: case M_list: return z == 4 ? 8 : 4; + }*/ + switch (m) { + case M_rdd: + case M_rda: return z == 4 ? [ 0,0,0] : [ 0,0,0]; + case M_ria: return z == 4 ? [ 8,2,0] : [ 4,1,0]; + case M_ripo: return z == 4 ? [ 8,2,0] : [ 4,1,0]; + case M_ripr: return z == 4 ? [10,2,0] : [ 6,1,0]; + case M_rid: return z == 4 ? [12,3,0] : [ 8,2,0]; + case M_rii: return z == 4 ? [14,3,0] : [10,2,0]; + case M_pcid: return z == 4 ? [12,3,0] : [ 8,2,0]; + case M_pcii: return z == 4 ? [14,3,0] : [10,2,0]; + case M_absw: return z == 4 ? [12,3,0] : [ 8,2,0]; + case M_absl: return z == 4 ? [16,4,0] : [12,3,0]; + case M_imm: + case M_list: return z == 4 ? [ 8,2,0] : [ 4,1,0]; } } @@ -2227,7 +2249,7 @@ function CPU() { i.mn = mn; i.f = null; i.p = {}; - if (cyc) i.p.cyc = cyc; + i.p.cyc = cyc; return i; } @@ -2242,7 +2264,9 @@ function CPU() { i.p.s = new effAddr(s, r); i.p.s.c = mkCyc(z, s); i.p.cyc = cyc; - if (add) i.p.cyc += i.p.s.c; + if (add) i.p.cyc[0] += i.p.s.c[0]; + i.p.cyc[1] += i.p.s.c[1]; + i.p.cyc[2] += i.p.s.c[2]; return i; } @@ -2257,7 +2281,9 @@ function CPU() { i.p.d = new effAddr(d, r); i.p.d.c = mkCyc(z, d); i.p.cyc = cyc; - if (add) i.p.cyc += i.p.d.c; + if (add) i.p.cyc[0] += i.p.d.c[0]; + i.p.cyc[1] += i.p.d.c[1]; + i.p.cyc[2] += i.p.d.c[2]; return i; } @@ -2276,8 +2302,12 @@ function CPU() { i.p.s.c = mkCyc(z, sm); i.p.d.c = mkCyc(z, dm); i.p.cyc = cyc; - if (sa) i.p.cyc += i.p.s.c; - if (da) i.p.cyc += i.p.d.c; + if (sa) i.p.cyc[0] += i.p.s.c[0]; + if (da) i.p.cyc[0] += i.p.d.c[0]; + i.p.cyc[1] += i.p.s.c[1]; + i.p.cyc[2] += i.p.s.c[2]; + i.p.cyc[1] += i.p.d.c[1]; + i.p.cyc[2] += i.p.d.c[2]; return i; } @@ -2324,9 +2354,13 @@ function CPU() { i.p.cycTrue = cycTrue; i.p.cycFalse = cycFalse; if (add) { - i.p.cycTrue += i.p.d.c; - i.p.cycFalse += i.p.d.c; + i.p.cycTrue[0] += i.p.d.c[0]; + i.p.cycFalse[0] += i.p.d.c[0]; } + i.p.cycTrue[1] += i.p.d.c[1]; + i.p.cycTrue[2] += i.p.d.c[2]; + i.p.cycFalse[1] += i.p.d.c[1]; + i.p.cycFalse[2] += i.p.d.c[2]; return i; } @@ -2380,9 +2414,9 @@ function CPU() { if (iTab[op].op === -1) { if (rm == 0) - iTab[op] = mkSD(op, 'ABCD', 1, M_rdd, Ry, M_rdd, Rx, 6, false, false); + iTab[op] = mkSD(op, 'ABCD', 1, M_rdd, Ry, M_rdd, Rx, [6,1,0], false, false); else - iTab[op] = mkSD(op, 'ABCD', 1, M_ripr, Ry, M_ripr, Rx, 18, false, false); + iTab[op] = mkSD(op, 'ABCD', 1, M_ripr, Ry, M_ripr, Rx, [18,3,1], false, false); iTab[op].f = I_ABCD; cnt++; @@ -2412,8 +2446,8 @@ function CPU() { op = (13 << 12) | (Dn << 9) | (dir << 8) | (z << 6) | ea[0]; - cyc = dir == 0 ? (z2 == 4 ? (ea[1] == M_rdd || ea[1] == M_imm ? 8 : 6) : 4) : (z2 == 4 ? 12 : 8); - + cyc = dir == 0 ? (z2 == 4 ? (ea[1] == M_rdd || ea[1] == M_imm ? [8,1,0] : [6,1,0]) : [4,1,0]) : (z2 == 4 ? [12,1,2] : [8,1,1]); + if (iTab[op].op === -1) { if (dir == 0) iTab[op] = mkSD(op, 'ADD', z2, ea[1], ea[2], M_rdd, Dn, cyc, true, false); @@ -2421,7 +2455,6 @@ function CPU() { iTab[op] = mkSD(op, 'ADD', z2, M_rdd, Dn, ea[1], ea[2], cyc, false, true); iTab[op].f = I_ADD; - //iTab[op].p.cyc = ((dir == 0) ? (z2 == 4 ? (ea[1]==M_rdd||ea[1]==M_imm?8:6) : 4) : (z2 == 4 ? 12 : 8)) + mkCyc(z2, ea[1]); cnt++; } else { BUG.say('OP EXISTS ADD ' + op); @@ -2448,9 +2481,8 @@ function CPU() { op = (13 << 12) | (An << 9) | (z3 << 6) | ea[0]; if (iTab[op].op === -1) { - iTab[op] = mkSD(op, 'ADDA', z2, ea[1], ea[2], M_rda, An, z2 == 4 ? (ea[1] == M_rdd || ea[1] == M_imm ? 8 : 6) : 8, true, false); + iTab[op] = mkSD(op, 'ADDA', z2, ea[1], ea[2], M_rda, An, z2 == 4 ? (ea[1] == M_rdd || ea[1] == M_imm ? [8,1,0] : [6,1,0]) : [8,1,0], true, false); iTab[op].f = I_ADDA; - //iTab[op].p.cyc = (z2 == 4 ? (ea[1] == M_rdd || ea[1] == M_imm ? 8 : 6) : 8) + mkCyc(z2, ea[1]); cnt++; } else { BUG.say('OP EXISTS ADDA ' + op); @@ -2474,7 +2506,7 @@ function CPU() { op = (6 << 8) | (z << 6) | ea[0]; if (iTab[op].op === -1) { - iTab[op] = mkSD(op, 'ADDI', z2, M_imm, -1, ea[1], ea[2], ea[1] == M_rdd ? (z2 == 4 ? 16 : 8) : (z2 == 4 ? 20 : 12), false, ea[1] != M_rdd); + iTab[op] = mkSD(op, 'ADDI', z2, M_imm, -1, ea[1], ea[2], ea[1] == M_rdd ? (z2 == 4 ? [16,3,0] : [8,2,0]) : (z2 == 4 ? [20,3,2] : [12,2,1]), false, ea[1] != M_rdd); iTab[op].f = I_ADDI; cnt++; } else { @@ -2499,11 +2531,12 @@ function CPU() { if (ea[1] == M_rda && z == 0) continue; //An word and long only op = (5 << 12) | (id << 9) | (z << 6) | ea[0]; - cyc = ea[1] == M_rda ? 8 : (ea[1] == M_rdd ? (z2 == 4 ? 8 : 4) : (z2 == 4 ? 12 : 8)); + cyc = ea[1] == M_rda ? [8,1,0] : (ea[1] == M_rdd ? (z2 == 4 ? [8,1,0] : [4,1,0]) : (z2 == 4 ? [12,1,2] : [8,1,1])); if (iTab[op].op === -1) { iTab[op] = mkSD(op, 'ADDQ', z2, M_imm, id == 0 ? 8 : id, ea[1], ea[2], cyc, false, ea[1] != M_rdd && ea[1] != M_rda); - iTab[op].f = I_ADDQ; + //iTab[op].f = I_ADDQ; + iTab[op].f = ea[1] != M_rda ? I_ADDQ : I_ADDQA; cnt++; } else { BUG.say('OP EXISTS ADDQ ' + op); @@ -2527,9 +2560,9 @@ function CPU() { if (iTab[op].op === -1) { if (rm == 0) - iTab[op] = mkSD(op, 'ADDX', z2, M_rdd, Ry, M_rdd, Rx, z2 == 4 ? 8 : 4, false, false); - else - iTab[op] = mkSD(op, 'ADDX', z2, M_ripr, Ry, M_ripr, Rx, z2 == 4 ? 30 : 18, false, false); + iTab[op] = mkSD(op, 'ADDX', z2, M_rdd, Ry, M_rdd, Rx, z2 == 4 ? [8,1,0] : [4,1,0], false, false); + else + iTab[op] = mkSD(op, 'ADDX', z2, M_ripr, Ry, M_ripr, Rx, z2 == 4 ? [30,5,2] : [18,1,0], false, false); iTab[op].f = I_ADDX; cnt++; @@ -2558,7 +2591,7 @@ function CPU() { if (ea[0] != -1) { op = (12 << 12) | (Dn << 9) | (dir << 8) | (z << 6) | ea[0]; - cyc = dir == 0 ? (z2 == 4 ? (ea[1] == M_rdd || ea[1] == M_imm ? 8 : 6) : 4) : (z2 == 4 ? 12 : 8); + cyc = dir == 0 ? (z2 == 4 ? (ea[1] == M_rdd || ea[1] == M_imm ? [8,1,0] : [6,1,0]) : [4,1,0]) : (z2 == 4 ? [12,1,2] : [8,1,1]); if (iTab[op].op === -1) { if (dir == 0) @@ -2567,7 +2600,6 @@ function CPU() { iTab[op] = mkSD(op, 'AND', z2, M_rdd, Dn, ea[1], ea[2], cyc, false, true); iTab[op].f = I_AND; - //iTab[op].p.cyc = (dir == 0 ? (z2 == 4 ? (ea[1]==M_rdd||ea[1]==M_imm?8:6) : 4) : (z2 == 4 ? 12 : 8)) + mkCyc(z2, ea[1]); cnt++; } else { BUG.say('OP EXISTS AND ' + op); @@ -2592,7 +2624,7 @@ function CPU() { op = (2 << 8) | (z << 6) | ea[0]; if (iTab[op].op === -1) { - iTab[op] = mkSD(op, 'ANDI', z2, M_imm, -1, ea[1], ea[2], ea[1] == M_rdd ? (z2 == 4 ? 16 : 8) : (z2 == 4 ? 20 : 12), false, ea[1] != M_rdd); + iTab[op] = mkSD(op, 'ANDI', z2, M_imm, -1, ea[1], ea[2], ea[1] == M_rdd ? (z2 == 4 ? [16,3,0] : [8,2,0]) : (z2 == 4 ? [20,3,2] : [12,2,1]), false, ea[1] != M_rdd); iTab[op].f = I_ANDI; cnt++; } else { @@ -2608,7 +2640,7 @@ function CPU() { op = 0x23C; if (iTab[op].op === -1) { - iTab[op] = mkS(op, 'ANDI_CCR', 1, M_imm, -1, 20, false); + iTab[op] = mkS(op, 'ANDI_CCR', 1, M_imm, -1, [20,3,0], false); iTab[op].f = I_ANDI_CCR; cnt++; } else { @@ -2621,7 +2653,7 @@ function CPU() { op = 0x27C; if (iTab[op].op === -1) { - iTab[op] = mkS(op, 'ANDI_SR', 2, M_imm, -1, 20, false); + iTab[op] = mkS(op, 'ANDI_SR', 2, M_imm, -1, [20,3,0], false); iTab[op].pr = true; iTab[op].f = I_ANDI_SR; cnt++; @@ -2646,9 +2678,9 @@ function CPU() { if (iTab[op].op === -1) { if (ir == 0) - iTab[op] = mkSD(op, dr == 0 ? 'ASR_RI' : 'ASL_RI', z2, M_imm, cr == 0 ? 8 : cr, M_rdd, Dy, z2 == 4 ? 8 : 6, false, false); + iTab[op] = mkSD(op, dr == 0 ? 'ASR_RI' : 'ASL_RI', z2, M_imm, cr == 0 ? 8 : cr, M_rdd, Dy, z2 == 4 ? [8,1,0] : [6,1,0], false, false); else - iTab[op] = mkSD(op, dr == 0 ? 'ASR_RD' : 'ASL_RD', z2, M_rdd, cr, M_rdd, Dy, z2 == 4 ? 8 : 6, false, false); + iTab[op] = mkSD(op, dr == 0 ? 'ASR_RD' : 'ASL_RD', z2, M_rdd, cr, M_rdd, Dy, z2 == 4 ? [8,1,0] : [6,1,0], false, false); iTab[op].f = dr == 0 ? I_ASR : I_ASL; cnt++; @@ -2668,7 +2700,7 @@ function CPU() { op = (112 << 9) | (dr << 8) | (3 << 6) | ea[0]; if (iTab[op].op === -1) { - iTab[op] = mkSD(op, dr == 0 ? 'ASR_M' : 'ASL_M', 2, M_imm, 1, ea[1], ea[2], 8, false, true); + iTab[op] = mkSD(op, dr == 0 ? 'ASR_M' : 'ASL_M', 2, M_imm, 1, ea[1], ea[2], [8,1,1], false, true); iTab[op].f = dr == 0 ? I_ASR : I_ASL; cnt++; } else { @@ -2684,12 +2716,12 @@ function CPU() { var cc, dp; for (cc = 2; cc < 16; cc++) { - for (dp = 0; dp < 255; dp++) /* 0xff = 68020 only */ + for (dp = 0; dp < 255; dp++) /* 0xff = long, 68020 only */ { op = (6 << 12) | (cc << 8) | dp; if (iTab[op].op === -1) { - iTab[op] = mkC(op, 'B' + ccNames[cc], dp == 0 ? 1 : 2, cc, dp, -1, 10, dp == 0 ? 12 : 8); + iTab[op] = mkC(op, 'B' + ccNames[cc], dp == 0 ? 1 : 2, cc, dp, -1, [10,2,0], dp == 0 ? [12,1,0] : [8,1,0]); iTab[op].f = I_Bcc; cnt++; } else { @@ -2711,7 +2743,7 @@ function CPU() { op = (Dn << 9) | (5 << 6) | ea[0]; if (iTab[op].op === -1) { - iTab[op] = mkSD(op, 'BCHG1', 4, M_rdd, Dn, ea[1], ea[2], 8, false, false); + iTab[op] = mkSD(op, 'BCHG1', 4, M_rdd, Dn, ea[1], ea[2], [8,1,0], false, false); iTab[op].f = I_BCHG; cnt++; } else { @@ -2727,7 +2759,7 @@ function CPU() { op = (33 << 6) | ea[0]; if (iTab[op].op === -1) { - iTab[op] = mkSD(op, 'BCHG2', 1, M_imm, -1, ea[1], ea[2], 8, false, true); + iTab[op] = mkSD(op, 'BCHG2', 1, M_imm, -1, ea[1], ea[2], [8,1,1], false, true); iTab[op].f = I_BCHG; cnt++; } else { @@ -2749,7 +2781,7 @@ function CPU() { op = (Dn << 9) | (6 << 6) | ea[0]; if (iTab[op].op === -1) { - iTab[op] = mkSD(op, 'BCLR1', 4, M_rdd, Dn, ea[1], ea[2], 10, false, false); + iTab[op] = mkSD(op, 'BCLR1', 4, M_rdd, Dn, ea[1], ea[2], [10,1,0], false, false); iTab[op].f = I_BCLR; cnt++; } else { @@ -2765,7 +2797,7 @@ function CPU() { op = (34 << 6) | ea[0]; if (iTab[op].op === -1) { - iTab[op] = mkSD(op, 'BCLR2', 1, M_imm, - 1, ea[1], ea[2], 8, false, true); + iTab[op] = mkSD(op, 'BCLR2', 1, M_imm, - 1, ea[1], ea[2], [8,1,1], false, true); iTab[op].f = I_BCLR; cnt++; } else { @@ -2787,7 +2819,7 @@ function CPU() { op = (Dn << 9) | (7 << 6) | ea[0]; if (iTab[op].op === -1) { - iTab[op] = mkSD(op, 'BSET1', 4, M_rdd, Dn, ea[1], ea[2], 8, false, false); + iTab[op] = mkSD(op, 'BSET1', 4, M_rdd, Dn, ea[1], ea[2], [8,1,0], false, false); iTab[op].f = I_BSET; cnt++; } else { @@ -2803,7 +2835,7 @@ function CPU() { op = (35 << 6) | ea[0]; if (iTab[op].op === -1) { - iTab[op] = mkSD(op, 'BSET2', 1, M_imm, - 1, ea[1], ea[2], 8, false, true); + iTab[op] = mkSD(op, 'BSET2', 1, M_imm, - 1, ea[1], ea[2], [8,1,1], false, true); iTab[op].f = I_BSET; cnt++; } else { @@ -2825,7 +2857,7 @@ function CPU() { op = (Dn << 9) | (4 << 6) | ea[0]; if (iTab[op].op === -1) { - iTab[op] = mkSD(op, 'BTST1', 4, M_rdd, Dn, ea[1], ea[2], 6, false, false); + iTab[op] = mkSD(op, 'BTST1', 4, M_rdd, Dn, ea[1], ea[2], [6,1,0], false, false); iTab[op].f = I_BTST; cnt++; } else { @@ -2842,7 +2874,7 @@ function CPU() { op = (32 << 6) | ea[0]; if (iTab[op].op === -1) { - iTab[op] = mkSD(op, 'BTST2', 1, M_imm, -1, ea[1], ea[2], 8, false, true); + iTab[op] = mkSD(op, 'BTST2', 1, M_imm, -1, ea[1], ea[2], [4,1,0], false, true); iTab[op].f = I_BTST; cnt++; } else { @@ -2861,7 +2893,7 @@ function CPU() { op = (96 << 8) | dp; if (iTab[op].op === -1) { - iTab[op] = mkC(op, 'BRA', dp == 0 ? 1 : 2, 0, dp, -1, 10, null); + iTab[op] = mkC(op, 'BRA', dp == 0 ? 1 : 2, 0, dp, -1, [10,2,0], null); iTab[op].f = I_BRA; cnt++; } else { @@ -2879,7 +2911,7 @@ function CPU() { op = (97 << 8) | dp; if (iTab[op].op === -1) { - iTab[op] = mkC(op, 'BSR', dp == 0 ? 1 : 2, 1, dp, -1, 18, null); + iTab[op] = mkC(op, 'BSR', dp == 0 ? 1 : 2, 1, dp, -1, [18,2,2], null); iTab[op].f = I_BSR; cnt++; } else { @@ -2902,7 +2934,7 @@ function CPU() { op = (4 << 12) | (Dn << 9) | (z3 << 7) | ea[0]; if (iTab[op].op === -1) { - iTab[op] = mkSD(op, 'CHK', z2, ea[1], ea[2], M_rdd, Dn, 10, true, false); + iTab[op] = mkSD(op, 'CHK', z2, ea[1], ea[2], M_rdd, Dn, [10,1,0], true, false); iTab[op].f = I_CHK; iTab[op].p.cycTaken = iTab[op].p.s.c; cnt++; @@ -2927,7 +2959,7 @@ function CPU() { op = (66 << 8) | (z << 6) | ea[0]; if (iTab[op].op === -1) { - iTab[op] = mkD(op, 'CLR', z2, ea[1], ea[2], ea[1] == M_rdd ? (z2 == 4 ? 6 : 4) : (z2 == 4 ? 12 : 8), ea[1] != M_rdd); + iTab[op] = mkD(op, 'CLR', z2, ea[1], ea[2], ea[1] == M_rdd ? (z2 == 4 ? [6,1,0] : [4,1,0]) : (z2 == 4 ? [12,1,2] : [8,1,1]), ea[1] != M_rdd); iTab[op].f = I_CLR; cnt++; } else { @@ -2954,9 +2986,8 @@ function CPU() { op = (11 << 12) | (Dn << 9) | (z << 6) | ea[0]; if (iTab[op].op === -1) { - iTab[op] = mkSD(op, 'CMP', z2, ea[1], ea[2], M_rdd, Dn, z2 == 4 ? 6 : 4, true, false); + iTab[op] = mkSD(op, 'CMP', z2, ea[1], ea[2], M_rdd, Dn, z2 == 4 ? [6,1,0] : [4,1,0], true, false); iTab[op].f = I_CMP; - //iTab[op].p.cyc = (z2 == 4 ? 6 : 4) + mkCyc(z2, ea[1]); cnt++; } else { BUG.say('OP EXISTS CMP ' + op); @@ -2982,9 +3013,8 @@ function CPU() { op = (11 << 12) | (An << 9) | (z3 << 6) | ea[0]; if (iTab[op].op === -1) { - iTab[op] = mkSD(op, 'CMPA', z2, ea[1], ea[2], M_rda, An, 6, true, false); + iTab[op] = mkSD(op, 'CMPA', z2, ea[1], ea[2], M_rda, An, [6,1,0], true, false); iTab[op].f = I_CMPA; - //iTab[op].p.cyc = 6 + mkCyc(z2, ea[1]); cnt++; } else { BUG.say('OP EXISTS CMPA ' + op); @@ -3008,7 +3038,7 @@ function CPU() { op = (12 << 8) | (z << 6) | ea[0]; if (iTab[op].op === -1) { - iTab[op] = mkSD(op, 'CMPI', z2, M_imm, -1, ea[1], ea[2], ea[1] == M_rdd ? (z2 == 4 ? 14 : 8) : (z2 == 4 ? 12 : 8), false, ea[1] != M_rdd); + iTab[op] = mkSD(op, 'CMPI', z2, M_imm, -1, ea[1], ea[2], ea[1] == M_rdd ? (z2 == 4 ? [14,3,0] : [8,2,0]) : (z2 == 4 ? [12,3,0] : [8,2,0]), false, ea[1] != M_rdd); iTab[op].f = I_CMPI; cnt++; } else { @@ -3030,7 +3060,7 @@ function CPU() { op = (11 << 12) | (Ax << 9) | (1 << 8) | (z << 6) | (1 << 3) | Ay; if (iTab[op].op === -1) { - iTab[op] = mkSD(op, 'CMPM', z2, M_ripo, Ay, M_ripo, Ax, z2 == 4 ? 20 : 12, false, false); + iTab[op] = mkSD(op, 'CMPM', z2, M_ripo, Ay, M_ripo, Ax, z2 == 4 ? [20,5,0] : [12,3,0], false, false); iTab[op].f = I_CMPM; cnt++; } else { @@ -3050,7 +3080,7 @@ function CPU() { op = (5 << 12) | (cc << 8) | (25 << 3) | dr; if (iTab[op].op === -1) { - iTab[op] = mkDBcc(op, 'DB' + ccNames[cc], 2, cc, -1, dr, 12, 10, 14); + iTab[op] = mkDBcc(op, 'DB' + ccNames[cc], 2, cc, -1, dr, [12,2,0], [10,2,0], [14,3,0]); iTab[op].f = I_DBcc; cnt++; } else { @@ -3072,7 +3102,7 @@ function CPU() { op = (8 << 12) | (Dn << 9) | (7 << 6) | ea[0]; if (iTab[op].op === -1) { - iTab[op] = mkSD(op, 'DIVS', 2, ea[1], ea[2], M_rdd, Dn, 158, true, false); + iTab[op] = mkSD(op, 'DIVS', 2, ea[1], ea[2], M_rdd, Dn, [158,1,0], true, false); iTab[op].f = I_DIVS; cnt++; } else { @@ -3095,7 +3125,7 @@ function CPU() { op = (8 << 12) | (Dn << 9) | (3 << 6) | ea[0]; if (iTab[op].op === -1) { - iTab[op] = mkSD(op, 'DIVU', 2, ea[1], ea[2], M_rdd, Dn, 140, true, false); + iTab[op] = mkSD(op, 'DIVU', 2, ea[1], ea[2], M_rdd, Dn, [140,1,0], true, false); iTab[op].f = I_DIVU; cnt++; } else { @@ -3121,9 +3151,8 @@ function CPU() { op = (11 << 12) | (Dn << 9) | (z3 << 6) | ea[0]; if (iTab[op].op === -1) { - iTab[op] = mkSD(op, 'EOR', z2, M_rdd, Dn, ea[1], ea[2], ea[1] == M_rdd ? (z2 == 4 ? 8 : 4) : (z2 == 4 ? 12 : 8), false, true); + iTab[op] = mkSD(op, 'EOR', z2, M_rdd, Dn, ea[1], ea[2], ea[1] == M_rdd ? (z2 == 4 ? [8,1,0] : [4,1,0]) : (z2 == 4 ? [12,1,2] : [8,1,1]), false, true); iTab[op].f = I_EOR; - //iTab[op].p.cyc = ea[1] == M_rdd ? (z2 == 4 ? 8 : 4) : ((z2 == 4 ? 12 : 8) + mkCyc(z2, ea[1])); cnt++; } else { BUG.say('OP EXISTS EOR ' + op); @@ -3147,7 +3176,7 @@ function CPU() { op = (10 << 8) | (z << 6) | ea[0]; if (iTab[op].op === -1) { - iTab[op] = mkSD(op, 'EORI', z2, M_imm, -1, ea[1], ea[2], ea[1] == M_rdd ? (z2 == 4 ? 16 : 8) : (z2 == 4 ? 20 : 12), false, ea[1] != M_rdd); + iTab[op] = mkSD(op, 'EORI', z2, M_imm, -1, ea[1], ea[2], ea[1] == M_rdd ? (z2 == 4 ? [16,3,0] : [8,2,0]) : (z2 == 4 ? [20,3,2] : [12,2,1]), false, ea[1] != M_rdd); iTab[op].f = I_EORI; cnt++; } else { @@ -3163,7 +3192,7 @@ function CPU() { op = 0xA3C; if (iTab[op].op === -1) { - iTab[op] = mkS(op, 'EORI_CCR', 1, M_imm, -1, 20, false); + iTab[op] = mkS(op, 'EORI_CCR', 1, M_imm, -1, [20,3,0], false); iTab[op].f = I_EORI_CCR; cnt++; } else { @@ -3176,7 +3205,7 @@ function CPU() { op = 0xA7C; if (iTab[op].op === -1) { - iTab[op] = mkS(op, 'EORI_SR', 2, M_imm, -1, 20, false); + iTab[op] = mkS(op, 'EORI_SR', 2, M_imm, -1, [20,3,0], false); iTab[op].pr = true; iTab[op].f = I_EORI_SR; cnt++; @@ -3197,11 +3226,11 @@ function CPU() { if (iTab[op].op === -1) { if (m == 0) - iTab[op] = mkSD(op, 'EXG', 4, M_rdd, Rx, M_rdd, Ry, 6, false, false); + iTab[op] = mkSD(op, 'EXG', 4, M_rdd, Rx, M_rdd, Ry, [6,1,0], false, false); else if (m == 1) - iTab[op] = mkSD(op, 'EXG', 4, M_rda, Rx, M_rda, Ry, 6, false, false); + iTab[op] = mkSD(op, 'EXG', 4, M_rda, Rx, M_rda, Ry, [6,1,0], false, false); else - iTab[op] = mkSD(op, 'EXG', 4, M_rdd, Rx, M_rda, Ry, 6, false, false); + iTab[op] = mkSD(op, 'EXG', 4, M_rdd, Rx, M_rda, Ry, [6,1,0], false, false); iTab[op].f = I_EXG; cnt++; @@ -3224,7 +3253,7 @@ function CPU() { op = (36 << 9) | (opm << 6) | Dn; if (iTab[op].op === -1) { - iTab[op] = mkD(op, 'EXT', z2, M_rdd, Dn, 4, false); + iTab[op] = mkD(op, 'EXT', z2, M_rdd, Dn, [4,1,0], false); iTab[op].f = I_EXT; cnt++; } else { @@ -3239,7 +3268,7 @@ function CPU() { op = 0x4AFC; if (iTab[op].op === -1) { - iTab[op] = mkN(op, 'ILLEGAL'); + iTab[op] = mkN(op, 'ILLEGAL', [0,0,0]); iTab[op].f = I_ILLEGAL; cnt++; } else { @@ -3257,15 +3286,15 @@ function CPU() { if (ea[0] != -1) { op = (315 << 6) | ea[0]; - if (iTab[op].op === -1) { + if (iTab[op].op === -1) { switch (ea[1]) { - case M_ria: cyc = 8; break; - case M_rid: cyc = 10; break; - case M_rii: cyc = 14; break; - case M_pcid: cyc = 10; break; - case M_pcii: cyc = 14; break; - case M_absw: cyc = 10; break; - case M_absl: cyc = 12; break; + case M_ria: cyc = [ 8,2,0]; break; + case M_rid: cyc = [10,2,0]; break; + case M_rii: cyc = [14,3,0]; break; + case M_pcid: cyc = [10,2,0]; break; + case M_pcii: cyc = [14,3,0]; break; + case M_absw: cyc = [10,2,0]; break; + case M_absl: cyc = [12,3,0]; break; } iTab[op] = mkD(op, 'JMP', 0, ea[1], ea[2], cyc, false); iTab[op].f = I_JMP; @@ -3289,13 +3318,13 @@ function CPU() { if (iTab[op].op === -1) { switch (ea[1]) { - case M_ria: cyc = 16; break; - case M_rid: cyc = 18; break; - case M_rii: cyc = 22; break; - case M_pcid: cyc = 18; break; - case M_pcii: cyc = 22; break; - case M_absw: cyc = 18; break; - case M_absl: cyc = 20; break; + case M_ria: cyc = [16,2,2]; break; + case M_rid: cyc = [18,2,2]; break; + case M_rii: cyc = [22,2,2]; break; + case M_pcid: cyc = [18,2,2]; break; + case M_pcii: cyc = [22,2,2]; break; + case M_absw: cyc = [18,2,2]; break; + case M_absl: cyc = [20,3,2]; break; } iTab[op] = mkD(op, 'JSR', 0, ea[1], ea[2], cyc, false); iTab[op].f = I_JSR; @@ -3320,14 +3349,14 @@ function CPU() { if (iTab[op].op === -1) { switch (ea[1]) { - case M_ria: cyc = 4; break; - case M_rid: cyc = 8; break; - case M_rii: cyc = 12; break; - case M_pcid: cyc = 8; break; - case M_pcii: cyc = 12; break; - case M_absw: cyc = 8; break; - case M_absl: cyc = 12; break; - } + case M_ria: cyc = [ 4,1,0]; break; + case M_rid: cyc = [ 8,2,0]; break; + case M_rii: cyc = [12,2,0]; break; + case M_pcid: cyc = [ 8,2,0]; break; + case M_pcii: cyc = [12,2,0]; break; + case M_absw: cyc = [ 8,2,0]; break; + case M_absl: cyc = [12,3,0]; break; + } iTab[op] = mkSD(op, 'LEA', 4, ea[1], ea[2], M_rda, An, cyc, false, false); iTab[op].f = I_LEA; cnt++; @@ -3347,7 +3376,7 @@ function CPU() { op = (2506 << 3) | An; if (iTab[op].op === -1) { - iTab[op] = mkSD(op, 'LINK', 2, M_rda, An, M_imm, -1, 16, false, false); + iTab[op] = mkSD(op, 'LINK', 2, M_rda, An, M_imm, -1, [16,2,2], false, false); iTab[op].f = I_LINK; cnt++; } else { @@ -3372,9 +3401,9 @@ function CPU() { if (iTab[op].op === -1) { if (ir == 0) - iTab[op] = mkSD(op, dr == 0 ? 'LSR_RI' : 'LSL_RI', z2, M_imm, cr == 0 ? 8 : cr, M_rdd, Dy, z2 == 4 ? 8 : 6, false, false); + iTab[op] = mkSD(op, dr == 0 ? 'LSR_RI' : 'LSL_RI', z2, M_imm, cr == 0 ? 8 : cr, M_rdd, Dy, z2 == 4 ? [8,1,0] : [6,1,0], false, false); else - iTab[op] = mkSD(op, dr == 0 ? 'LSR_RD' : 'LSL_RD', z2, M_rdd, cr, M_rdd, Dy, z2 == 4 ? 8 : 6, false, false); + iTab[op] = mkSD(op, dr == 0 ? 'LSR_RD' : 'LSL_RD', z2, M_rdd, cr, M_rdd, Dy, z2 == 4 ? [8,1,0] : [6,1,0], false, false); iTab[op].f = dr == 0 ? I_LSR : I_LSL; cnt++; @@ -3394,7 +3423,7 @@ function CPU() { op = (113 << 9) | (dr << 8) | (3 << 6) | ea[0]; if (iTab[op].op === -1) { - iTab[op] = mkSD(op, dr == 0 ? 'LSR_M' : 'LSL_M', 2, M_imm, 1, ea[1], ea[2], 8, false, true); + iTab[op] = mkSD(op, dr == 0 ? 'LSR_M' : 'LSL_M', 2, M_imm, 1, ea[1], ea[2], [8,1,1], false, true); iTab[op].f = dr == 0 ? I_LSR : I_LSL; cnt++; } else { @@ -3406,37 +3435,37 @@ function CPU() { } } //MOVE - { + { var tab2 = [ - [ 4,0, 8, 8, 8,12,0,0,14,12,16,0], - [ 4,0, 8, 8, 8,12,0,0,14,12,16,0], - [ 8,0,12,12,12,16,0,0,18,16,20,0], - [ 8,0,12,12,12,16,0,0,18,16,20,0], - [10,0,14,14,14,18,0,0,20,18,22,0], - [12,0,16,16,16,20,0,0,22,20,24,0], - [14,0,18,18,18,22,0,0,24,22,26,0], - [12,0,16,16,16,20,0,0,22,20,24,0], - [14,0,18,18,18,22,0,0,24,22,26,0], - [12,0,16,16,16,20,0,0,22,20,24,0], - [16,0,20,20,20,24,0,0,26,24,28,0], - [ 8,0,12,12,12,16,0,0,18,16,20,0] + [[ 4,1,0],null,[ 8,1,1],[ 8,1,1],[ 8,1,1],[12,2,1],[14,2,1],null,null,[12,2,1],[16,3,1],null], + [[ 4,1,0],null,[ 8,1,1],[ 8,1,1],[ 8,1,1],[12,2,1],[14,2,1],null,null,[12,2,1],[16,3,1],null], + [[ 8,2,0],null,[12,2,1],[12,2,1],[12,2,1],[16,3,1],[18,3,1],null,null,[16,3,1],[20,4,1],null], + [[ 8,2,0],null,[12,2,1],[12,2,1],[12,2,1],[16,3,1],[18,3,1],null,null,[16,3,1],[20,4,1],null], + [[10,2,0],null,[14,2,1],[14,2,1],[14,2,1],[18,3,1],[20,4,1],null,null,[18,3,1],[22,4,1],null], + [[12,3,0],null,[16,3,1],[16,3,1],[16,3,1],[20,4,1],[22,4,1],null,null,[20,4,1],[24,5,1],null], + [[14,3,0],null,[18,3,1],[18,3,1],[18,3,1],[22,4,1],[24,4,1],null,null,[22,4,1],[26,5,1],null], + [[12,3,0],null,[16,3,1],[16,3,1],[16,3,1],[20,4,1],[22,4,1],null,null,[20,4,1],[24,5,1],null], + [[14,3,0],null,[18,3,1],[18,3,1],[18,3,1],[22,4,1],[24,4,1],null,null,[22,4,1],[26,5,1],null], + [[12,3,0],null,[16,3,1],[16,3,1],[16,3,1],[20,4,1],[22,4,1],null,null,[20,4,1],[24,5,1],null], + [[16,4,0],null,[20,4,1],[20,4,1],[20,4,1],[24,5,1],[26,5,1],null,null,[24,5,1],[28,6,1],null], + [[ 8,2,0],null,[12,2,1],[12,2,1],[12,2,1],[16,3,1],[18,3,1],null,null,[16,3,1],[20,4,1],null] ]; var tab4 = [ - [ 4,0,12,12,12,16,0,0,18,16,20,0], - [ 4,0,12,12,12,16,0,0,18,16,20,0], - [12,0,20,20,20,24,0,0,26,24,28,0], - [12,0,20,20,20,24,0,0,26,24,28,0], - [14,0,22,22,22,26,0,0,28,26,30,0], - [16,0,24,24,24,28,0,0,30,28,32,0], - [18,0,26,26,26,30,0,0,32,30,34,0], - [16,0,24,24,24,28,0,0,30,28,32,0], - [18,0,26,26,26,30,0,0,32,30,34,0], - [16,0,24,24,24,28,0,0,30,28,32,0], - [20,0,28,28,28,32,0,0,34,32,36,0], - [12,0,20,20,20,24,0,0,26,24,28,0] - ]; + [[ 4,1,0],null,[12,1,2],[12,1,2],[12,1,2],[16,2,2],[18,2,2],null,null,[16,2,2],[20,3,2],null], + [[ 4,1,0],null,[12,1,2],[12,1,2],[12,1,2],[16,2,2],[18,2,2],null,null,[16,2,2],[20,3,2],null], + [[12,3,0],null,[20,3,2],[20,3,2],[20,3,2],[24,4,2],[26,4,2],null,null,[24,4,2],[28,5,2],null], + [[12,3,0],null,[20,3,2],[20,3,2],[20,3,2],[24,4,2],[26,4,2],null,null,[24,4,2],[28,5,2],null], + [[14,3,0],null,[22,3,2],[22,3,2],[22,3,2],[26,4,2],[28,4,2],null,null,[26,4,2],[30,5,2],null], + [[16,4,0],null,[24,4,2],[24,4,2],[24,4,2],[28,5,2],[30,5,2],null,null,[28,5,2],[32,6,2],null], + [[18,4,0],null,[26,4,2],[26,4,2],[26,4,2],[30,5,2],[32,5,2],null,null,[30,5,2],[34,6,2],null], + [[16,4,0],null,[24,4,2],[24,4,2],[24,4,2],[28,5,2],[30,5,2],null,null,[28,5,2],[32,5,2],null], + [[18,4,0],null,[26,4,2],[26,4,2],[26,4,2],[30,5,2],[32,5,2],null,null,[30,5,2],[34,6,2],null], + [[16,4,0],null,[24,4,2],[24,4,2],[24,4,2],[28,5,2],[30,5,2],null,null,[28,5,2],[32,6,2],null], + [[20,5,0],null,[28,5,2],[28,5,2],[28,5,2],[32,6,2],[34,6,2],null,null,[32,6,2],[36,7,2],null], + [[12,3,0],null,[20,3,2],[20,3,2],[20,3,2],[24,4,2],[26,4,2],null,null,[24,4,2],[28,5,2],null] + ]; var sen = [M_rdd, M_rda, M_ria, M_ripo, M_ripr, M_rid, M_rii, M_pcid, M_pcii, M_absw, M_absl, M_imm]; - var den = [M_rdd,M_ria, M_ripo, M_ripr, M_rid, M_rii,M_absw, M_absl]; + var den = [M_rdd, M_ria, M_ripo, M_ripr, M_rid, M_rii, M_absw, M_absl]; var z, z2, z3, smr, dmr, sea, dea; for (z = 0; z < 3; z++) { @@ -3472,8 +3501,34 @@ function CPU() { } //MOVEA { - var tab2 = [4,4,8,8,10,12,14,12,14,12,16,8]; - var tab4 = [4,4,12,12,14,16,18,16,18,16,20,12]; + var tab2 = [ + [ 4,1,0], + [ 4,1,0], + [ 8,2,0], + [ 8,2,0], + [10,2,0], + [12,3,0], + [14,3,0], + [12,3,0], + [14,3,0], + [12,3,0], + [16,4,0], + [ 8,2,0] + ]; + var tab4 = [ + [ 4,1,0], + [ 4,1,0], + [12,3,0], + [12,3,0], + [14,3,0], + [16,4,0], + [18,4,0], + [16,4,0], + [18,4,0], + [16,4,0], + [20,5,0], + [12,3,0] + ]; var en = [M_rdd, M_rda, M_ria, M_ripo, M_ripr, M_rid, M_rii, M_pcid, M_pcii, M_absw, M_absl, M_imm]; var z, z2, z3, An, mr, ea; @@ -3514,7 +3569,7 @@ function CPU() { op = (267 << 6) | ea[0]; if (iTab[op].op === -1) { - iTab[op] = mkD(op, 'MOVE_CCR2', 2, ea[1], ea[2]); + iTab[op] = mkD(op, 'MOVE_CCR2', 2, ea[1], ea[2], [0,0,0], false); iTab[op].f = I_MOVE_CCR2; cnt++; } else { @@ -3535,7 +3590,7 @@ function CPU() { op = (275 << 6) | ea[0]; if (iTab[op].op === -1) { - iTab[op] = mkS(op, 'MOVE_2CCR', 2, ea[1], ea[2], 12, ea[1] == M_rdd ? false : true); + iTab[op] = mkS(op, 'MOVE_2CCR', 2, ea[1], ea[2], [12,1,0], ea[1] == M_rdd ? false : true); iTab[op].f = I_MOVE_2CCR; cnt++; } else { @@ -3556,7 +3611,7 @@ function CPU() { op = (259 << 6) | ea[0]; if (iTab[op].op === -1) { - iTab[op] = mkD(op, 'MOVE_SR2', 2, ea[1], ea[2], ea[1] == M_rdd ? 6 : 8, ea[1] != M_rdd); + iTab[op] = mkD(op, 'MOVE_SR2', 2, ea[1], ea[2], ea[1] == M_rdd ? [6,1,0] : [8,1,1], ea[1] != M_rdd); iTab[op].f = I_MOVE_SR2; cnt++; } else { @@ -3577,7 +3632,7 @@ function CPU() { op = (283 << 6) | ea[0]; if (iTab[op].op === -1) { - iTab[op] = mkS(op, 'MOVE_2SR', 2, ea[1], ea[2], 12, ea[1] == M_rdd ? false : true); + iTab[op] = mkS(op, 'MOVE_2SR', 2, ea[1], ea[2], [12,1,0], ea[1] == M_rdd ? false : true); iTab[op].pr = true; iTab[op].f = I_MOVE_2SR; cnt++; @@ -3598,9 +3653,9 @@ function CPU() { if (iTab[op].op === -1) { if (dr == 0) - iTab[op] = mkS(op, 'MOVE_A2USP', 4, M_rda, An, 4, false); + iTab[op] = mkS(op, 'MOVE_A2USP', 4, M_rda, An, [4,1,0], false); else - iTab[op] = mkD(op, 'MOVE_USP2A', 4, M_rda, An, 4, false); + iTab[op] = mkD(op, 'MOVE_USP2A', 4, M_rda, An, [4,1,0], false); iTab[op].pr = true; iTab[op].f = (dr == 0) ? I_MOVE_A2USP : I_MOVE_USP2A; @@ -3613,6 +3668,19 @@ function CPU() { } } //MOVEM + /* + instr size (An) (An)+ -(An) d(An) d(An,ix)+ d(PC) d(PC,ix)* xxx.W xxx.L + MOVEM + word 12+4n 12+4n - 16+4n 18+4n 16+4n 18+4n 16+4n 20+4n + M->R (3+n/0) (3+n/0) - (4+n/0) (4+n/0) (4+n/0) (4+n/0) (4+n/0) (5+n/0) + long 12+8n 12+8n - 16+8n 18+8n 16+8n 18+8n 16+8n 20+8n + (3+2n/0) (3+2n/0) - (4+2n/0) (4+2n/0) (4+2n/0) (4+2n/0) (4+2n/0) (5+2n/0) + + MOVEM + word 8+4n - 8+4n 12+4n 14+4n - - 12+4n 16+4n + R->M (2/n) - (2/n) (3/n) (3/n) - - (3/n) (4/n) + long 8+8n - 8+8n 12+8n 14+8n - - 12+8n 16+8n + (2/2n) - (2/2n) (3/2n) (3/2n) - - (3/2n) (4/2n)*/ { var z, z2, dr, mr, ea, cyc; @@ -3630,25 +3698,25 @@ function CPU() { if (iTab[op].op === -1) { if (dr == 0) { switch (ea[1]) { - case M_ria: cyc = 8; break; - case M_ripr: cyc = 8; break; - case M_rid: cyc = 12; break; - case M_rii: cyc = 14; break; - case M_absw: cyc = 12; break; - case M_absl: cyc = 16; break; + case M_ria: cyc = [8,2,0]; break; + case M_ripr: cyc = [8,2,0]; break; + case M_rid: cyc = [12,3,0]; break; + case M_rii: cyc = [14,3,0]; break; + case M_absw: cyc = [12,3,0]; break; + case M_absl: cyc = [16,4,0]; break; } iTab[op] = mkSD(op, 'MOVEM_R2M', z2, M_list, -1, ea[1], ea[2], cyc, false, false); iTab[op].f = I_MOVEM_R2M; } else { switch (ea[1]) { - case M_ria: cyc = 12; break; - case M_ripo: cyc = 12; break; - case M_rid: cyc = 16; break; - case M_rii: cyc = 18; break; - case M_pcid: cyc = 16; break; - case M_pcii: cyc = 18; break; - case M_absw: cyc = 16; break; - case M_absl: cyc = 20; break; + case M_ria: cyc = [12,3,0]; break; + case M_ripo: cyc = [12,3,0]; break; + case M_rid: cyc = [16,4,0]; break; + case M_rii: cyc = [18,4,0]; break; + case M_pcid: cyc = [16,4,0]; break; + case M_pcii: cyc = [18,4,0]; break; + case M_absw: cyc = [16,4,0]; break; + case M_absl: cyc = [20,5,0]; break; } iTab[op] = mkSD(op, 'MOVEM_M2R', z2, M_list, -1, ea[1], ea[2], cyc, false, false); iTab[op].f = I_MOVEM_M2R; @@ -3675,13 +3743,13 @@ function CPU() { if (iTab[op].op === -1) { if (m == 0) - iTab[op] = mkSD(op, 'MOVEP', 2, M_rid, An, M_rdd, Dn, 16, false, false); + iTab[op] = mkSD(op, 'MOVEP', 2, M_rid, An, M_rdd, Dn, [16,4,0], false, false); else if (m == 1) - iTab[op] = mkSD(op, 'MOVEP', 4, M_rid, An, M_rdd, Dn, 24, false, false); + iTab[op] = mkSD(op, 'MOVEP', 4, M_rid, An, M_rdd, Dn, [24,6,0], false, false); else if (m == 2) - iTab[op] = mkSD(op, 'MOVEP', 2, M_rdd, Dn, M_rid, An, 16, false, false); + iTab[op] = mkSD(op, 'MOVEP', 2, M_rdd, Dn, M_rid, An, [16,2,2], false, false); else - iTab[op] = mkSD(op, 'MOVEP', 4, M_rdd, Dn, M_rid, An, 24, false, false); + iTab[op] = mkSD(op, 'MOVEP', 4, M_rdd, Dn, M_rid, An, [24,2,4], false, false); iTab[op].f = I_MOVEP; cnt++; @@ -3702,7 +3770,7 @@ function CPU() { op = (7 << 12) | (Dn << 9) | d; if (iTab[op].op === -1) { - iTab[op] = mkSD(op, 'MOVEQ', 4, M_imm, d, M_rdd, Dn, 4, false, false); + iTab[op] = mkSD(op, 'MOVEQ', 4, M_imm, d, M_rdd, Dn, [4,1,0], false, false); iTab[op].f = I_MOVEQ; cnt++; } else { @@ -3724,7 +3792,7 @@ function CPU() { op = (12 << 12) | (Dn << 9) | (7 << 6) | ea[0]; if (iTab[op].op === -1) { - iTab[op] = mkSD(op, 'MULS', 2, ea[1], ea[2], M_rdd, Dn, 70, true, false); + iTab[op] = mkSD(op, 'MULS', 2, ea[1], ea[2], M_rdd, Dn, [70,1,0], true, false); iTab[op].f = I_MULS; cnt++; } else { @@ -3747,7 +3815,7 @@ function CPU() { op = (12 << 12) | (Dn << 9) | (3 << 6) | ea[0]; if (iTab[op].op === -1) { - iTab[op] = mkSD(op, 'MULU', 2, ea[1], ea[2], M_rdd, Dn, 70, true, false); + iTab[op] = mkSD(op, 'MULU', 2, ea[1], ea[2], M_rdd, Dn, [70,1,0], true, false); iTab[op].f = I_MULU; cnt++; } else { @@ -3769,7 +3837,7 @@ function CPU() { op = (288 << 6) | ea[0]; if (iTab[op].op === -1) { - iTab[op] = mkD(op, 'NBCD', 1, ea[1], ea[2], ea[1] == M_rdd ? 6 : 8, ea[1] != M_rdd); + iTab[op] = mkD(op, 'NBCD', 1, ea[1], ea[2], ea[1] == M_rdd ? [6,1,0] : [8,1,1], ea[1] != M_rdd); iTab[op].f = I_NBCD; cnt++; } else { @@ -3792,7 +3860,7 @@ function CPU() { op = (68 << 8) | (z << 6) | ea[0]; if (iTab[op].op === -1) { - iTab[op] = mkD(op, 'NEG', z2, ea[1], ea[2], ea[1] == M_rdd ? (z2 == 4 ? 6 : 4) : (z2 == 4 ? 12 : 8), ea[1] != M_rdd); + iTab[op] = mkD(op, 'NEG', z2, ea[1], ea[2], ea[1] == M_rdd ? (z2 == 4 ? [6,1,0] : [4,1,0]) : (z2 == 4 ? [12,1,2] : [8,1,1]), ea[1] != M_rdd); iTab[op].f = I_NEG; cnt++; } else { @@ -3816,7 +3884,7 @@ function CPU() { op = (64 << 8) | (z << 6) | ea[0]; if (iTab[op].op === -1) { - iTab[op] = mkD(op, 'NEGX', z2, ea[1], ea[2], ea[1] == M_rdd ? (z2 == 4 ? 6 : 4) : (z2 == 4 ? 12 : 8), ea[1] != M_rdd); + iTab[op] = mkD(op, 'NEGX', z2, ea[1], ea[2], ea[1] == M_rdd ? (z2 == 4 ? [6,1,0] : [4,1,0]) : (z2 == 4 ? [12,1,2] : [8,1,1]), ea[1] != M_rdd); iTab[op].f = I_NEGX; cnt++; } else { @@ -3832,7 +3900,7 @@ function CPU() { op = 0x4E71; if (iTab[op].op === -1) { - iTab[op] = mkN(op, 'NOP', 4); + iTab[op] = mkN(op, 'NOP', [4,1,0]); iTab[op].f = I_NOP; cnt++; } else { @@ -3853,7 +3921,7 @@ function CPU() { op = (70 << 8) | (z << 6) | ea[0]; if (iTab[op].op === -1) { - iTab[op] = mkD(op, 'NOT', z2, ea[1], ea[2], ea[1] == M_rdd ? (z2 == 4 ? 6 : 4) : (z2 == 4 ? 12 : 8), ea[1] != M_rdd); + iTab[op] = mkD(op, 'NOT', z2, ea[1], ea[2], ea[1] == M_rdd ? (z2 == 4 ? [6,1,0] : [4,1,0]) : (z2 == 4 ? [12,1,2] : [8,1,1]), ea[1] != M_rdd); iTab[op].f = I_NOT; cnt++; } else { @@ -3880,7 +3948,7 @@ function CPU() { if (ea[0] != -1) { op = (8 << 12) | (Dn << 9) | (dir << 8) | (z << 6) | ea[0]; - cyc = dir == 0 ? (z2 == 4 ? (ea[1] == M_rdd || ea[1] == M_imm ? 8 : 6) : (ea[1] == M_rdd || ea[1] == M_imm ? 8 : 4)) : (z2 == 4 ? 12 : 8); + cyc = dir == 0 ? (z2 == 4 ? (ea[1] == M_rdd || ea[1] == M_imm ? [8,1,0] : [6,1,0]) : (ea[1] == M_rdd || ea[1] == M_imm ? [8,1,0] : [4,1,0])) : (z2 == 4 ? [12,1,2] : [8,1,1]); if (iTab[op].op === -1) { if (dir == 0) @@ -3889,7 +3957,6 @@ function CPU() { iTab[op] = mkSD(op, 'OR', z2, M_rdd, Dn, ea[1], ea[2], cyc, false, true); iTab[op].f = I_OR; - //iTab[op].p.cyc = (dir == 0 ? (z2 == 4 ? (ea[1]==M_rdd||ea[1]==M_imm?8:6) : (ea[1]==M_rdd||ea[1]==M_imm?8:4)) : (z2 == 4 ? 12 : 8)) + mkCyc(z2, ea[1]); cnt++; } else { BUG.say('OP EXISTS OR ' + op); @@ -3914,7 +3981,7 @@ function CPU() { op = (z << 6) | ea[0]; if (iTab[op].op === -1) { - iTab[op] = mkSD(op, 'ORI', z2, M_imm, -1, ea[1], ea[2], ea[1] == M_rdd ? (z2 == 4 ? 16 : 8) : (z2 == 4 ? 20 : 12), false, ea[1] != M_rdd); + iTab[op] = mkSD(op, 'ORI', z2, M_imm, -1, ea[1], ea[2], ea[1] == M_rdd ? (z2 == 4 ? [16,3,0] : [8,2,0]) : (z2 == 4 ? [20,3,2] : [12,2,1]), false, ea[1] != M_rdd); iTab[op].f = I_ORI; cnt++; } else { @@ -3930,7 +3997,7 @@ function CPU() { op = 0x3C; if (iTab[op].op === -1) { - iTab[op] = mkS(op, 'ORI_CCR', 1, M_imm, -1, 20, false); + iTab[op] = mkS(op, 'ORI_CCR', 1, M_imm, -1, [20,3,0], false); iTab[op].f = I_ORI_CCR; cnt++; } else { @@ -3943,7 +4010,7 @@ function CPU() { op = 0x7C; if (iTab[op].op === -1) { - iTab[op] = mkS(op, 'ORI_SR', 2, M_imm, -1, 20, false); + iTab[op] = mkS(op, 'ORI_SR', 2, M_imm, -1, [20,3,0], false); iTab[op].pr = true; iTab[op].f = I_ORI_SR; cnt++; @@ -3951,7 +4018,7 @@ function CPU() { BUG.say('OP EXISTS ORI_SR ' + op); return false; } - } + } //PEA { var en = [M_ria, M_rid, M_rii, M_pcid, M_pcii, M_absw, M_absl]; @@ -3964,13 +4031,13 @@ function CPU() { if (iTab[op].op === -1) { switch (ea[1]) { - case M_ria: cyc = 12; break; - case M_rid: cyc = 16; break; - case M_rii: cyc = 20; break; - case M_pcid: cyc = 16; break; - case M_pcii: cyc = 20; break; - case M_absw: cyc = 16; break; - case M_absl: cyc = 20; break; + case M_ria: cyc = [12,1,2]; break; + case M_rid: cyc = [16,2,2]; break; + case M_rii: cyc = [20,2,2]; break; + case M_pcid: cyc = [16,2,2]; break; + case M_pcii: cyc = [20,2,2]; break; + case M_absw: cyc = [16,2,2]; break; + case M_absl: cyc = [20,3,2]; break; } iTab[op] = mkS(op, 'PEA', 4, ea[1], ea[2], cyc, false); iTab[op].f = I_PEA; @@ -3987,7 +4054,7 @@ function CPU() { op = 0x4E70; if (iTab[op].op === -1) { - iTab[op] = mkN(op, 'RESET', 132); + iTab[op] = mkN(op, 'RESET', [132,1,0]); iTab[op].f = I_RESET; cnt++; } else { @@ -4011,9 +4078,9 @@ function CPU() { if (iTab[op].op === -1) { if (ir == 0) - iTab[op] = mkSD(op, dr == 0 ? 'ROR_RI' : 'ROL_RI', z2, M_imm, cr == 0 ? 8 : cr, M_rdd, Dy, z2 == 4 ? 8 : 6, false, false); + iTab[op] = mkSD(op, dr == 0 ? 'ROR_RI' : 'ROL_RI', z2, M_imm, cr == 0 ? 8 : cr, M_rdd, Dy, z2 == 4 ? [8,1,0] : [6,1,0], false, false); else - iTab[op] = mkSD(op, dr == 0 ? 'ROR_RD' : 'ROL_RD', z2, M_rdd, cr, M_rdd, Dy, z2 == 4 ? 8 : 6, false, false); + iTab[op] = mkSD(op, dr == 0 ? 'ROR_RD' : 'ROL_RD', z2, M_rdd, cr, M_rdd, Dy, z2 == 4 ? [8,1,0] : [6,1,0], false, false); iTab[op].f = dr == 0 ? I_ROR : I_ROL; cnt++; @@ -4033,7 +4100,7 @@ function CPU() { op = (115 << 9) | (dr << 8) | (3 << 6) | ea[0]; if (iTab[op].op === -1) { - iTab[op] = mkSD(op, dr == 0 ? 'ROR_M' : 'ROL_M', 2, M_imm, 1, ea[1], ea[2], 8, false, true); + iTab[op] = mkSD(op, dr == 0 ? 'ROR_M' : 'ROL_M', 2, M_imm, 1, ea[1], ea[2], [8,1,1], false, true); iTab[op].f = dr == 0 ? I_ROR : I_ROL; cnt++; } else { @@ -4060,9 +4127,9 @@ function CPU() { if (iTab[op].op === -1) { if (ir == 0) - iTab[op] = mkSD(op, dr == 0 ? 'ROXR_RI' : 'ROXL_RI', z2, M_imm, cr == 0 ? 8 : cr, M_rdd, Dy, z2 == 4 ? 8 : 6, false, false); + iTab[op] = mkSD(op, dr == 0 ? 'ROXR_RI' : 'ROXL_RI', z2, M_imm, cr == 0 ? 8 : cr, M_rdd, Dy, z2 == 4 ? [8,1,0] : [6,1,0], false, false); else - iTab[op] = mkSD(op, dr == 0 ? 'ROXR_RD' : 'ROXL_RD', z2, M_rdd, cr, M_rdd, Dy, z2 == 4 ? 8 : 6, false, false); + iTab[op] = mkSD(op, dr == 0 ? 'ROXR_RD' : 'ROXL_RD', z2, M_rdd, cr, M_rdd, Dy, z2 == 4 ? [8,1,0] : [6,1,0], false, false); iTab[op].f = dr == 0 ? I_ROXR : I_ROXL; cnt++; @@ -4082,7 +4149,7 @@ function CPU() { op = (114 << 9) | (dr << 8) | (3 << 6) | ea[0]; if (iTab[op].op === -1) { - iTab[op] = mkSD(op, dr == 0 ? 'ROXR_M' : 'ROXL_M', 2, M_imm, 1, ea[1], ea[2], 8, false, true); + iTab[op] = mkSD(op, dr == 0 ? 'ROXR_M' : 'ROXL_M', 2, M_imm, 1, ea[1], ea[2], [8,1,1], false, true); iTab[op].f = dr == 0 ? I_ROXR : I_ROXL; cnt++; } else { @@ -4098,7 +4165,7 @@ function CPU() { op = 0x4E73; if (iTab[op].op === -1) { - iTab[op] = mkN(op, 'RTE', 20); + iTab[op] = mkN(op, 'RTE', [20,5,0]); iTab[op].pr = true; iTab[op].f = I_RTE; cnt++; @@ -4112,7 +4179,7 @@ function CPU() { op = 0x4E77; if (iTab[op].op === -1) { - iTab[op] = mkN(op, 'RTR', 20); + iTab[op] = mkN(op, 'RTR', [20,5,0]); iTab[op].f = I_RTR; cnt++; } else { @@ -4125,7 +4192,7 @@ function CPU() { op = 0x4E75; if (iTab[op].op === -1) { - iTab[op] = mkN(op, 'RTS', 16); + iTab[op] = mkN(op, 'RTS', [16,4,0]); iTab[op].f = I_RTS; cnt++; } else { @@ -4144,9 +4211,9 @@ function CPU() { if (iTab[op].op === -1) { if (rm == 0) - iTab[op] = mkSD(op, 'SBCD', 1, M_rdd, Rx, M_rdd, Ry, 6, false, false); + iTab[op] = mkSD(op, 'SBCD', 1, M_rdd, Rx, M_rdd, Ry, [6,3,1], false, false); else - iTab[op] = mkSD(op, 'SBCD', 1, M_ripr, Rx, M_ripr, Ry, 18, false, false); + iTab[op] = mkSD(op, 'SBCD', 1, M_ripr, Rx, M_ripr, Ry, [18,3,1], false, false); iTab[op].f = I_SBCD; cnt++; @@ -4170,7 +4237,7 @@ function CPU() { op = (5 << 12) | (cc << 8) | (3 << 6) | ea[0]; if (iTab[op].op === -1) { - iTab[op] = mkCD(op, 'S' + ccNames[cc], 1, cc, -1, -1, ea[1], ea[2], ea[1] == M_rdd ? 6 : 8, ea[1] == M_rdd ? 4 : 8, ea[1] != M_rdd); + iTab[op] = mkCD(op, 'S' + ccNames[cc], 1, cc, -1, -1, ea[1], ea[2], ea[1] == M_rdd ? [6,1,0] : [8,1,1], ea[1] == M_rdd ? [4,1,0] : [8,1,1], ea[1] != M_rdd); iTab[op].f = I_Scc; cnt++; } else { @@ -4186,7 +4253,7 @@ function CPU() { op = 0x4E72; if (iTab[op].op === -1) { - iTab[op] = mkS(op, 'STOP', 2, M_imm, -1, 4, false); + iTab[op] = mkS(op, 'STOP', 2, M_imm, -1, [4,0,0], false); iTab[op].pr = true; iTab[op].f = I_STOP; cnt++; @@ -4214,8 +4281,8 @@ function CPU() { op = (9 << 12) | (Dn << 9) | (dir << 8) | (z << 6) | ea[0]; - cyc = dir == 0 ? (z2 == 4 ? (ea[1] == M_rdd || ea[1] == M_imm ? 8 : 6) : 4) : (z2 == 4 ? 12 : 8); - + cyc = dir == 0 ? (z2 == 4 ? (ea[1] == M_rdd || ea[1] == M_imm ? [8,1,0] : [6,1,0]) : [4,1,0]) : (z2 == 4 ? [12,1,2] : [8,1,1]); + if (iTab[op].op === -1) { if (dir == 0) iTab[op] = mkSD(op, 'SUB', z2, ea[1], ea[2], M_rdd, Dn, cyc, true, false); @@ -4223,7 +4290,6 @@ function CPU() { iTab[op] = mkSD(op, 'SUB', z2, M_rdd, Dn, ea[1], ea[2], cyc, false, true); iTab[op].f = I_SUB; - //iTab[op].p.cyc = ((dir == 0) ? (z2 == 4 ? (ea[1]==M_rdd||ea[1]==M_imm?8:6) : 4) : (z2 == 4 ? 12 : 8)) + mkCyc(z2, ea[1]); cnt++; } else { BUG.say('OP EXISTS SUB ' + op); @@ -4250,9 +4316,8 @@ function CPU() { op = (9 << 12) | (An << 9) | (z3 << 6) | ea[0]; if (iTab[op].op === -1) { - iTab[op] = mkSD(op, 'SUBA', z2, ea[1], ea[2], M_rda, An, z2 == 4 ? (ea[1] == M_rdd || ea[1] == M_imm ? 8 : 6) : 8, true, false); + iTab[op] = mkSD(op, 'SUBA', z2, ea[1], ea[2], M_rda, An, z2 == 4 ? (ea[1] == M_rdd || ea[1] == M_imm ? [8,1,0] : [6,1,0]) : [8,1,0], true, false); iTab[op].f = I_SUBA; - //iTab[op].p.cyc = (z2 == 4 ? (ea[1]==M_rdd||ea[1]==M_imm?8:6) : 8) + mkCyc(z2, ea[1]); cnt++; } else { BUG.say('OP EXISTS SUBA ' + op); @@ -4276,7 +4341,7 @@ function CPU() { op = (4 << 8) | (z << 6) | ea[0]; if (iTab[op].op === -1) { - iTab[op] = mkSD(op, 'SUBI', z2, M_imm, -1, ea[1], ea[2], ea[1] == M_rdd ? (z2 == 4 ? 16 : 8) : (z2 == 4 ? 20 : 12), false, ea[1] != M_rdd); + iTab[op] = mkSD(op, 'SUBI', z2, M_imm, -1, ea[1], ea[2], ea[1] == M_rdd ? (z2 == 4 ? [16,3,0] : [8,2,0]) : (z2 == 4 ? [20,3,2] : [12,2,1]), false, ea[1] != M_rdd); iTab[op].f = I_SUBI; cnt++; } else { @@ -4301,11 +4366,12 @@ function CPU() { if (ea[1] == M_rda && z == 0) continue; //An word and long only op = (5 << 12) | (id << 9) | (1 << 8) | (z << 6) | ea[0]; - cyc = ea[1] == M_rda ? 8 : (ea[1] == M_rdd ? (z2 == 4 ? 8 : 4) : (z2 == 4 ? 12 : 8)); + cyc = ea[1] == M_rda ? [8,1,0] : (ea[1] == M_rdd ? (z2 == 4 ? [8,1,0] : [4,1,0]) : (z2 == 4 ? [12,1,2] : [8,1,1])); if (iTab[op].op === -1) { iTab[op] = mkSD(op, 'SUBQ', z2, M_imm, id == 0 ? 8 : id, ea[1], ea[2], cyc, false, ea[1] != M_rdd && ea[1] != M_rda); - iTab[op].f = I_SUBQ; + //iTab[op].f = I_SUBQ; + iTab[op].f = ea[1] != M_rda ? I_SUBQ : I_SUBQA; cnt++; } else { BUG.say('OP EXISTS SUBQ ' + op); @@ -4329,9 +4395,9 @@ function CPU() { if (iTab[op].op === -1) { if (rm == 0) - iTab[op] = mkSD(op, 'SUBX', z2, M_rdd, Rx, M_rdd, Ry, z2 == 4 ? 8 : 4, false, false); + iTab[op] = mkSD(op, 'SUBX', z2, M_rdd, Rx, M_rdd, Ry, z2 == 4 ? [8,1,0] : [4,1,0], false, false); else - iTab[op] = mkSD(op, 'SUBX', z2, M_ripr, Rx, M_ripr, Ry, z2 == 4 ? 30 : 18, false, false); + iTab[op] = mkSD(op, 'SUBX', z2, M_ripr, Rx, M_ripr, Ry, z2 == 4 ? [30,5,2] : [18,1,0], false, false); iTab[op].f = I_SUBX; cnt++; @@ -4352,7 +4418,7 @@ function CPU() { op = (2312 << 3) | Dn; if (iTab[op].op === -1) { - iTab[op] = mkD(op, 'SWAP', 2, M_rdd, Dn, 4, false); + iTab[op] = mkD(op, 'SWAP', 2, M_rdd, Dn, [4,1,0], false); iTab[op].f = I_SWAP; cnt++; } else { @@ -4372,7 +4438,7 @@ function CPU() { op = (299 << 6) | ea[0]; if (iTab[op].op === -1) { - iTab[op] = mkD(op, 'TAS', 1, ea[1], ea[2], ea[1] == M_rdd ? 4 : 10, ea[1] != M_rdd); + iTab[op] = mkD(op, 'TAS', 1, ea[1], ea[2], ea[1] == M_rdd ? [4,1,0] : [10,1,1], ea[1] != M_rdd); iTab[op].f = I_TAS; cnt++; } else { @@ -4390,7 +4456,7 @@ function CPU() { op = (1252 << 4) | v; if (iTab[op].op === -1) { - iTab[op] = mkD(op, 'TRAP', 0, M_imm, v, 38, false); + iTab[op] = mkD(op, 'TRAP', 0, M_imm, v, [38,4,3], false); iTab[op].f = I_TRAP; cnt++; } else { @@ -4404,7 +4470,7 @@ function CPU() { op = 0x4E76; if (iTab[op].op === -1) { - iTab[op] = mkN(op, 'TRAPV', 4); + iTab[op] = mkN(op, 'TRAPV', [4,1,0]); iTab[op].f = I_TRAPV; cnt++; } else { @@ -4425,7 +4491,7 @@ function CPU() { op = (74 << 8) | (z << 6) | ea[0]; if (iTab[op].op === -1) { - iTab[op] = mkD(op, 'TST', z2, ea[1], ea[2], 4, ea[1] != M_rdd && ea[1] != M_rda); + iTab[op] = mkD(op, 'TST', z2, ea[1], ea[2], [4,1,0], ea[1] != M_rdd && ea[1] != M_rda); iTab[op].f = I_TST; cnt++; } else { @@ -4444,7 +4510,7 @@ function CPU() { op = (2507 << 3) | An; if (iTab[op].op === -1) { - iTab[op] = mkS(op, 'UNLK', 0, M_rda, An, 12, false); + iTab[op] = mkS(op, 'UNLK', 0, M_rda, An, [12,3,0], false); iTab[op].f = I_UNLK; cnt++; } else { @@ -4959,32 +5025,36 @@ function CPU() { regs.t = 0; } - function exception(n) { - //BUG.say(sprintf('cpu.exception() nr %d', n)); + function exception_cycles(n) { var c; if (n < 16) switch (n) { - case 0: c = 40; break; //Reset Initial Interrupt Stack Pointer - case 1: c = 40; break; //Reset Initial Program Counter - case 2: c = 50; break; //Access Fault - case 3: c = 50; break; //Address Error - case 4: c = 34; break; //Illegal Instruction - case 5: c = 42; break; //Integer Divide by Zero - case 6: c = 44; break; //CHK, CHK2 Instruction - case 7: c = 34; break; //FTRAPcc, TRAPcc, TRAPV Instructions - case 8: c = 34; break; //Privilege Violation - case 9: c = 34; break; //Trace - case 10: c = 34; break; //Line 1010 Emulator (Unimplemented A- Line Opcode) - case 11: c = 34; break; //Line 1111 Emulator (Unimplemented F-Line Opcode) + case 0: c = [40,6,0]; break; //Reset Initial Interrupt Stack Pointer + case 1: c = [40,6,0]; break; //Reset Initial Program Counter + case 2: c = [50,4,7]; break; //Access Fault + case 3: c = [50,4,7]; break; //Address Error + case 4: c = [34,4,3]; break; //Illegal Instruction + case 5: c = [42,5,3]; break; //Integer Divide by Zero + case 6: c = [44,5,3]; break; //CHK, CHK2 Instruction + case 7: c = [34,4,3]; break; //FTRAPcc, TRAPcc, TRAPV Instructions + case 8: c = [34,4,3]; break; //Privilege Violation + case 9: c = [34,4,3]; break; //Trace + case 10: c = [34,4,3]; break; //Line 1010 Emulator (Unimplemented A- Line Opcode) + case 11: c = [34,4,3]; break; //Line 1111 Emulator (Unimplemented F-Line Opcode) } else if (n >= 24 && n < 32) - c = 44 + 4; + c = [44+4,5,3]; else if (n >= 32 && n < 48) - c = 38; + c = [38,4,3]; else { BUG.say(sprintf('cpu.exception() no cycle for %d', n)); - c = 4; + c = [4,0,0]; } + return c; + } + + function exception(n) { + //BUG.say(sprintf('cpu.exception() nr %d', n)); var olds = regs.s; if (n >= 24 && n < 24 + 8) { @@ -4999,7 +5069,7 @@ function CPU() { regs.s = true; regs.usp = regs.a[7]; regs.a[7] = regs.isp; - + BUG.col = 2; } @@ -5043,7 +5113,7 @@ function CPU() { regs.pc = pc; exception_trace(n); - return c; + return exception_cycles(n); } function exception2(ad) { @@ -5058,34 +5128,6 @@ function CPU() { throw new Exception23(3); } - function cycle_real() { - //if (doDiss) AMIGA.cpu.diss(null, 1); - - var op = nextIWord(); - fault.pc = regs.pc - 2; - fault.op = op; - - var cycles; - try { - cycles = iTab[op].f(iTab[op].p); - } catch (e) { - if (e instanceof Exception23) { - //BUG.info('cpu.cycle() USER EXCEPTION [%d]', e.num); - cycles = exception(e.num); - } - else if (e instanceof Error) { - BUG.info('cpu.cycle() ERROR EXCEPTION [%s]', e); - cycles = 4; - } else { - BUG.info('cpu.cycle() UNKNOWN EXCEPTION [%s]', e); - cycles = 4; - } - } - //if (doDiss) { if (doDiss) doDiss--; AMIGA.cpu.dump(); } - - return cycles >> 1; - } - function interrupt(nr) { regs.stopped = false; clr_special(SPCFLAG_STOP); @@ -5097,16 +5139,8 @@ function CPU() { AMIGA.doint(); } - var last_trace_ad = 0; function trace() { - /*if (regs.t0 && AMIGA.config.cpu.model >= 68020) { - } else if (regs.t1) { - last_trace_ad = regs.pc; - clr_special(SPCFLAG_TRACE); - set_special(SPCFLAG_DOTRACE); - }*/ if (regs.t) { - last_trace_ad = regs.pc; clr_special(SPCFLAG_TRACE); set_special(SPCFLAG_DOTRACE); } @@ -5116,117 +5150,97 @@ function CPU() { if (AMIGA.spcflags & SPCFLAG_COPPER) AMIGA.copper.cycle(); - while ((AMIGA.spcflags & SPCFLAG_BLTNASTY) && AMIGA.dmaen(DMAF_BLTEN) && cycles > 0 && !AMIGA.config.blitter.exact) { + while ((AMIGA.spcflags & SPCFLAG_BLTNASTY) && AMIGA.dmaen(DMAF_BLTEN) && cycles > 0) { var c = AMIGA.blitter.blitnasty(); - if (c < 0) { - break; - } else if (c > 0) { + if (c > 0) { cycles -= c * CYCLE_UNIT * 2; if (cycles < CYCLE_UNIT) cycles = 0; - } else { + } else c = 4; - } - /*if (c == 0) { //old blitter - cycles -= 2 * CYCLE_UNIT; - if (cycles < CYCLE_UNIT) cycles = 0; - c = 1; - }*/ + AMIGA.events.cycle(c * CYCLE_UNIT); - if (AMIGA.spcflags & SPCFLAG_COPPER) AMIGA.copper.cycle(); + if (AMIGA.spcflags & SPCFLAG_COPPER) + AMIGA.copper.cycle(); } - /*if (AMIGA.spcflags & SPCFLAG_DOTRACE) + if (AMIGA.spcflags & SPCFLAG_DOTRACE) exception(9); - if (AMIGA.spcflags & SPCFLAG_TRAP) { clr_special(SPCFLAG_TRAP); exception(3); - }*/ + } while (AMIGA.spcflags & SPCFLAG_STOP) { - AMIGA.events.cycle (AMIGA.config.cpu.exact ? 2 * CYCLE_UNIT : 4 * CYCLE_UNIT); + AMIGA.events.cycle(4 * CYCLE_UNIT); if (AMIGA.spcflags & SPCFLAG_COPPER) AMIGA.copper.cycle(); - if (AMIGA.config.cpu.exact) { - regs.ipl = regs.ipl_pin; - if (regs.ipl > regs.intmask || regs.ipl == 7) - interrupt(regs.ipl); - } else { - if (AMIGA.spcflags & (SPCFLAG_INT | SPCFLAG_DOINT)) { - clr_special(SPCFLAG_INT | SPCFLAG_DOINT); - var intr = AMIGA.intlev(); - if (intr > 0 && intr > regs.intmask) - interrupt(intr); - } + if (AMIGA.spcflags & (SPCFLAG_INT | SPCFLAG_DOINT)) { + clr_special(SPCFLAG_INT | SPCFLAG_DOINT); + var intr = AMIGA.intlev(); + if (intr > 0 && intr > regs.intmask) + interrupt(intr); } - - /*if ((AMIGA.spcflags & (SPCFLAG_BRK | SPCFLAG_MODE_CHANGE))) { - clr_special(SPCFLAG_BRK | SPCFLAG_MODE_CHANGE); + /*if (AMIGA.spcflags & SPCFLAG_BRK) { + clr_special(SPCFLAG_BRK); clr_special(SPCFLAG_STOP); regs.stopped = false; - return 1; - }*/ - if (AMIGA.state != CMD_CYCLE) { - if (regs.stopped) { - regs.stopped = false; - if (AMIGA.config.cpu.exact && AMIGA.config.cpu.model == 68000) - AMIGA.events.cycle(CYCLE_UNIT / 2 * 6); - clr_special(SPCFLAG_STOP); - } - return 1; - } + return true; + }*/ } if (AMIGA.spcflags & SPCFLAG_TRACE) trace(); - if (AMIGA.config.cpu.exact) { - if (regs.ipl > regs.intmask || regs.ipl == 7) - interrupt(regs.ipl); - } else { - if (AMIGA.spcflags & SPCFLAG_INT) { - clr_special(SPCFLAG_INT | SPCFLAG_DOINT); - var intr = AMIGA.intlev(); - if (intr > 0 && (intr > regs.intmask || intr == 7)) - interrupt(intr); - } + if (AMIGA.spcflags & SPCFLAG_INT) { + clr_special(SPCFLAG_INT | SPCFLAG_DOINT); + var intr = AMIGA.intlev(); + if (intr > 0 && (intr > regs.intmask || intr == 7)) + interrupt(intr); } - if (AMIGA.spcflags & SPCFLAG_DOINT) { clr_special(SPCFLAG_DOINT); set_special(SPCFLAG_INT); } - - /*if ((AMIGA.spcflags & (SPCFLAG_BRK | SPCFLAG_MODE_CHANGE))) { - clr_special(SPCFLAG_BRK | SPCFLAG_MODE_CHANGE); - return 1; - }*/ - if (AMIGA.state != CMD_CYCLE) - return 1; - - return 0; + /*if (AMIGA.spcflags & SPCFLAG_BRK) { + clr_special(SPCFLAG_BRK); + return true; + }*/ + return false; } - this.cycles = 2; - this.cycle = function() { - AMIGA.events.cycle(this.cycles * CYCLE_UNIT); - if (AMIGA.state != CMD_CYCLE) - return; + while (AMIGA.state == ST_CYCLE) { + AMIGA.events.cycle(cpu_cycles); - this.cycles = cycle_real(); - - if (AMIGA.spcflags) { - if (cycle_spc(this.cycles * CYCLE_UNIT)) - return; + var op = nextOPCode(); + try { + var cycles = iTab[op].f(iTab[op].p); + cpu_cycles = cycles[0] * cpu_cycle_unit; + } catch (e) { + if (e instanceof Exception23) { + //BUG.info('cpu.cycle_real() USER EXCEPTION [%d]', e.num); + var cycles = exception(e.num); + cpu_cycles = cycles[0] * cpu_cycle_unit; + } + else if (e instanceof VSync) { + //BUG.info('cpu.cycle_real() VSYNC [%s]', e); + cpu_cycles = 48 * cpu_cycle_unit; + throw new VSync(e.error, e.message); + } + else if (e instanceof FatalError) { + //BUG.info('cpu.cycle_real() FATAL ERROR [%s]', e); + Fatal(e.error, e.message); + } + else { + Fatal(SAEE_CPU_Internal, e.message); + } + } + + if (AMIGA.spcflags) + cycle_spc(cpu_cycles); } - regs.ipl = regs.ipl_pin; - } - - this.setIPL = function(lev) { - regs.ipl_pin = lev; - } + } } \ No newline at end of file diff --git a/sae/custom.js b/sae/custom.js index 18f96e1..77ad5eb 100644 --- a/sae/custom.js +++ b/sae/custom.js @@ -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) { diff --git a/sae/disk.js b/sae/disk.js index 490bad8..0800fec 100644 --- a/sae/disk.js +++ b/sae/disk.js @@ -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) { diff --git a/sae/events.js b/sae/events.js index b989c28..9d8c7b7 100644 --- a/sae/events.js +++ b/sae/events.js @@ -25,50 +25,45 @@ function Event2() { function Events() { const SYNCBASE = 1000; - this.lofChanged = false; - this.lofStore = 0; - this.lof = 0; - this.lol = 0; - - this.vpos = 0; - this.vpos_previous = 0; - this.hpos_previous = 0; - - this.maxhpos = 0; - this.maxvpos = 0; - this.hz = 0; - - var dmal = 0 - var dmal_hpos = 0; - - var vsynctimebase = 0; - var vsyncmintime = 0; - var vsynctimeperline = 0; - var vsyncmaxtime = 0; - var vsyncwaittime = 0; - var vsync_rendered = false; - var is_syncline = 0; - var is_syncline_end = 0; - - var frameskip = new mavg(128); - var frameskiptime = 0; - - var counter = { - lasttime:0, - frametime:0, - frames:0, - fps:new mavg(10), - idle:new mavg(10), - idletime:0, - bogus:0 - }; - this.timeframes = 0; - this.eventtab = null; this.eventtab2 = null; this.currcycle = 0; - var nextEvent = 0; - var nextEvent2 = EV2_MISC; + var nextevent = 0; + var nextevent2 = 0; + + var dmal = 0 + var dmal_hpos = 0; + + var vsynctimebase = 0; + var vsyncmintime = 0; + var vsyncmaxtime = 0; + var vsyncwaittime = 0; + var vsynctimeperline = 0; + var is_syncline = 0; + var is_syncline_end = 0; + //var hsync_counter = 0; + //var vsync_counter = 0; + + const MAVG_VSYNC_SIZE = 128; + var ma_frameskipt = new mavg(MAVG_VSYNC_SIZE); + + const FPSCOUNTER_MAVG_SIZE = 10; + var fps_mavg = new mavg(FPSCOUNTER_MAVG_SIZE); + var idle_mavg = new mavg(FPSCOUNTER_MAVG_SIZE); + var timeframes = 0; + var lastframetime = 0; + var idletime = 0; + var frametime = 0; + var frameskiptime = 0; + var linecounter = 0; + + var vsync_rendered = false; + var frame_rendered = false; + var frame_shown = false; + + var vsyncresume = false; + + /*---------------------------------*/ this.setup = function() { if (this.eventtab === null) { @@ -78,47 +73,39 @@ function Events() { this.eventtab[EV_CIA].handler = function() { AMIGA.cia.handler(); } this.eventtab[EV_AUDIO].handler = function() { AMIGA.audio.handler(); } - this.eventtab[EV_MISC].handler = function() { var stack = { recursive:0, dorecheck:false }; AMIGA.events.MISC_handler(stack); } - this.eventtab[EV_HSYNC].handler = function() { AMIGA.events.hSync(); } - //this.eventtab[EV_COPPER].handler = function() { AMIGA.copper.handler(); } - //this.eventtab[EV_BLITTER].handler = function() { AMIGA.blitter.handler(); } - //this.eventtab[EV_RENDER].handler = function() { AMIGA.playfield.hSync(); } - - BUG.info('Events.setup() set %d event handlers', EV_MAX); - } else - BUG.info('Events.setup() event handlers are cached...'); - + this.eventtab[EV_MISC].handler = function() { AMIGA.events.misc_handler(); } + this.eventtab[EV_HSYNC].handler = function() { AMIGA.events.hsync_handler(); } + } if (this.eventtab2 === null) { this.eventtab2 = new Array(EV2_MAX); for (var i = 0; i < EV2_MAX; i++) this.eventtab2[i] = new Event2(); - //this.eventtab[EV2_BLITTER].handler = function(data) { AMIGA.blitter.handler(data); } - //this.eventtab[EV2_DISK].handler = function(data) { AMIGA.disk.handler(data); } - - BUG.info('Events.setup() set %d event2 handlers', EV2_MAX); - } else - BUG.info('Events.setup() event2 handlers are cached...'); - - this.initHz(); + this.eventtab2[EV2_BLITTER].handler = function(data) { AMIGA.blitter.handler(data); } + this.eventtab2[EV2_DISK].handler = function(data) { AMIGA.disk.handler(data); } + this.eventtab2[EV2_DMAL].handler = function(data) { AMIGA.events.dmal_handler(data); } + } + + this.calc_vsynctimebase(AMIGA.config.video.ntsc ? 60 : 50); } this.reset = function() { - this.lofStore = 1; - this.lof = 1; - this.lol = 0; - this.vpos = 0; - dmal = 0 dmal_hpos = 0; - - frameskip.clr(); - frameskiptime = 0; - this.fpscounter_reset(); - - this.initHz(); this.currcycle = 0; + nextevent = CYCLE_MAX; + nextevent2 = EV2_MISC; + + vsynctimebase = 0; + vsyncmintime = 0; + vsyncmaxtime = 0; + vsyncwaittime = 0; + vsynctimeperline = 0; + is_syncline = 0; + is_syncline_end = 0; + + this.fpscounter_reset(); for (var i = 0; i < EV_MAX; i++) { this.eventtab[i].active = false; @@ -129,30 +116,18 @@ function Events() { this.eventtab2[i].active = false; this.eventtab2[i].evtime = 0; } - this.eventtab[EV_HSYNC].evtime = this.maxhpos * CYCLE_UNIT; /* 0xe3 */ + this.eventtab[EV_HSYNC].evtime = 227 * CYCLE_UNIT; /* 0xe3 */ this.eventtab[EV_HSYNC].active = true; - /*if (AMIGA.config.video.enabled) { - //this.eventtab[EV_RENDER].evtime = 0x38 * CYCLE_UNIT; - this.eventtab[EV_RENDER].evtime = 0xd4 * CYCLE_UNIT; - this.eventtab[EV_RENDER].active = true; - }*/ + this.schedule(); } - - /*---------------------------------*/ - - this.initHz = function() { - if (!AMIGA.config.video.ntsc) { - this.maxvpos = 312; - this.maxhpos = 227; - this.hz = 50; - } else { - this.maxvpos = 262; - this.maxhpos = 227; - this.hz = 60; - } - vsynctimebase = SYNCBASE / this.hz; + + this.calc_vsynctimebase = function(hz) { + vsynctimebase = Math.floor(SYNCBASE / hz); + //vsynctimebase >>= 1;//(AMIGA.config.video.framerate > 1 ? 1 : 0); } + + /*---------------------------------*/ this.hpos = function() { return Math.floor((this.currcycle - this.eventtab[EV_HSYNC].oldcycles) * CYCLE_UNIT_INV); @@ -162,121 +137,6 @@ function Events() { return (endcycles - this.currcycle > 0); } - /*this.get_cycles = function() { - return this.currcycle; - } - - this.set_cycles = function(x) { - this.currcycle = x; - this.eventtab[EV_HSYNC].oldcycles = x; - }*/ - - /*---------------------------------*/ - - this.MISC_handler = function(stack) { - //console.log('MISC_handler() recursive %d', stack.recursive); - var mintime; - var recheck; - var ct = AMIGA.events.currcycle; - - if (stack.recursive) { - stack.dorecheck = true; - return; - } - stack.recursive++; - AMIGA.events.eventtab[EV_MISC].active = false; - recheck = true; - while (recheck) { - recheck = false; - mintime = CYCLE_MAX; - - for (var i = 0; i < EV2_MAX; i++) { - if (AMIGA.events.eventtab2[i].active) { - if (AMIGA.events.eventtab2[i].evtime == ct) { - AMIGA.events.eventtab2[i].active = false; - - if (i == EV2_BLITTER) - AMIGA.blitter.handler(AMIGA.events.eventtab2[i].data); - else if (i == EV2_DISK) - AMIGA.disk.handler(AMIGA.events.eventtab2[i].data); - else - AMIGA.events.eventtab2[i].handler(AMIGA.events.eventtab2[i].data); - - if (stack.dorecheck || AMIGA.events.eventtab2[i].active) { - recheck = true; - stack.dorecheck = false; - } - } else { - var eventtime = AMIGA.events.eventtab2[i].evtime - ct; - if (eventtime < mintime) - mintime = eventtime; - } - } - } - } - if (mintime != CYCLE_MAX) { - AMIGA.events.eventtab[EV_MISC].active = true; - AMIGA.events.eventtab[EV_MISC].oldcycles = ct; - AMIGA.events.eventtab[EV_MISC].evtime = ct + mintime; - AMIGA.events.schedule(); - } - stack.recursive--; - } - - this.event2_newevent_xx = function(no, t, data, func) { - var et = this.currcycle + t; - if (no < 0) { - no = nextEvent2; - for (;;) { - if (!this.eventtab2[no].active) - break; - //if (this.eventtab2[no].evtime == et && this.eventtab2[no].handler == func && this.eventtab2[no].data == data) - if (this.eventtab2[no].evtime == et && this.eventtab2[no].data == data) - break; - - no++; - if (no == EV2_MAX) - no = EV2_MISC; - if (no == nextEvent2) { - BUG.info('event2_newevent_xx() out of event2\'s!'); - return; - } - } - nextEvent2 = no; - } - this.eventtab2[no].active = true; - this.eventtab2[no].evtime = et; - this.eventtab2[no].handler = func; - this.eventtab2[no].data = data; - - var stack = { recursive:0, dorecheck:false }; - this.MISC_handler(stack); - } - - this.event2_newevent_x = function(no, t, data, func) { - if (t <= 0) { - if (no == EV2_BLITTER) - AMIGA.blitter.handler(data); - else if (no == EV2_DISK) - AMIGA.disk.handler(data); - else - func(data); - } else - this.event2_newevent_xx(no, t * CYCLE_UNIT, data, func); - } - - this.event2_newevent2 = function(t, data, func) { - this.event2_newevent_x(-1, t, data, func); - } - - this.event2_newevent = function(no, t, data) { - this.event2_newevent_x(no, t, data, null); //this.eventtab2[no].handler); - } - - this.event2_remevent = function(no) { - this.eventtab2[no].active = false; - } - /*---------------------------------*/ this.schedule = function() { @@ -288,516 +148,483 @@ function Events() { if (evtime < mintime) mintime = evtime; } } - nextEvent = this.currcycle + mintime; + nextevent = this.currcycle + mintime; } - this.cycle = function (cycles) { - while ((nextEvent - this.currcycle) <= cycles) { + this.cycle = function(cycles) { + if (vsyncresume) { + vsyncresume = false; + this.hsync_handler_post(1); + } + + while ((nextevent - this.currcycle) <= cycles) { if (is_syncline) { - var rpt = new Date().getTime(); - var v = rpt - vsyncmintime; - var v2 = rpt - is_syncline_end; - if (v > vsynctimebase || v < -vsynctimebase) v = 0; - if (v < 0 && v2 < 0) return; + var rpt = read_processor_time(); + if (is_syncline > 0) { + var v = rpt - vsyncmintime; + var v2 = rpt - is_syncline_end; + if (v > vsynctimebase || v < -vsynctimebase) v = 0; + if (v < 0 && v2 < 0) return; + } else if (is_syncline < 0) { + var v = rpt - is_syncline_end; + if (v < 0) return; + } is_syncline = 0; - } + } - cycles -= nextEvent - this.currcycle; - this.currcycle = nextEvent; + cycles -= nextevent - this.currcycle; + this.currcycle = nextevent; for (var i = 0; i < EV_MAX; i++) { if (this.eventtab[i].active && this.eventtab[i].evtime == this.currcycle) this.eventtab[i].handler(this.eventtab[i].data); - } + } this.schedule(); } this.currcycle += cycles; } + + /*---------------------------------*/ + + var stack = { recursive:0, dorecheck:false }; + + this.misc_handler = function() { + //if (stack.recursive > 1) BUG.info('misc_handler() recursive %d', stack.recursive); + var mintime; + var ct = this.currcycle; + + if (stack.recursive) { + stack.dorecheck = true; + return; + } + stack.recursive++; + this.eventtab[EV_MISC].active = false; + + var recheck = true; + while (recheck) { + recheck = false; + mintime = CYCLE_MAX; + + for (var i = 0; i < EV2_MAX; i++) { + if (this.eventtab2[i].active) { + if (this.eventtab2[i].evtime == ct) { + this.eventtab2[i].active = false; + this.eventtab2[i].handler(this.eventtab2[i].data); + + if (stack.dorecheck || this.eventtab2[i].active) { + recheck = true; + stack.dorecheck = false; + } + } else { + var eventtime = this.eventtab2[i].evtime - ct; + if (eventtime < mintime) + mintime = eventtime; + } + } + } + } + if (mintime != CYCLE_MAX) { + this.eventtab[EV_MISC].active = true; + this.eventtab[EV_MISC].oldcycles = ct; + this.eventtab[EV_MISC].evtime = ct + mintime; + this.schedule(); + } + stack.recursive--; + } + + this.newevent2_x = function(t, data, func) { + var et = this.currcycle + t; + var no = nextevent2; + for (;;) { + if (!this.eventtab2[no].active) + break; + + no++; + if (no == EV2_MAX) + no = EV2_MISC; + if (no == nextevent2) { + BUG.info('newevent2_x() out of events!'); + return; + } + } + nextevent2 = no; + + this.eventtab2[no].active = true; + this.eventtab2[no].evtime = et; + this.eventtab2[no].handler = func; + this.eventtab2[no].data = data; + this.misc_handler(); + } + + this.newevent2 = function(t, data, func) { + if (t <= 0) + func(data); + else + this.newevent2_x(t * CYCLE_UNIT, data, func); + } + + this.newevent = function(id, t, data) { + this.eventtab2[id].active = true; + this.eventtab2[id].evtime = this.currcycle + t * CYCLE_UNIT; + this.eventtab2[id].data = data; + this.misc_handler(); + } + + this.remevent = function(no) { + if (this.eventtab2[no].active) { + this.eventtab2[no].active = false; + //BUG.info('remevent() %d', no); + } + } /*---------------------------------*/ this.dmal_emu = function(v) { if (!(AMIGA.dmacon & DMAF_DMAEN)) return; - - //BUG.info('Events.dmal_emu() %d', v); + var hpos = this.hpos(); if (v >= 6) { v -= 6; - var nr = v >>> 1; + var nr = v >> 1; var pt = AMIGA.audio.getpt(nr, (v & 1) != 0); - var dat = AMIGA.mem.load16_chip(pt); + //var dat = AMIGA.mem.load16_chip(pt); + var dat = AMIGA.mem.chip.data[pt >>> 1]; + AMIGA.custom.last_value = dat; AMIGA.audio.AUDxDAT(nr, dat); } else { var w = v & 1; var pt = AMIGA.disk.getpt(); if (w) { if (AMIGA.disk.fifostatus() <= 0) { - var dat = AMIGA.mem.load16_chip(pt); + //var dat = AMIGA.mem.load16_chip(pt); + var dat = AMIGA.mem.chip.data[pt >>> 1]; + AMIGA.custom.last_value = dat; AMIGA.disk.DSKDAT(dat); } } else { if (AMIGA.disk.fifostatus() >= 0) { var dat = AMIGA.disk.DSKDATR(); - AMIGA.mem.store16_chip(pt, dat); + //AMIGA.mem.store16_chip(pt, dat); + AMIGA.mem.chip.data[pt >>> 1] = dat; } } } } - this.dmal_func = function(v) { - this.dmal_emu(v); - this.dmal_handle(0); - } - - this.dmal_func2 = function(v) { + this.dmal_handler = function(v) { while (dmal) { if (dmal & 3) this.dmal_emu(dmal_hpos + ((dmal & 2) ? 1 : 0)); dmal_hpos += 2; dmal >>>= 2; } + this.remevent(EV2_DMAL); } - - this.dmal_handle = function(hp) { - if (!dmal) - return; - if (AMIGA.config.cpu.exact) { - while (dmal) { - if (dmal & 3) - break; - hp += 2; - dmal >>>= 2; - dmal_hpos += 2; - } - this.event2_newevent2(hp, dmal_hpos + ((dmal & 2) ? 1 : 0), function(v) { AMIGA.events.dmal_func(v); }); - dmal &= ~3; - } else { - this.event2_newevent2(hp, 13, function(v) { AMIGA.events.dmal_func2(v); }); - } - } - + this.dmal_hsync = function() { - if (dmal) BUG.info('Events.dmal_hsync() DMAL error!? %04x', dmal); + if (dmal) BUG.info('dmal_hsync() DMAL error!? %04x', dmal); dmal = AMIGA.audio.dmal(); dmal <<= 6; dmal |= AMIGA.disk.dmal(); - if (!dmal) - return; - //BUG.info('Events.dmal_hsync() %04x', dmal); - dmal_hpos = 0; - this.dmal_handle(7); - } - - /*---------------------------------*/ - - this.fpscounter_reset = function() { - counter.frames = 0; - counter.lasttime = new Date().getTime(); - counter.fps.clr(); - counter.idle.clr(); - counter.idletime = 0; - counter.bogus = 2; - this.timeframes = 0; - } - - this.fpscounter = function(frameok) { - var now = new Date().getTime(); - var last = now - counter.lasttime; - counter.lasttime = now; - - if (counter.bogus || last < 0) - return; - - counter.fps.set(last / 10); - counter.idle.set(counter.idletime / 10); - counter.idletime = 0; - - counter.frametime += last; - counter.frames++; - this.timeframes++; - if ((counter.frames & 7) == 0) { - var idle = 1000 - (counter.idle.average == 0 ? 0 : counter.idle.average * 1000 / vsynctimebase); - var fps = counter.fps.average == 0 ? 0 : SYNCBASE * 10 / counter.fps.average; - if (fps > 9999) fps = 9999; - if (idle < 0) idle = 0; - if (idle > 100 * 10) idle = 100 * 10; - if (fps < this.hz * 10) idle *= (this.hz * 10 / fps); - - if ((counter.frames & 15) == 0) { - AMIGA.config.hooks.fps(Math.round(fps * 0.1)); - AMIGA.config.hooks.cpu(Math.round(idle * 0.1)); - } + if (dmal) { + dmal_hpos = 0; + this.newevent(EV2_DMAL, 7, 13); } } - var lastskiptime = new Date().getTime(); - this.testFrameSkip = function() { - var now = new Date().getTime(); - var time = now - lastskiptime; - lastskiptime = now; - - var fps = Math.floor(SYNCBASE / (time * 0.1)) * 0.1; - if (fps < this.hz) { - if (AMIGA.playfield.frame.skip) { - if (++AMIGA.playfield.frame.skipcount >= MAX_FRAMESKIP_COUNT) { - if (!AMIGA.playfield.state.ilace || (AMIGA.playfield.state.ilace && this.lof == 1)) { - AMIGA.playfield.frame.skipcount = 0; - AMIGA.playfield.frame.skip = false; - //BUG.info('Events.vSyncPost() force frameskip disable'); - } - } - } else { - if (!AMIGA.playfield.state.ilace || (AMIGA.playfield.state.ilace && this.lof == 0)) - AMIGA.playfield.frame.skip = true; - } - } else { - AMIGA.playfield.frame.skip = false; - AMIGA.playfield.frame.skipcount = 0; - } - //AMIGA.playfield.frame.skip = (AMIGA.playfield.frame.count & 1) == 1; - } - /*---------------------------------*/ - /*function getTime() { - return new Date().getTime(); - }*/ - - this.sleep = function(ms) { - //console.log('sleep'); + function sleep(ms) { var start = new Date().getTime(); while ((new Date().getTime() - start) < ms); } - this.rpt_vsync = function(adjust) { - var t = new Date().getTime(); - var v = t - vsyncwaittime + adjust; + function read_processor_time() { + return (new Date().getTime()); + //return window.performance.now(); + //return window.performance.webkitNow(); + } + + function rpt_vsync(adjust) { + var curr_time = read_processor_time(); + var v = curr_time - vsyncwaittime + adjust; if (v > SYNCBASE || v < -SYNCBASE) { - vsyncmintime = vsyncmaxtime = vsyncwaittime = t; + vsyncmintime = vsyncmaxtime = vsyncwaittime = curr_time; v = 0; } return v; } - - this.framewait = function() { - var curr_time; + + this.framewait = function() { var clockadjust = 0; var vstb = vsynctimebase; - - is_syncline = 0; - - var frameskip_avg = frameskip.set(frameskiptime); - frameskiptime = 0; - //BUG.info(frameskip_avg); - if (AMIGA.config.cpu.speed == SAEV_Config_CPU_Speed_Maximum) { - curr_time = new Date().getTime(); + var frameskipt_avg = ma_frameskipt.set(frameskiptime); + frameskiptime = 0; + + is_syncline = 0; + + if (AMIGA.config.cpu.speed < 0) { + if (!frame_rendered) + frame_rendered = AMIGA.playfield.render_screen(false); + + var curr_time = read_processor_time(); var adjust = 0; - if (curr_time - vsyncwaittime > 0 && curr_time - vsyncwaittime < vstb / 2) + if (Math.floor(curr_time - vsyncwaittime) > 0 && Math.floor(curr_time - vsyncwaittime) < (vstb >> 1)) adjust += curr_time - vsyncwaittime; adjust += clockadjust; - var max = Math.floor(vstb * (1.0 - adjust)); + console.log(adjust); + vsyncwaittime = curr_time + vstb - adjust; vsyncmintime = curr_time; + var max = Math.floor(vstb - adjust); if (max < 0) { max = 0; vsynctimeperline = 1; - } else { - vsynctimeperline = Math.floor(max / (this.maxvpos + 1)); - } - vsyncmaxtime = curr_time + max; + } else + vsynctimeperline = Math.floor(max / (AMIGA.playfield.maxvpos_nom + 1)); - //BUG.info("%06d:%06d/%06d", adjust, vsynctimeperline, vstb); + vsyncmaxtime = curr_time + max; } else { - var start = new Date().getTime(); - while (true) { - var v = this.rpt_vsync(clockadjust);// / (SYNCBASE / 1000.0); - if (v >= -4) break; - this.sleep(2); - } - curr_time = start = new Date().getTime(); - while (this.rpt_vsync(clockadjust) < 0); - counter.idletime += new Date().getTime() - start; + var start; + var t = 0; + + if (!frame_rendered) { + start = read_processor_time(); + frame_rendered = AMIGA.playfield.render_screen(false); + t = read_processor_time() - start; + } + while (rpt_vsync(clockadjust) < -4)// / (SYNCBASE / 1000.0); + sleep(2); + + start = read_processor_time(); + while (rpt_vsync(clockadjust) < 0); + idletime += read_processor_time() - start; - curr_time = new Date().getTime(); + var curr_time = read_processor_time(); vsyncmintime = curr_time; vsyncmaxtime = vsyncwaittime = curr_time + vstb; - - var t = frameskip_avg; - vsynctimeperline = (vstb - t) / 3; + if (frame_rendered) { + frame_shown = AMIGA.playfield.show_screen(); + t += read_processor_time() - curr_time; + } + t += frameskipt_avg; + + vsynctimeperline = Math.floor((vstb - t) / 3); if (vsynctimeperline < 0) vsynctimeperline = 0; - else if (vsynctimeperline > vstb / 3) - vsynctimeperline = vstb / 3; + else if (vsynctimeperline > Math.floor(vstb / 3)) + vsynctimeperline = Math.floor(vstb / 3); } } - - this.is_last_line = function() { - return this.vpos + 1 == this.maxvpos + this.lof_store; - } + this.framewait2 = function() { - if (AMIGA.config.cpu.speed == SAEV_Config_CPU_Speed_Maximum) { - if (this.is_last_line()) { - vsyncmintime = vsyncmaxtime; - is_syncline_end = new Date().getTime() + vsynctimebase; + if (AMIGA.config.cpu.speed < 0) { + if (AMIGA.playfield.is_last_line()) { + /* really last line, just run the cpu emulation until whole vsync time has been used */ + vsyncmintime = vsyncmaxtime; /* emulate if still time left */ + is_syncline_end = read_processor_time() + vsynctimebase; /* far enough in future, we never wait that long */ is_syncline = 1; } else { + /* end of scanline, run cpu emulation as long as we still have time */ vsyncmintime += vsynctimeperline; + linecounter++; is_syncline = 0; - if (vsyncmaxtime - vsyncmintime > 0) { - if (vsyncwaittime - vsyncmintime > 0) { - var rpt = new Date().getTime(); - if (vsyncmintime - rpt > 0) { + if (Math.floor(vsyncmaxtime - vsyncmintime) > 0) { + if (Math.floor(vsyncwaittime - vsyncmintime) > 0) { + var rpt = read_processor_time(); + /* Extra time left? Do some extra CPU emulation */ + if (Math.floor(vsyncmintime - rpt) > 0) { is_syncline = 1; + /* limit extra time */ is_syncline_end = rpt + vsynctimeperline; + linecounter = 0; } } + // extra cpu emulation time if previous 10 lines without extra time. + if (!is_syncline && linecounter >= 10) { + is_syncline = -1; + is_syncline_end = read_processor_time() + vsynctimeperline; + linecounter = 0; + } } } } else { - if (this.is_last_line() && (this.vpos == Math.floor(this.maxvpos * 1 / 3) || this.vpos == Math.floor(this.maxvpos * 2 / 3))) { + if (AMIGA.playfield.vpos + 1 < AMIGA.playfield.maxvpos + AMIGA.playfield.lof_store && (AMIGA.playfield.vpos == Math.floor(AMIGA.playfield.maxvpos_nom / 3) || AMIGA.playfield.vpos == Math.floor(AMIGA.playfield.maxvpos_nom * 2 / 3))) { vsyncmintime += vsynctimeperline; - var rpt = new Date().getTime(); - while (vsyncmintime - (rpt + vsynctimebase / 10) > 0 && vsyncmintime - rpt < vsynctimebase) { - this.sleep(1); - rpt = new Date().getTime(); + var rpt = read_processor_time(); + // sleep if more than 2ms "free" time + while (Math.floor(vsyncmintime) - Math.floor(rpt + vsynctimebase / 10) > 0 && Math.floor(vsyncmintime - rpt) < vsynctimebase) { + sleep(1); + rpt = read_processor_time(); + //console.log('*'); } } } } - + + this.fpscounter_reset = function() { + timeframes = 0; + fps_mavg.clr(); + idle_mavg.clr(); + lastframetime = read_processor_time(); + idletime = 0; + } + + this.fpscounter = function() { + var hz = AMIGA.playfield.vblank_hz; + + var now = read_processor_time(); + var last = now - lastframetime; + lastframetime = now; + + if (AMIGA.config.video.framerate > 1) { + last <<= 1; + hz /= 2; + } + + fps_mavg.set(last / 10); + idle_mavg.set(idletime / 10); + idletime = 0; + + frametime += last; + timeframes++; + + if ((timeframes & 7) == 0) { + var idle = 1000 - (idle_mavg.average == 0 ? 0.0 : idle_mavg.average * 1000.0 / vsynctimebase); + var fps = fps_mavg.average == 0 ? 0 : SYNCBASE * 10 / fps_mavg.average; + if (fps > 9999) fps = 9999; + if (idle < 0) idle = 0; + if (idle > 100 * 10) idle = 100 * 10; + if (hz * 10 > fps) idle *= (hz * 10 / fps); + + if ((timeframes & 15) == 0) { + AMIGA.config.hooks.fps(Math.round(fps * 0.1)); + AMIGA.config.hooks.cpu(Math.round(idle * 0.1)); + } + } + } + /*---------------------------------*/ - this.vSyncPre = function() { - if (counter.bogus > 0) - counter.bogus--; + this.hsync_handler_pre = function(onvsync) { + var hpos = this.hpos(); + AMIGA.copper.sync_copper_with_cpu(AMIGA.playfield.maxhpos, 0); + AMIGA.playfield.hsync_handler_pre(); + AMIGA.disk.hsync(); + if (AMIGA.config.audio.enabled) + AMIGA.audio.hsync(); + //AMIGA.cia.hsync_prehandler(); //empty + //hsync_counter++; + AMIGA.playfield.hsync_handler_pre_next_vpos(onvsync); - AMIGA.cia.vSyncPre(); + this.eventtab[EV_HSYNC].evtime = this.currcycle + AMIGA.playfield.maxhpos * CYCLE_UNIT; + this.eventtab[EV_HSYNC].oldcycles = this.currcycle; + } + + this.vsync_handler_pre = function() { + //AMIGA.audio.vsync(); //empty + AMIGA.cia.vsync_prehandler(); if (!vsync_rendered) { - var start = new Date().getTime(); - if (AMIGA.config.video.enabled) { - AMIGA.playfield.vSync(); - if (AMIGA.config.video.skip) this.testFrameSkip(); - } - frameskiptime += new Date().getTime() - start; + var start = read_processor_time(); + AMIGA.playfield.vsync_handle_redraw(); + frameskiptime += read_processor_time() - start; + vsync_rendered = true; } - this.framewait(); + if (!frame_rendered) + frame_rendered = AMIGA.playfield.render_screen(false); + if (frame_rendered && !frame_shown) + frame_shown = AMIGA.playfield.show_screen(); + this.fpscounter(); - vsync_rendered = false; + frame_shown = false; + frame_rendered = false; + + AMIGA.playfield.checklacecount(null); } - this.vSyncPost = function() { - AMIGA.disk.vsync(); + var cia_hsync = 256; + this.hsync_handler_post = function(onvsync) { + AMIGA.copper.last_copper_hpos = 0; + + var ciasyncs = !(AMIGA.playfield.bplcon0 & 2) || ((AMIGA.playfield.bplcon0 & 2) && AMIGA.config.chipset.genlock); + AMIGA.cia.hsync_posthandler(ciasyncs); + if (AMIGA.config.cia.tod > 0) { + cia_hsync -= 256; + if (cia_hsync <= 0) { + AMIGA.cia.vsync_posthandler(1); + cia_hsync += Math.floor((MAXVPOS_PAL * MAXHPOS_PAL * 50 * 256) / (AMIGA.playfield.maxhpos * (AMIGA.config.cia.tod == 2 ? 60 : 50))); + } + } else if (AMIGA.config.cia.tod == 0 && onvsync) + AMIGA.cia.vsync_posthandler(ciasyncs); - if (AMIGA.playfield.bplcon0 & 4) - this.lofStore = this.lofStore ? 0 : 1; - this.lof = this.lofStore; - - //if ((this.beamcon0 & (0x20|0x80)) != (this.new_beamcon0 & (0x20|0x80)) || this.hack_vpos) - //if ((this.beamcon0 & (0x20|0x80)) != (this.new_beamcon0 & (0x20|0x80)) || (abs (vpos_count - vpos_count_prev) > 1)) this.initHz(); - //if (this.lofChanged) this.compute_vsynctime(); - - this.lofChanged = false; - - AMIGA.copper.COPJMP(1, 1); - - if (!AMIGA.playfield.state.ilace || (AMIGA.playfield.state.ilace && this.lof == 1)) - AMIGA.state = CMD_IDLE; - } - - this.hSyncPre = function(isvsync) { - AMIGA.copper.sync_copper_with_cpu(this.maxhpos, 0); - - if (AMIGA.config.video.enabled) - AMIGA.playfield.hSync(); - - AMIGA.disk.hsync(); - - if (AMIGA.config.audio.enabled) - AMIGA.audio.hsync(); - - //AMIGA.cia.hSyncPre(); //empty - - if (AMIGA.config.video.ntsc) { - this.lol ^= 1; - this.maxhpos = 227 + this.lol; - } else { - this.lol = 0; - this.maxhpos = 227; - } - this.vpos++; - if (isvsync) - this.vpos = 0; - - AMIGA.playfield.sprites.clear(); - - this.eventtab[EV_HSYNC].oldcycles = this.currcycle; - this.eventtab[EV_HSYNC].evtime = this.maxhpos * CYCLE_UNIT + this.currcycle; - } - - this.hSyncPost = function(isvsync) { - AMIGA.cia.hSyncPost(1); - if (isvsync) - AMIGA.cia.vSyncPost(1); - + AMIGA.playfield.hsync_handler_post(); AMIGA.custom.last_value = 0xffff; - //if (!AMIGA.config.blitter.exact && AMIGA.blitter.getState() != BLT_done && AMIGA.dmaen(DMAF_BPLEN))// && diwstate == DIW_waiting_stop) AMIGA.blitter.slowdown(); - - if (isvsync) { - this.vpos = 0; - this.vSyncPost(); - } - - if (AMIGA.config.chipset.agnus == AGNUS_8361) { - if (this.vpos == 1) - AMIGA.send_interrupt(5, 1 * CYCLE_UNIT); - } else { - if (this.vpos == 0) - AMIGA.send_interrupt(5, 1 * CYCLE_UNIT); - } + if (!AMIGA.config.blitter.immediate && AMIGA.blitter.getState() != BLT_done && AMIGA.dmaen(DMAF_BPLEN) && AMIGA.playfield.getDiwstate() == DIW_WAITING_STOP) + AMIGA.blitter.slowdown(); - this.dmal_hsync(); - - AMIGA.copper.reset2(); - //AMIGA.copper.check(2); - - this.framewait2(); - - AMIGA.playfield.sprites.cycle(0); - - if (this.vpos + 1 == this.maxvpos + this.lof_store && AMIGA.config.cpu.speed == SAEV_Config_CPU_Speed_Maximum && !vsync_rendered) { - var start = new Date().getTime(); - if (AMIGA.config.video.enabled) { - AMIGA.playfield.vSync(); - if (AMIGA.config.video.skip) this.testFrameSkip(); - } - frameskiptime += new Date().getTime() - start; - vsync_rendered = true; - } - } - - this.hSync = function() { - var cvp = this.vpos + 1; - var mvp = this.maxvpos + this.lofStore; - var vsync = cvp == mvp || cvp == mvp + 1; - - this.hSyncPre(vsync); - if (vsync) - this.vSyncPre(); - - this.hSyncPost(vsync); - } - - /*---------------------------------*/ - - this.GETVPOS = function() { - return ((AMIGA.playfield.bplcon0 & 2) ? this.vpos_previous : this.vpos); - } - this.GETHPOS = function() { - return ((AMIGA.playfield.bplcon0 & 2) ? this.hpos_previous : this.hpos()); - } - - this.VPOSR = function() { - var chipset = 0; - - switch (AMIGA.config.chipset.agnus) { - case AGNUS_8367: - case AGNUS_8371: - chipset = 0; - break; - case AGNUS_8361: - case AGNUS_8370: - chipset = 10; - break; - case AGNUS_8372: { - if (AMIGA.config.chipset.agnus_rev <= 4) - chipset = AMIGA.config.video.ntsc ? 30 : 20; - else - chipset = AMIGA.config.video.ntsc ? 31 : 21; - break; - } - /*AGA - case AGNUS_8374: { - if (AMIGA.config.chipset.agnus_rev <= 2) - chipset = AMIGA.config.video.ntsc ? 32 : 22; - else - chipset = AMIGA.config.video.ntsc ? 33 : 23; - break; + if (onvsync) { + // vpos_count >= MAXVPOS just to not crash if VPOSW writes prevent vsync completely + /*if ((AMIGA.playfield.bplcon0 & 8) && !lightpen_triggered) { + vpos_lpen = AMIGA.playfield.vpos - 1; + hpos_lpen = AMIGA.playfield.maxhpos; + lightpen_triggered = 1; }*/ - } - var vp = this.GETVPOS(); - var hp = this.GETHPOS(); - - if (hp + 3 >= this.maxhpos) { - vp++; - if (vp >= this.maxvpos + this.lofStore) - vp = 0; + AMIGA.playfield.vpos = 0; + this.vsync_handler_post(); + AMIGA.playfield.vpos_count = 0; } - vp = (vp >> 8) & 7; - vp &= 1; - - //vp = (vp >> 8) & 1; - - var vpos = (this.lofStore << 15) | (chipset << 8) | (this.lol << 7) | vp; - - //BUG.info('Custom.VPOSR() vp %d, hp %d, vpos $%04x', this.vpos, this.hpos(), vpos); - return vpos; - } - - this.VPOSW = function (v) { - //BUG.info('Custom.VPOSW() $%04x', v); - - if (this.lofStore != ((v & 0x8000) ? 1 : 0)) { - this.lofChanged = true; - this.lofStore = (v & 0x8000) ? 1 : 0; + if (AMIGA.config.chipset.agnus_dip) { + if (AMIGA.playfield.vpos == 1) + AMIGA.INTREQ_0(INT_VERTB); + } else { + if (AMIGA.playfield.vpos == 0) + AMIGA.INTREQ_0(INT_VERTB); } - if (AMIGA.config.video.ntsc) - this.lol = (v & 0x0080) ? 1 : 0; + this.dmal_hsync(); + this.framewait2(); + AMIGA.playfield.hsync_handler_post_nextline_how(); + AMIGA.copper.reset2(); - if (this.lofChanged) - return; - - this.vpos &= 0x00ff; - this.vpos |= ((v & 1) << 8); + if (CUSTOM_SIMPLE) + AMIGA.playfield.do_sprites(0); + + //AMIGA.copper.check(2); + AMIGA.playfield.hsync_handler_post_diw_change(); } - - this.VHPOSW = function (v) { - //BUG.info('Custom.VHPOSW() $%04x', v); - - this.vpos &= 0xff00; - this.vpos |= (v >> 8); - } - - this.VHPOSR = function() { - var vp = this.GETVPOS(); - var hp = this.GETHPOS(); - - if (hp >= this.maxhpos) { - //console.log(hp); - hp -= this.maxhpos; - vp++; - if (vp >= this.maxvpos + this.lofStore) - vp = 0; - } - hp += 1; - if (hp >= this.maxhpos) - hp -= this.maxhpos; - - var vhpos = ((vp & 0xff) << 8) | ((hp >> 1) & 0xff); - - //BUG.info('Custom.VHPOSR() vp %d, hp %d, vhpos $%04x', vp, hp, vhpos); - return vhpos; - } - this.BEAMCON0 = function (v) { - BUG.info('BEAMCON0() $%04x', v); + this.vsync_handler_post = function() { + //if ((AMIGA.intreq & 0x0020) && (AMIGA.intena & 0x0020)) BUG.info('vblank interrupt not cleared'); + AMIGA.disk.vsync(); + AMIGA.playfield.vsync_handler_post(); } + + this.hsync_handler = function() { + var vs = AMIGA.playfield.is_custom_vsync(); + this.hsync_handler_pre(vs); + if (vs) { + this.vsync_handler_pre(); + + if (AMIGA.config.video.framerate > 1) { + if (AMIGA.playfield.framecnt == AMIGA.config.video.framerate - 1) { + //vsyncresume = true; + //throw new VSync(0, 'vsync'); + AMIGA.state = ST_IDLE; + } + } else { + //vsyncresume = true; + //throw new VSync(0, 'vsync'); + AMIGA.state = ST_IDLE; + } + } + this.hsync_handler_post(vs); + } } diff --git a/sae/input.js b/sae/input.js index 43c38c2..9035c55 100644 --- a/sae/input.js +++ b/sae/input.js @@ -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(); diff --git a/sae/memory.js b/sae/memory.js index 6afc7fb..343b325 100644 --- a/sae/memory.js +++ b/sae/memory.js @@ -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]; - } - }*/ + }*/ + } } \ No newline at end of file diff --git a/sae/playfield.js b/sae/playfield.js index 223c010..c826ee3 100644 --- a/sae/playfield.js +++ b/sae/playfield.js @@ -6,214 +6,2927 @@ * ©2012 Rupert Hausberger * Commercial use is prohibited. * +*************************************************************************** +* Notes: +* - Portet from WinUAE 2.5.0 +* - AGA support is commented out. +* **************************************************************************/ -function Sprite(num) { - this.num = num; - this.pt = 0; - this.pos = 0; - this.ctl = 0; - this.data = 0; - this.datb = 0; +function Playfield() { + function decision() { + this.plfleft = 0; + this.plfright = 0; + this.plflinelen = 0; + this.diwfirstword = 0; + this.diwlastword = 0; + this.ctable = 0; + this.bplcon0 = 0; + this.bplcon2 = 0; + this.bplcon3 = 0; +/*#ifdef AGA + this.bplcon4 = 0; +#endif*/ + this.nr_planes = 0; + this.bplres = 0; + this.ehb_seen = false; + this.ham_seen = false; + this.ham_at_start = false; - this.xpos = 0; - this.vstart = 0; - this.vstop = 0; - this.armed = false; - this.dmastate = 0; - this.dmacycle = 0; -} + this.clr = function() { + this.plfleft = 0; + this.plfright = 0; + this.plflinelen = 0; + this.diwfirstword = 0; + this.diwlastword = 0; + this.ctable = 0; + this.bplcon0 = 0; + this.bplcon2 = 0; + this.bplcon3 = 0; +/*#ifdef AGA + this.bplcon4 = 0; +#endif*/ + this.nr_planes = 0; + this.bplres = 0; + this.ehb_seen = false; + this.ham_seen = false; + this.ham_at_start = false; + } -function Sprites() { - const MAX_SPRITES = 8; + this.set = function(src) { + this.plfleft = src.plfleft; + this.plfright = src.plfright; + this.plflinelen = src.plflinelen; + this.diwfirstword = src.diwfirstword; + this.diwlastword = src.diwlastword; + this.ctable = src.ctable; + this.bplcon0 = src.bplcon0; + this.bplcon2 = src.bplcon2; + this.bplcon3 = src.bplcon3; +/*#ifdef AGA + this.bplcon4 = src.bplcon4; +#endif*/ + this.nr_planes = src.nr_planes; + this.bplres = src.bplres; + this.ehb_seen = src.ehb_seen; + this.ham_seen = src.ham_seen; + this.ham_at_start = src.ham_at_start; + } + } + + function color_entry() { + this.color_regs_ecs = new Uint16Array(32); +//#ifndef AGA + this.acolors = new Uint32Array(32); +/*#else + this.acolors = new Uint32Array(256); + this.color_regs_aga = new Uint32Array(256); +#endif*/ + this.borderblank = false; + } - this.sprite = new Array(MAX_SPRITES); + function color_change() { + this.linepos = 0; + this.regno = 0; + this.value = 0; + + this.set = function(v) { + this.linepos = v.linepos; + this.regno = v.regno; + this.value = v.value; + } + this.cmp = function(v) { + return (this.linepos == v.linepos && this.regno == v.regno && this.value == v.value ? 0 : 1); + } + } + + function draw_info() { + this.first_sprite_entry = 0; + this.last_sprite_entry = 0; + this.first_color_change = 0; + this.last_color_change = 0; + this.nr_color_changes = 0; + this.nr_sprites = 0; + } + + function vidbuffer() { + this.rowbytes = 0; /* Bytes per row in the memory pointed at by bufmem. */ + this.pixbytes = 0; /* Bytes per pixel. */ + /* size of this buffer */ + this.width_allocated = 0; + this.height_allocated = 0; + /* size of max visible image */ + this.outwidth = 0; + this.outheight = 0; + /* nominal size of image for centering */ + this.inwidth = 0; + this.inheight = 0; + /* same but doublescan multiplier included */ + this.inwidth2 = 0; + this.inheight2 = 0; + /* extra width, chipset hpos extra in right border */ + this.extrawidth = 0; + + this.xoffset = 0; /* superhires pixels from left edge */ + this.yoffset = 0; /* lines from top edge */ + this.inxoffset = 0; /* positive if sync positioning */ + this.inyoffset = 0; + } + + /*---------------------------------*/ + /* drawing */ + + const dblpfofs = [0, 2, 4, 8, 16, 32, 64, 128]; + + var dblpf_ms1 = new Uint8Array(256); + var dblpf_ms2 = new Uint8Array(256); + var dblpf_ms = new Uint8Array(256); + var dblpf_ind1 = new Uint8Array(256); + var dblpf_ind2 = new Uint8Array(256); + var dblpf_2nd1 = new Uint8Array(256); + var dblpf_2nd2 = new Uint8Array(256); + + var linestate = new Uint8Array((MAXVPOS + 2) * 2 + 1); //[(MAXVPOS + 2) * 2 + 1]; + for (var i = 0; i < linestate.length; i++) + linestate[i] = 0; + + var line_data = []; //[(MAXVPOS + 2) * 2][MAX_PLANES * MAX_WORDS_PER_LINE * 2]; + for (var i = 0; i < (MAXVPOS + 2) * 2; i++) { + line_data[i] = []; + for (var j = 0; j < MAX_PLANES; j++) { + line_data[i][j] = new Uint32Array(MAX_WORDS_PER_LINE * 2); + for (var k = 0; k < MAX_WORDS_PER_LINE * 2; k++) + line_data[i][j][k] = 0; + } + } + + var line_decisions = []; + for (var i = 0; i < 2 * (MAXVPOS + 2) + 1; i++) + line_decisions[i] = new decision(); + var color_tables = []; + for (var i = 0; i < 2; i++) { + color_tables[i] = []; + for (var j = 0; j < COLOR_TABLE_SIZE; j++) + color_tables[i][j] = new color_entry(); + } + var color_changes = []; + for (var i = 0; i < 2; i++) { + color_changes[i] = []; + for (var j = 0; j < MAX_REG_CHANGE; j++) + color_changes[i][j] = new color_change(); + } + var line_drawinfo = []; + for (var i = 0; i < 2; i++) { + line_drawinfo[i] = []; + for (var j = 0; j < 2 * (MAXVPOS + 2) + 1; j++) + line_drawinfo[i][j] = new draw_info(); + } + + var gfxvidinfo = { + maxblocklines:0, + drawbuffer: new vidbuffer(), + gfx_resolution_reserved: 0, // reserved space for currprefs.hresolution + gfx_vresolution_reserved: 0, // reserved space for currprefs.hresolution + xchange: 0, /* how many superhires pixels in one pixel in buffer */ + ychange: 0, /* how many interlaced lines in one line in buffer */ + }; + + var xlinebuffer = new Uint32Array(MAX_PIXELS_PER_LINE); + for (var i = 0; i < xlinebuffer.length; i++) xlinebuffer[i] = 0; + + var ham_linebuf = new Uint32Array(MAX_PIXELS_PER_LINE << 1); + for (var i = 0; i < ham_linebuf.length; i++) ham_linebuf[i] = 0; + + var apixels = new Uint8Array(MAX_PIXELS_PER_LINE << 1); + for (var i = 0; i < apixels.length; i++) apixels[i] = 0; + + var colors_for_drawing = new color_entry(); + var current_colors = new color_entry(); + + var xcolors = new Uint32Array(4096); + for (var i = 0; i < xcolors.length; i++) xcolors[i] = 0; + + var thisline_decision = new decision(); + var thisline_changed = 0; + + var amiga2aspect_line_map = null; + var native2amiga_line_map = null; + + var curr_sprite_entries = null; + var prev_sprite_entries = null; + var curr_color_changes = null; + var prev_color_changes = null; + var curr_drawinfo = null; + var prev_drawinfo = null; + var curr_color_tables = null; + var prev_color_tables = null; + var current_change_set = 0; + + var autoscale_bordercolors = 0; + var frame_redraw_necessary = 0; + + var first_drawn_line = 0; + var last_drawn_line = 0; + var first_block_line = 0; + var last_block_line = 0; + var thisframe_first_drawn_line = 0; + var thisframe_last_drawn_line = 0; + + var drawing_color_matches = -1; + var linedbl = 0, linedbld = 0; + var min_diwstart = 0; + var max_diwstop = 0; + var min_ypos_for_screen = 0; + var max_ypos_thisframe = 0; + + var visible_left_border = 0; + var visible_right_border = 0; + var visible_left_start = 0; + var visible_right_stop = MAX_STOP; + var visible_top_start = 0; + var visible_bottom_stop = MAX_STOP; + var thisframe_y_adjust = 0; + var thisframe_y_adjust_real = 0; + var max_drawn_amiga_line = 0; + var linetoscr_x_adjust_bytes = 0; + var last_max_ypos = 0; + var extra_y_adjust = 0; + var center_reset = true; + this.framecnt = 0; + var last_redraw_point = 0; + var lores_shift = 0; + + var dp_for_drawing = null; + var dip_for_drawing = null; + var hposblank = 0; + var bplxor = 0; + + var playfield_start = 0, playfield_end = 0; + var real_playfield_start = 0, real_playfield_end = 0; + var linetoscr_diw_start = 0, linetoscr_diw_end = 0; + var native_ddf_left = 0, native_ddf_right = 0; + + var unpainted = 0; /* How many pixels in window coordinates which are to the left of the left border. */ + var pixels_offset = 0; + var src_pixel = 0, ham_src_pixel = 0; + var ham_decode_pixel = 0; + var ham_lastcolor = 0; + + var next_color_change = 0; + var next_color_entry = 0; + var remembered_color_entry = -1; + var color_src_match = -1; + var color_dest_match = -1; + var color_compare_result = 0; + + var res_shift = 0; + var bplres = 0; + var bplplanecnt = 0; + var bplham = false; + var bplehb = false; + var issprites = 0; + var ecsshres = false; + var plf1pri = 0; + var plf2pri = 0; + var plf_sprite_mask = 0; + var bpldualpf = false; + var bpldualpfpri = false; + + /*---------------------------------*/ + /* sprites */ + + function sprite() { + this.pt = 0; + this.xpos = 0; + this.vstart = 0; + this.vstop = 0; + this.dblscan = 0; /* AGA SSCAN2 */ + this.armed = 0; + this.dmastate = 0; + this.dmacycle = 0; + this.ptxhpos = 0; + + this.clr = function() { + this.pt = 0; + this.xpos = 0; + this.vstart = 0; + this.vstop = 0; + this.dblscan = 0; + this.armed = 0; + this.dmastate = 0; + this.dmacycle = 0; + this.ptxhpos = 0; + } + } + + function sprite_entry() { + this.pos = 0; + this.max = 0; + this.first_pixel = 0; + this.has_attached = false; + } + + function spritepixelsbuf() { + this.attach = 0; + this.stdata = 0; + this.data = 0; + + this.clr = function() { + this.attach = 0; + this.stdata = 0; + this.data = 0; + } + } + + var sprinit = false; + var sprtaba = new Uint32Array(256); + var sprtabb = new Uint32Array(256); + var sprite_ab_merge = new Uint32Array(256); + var sprclx = new Uint32Array(16); + var clxmask = new Uint32Array(16); + + var sprite_offs = new Uint8Array(256); + var clxtab = new Uint32Array(256); + + var spr = []; for (var i = 0; i < MAX_SPRITES; i++) - this.sprite[i] = new Sprite(i); + spr[i] = new sprite(); + + /*union sps_union { + uae_u8 bytes[MAX_SPR_PIXELS * 2]; + uae_u32 words[MAX_SPR_PIXELS * 2 / 4]; + };*/ + var spixstate = new Uint8Array(MAX_SPR_PIXELS << 1); + var spixels = new Uint16Array(MAX_SPR_PIXELS << 1); + for (var i = 0; i < MAX_SPR_PIXELS << 1; i++) + spixstate[i] = spixels[i] = 0; + + var sprite_entries = []; //[2][MAX_SPR_PIXELS / 16]; + for (var i = 0; i < 2; i++) { + sprite_entries[i] = []; + for (var j = 0; j < MAX_SPR_PIXELS >> 4; j++) + sprite_entries[i][j] = new sprite_entry(); + } - var spr_data = []; - var spr_state = []; - var spr_attach = []; + var spritepixels = []; + for (var i = 0; i < MAX_PIXELS_PER_LINE; i++) + spritepixels[i] = new spritepixelsbuf(); - var dblpf_ms = null; - var dblpf_ms1 = null; - var dblpf_ms2 = null; - var sprite_offs = null; + var sprctl = new Uint16Array(MAX_SPRITES); + var sprpos = new Uint16Array(MAX_SPRITES); + for (var i = 0; i < MAX_SPRITES; i++) + sprctl[i] = sprpos[i] = 0; - var sprtabb = null; - var sprtaba = null; - var sprite_ab_merge = null; - var sprclx = null; - var clxmask = null; +/*#ifdef AGA + //[MAX_SPRITES][4] + var sprdata = []; + var sprdatb = []; + for (var i = 0; i < MAX_SPRITES; i++) { + sprdata[i] = new Uint16Array(4); + sprdatb[i] = new Uint16Array(4); + for (var j = 0; j < 4; j++) { + sprdata[i][j] = 0; + sprdatb[i][j] = 0; + } + } +#else*/ + //[MAX_SPRITES][1] + var sprdata = []; + var sprdatb = []; + for (var i = 0; i < MAX_SPRITES; i++) { + sprdata[i] = new Uint16Array(1); + sprdatb[i] = new Uint16Array(1); + sprdata[i][0] = 0; + sprdatb[i][0] = 0; + } +//#endif - this.nr_armed = 0; - var sprite_vblank_endline = 0; - var sprite_mask = 0; - //var sprite_minx, sprite_maxx; - - this.clxdat = 0; - this.clxcon = 0; + var clxcon = 0; var clxcon_bpl_enable = 0; var clxcon_bpl_match = 0; + var clxcon2 = 0; + var clxdat = 0; - this.init_sprite_tables = function() { - //spr_data = new Array(800); - //spr_state = new Array(800); - //spr_attach = new Array(800); + var sprres = 0; + var nr_armed = 0; - dblpf_ms = new Array(256); - dblpf_ms1 = new Array(256); - dblpf_ms2 = new Array(256); - sprite_offs = new Array(256); + var sprite_buffer_res = 0; + var sprite_vblank_endline = VBLANK_SPRITE_PAL; + var sprite_minx = 0; + var sprite_maxx = 0; + var sprite_width = 0; + var sprite_first_x = 0; + var sprite_last_x = 0; + + var sprite_0 = 0; + var sprite_0_width = 0; + var sprite_0_height = 0; + var sprite_0_doubled = 0; + var sprite_0_colors = [0,0,0,0]; - sprtaba = new Array(256); - sprtabb = new Array(256); - sprite_ab_merge = new Array(256); + var next_sprite_entry = 0; + var next_sprite_forced = 1; + var prev_next_sprite_entry = 0; + var last_sprite_point = 0; + //var magic_sprite_mask = 0xff; + /*---------------------------------*/ + /* playfield */ + + var bplcon0 = 0; + var bplcon1 = 0; + var bplcon2 = 0; + var bplcon3 = 0; + var bplcon4 = 0; + + var bpl1mod = 0; + var bpl2mod = 0; + + var bplxdat = [0,0,0,0,0,0,0,0]; + var bplpt = [0,0,0,0,0,0,0,0]; + var bplptx = [0,0,0,0,0,0,0,0]; + + var diwstrt = 0; + var diwstop = 0; + var ddfstrt = 0; + var ddfstrt_old_hpos = -1; + var ddfstop = 0; + var ddf_change = 0; + var diwhigh = 0; + var diwhigh_written = false; + + var hdiwstate = 0; + + var beamcon0 = 0; + var new_beamcon0 = 0; + + this.vpos = 0; + this.vpos_count = 0; + this.vpos_count_diff = 0; + this.hpos = function() { + return Math.floor((AMIGA.events.currcycle - AMIGA.events.eventtab[EV_HSYNC].oldcycles) * CYCLE_UNIT_INV); + } + var vpos_previous = 0; + var hpos_previous = 0; + + this.maxvpos = MAXVPOS; + this.maxvpos_nom = MAXVPOS; + this.maxvpos_total = MAXVPOS; + this.maxhpos = MAXHPOS; + this.maxhpos_short = MAXHPOS; + + this.lof_store = 0; + this.lof_current = 0; + this.lof_previous = 0; + this.lof_changed = 0; + this.lof_changing = 0; + this.lol = 0; + + this.vblank_hz = 0; + + var aga_mode = 0; + var direct_rgb = 0; + + var prevbpl = []; //[2][MAXVPOS][8]; + for (var i = 0; i < 2; i++) { + prevbpl[i] = []; + for (var j = 0; j < MAXVPOS; j++) { + prevbpl[i][j] = new Uint32Array(8); + for (var k = 0; k < 8; k++) { + prevbpl[i][j][k] = 0; + } + } + } + + var scandoubled_line = 0; + var doublescan = 0; + var interlace_seen = 0; + var interlace_changed = 0; + var lof_togglecnt_nlace = 0; + var lof_togglecnt_lace = 0; + var nlace_cnt = 0; + + var minfirstline = 0; + var equ_vblank_endline = 0; + var equ_vblank_toggle = false; + + this.vtotal = MAXVPOS_PAL, this.htotal = MAXHPOS_PAL; + this.hsstop = 0, this.hbstrt = 0, this.hbstop = 0; + this.vsstop = 0, this.vbstrt = 0, this.vbstop = 0; + this.hsstrt = 0, this.vsstrt = 0, this.hcenter = 0; + var hsyncstartpos = 0; + var hsyncendpos = 0; + + var diwstate = 0; + var ddfstate = 0; + var diw_change = 2; + var diw_hstrt = 0; + var diw_hstop = 0; + var diw_hcounter = 0; + var last_hdiw = 0; + + var diwfirstword = 0; + var diwlastword = 0; + var plffirstline = 0; + var plflastline = 0; + + var plfstrt = 0; + var plfstrt_sprite = 0; + var plfstrt_start = 0; + var plfstop = 0; + + var plf_state = 0; + + var nextline_how = 0; + var next_lineno = 0; + var prev_lineno = -1; + + var first_bpl_vpos = 0; + var first_planes_vpos = 0; + var last_planes_vpos = 0; + var firstword_bplcon1 = 0; + var diwfirstword_total = 0; + var diwlastword_total = 0; + var ddffirstword_total = 0; + var ddflastword_total = 0; + var plffirstline_total = 0; + var plflastline_total = 0; + + /*var lightpen_active = 0; + var lightpen_triggered = 0; + var lightpen_cx = 0; + var lightpen_cy = 0; + var lightpen_y1 = -1; + var lightpen_y2 = -1; + var vpos_lpen = 0; + var hpos_lpen = 0;*/ + + var bplcon0_d = 0; + var bplcon0_dd = 0; + var bplcon1_hpos = 0; + var bplcon1t = 0; + var bplcon1t2 = 0; + + var badmode = 0; + var bplcon0_res = 0; + var bplcon0_planes = 0; + var bplcon0_planes_limit = 0; + + var fmode = 0; + var fetchmode = 0; + var fetchunit = 0; + var fetchunit_mask = 0; + const fetchunits = [ 8,8,8,0, 16,8,8,0, 32,16,8,0 ]; + var fetchstart = 0; + var fetchstart_shift = 0; + var fetchstart_mask = 0; + const fetchstarts = [ 3,2,1,0, 4,3,2,0, 5,4,3,0 ]; + var fm_maxplane = 0; + var fm_maxplane_shift = 0; + const fm_maxplanes = [ 3,2,1,0, 3,3,2,0, 3,3,3,0 ]; + var real_bitplane_number = []; //[3][3][9]; + + var fetch_state = 0; + var fetch_cycle = 0; + var fetch_modulo_cycle = 0; + + const cycle_sequences = [[2,1,2,1,2,1,2,1], [4,2,3,1,4,2,3,1], [8,4,6,2,7,3,5,1]]; + var cycle_diagram_shift = 0; + var cycle_diagram_table = null; //[3][3][9][32]; + var cycle_diagram_free_cycles = []; //[3][3][9]; + var cycle_diagram_total_cycles = []; //[3][3][9]; + var curr_diagram = []; + + var estimated_last_fetch_cycle = 0; + + var bpldmasetuphpos = -1; + var bpldmasetupphase = 0; + + var bpl1dat_written = false; + var bpl1dat_written_at_least_once = false; + var bpl1dat_early = false; + var plfleft_real = -1; + + var out_nbits = 0; + var out_offs = 0; + var outword = new Uint32Array(MAX_PLANES); + var todisplay = []; //[MAX_PLANES][4]; + for (var i = 0; i < MAX_PLANES; i++) { + todisplay[i] = new Uint32Array(4); + for (var j = 0; j < 4; j++) + todisplay[i][j] = 0; + } + var fetched = new Uint32Array(MAX_PLANES); + for (var i = 0; i < MAX_PLANES; i++) + fetched[i] = 0; +/*#ifdef AGA + var fetched_aga0 = new Uint32Array(MAX_PLANES); + var fetched_aga1 = new Uint32Array(MAX_PLANES); +#endif*/ + + var toscr_res = 0; + var toscr_nr_planes = 0; + var toscr_nr_planes2 = 0; + var toscr_delay1 = 0; + var toscr_delay2 = 0; + var toscr_nbits = 0; + + //var fetchwidth = 0; + var delayoffset = 0; + + var last_decide_line_hpos = -1; + var last_ddf_pix_hpos = -1; + var last_sprite_hpos = -1; + var last_fetch_hpos = -1; + + /*-----------------------------------------------------------------------*/ + /* common */ + /*-----------------------------------------------------------------------*/ + + function RES_SHIFT(res) { + return res == RES_LORES ? 8 : (res == RES_HIRES ? 4 : 2); + } + function GET_RES_DENISE(con0) { + if (!(AMIGA.config.chipset.mask & CSMASK_ECS_DENISE)) con0 &= ~0x40; // SUPERHIRES + return (con0 & 0x8000) ? RES_HIRES : ((con0 & 0x40) ? RES_SUPERHIRES : RES_LORES); + } + function GET_RES_AGNUS(con0) { + if (!(AMIGA.config.chipset.mask & CSMASK_ECS_AGNUS)) con0 &= ~0x40; // SUPERHIRES + return (con0 & 0x8000) ? RES_HIRES : ((con0 & 0x40) ? RES_SUPERHIRES : RES_LORES); + } + function GET_SPRITEWIDTH(fmode) { + return (((fmode >> 2) & 3) == 3 ? 64 : ((fmode >> 2) & 3) == 0 ? 16 : 32); + } + function GET_PLANES(con0) { + if ((con0 & 0x0010) && (con0 & 0x7000)) return 0; // >8 planes = 0 planes + if (con0 & 0x0010) return 8; // AGA 8-planes bit + return (con0 >> 12) & 7; // normal planes bits + } + function GET_PLANES_LIMIT(con0) { + var res = GET_RES_AGNUS(con0); + var planes = GET_PLANES(con0); + return real_bitplane_number[fetchmode][res][planes]; + } + + this.nodraw = function() { + return this.framecnt != 0; + } + + this.doflickerfix = function() { + return AMIGA.config.video.vresolution && doublescan < 0 && this.vpos < MAXVPOS; + } + + this.current_maxvpos = function() { + return this.maxvpos + (this.lof_store ? 1 : 0); + } + + this.is_custom_vsync = function() { + var vp = this.vpos + 1; + var vpc = this.vpos_count + 1; + /* Agnus vpos counter keeps counting until it wraps around if VPOSW writes put it past maxvpos */ + if (vp >= this.maxvpos_total) + vp = 0; + if (vp == this.maxvpos + this.lof_store || vp == this.maxvpos + this.lof_store + 1 || vpc >= MAXVPOS) { + // vpos_count >= MAXVPOS just to not crash if VPOSW writes prevent vsync completely + return true; + } + return false; + } + + this.is_linetoggle = function() { + if (!(beamcon0 & 0x0800) && !(beamcon0 & 0x0020) && (AMIGA.config.chipset.mask & CSMASK_ECS_AGNUS)) + return true; //NTSC and !LOLDIS -> LOL toggles every line + else if (!(AMIGA.config.chipset.mask & CSMASK_ECS_AGNUS) && AMIGA.config.video.ntsc) + return true; //hardwired NTSC Agnus + return false; + } + + this.is_last_line = function() { + return this.vpos + 1 == this.maxvpos + this.lof_store; + } + + /*-----------------------------------------------------------------------*/ + /* drawing */ + /*-----------------------------------------------------------------------*/ + + function setup_drawing_tables() { for (var i = 0; i < 256; i++) { var plane1 = ((i >> 0) & 1) | ((i >> 1) & 2) | ((i >> 2) & 4) | ((i >> 3) & 8); var plane2 = ((i >> 1) & 1) | ((i >> 2) & 2) | ((i >> 3) & 4) | ((i >> 4) & 8); - dblpf_ms[i] = i == 0 ? 16 : 8; + dblpf_2nd1[i] = plane1 == 0 && plane2 != 0; + dblpf_2nd2[i] = plane2 != 0; + +/*#ifdef AGA + dblpf_ind1_aga[i] = plane1 == 0 ? plane2 : plane1; + dblpf_ind2_aga[i] = plane2 == 0 ? plane1 : plane2; +#endif*/ dblpf_ms1[i] = plane1 == 0 ? (plane2 == 0 ? 16 : 8) : 0; dblpf_ms2[i] = plane2 == 0 ? (plane1 == 0 ? 16 : 0) : 8; + dblpf_ms[i] = i == 0 ? 16 : 8; - sprite_offs[i] = (i & 15) ? 0 : 2; - - sprtaba[i] = ((((i >> 7) & 1) << 0) | (((i >> 6) & 1) << 2) | (((i >> 5) & 1) << 4) | (((i >> 4) & 1) << 6) | (((i >> 3) & 1) << 8) | (((i >> 2) & 1) << 10) | (((i >> 1) & 1) << 12) | (((i >> 0) & 1) << 14)); - sprtabb[i] = sprtaba[i] << 1; - sprite_ab_merge[i] = (((i & 15) ? 1 : 0) | ((i & 240) ? 2 : 0)); - } - - sprclx = new Array(16); - clxmask = new Array(16); - - for (var i = 0; i < 16; i++) { - clxmask[i] = (((i & 1) ? 0xF : 0x3) | ((i & 2) ? 0xF0 : 0x30) | ((i & 4) ? 0xF00 : 0x300) | ((i & 8) ? 0xF000 : 0x3000)); - sprclx[i] = (((i & 0x3) == 0x3 ? 1 : 0) | ((i & 0x5) == 0x5 ? 2 : 0) | ((i & 0x9) == 0x9 ? 4 : 0) | ((i & 0x6) == 0x6 ? 8 : 0) | ((i & 0xA) == 0xA ? 16 : 0) | ((i & 0xC) == 0xC ? 32 : 0)) << 9; + if (plane2 > 0) + plane2 += 8; + dblpf_ind1[i] = i >= 128 ? i & 0x7F : (plane1 == 0 ? plane2 : plane1); + dblpf_ind2[i] = i >= 128 ? i & 0x7F : (plane2 == 0 ? plane1 : plane2); } } - this.setup = function() { - sprite_vblank_endline = AMIGA.config.video.ntsc ? 20 : 25; + this.recreate_aspect_maps = function() { + var i, h = gfxvidinfo.drawbuffer.height_allocated; + if (h == 0) + return; + + linedbld = linedbl = AMIGA.config.video.vresolution; + if (doublescan > 0 && interlace_seen <= 0) { + linedbl = 0; + linedbld = 1; + } - if (dblpf_ms == null) this.init_sprite_tables(); + if (native2amiga_line_map) native2amiga_line_map = null; + if (amiga2aspect_line_map) amiga2aspect_line_map = null; + + amiga2aspect_line_map = new Int32Array((MAXVPOS + 1) * 2 + 1); + native2amiga_line_map = new Int32Array(h); + + var maxl = (MAXVPOS + 1) << linedbld; + min_ypos_for_screen = minfirstline << linedbl; + max_drawn_amiga_line = -1; + for (i = 0; i < maxl; i++) { + var v = i - min_ypos_for_screen; + if (v >= h && max_drawn_amiga_line < 0) + max_drawn_amiga_line = i - min_ypos_for_screen; + if (i < min_ypos_for_screen || v >= h) + v = -1; + amiga2aspect_line_map[i] = v; + } + if (max_drawn_amiga_line < 0) + max_drawn_amiga_line = maxl - min_ypos_for_screen; + max_drawn_amiga_line >>>= linedbl; + + if (AMIGA.config.video.ycenter) { + extra_y_adjust = (h - (this.maxvpos_nom << linedbl)) >> 1; + if (extra_y_adjust < 0) + extra_y_adjust = 0; + } + + for (i = 0; i < h; i++) + native2amiga_line_map[i] = -1; + + for (i = maxl - 1; i >= min_ypos_for_screen; i--) { + if (amiga2aspect_line_map[i] == -1) + continue; + for (var j = amiga2aspect_line_map[i]; j < h && native2amiga_line_map[j] == -1; j++) + native2amiga_line_map[j] = i >> linedbl; + } + + gfxvidinfo.xchange = 1 << (RES_MAX - AMIGA.config.video.hresolution); + gfxvidinfo.ychange = linedbl ? 1 : 2; + + visible_left_start = 0; + visible_right_stop = MAX_STOP; + visible_top_start = 0; + visible_bottom_stop = MAX_STOP; + //console.log('recreate_aspect_maps', amiga2aspect_line_map, native2amiga_line_map); + } + + /*---------------------------------*/ + + function xlinecheck(id, start, end) { + var xstart = start * gfxvidinfo.drawbuffer.pixbytes; + var xend = end * gfxvidinfo.drawbuffer.pixbytes; + var end1 = gfxvidinfo.drawbuffer.rowbytes * gfxvidinfo.drawbuffer.height; + var min = Math.floor(linetoscr_x_adjust_bytes / gfxvidinfo.drawbuffer.pixbytes); + var ok = 1; + + if (xend > end1 || xstart >= end1) + ok = 0; + if ((xstart % gfxvidinfo.drawbuffer.rowbytes) >= gfxvidinfo.drawbuffer.width * gfxvidinfo.drawbuffer.pixbytes) + ok = 0; + if ((xend % gfxvidinfo.drawbuffer.rowbytes) >= gfxvidinfo.drawbuffer.width * gfxvidinfo.drawbuffer.pixbytes) + ok = 0; + if (xstart >= xend) + ok = 0; + if (xend - xstart > gfxvidinfo.drawbuffer.width * gfxvidinfo.drawbuffer.pixbytes) + ok = 0; + + if (!ok) { + console.log(id, start, end, min); + BUG.info('xlinecheck() ERROR %d-%d (%dx%dx%d %d)', + start - min, end - min, gfxvidinfo.drawbuffer.width, gfxvidinfo.drawbuffer.height, + gfxvidinfo.drawbuffer.pixbytes, gfxvidinfo.drawbuffer.rowbytes); + } + } + + /*---------------------------------*/ + + function max_diwlastword() { + return (0x1d4 - DISPLAY_LEFT_SHIFT + DIW_DDF_OFFSET - 1) << lores_shift; } - this.cleanup = function() {} - this.reset = function() {} - - this.clear = function() { - spr_data = []; - spr_state = []; - spr_attach = []; + function xshift(x, shift) { + return shift < 0 ? x >> (-shift) : x << shift; } - this.setMask = function (pf1p, pf2p) { - sprite_mask = 0xFFFF0000 << (4 * pf2p); - sprite_mask &= 0xFFFFFFFF; - sprite_mask |= (0x0000FFFF << (4 * pf1p)) & 0xFFFF; - sprite_mask &= 0xFFFFFFFF; + function coord_hw_to_window_x(x) { + return (x - DISPLAY_LEFT_SHIFT) << lores_shift; + } + function coord_window_to_hw_x(x) { + return (x >> lores_shift) + DISPLAY_LEFT_SHIFT; } - this.render = function (pos, apixel) { - if (!spr_data[pos]) return 0; + function coord_diw_to_window_x(x) { + return (x - DISPLAY_LEFT_SHIFT + DIW_DDF_OFFSET - 1) << lores_shift; + } + function coord_window_to_diw_x(x) { + return (x >> lores_shift) + DISPLAY_LEFT_SHIFT - DIW_DDF_OFFSET; + } + + function coord_native_to_amiga_x(x) { + return xshift(x + visible_left_border, 1 - lores_shift) + 2 * DISPLAY_LEFT_SHIFT - 2 * DIW_DDF_OFFSET; + } + function coord_native_to_amiga_y(y) { + return native2amiga_line_map[y] + thisframe_y_adjust - minfirstline; + } - var maskshift = AMIGA.playfield.state.dpf ? (AMIGA.playfield.state.pf2pri ? dblpf_ms2[apixel] : dblpf_ms1[apixel]) : dblpf_ms[apixel]; - var plfmask = (sprite_mask >>> maskshift) >>> maskshift; - var v = spr_data[pos] & ~plfmask; + function res_shift_from_window(x) { + return res_shift >= 0 ? x >> res_shift : x << -res_shift; + } + function res_shift_from_amiga(x) { + return res_shift >= 0 ? x >> res_shift : x << -res_shift; + } + + /*---------------------------------*/ + + this.render_screen = function(immediate) { + if (AMIGA.config.video.enabled) + AMIGA.video.render(); + return true; + } + this.show_screen = function() { + if (AMIGA.config.video.enabled) + AMIGA.video.show(); //flip + return true; + } + + /*function flush_line(vb, lineno) { + AMIGA.video.drawline(lineno, xlinebuffer, linetoscr_x_adjust_bytes >> 2); + } + function flush_block(vb, first_line, last_line) { + console.log('flush_block() called', first_line, last_line); + } + function flush_screen(vb, first_line, last_line) { + console.log('flush_screen() called', first_line, last_line); + } + this.do_flush_line = function(vb, lineno) { + if (lineno < first_drawn_line) + first_drawn_line = lineno; + if (lineno > last_drawn_line) + last_drawn_line = lineno; - if (v != 0) { - var v1 = v & 255; - var offs; - var col; - - if (v1 == 0) offs = sprite_offs[v >> 8] + 4; - else offs = sprite_offs[v1]; - - v = (v >> (offs << 1)) & 15; - //v ^= 8; /* debug */ - - if (spr_attach[pos] && (spr_state[pos] & (3 << offs))) { - col = 16 + v; - } else { - var vlo = v & 3; - var vhi = (v & (vlo - 1)) >> 2; - col = 16 + (vlo | vhi) + offs * 2; + if (gfxvidinfo.maxblocklines == 0) + flush_line(vb, lineno); + else { + if ((last_block_line + 2) < lineno) { + if (first_block_line != NO_BLOCK) + flush_block(vb, first_block_line, last_block_line); + first_block_line = lineno; + } + last_block_line = lineno; + if (last_block_line - first_block_line >= gfxvidinfo.maxblocklines) { + flush_block(vb, first_block_line, last_block_line); + first_block_line = last_block_line = NO_BLOCK; } - return col; } - return 0; + }*/ + + this.do_flush_line = function(vb, lineno) { + if (lineno < first_drawn_line) + first_drawn_line = lineno; + if (lineno > last_drawn_line) + last_drawn_line = lineno; + + AMIGA.video.drawline(lineno, xlinebuffer, linetoscr_x_adjust_bytes >> 2); } - this.spr_plf_collision = function() { - if (clxcon_bpl_enable == 0) { - this.clxdat |= 0x1fe; + /*this.do_flush_screen = function(vb, start, stop) { + if (gfxvidinfo.maxblocklines != 0 && first_block_line != NO_BLOCK) + flush_block(vb, first_block_line, last_block_line); + if (start <= stop) + flush_screen(vb, start, stop); + }*/ + + /*---------------------------------*/ + + function is_ehb(con0, con2) { + if (AMIGA.config.chipset.mask & CSMASK_AGA) + return ((con0 & 0x7010) == 0x6000); + if (AMIGA.config.chipset.mask & CSMASK_ECS_DENISE) + return ((con0 & 0xFC00) == 0x6000 || (con0 & 0xFC00) == 0x7000); + + return ((con0 & 0xFC00) == 0x6000 || (con0 & 0xFC00) == 0x7000);// && !currprefs.cs_denisenoehb; + } + + function is_ham(con0) { + var p = GET_PLANES(con0); + if (!(con0 & 0x800)) + return false; + if (AMIGA.config.chipset.mask & CSMASK_AGA) { + // AGA only has 6 or 8 plane HAM + if (p == 6 || p == 8) + return true; + } else { + // OCS/ECS also supports 5 plane HAM + if (GET_RES_DENISE(con0) > 0) + return 0; + if (p >= 5) + return true; + } + return false; + } + + /*function get_sprite_mask() { + var hi = new Uint64(0x00000000,0xFFFF0000); + hi.lshift(4 * plf2pri); + var lo = new Uint64(0x00000000,0x0000FFFF); + lo.lshift(4 * plf1pri); + hi.or(lo); + return hi; + }*/ + + this.pfield_expand_dp_bplcon = function() { + bplres = dp_for_drawing.bplres; + bplplanecnt = dp_for_drawing.nr_planes; + bplham = dp_for_drawing.ham_seen; + bplehb = dp_for_drawing.ehb_seen; + if ((AMIGA.config.chipset.mask & CSMASK_AGA) && (dp_for_drawing.bplcon2 & 0x0200)) + bplehb = 0; + issprites = dip_for_drawing.nr_sprites; + ecsshres = bplres == RES_SUPERHIRES && (AMIGA.config.chipset.mask & CSMASK_ECS_DENISE) && !(AMIGA.config.chipset.mask & CSMASK_AGA); + + plf1pri = dp_for_drawing.bplcon2 & 7; + plf2pri = (dp_for_drawing.bplcon2 >> 3) & 7; + plf_sprite_mask = 0xFFFF0000 << (4 * plf2pri); + plf_sprite_mask |= (0x0000FFFF << (4 * plf1pri)) & 0xFFFF; + plf_sprite_mask >>>= 0; + //plf_sprite_mask = get_sprite_mask(); + + bpldualpf = (dp_for_drawing.bplcon0 & 0x400) == 0x400; + bpldualpfpri = (dp_for_drawing.bplcon2 & 0x40) == 0x40; + +/*#ifdef AGA + bpldualpf2of = (dp_for_drawing.bplcon3 >> 10) & 7; + sbasecol[0] = ((dp_for_drawing.bplcon4 >> 4) & 15) << 4; + sbasecol[1] = ((dp_for_drawing.bplcon4 >> 0) & 15) << 4; + brdsprt = !brdblank && (AMIGA.config.chipset.mask & CSMASK_AGA) && (dp_for_drawing.bplcon0 & 1) && (dp_for_drawing.bplcon3 & 0x02); + bplxor = dp_for_drawing.bplcon4 >> 8; +#endif*/ + } + + this.pfield_expand_dp_bplconx = function(regno, v) { + if (regno == 0xffff) { + //hposblank = 1; //FIXME return; } - var collision_mask = clxmask[this.clxcon >> 12]; + regno -= 0x1000; + switch (regno) { + case 0x100: + dp_for_drawing.bplcon0 = v; + dp_for_drawing.bplres = GET_RES_DENISE(v); + dp_for_drawing.nr_planes = GET_PLANES(v); + dp_for_drawing.ham_seen = is_ham(v); + break; + case 0x104: + dp_for_drawing.bplcon2 = v; + break; + case 0x106: + dp_for_drawing.bplcon3 = v; + break; +/*#ifdef AGA + case 0x10c: + dp_for_drawing.bplcon4 = v; + break; +#endif*/ + } + this.pfield_expand_dp_bplcon(); + res_shift = lores_shift - bplres; + } + + this.center_image = function() { + var prev_x_adjust = visible_left_border; + var prev_y_adjust = thisframe_y_adjust; + var tmp; - for (var i = 0; i < MAX_SPRITES; i++) { - var sprxp = (this.sprite[i].xpos - AMIGA.playfield.state.hstart + 1) * (AMIGA.playfield.state.hires ? 2 : 1); + var w = gfxvidinfo.drawbuffer.inwidth; + if (AMIGA.config.video.xcenter && max_diwstop > 0) { + if (max_diwstop - min_diwstart < w && AMIGA.config.video.xcenter == 2) + /* Try to center. */ + visible_left_border = ((max_diwstop - min_diwstart - w) >> 1) + min_diwstart; + else + visible_left_border = max_diwstop - w - ((max_diwstop - min_diwstart - w) >> 1); + visible_left_border &= ~((xshift(1, lores_shift)) - 1); - if (!this.sprite[i].armed || sprxp < 0) continue; + /* Would the old value be good enough? If so, leave it as it is if we want to be clever. */ + if (AMIGA.config.video.xcenter == 2) { + if (center_reset || (visible_left_border < prev_x_adjust && prev_x_adjust < min_diwstart && min_diwstart - visible_left_border <= 32)) + visible_left_border = prev_x_adjust; + } + } else if (gfxvidinfo.drawbuffer.extrawidth) { + visible_left_border = max_diwlastword() - w; + if (gfxvidinfo.drawbuffer.extrawidth > 0) + visible_left_border += gfxvidinfo.drawbuffer.extrawidth << AMIGA.config.video.hresolution; + } else { + if (gfxvidinfo.drawbuffer.inxoffset < 0) { + visible_left_border = 0; + } else { + visible_left_border = gfxvidinfo.drawbuffer.inxoffset - DISPLAY_LEFT_SHIFT; + } + } - var minpos = sprxp; - var maxpos = sprxp + 16; + if (visible_left_border > max_diwlastword() - 32) + visible_left_border = max_diwlastword() - 32; + if (visible_left_border < 0) + visible_left_border = 0; + visible_left_border &= ~((xshift(1, lores_shift)) - 1); + + linetoscr_x_adjust_bytes = visible_left_border * gfxvidinfo.drawbuffer.pixbytes; - for (var j = minpos; j < maxpos; j++) { - var sprpix = spr_data[j] & collision_mask; - var match = 1; + visible_right_border = visible_left_border + w; + if (visible_right_border > max_diwlastword()) + visible_right_border = max_diwlastword(); - if (sprpix == 0) continue; + thisframe_y_adjust = minfirstline; + if (AMIGA.config.video.ycenter && thisframe_first_drawn_line >= 0) { + if (thisframe_last_drawn_line - thisframe_first_drawn_line < max_drawn_amiga_line && AMIGA.config.video.ycenter == 2) + thisframe_y_adjust = ((thisframe_last_drawn_line - thisframe_first_drawn_line - max_drawn_amiga_line) >> 1) + thisframe_first_drawn_line; + else + thisframe_y_adjust = thisframe_first_drawn_line + (((thisframe_last_drawn_line - thisframe_first_drawn_line) - max_drawn_amiga_line) >> 1); - sprpix = sprite_ab_merge[sprpix & 255] | (sprite_ab_merge[sprpix >> 8] << 2); - sprpix <<= 1; + if (AMIGA.config.video.ycenter == 2) { + if (center_reset || (thisframe_y_adjust != prev_y_adjust + && prev_y_adjust <= thisframe_first_drawn_line + && prev_y_adjust + max_drawn_amiga_line > thisframe_last_drawn_line)) + thisframe_y_adjust = prev_y_adjust; + } + } + if (thisframe_y_adjust + max_drawn_amiga_line > this.maxvpos_nom) + thisframe_y_adjust = this.maxvpos_nom - max_drawn_amiga_line; + if (thisframe_y_adjust < minfirstline) + thisframe_y_adjust = minfirstline; - for (var k = 1; k >= 0; k--) { - if (AMIGA.playfield.bplcon0 & 0x400) match = 1; + thisframe_y_adjust_real = thisframe_y_adjust << linedbl; + tmp = (this.maxvpos_nom - thisframe_y_adjust + 1) << linedbl; + if (tmp != max_ypos_thisframe) { + last_max_ypos = tmp; + if (last_max_ypos < 0) + last_max_ypos = 0; + } + max_ypos_thisframe = tmp; - for (var l = k; match && l < 6; l += 2) { - if (clxcon_bpl_enable & (1 << l)) { - var t = 0; - if (l < AMIGA.playfield.state.planes) { - t = (AMIGA.playfield.linedata[j] >> l) & 1; - } - if (t != ((clxcon_bpl_match >> l) & 1)) match = 0; - } + if (prev_x_adjust != visible_left_border || prev_y_adjust != thisframe_y_adjust) + frame_redraw_necessary |= (interlace_seen > 0 && linedbl) ? 2 : 1; + + max_diwstop = 0; + min_diwstart = MAX_STOP; + + gfxvidinfo.drawbuffer.xoffset = (DISPLAY_LEFT_SHIFT << RES_MAX) + (visible_left_border << (RES_MAX - AMIGA.config.video.hresolution)); + gfxvidinfo.drawbuffer.yoffset = thisframe_y_adjust << VRES_MAX; + + center_reset = false; + } + + /*---------------------------------*/ + + const COLOR_MATCH_ACOLORS = 1; + const COLOR_MATCH_FULL = 2; + var color_match_type = 0; + + this.adjust_drawing_colors = function(ctable, need_full) { + if (FAST_COLORS) { + if (need_full) + color_reg_cpy(colors_for_drawing, current_colors); + else + color_reg_cpy_acolors(colors_for_drawing, current_colors); + return; + } + if (drawing_color_matches != ctable) { + if (need_full) { + color_reg_cpy(colors_for_drawing, curr_color_tables[ctable]); + color_match_type = COLOR_MATCH_FULL; + } else { + //memcpy (colors_for_drawing.acolors, curr_color_tables[ctable].acolors, sizeof colors_for_drawing.acolors); + //for (var i = 0; i < colors_for_drawing.acolors.length; i++) colors_for_drawing.acolors[i] = curr_color_tables[ctable].acolors[i]; colors_for_drawing.borderblank = curr_color_tables[ctable].borderblank; + color_reg_cpy_acolors(colors_for_drawing, curr_color_tables[ctable]); + color_match_type = COLOR_MATCH_ACOLORS; + } + drawing_color_matches = ctable; + } + else if (need_full && color_match_type != COLOR_MATCH_FULL) { + color_reg_cpy(colors_for_drawing, curr_color_tables[ctable]); + color_match_type = COLOR_MATCH_FULL; + } + } + + this.do_color_changes = function(worker_border, worker_pfield, vp) { + var lastpos = visible_left_border; + var endpos = visible_left_border + gfxvidinfo.drawbuffer.inwidth; + + for (var i = dip_for_drawing.first_color_change; i <= dip_for_drawing.last_color_change; i++) { + var regno = curr_color_changes[i].regno; + var value = curr_color_changes[i].value; + var nextpos, nextpos_in_range; + + if (i == dip_for_drawing.last_color_change) + nextpos = endpos; + else + nextpos = coord_hw_to_window_x(curr_color_changes[i].linepos); + + nextpos_in_range = nextpos; + if (nextpos > endpos) + nextpos_in_range = endpos; + + if (nextpos_in_range > lastpos) { + if (lastpos < playfield_start) { + var t = nextpos_in_range <= playfield_start ? nextpos_in_range : playfield_start; + worker_border(lastpos, t, false); + lastpos = t; + } + } + if (nextpos_in_range > lastpos) { + if (lastpos >= playfield_start && lastpos < playfield_end) { + var t = nextpos_in_range <= playfield_end ? nextpos_in_range : playfield_end; + worker_pfield(lastpos, t, false); + // blank start and end that shouldn't be visible + if (lastpos < visible_left_start) + worker_border(lastpos, visible_left_start, true); + if (t > visible_right_stop) + worker_border(visible_right_stop, endpos, true); + lastpos = t; + } + } + if (nextpos_in_range > lastpos) { + if (lastpos >= playfield_end) + worker_border(lastpos, nextpos_in_range, false); + lastpos = nextpos_in_range; + } + + if (regno >= 0x1000) + this.pfield_expand_dp_bplconx(regno, value); + else if (regno >= 0) { + if (regno == 0 && (value & COLOR_CHANGE_BRDBLANK)) + colors_for_drawing.borderblank = (value & 1) != 0; + else { + color_reg_set(colors_for_drawing, regno, value); + colors_for_drawing.acolors[regno] = getxcolor(value); + } + } + if (lastpos >= endpos) + break; + } + if (vp < visible_top_start || vp >= visible_bottom_stop) { + // outside of visible area + // Just overwrite with black. Above code needs to run because of custom registers, + // not worth the trouble for separate code path just for max 10 lines or so + worker_border(visible_left_border, visible_left_border + gfxvidinfo.drawbuffer.inwidth, true); + } + } + + /*---------------------------------*/ + + function getbgc(blank) { +/*#if 0 + if (blank) + return xcolors[0x088]; + else if (hposblank == 1) + return xcolors[0xf00]; + else if (hposblank == 2) + return xcolors[0x0f0]; + else if (hposblank == 3) + return xcolors[0x00f]; + else if (brdblank) + return xcolors[0x880]; + //return colors_for_drawing.acolors[0]; + return xcolors[0xf0f]; +#endif*/ + return (blank || hposblank || colors_for_drawing.borderblank) ? 0 : colors_for_drawing.acolors[0]; + } + + function fill_line_16(buf, start, stop, blank) { + console.log('fill_line_16() NI', start, stop, blank); + /*uae_u16 *b = (uae_u16 *)buf; + var rem = 0; + var col = getbgc(blank); + + if (((long)&b[start]) & 1) + b[start++] = (uae_u16) col; + + if (start >= stop) + return; + + if (((long)&b[stop]) & 1) { + rem++; + stop--; + } + for (var i = start; i < stop; i += 2) { + uae_u32 *b2 = (uae_u32 *)&b[i]; + *b2 = col; + } + if (rem) + b[stop] = (uae_u16)col;*/ + } + function fill_line_32(buf, start, stop, blank) { + var col = getbgc(blank); + for (var i = start; i < stop; i++) + buf[i] = col; + } + + function pfield_do_fill_line2(start, stop, blank) { + switch (gfxvidinfo.drawbuffer.pixbytes) { + case 2: fill_line_16(xlinebuffer, start, stop, blank); break; + case 4: fill_line_32(xlinebuffer, start, stop, blank); break; + } + } + function pfield_do_fill_line(start, stop, blank) { + //console.log('pfield_do_fill_line()', start, stop, blank); + //xlinecheck('pfield_do_fill_line', start, stop); + if (!blank) { + if (start < visible_left_start) { + pfield_do_fill_line2(start, visible_left_start, true); + start = visible_left_start; + } + if (stop > visible_right_stop) { + pfield_do_fill_line2(start, visible_right_stop, false); + blank = true; + start = visible_right_stop; + } + } + pfield_do_fill_line2(start, stop, blank); + } + + function fill_line2(startpos, len) { + //console.log('fill_line2', startpos, len); + var shift = 0; + if (gfxvidinfo.drawbuffer.pixbytes == 2) shift = 1; + if (gfxvidinfo.drawbuffer.pixbytes == 4) shift = 2; + + var nints = len;// >> (2 - shift); + var nrem = nints & 7; + nints &= ~7; + //int *start = (int *)(((uae_u8*)xlinebuffer) + (startpos << shift)); + var start = startpos;// << shift >> 2; + var val = getbgc(false); + + /*for (; nints > 0; nints -= 8, start += 8) { + *start = val; + *(start+1) = val; + *(start+2) = val; + *(start+3) = val; + *(start+4) = val; + *(start+5) = val; + *(start+6) = val; + *(start+7) = val; + } + switch (nrem) { + case 7: *start++ = val; + case 6: *start++ = val; + case 5: *start++ = val; + case 4: *start++ = val; + case 3: *start++ = val; + case 2: *start++ = val; + case 1: *start = val; + }*/ + + for (; nints > 0; nints -= 8, start += 8) { + xlinebuffer[start ] = val; + xlinebuffer[start + 1] = val; + xlinebuffer[start + 2] = val; + xlinebuffer[start + 3] = val; + xlinebuffer[start + 4] = val; + xlinebuffer[start + 5] = val; + xlinebuffer[start + 6] = val; + xlinebuffer[start + 7] = val; + } + switch (nrem) { + case 7: xlinebuffer[start++] = val; + case 6: xlinebuffer[start++] = val; + case 5: xlinebuffer[start++] = val; + case 4: xlinebuffer[start++] = val; + case 3: xlinebuffer[start++] = val; + case 2: xlinebuffer[start++] = val; + case 1: xlinebuffer[start] = val; + } + } + function fill_line() { + var hs = coord_hw_to_window_x(hsyncstartpos * 2); + if (hs >= gfxvidinfo.drawbuffer.inwidth || hposblank) { + //hposblank = 3; //FIXME + fill_line2(visible_left_border, gfxvidinfo.drawbuffer.inwidth); + } else { + fill_line2(visible_left_border, hs); + //hposblank = 2; //FIXME + fill_line2(visible_left_border + hs, gfxvidinfo.drawbuffer.inwidth); + } + } + + /*---------------------------------*/ + + this.pfield_init_linetoscr = function() { + var ddf_left = dp_for_drawing.plfleft * 2 + DIW_DDF_OFFSET; + var ddf_right = dp_for_drawing.plfright * 2 + DIW_DDF_OFFSET; + + native_ddf_left = coord_hw_to_window_x(ddf_left); + native_ddf_right = coord_hw_to_window_x(ddf_right); + + linetoscr_diw_start = dp_for_drawing.diwfirstword; + linetoscr_diw_end = dp_for_drawing.diwlastword; + + res_shift = lores_shift - bplres; + + if (dip_for_drawing.nr_sprites == 0) { + if (linetoscr_diw_start < native_ddf_left) + linetoscr_diw_start = native_ddf_left; + if (linetoscr_diw_end > native_ddf_right) + linetoscr_diw_end = native_ddf_right; + } + if (linetoscr_diw_end < linetoscr_diw_start) + linetoscr_diw_end = linetoscr_diw_start; + + playfield_start = linetoscr_diw_start; + playfield_end = linetoscr_diw_end; + + unpainted = visible_left_border < playfield_start ? 0 : visible_left_border - playfield_start; + ham_src_pixel = MAX_PIXELS_PER_LINE + res_shift_from_window(playfield_start - native_ddf_left); + unpainted = res_shift_from_window(unpainted); + + if (playfield_start < visible_left_border) + playfield_start = visible_left_border; + if (playfield_start > visible_right_border) + playfield_start = visible_right_border; + if (playfield_end < visible_left_border) + playfield_end = visible_left_border; + if (playfield_end > visible_right_border) + playfield_end = visible_right_border; + + real_playfield_end = playfield_end; + real_playfield_start = playfield_start; + +/*#ifdef AGA + if (brdsprt && dip_for_drawing.nr_sprites) { + var min = visible_right_border, max = visible_left_border, i; + for (i = 0; i < dip_for_drawing.nr_sprites; i++) { + var x; + x = curr_sprite_entries[dip_for_drawing.first_sprite_entry + i].pos; + if (x < min) + min = x; + x = curr_sprite_entries[dip_for_drawing.first_sprite_entry + i].max; + if (x > max) + max = x; + } + min = coord_hw_to_window_x (min >> sprite_buffer_res) + (DIW_DDF_OFFSET << lores_shift); + max = coord_hw_to_window_x (max >> sprite_buffer_res) + (DIW_DDF_OFFSET << lores_shift); + if (min < playfield_start) + playfield_start = min; + if (playfield_start < visible_left_border) + playfield_start = visible_left_border; + if (max > playfield_end) + playfield_end = max; + if (playfield_end > visible_right_border) + playfield_end = visible_right_border; + } +#endif*/ + + if (sprite_first_x < sprite_last_x) { + if (sprite_first_x < 0) + sprite_first_x = 0; + if (sprite_last_x >= MAX_PIXELS_PER_LINE - 1) + sprite_last_x = MAX_PIXELS_PER_LINE - 2; + if (sprite_first_x < sprite_last_x) { + //memset (spritepixels + sprite_first_x, 0, sizeof (struct spritepixelsbuf) * (sprite_last_x - sprite_first_x + 1)); + for (var i = sprite_first_x; i <= sprite_last_x; i++) { + spritepixels[i].clr(); + } + } + } + sprite_last_x = 0; + sprite_first_x = MAX_PIXELS_PER_LINE - 1; + + ddf_left -= DISPLAY_LEFT_SHIFT; + pixels_offset = MAX_PIXELS_PER_LINE - (ddf_left << bplres); + ddf_left <<= bplres; + src_pixel = MAX_PIXELS_PER_LINE + res_shift_from_window(playfield_start - native_ddf_left); + + if (dip_for_drawing.nr_sprites == 0) + return; + + /* Must clear parts of apixels. */ + if (linetoscr_diw_start < native_ddf_left) { + var size = res_shift_from_window(native_ddf_left - linetoscr_diw_start); + linetoscr_diw_start = native_ddf_left; + //memset (apixels + MAX_PIXELS_PER_LINE - size, 0, size); + for (var i = 0; i < size; i++) { + apixels[MAX_PIXELS_PER_LINE - size + i] = 0; + } + } + if (linetoscr_diw_end > native_ddf_right) { + var pos = res_shift_from_window(native_ddf_right - native_ddf_left); + var size = res_shift_from_window(linetoscr_diw_end - native_ddf_right); + linetoscr_diw_start = native_ddf_left; + //memset (apixels + MAX_PIXELS_PER_LINE + pos, 0, size); + for (var i = 0; i < size; i++) { + apixels[MAX_PIXELS_PER_LINE + pos + i] = 0; + } + } + } + + function dummy_worker(start, stop, blank) { } + + + function linetoscr_32(spix, dpix, stoppos) { + //uae_u32 *buf = (uae_u32 *) xlinebuffer; + var buf = xlinebuffer; + + if (dp_for_drawing.ham_seen) { + while (dpix < stoppos) { + var spix_val; + var dpix_val; + var out_val; + + dpix_val = xcolors[ham_linebuf[spix]]; + spix++; + out_val = dpix_val; + buf[dpix++] = out_val; + } + } else if (bpldualpf) { + var lookup = bpldualpfpri ? dblpf_ind2 : dblpf_ind1; + while (dpix < stoppos) { + var spix_val; + var dpix_val; + var out_val; + + spix_val = apixels[spix]; + dpix_val = colors_for_drawing.acolors[lookup[spix_val]]; + spix++; + out_val = dpix_val; + buf[dpix++] = out_val; + } + } else if (bplehb) { + while (dpix < stoppos) { + var spix_val; + var dpix_val; + var out_val; + + spix_val = apixels[spix]; + if (spix_val <= 31) + dpix_val = colors_for_drawing.acolors[spix_val]; + else + dpix_val = xcolors[(colors_for_drawing.color_regs_ecs[spix_val - 32] >> 1) & 0x777]; + spix++; + out_val = dpix_val; + buf[dpix++] = out_val; + } + } else { + while (dpix < stoppos) { + var spix_val; + var dpix_val; + var out_val; + + spix_val = apixels[spix]; + dpix_val = colors_for_drawing.acolors[spix_val]; + spix++; + out_val = dpix_val; + buf[dpix++] = out_val; + } + } + + return spix; + } + + function linetoscr_32_stretch1(spix, dpix, stoppos) { + //uae_u32 *buf = (uae_u32 *) xlinebuffer; + var buf = xlinebuffer; + + if (dp_for_drawing.ham_seen) { + while (dpix < stoppos) { + var spix_val; + var dpix_val; + var out_val; + + dpix_val = xcolors[ham_linebuf[spix]]; + spix++; + out_val = dpix_val; + buf[dpix++] = out_val; + buf[dpix++] = out_val; + } + } else if (bpldualpf) { + var lookup = bpldualpfpri ? dblpf_ind2 : dblpf_ind1; + while (dpix < stoppos) { + var spix_val; + var dpix_val; + var out_val; + + spix_val = apixels[spix]; + dpix_val = colors_for_drawing.acolors[lookup[spix_val]]; + spix++; + out_val = dpix_val; + buf[dpix++] = out_val; + buf[dpix++] = out_val; + } + } else if (bplehb) { + while (dpix < stoppos) { + var spix_val; + var dpix_val; + var out_val; + + spix_val = apixels[spix]; + if (spix_val <= 31) + dpix_val = colors_for_drawing.acolors[spix_val]; + else + dpix_val = xcolors[(colors_for_drawing.color_regs_ecs[spix_val - 32] >> 1) & 0x777]; + spix++; + out_val = dpix_val; + buf[dpix++] = out_val; + buf[dpix++] = out_val; + } + } else { + while (dpix < stoppos) { + var spix_val; + var dpix_val; + var out_val; + + spix_val = apixels[spix]; + dpix_val = colors_for_drawing.acolors[spix_val]; + spix++; + out_val = dpix_val; + buf[dpix++] = out_val; + buf[dpix++] = out_val; + } + } + return spix; + } + + function linetoscr_32_shrink1(spix, dpix, stoppos) { + //uae_u32 *buf = (uae_u32 *) xlinebuffer; + var buf = xlinebuffer; + + if (dp_for_drawing.ham_seen) { + while (dpix < stoppos) { + var spix_val; + var dpix_val; + var out_val; + + dpix_val = xcolors[ham_linebuf[spix]]; + spix += 2; + out_val = dpix_val; + buf[dpix++] = out_val; + } + } else if (bpldualpf) { + var lookup = bpldualpfpri ? dblpf_ind2 : dblpf_ind1; + while (dpix < stoppos) { + var spix_val; + var dpix_val; + var out_val; + + spix_val = apixels[spix]; + dpix_val = colors_for_drawing.acolors[lookup[spix_val]]; + spix += 2; + out_val = dpix_val; + buf[dpix++] = out_val; + } + } else if (bplehb) { + while (dpix < stoppos) { + var spix_val; + var dpix_val; + var out_val; + + spix_val = apixels[spix]; + if (spix_val <= 31) + dpix_val = colors_for_drawing.acolors[spix_val]; + else + dpix_val = xcolors[(colors_for_drawing.color_regs_ecs[spix_val - 32] >> 1) & 0x777]; + spix += 2; + out_val = dpix_val; + buf[dpix++] = out_val; + } + } else { + while (dpix < stoppos) { + var spix_val; + var dpix_val; + var out_val; + + spix_val = apixels[spix]; + dpix_val = colors_for_drawing.acolors[spix_val]; + spix += 2; + out_val = dpix_val; + buf[dpix++] = out_val; + } + } + return spix; + } + + + function linetoscr_32_spr(spix, dpix, stoppos) { + //uae_u32 *buf = (uae_u32 *) xlinebuffer; + var buf = xlinebuffer; + var sprcol; + + if (dp_for_drawing.ham_seen) { + while (dpix < stoppos) { + var sprpix_val; + var spix_val; + var dpix_val; + var out_val; + + dpix_val = xcolors[ham_linebuf[spix]]; + sprpix_val = dpix_val; + spix++; + out_val = dpix_val; + if (spritepixels[dpix].data) { + sprcol = render_sprites (dpix, 0, sprpix_val, 0); + if (sprcol) { + var spcol = colors_for_drawing.acolors[sprcol]; + out_val = spcol; } - if (match) { - this.clxdat |= sprpix << (k * 4); + } + buf[dpix++] = out_val; + } + } else if (bpldualpf) { + var lookup = bpldualpfpri ? dblpf_ind2 : dblpf_ind1; + while (dpix < stoppos) { + var sprpix_val; + var spix_val; + var dpix_val; + var out_val; + + spix_val = apixels[spix]; + sprpix_val = spix_val; + dpix_val = colors_for_drawing.acolors[lookup[spix_val]]; + spix++; + out_val = dpix_val; + if (spritepixels[dpix].data) { + sprcol = render_sprites (dpix, 1, sprpix_val, 0); + if (sprcol) { + var spcol = colors_for_drawing.acolors[sprcol]; + out_val = spcol; } } + buf[dpix++] = out_val; + } + } else if (bplehb) { + while (dpix < stoppos) { + var sprpix_val; + var spix_val; + var dpix_val; + var out_val; + + spix_val = apixels[spix]; + sprpix_val = spix_val; + if (spix_val <= 31) + dpix_val = colors_for_drawing.acolors[spix_val]; + else + dpix_val = xcolors[(colors_for_drawing.color_regs_ecs[spix_val - 32] >> 1) & 0x777]; + spix++; + out_val = dpix_val; + if (spritepixels[dpix].data) { + sprcol = render_sprites (dpix, 0, sprpix_val, 0); + if (sprcol) { + var spcol = colors_for_drawing.acolors[sprcol]; + out_val = spcol; + } + } + buf[dpix++] = out_val; + } + } else { + while (dpix < stoppos) { + var sprpix_val; + var spix_val; + var dpix_val; + var out_val; + + spix_val = apixels[spix]; + sprpix_val = spix_val; + dpix_val = colors_for_drawing.acolors[spix_val]; + spix++; + out_val = dpix_val; + if (spritepixels[dpix].data) { + sprcol = render_sprites (dpix, 0, sprpix_val, 0); + if (sprcol) { + var spcol = colors_for_drawing.acolors[sprcol]; + out_val = spcol; + } + } + buf[dpix++] = out_val; + } + } + + return spix; + } + + function linetoscr_32_stretch1_spr(spix, dpix, stoppos) { + //uae_u32 *buf = (uae_u32 *) xlinebuffer; + var buf = xlinebuffer; + var sprcol; + + if (dp_for_drawing.ham_seen) { + while (dpix < stoppos) { + var sprpix_val; + var spix_val; + var dpix_val; + var out_val; + + dpix_val = xcolors[ham_linebuf[spix]]; + sprpix_val = dpix_val; + spix++; + out_val = dpix_val; + if (spritepixels[dpix].data) { + sprcol = render_sprites (dpix, 0, sprpix_val, 0); + if (sprcol) { + var spcol = colors_for_drawing.acolors[sprcol]; + out_val = spcol; + } + } + buf[dpix++] = out_val; + buf[dpix++] = out_val; + } + } else if (bpldualpf) { + var lookup = bpldualpfpri ? dblpf_ind2 : dblpf_ind1; + while (dpix < stoppos) { + var sprpix_val; + var spix_val; + var dpix_val; + var out_val; + + spix_val = apixels[spix]; + sprpix_val = spix_val; + dpix_val = colors_for_drawing.acolors[lookup[spix_val]]; + spix++; + out_val = dpix_val; + if (spritepixels[dpix].data) { + sprcol = render_sprites (dpix, 1, sprpix_val, 0); + if (sprcol) { + var spcol = colors_for_drawing.acolors[sprcol]; + out_val = spcol; + } + } + buf[dpix++] = out_val; + buf[dpix++] = out_val; + } + } else if (bplehb) { + while (dpix < stoppos) { + var sprpix_val; + var spix_val; + var dpix_val; + var out_val; + + spix_val = apixels[spix]; + sprpix_val = spix_val; + if (spix_val <= 31) + dpix_val = colors_for_drawing.acolors[spix_val]; + else + dpix_val = xcolors[(colors_for_drawing.color_regs_ecs[spix_val - 32] >> 1) & 0x777]; + spix++; + out_val = dpix_val; + if (spritepixels[dpix].data) { + sprcol = render_sprites (dpix, 0, sprpix_val, 0); + if (sprcol) { + var spcol = colors_for_drawing.acolors[sprcol]; + out_val = spcol; + } + } + buf[dpix++] = out_val; + buf[dpix++] = out_val; + } + } else { + while (dpix < stoppos) { + var sprpix_val; + var spix_val; + var dpix_val; + var out_val; + + spix_val = apixels[spix]; + sprpix_val = spix_val; + dpix_val = colors_for_drawing.acolors[spix_val]; + spix++; + out_val = dpix_val; + if (spritepixels[dpix].data) { + sprcol = render_sprites (dpix, 0, sprpix_val, 0); + if (sprcol) { + var spcol = colors_for_drawing.acolors[sprcol]; + out_val = spcol; + } + } + buf[dpix++] = out_val; + buf[dpix++] = out_val; + } + } + return spix; + } + + function linetoscr_32_shrink1_spr(spix, dpix, stoppos) { + //var *buf = (var *) xlinebuffer; + var buf = xlinebuffer; + var sprcol; + + if (dp_for_drawing.ham_seen) { + while (dpix < stoppos) { + var sprpix_val; + var spix_val; + var dpix_val; + var out_val; + + dpix_val = xcolors[ham_linebuf[spix]]; + sprpix_val = dpix_val; + spix += 2; + out_val = dpix_val; + if (spritepixels[dpix].data) { + sprcol = render_sprites (dpix, 0, sprpix_val, 0); + if (sprcol) { + var spcol = colors_for_drawing.acolors[sprcol]; + out_val = spcol; + } + } + buf[dpix++] = out_val; + } + } else if (bpldualpf) { + var lookup = bpldualpfpri ? dblpf_ind2 : dblpf_ind1; + while (dpix < stoppos) { + var sprpix_val; + var spix_val; + var dpix_val; + var out_val; + + spix_val = apixels[spix]; + sprpix_val = spix_val; + dpix_val = colors_for_drawing.acolors[lookup[spix_val]]; + spix += 2; + out_val = dpix_val; + if (spritepixels[dpix].data) { + sprcol = render_sprites (dpix, 1, sprpix_val, 0); + if (sprcol) { + var spcol = colors_for_drawing.acolors[sprcol]; + out_val = spcol; + } + } + buf[dpix++] = out_val; + } + } else if (bplehb) { + while (dpix < stoppos) { + var sprpix_val; + var spix_val; + var dpix_val; + var out_val; + + spix_val = apixels[spix]; + sprpix_val = spix_val; + if (spix_val <= 31) + dpix_val = colors_for_drawing.acolors[spix_val]; + else + dpix_val = xcolors[(colors_for_drawing.color_regs_ecs[spix_val - 32] >> 1) & 0x777]; + spix += 2; + out_val = dpix_val; + if (spritepixels[dpix].data) { + sprcol = render_sprites (dpix, 0, sprpix_val, 0); + if (sprcol) { + var spcol = colors_for_drawing.acolors[sprcol]; + out_val = spcol; + } + } + buf[dpix++] = out_val; + } + } else { + while (dpix < stoppos) { + var sprpix_val; + var spix_val; + var dpix_val; + var out_val; + + spix_val = apixels[spix]; + sprpix_val = spix_val; + dpix_val = colors_for_drawing.acolors[spix_val]; + spix += 2; + out_val = dpix_val; + if (spritepixels[dpix].data) { + sprcol = render_sprites (dpix, 0, sprpix_val, 0); + if (sprcol) { + var spcol = colors_for_drawing.acolors[sprcol]; + out_val = spcol; + } + } + buf[dpix++] = out_val; + } + } + + return spix; + } + + + //apixels -> xlinebuffer + function pfield_do_linetoscr(start, stop, blank) { + //console.log('pfield_do_linetoscr()', start, stop, stop - start); + //xlinecheck('pfield_do_linetoscr', start, stop); + +/*#ifdef AGA + if (issprites && (AMIGA.config.chipset.mask & CSMASK_AGA)) { + if (res_shift == 0) { + switch (gfxvidinfo.drawbuffer.pixbytes) { + case 2: src_pixel = linetoscr_16_aga_spr (src_pixel, start, stop); break; + case 4: src_pixel = linetoscr_32_aga_spr (src_pixel, start, stop); break; + } + } else if (res_shift == 2) { + switch (gfxvidinfo.drawbuffer.pixbytes) { + case 2: src_pixel = linetoscr_16_stretch2_aga_spr (src_pixel, start, stop); break; + case 4: src_pixel = linetoscr_32_stretch2_aga_spr (src_pixel, start, stop); break; + } + } else if (res_shift == 1) { + switch (gfxvidinfo.drawbuffer.pixbytes) { + case 2: src_pixel = linetoscr_16_stretch1_aga_spr (src_pixel, start, stop); break; + case 4: src_pixel = linetoscr_32_stretch1_aga_spr (src_pixel, start, stop); break; + } + } else if (res_shift == -1) { + if (currprefs.gfx_lores_mode) { + switch (gfxvidinfo.drawbuffer.pixbytes) { + case 2: src_pixel = linetoscr_16_shrink1f_aga_spr (src_pixel, start, stop); break; + case 4: src_pixel = linetoscr_32_shrink1f_aga_spr (src_pixel, start, stop); break; + } + } else { + switch (gfxvidinfo.drawbuffer.pixbytes) { + case 2: src_pixel = linetoscr_16_shrink1_aga_spr (src_pixel, start, stop); break; + case 4: src_pixel = linetoscr_32_shrink1_aga_spr (src_pixel, start, stop); break; + } + } + } else if (res_shift == -2) { + if (currprefs.gfx_lores_mode) { + switch (gfxvidinfo.drawbuffer.pixbytes) { + case 2: src_pixel = linetoscr_16_shrink2f_aga_spr (src_pixel, start, stop); break; + case 4: src_pixel = linetoscr_32_shrink2f_aga_spr (src_pixel, start, stop); break; + } + } else { + switch (gfxvidinfo.drawbuffer.pixbytes) { + case 2: src_pixel = linetoscr_16_shrink2_aga_spr (src_pixel, start, stop); break; + case 4: src_pixel = linetoscr_32_shrink2_aga_spr (src_pixel, start, stop); break; + } + } + } + } else if (AMIGA.config.chipset.mask & CSMASK_AGA) { + if (res_shift == 0) { + switch (gfxvidinfo.drawbuffer.pixbytes) { + case 2: src_pixel = linetoscr_16_aga (src_pixel, start, stop); break; + case 4: src_pixel = linetoscr_32_aga (src_pixel, start, stop); break; + } + } else if (res_shift == 2) { + switch (gfxvidinfo.drawbuffer.pixbytes) { + case 2: src_pixel = linetoscr_16_stretch2_aga (src_pixel, start, stop); break; + case 4: src_pixel = linetoscr_32_stretch2_aga (src_pixel, start, stop); break; + } + } else if (res_shift == 1) { + switch (gfxvidinfo.drawbuffer.pixbytes) { + case 2: src_pixel = linetoscr_16_stretch1_aga (src_pixel, start, stop); break; + case 4: src_pixel = linetoscr_32_stretch1_aga (src_pixel, start, stop); break; + } + } else if (res_shift == -1) { + if (currprefs.gfx_lores_mode) { + switch (gfxvidinfo.drawbuffer.pixbytes) { + case 2: src_pixel = linetoscr_16_shrink1f_aga (src_pixel, start, stop); break; + case 4: src_pixel = linetoscr_32_shrink1f_aga (src_pixel, start, stop); break; + } + } else { + switch (gfxvidinfo.drawbuffer.pixbytes) { + case 2: src_pixel = linetoscr_16_shrink1_aga (src_pixel, start, stop); break; + case 4: src_pixel = linetoscr_32_shrink1_aga (src_pixel, start, stop); break; + } + } + } else if (res_shift == -2) { + if (currprefs.gfx_lores_mode) { + switch (gfxvidinfo.drawbuffer.pixbytes) { + case 2: src_pixel = linetoscr_16_shrink2f_aga (src_pixel, start, stop); break; + case 4: src_pixel = linetoscr_32_shrink2f_aga (src_pixel, start, stop); break; + } + } else { + switch (gfxvidinfo.drawbuffer.pixbytes) { + case 2: src_pixel = linetoscr_16_shrink2_aga (src_pixel, start, stop); break; + case 4: src_pixel = linetoscr_32_shrink2_aga (src_pixel, start, stop); break; + } + } + } + } else +#endif*/ + +/*#ifdef ECS_DENISE + if (ecsshres) { + if (res_shift == 0) { + switch (gfxvidinfo.drawbuffer.pixbytes) { + case 2: src_pixel = linetoscr_16_sh (src_pixel, start, stop, issprites); break; + case 4: src_pixel = linetoscr_32_sh (src_pixel, start, stop, issprites); break; + } + } else if (res_shift == -1) { + if (currprefs.gfx_lores_mode) { + switch (gfxvidinfo.drawbuffer.pixbytes) { + case 2: src_pixel = linetoscr_16_shrink1f_sh (src_pixel, start, stop, issprites); break; + case 4: src_pixel = linetoscr_32_shrink1f_sh (src_pixel, start, stop, issprites); break; + } + } else { + switch (gfxvidinfo.drawbuffer.pixbytes) { + case 2: src_pixel = linetoscr_16_shrink1_sh (src_pixel, start, stop, issprites); break; + case 4: src_pixel = linetoscr_32_shrink1_sh (src_pixel, start, stop, issprites); break; + } + } + } else if (res_shift == -2) { + if (currprefs.gfx_lores_mode) { + switch (gfxvidinfo.drawbuffer.pixbytes) { + case 2: src_pixel = linetoscr_16_shrink2f_sh (src_pixel, start, stop, issprites); break; + case 4: src_pixel = linetoscr_32_shrink2f_sh (src_pixel, start, stop, issprites); break; + } + } else { + switch (gfxvidinfo.drawbuffer.pixbytes) { + case 2: src_pixel = linetoscr_16_shrink2_sh (src_pixel, start, stop, issprites); break; + case 4: src_pixel = linetoscr_32_shrink2_sh (src_pixel, start, stop, issprites); break; + } + } + } + } else +#endif*/ + + if (issprites) { + if (res_shift == 0) { + switch (gfxvidinfo.drawbuffer.pixbytes) { + case 2: src_pixel = linetoscr_16_spr (src_pixel, start, stop); break; + case 4: src_pixel = linetoscr_32_spr (src_pixel, start, stop); break; + } + } else if (res_shift == 2) { + switch (gfxvidinfo.drawbuffer.pixbytes) { + case 2: src_pixel = linetoscr_16_stretch2_spr (src_pixel, start, stop); break; + case 4: src_pixel = linetoscr_32_stretch2_spr (src_pixel, start, stop); break; + } + } else if (res_shift == 1) { + switch (gfxvidinfo.drawbuffer.pixbytes) { + case 2: src_pixel = linetoscr_16_stretch1_spr (src_pixel, start, stop); break; + case 4: src_pixel = linetoscr_32_stretch1_spr (src_pixel, start, stop); break; + } + } else if (res_shift == -1) { + switch (gfxvidinfo.drawbuffer.pixbytes) { + case 2: src_pixel = linetoscr_16_shrink1_spr (src_pixel, start, stop); break; + case 4: src_pixel = linetoscr_32_shrink1_spr (src_pixel, start, stop); break; + } + } + } else { + if (res_shift == 0) { + switch (gfxvidinfo.drawbuffer.pixbytes) { + case 2: src_pixel = linetoscr_16 (src_pixel, start, stop); break; + case 4: src_pixel = linetoscr_32 (src_pixel, start, stop); break; + } + } else if (res_shift == 2) { + switch (gfxvidinfo.drawbuffer.pixbytes) { + case 2: src_pixel = linetoscr_16_stretch2 (src_pixel, start, stop); break; + case 4: src_pixel = linetoscr_32_stretch2 (src_pixel, start, stop); break; + } + } else if (res_shift == 1) { + switch (gfxvidinfo.drawbuffer.pixbytes) { + case 2: src_pixel = linetoscr_16_stretch1 (src_pixel, start, stop); break; + case 4: src_pixel = linetoscr_32_stretch1 (src_pixel, start, stop); break; + } + } else if (res_shift == -1) { + switch (gfxvidinfo.drawbuffer.pixbytes) { + case 2: src_pixel = linetoscr_16_shrink1 (src_pixel, start, stop); break; + case 4: src_pixel = linetoscr_32_shrink1 (src_pixel, start, stop); break; + } + } + } + } + + function init_ham_decoding() { + var unpainted_amiga = unpainted; + + ham_decode_pixel = ham_src_pixel; + ham_lastcolor = color_reg_get(colors_for_drawing, 0); + + if (!bplham) { + if (unpainted_amiga > 0) { + var pv = apixels[ham_decode_pixel + unpainted_amiga - 1]; +/*#ifdef AGA + if (currprefs.chipset_mask & CSMASK_AGA) + ham_lastcolor = colors_for_drawing.color_regs_aga[pv ^ bplxor]; + else +#endif*/ + ham_lastcolor = colors_for_drawing.color_regs_ecs[pv]; + } +/*#ifdef AGA + } else if (currprefs.chipset_mask & CSMASK_AGA) { + if (bplplanecnt >= 7) { // AGA mode HAM8 + while (unpainted_amiga-- > 0) { + var pv = apixels[ham_decode_pixel++] ^ bplxor; + switch (pv & 0x3) { + case 0x0: ham_lastcolor = colors_for_drawing.color_regs_aga[pv >> 2]; break; + case 0x1: ham_lastcolor &= 0xFFFF03; ham_lastcolor |= (pv & 0xFC); break; + case 0x2: ham_lastcolor &= 0x03FFFF; ham_lastcolor |= (pv & 0xFC) << 16; break; + case 0x3: ham_lastcolor &= 0xFF03FF; ham_lastcolor |= (pv & 0xFC) << 8; break; + } + } + } else { // AGA mode HAM6 + while (unpainted_amiga-- > 0) { + var pv = apixels[ham_decode_pixel++] ^ bplxor; + switch (pv & 0x30) { + case 0x00: ham_lastcolor = colors_for_drawing.color_regs_aga[pv]; break; + case 0x10: ham_lastcolor &= 0xFFFF00; ham_lastcolor |= (pv & 0xF) << 4; break; + case 0x20: ham_lastcolor &= 0x00FFFF; ham_lastcolor |= (pv & 0xF) << 20; break; + case 0x30: ham_lastcolor &= 0xFF00FF; ham_lastcolor |= (pv & 0xF) << 12; break; + } + } + } +#endif*/ + } else { + /* OCS/ECS mode HAM6 */ + while (unpainted_amiga-- > 0) { + var pv = apixels[ham_decode_pixel++]; + switch (pv & 0x30) { + case 0x00: ham_lastcolor = colors_for_drawing.color_regs_ecs[pv]; break; + case 0x10: ham_lastcolor &= 0xFF0; ham_lastcolor |= (pv & 0xF); break; + case 0x20: ham_lastcolor &= 0x0FF; ham_lastcolor |= (pv & 0xF) << 8; break; + case 0x30: ham_lastcolor &= 0xF0F; ham_lastcolor |= (pv & 0xF) << 4; break; + } } } } - this.draw_1 = function (sprxp, bufpos, datab, num, dbl, mask, do_collisions, collision_mask) { + function decode_ham(pix, stoppos, blank) { + var todraw_amiga = res_shift_from_window(stoppos - pix); + + if (!bplham) { + while (todraw_amiga-- > 0) { + var pv = apixels[ham_decode_pixel]; +/*#ifdef AGA + if (currprefs.chipset_mask & CSMASK_AGA) + ham_lastcolor = colors_for_drawing.color_regs_aga[pv ^ bplxor]; + else +#endif*/ + ham_lastcolor = colors_for_drawing.color_regs_ecs[pv]; + + ham_linebuf[ham_decode_pixel++] = ham_lastcolor; + } +/*#ifdef AGA + } else if (currprefs.chipset_mask & CSMASK_AGA) { + if (bplplanecnt >= 7) { // AGA mode HAM8 + while (todraw_amiga-- > 0) { + var pv = apixels[ham_decode_pixel] ^ bplxor; + switch (pv & 0x3) { + case 0x0: ham_lastcolor = colors_for_drawing.color_regs_aga[pv >> 2]; break; + case 0x1: ham_lastcolor &= 0xFFFF03; ham_lastcolor |= (pv & 0xFC); break; + case 0x2: ham_lastcolor &= 0x03FFFF; ham_lastcolor |= (pv & 0xFC) << 16; break; + case 0x3: ham_lastcolor &= 0xFF03FF; ham_lastcolor |= (pv & 0xFC) << 8; break; + } + ham_linebuf[ham_decode_pixel++] = ham_lastcolor; + } + } else { // AGA mode HAM6 + while (todraw_amiga-- > 0) { + var pv = apixels[ham_decode_pixel] ^ bplxor; + switch (pv & 0x30) { + case 0x00: ham_lastcolor = colors_for_drawing.color_regs_aga[pv]; break; + case 0x10: ham_lastcolor &= 0xFFFF00; ham_lastcolor |= (pv & 0xF) << 4; break; + case 0x20: ham_lastcolor &= 0x00FFFF; ham_lastcolor |= (pv & 0xF) << 20; break; + case 0x30: ham_lastcolor &= 0xFF00FF; ham_lastcolor |= (pv & 0xF) << 12; break; + } + ham_linebuf[ham_decode_pixel++] = ham_lastcolor; + } + } +#endif*/ + } else { + /* OCS/ECS mode HAM6 */ + while (todraw_amiga-- > 0) { + var pv = apixels[ham_decode_pixel]; + switch (pv & 0x30) { + case 0x00: ham_lastcolor = colors_for_drawing.color_regs_ecs[pv]; break; + case 0x10: ham_lastcolor &= 0xFF0; ham_lastcolor |= (pv & 0xF); break; + case 0x20: ham_lastcolor &= 0x0FF; ham_lastcolor |= (pv & 0xF) << 8; break; + case 0x30: ham_lastcolor &= 0xF0F; ham_lastcolor |= (pv & 0xF) << 4; break; + } + ham_linebuf[ham_decode_pixel++] = ham_lastcolor; + } + } + } + + function weird_bitplane_fix() { + for (var i = playfield_start >> lores_shift; i < playfield_end >> lores_shift; i++) { + if (apixels[pixels_offset + i] > 16) apixels[pixels_offset + i] = 16; + } + } + + //line_data -> apixels + this.pfield_doline_1 = function(lineno, wordcount, planes) { + var pixels = MAX_PIXELS_PER_LINE; + var tmp, d0, d1, d2, d3, d4, d5, d6, d7; + var offs = 0; + + while (wordcount-- > 0) { + d0 = d1 = d2 = d3 = d4 = d5 = d6 = d7 = 0; + + switch (planes) { +/*#ifdef AGA + case 8: d0 = line_data[lineno][7][offs]; + case 7: d1 = line_data[lineno][6][offs]; +#endif*/ + case 6: d2 = line_data[lineno][5][offs]; + case 5: d3 = line_data[lineno][4][offs]; + case 4: d4 = line_data[lineno][3][offs]; + case 3: d5 = line_data[lineno][2][offs]; + case 2: d6 = line_data[lineno][1][offs]; + case 1: d7 = line_data[lineno][0][offs]; + } + offs++; + + tmp = (d0 ^ (d1 >>> 1)) & 0x55555555; d0 ^= tmp; d1 ^= (tmp << 1); + tmp = (d2 ^ (d3 >>> 1)) & 0x55555555; d2 ^= tmp; d3 ^= (tmp << 1); + tmp = (d4 ^ (d5 >>> 1)) & 0x55555555; d4 ^= tmp; d5 ^= (tmp << 1); + tmp = (d6 ^ (d7 >>> 1)) & 0x55555555; d6 ^= tmp; d7 ^= (tmp << 1); + + tmp = (d0 ^ (d2 >>> 2)) & 0x33333333; d0 ^= tmp; d2 ^= (tmp << 2); + tmp = (d1 ^ (d3 >>> 2)) & 0x33333333; d1 ^= tmp; d3 ^= (tmp << 2); + tmp = (d4 ^ (d6 >>> 2)) & 0x33333333; d4 ^= tmp; d6 ^= (tmp << 2); + tmp = (d5 ^ (d7 >>> 2)) & 0x33333333; d5 ^= tmp; d7 ^= (tmp << 2); + + tmp = (d0 ^ (d4 >>> 4)) & 0x0f0f0f0f; d0 ^= tmp; d4 ^= (tmp << 4); + tmp = (d1 ^ (d5 >>> 4)) & 0x0f0f0f0f; d1 ^= tmp; d5 ^= (tmp << 4); + tmp = (d2 ^ (d6 >>> 4)) & 0x0f0f0f0f; d2 ^= tmp; d6 ^= (tmp << 4); + tmp = (d3 ^ (d7 >>> 4)) & 0x0f0f0f0f; d3 ^= tmp; d7 ^= (tmp << 4); + + tmp = (d0 ^ (d1 >>> 8)) & 0x00ff00ff; d0 ^= tmp; d1 ^= (tmp << 8); + tmp = (d2 ^ (d3 >>> 8)) & 0x00ff00ff; d2 ^= tmp; d3 ^= (tmp << 8); + tmp = (d4 ^ (d5 >>> 8)) & 0x00ff00ff; d4 ^= tmp; d5 ^= (tmp << 8); + tmp = (d6 ^ (d7 >>> 8)) & 0x00ff00ff; d6 ^= tmp; d7 ^= (tmp << 8); + + tmp = (d0 ^ (d2 >>> 16)) & 0x0000ffff; d0 ^= tmp; d2 ^= (tmp << 16); + tmp = (d1 ^ (d3 >>> 16)) & 0x0000ffff; d1 ^= tmp; d3 ^= (tmp << 16); + tmp = (d4 ^ (d6 >>> 16)) & 0x0000ffff; d4 ^= tmp; d6 ^= (tmp << 16); + tmp = (d5 ^ (d7 >>> 16)) & 0x0000ffff; d5 ^= tmp; d7 ^= (tmp << 16); + + apixels[pixels ] = (d0 >>> 24) & 0xff; + apixels[pixels + 1] = (d0 >>> 16) & 0xff; + apixels[pixels + 2] = (d0 >>> 8) & 0xff; + apixels[pixels + 3] = d0 & 0xff; + apixels[pixels + 4] = (d4 >>> 24) & 0xff; + apixels[pixels + 5] = (d4 >>> 16) & 0xff; + apixels[pixels + 6] = (d4 >>> 8) & 0xff; + apixels[pixels + 7] = d4 & 0xff; + apixels[pixels + 8] = (d1 >>> 24) & 0xff; + apixels[pixels + 9] = (d1 >>> 16) & 0xff; + apixels[pixels + 10] = (d1 >>> 8) & 0xff; + apixels[pixels + 11] = d1 & 0xff; + apixels[pixels + 12] = (d5 >>> 24) & 0xff; + apixels[pixels + 13] = (d5 >>> 16) & 0xff; + apixels[pixels + 14] = (d5 >>> 8) & 0xff; + apixels[pixels + 15] = d5 & 0xff; + apixels[pixels + 16] = (d2 >>> 24) & 0xff; + apixels[pixels + 17] = (d2 >>> 16) & 0xff; + apixels[pixels + 18] = (d2 >>> 8) & 0xff; + apixels[pixels + 19] = d2 & 0xff; + apixels[pixels + 20] = (d6 >>> 24) & 0xff; + apixels[pixels + 21] = (d6 >>> 16) & 0xff; + apixels[pixels + 22] = (d6 >>> 8) & 0xff; + apixels[pixels + 23] = d6 & 0xff; + apixels[pixels + 24] = (d3 >>> 24) & 0xff; + apixels[pixels + 25] = (d3 >>> 16) & 0xff; + apixels[pixels + 26] = (d3 >>> 8) & 0xff; + apixels[pixels + 27] = d3 & 0xff; + apixels[pixels + 28] = (d7 >>> 24) & 0xff; + apixels[pixels + 29] = (d7 >>> 16) & 0xff; + apixels[pixels + 30] = (d7 >>> 8) & 0xff; + apixels[pixels + 31] = d7 & 0xff; + pixels += 32; + + /*apixels[pixels++] = (d0 >>> 24); + apixels[pixels++] = (d0 >>> 16) & 0xff; + apixels[pixels++] = (d0 >>> 8) & 0xff; + apixels[pixels++] = d0 & 0xff; + apixels[pixels++] = (d4 >>> 24); + apixels[pixels++] = (d4 >>> 16) & 0xff; + apixels[pixels++] = (d4 >>> 8) & 0xff; + apixels[pixels++] = d4 & 0xff; + apixels[pixels++] = (d1 >>> 24); + apixels[pixels++] = (d1 >>> 16) & 0xff; + apixels[pixels++] = (d1 >>> 8) & 0xff; + apixels[pixels++] = d1 & 0xff; + apixels[pixels++] = (d5 >>> 24); + apixels[pixels++] = (d5 >>> 16) & 0xff; + apixels[pixels++] = (d5 >>> 8) & 0xff; + apixels[pixels++] = d5 & 0xff; + apixels[pixels++] = (d2 >>> 24); + apixels[pixels++] = (d2 >>> 16) & 0xff; + apixels[pixels++] = (d2 >>> 8) & 0xff; + apixels[pixels++] = d2 & 0xff; + apixels[pixels++] = (d6 >>> 24); + apixels[pixels++] = (d6 >>> 16) & 0xff; + apixels[pixels++] = (d6 >>> 8) & 0xff; + apixels[pixels++] = d6 & 0xff; + apixels[pixels++] = (d3 >>> 24); + apixels[pixels++] = (d3 >>> 16) & 0xff; + apixels[pixels++] = (d3 >>> 8) & 0xff; + apixels[pixels++] = d3 & 0xff; + apixels[pixels++] = (d7 >>> 24); + apixels[pixels++] = (d7 >>> 16) & 0xff; + apixels[pixels++] = (d7 >>> 8) & 0xff; + apixels[pixels++] = d7 & 0xff;*/ + } + } + + this.pfield_doline = function(lineno) { + if (bplplanecnt) + this.pfield_doline_1(lineno, dp_for_drawing.plflinelen, bplplanecnt); + else { + for (var i = 0; i < dp_for_drawing.plflinelen * 32; i++) apixels[i] = 0; //memset (data, 0, dp_for_drawing.plflinelen * 32); + } + } + + this.pfield_draw_line = function(vb, lineno, gfx_ypos, follow_ypos) { + if (!AMIGA.config.video.enabled) return; + //console.log('pfield_draw_line', lineno, gfx_ypos, follow_ypos); + var border = 0; + var do_double = 0; + + dp_for_drawing = line_decisions[lineno]; + dip_for_drawing = curr_drawinfo[lineno]; + + switch (linestate[lineno]) { + case LINE_REMEMBERED_AS_PREVIOUS: + BUG.info('pfield_draw_line() Shouldn\'t get here... this is a bug.'); + return; + case LINE_BLACK: + linestate[lineno] = LINE_REMEMBERED_AS_BLACK; + border = 2; + break; + case LINE_REMEMBERED_AS_BLACK: + return; + case LINE_AS_PREVIOUS: + //dp_for_drawing--; + //dip_for_drawing--; + dp_for_drawing = line_decisions[lineno - 1]; + dip_for_drawing = curr_drawinfo[lineno - 1]; + linestate[lineno] = LINE_DONE_AS_PREVIOUS; + if (dp_for_drawing.plfleft < 0) + border = 1; + break; + case LINE_DONE_AS_PREVIOUS: + /* fall through */ + case LINE_DONE: + return; + case LINE_DECIDED_DOUBLE: + if (follow_ypos >= 0) { + do_double = 1; + linestate[lineno + 1] = LINE_DONE_AS_PREVIOUS; + } + /* fall through */ + default: + if (dp_for_drawing.plfleft < 0) + border = 1; + linestate[lineno] = LINE_DONE; + break; + } + + if (border == 0) { + this.pfield_expand_dp_bplcon(); + this.pfield_init_linetoscr(); + this.pfield_doline(lineno); + + this.adjust_drawing_colors(dp_for_drawing.ctable, dp_for_drawing.ham_seen || bplehb || ecsshres); + + if (dp_for_drawing.ham_seen) { + init_ham_decoding(); + if (dip_for_drawing.nr_color_changes == 0) + decode_ham(visible_left_border, visible_right_border, false); + else { + this.do_color_changes(dummy_worker, decode_ham, lineno); + this.adjust_drawing_colors(dp_for_drawing.ctable, dp_for_drawing.ham_seen || bplehb); + } + bplham = dp_for_drawing.ham_at_start; + } + if (plf2pri > 5 && bplplanecnt == 5 && !(AMIGA.config.chipset.mask & CSMASK_AGA)) + weird_bitplane_fix(); + + if (dip_for_drawing.nr_sprites) { +/*#ifdef AGA + if (brdsprt) + this.clear_bitplane_border_aga(); +#endif*/ + for (var i = 0; i < dip_for_drawing.nr_sprites; i++) + draw_sprites(curr_sprite_entries[dip_for_drawing.first_sprite_entry + i]); + } + this.do_color_changes(pfield_do_fill_line, pfield_do_linetoscr, lineno); + + this.do_flush_line(vb, gfx_ypos); + if (do_double) + this.do_flush_line(vb, follow_ypos); + } else if (border == 1) { + var dosprites = 0; + + this.adjust_drawing_colors(dp_for_drawing.ctable, false); + +/*#ifdef AGA + if (brdsprt && dip_for_drawing->nr_sprites > 0) { + dosprites = 1; + this.pfield_expand_dp_bplcon(); + pfield_init_linetoscr (); + memset (apixels + MAX_PIXELS_PER_LINE, colors_for_drawing.borderblank ? 0 : colors_for_drawing.acolors[0], MAX_PIXELS_PER_LINE); + } +#endif*/ + if (!dosprites && dip_for_drawing.nr_color_changes == 0) { + fill_line(); + this.do_flush_line(vb, gfx_ypos); + if (do_double) + this.do_flush_line(vb, follow_ypos); + return; + } + if (dosprites) { + for (var i = 0; i < dip_for_drawing.nr_sprites; i++) + this.draw_sprites(curr_sprite_entries[dip_for_drawing.first_sprite_entry + i]); + var oxor = bplxor; + for (var i = 0; i < apixels.length; i++) apixels[i] = 0; //memset (apixels, 0, sizeof apixels); + bplxor = 0; + this.do_color_changes(pfield_do_fill_line, pfield_do_linetoscr, lineno); + bplxor = oxor; + } else { + playfield_start = visible_right_border; + playfield_end = visible_right_border; + this.do_color_changes(pfield_do_fill_line, pfield_do_fill_line, lineno); + } + this.do_flush_line(vb, gfx_ypos); + if (do_double) + this.do_flush_line(vb, follow_ypos); + } else { + var tmp = hposblank; + //hposblank = brdblank; + hposblank = colors_for_drawing.borderblank; + fill_line(); + this.do_flush_line(vb, gfx_ypos); + hposblank = tmp; + } + } + + this.init_drawing_frame = function() { + this.init_hardware_for_drawing_frame(); + + if (thisframe_first_drawn_line < 0) + thisframe_first_drawn_line = minfirstline; + if (thisframe_first_drawn_line > thisframe_last_drawn_line) + thisframe_last_drawn_line = thisframe_first_drawn_line; + + var maxline = ((this.maxvpos_nom + 1) << linedbl) + 2; + + if (SMART_UPDATE) { + for (var i = 0; i < maxline; i++) { + switch (linestate[i]) { + case LINE_DONE_AS_PREVIOUS: + linestate[i] = LINE_REMEMBERED_AS_PREVIOUS; + break; + case LINE_REMEMBERED_AS_BLACK: + break; + default: + linestate[i] = LINE_UNDECIDED; + break; + } + } + } else { + for (var i = 0; i < maxline; i++) linestate[i] = LINE_UNDECIDED; //memset(linestate, LINE_UNDECIDED, maxline); + } + + last_drawn_line = 0; + first_drawn_line = 0x7fff; + + first_block_line = last_block_line = NO_BLOCK; + if (frame_redraw_necessary) + frame_redraw_necessary--; + + this.center_image(); + + thisframe_first_drawn_line = -1; + thisframe_last_drawn_line = -1; + + drawing_color_matches = -1; + } + + this.finish_drawing_frame = function() { + var vb = gfxvidinfo.drawbuffer; + + if (SMART_UPDATE) { + for (var i = 0; i < max_ypos_thisframe; i++) { + var i1 = i + min_ypos_for_screen; + var line = i + thisframe_y_adjust_real; + + var where2 = amiga2aspect_line_map[i1]; + if (where2 >= vb.inheight) + break; + if (where2 < 0) + continue; + hposblank = 0; + this.pfield_draw_line(vb, line, where2, amiga2aspect_line_map[i1 + 1]); + } + //if (lightpen_active) lightpen_update(vb); + + //this.do_flush_screen(vb, first_drawn_line, last_drawn_line); + } /*else { + if (!interlace_seen) + this.do_flush_screen(vb, first_drawn_line, last_drawn_line); + }*/ + } + + this.hardware_line_completed = function(lineno) { + if (!SMART_UPDATE) { + var i = lineno - thisframe_y_adjust_real; + if (i >= 0 && i < max_ypos_thisframe) { + var where = amiga2aspect_line_map[i + min_ypos_for_screen]; + if (where < gfxvidinfo.drawbuffer.outheight && where >= 0) + this.pfield_draw_line(null, lineno, where, amiga2aspect_line_map[i + min_ypos_for_screen+1]); + } + } + } + + this.notice_interlace_seen = function(lace) { + var changed = false; + if (lace) { + if (interlace_seen == 0) { + changed = true; + //BUG.info('->lace'); + } + interlace_seen = AMIGA.config.video.vresolution ? 1 : -1; + } else { + if (interlace_seen) { + changed = true; + //BUG.info('->non-lace'); + } + interlace_seen = 0; + } + return changed; + } + + this.notice_screen_contents_lost = function() { + frame_redraw_necessary = 2; + } + + /*---------------------------------*/ + + this.reset_lores = function() { + lores_shift = AMIGA.config.video.hresolution; + if (doublescan > 0) { + if (lores_shift < 2) + lores_shift++; + } + sprite_buffer_res = AMIGA.config.video.hresolution; + if (doublescan > 0 && sprite_buffer_res < RES_SUPERHIRES) + sprite_buffer_res++; + } + + this.bpldmainitdelay = function(hpos) { + var hposa = hpos + (4 + (bplcon0_planes == 8 ? 1 : 0)); //BPLCON_AGNUS_DELAY; + ddf_change = this.vpos; + if (hposa < 0x14) { + this.BPLCON0_Denise(hpos, bplcon0, false); + this.setup_fmodes(hpos); + return; + } + if (bpldmasetuphpos < 0) { + bpldmasetupphase = 0; + bpldmasetuphpos = hpos + BPLCON_DENISE_DELAY; + } + } + + this.update_ddf_change = function() { + ddf_change = this.vpos; + } + + /*---------------------------------*/ + + this.allocsoftbuffer = function(buf, flags, width, height, depth) { + buf.rowbytes = MAX_PIXELS_PER_LINE >> 3; /* for xlinecheck() */ + buf.pixbytes = Math.floor((depth + 7) / 8); + buf.width_allocated = (width + 7) & ~7; + buf.height_allocated = height; + } + + this.setup_drawing = function() { + setup_drawing_tables(); + this.allocsoftbuffer(gfxvidinfo.drawbuffer, 0, VIDEO_WIDTH, VIDEO_HEIGHT, VIDEO_DEPTH); + } + + this.cleanup_drawing = function() {} + + this.reset_drawing = function() { + var i; + max_diwstop = 0; + this.reset_lores(); + for (i = 0; i < linestate.length; i++) linestate[i] = LINE_UNDECIDED; + this.recreate_aspect_maps(); + last_redraw_point = 0; + for (i = 0; i < spixels.length; i++) spixels[i] = 0; //memset(spixels, 0, sizeof spixels); + for (i = 0; i < spixstate.length; i++) spixstate[i] = 0; //memset(&spixstate, 0, sizeof spixstate); + this.init_drawing_frame(); + this.notice_screen_contents_lost(); + //lightpen_y1 = lightpen_y2 = -1; + center_reset = true; + } + + /*-----------------------------------------------------------------------*/ + /* sprites */ + /*-----------------------------------------------------------------------*/ + + function setup_sprite_tables() { + for (var i = 0; i < 256; i++) { + sprtaba[i] = + (((i >> 7) & 1) << 0) + | (((i >> 6) & 1) << 2) + | (((i >> 5) & 1) << 4) + | (((i >> 4) & 1) << 6) + | (((i >> 3) & 1) << 8) + | (((i >> 2) & 1) << 10) + | (((i >> 1) & 1) << 12) + | (((i >> 0) & 1) << 14); + sprtabb[i] = sprtaba[i] << 1; + sprite_ab_merge[i] = ((i & 15) ? 1 : 0) | ((i & 240) ? 2 : 0); + clxtab[i] = + ((((i & 3) && (i & 12)) << 9) | + (((i & 3) && (i & 48)) << 10) | + (((i & 3) && (i & 192)) << 11) | + (((i & 12) && (i & 48)) << 12) | + (((i & 12) && (i & 192)) << 13) | + (((i & 48) && (i & 192)) << 14)); + sprite_offs[i] = (i & 15) ? 0 : 2; + } + for (var i = 0; i < 16; i++) { + clxmask[i] = + ((i & 1) ? 0xF : 0x3) + | ((i & 2) ? 0xF0 : 0x30) + | ((i & 4) ? 0xF00 : 0x300) + | ((i & 8) ? 0xF000 : 0x3000); + sprclx[i] = + (((i & 0x3) == 0x3 ? 1 : 0) + | ((i & 0x5) == 0x5 ? 2 : 0) + | ((i & 0x9) == 0x9 ? 4 : 0) + | ((i & 0x6) == 0x6 ? 8 : 0) + | ((i & 0xA) == 0xA ? 16 : 0) + | ((i & 0xC) == 0xC ? 32 : 0)) << 9; + } + } + + function render_sprites(pos, dualpf, apixel, aga) { + if (!DO_SPRITES) return; //FIXME + var spb = spritepixels[pos]; + var v = spb.data; + var shift_lookup = dualpf ? (bpldualpfpri ? dblpf_ms2 : dblpf_ms1) : dblpf_ms; + var maskshift = shift_lookup[apixel]; + var plfmask = (plf_sprite_mask >>> maskshift) >>> maskshift; + + v &= ~plfmask; + if (v != 0) { //|| SPRITE_DEBUG) { + var vlo, vhi, col; + var v1 = v & 255; + var offs; + if (v1 == 0) + offs = 4 + sprite_offs[v >> 8]; + else + offs = sprite_offs[v1]; + + v >>= offs * 2; + v &= 15; +/*#if SPRITE_DEBUG > 0 + v ^= 8; +#endif*/ + if (spb.attach && (spb.stdata & (3 << offs))) { + col = v; + if (aga) + col += sbasecol[1]; + else + col += 16; + } else { + vlo = v & 3; + vhi = (v & (vlo - 1)) >> 2; + col = (vlo | vhi); + if (aga) { + if (vhi > 0) + col += sbasecol[1]; + else + col += sbasecol[0]; + } else { + col += 16; + } + col += offs * 2; + } + return col; + } + return 0; + } + + function draw_sprites_1(e, dualpf, has_attach) { + //uae_u16 *buf = spixels + e.first_pixel; + //uae_u8 *stbuf = spixstate.bytes + e.first_pixel; + //buf -= e.pos; + //stbuf -= e.pos; + var pos2 = e.first_pixel - e.pos; + + var spr_pos = e.pos + ((DIW_DDF_OFFSET - DISPLAY_LEFT_SHIFT) << sprite_buffer_res); + + if (spr_pos < sprite_first_x) + sprite_first_x = spr_pos; + + for (var pos = e.pos; pos < e.max; pos++, spr_pos++) { + if (spr_pos >= 0 && spr_pos < MAX_PIXELS_PER_LINE) { + //spritepixels[spr_pos].data = buf[pos]; + //spritepixels[spr_pos].stdata = stbuf[pos]; + spritepixels[spr_pos].data = spixels[pos2 + pos]; + spritepixels[spr_pos].stdata = spixstate[pos2 + pos]; + spritepixels[spr_pos].attach = has_attach; + } + } + if (spr_pos > sprite_last_x) + sprite_last_x = spr_pos; + } + + function draw_sprites(e) { + if (!DO_SPRITES) return; //FIXME + draw_sprites_1(e, bpldualpf, e.has_attached); + } + + function ecsshres_func() { + return bplcon0_res == RES_SUPERHIRES && (AMIGA.config.chipset.mask & CSMASK_ECS_DENISE) && !(AMIGA.config.chipset.mask & CSMASK_AGA); + } + + /* handle very rarely needed playfield collision (CLXDAT bit 0) only known game needing this is Rotor */ + this.do_playfield_collisions = function() { + var bplres = bplcon0_res; + var ddf_left = thisline_decision.plfleft * 2 << bplres; + var hw_diwlast = coord_window_to_diw_x(thisline_decision.diwlastword); + var hw_diwfirst = coord_window_to_diw_x(thisline_decision.diwfirstword); + var i, collided, minpos, maxpos; +/*#ifdef AGA + var planes = (currprefs.chipset_mask & CSMASK_AGA) ? 8 : 6; +#else*/ + var planes = 6; +//#endif + + if (clxcon_bpl_enable == 0) { + clxdat |= 1; + return; + } + if (clxdat & 1) + return; + + collided = 0; + minpos = thisline_decision.plfleft * 2; + if (minpos < hw_diwfirst) + minpos = hw_diwfirst; + maxpos = thisline_decision.plfright * 2; + if (maxpos > hw_diwlast) + maxpos = hw_diwlast; + for (i = minpos; i < maxpos && !collided; i+= 32) { + var offs = ((i << bplres) - ddf_left) >> 3; + var j; + var total = 0xffffffff; + for (j = 0; j < planes; j++) { + var ena = (clxcon_bpl_enable >> j) & 1; + var match = (clxcon_bpl_match >> j) & 1; + var t = 0xffffffff; + if (ena) { + if (j < thisline_decision.nr_planes) { + //t = *(uae_u32 *)(line_data[next_lineno] + offs + 2 * j * MAX_WORDS_PER_LINE); + t = line_data[next_lineno][j][offs]; + t ^= (match & 1) - 1; + } else { + t = (match & 1) - 1; + } + } + total &= t; + } + if (total) { + collided = 1; + /*if (1) { //debug + for (var k = 0; k < 1; k++) { + //uae_u32 *ldata = (uae_u32 *)(line_data[next_lineno] + offs + 2 * k * MAX_WORDS_PER_LINE); *ldata ^= 0x5555555555; + line_data[next_lineno][k][offs] ^= 0x5555555555; + } + }*/ + } + } + if (collided) + clxdat |= 1; + } + + /* Sprite-to-sprite collisions are taken care of in record_sprite. This one does playfield/sprite collisions. */ + this.do_sprite_collisions = function() { + var nr_sprites = curr_drawinfo[next_lineno].nr_sprites; + var first = curr_drawinfo[next_lineno].first_sprite_entry; + var collision_mask = clxmask[clxcon >> 12]; + var bplres = bplcon0_res; + var ddf_left = thisline_decision.plfleft * 2 << bplres; + var hw_diwlast = coord_window_to_diw_x(thisline_decision.diwlastword); + var hw_diwfirst = coord_window_to_diw_x(thisline_decision.diwfirstword); + + if (clxcon_bpl_enable == 0) { + clxdat |= 0x1fe; + return; + } + + for (var i = 0; i < nr_sprites; i++) { + var e = curr_sprite_entries[first + i]; + var minpos = e.pos; + var maxpos = e.max; + var minp1 = minpos >> sprite_buffer_res; + var maxp1 = maxpos >> sprite_buffer_res; + + if (maxp1 > hw_diwlast) + maxpos = hw_diwlast << sprite_buffer_res; + if (maxp1 > thisline_decision.plfright * 2) + maxpos = thisline_decision.plfright * 2 << sprite_buffer_res; + if (minp1 < hw_diwfirst) + minpos = hw_diwfirst << sprite_buffer_res; + if (minp1 < thisline_decision.plfleft * 2) + minpos = thisline_decision.plfleft * 2 << sprite_buffer_res; + + for (var j = minpos; j < maxpos; j++) { + var sprpix = spixels[e.first_pixel + j - e.pos] & collision_mask; + + if (sprpix == 0) + continue; + + var match = 1; + var offs = ((j << bplres) >> sprite_buffer_res) - ddf_left; + sprpix = (sprite_ab_merge[sprpix & 255] | (sprite_ab_merge[sprpix >> 8] << 2)) << 1; + + for (var k = 1; k >= 0; k--) { +/*#ifdef AGA + var planes = (currprefs.chipset_mask & CSMASK_AGA) ? 8 : 6; +#else*/ + var planes = 6; +//#endif + if (bplcon0 & 0x400) + match = 1; + for (var l = k; match && l < planes; l += 2) { + var t = 0; + if (l < thisline_decision.nr_planes) { + //uae_u32 *ldata = (uae_u32 *)(line_data[next_lineno] + 2 * l * MAX_WORDS_PER_LINE); var word = ldata[offs >> 5]; + var word = line_data[next_lineno][l][offs >> 5]; + t = (word >>> (31 - (offs & 31))) & 1; + /*if (1) { //debug: draw collision mask + for (var m = 0; m < 5; m++) { + //uae_u32 *ldata = (uae_u32 *)(line_data[next_lineno] + 2 * m * MAX_WORDS_PER_LINE); ldata[(offs >> 5) + 1] |= 15 << (31 - (offs & 31)); + line_data[next_lineno][m][(offs >> 5) + 0] |= 15 << (31 - (offs & 31)); + } + }*/ + } + if (clxcon_bpl_enable & (1 << l)) { + if (t != ((clxcon_bpl_match >> l) & 1)) + match = 0; + } + } + if (match) { + /*if (1) { //debug: mark lines where collisions are detected + for (var l = 0; l < 5; l++) { + //uae_u32 *ldata = (uae_u32 *)(line_data[next_lineno] + 2 * l * MAX_WORDS_PER_LINE); ldata[(offs >> 5) + 1] |= 15 << (31 - (offs & 31)); + line_data[next_lineno][l][(offs >> 5) + 0] |= 15 << (31 - (offs & 31)); + } + }*/ + clxdat |= (sprpix << (k * 4)); + } + } + } + } + /*{ + static var olx; + if (clxdat != olx) BUG.info('%d: %04x', vpos, clxdat); + olx = clxdat; + }*/ + } + + this.record_sprite_1 = function(sprxp, buf, datab, num, dbl, mask, do_collisions, collision_mask) { var j = 0; + while (datab) { var col = 0; var coltmp = 0; - //if ((sprxp >= this.sprite_minx && sprxp < this.sprite_maxx) || (AMIGA.playfield.bplcon3 & 2)) + if ((sprxp >= sprite_minx && sprxp < sprite_maxx) || (bplcon3 & 2)) col = (datab & 3) << (2 * num); - /*if (0) { - if (sprxp == this.sprite_minx || sprxp == this.sprite_maxx - 1) - col ^= (rand () << 16) | rand (); - }*/ - //if ((j & mask) == 0) - { - var tmp = spr_data[bufpos] | col; - spr_data[bufpos++] = tmp; - if (do_collisions) coltmp |= tmp; - //sprxp++; + + //if (sprxp == sprite_minx || sprxp == sprite_maxx - 1) col ^= Math.floor(Math.random() * 0xffffffff); + + if ((j & mask) == 0) { + //var tmp = (*buf) | col; *buf++ = tmp; + var tmp = spixels[buf] | col; spixels[buf++] = tmp; + if (do_collisions) + coltmp |= tmp; + sprxp++; } if (dbl > 0) { - var tmp = spr_data[bufpos] | col; - spr_data[bufpos++] = tmp; - if (do_collisions) coltmp |= tmp; - //sprxp++; + //var tmp = (*buf) | col; *buf++ = tmp; + var tmp = spixels[buf] | col; spixels[buf++] = tmp; + if (do_collisions) + coltmp |= tmp; + sprxp++; + } + if (dbl > 1) { + var tmp; + //tmp = (*buf) | col; *buf++ = tmp; + tmp = spixels[buf] | col; spixels[buf++] = tmp; + if (do_collisions) + coltmp |= tmp; + //tmp = (*buf) | col; *buf++ = tmp; + tmp = spixels[buf] | col; spixels[buf++] = tmp; + if (do_collisions) + coltmp |= tmp; + sprxp++; + sprxp++; } j++; datab >>>= 2; @@ -221,988 +2934,639 @@ function Sprites() { coltmp &= collision_mask; if (coltmp) { var shrunk_tmp = sprite_ab_merge[coltmp & 255] | (sprite_ab_merge[coltmp >> 8] << 2); - this.clxdat |= sprclx[shrunk_tmp]; + clxdat |= sprclx[shrunk_tmp]; } } } } + + //this.record_sprite = function(line, num, sprxp, data, datb, ctl) { + this.record_sprite = function(line, num, sprxp) { + var e = curr_sprite_entries[next_sprite_entry]; + var word_offs; + var collision_mask; + var width, dbl, half; + var mask = 0; + var attachment; + var i; + + //var data = 0, datb = 0; + var this_sprite_entry = next_sprite_entry; + var num2 = 0; - this.draw = function() { - //if (this.nr_armed == 0) return; + half = 0; + dbl = sprite_buffer_res - sprres; + if (dbl < 0) { + half = -dbl; + dbl = 0; + mask = 1 << half; + } + width = (sprite_width << sprite_buffer_res) >> sprres; + attachment = sprctl[num | 1] & 0x80; + + /* Try to coalesce entries if they aren't too far apart */ + //if (!next_sprite_forced && e[-1].max + sprite_width >= sprxp) { + if (this_sprite_entry > 0 && !next_sprite_forced && curr_sprite_entries[this_sprite_entry - 1].max + sprite_width >= sprxp) { + //e--; + e = curr_sprite_entries[this_sprite_entry - 1]; + this_sprite_entry--; + //console.log('RS',this_sprite_entry); + } else { + next_sprite_entry++; + e.pos = sprxp; + e.has_attached = 0; + } + if (sprxp < e.pos) + Fatal(333, 'sprxp < e->pos'); + + e.max = sprxp + width; + //e[1].first_pixel = e.first_pixel + ((e.max - e.pos + 3) & ~3); + curr_sprite_entries[this_sprite_entry + 1].first_pixel = e.first_pixel + ((e.max - e.pos + 3) & ~3); + next_sprite_forced = 0; + + collision_mask = clxmask[clxcon >> 12]; + word_offs = e.first_pixel + sprxp - e.pos; + + for (i = 0; i < sprite_width; i += 16) { + //var da = *data; + //var db = *datb; + //var da = sprdata[data][0]; + //var db = sprdatb[datb][0]; + var da = sprdata[num][num2]; + var db = sprdatb[num][num2]; + var datab = ((sprtaba[da & 0xFF] << 16) | sprtaba[da >> 8] | (sprtabb[db & 0xFF] << 16) | sprtabb[db >> 8]) >>> 0; + var off = (i << dbl) >> half; + //uae_u16 *buf = spixels + word_offs + off; + var buf = word_offs + off; + if (AMIGA.config.chipset.collision_level > 0 && collision_mask) + this.record_sprite_1(sprxp + off, buf, datab, num, dbl, mask, 1, collision_mask); + else + this.record_sprite_1(sprxp + off, buf, datab, num, dbl, mask, 0, collision_mask); + + //*data++; *datb++; + num2++; + } + + /* We have 8 bits per pixel in spixstate, two for every sprite pair. + The low order bit records whether the attach bit was set for this pair. */ + if (attachment && !ecsshres_func()) { + var state = ((0x01010101 << (num & ~1)) >>> 0) & 0xff; + /*uae_u8 *stb1 = spixstate.bytes + word_offs; + for (i = 0; i < width; i += 8) { + stb1[0] |= state; + stb1[1] |= state; + stb1[2] |= state; + stb1[3] |= state; + stb1[4] |= state; + stb1[5] |= state; + stb1[6] |= state; + stb1[7] |= state; + stb1 += 8; + }*/ + var stb1 = word_offs; + for (i = 0; i < width; i += 8) { + spixstate[stb1 + 0] |= state; + spixstate[stb1 + 1] |= state; + spixstate[stb1 + 2] |= state; + spixstate[stb1 + 3] |= state; + spixstate[stb1 + 4] |= state; + spixstate[stb1 + 5] |= state; + spixstate[stb1 + 6] |= state; + spixstate[stb1 + 7] |= state; + stb1 += 8; + } + e.has_attached = 1; + } + } + + function tospritexdiw(diw) { + return coord_window_to_hw_x(diw - (DIW_DDF_OFFSET << lores_shift)) << sprite_buffer_res; + } + function tospritexddf(ddf) { + return (ddf << 1) << sprite_buffer_res; + } + function fromspritexdiw(ddf) { + return coord_hw_to_window_x(ddf >> sprite_buffer_res) + (DIW_DDF_OFFSET << lores_shift); + } + + function calcsprite() { + sprite_maxx = 0x7fff; + sprite_minx = 0; + if (thisline_decision.diwlastword >= 0) + sprite_maxx = tospritexdiw(thisline_decision.diwlastword); + if (thisline_decision.diwfirstword >= 0) + sprite_minx = tospritexdiw(thisline_decision.diwfirstword); + if (thisline_decision.plfleft >= 0) { + var min = tospritexddf(thisline_decision.plfleft); + var max = tospritexddf(thisline_decision.plfright); + if (min > sprite_minx && min < max) /* min < max = full line ddf */ + sprite_minx = min; + } + } + + function add_sprite(count, num, sprxp, posns, nrs) { + var bestp, j; + for (bestp = 0; bestp < count; bestp++) { + if (posns[bestp] > sprxp) + break; + if (posns[bestp] == sprxp && nrs[bestp] < num) + break; + } + for (j = count; j > bestp; j--) { + posns[j] = posns[j - 1]; + nrs[j] = nrs[j - 1]; + } + posns[j] = sprxp; + nrs[j] = num; + } + + this.decide_sprites = function(hpos) { + if (!DO_SPRITES) return; //FIXME var nrs = [], posns = []; - var count = 0; - var xoffs = (180 - (AMIGA.playfield.state.hlen >> 1)) << (AMIGA.playfield.state.hires ? 1 : 0); + var point = hpos * 2 - 3; + var width = sprite_width; + var sscanmask = 0x100 << sprite_buffer_res; + var gotdata = 0; + var count, i; - for (var i = 0; i < MAX_SPRITES; i++) { - var sprxp = xoffs + ((this.sprite[i].xpos - AMIGA.playfield.state.hstart) << (AMIGA.playfield.state.hires ? 1 : 0)); + if (thisline_decision.plfleft < 0 && !(bplcon3 & 2)) + return; - if (!this.sprite[i].armed || sprxp < 0) continue; + if (this.nodraw() || hpos < 0x14 || nr_armed == 0 || point == last_sprite_point) + return; - var j, bestp; + this.decide_diw(hpos); + this.decide_line(hpos); - for (bestp = 0; bestp < count; bestp++) { - if (posns[bestp] > sprxp) break; - if (posns[bestp] == sprxp && nrs[bestp] < i) break; + calcsprite(); + + for (i = 0; i < MAX_SPRITES * 2; i++) + nrs[i] = posns[i] = 0; + + count = 0; + for (i = 0; i < MAX_SPRITES; i++) { + var sprxp = (fmode & 0x8000) ? (spr[i].xpos & ~sscanmask) : spr[i].xpos; + var hw_xp = sprxp >> sprite_buffer_res; + + if (!spr[i].armed || spr[i].xpos < 0) + continue; + /*if (!((debug_sprite_mask & magic_sprite_mask) & (1 << i))) + continue;*/ + + if (hw_xp > last_sprite_point && hw_xp <= point) + add_sprite(count++, i, sprxp, posns, nrs); + + if ((fmode & 0x8000) && !(sprxp & sscanmask)) { + sprxp |= sscanmask; + hw_xp = sprxp >> sprite_buffer_res; + if (hw_xp > last_sprite_point && hw_xp <= point) + add_sprite(count++, MAX_SPRITES + i, sprxp, posns, nrs); } - for (j = count; j > bestp; j--) { - posns[j] = posns[j - 1]; - nrs[j] = nrs[j - 1]; - } - posns[j] = sprxp; - nrs[j] = i; - count++; - } - //if (count) { for (i = 0; i < count; i++) BUG.info('SPR n %d, x %d', nrs[i], posns[i]); BUG.info('------------'); } - - var collision_mask = clxmask[this.clxcon >> 12]; - + } for (i = 0; i < count; i++) { - var sprxp = posns[i]; - var nr = nrs[i]; - var attachment = this.sprite[nr | 1].ctl & 0x80; - var da = this.sprite[nr].data; - var db = this.sprite[nr].datb; - var datab = ((sprtaba[da & 0xFF] << 16) | sprtaba[da >> 8] | (sprtabb[db & 0xFF] << 16) | sprtabb[db >> 8]); - var dbl = AMIGA.playfield.state.hires ? 1 : 0; - var mask = 0; - - if (AMIGA.config.chipset.colLevel != SAEV_Config_Chipset_ColLevel_None && collision_mask) this.draw_1(sprxp, sprxp, datab, nr, dbl, mask, 1, collision_mask); - else this.draw_1(sprxp, sprxp, datab, nr, dbl, mask, 0, collision_mask); - - if (attachment) { - var state = (1 << (nr & ~1)) & 0xff; - for (j = 0; j < 16; j++) { - spr_state[sprxp + j] |= state; - spr_attach[sprxp + j] = true; + var nr = nrs[i] & (MAX_SPRITES - 1); + //this.record_sprite(next_lineno, nr, posns[i], sprdata[nr], sprdatb[nr], sprctl[nr]); + this.record_sprite(next_lineno, nr, posns[i]); + + /* get left and right sprite edge if brdsprt enabled */ +/*#if AUTOSCALE_SPRITES + if (AMIGA.dmaen(DMAF_SPREN) && (bplcon0 & 1) && (bplcon3 & 0x02) && !(bplcon3 & 0x20) && nr > 0) { + var j, jj; + for (j = 0, jj = 0; j < sprite_width; j+= 16, jj++) { + var nx = fromspritexdiw (posns[i] + j); + if (sprdata[nr][jj] || sprdatb[nr][jj]) { + if (diwfirstword_total > nx && nx >= (48 << currprefs.hresolution)) + diwfirstword_total = nx; + if (diwlastword_total < nx + 16 && nx <= (448 << currprefs.hresolution)) + diwlastword_total = nx + 16; + } } + gotdata = 1; } +#endif*/ } - } + last_sprite_point = point; - this.sprite_fetch = function(n, dma, hpos, cycle, mode) { + /* get upper and lower sprite position if brdsprt enabled */ +/*#if AUTOSCALE_SPRITES + if (gotdata) { + if (vpos < first_planes_vpos) + first_planes_vpos = vpos; + if (vpos < plffirstline_total) + plffirstline_total = vpos; + if (vpos > last_planes_vpos) + last_planes_vpos = vpos; + if (vpos > plflastline_total) + plflastline_total = vpos; + } +#endif*/ + } + + this.cursorsprite = function() { + if (!AMIGA.dmaen(DMAF_SPREN) || first_planes_vpos == 0) + return; + sprite_0 = spr[0].pt; + sprite_0_height = spr[0].vstop - spr[0].vstart; + sprite_0_colors[0] = 0; + sprite_0_doubled = 0; + if (sprres == 0) + sprite_0_doubled = 1; + if (AMIGA.config.chipset.mask & CSMASK_AGA) { + var sbasecol = ((bplcon4 >> 4) & 15) << 4; + sprite_0_colors[1] = current_colors.color_regs_aga[sbasecol + 1]; + sprite_0_colors[2] = current_colors.color_regs_aga[sbasecol + 2]; + sprite_0_colors[3] = current_colors.color_regs_aga[sbasecol + 3]; + } else { + sprite_0_colors[1] = xcolors[current_colors.color_regs_ecs[17]]; + sprite_0_colors[2] = xcolors[current_colors.color_regs_ecs[18]]; + sprite_0_colors[3] = xcolors[current_colors.color_regs_ecs[19]]; + } + sprite_0_width = sprite_width; + /*if (currprefs.input_tablet && currprefs.input_magic_mouse) { + if (currprefs.input_magic_mouse_cursor == MAGICMOUSE_HOST_ONLY && mousehack_alive ()) + magic_sprite_mask &= ~1; + else + magic_sprite_mask |= 1; + }*/ + } + + function sprite_fetch(s, dma, hpos, cycle, mode) { var data = AMIGA.custom.last_value; - if (dma) - data = AMIGA.mem.load16_chip(this.sprite[n].pt); - this.sprite[n].pt += 2; + if (dma) { + //data = AMIGA.mem.load16_chip(s.pt); + data = AMIGA.custom.last_value = AMIGA.mem.chip.data[s.pt >>> 1]; + } + s.pt += 2; + return data; + } + function sprite_fetch2(s, hpos, cycle, mode) { + //var data = AMIGA.mem.load16_chip(s.pt); + var data = AMIGA.custom.last_value = AMIGA.mem.chip.data[s.pt >>> 1]; + s.pt += 2; return data; } - this.cycle_1 = function (vp, n, cycle, hpos) { - var isdma = AMIGA.dmaen(DMAF_SPREN) || ((n & 1) && this.sprite[n & ~1].dmacycle); + this.do_sprites_1 = function(num, cycle, hpos) { + var s = spr[num]; + var isdma = AMIGA.dmaen(DMAF_SPREN) || ((num & 1) && spr[num & ~1].dmacycle); - if (isdma && vp == sprite_vblank_endline) this.sprArm(n, 0); - - if (vp == this.sprite[n].vstart) { - this.sprite[n].dmastate = 1; - //if (n == 0 && cycle == 0) cursorsprite(); + if (isdma && this.vpos == sprite_vblank_endline) + spr_arm(num, 0); +/*#ifdef AGA + if (isdma && s.dblscan && (fmode & 0x8000) && (this.vpos & 1) != (s.vstart & 1) && s.dmastate) { + spr_arm(num, 1); + return; } - if (vp == this.sprite[n].vstop || vp == sprite_vblank_endline) { - this.sprite[n].dmastate = 0; - if (1) { - // roots 2.0 flower zoomer bottom part missing if this enabled - if (vp == this.sprite[n].vstop) { - this.sprArm(n, 0); - //return; - } +#endif*/ + + //if (this.vpos >= SPRITE_DEBUG_MINY && this.vpos <= SPRITE_DEBUG_MAXY) BUG.info('%d:%d:slot%d:%d', this.vpos, hpos, num, cycle); + + if (this.vpos == s.vstart) { + //if (!s.dmastate && this.vpos >= SPRITE_DEBUG_MINY && this.vpos <= SPRITE_DEBUG_MAXY) BUG.info('%d:%d:SPR%d START', this.vpos, hpos, num); + s.dmastate = 1; + if (num == 0 && cycle == 0) + this.cursorsprite(); + } + if (this.vpos == s.vstop || this.vpos == sprite_vblank_endline) { + //if (s.dmastate && this.vpos >= SPRITE_DEBUG_MINY && this.vpos <= SPRITE_DEBUG_MAXY) BUG.info('%d:%d:SPR%d STOP', this.vpos, hpos, num); + s.dmastate = 0; +/*#if 0 + // roots 2.0 flower zoomer bottom part missing if this enabled + if (this.vpos == s.vstop) { + spr_arm (num, 0); + //return; } +#endif*/ } - if (!isdma) return; - if (cycle && !this.sprite[n].dmacycle) return; /* Superfrog intro flashing bee fix */ + if (!isdma) + return; + if (cycle && !s.dmacycle) + return; /* Superfrog intro flashing bee fix */ - var dma = hpos < AMIGA.playfield.state.dstart; + var dma = hpos < plfstrt_sprite || diwstate != DIW_WAITING_STOP; var posctl = 0; - if (vp == this.sprite[n].vstop || vp == sprite_vblank_endline) { - this.sprite[n].dmastate = 0; + if (this.vpos == s.vstop || this.vpos == sprite_vblank_endline) { + s.dmastate = 0; posctl = 1; if (dma) { - var data = this.sprite_fetch(n, dma, hpos, cycle, 0); - + var data = sprite_fetch(s, dma, hpos, cycle, 0); + switch (sprite_width) { + case 64: + sprite_fetch2(s, hpos, cycle, 0); + sprite_fetch2(s, hpos, cycle, 0); + case 32: + sprite_fetch2(s, hpos, cycle, 0); + break; + } + //BUG.info('%d:%d: %04X=%04X', this.vpos, hpos, 0x140 + cycle * 2 + num * 8, data); if (cycle == 0) { - this.SPRxPOS(data, n); - this.sprite[n].dmacycle = 1; + this.SPRxPOS_1(data, num, hpos); + s.dmacycle = 1; } else { - this.SPRxCTL(data, n); - this.sprite[n].dmastate = 0; - this.sprStartStop(n); + this.SPRxCTL_1(data, num, hpos); + s.dmastate = 0; + this.sprstartstop(s); } } + //if (this.vpos >= SPRITE_DEBUG_MINY && this.vpos <= SPRITE_DEBUG_MAXY) BUG.info('%d:%d:dma:P=%06X '), this.vpos, hpos, s.pt); } - if (this.sprite[n].dmastate && !posctl && dma) { - var data = this.sprite_fetch(n, dma, hpos, cycle, 1); - + if (s.dmastate && !posctl && dma) { + var data = sprite_fetch(s, dma, hpos, cycle, 1); + //if (this.vpos >= SPRITE_DEBUG_MINY && this.vpos <= SPRITE_DEBUG_MAXY) BUG.info('%d:%d:dma:P=%06X '), this.vpos, hpos, s.pt); if (cycle == 0) { - this.SPRxDATA(data, n); - this.sprite[n].dmacycle = 1; + this.SPRxDATA_1(data, num, hpos); + s.dmacycle = 1; } else { - this.SPRxDATB(data, n); - this.sprArm(n, 1); + this.SPRxDATB_1(data, num, hpos); + spr_arm(num, 1); } +/*#ifdef AGA + switch (sprite_width) { + case 64: { + var data32 = sprite_fetch2 (s, hpos, cycle, 1); + var data641 = sprite_fetch2 (s, hpos, cycle, 1); + var data642 = sprite_fetch2 (s, hpos, cycle, 1); + if (dma) { + if (cycle == 0) { + sprdata[num][3] = data642; + sprdata[num][2] = data641; + sprdata[num][1] = data32; + } else { + sprdatb[num][3] = data642; + sprdatb[num][2] = data641; + sprdatb[num][1] = data32; + } + } + } + break; + case 32: { + var data32 = sprite_fetch2 (s, hpos, cycle, 1); + if (dma) { + if (cycle == 0) + sprdata[num][1] = data32; + else + sprdatb[num][1] = data32; + } + } + break; + } +#endif*/ } } - this.cycle = function (hpos) { - var vp = AMIGA.events.vpos; - if (vp < sprite_vblank_endline) return; + this.do_sprites = function(hpos) { + if (!DO_SPRITES) return; //FIXME + if (this.vpos < sprite_vblank_endline) + return; - for (var i = 0; i < MAX_SPRITES * 2; i++) { - this.sprite[i >> 1].dmacycle = 1; - this.cycle_1(vp, i >> 1, i & 1, 0); + if (this.doflickerfix() && interlace_seen && (next_lineno & 1)) + return; + + if (!CUSTOM_SIMPLE) { + var minspr = last_sprite_hpos + 1; + var maxspr = hpos; + + if (minspr >= maxspr || last_sprite_hpos == hpos) + return; + + if (maxspr >= SPR0_HPOS + MAX_SPRITES * 4) + maxspr = SPR0_HPOS + MAX_SPRITES * 4 - 1; + if (minspr < SPR0_HPOS) + minspr = SPR0_HPOS; + + if (minspr == maxspr) + return; + + for (var i = minspr; i <= maxspr; i++) { + var cycle = -1; + var num = (i - SPR0_HPOS) >> 2; + switch ((i - SPR0_HPOS) & 3) { + case 0: + cycle = 0; + spr[num].dmacycle = 0; + break; + case 2: + cycle = 1; + break; + } + if (cycle >= 0) { + spr[num].ptxhpos = MAXHPOS; + this.do_sprites_1(num, cycle, i); + } + } + last_sprite_hpos = hpos; + } else { + for (var i = 0; i < MAX_SPRITES * 2; i++) { + spr[i >> 1].dmacycle = 1; + this.do_sprites_1(i >> 1, i & 1, 0); + } + } + } + + function expand_sprres(con0, con3) { + switch ((con3 >> 6) & 3) { + case 0: { + if ((AMIGA.config.chipset.mask & CSMASK_ECS_DENISE) && GET_RES_DENISE(con0) == RES_SUPERHIRES) + return RES_HIRES; + else + return RES_LORES; + } +/*#ifdef AGA + case 1: + return RES_LORES; + case 2: + return RES_HIRES; + case 3: + return RES_SUPERHIRES; +#endif*/ + default: + return RES_LORES; } } - this.sprArm = function (n, state) { + function spr_arm(num, state) { switch (state) { case 0: - this.nr_armed -= this.sprite[n].armed; - this.sprite[n].armed = 0; + nr_armed -= spr[num].armed; + spr[num].armed = 0; break; default: - this.nr_armed += 1 - this.sprite[n].armed; - this.sprite[n].armed = 1; - } + nr_armed += 1 - spr[num].armed; + spr[num].armed = 1; + break; + } } - this.sprStartStop = function (n) { - if (AMIGA.events.vpos + 1 == this.sprite[n].vstart) this.sprite[n].dmastate = 1; - if (AMIGA.events.vpos + 1 == this.sprite[n].vstop) this.sprite[n].dmastate = 0; + this.sprstartstop = function(s) { + if (this.vpos == s.vstart) + s.dmastate = 1; + if (this.vpos == s.vstop) + s.dmastate = 0; } - this.SPRxCTLPOS = function (n) { - this.sprStartStop(n); - - this.sprite[n].xpos = (this.sprite[n].pos & 0xff) * 2 + (this.sprite[n].ctl & 1); - this.sprite[n].vstart = (this.sprite[n].pos >> 8) | ((this.sprite[n].ctl << 6) & 0x100); - this.sprite[n].vstop = (this.sprite[n].ctl >> 8) | ((this.sprite[n].ctl << 7) & 0x100); - /*if (AMIGA.config.chipset.type == SAEV_Config_Chipset_Type_ECS) { - this.sprite[n].vstart |= (this.sprite[n].ctl << 3) & 0x200; - this.sprite[n].vstop |= (this.sprite[n].ctl << 4) & 0x200; - }*/ - this.sprStartStop(n); - } - - this.SPRxCTL = function (v, n) { - this.sprite[n].ctl = v; - this.sprArm(n, 0); - this.SPRxCTLPOS(n); - } - - this.SPRxPOS = function (v, n) { - this.sprite[n].pos = v; - this.SPRxCTLPOS(n); - } - - this.SPRxDATA = function (v, n) { - this.sprite[n].data = v; - this.sprArm(n, 1); - } - - this.SPRxDATB = function (v, n) { - this.sprite[n].datb = v; - } - - this.SPRxPTH = function (v, n) { - this.sprite[n].pt = ((v << 16) | (this.sprite[n].pt & 0xffff)) >>> 0; - } - - this.SPRxPTL = function (v, n) { - this.sprite[n].pt = ((this.sprite[n].pt & 0xffff0000) | v) >>> 0; - } - - this.CLXCON = function (v) { - this.clxcon = v; + this.CLXCON = function(v) { + clxcon = v; clxcon_bpl_enable = (v >> 6) & 63; clxcon_bpl_match = v & 63; } + this.CLXCON2 = function(v) { + if (!(AMIGA.config.chipset.mask & CSMASK_AGA)) + return; + clxcon2 = v; + clxcon_bpl_enable |= v & (0x40 | 0x80); + clxcon_bpl_match |= (v & (0x01 | 0x02)) << 6; + } + this.CLXDAT = function() { - var v = this.clxdat | 0x8000; - this.clxdat = 0; + var v = clxdat | 0x8000; + clxdat = 0; return v; } -} - -function Plane(num) { - this.num = num; - this.pt = 0; - this.dat = -1; - this.line = new Uint16Array(45); -} - -function Playfield() { - /* BPLCON0 flags */ - const BPLF_ERSY = 1 << 1; - const BPLF_LACE = 1 << 2; - const BPLF_LPEN = 1 << 3; - const BPLF_GAUD = 1 << 8; - const BPLF_COLOR = 1 << 9; - const BPLF_DBLPF = 1 << 10; - const BPLF_HOMOD = 1 << 11; - const BPLF_HIRES = 1 << 15; - /* BPLCON2 flags */ - const BPLF_PF2PRI = 1 << 6; - - this.sprites = new Sprites(); - - this.plane = new Array(6); - for (var i = 0; i < 6; i++) - this.plane[i] = new Plane(i); - - this.color_std = new Uint16Array(32); - this.color_ehb = new Uint16Array(32); - for (var i = 0; i < 32; i++) this.color_std[i] = this.color_ehb[i] = 0; - - this.linedata = []; - - this.bplcon0 = 0; - this.bplcon1 = 0; - this.bplcon2 = 0; - this.bplcon3 = 0; - - this.bpl1mod = 0; - this.bpl2mod = 0; - - this.diwstrt = 0; - this.diwstop = 0; - this.diwhigh = -1; //ECS - this.ddfstrt = 0; - this.ddfstop = 0; - - this.state = { - vstart: 0, - vstop: 0, - vlen: 0, - vlenreal: 0, - vlenrealset: 0, - vlenrealtmp: 0, - hstart: 0, - hstop: 0, - hlen: 0, - hnum: 0, - hpixel: 0, - hleft: 0, - dstart: 0, - dstop: 0, - dlen: 0, - dnum: 0, - dwords: 0, - ddiff: 0, - altget: false, - hires: false, - ilace: false, - std: false, - ehb: false, - dpf: false, - ham: false, - planes: 0, - delay1: 0, - delay2: 0, - pf2pri: false, - pf1p: 0, - pf2p: 0, - colorOnly: true, - hScale: true, - vScale: true, - }; - - this.frame = { - skip: false, - skipcount: 0, - count: 0 - }; - - /* for playfield development */ - /*this.lamps = function() { - var e = document.getElementById('lamp_hir'); - if (e) e.style.color = this.state.hires ? '#8c8' : '#888'; - e = document.getElementById('lamp_ila'); - if (e) e.style.color = this.state.ilace ? '#8c8' : '#888'; - e = document.getElementById('lamp_dpf'); - if (e) e.style.color = this.state.dpf ? '#8c8' : '#888'; - e = document.getElementById('lamp_ham'); - if (e) e.style.color = this.state.ham ? '#8c8' : '#888'; - e = document.getElementById('lamp_ehb'); - if (e) e.style.color = this.state.ehb ? '#8c8' : '#888'; - e = document.getElementById('lamp_scr'); - if (e) e.style.color = this.state.altget ? '#8c8' : '#888'; - e = document.getElementById('lamp_p2p'); - if (e) e.style.color = this.state.pf2pri ? '#8c8' : '#888'; - e = document.getElementById('lamp_nPl'); - if (e) e.innerHTML = this.state.planes; - e = document.getElementById('lamp_dl1'); - if (e) e.innerHTML = sprintf('%02d', this.state.delay1); - e = document.getElementById('lamp_dl2'); - if (e) e.innerHTML = sprintf('%02d', this.state.delay2); - //if (this.state.hlen > 0 && this.state.hlen <= 720 && this.state.vlen > 0 && this.state.vlen <= 288) - { - e = document.getElementById('lamp_diw'); - if (e) e.innerHTML = sprintf('%dx%d', this.state.hlen, this.state.vlenreal); - } - e = document.getElementById('lamp_dff'); - if (e) e.innerHTML = sprintf('%d (%d)', this.state.dlen, this.state.ddiff); - }*/ - - this.setup = function() { - this.create_cycle_diagram_table(); - this.sprites.setup(); - } + this.SPRxCTLPOS = function(num) { + var sprxp; + var s = spr[num]; - this.cleanup = function() { - this.sprites.cleanup(); - } - - this.reset = function() { - this.state.colorOnly = true; - this.state.hScale = true; - this.state.vScale = true; - - for (var i = 0; i < 32; i++) - this.color_std[i] = this.color_ehb[i] = 0; - - this.frame.skip = false; - this.frame.skipcount = 0; - } - - this.recalc = function() { - this.state.vlen = this.state.vstop - this.state.vstart; - this.state.hlen = this.state.hstop - this.state.hstart; - this.state.hnum = this.state.hlen >> 3; - - this.state.dlen = (this.state.dstop - this.state.dstart + 15) & ~7; - this.state.dnum = this.state.dlen >> 3; - this.state.ddiff = (this.state.dnum << 1) - this.state.hnum; - if (this.state.ddiff < 0) this.state.ddiff = 0; - - //this.state.hlen = this.state.dlen << 1; - - this.state.hpixel = this.state.hlen << (this.state.hires ? 1 : 0); - this.state.hleft = (180 - Math.min(this.state.hlen >> 1, this.state.dlen)) << (this.state.hires ? 1 : 0); - this.state.dwords = this.state.dnum << (this.state.hires ? 1 : 0); - - this.state.altget = this.state.ddiff != 0 && ((this.state.dstart >> 3) & 1) != 0; - - //this.lamps(); - } - - this.calcdiw = function() { - this.state.vstart = this.diwstrt >> 8; - this.state.vstop = this.diwstop >> 8; - this.state.hstart = this.diwstrt & 0xff; - this.state.hstop = this.diwstop & 0xff; - this.state.hstart &= ~7; - this.state.hstop &= ~7; - - if (AMIGA.config.chipset.type == SAEV_Config_Chipset_Type_ECS && this.diwhigh != -1) { - this.state.vstart |= (this.diwhigh & 7) << 8; - this.state.vstop |= ((this.diwhigh >> 8) & 7) << 8; - this.state.hstart |= ((this.diwhigh >> 5) & 1) << 8; - this.state.hstop |= ((this.diwhigh >> 13) & 1) << 8; - } else { - if ((this.state.vstop & 0x80) == 0) this.state.vstop |= 0x100; - this.state.hstop += 0x100; - } - - this.recalc(); - //BUG.info('Playfield.calcdiw() diwstrt $%04x diwstop $%04x | v %d-%d, h %d-%d | %d x %d', this.diwstrt, this.diwstop, this.state.vstart, this.state.vstop, this.state.hstart, this.state.hstop, this.state.hlen, this.state.vlen); - } - - this.calcddf = function(stop) { - this.state.dstart = this.ddfstrt & 0xff; - this.state.dstop = this.ddfstop & 0xff; - this.state.dstart &= ~3; - this.state.dstop &= ~3; - - if (this.state.dstart < 0x18) this.state.dstart = 0x18; - if (this.state.dstop > 0xd8) this.state.dstop = 0xd8; - - /*if (AMIGA.config.chipset.type == SAEV_Config_Chipset_Type_ECS) { - if (this.state.dstop > AMIGA.events.maxhpos) this.state.dstart = 0; - if (this.state.dstart < 0x18) this.state.dstart = 0x18; - } else { - if (this.state.dstart >= this.state.dstop && this.state.dstart >= 0x18) this.state.dstop = 0xff; - }*/ - - this.recalc(); - //BUG.info('Playfield.calcddf() ddfstrt $%04x ddfstop $%04x | plflinelen %d', this.ddfstrt, this.ddfstop, this.state.dlen); - } - - - this.drawpixel = function (xpos, ypos, rgb) { - /*if (this.state.ilace) { - if (this.state.hires) - AMIGA.video.drawpixel(xpos, ypos, rgb); - else { - AMIGA.video.drawpixel(xpos*2, ypos, rgb); - AMIGA.video.drawpixel(xpos*2+1, ypos, rgb); - } - } else { - if (this.state.hires) { - AMIGA.video.drawpixel(xpos, ypos*2, rgb); - AMIGA.video.drawpixel(xpos, ypos*2+1, rgb); - } else { - AMIGA.video.drawpixel(xpos*2, ypos*2, rgb); - AMIGA.video.drawpixel(xpos*2+1, ypos*2, rgb); - AMIGA.video.drawpixel(xpos*2, ypos*2+1, rgb); - AMIGA.video.drawpixel(xpos*2+1, ypos*2+1, rgb); - } - }*/ - - if (this.state.hires) - AMIGA.video.drawpixel(xpos, ypos, rgb); - else - AMIGA.video.draw2pixel(xpos << 1, ypos, rgb); - } - this.drawpixel_std = function (xpos, ypos, col) { - var spritecol = this.sprites.render(xpos, col); - var rgb = this.color_std[spritecol ? spritecol : col]; - this.linedata[xpos] = col; - //AMIGA.video.drawpixel(xpos, ypos, rgb); - this.drawpixel(xpos, ypos, rgb); - } - - this.drawpixel_ehb = function (xpos, ypos, col, ehb) { - var rgb; - var spritecol = this.sprites.render(xpos, col); - if (spritecol) rgb = this.color_std[spritecol]; - else rgb = ehb ? this.color_ehb[col] : this.color_std[col]; - this.linedata[xpos] = col; - //AMIGA.video.drawpixel(xpos, ypos, rgb); - this.drawpixel(xpos, ypos, rgb); - } - - this.drawpixel_dpf = function (xpos, ypos, col1, col2) { - var rgb, col = this.state.pf2pri ? col2 : col1; - var spritecol = this.sprites.render(xpos, col); - if (spritecol) - rgb = this.color_std[spritecol]; - else { - col = this.state.pf2pri ? (col2 > 0 ? (8 + col2) : col1) : (col1 > 0 ? col1 : (8 + col2)); - rgb = this.color_std[col]; - } - this.linedata[xpos] = col; - //AMIGA.video.drawpixel(xpos, ypos, rgb); - this.drawpixel(xpos, ypos, rgb); - } - - this.drawpixel_ham_col = function (xpos, ypos, col) { - var spritecol = this.sprites.render(xpos, col); - var rgb = this.color_std[spritecol ? spritecol : col] - this.linedata[xpos] = col; - //AMIGA.video.drawpixel(xpos, ypos, rgb); - this.drawpixel(xpos, ypos, rgb); - } - - this.drawpixel_ham_rgb = function (xpos, ypos, rgb) { - var spritecol = this.sprites.render(xpos, 0); - if (spritecol) rgb = this.color_std[spritecol]; - this.linedata[xpos] = 0; - //AMIGA.video.drawpixel(xpos, ypos, rgb); - this.drawpixel(xpos, ypos, rgb); - } - - - this.drawline_std = function(x, y, o) { - var i, j, l; - if (this.state.altget && this.state.ddiff < 4) { - for (j = 0; j < 4; j++) AMIGA.video.drawpixel(x + j, y, this.color_std[0]); - - for (j = 4, l = 11; j < 16; j++, l--) { - var col = 0; - switch (this.state.planes) { - case 5: col = ((this.plane[4].line[o] >> l) & 1); - case 4: col = (col << 1) | ((this.plane[3].line[o] >> l) & 1); - case 3: col = (col << 1) | ((this.plane[2].line[o] >> l) & 1); - case 2: col = (col << 1) | ((this.plane[1].line[o] >> l) & 1); - case 1: col = (col << 1) | ((this.plane[0].line[o] >> l) & 1); - } - this.drawpixel_std(x + j, y, col); - } - i = 16; o++; + this.sprstartstop(s); + sprxp = (sprpos[num] & 0xFF) * 2 + (sprctl[num] & 1); + sprxp <<= sprite_buffer_res; +/*#ifdef AGA + if (AMIGA.config.chipset.mask & CSMASK_AGA) { + sprxp |= ((sprctl[num] >> 3) & 3) >> (RES_MAX - sprite_buffer_res); + s.dblscan = sprpos[num] & 0x80; } else - i = 0; - - for (; i < this.state.hpixel; i += 16, o++) { - for (j = 0, l = 15; j < 16; j++, l--) { - var col = 0; - switch (this.state.planes) { - case 5: col = ((this.plane[4].line[o] >> l) & 1); - case 4: col = (col << 1) | ((this.plane[3].line[o] >> l) & 1); - case 3: col = (col << 1) | ((this.plane[2].line[o] >> l) & 1); - case 2: col = (col << 1) | ((this.plane[1].line[o] >> l) & 1); - case 1: col = (col << 1) | ((this.plane[0].line[o] >> l) & 1); - } - this.drawpixel_std(x + i + j, y, col); - } +#endif*/ + if (AMIGA.config.chipset.mask & CSMASK_ECS_DENISE) { + sprxp |= ((sprctl[num] >> 3) & 2) >> (RES_MAX - sprite_buffer_res); } - } - - this.drawline_ehb = function(x, y, o) { - for (var i = 0; i < this.state.hpixel; i += 16, o++) { - for (var j = 0, l = 15; j < 16; j++, l--) { - var ehb = ((this.plane[5].line[o] >> l) & 1); - var col = ((this.plane[4].line[o] >> l) & 1); - col = (col << 1) | ((this.plane[3].line[o] >> l) & 1); - col = (col << 1) | ((this.plane[2].line[o] >> l) & 1); - col = (col << 1) | ((this.plane[1].line[o] >> l) & 1); - col = (col << 1) | ((this.plane[0].line[o] >> l) & 1); - this.drawpixel_ehb(x + i + j, y, col, ehb); - } - } - } - - this.drawline_dpf = function(x, y, o) { - for (var i = 0; i < this.state.hpixel; i += 16, o++) { - for (var j = 0, l = 15; j < 16; j++, l--) { - var col1 = 0, col2 = 0; - switch (this.state.planes) { - case 6: col2 = ((this.plane[5].line[o] >> l) & 1); - case 5: col1 = ((this.plane[4].line[o] >> l) & 1); - case 4: col2 = (col2 << 1) | ((this.plane[3].line[o] >> l) & 1); - case 3: col1 = (col1 << 1) | ((this.plane[2].line[o] >> l) & 1); - case 2: col2 = (col2 << 1) | ((this.plane[1].line[o] >> l) & 1); - case 1: col1 = (col1 << 1) | ((this.plane[0].line[o] >> l) & 1); - } - this.drawpixel_dpf(x + i + j, y, col1, col2); - } - } + s.xpos = sprxp; + s.vstart = (sprpos[num] >> 8) | ((sprctl[num] << 6) & 0x100); + s.vstop = (sprctl[num] >> 8) | ((sprctl[num] << 7) & 0x100); + if (AMIGA.config.chipset.mask & CSMASK_ECS_AGNUS) { + s.vstart |= (sprctl[num] << 3) & 0x200; + s.vstop |= (sprctl[num] << 4) & 0x200; + } + this.sprstartstop(s); } - - this.drawline_ham = function(x, y, o) { - var opm, col, r = 0, g = 0, b = 0; - - for (var i = 0; i < this.state.hpixel; i += 16, o++) { - for (var j = 0, l = 15; j < 16; j++, l--) { - opm = (((this.plane[5].line[o] >> l) & 1) << 1) | ((this.plane[4].line[o] >> l) & 1); - col = ((this.plane[3].line[o] >> l) & 1); - col = (col << 1) | ((this.plane[2].line[o] >> l) & 1); - col = (col << 1) | ((this.plane[1].line[o] >> l) & 1); - col = (col << 1) | ((this.plane[0].line[o] >> l) & 1); - switch (opm) { - case 2: { r = col; this.drawpixel_ham_rgb(x + i + j, y, ((r << 1) << 11) | ((g << 2) << 5) | (b << 1)); break; } - case 3: { g = col; this.drawpixel_ham_rgb(x + i + j, y, ((r << 1) << 11) | ((g << 2) << 5) | (b << 1)); break; } - case 1: { b = col; this.drawpixel_ham_rgb(x + i + j, y, ((r << 1) << 11) | ((g << 2) << 5) | (b << 1)); break; } - default: { - r = ((this.color_std[col] >> 11) & 31) >> 1; - g = ((this.color_std[col] >> 5) & 63) >> 2; - b = (this.color_std[col] & 31) >> 1; - this.drawpixel_ham_col(x + i + j, y, col); - } - } - } - } - } - this.drawline_border = function(y) { - var l = this.state.hleft; - var w = this.state.hpixel; - var r = this.state.hires ? VIDEO_WIDTH : VIDEO_WIDTH >> 1; - var x, rgb = this.color_std[0]; - - if (!this.state.hires) { - l <<= 1; - w <<= 1; - r <<= 1; - } - AMIGA.video.drawline_from_to(0, l, y, rgb); - AMIGA.video.drawline_from_to(l + w, r, y, rgb); + this.SPRxCTL_1 = function(v, num, hpos) { + //struct sprite *s = &spr[num]; + sprctl[num] = v; + spr_arm(num, 0); + this.SPRxCTLPOS(num); + /*if (this.vpos >= SPRITE_DEBUG_MINY && this.vpos <= SPRITE_DEBUG_MAXY) { + BUG.info('%d:%d:SPR%dCTL %04X P=%06X VSTRT=%d VSTOP=%d HSTRT=%d D=%d A=%d CP=%x PC=%x', this.vpos, hpos, num, v, s->pt, s->vstart, s->vstop, s->xpos, spr[num].dmastate, spr[num].armed, cop_state.ip, M68K_GETPC); + }*/ } - this.drawline_empty = function(y) { - var l = this.state.hleft; - var w = this.state.hpixel; - var x, rgb = this.color_std[0]; - - if (!this.state.hires) { - l <<= 1; - w <<= 1; - } - AMIGA.video.drawline_from_to(l, l + w, y, rgb); + + this.SPRxPOS_1 = function(v, num, hpos) { + //struct sprite *s = &spr[num]; + sprpos[num] = v; + this.SPRxCTLPOS(num); + /*if (this.vpos >= SPRITE_DEBUG_MINY && this.vpos <= SPRITE_DEBUG_MAXY) { + BUG.info('%d:%d:SPR%dPOS %04X P=%06X VSTRT=%d VSTOP=%d HSTRT=%d D=%d A=%d CP=%x PC=%x', this.vpos, hpos, num, v, s->pt, s->vstart, s->vstop, s->xpos, spr[num].dmastate, spr[num].armed, cop_state.ip, M68K_GETPC); + }*/ + } + + this.SPRxDATA_1 = function(v, num, hpos) { + sprdata[num][0] = v; +/*#ifdef AGA + sprdata[num][1] = v; + sprdata[num][2] = v; + sprdata[num][3] = v; +#endif*/ + spr_arm(num, 1); + /*if (this.vpos >= SPRITE_DEBUG_MINY && this.vpos <= SPRITE_DEBUG_MAXY) { + BUG.info('%d:%d:SPR%dDATA %04X P=%06X D=%d A=%d PC=%x', this.vpos, hpos, num, v, spr[num].pt, spr[num].dmastate, spr[num].armed, M68K_GETPC); + }*/ + } + + this.SPRxDATB_1 = function(v, num, hpos) { + sprdatb[num][0] = v; +/*#ifdef AGA + sprdatb[num][1] = v; + sprdatb[num][2] = v; + sprdatb[num][3] = v; +#endif*/ + /*if (this.vpos >= SPRITE_DEBUG_MINY && this.vpos <= SPRITE_DEBUG_MAXY) { + BUG.info('%d:%d:SPR%dDATB %04X P=%06X D=%d A=%d PC=%x', this.vpos, hpos, num, v, spr[num].pt, spr[num].dmastate, spr[num].armed, M68K_GETPC); + }*/ } - this.fetchline = function() { - var pt5 = this.plane[5].pt >>> 1; - var pt4 = this.plane[4].pt >>> 1; - var pt3 = this.plane[3].pt >>> 1; - var pt2 = this.plane[2].pt >>> 1; - var pt1 = this.plane[1].pt >>> 1; - var pt0 = this.plane[0].pt >>> 1; + this.SPRxDATA = function(hpos, v, num) { this.decide_sprites(hpos); this.SPRxDATA_1(v, num, hpos); } + this.SPRxDATB = function(hpos, v, num) { this.decide_sprites(hpos); this.SPRxDATB_1(v, num, hpos); } + this.SPRxCTL = function(hpos, v, num) { this.decide_sprites(hpos); this.SPRxCTL_1(v, num, hpos); } + this.SPRxPOS = function(hpos, v, num) { this.decide_sprites(hpos); this.SPRxPOS_1(v, num, hpos); } - if (this.state.altget) { - switch (this.state.planes) { - case 6: { this.plane[5].line[0] = AMIGA.mem.chip.data[pt5] >> 8; } - case 5: { this.plane[4].line[0] = AMIGA.mem.chip.data[pt4] >> 8; } - case 4: { this.plane[3].line[0] = AMIGA.mem.chip.data[pt3] >> 8; } - case 3: { this.plane[2].line[0] = AMIGA.mem.chip.data[pt2] >> 8; } - case 2: { this.plane[1].line[0] = AMIGA.mem.chip.data[pt1] >> 8; } - case 1: { this.plane[0].line[0] = AMIGA.mem.chip.data[pt0] >> 8; } - } - for (var i = 1; i < this.state.dwords + 1; i++) { - switch (this.state.planes) { - case 6: { this.plane[5].line[i] = ((AMIGA.mem.chip.data[pt5] & 0xff) << 8) | (AMIGA.mem.chip.data[++pt5] >> 8); } - case 5: { this.plane[4].line[i] = ((AMIGA.mem.chip.data[pt4] & 0xff) << 8) | (AMIGA.mem.chip.data[++pt4] >> 8); } - case 4: { this.plane[3].line[i] = ((AMIGA.mem.chip.data[pt3] & 0xff) << 8) | (AMIGA.mem.chip.data[++pt3] >> 8); } - case 3: { this.plane[2].line[i] = ((AMIGA.mem.chip.data[pt2] & 0xff) << 8) | (AMIGA.mem.chip.data[++pt2] >> 8); } - case 2: { this.plane[1].line[i] = ((AMIGA.mem.chip.data[pt1] & 0xff) << 8) | (AMIGA.mem.chip.data[++pt1] >> 8); } - case 1: { this.plane[0].line[i] = ((AMIGA.mem.chip.data[pt0] & 0xff) << 8) | (AMIGA.mem.chip.data[++pt0] >> 8); } - } - } - switch (this.state.planes) { - case 6: { this.plane[5].line[i] = 0; } - case 5: { this.plane[4].line[i] = 0; } - case 4: { this.plane[3].line[i] = 0; } - case 3: { this.plane[2].line[i] = 0; } - case 2: { this.plane[1].line[i] = 0; } - case 1: { this.plane[0].line[i] = 0; } - } - } else { - for (var i = 0; i < this.state.dwords; i++) { - switch (this.state.planes) { - case 6: { this.plane[5].line[i] = AMIGA.mem.chip.data[pt5++]; } - case 5: { this.plane[4].line[i] = AMIGA.mem.chip.data[pt4++]; } - case 4: { this.plane[3].line[i] = AMIGA.mem.chip.data[pt3++]; } - case 3: { this.plane[2].line[i] = AMIGA.mem.chip.data[pt2++]; } - case 2: { this.plane[1].line[i] = AMIGA.mem.chip.data[pt1++]; } - case 1: { this.plane[0].line[i] = AMIGA.mem.chip.data[pt0++]; } - } - } + this.SPRxPTH = function(hpos, v, num) { + this.decide_sprites(hpos); + if (hpos - 1 != spr[num].ptxhpos) { + spr[num].pt = ((v << 16) | (spr[num].pt & 0xffff)) >>> 0; } - - switch (this.state.planes) { - case 6: this.plane[5].pt = pt5 << 1; - case 5: this.plane[4].pt = pt4 << 1; - case 4: this.plane[3].pt = pt3 << 1; - case 3: this.plane[2].pt = pt2 << 1; - case 2: this.plane[1].pt = pt1 << 1; - case 1: this.plane[0].pt = pt0 << 1; + //if (this.vpos >= SPRITE_DEBUG_MINY && this.vpos <= SPRITE_DEBUG_MAXY) BUG.info('%d:%d:SPR%dPTH %06X', this.vpos, hpos, num, spr[num].pt); + } + this.SPRxPTL = function(hpos, v, num) { + this.decide_sprites(hpos); + if (hpos - 1 != spr[num].ptxhpos) { + spr[num].pt = ((spr[num].pt & 0xffff0000) | (v & 0xfffe)) >>> 0; + } + //if (this.vpos >= SPRITE_DEBUG_MINY && this.vpos <= SPRITE_DEBUG_MAXY) BUG.info('%d:%d:SPR%dPTL %06X', this.vpos, hpos, num, spr[num].pt); + } + + this.setup_sprites = function() { + if (!sprinit) { + sprinit = true; + setup_sprite_tables(); } } - this.scrollline = function(d1, d2) { - var d1n = 16 - d1; - var d2n = 16 - d2; - for (var i = this.state.dwords - 1; i > 0; i--) { - switch (this.state.planes) { - case 6: { if (d2) this.plane[5].line[i] = (this.plane[5].line[i] >> d2) | (this.plane[5].line[i - 1] << d2n); } - case 5: { if (d1) this.plane[4].line[i] = (this.plane[4].line[i] >> d1) | (this.plane[4].line[i - 1] << d1n); } - case 4: { if (d2) this.plane[3].line[i] = (this.plane[3].line[i] >> d2) | (this.plane[3].line[i - 1] << d2n); } - case 3: { if (d1) this.plane[2].line[i] = (this.plane[2].line[i] >> d1) | (this.plane[2].line[i - 1] << d1n); } - case 2: { if (d2) this.plane[1].line[i] = (this.plane[1].line[i] >> d2) | (this.plane[1].line[i - 1] << d2n); } - case 1: { if (d1) this.plane[0].line[i] = (this.plane[0].line[i] >> d1) | (this.plane[0].line[i - 1] << d1n); } - } - } - switch (this.state.planes) { - case 6: { if (d2) this.plane[5].line[i] = this.plane[5].line[i] >> d2; } - case 5: { if (d1) this.plane[4].line[i] = this.plane[4].line[i] >> d1; } - case 4: { if (d2) this.plane[3].line[i] = this.plane[3].line[i] >> d2; } - case 3: { if (d1) this.plane[2].line[i] = this.plane[2].line[i] >> d1; } - case 2: { if (d2) this.plane[1].line[i] = this.plane[1].line[i] >> d2; } - case 1: { if (d1) this.plane[0].line[i] = this.plane[0].line[i] >> d1; } - } + this.cleanup_sprites = function() {} + + this.reset_sprites = function() { + var i; + for (i = 0; i < sprpos.length; i++) sprpos[i] = 0; //memset (sprpos, 0, sizeof sprpos); + for (i = 0; i < sprctl.length; i++) sprctl[i] = 0; //memset (sprctl, 0, sizeof sprctl); + + for (i = 0; i < spixels.length; i++) spixels[i] = 0; //memset(spixels, 0, sizeof spixels); + for (i = 0; i < spixstate.length; i++) spixstate[i] = 0; //memset(&spixstate, 0, sizeof spixstate); } - this.mod = function() { - switch (this.state.planes) { - case 6: this.plane[5].pt += this.bpl2mod; - case 5: this.plane[4].pt += this.bpl1mod; - case 4: this.plane[3].pt += this.bpl2mod; - case 3: this.plane[2].pt += this.bpl1mod; - case 2: this.plane[1].pt += this.bpl2mod; - case 1: this.plane[0].pt += this.bpl1mod; - } - } - - this.hSync = function() { - if (!this.frame.skip) { - var x = this.state.hleft; - var y = AMIGA.events.vpos - ((this.state.vlenreal > 256) ? this.state.vstart : 0x2c); - - if (this.state.ilace) y = y * 2 + 1 - AMIGA.events.lof; - if (x < 0) x = 0; - if (y < 0) y = 0; else if (y >= VIDEO_HEIGHT) y = VIDEO_HEIGHT - 1; - - if (AMIGA.events.vpos >= this.state.vstart && AMIGA.events.vpos < this.state.vstop) { - if (this.state.planes > 0 && AMIGA.dmaen(DMAF_BPLEN)) { - var offs = this.state.ddiff ? (this.state.ddiff - 1) >> 1 : 0; - if (this.state.ddiff == 2) { this.state.altget = false; offs++ }; - this.state.colorOnly = false; - - if (this.sprites.nr_armed > 0) this.sprites.draw(); - - this.fetchline(); - this.mod(); - - if (this.state.delay1 || this.state.delay2) { - var d1 = this.state.hires ? ((this.state.delay1 & 7) << 1) : this.state.delay1; - var d2 = this.state.hires ? ((this.state.delay2 & 7) << 1) : this.state.delay2; - this.scrollline(d1, d2); - } - - - if (this.state.std) this.drawline_std(x, y, offs); - else if (this.state.ehb) this.drawline_ehb(x, y, offs); - else if (this.state.dpf) this.drawline_dpf(x, y, offs); - else if (this.state.ham) this.drawline_ham(x, y, offs); - else AMIGA.video.drawline(y, this.color_std[0]); - - this.drawline_border(y); - - if (this.state.vlenrealset == 0) { - this.state.vlenrealset++; - this.state.vlenrealtmp = AMIGA.events.vpos; - } - } else { - AMIGA.video.drawline(y, this.color_std[0]); - } - } else { - if (this.state.vlenrealset == 1) { - this.state.vlenrealset++; - this.state.vlenreal = AMIGA.events.vpos - this.state.vlenrealtmp; - //this.lamps(); - } - AMIGA.video.drawline(y, this.color_std[0]); - } - } - - //AMIGA.events.eventtab[EV_RENDER].oldcycles = AMIGA.events.currcycle; - //AMIGA.events.eventtab[EV_RENDER].evtime = AMIGA.events.currcycle + AMIGA.events.maxhpos * CYCLE_UNIT; - } - - this.vSync = function() { - if (!this.frame.skip && (!this.state.ilace || (this.state.ilace && AMIGA.events.lof == 0))) { - AMIGA.video.draw(this.color_std[0], this.state.hScale, this.state.vScale, this.state.colorOnly); - - //if (!this.state.colorOnly) AMIGA.video.clear_pixels(); - } - - if (this.state.ilace) { if (AMIGA.events.lof == 0) this.frame.count++; } else this.frame.count++; if (this.frame.count == AMIGA.events.hz) this.frame.count = 0; - - /*this.state.hires = false; - this.state.ilace = false; - this.state.ham = false; - this.state.dpf = false; - this.state.ehb = false; - this.state.std = false; - this.state.altget = false; - this.state.hScale = true; - this.state.vScale = true;*/ - - this.state.colorOnly = true; - this.state.vlenrealset = 0; - } - - this.COLORxx = function (v, num) { - //BUG.info('Playfield.COLOR%02d() $%04x', num, v); - var r = (v >> 8) & 15; - var g = (v >> 4) & 15; - var b = v & 15; - this.color_std[num] = ((r << 1) << 11) | ((g << 2) << 5) | (b << 1); - this.color_ehb[num] = (r << 11) | ((g << 1) << 5) | b; - } - - this.BPLxPTx = function (v, num, hi) { - if (hi) { - this.plane[num].pt = ((v << 16) | (this.plane[num].pt & 0xffff)) >>> 0; - } else { - /*if (AMIGA.copper.access && this.is_bitplane_dma(AMIGA.events.hpos() + 1) == num + 1) { - console.log('BPLxPTx() SKIP! ', num, AMIGA.events.hpos()); - return; - }*/ - this.plane[num].pt = ((this.plane[num].pt & 0xffff0000) | v) >>> 0; - } - } - - this.BPLxDAT = function (v, num) { - //if (v) BUG.info('Custom.BPL%dDAT() $%04x', num, v); - this.plane[num].dat = v; - } - - /*this.BPLCON0_getRes = function (v) { - if (AMIGA.config.chipset.type == SAEV_Config_Chipset_Type_OCS) - v &= ~0x40; - return (v & 0x8000) ? 2 : ((v & 0x40) ? 3 : 1); - }*/ - - this.BPLCON0_getPlanes = function (v) { - if ((v & 0x0010) && (v & 0x7000)) - return 0; - if (v & 0x0010) - return 8; - return (v >> 12) & 7; - } - - this.BPLCON0 = function (v) { - //BUG.info('Custom.BPLCON0() $%04x', v); - //var hires_old = this.state.hires; - var ilace_old = this.state.ilace; - - if (!(this.bplcon0 & 2)) { - AMIGA.events.vpos_previous = AMIGA.events.vpos; - AMIGA.events.hpos_previous = AMIGA.events.hpos(); - } - - this.bplcon0 = v; - this.state.planes = this.BPLCON0_getPlanes(v); - - this.state.hires = (v & BPLF_HIRES) != 0; - this.state.ilace = (v & BPLF_LACE) != 0; - this.state.dpf = (v & BPLF_DBLPF) != 0; - this.state.ham = (v & BPLF_HOMOD) != 0; - this.state.ehb = (this.state.planes == 6 && !this.state.dpf && !this.state.ham); - this.state.std = (!this.state.ehb && !this.state.dpf && !this.state.ham); - - this.state.hpixel = this.state.hlen << (this.state.hires ? 1 : 0); - this.state.hleft = (180 - Math.min(this.state.hlen >> 1, this.state.dlen)) << (this.state.hires ? 1 : 0); - this.state.dwords = this.state.dnum << (this.state.hires ? 1 : 0); - - if (this.state.planes) { - this.state.hScale = !this.state.hires; - this.state.vScale = !this.state.ilace; - } - - //if (this.state.hires != hires_old) BUG.info('Custom.BPLCON0() hires change %d, vpos %d, hpos %d', this.state.hires?1:0, AMIGA.events.vpos, AMIGA.events.hpos()); - if (this.state.ilace != ilace_old) { - //BUG.info('Custom.BPLCON0() ilace change %d, vpos %d, hpos %d', this.state.ilace?1:0, AMIGA.events.vpos, AMIGA.events.hpos()); - if (!this.state.ilace) AMIGA.video.clear_pixels(); - AMIGA.audio.recalc_sample_evtime(); - } - - this.setup_fmodes(AMIGA.events.hpos()); - - //this.lamps(); - } - - this.BPLCON1 = function (v) { - this.bplcon1 = v; - this.state.delay1 = v & 0xf; - this.state.delay2 = (v >> 4) & 0xf; - - //this.lamps(); - } - - this.BPLCON2 = function (v) { - this.bplcon2 = v; - this.state.pf2pri = (v & BPLF_PF2PRI) != 0; - this.state.pf1p = v & 7; - this.state.pf2p = (v >> 3) & 7; - - this.sprites.setMask(this.state.pf1p, this.state.pf2p); - - //this.lamps(); - } - - this.BPLCON3 = function (v) { - this.bplcon3 = v; - } - - this.BPL1MOD = function (v) { - //if (v) BUG.info('Custom.BPL1MOD() $%04x', v); - this.bpl1mod = (v & 0x8000) ? (v - 0x10000) : v; - } - - this.BPL2MOD = function (v) { - //if (v) BUG.info('Custom.BPL2MOD() $%04x', v); - this.bpl2mod = (v & 0x8000) ? (v - 0x10000) : v; - } - - this.DIWSTRT = function (v) { - //BUG.info('Custom.DIWSTRT() $%04x', v); - this.diwstrt = v; - this.calcdiw(); - } - - this.DIWSTOP = function (v) { - //BUG.info('Custom.DIWSTOP() $%04x', v); - this.diwstop = v; - this.calcdiw(); - } - - this.DDFSTRT = function (v) { - //BUG.info('Custom.DDFSTRT() $%04x', v); - this.ddfstrt = v; - this.calcddf(0); - } - - this.DDFSTOP = function (v) { - //BUG.info('Custom.DDFSTOP() $%04x', v); - this.ddfstop = v; - this.calcddf(1); - } - - /* ECS - * 7-4 Lisa/Denise/ECS Denise Revision level (decrement to bump revision level, hex F represents 0th rev. level) - * 3 Maintain as a 1 for future generation - * 2 When low indicates AA feature set (LISA) - * 1 When low indicates ECS feature set (LISA or ECS DENISE) - * 0 Maintain as a 1 for future generation - * - * Denise ID: OCS = 0xFF, ECS = 0xFC, AGA = 0xF8 - */ - this.DENISEID___ = function() { - var smb = 0xff; - - var v = ((0xf - AMIGA.config.chipset.agnus_rev) << 4); - v |= 8; - v |= 4; /* low = AGA */ - /* v |= 2; low = ECS */ - //v |= 1; - - BUG.info('Custom.DENISEID() $%04x', (smb << 8) | v); - return (smb << 8) | v; - } - - this.DENISEID = function() { - //if (AMIGA.config.chipset.type == SAEV_Config_Chipset_Type_AGA) return [0, 0x00F8]; - if (AMIGA.config.chipset.type == SAEV_Config_Chipset_Type_ECS) return [0, 0xFFFC]; - if (AMIGA.config.cpu.model == 68000 && (AMIGA.config.cpu.compatible || AMIGA.config.cpu.exact)) - return [1, 0xFFFF]; - return [0, 0xFFFF]; - } - - this.DIWHIGH = function (v) { - //if (!(AMIGA.config.chipset.type == CHIPSET_AGA)) - v &= ~ (0x0008 | 0x0010 | 0x1000 | 0x0800); - v &= ~ (0x8000 | 0x4000 | 0x0080 | 0x0040); - - //BUG.info('Custom.DIWHIGH() $%04x', v); - this.diwhigh = v; - this.calcdiw(); - } - - /*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/ + /* playfield */ /*-----------------------------------------------------------------------*/ - var bplcon0_res = 0; - var bplcon0_planes = 0; - var bplcon0_planes_limit = 0; - - var real_bitplane_number = []; //[3][3][9]; - var fmode = 0; - var fetchmode = 0; - var fetchunits = [ 8,8,8,0, 16,8,8,0, 32,16,8,0 ]; - var fetchstarts = [ 3,2,1,0, 4,3,2,0, 5,4,3,0 ]; - var fm_maxplanes = [ 3,2,1,0, 3,3,2,0, 3,3,3,0 ]; - var fetchunit = 0; + function debug_cycle_diagram() { + var fm, res, planes, cycle, v; + var aa, txt = ''; - var fetchunit_mask = 0; - var fetchstart_shift = 0; - var fetchstart = 0; - var fetchstart_mask = 0; - - var cycle_diagram_table = []; //[3][3][9][32]; - var cycle_diagram_free_cycles = []; //[3][3][9]; - var cycle_diagram_total_cycles = []; //[3][3][9]; - var cycle_sequences = [ [2,1,2,1,2,1,2,1], [4,2,3,1,4,2,3,1], [8,4,6,2,7,3,5,1] ]; - var curr_diagram = []; + for (fm = 0; fm <= 2; fm++) { + txt += sprintf('FMODE %d\n=======\n', fm); + for (res = 0; res <= 2; res++) { + for (planes = 0; planes <= 8; planes++) { + txt += sprintf('%d: ',planes); + for (cycle = 0; cycle < 32; cycle++) { + v = cycle_diagram_table[fm][res][planes][cycle]; + if (v == 0) aa='-'; else if (v > 0) aa='1'; else aa='X'; + txt += sprintf('%s', aa); + } + txt += sprintf(' %d:%d\n', cycle_diagram_free_cycles[fm][res][planes], cycle_diagram_total_cycles[fm][res][planes]); + } + txt += sprintf('\n'); + } + } + BUG.info(txt); + } - this.create_cycle_diagram_table = function () { + function create_cycle_diagram_table() { var fm, res, cycle, planes, rplanes, v; var fetch_start, max_planes, freecycles; var cycle_sequence; - var i, j, k, l; - + var i, j, k, l; + for (i = 0; i < 3; i++) { real_bitplane_number[i] = []; cycle_diagram_free_cycles[i] = []; @@ -1218,6 +3582,7 @@ function Playfield() { } } } + cycle_diagram_table = []; for (i = 0; i < 3; i++) { cycle_diagram_table[i] = []; for (j = 0; j < 3; j++) { @@ -1229,7 +3594,7 @@ function Playfield() { } } } - + for (fm = 0; fm <= 2; fm++) { for (res = 0; res <= 2; res++) { max_planes = fm_maxplanes[fm * 4 + res]; @@ -1256,65 +3621,1076 @@ function Playfield() { rplanes = planes; if (rplanes > max_planes) rplanes = 0; - if (rplanes == 7 && fm == 0 && res == 0) //&& !(currprefs.chipset_mask & CSMASK_AGA)) + if (rplanes == 7 && fm == 0 && res == 0 && !(AMIGA.config.chipset.mask & CSMASK_AGA)) rplanes = 4; real_bitplane_number[fm][res][planes] = rplanes; } } } + //debug_cycle_diagram(); } - - //var estimated_last_fetch_cycle = 0; - //var cycle_diagram_shift = 0; - - /*this.estimate_last_fetch_cycle = function (hpos) { - var fetchunit = fetchunits[fetchmode * 4 + bplcon0_res]; - if (plf_state < plf_passed_stop) { - var stop = plfstop < hpos || plfstop > HARD_DDF_STOP ? HARD_DDF_STOP : plfstop; - var fetch_cycle_at_stop = fetch_cycle + (stop - hpos); - var starting_last_block_at = (fetch_cycle_at_stop + fetchunit - 1) & ~(fetchunit - 1); + /*---------------------------------*/ - estimated_last_fetch_cycle = hpos + (starting_last_block_at - fetch_cycle) + fetchunit; - } else { - var starting_last_block_at = (fetch_cycle + fetchunit - 1) & ~(fetchunit - 1); - if (plf_state == plf_passed_stop2) - starting_last_block_at -= fetchunit; + function doMask(p, bits, shift) { + /* scale to 0..255, shift to align msb with mask, and apply mask */ - estimated_last_fetch_cycle = hpos + (starting_last_block_at - fetch_cycle) + fetchunit; + //if (flashscreen) p ^= 0xff; + var val = (p << 24) >>> 0; + if (!bits) + return 0; + val >>>= (32 - bits); + val <<= shift; + + return val >>> 0; + } + function doAlpha (alpha, bits, shift) { + return ((alpha & ((1 << bits) - 1)) << shift) >>> 0; + } + function alloc_colors64k (rw, gw, bw, rs, gs, bs, aw, as, alpha, byte_swap) { + //#define bswap_16(x) (((x) >> 8) | (((x) & 0xFF) << 8)) + //#define bswap_32(x) (((x) << 24) | (((x) << 8) & 0x00FF0000) | (((x) >> 8) & 0x0000FF00) | ((x) >> 24)) + var bpp = rw + gw + bw + aw; + //var j = 256; + + //video_calc_gammatable(); + for (var i = 0; i < 4096; i++) { + var r = ((i >> 8) << 4) | (i >> 8); + var g = (((i >> 4) & 0xf) << 4) | ((i >> 4) & 0x0f); + var b = ((i & 0xf) << 4) | (i & 0x0f); + //r = gamma[r + j]; + //g = gamma[g + j]; + //b = gamma[b + j]; + xcolors[i] = (doMask(r, rw, rs) | doMask(g, gw, gs) | doMask(b, bw, bs) | doAlpha(alpha, aw, as)) >>> 0; + if (byte_swap) { + if (bpp <= 16) + xcolors[i] = bswap_16(xcolors[i]); + else + xcolors[i] = bswap_32(xcolors[i]); + } + if (bpp <= 16) { + /* Fill upper 16 bits of each colour value + * with a copy of the colour. */ + xcolors[i] |= xcolors[i] * 0x00010001; + xcolors[i] >>>= 0; + } } + //console.log('alloc_colors64k', xcolors); + } + + function update_mirrors() { + aga_mode = (AMIGA.config.chipset.mask & CSMASK_AGA) != 0; + direct_rgb = aga_mode; + } + + function docols(colentry) { +/*#ifdef AGA + if (AMIGA.config.chipset.mask & CSMASK_AGA) { + for (var i = 0; i < 256; i++) { + var v = color_reg_get (colentry, i); + if (v < 0 || v > 16777215) + continue; + colentry->acolors[i] = getxcolor (v); + } + } else { +#endif*/ + for (var i = 0; i < 32; i++) { + var v = color_reg_get(colentry, i); + if (v < 0 || v > 4095) + continue; + colentry.acolors[i] = getxcolor(v); + } +/*#ifdef AGA + } +#endif*/ + } + function notice_new_xcolors() { + update_mirrors(); + docols(current_colors); + docols(colors_for_drawing); + for (var i = 0; i < (MAXVPOS + 1) * 2; i++) { + docols(color_tables[0][i]); + docols(color_tables[1][i]); + } + } + + /*---------------------------------*/ + + function getxcolor(c) { +/*#ifdef AGA + if (direct_rgb) + return CONVERT_RGB(c); + else +#endif*/ + return xcolors[c]; + } + + function color_reg_get(ce, c) { +/*#ifdef AGA + if (aga_mode) + return ce.color_regs_aga[c]; + else +#endif*/ + return ce.color_regs_ecs[c]; + } + + function color_reg_set(ce, c, v) { +/*#ifdef AGA + if (aga_mode) + ce.color_regs_aga[c] = v; + else +#endif*/ + ce.color_regs_ecs[c] = v; + } + + function color_reg_cmp(ce1, ce2) { +/*#ifdef AGA + if (aga_mode) { + v = memcmp (ce1->color_regs_aga, ce2->color_regs_aga, sizeof (uae_u32) * 256); + } else +#endif*/ + { + //v = memcmp (ce1.color_regs_ecs, ce2.color_regs_ecs, sizeof (uae_u16) * 32); + for (var i = 0; i < 32; i++) { + if (ce1.color_regs_ecs[i] != ce2.color_regs_ecs[i]) + return 1; + } + return ce1.borderblank == ce2.borderblank ? 0 : 1; + } + } + + function color_reg_cpy(dst, src) { + dst.borderblank = src.borderblank; +/*#ifdef AGA + if (aga_mode) + //copy acolors and color_regs_aga + memcpy (dst->acolors, src->acolors, sizeof(struct color_entry) - sizeof(uae_u16) * 32); + else +#endif*/ + //copy first 32 acolors and color_regs_ecs + //memcpy (dst.color_regs_ecs, src.color_regs_ecs, sizeof(struct color_entry)); + + for (var i = 0; i < 32; i++) { + dst.acolors[i] = src.acolors[i]; + dst.color_regs_ecs[i] = src.color_regs_ecs[i]; + } + //console.log('color_reg_cpy()', dst, src); + } + + function color_reg_cpy_acolors(dst, src) { + dst.borderblank = src.borderblank; + for (var i = 0; i < dst.acolors.length; i++) + dst.acolors[i] = src.acolors[i]; + } + + /*---------------------------------*/ + + this.remember_ctable = function() { + if (next_color_entry >= COLOR_TABLE_SIZE) { + BUG.info('remember_ctable() BUG', next_color_entry); + return; + } + if (remembered_color_entry < 0) { + color_reg_cpy(curr_color_tables[next_color_entry], current_colors); + remembered_color_entry = next_color_entry++; + } + thisline_decision.ctable = remembered_color_entry; + + if (color_src_match < 0 || color_dest_match != remembered_color_entry || line_decisions[next_lineno].ctable != color_src_match) { + var oldctable = line_decisions[next_lineno].ctable; + var changed = 0; + + if (oldctable < 0) { + changed = 1; + color_src_match = color_dest_match = -1; + } else { + color_compare_result = color_reg_cmp(prev_color_tables[oldctable], current_colors) != 0; + if (color_compare_result) + changed = 1; + color_src_match = oldctable; + color_dest_match = remembered_color_entry; + } + thisline_changed |= changed; + } else { + if (color_compare_result) + thisline_changed = 1; + } + } + + this.record_color_change2 = function(hpos, regno, value) { + //if (FAST_COLORS) //en for better? + //return; + var pos = hpos * 2; + if (regno == 0x1000 + 0x10c) pos++; // BPLCON4 change needs 1 lores pixel delay + curr_color_changes[next_color_change].linepos = pos; + curr_color_changes[next_color_change].regno = regno; + curr_color_changes[next_color_change++].value = value; + curr_color_changes[next_color_change].regno = -1; + //console.log('record_color_change2()', next_color_change); + } + + this.record_color_change = function(hpos, regno, value) { + if (FAST_COLORS) + return; + if (this.vpos < minfirstline || (regno < 0x1000 && this.nodraw())) + return; + + this.decide_diw(hpos); + this.decide_line(hpos); + + if (thisline_decision.ctable < 0) + this.remember_ctable(); + + if ((regno < 0x1000 || regno == 0x1000 + 0x10c) && hpos < HBLANK_OFFSET && !(beamcon0 & 0x80) && prev_lineno >= 0) { + var pdip = curr_drawinfo[prev_lineno]; + var idx = pdip.last_color_change; + var extrahpos = regno == 0x1000 + 0x10c ? 1 : 0; + var lastsync = false; + + if (idx > 0 && curr_color_changes[idx - 1].regno == 0xffff) { + idx--; + lastsync = true; + } + pdip.last_color_change++; + pdip.nr_color_changes++; + curr_color_changes[idx].linepos = (hpos + this.maxhpos) * 2 + extrahpos; + curr_color_changes[idx].regno = regno; + curr_color_changes[idx].value = value; + if (lastsync) { + curr_color_changes[idx + 1].linepos = hsyncstartpos * 2; + curr_color_changes[idx + 1].regno = 0xffff; + curr_color_changes[idx + 2].regno = -1; + } else + curr_color_changes[idx + 1].regno = -1; + } + this.record_color_change2(hpos, regno, value); + } + + this.isbrdblank = function(hpos, con0, con3) { + var brdblank = (AMIGA.config.chipset.mask & CSMASK_ECS_DENISE) != 0 && (con0 & 1) != 0 && (con3 & 0x20) != 0; + + if (hpos >= 0 && current_colors.borderblank != brdblank) { + if (!FAST_COLORS) { + this.record_color_change(hpos, 0, (COLOR_CHANGE_BRDBLANK | (brdblank ? 1 : 0)) >>> 0); + remembered_color_entry = -1; + } + current_colors.borderblank = brdblank; + } + return brdblank; + } + + this.record_register_change = function(hpos, regno, value) { + if (regno == 0x100) { // BPLCON0 + if (value & 0x800) + thisline_decision.ham_seen = 1; + thisline_decision.ehb_seen = is_ehb(value, bplcon2); + this.isbrdblank(hpos, value, bplcon3); + } else if (regno == 0x104) // BPLCON2 + thisline_decision.ehb_seen = is_ehb(bplcon0, value); + else if (regno == 0x106) // BPLCON3 + this.isbrdblank(hpos, bplcon0, value); + + if (!FAST_COLORS) + this.record_color_change(hpos, regno + 0x1000, value); + } + + /*---------------------------------*/ + + this.compute_vsynctime = function() { + if (AMIGA.config.chipset.refreshrate > 0) + this.vblank_hz = AMIGA.config.chipset.refreshrate; + + AMIGA.events.calc_vsynctimebase(this.vblank_hz); + + if (AMIGA.config.audio.enabled && AMIGA.config.audio.mode > 0) + AMIGA.audio.calc_sample_evtime(this.vblank_hz, (bplcon0 & 4) ? -1 : this.lof_store, this.is_linetoggle()); + } + + this.compute_framesync = function() { + var islace = interlace_seen ? 1 : 0; + var isntsc = (beamcon0 & 0x20) ? 0 : 1; + var found = false; + + interlace_changed = 0; + gfxvidinfo.drawbuffer.inxoffset = -1; + gfxvidinfo.drawbuffer.inyoffset = -1; + + if (beamcon0 & 0x80) { + var res = GET_RES_AGNUS(bplcon0); + var vres = islace ? 1 : 0; + var res2, vres2; + + res2 = AMIGA.config.video.hresolution; + if (doublescan > 0) + res2++; + if (res2 > RES_MAX) + res2 = RES_MAX; + + vres2 = AMIGA.config.video.vresolution; + if (doublescan > 0 && !islace) + vres2--; + + if (vres2 < 0) + vres2 = 0; + if (vres2 > VRES_QUAD) + vres2 = VRES_QUAD; + + var start = this.hbstrt; + var stop = this.hbstop; + + gfxvidinfo.drawbuffer.inwidth = (((start > stop ? (this.maxhpos - (this.maxhpos - start + stop)) : (this.maxhpos - (stop - start) + 2)) * 2) << res2); + gfxvidinfo.drawbuffer.inxoffset = ((stop + 1) & ~1) * 2; + + gfxvidinfo.drawbuffer.extrawidth = 0; + gfxvidinfo.drawbuffer.inwidth2 = gfxvidinfo.drawbuffer.inwidth; + + gfxvidinfo.drawbuffer.inheight = (this.maxvpos - minfirstline) << vres2; + gfxvidinfo.drawbuffer.inheight2 = gfxvidinfo.drawbuffer.inheight; + } else { + gfxvidinfo.drawbuffer.inwidth = AMIGA_WIDTH_MAX << AMIGA.config.video.hresolution; + gfxvidinfo.drawbuffer.extrawidth = AMIGA.config.video.extrawidth ? AMIGA.config.video.extrawidth : -1; + gfxvidinfo.drawbuffer.inwidth2 = gfxvidinfo.drawbuffer.inwidth; + gfxvidinfo.drawbuffer.inheight = (this.maxvpos_nom - minfirstline + 1) << AMIGA.config.video.vresolution; + gfxvidinfo.drawbuffer.inheight2 = gfxvidinfo.drawbuffer.inheight; + } + + if (gfxvidinfo.drawbuffer.inwidth > gfxvidinfo.drawbuffer.width_allocated) + gfxvidinfo.drawbuffer.inwidth = gfxvidinfo.drawbuffer.width_allocated; + if (gfxvidinfo.drawbuffer.inwidth2 > gfxvidinfo.drawbuffer.width_allocated) + gfxvidinfo.drawbuffer.inwidth2 = gfxvidinfo.drawbuffer.width_allocated; + + if (gfxvidinfo.drawbuffer.inheight > gfxvidinfo.drawbuffer.height_allocated) + gfxvidinfo.drawbuffer.inheight = gfxvidinfo.drawbuffer.height_allocated; + if (gfxvidinfo.drawbuffer.inheight2 > gfxvidinfo.drawbuffer.height_allocated) + gfxvidinfo.drawbuffer.inheight2 = gfxvidinfo.drawbuffer.height_allocated; + + gfxvidinfo.drawbuffer.outwidth = gfxvidinfo.drawbuffer.inwidth; + gfxvidinfo.drawbuffer.outheight = gfxvidinfo.drawbuffer.inheight; + + if (gfxvidinfo.drawbuffer.outwidth > gfxvidinfo.drawbuffer.width_allocated) + gfxvidinfo.drawbuffer.outwidth = gfxvidinfo.drawbuffer.width_allocated; + + if (gfxvidinfo.drawbuffer.outheight > gfxvidinfo.drawbuffer.height_allocated) + gfxvidinfo.drawbuffer.outheight = gfxvidinfo.drawbuffer.height_allocated; + + //if (target_graphics_buffer_update()) this.reset_drawing(); + + for (var i = 0; i < 2 * (MAXVPOS + 2) + 1; i++) //memset (line_decisions, 0, sizeof line_decisions); + line_decisions[i].clr(); + + this.compute_vsynctime(); + + BUG.info('%s mode%s%s V=%.4fHz H=%.4fHz (%dx%d+%d)', + isntsc ? 'NTSC' : 'PAL', + islace ? ' lace' : '', + doublescan > 0 ? ' dblscan' : '', + this.vblank_hz, + (AMIGA.config.video.ntsc ? CHIPSET_CLOCK_NTSC : CHIPSET_CLOCK_PAL) / (this.maxhpos + (this.is_linetoggle() ? 0.5 : 0)), + this.maxhpos, this.maxvpos, this.lof_store ? 1 : 0 + ); + } + + this.init_hz = function(fullinit) { + var isntsc, islace; + var odbl = doublescan, omaxvpos = this.maxvpos; + var ovblank = this.vblank_hz; + var hzc = 0; + + if (fullinit) + this.vpos_count = 0; + + this.vpos_count_diff = this.vpos_count; + + doublescan = 0; + //programmedmode = false; + if ((beamcon0 & 0xA0) != (new_beamcon0 & 0xA0)) + hzc = 1; + if (beamcon0 != new_beamcon0) { + BUG.info('init_hz() BEAMCON0 %04x -> %04x', beamcon0, new_beamcon0); + this.vpos_count_diff = this.vpos_count = 0; + } + beamcon0 = new_beamcon0; + isntsc = (beamcon0 & 0x20) ? 0 : 1; + islace = (interlace_seen) ? 1 : 0; + if (!(AMIGA.config.chipset.mask & CSMASK_ECS_AGNUS)) + isntsc = AMIGA.config.video.ntsc ? 1 : 0; + if (!isntsc) { + this.maxvpos = MAXVPOS_PAL; + this.maxhpos = MAXHPOS_PAL; + this.vblank_hz = VBLANK_HZ_PAL; + minfirstline = VBLANK_ENDLINE_PAL; + sprite_vblank_endline = VBLANK_SPRITE_PAL; + equ_vblank_endline = EQU_ENDLINE_PAL; + equ_vblank_toggle = true; + } else { + this.maxvpos = MAXVPOS_NTSC; + this.maxhpos = MAXHPOS_NTSC; + this.vblank_hz = VBLANK_HZ_NTSC; + minfirstline = VBLANK_ENDLINE_NTSC; + sprite_vblank_endline = VBLANK_SPRITE_NTSC; + equ_vblank_endline = EQU_ENDLINE_NTSC; + equ_vblank_toggle = false; + } + // long/short field refresh rate adjustment + //this.vblank_hz >>= (AMIGA.config.video.framerate > 1 ? 1 : 0); + this.vblank_hz = this.vblank_hz * (this.maxvpos * 2 + 1) / ((this.maxvpos + this.lof_current) * 2); + + this.maxvpos_nom = this.maxvpos; + if (this.vpos_count > 0) { + BUG.info('init_hz() poked VPOSW at %d', this.vpos_count); + // we come here if this.vpos_count != this.maxvpos and beamcon0 didn't change (someone poked VPOSW) + if (this.vpos_count < 10) + this.vpos_count = 10; + this.vblank_hz = (isntsc ? 15734 : 15625) / this.vpos_count; + this.maxvpos_nom = this.vpos_count - (this.lof_current ? 1 : 0); + this.reset_drawing(); + } + if (beamcon0 & 0x80) { + // programmable scanrates (ECS Agnus) + if (this.vtotal >= MAXVPOS) + this.vtotal = MAXVPOS - 1; + this.maxvpos = this.vtotal + 1; + if (this.htotal >= MAXHPOS) + this.htotal = MAXHPOS - 1; + this.maxhpos = this.htotal + 1; + this.vblank_hz = 227 * 312 * 50 / (this.maxvpos * this.maxhpos); + minfirstline = this.vsstop > this.vbstop ? this.vsstop : this.vbstop; + if (minfirstline > this.maxvpos / 2) + minfirstline = this.vsstop > this.vsstop ? this.vbstop : this.vsstop; + if (minfirstline < 2) + minfirstline = 2; + if (minfirstline >= this.maxvpos) + minfirstline = this.maxvpos - 1; + sprite_vblank_endline = minfirstline - 2; + this.maxvpos_nom = this.maxvpos; + equ_vblank_endline = -1; + doublescan = this.htotal <= 164 ? 1 : 0; + //programmedmode = true; + this.dumpsync(); + hzc = 1; + } + if (this.maxvpos_nom >= MAXVPOS) + this.maxvpos_nom = MAXVPOS; + if (AMIGA.config.video.scandoubler && doublescan == 0) + doublescan = -1; + + if (doublescan != odbl || this.maxvpos != omaxvpos) + hzc = 1; + if (this.vblank_hz < 10) + this.vblank_hz = 10; + if (this.vblank_hz > 300) + this.vblank_hz = 300; + this.maxhpos_short = this.maxhpos; + if (beamcon0 & 0x80) { + if (this.hbstrt > this.maxhpos) + hsyncstartpos = this.hbstrt; + else + hsyncstartpos = this.maxhpos + this.hbstrt; + if (this.hbstop > this.maxhpos) + hsyncendpos = this.maxhpos - this.hbstop; + else + hsyncendpos = this.hbstop; + } else { + hsyncstartpos = this.maxhpos_short + 13; + hsyncendpos = 24; + } + + AMIGA.events.eventtab[EV_HSYNC].evtime = AMIGA.events.currcycle + this.maxhpos * CYCLE_UNIT; + AMIGA.events.eventtab[EV_HSYNC].oldcycles = AMIGA.events.currcycle; + AMIGA.events.schedule(); + + if (hzc) { + interlace_seen = islace; + this.reset_drawing(); + } + + this.maxvpos_total = (AMIGA.config.chipset.mask & CSMASK_ECS_AGNUS) ? 2047 : 511; + if (this.maxvpos_total > MAXVPOS) + this.maxvpos_total = MAXVPOS; +/*#ifdef PICASSO96 + if (!p96refresh_active) { + maxvpos_stored = this.maxvpos; + maxhpos_stored = this.maxhpos; + vblank_hz_stored = this.vblank_hz; + } +#endif*/ + this.compute_framesync(); +/*#ifdef PICASSO96 + init_hz_p96 (); +#endif*/ + if (fullinit) + this.vpos_count_diff = this.maxvpos_nom; + } + + this.BPLxPTH = function(hpos, v, num) { + this.decide_line(hpos); + this.decide_fetch(hpos); + bplpt[num] = ((v << 16) | (bplpt[num] & 0xffff)) >>> 0; + bplptx[num] = ((v << 16) | (bplptx[num] & 0xffff)) >>> 0; + //BUG.info('%d:%d:BPL%dPTH %08X', hpos, this.vpos, num, bplpt[num]); + } + + this.BPLxPTL = function(hpos, v, num) { + this.decide_line(hpos); + this.decide_fetch(hpos); + //if (AMIGA.copper.access && this.is_bitplane_dma(hpos + 1) == num + 1) return; + + bplpt[num] = ((bplpt[num] & 0xffff0000) | (v & 0xfffe)) >>> 0; + bplptx[num] = ((bplptx[num] & 0xffff0000) | (v & 0xfffe)) >>> 0; + //BUG.info('%d:%d:BPL%dPTL %08X', hpos, this.vpos, num, bplpt[num]); + } + + this.BPLxDAT = function(hpos, v, num) { + if (num == 0 && hpos >= 7) { + this.decide_line(hpos); + this.decide_fetch(hpos); + } + bplxdat[num] = v; + if (num == 0 && hpos >= 7) { + bpl1dat_written = true; + bpl1dat_written_at_least_once = true; + if (thisline_decision.plfleft < 0) { + thisline_decision.plfleft = hpos & ~3; + this.reset_bpl_vars(); + this.compute_delay_offset(); + } + this.update_bpldats(hpos); + } + } + + this.BPLCON0_Denise = function(hpos, v, immediate) { + if (!(AMIGA.config.chipset.mask & CSMASK_ECS_DENISE)) + v &= ~0x00F1; + else if (!(AMIGA.config.chipset.mask & CSMASK_AGA)) + v &= ~0x00B0; + v &= ~(0x0200 | 0x0100 | 0x0080 | 0x0020); +/*#if SPRBORDER + v |= 1; +#endif*/ + if (bplcon0_d == v) + return; + + bplcon0_dd = -1; + if (is_ehb(bplcon0_d, bplcon2)) + v |= 0x80; + + if (immediate) + this.record_register_change(hpos, 0x100, v); + else + this.record_register_change(hpos, 0x100, (bplcon0_d & ~(0x800 | 0x400 | 0x80)) | (v & (0x0800 | 0x400 | 0x80 | 0x01))); + + bplcon0_d = v & ~0x80; + + if (AMIGA.config.chipset.mask & CSMASK_ECS_DENISE) { + this.decide_sprites(hpos); + sprres = expand_sprres(v, bplcon3); + } + if (thisline_decision.plfleft < 0) + this.update_denise(hpos); + } + + this.BPLCON0 = function(hpos, v) { + if (!(AMIGA.config.chipset.mask & CSMASK_ECS_DENISE)) + v &= ~0x00F1; + else if (!(AMIGA.config.chipset.mask & CSMASK_AGA)) + v &= ~0x00B0; + v &= ~(0x0080 | 0x0020); + +/*#if SPRBORDER + v |= 1; +#endif*/ + if (bplcon0 == v) + return; + + if (!this.issyncstopped()) { + vpos_previous = this.vpos; + hpos_previous = hpos; + } + + if ((bplcon0 & 4) != (v & 4)) + this.checklacecount((v & 4) != 0); + + bplcon0 = v; + + this.bpldmainitdelay(hpos); + + if (thisline_decision.plfleft < 0) + this.BPLCON0_Denise(hpos, v, true); + } + + this.BPLCON1 = function(hpos, v) { + if (!(AMIGA.config.chipset.mask & CSMASK_AGA)) + v &= 0xff; + if (bplcon1 == v) + return; + ddf_change = this.vpos; + this.decide_line(hpos); + this.decide_fetch(hpos); + bplcon1_hpos = hpos; + bplcon1 = v; + } + + this.BPLCON2 = function(hpos, v) { + if (!(AMIGA.config.chipset.mask & CSMASK_AGA)) + v &= 0x7f; + if (bplcon2 == v) + return; + this.decide_line(hpos); + bplcon2 = v; + this.record_register_change(hpos, 0x104, v); + } + + this.BPLCON3 = function(hpos, v) { + if (!(AMIGA.config.chipset.mask & CSMASK_ECS_DENISE)) + return; + if (!(AMIGA.config.chipset.mask & CSMASK_AGA)) { + v &= 0x003f; + v |= 0x0c00; + } +/*#if SPRBORDER + v |= 2; +#endif*/ + if (bplcon3 == v) + return; + this.decide_line(hpos); + this.decide_sprites(hpos); + bplcon3 = v; + sprres = expand_sprres(bplcon0, bplcon3); + this.record_register_change(hpos, 0x106, v); + } + +/*#ifdef AGA + this.BPLCON4 = function(hpos, v) { + if (!(AMIGA.config.chipset.mask & CSMASK_AGA)) + return; + if (bplcon4 == v) + return; + this.decide_line(hpos); + bplcon4 = v; + this.record_register_change(hpos, 0x10c, v); + } +#endif*/ + + function castWord(v) { return (v & 0x8000) ? (v - 0x10000) : v; } + + this.BPL1MOD = function(hpos, v) { + v &= ~1; + if (bpl1mod == castWord(v)) + return; + this.decide_line(hpos); + this.decide_fetch(hpos); + bpl1mod = castWord(v); + } + + this.BPL2MOD = function(hpos, v) { + v &= ~1; + if (bpl2mod == castWord(v)) + return; + this.decide_line(hpos); + this.decide_fetch(hpos); + bpl2mod = castWord(v); + } + + this.calcdiw = function() { + var hstrt = diwstrt & 0xFF; + var hstop = diwstop & 0xFF; + var vstrt = diwstrt >> 8; + var vstop = diwstop >> 8; + + // vertical in ECS Agnus + if (diwhigh_written && (AMIGA.config.chipset.mask & CSMASK_ECS_AGNUS)) { + vstrt |= (diwhigh & 7) << 8; + vstop |= ((diwhigh >> 8) & 7) << 8; + } else { + if ((vstop & 0x80) == 0) + vstop |= 0x100; + } + // horizontal in ECS Denise + if (diwhigh_written && (AMIGA.config.chipset.mask & CSMASK_ECS_DENISE)) { + hstrt |= ((diwhigh >> 5) & 1) << 8; + hstop |= ((diwhigh >> 13) & 1) << 8; + } else { + hstop += 0x100; + } + + diw_hstrt = hstrt; + diw_hstop = hstop; + + diwfirstword = coord_diw_to_window_x(hstrt); + diwlastword = coord_diw_to_window_x(hstop); + if (diwfirstword >= diwlastword) { + diwfirstword = 0; + diwlastword = max_diwlastword(); + } + if (diwfirstword < 0) + diwfirstword = 0; + + plffirstline = vstrt; + plflastline = vstop; + + plfstrt = ddfstrt; + plfstop = ddfstop; + /* probably not the correct place.. should use plf_state instead */ + if (AMIGA.config.chipset.mask & CSMASK_ECS_AGNUS) { + /* ECS/AGA and ddfstop > maxhpos == always-on display */ + if (plfstop > this.maxhpos) + plfstrt = 0; + if (plfstrt < HARD_DDF_START) + plfstrt = HARD_DDF_START; + plfstrt_start = plfstrt - 4; + } else { + /* OCS and ddfstrt >= ddfstop == ddfstop = max */ + if (plfstrt >= plfstop && plfstrt >= HARD_DDF_START) + plfstop = 0xff; + plfstrt_start = HARD_DDF_START - 2; + } + diw_change = 2; + //console.log('calcdiw', hstrt,hstop,vstrt,vstop, plfstrt,plfstop); + } + + this.DIWSTRT = function(hpos, v) { + if (diwstrt == v && !diwhigh_written) + return; + this.decide_diw(hpos); + this.decide_line(hpos); + diwhigh_written = false; + diwstrt = v; + this.calcdiw(); + } + + this.DIWSTOP = function(hpos, v) { + if (diwstop == v && !diwhigh_written) + return; + this.decide_diw(hpos); + this.decide_line(hpos); + diwhigh_written = false; + diwstop = v; + this.calcdiw(); + } + + this.DIWHIGH = function(hpos, v) { + if (!(AMIGA.config.chipset.mask & (CSMASK_ECS_DENISE | CSMASK_ECS_AGNUS))) + return; + if (!(AMIGA.config.chipset.mask & CSMASK_AGA)) + v &= ~(0x0008 | 0x0010 | 0x1000 | 0x0800); + v &= ~(0x8000 | 0x4000 | 0x0080 | 0x0040); + if (diwhigh_written && diwhigh == v) + return; + this.decide_line(hpos); + diwhigh_written = true; + diwhigh = v; + this.calcdiw(); + } + + this.DDFSTRT = function(hpos, v) { + v &= 0xfe; + if (!(AMIGA.config.chipset.mask & CSMASK_ECS_AGNUS)) + v &= 0xfc; + if (ddfstrt == v && hpos + 2 != ddfstrt) + return; + ddf_change = this.vpos; + this.decide_line(hpos); + ddfstrt_old_hpos = hpos; + ddfstrt = v; + this.calcdiw(); + /*if (ddfstop > 0xD4 && (ddfstrt & 4) == 4) { + static int last_warned; + last_warned = (last_warned + 1) & 4095; + if (last_warned == 0) BUG.info('WARNING! Very strange DDF values (%x %x).', ddfstrt, ddfstop); + }*/ + } + + this.DDFSTOP = function(hpos, v) { + v &= 0xfe; + if (!(AMIGA.config.chipset.mask & CSMASK_ECS_AGNUS)) + v &= 0xfc; + if (ddfstop == v && hpos + 2 != ddfstop) + return; + ddf_change = this.vpos; + this.decide_line(hpos); + this.decide_fetch(hpos); + ddfstop = v; + this.calcdiw(); + if (fetch_state != FETCH_NOT_STARTED) + this.estimate_last_fetch_cycle(hpos); + /*if (ddfstop > 0xD4 && (ddfstrt & 4) == 4) { + static int last_warned; + if (last_warned == 0) BUG.info('WARNING! Very strange DDF values (%x).', ddfstop); + last_warned = (last_warned + 1) & 4095; + }*/ + } + + this.FMODE = function(hpos, v) { + if (!(AMIGA.config.chipset.mask & CSMASK_AGA)) + v = 0; + v &= 0xC00F; + if (fmode == v) + return; + ddf_change = this.vpos; + fmode = v; + sprite_width = GET_SPRITEWIDTH(fmode); + this.bpldmainitdelay(hpos); + } + + this.checkautoscalecol0 = function() { + if (!AMIGA.copper.access || this.vpos < 20 || this.isbrdblank(-1, bplcon0, bplcon3)) + return; + // autoscale if copper changes COLOR00 on top or bottom of screen + if (this.vpos >= minfirstline) { + var vpos2 = autoscale_bordercolors ? minfirstline : this.vpos; + if (first_planes_vpos == 0) + first_planes_vpos = vpos2 - 2; + if (plffirstline_total == this.current_maxvpos()) + plffirstline_total = vpos2 - 2; + if (vpos2 > last_planes_vpos || vpos2 > plflastline_total) + plflastline_total = last_planes_vpos = vpos2 + 3; + autoscale_bordercolors = 0; + } else + autoscale_bordercolors++; + } + + this.COLOR_WRITE = function(hpos, v, num) { + //var colzero = false; + v &= 0xFFF; +/*#ifdef AGA + if (AMIGA.config.chipset.mask & CSMASK_AGA) { + int r,g,b; + int cr,cg,cb; + int colreg; + uae_u32 cval; + + if (bplcon2 & 0x0100) + return; + + colreg = ((bplcon3 >> 13) & 7) * 32 + num; + r = (v & 0xF00) >> 8; + g = (v & 0xF0) >> 4; + b = (v & 0xF) >> 0; + cr = current_colors.color_regs_aga[colreg] >> 16; + cg = (current_colors.color_regs_aga[colreg] >> 8) & 0xFF; + cb = current_colors.color_regs_aga[colreg] & 0xFF; + + if (bplcon3 & 0x200) { + cr &= 0xF0; cr |= r; + cg &= 0xF0; cg |= g; + cb &= 0xF0; cb |= b; + } else { + cr = r + (r << 4); + cg = g + (g << 4); + cb = b + (b << 4); + color_regs_aga_genlock[colreg] = v >> 15; + } + cval = (cr << 16) | (cg << 8) | cb; + if (cval && colreg == 0) + colzero = true; + + if (cval == current_colors.color_regs_aga[colreg]) + return; + + if (colreg == 0) + this.checkautoscalecol0 (); + + //Call this with the old table still intact. + this.record_color_change (hpos, colreg, cval); + remembered_color_entry = -1; + current_colors.color_regs_aga[colreg] = cval; + current_colors.acolors[colreg] = getxcolor (cval); + + } else { +#endif*/ + //if (num && v == 0) colzero = true; + + if (!FAST_COLORS) { + if (current_colors.color_regs_ecs[num] == v) + return; + } + if (num == 0) + this.checkautoscalecol0(); + + if (!FAST_COLORS) { + this.record_color_change(hpos, num, v); + remembered_color_entry = -1; + } + current_colors.color_regs_ecs[num] = v; + current_colors.acolors[num] = getxcolor(v); +/*#ifdef AGA + } +#endif*/ + } + + /*this.islightpentriggered = function() { + if (beamcon0 & 0x2000) // LPENDIS + return 0; + return lightpen_triggered > 0; + } + this.GETVPOS = function() { + return this.islightpentriggered() ? vpos_lpen : (this.issyncstopped() ? vpos_previous : this.vpos); + } + this.GETHPOS = function() { + return this.islightpentriggered() ? hpos_lpen : (this.issyncstopped() ? hpos_previous : this.hpos()); }*/ - - const RES_LORES = 0; - const RES_HIRES = 1; - const RES_SUPERHIRES = 2; + this.issyncstopped = function() { + return (bplcon0 & 2) != 0 && !AMIGA.config.chipset.genlock; + } + this.GETVPOS = function() { + return this.issyncstopped() ? vpos_previous : this.vpos; + } + this.GETHPOS = function() { + return this.issyncstopped() ? hpos_previous : this.hpos(); + } - this.GET_RES_DENISE = function (con0) { - //if (!(currprefs.chipset_mask & CSMASK_ECS_DENISE)) - con0 &= ~0x40; // SUPERHIRES - return (con0 & 0x8000) ? RES_HIRES : (con0 & 0x40) ? RES_SUPERHIRES : RES_LORES; - } - this.GET_RES_AGNUS = function (con0) { - //if (!(currprefs.chipset_mask & CSMASK_ECS_AGNUS)) - con0 &= ~0x40; // SUPERHIRES - return (con0 & 0x8000) ? RES_HIRES : (con0 & 0x40) ? RES_SUPERHIRES : RES_LORES; - } - this.GET_PLANES = function (con0) { - if ((con0 & 0x0010) && (con0 & 0x7000)) - return 0; // >8 planes = 0 planes - if (con0 & 0x0010) - return 8; // AGA 8-planes bit - return (con0 >> 12) & 7; // normal planes bits - } - - this.GET_PLANES_LIMIT = function (con0) { - var res = this.GET_RES_AGNUS (con0); - var planes = this.GET_PLANES (con0); - return real_bitplane_number[fetchmode][res][planes]; - } + const HPOS_OFFSET = 3; //(currprefs.cpu_model < 68020 ? 3 : 0) + this.VPOSR = function() { + var vp = this.GETVPOS(); + var hp = this.GETHPOS(); + //var vp = this.vpos; + //var hp = this.hpos(); + var csbit = 0; - this.setup_fmodes = function (hpos) { + if (hp + HPOS_OFFSET >= this.maxhpos) { + vp++; + if (vp >= this.maxvpos + this.lof_store) + vp = 0; + } + vp = (vp >> 8) & 7; + + if (AMIGA.config.chipset.agnus_rev >= 0) + csbit |= AMIGA.config.chipset.agnus_rev << 8; + else { +/*#ifdef AGA + csbit |= (AMIGA.config.chipset.mask & CSMASK_AGA) ? 0x2300 : 0; +#endif*/ + csbit |= (AMIGA.config.chipset.mask & CSMASK_ECS_AGNUS) ? 0x2000 : 0; + if (AMIGA.mem.chip.size > 1024 * 1024 && (AMIGA.config.chipset.mask & CSMASK_ECS_AGNUS)) + csbit |= 0x2100; + if (AMIGA.config.video.ntsc) + csbit |= 0x1000; + } + + if (!(AMIGA.config.chipset.mask & CSMASK_ECS_AGNUS)) + vp &= 1; + vp = vp | (this.lof_store ? 0x8000 : 0) | csbit; + if (AMIGA.config.chipset.mask & CSMASK_ECS_AGNUS) + vp |= this.lol ? 0x80 : 0; + + //BUG.info('VPOSR $%x', vp); + return vp; + } + + this.VPOSW = function(v) { + if (this.lof_store != ((v & 0x8000) ? 1 : 0)) { + this.lof_store = (v & 0x8000) ? 1 : 0; + this.lof_changing = this.lof_store ? 1 : -1; + } + if (AMIGA.config.chipset.mask & CSMASK_ECS_AGNUS) { + this.lol = (v & 0x0080) ? 1 : 0; + if (!this.is_linetoggle()) + this.lol = 0; + } + if (this.lof_changing) + return; + + v &= 7; + if (!(AMIGA.config.chipset.mask & CSMASK_ECS_AGNUS)) + v &= 1; + + this.vpos &= 0x00ff; + this.vpos |= v << 8; + //BUG.info('VPOSW $%x', this.vpos); + } + + this.VHPOSW = function(v) { + this.vpos &= 0xff00; + this.vpos |= v >> 8; + //BUG.info('VHPOSW %x %d', v, this.vpos); + } + + this.VHPOSR = function() { + var vp = this.GETVPOS(); + var hp = this.GETHPOS(); + //var vp = this.vpos; + //var hp = this.hpos(); + + hp += HPOS_OFFSET; + if (hp >= this.maxhpos) { + hp -= this.maxhpos; + vp++; + if (vp >= this.maxvpos + this.lof_store) + vp = 0; + } + if (HPOS_OFFSET) { + hp += 1; + if (hp >= this.maxhpos) + hp -= this.maxhpos; + } + vp &= 0xff; + hp &= 0xff; + + vp <<= 8; + vp |= hp; + + //BUG.info('VHPOSR $%x', vp); + return vp; + } + + this.BEAMCON0 = function(v) { + if (AMIGA.config.chipset.mask & CSMASK_ECS_AGNUS) { + if (!(AMIGA.config.chipset.mask & CSMASK_ECS_DENISE)) + v &= 0x20; + + if (v != new_beamcon0) { + new_beamcon0 = v; + if (v & ~0x20) + BUG.info('BEAMCON0() $%04x written.', v); + } + } + } + + this.DENISEID = function() { + if (AMIGA.config.chipset.denise_rev >= 0) + return [0, AMIGA.config.chipset.denise_rev]; +/*#ifdef AGA + if (AMIGA.config.chipset.mask & CSMASK_AGA) { + if (currprefs.cs_ide == IDE_A4000) return [0, 0xFCF8]; + return [0, 0x00F8]; + } +#endif*/ + if (AMIGA.config.chipset.mask & CSMASK_ECS_DENISE) + return [0, 0xFFFC]; + + if (AMIGA.config.cpu.model == 68000 && AMIGA.config.cpu.compatible) + return [1, 0xFFFF]; + return [0, 0xFFFF]; + } + + /*---------------------------------*/ + + this.is_bitplane_dma = function(hpos) { + if (hpos < plfstrt) + return 0; + if ((plf_state == PLF_END && hpos >= thisline_decision.plfright) || hpos >= estimated_last_fetch_cycle) + return 0; + + return curr_diagram[(hpos - cycle_diagram_shift) & fetchstart_mask]; + } + + this.update_denise = function(hpos) { + toscr_res = GET_RES_DENISE(bplcon0_d); + if (bplcon0_dd != bplcon0_d) { + this.record_color_change2(hpos, 0x100 + 0x1000, bplcon0_d); + bplcon0_dd = bplcon0_d; + } + toscr_nr_planes = GET_PLANES(bplcon0_d); + + if (!(AMIGA.config.chipset.mask & CSMASK_AGA) && bplcon0_res == 0 && bplcon0_planes == 7) { //OCS 7 planes + if (toscr_nr_planes2 < 6) + toscr_nr_planes2 = 6; + } else + toscr_nr_planes2 = toscr_nr_planes; + } + + this.setup_fmodes = function(hpos) { switch (fmode & 3) { case 0: fetchmode = 0; @@ -1327,50 +4703,1543 @@ function Playfield() { fetchmode = 2; break; } - //badmode = GET_RES_AGNUS (bplcon0) != GET_RES_DENISE (this.bplcon0); - bplcon0_res = this.GET_RES_AGNUS (this.bplcon0); - bplcon0_planes = this.GET_PLANES (this.bplcon0); - bplcon0_planes_limit = this.GET_PLANES_LIMIT (this.bplcon0); - //console.log(bplcon0_res, bplcon0_planes, bplcon0_planes_limit); + badmode = GET_RES_AGNUS(bplcon0) != GET_RES_DENISE(bplcon0); + bplcon0_res = GET_RES_AGNUS(bplcon0); + bplcon0_planes = GET_PLANES(bplcon0); + bplcon0_planes_limit = GET_PLANES_LIMIT(bplcon0); fetchunit = fetchunits[fetchmode * 4 + bplcon0_res]; fetchunit_mask = fetchunit - 1; fetchstart_shift = fetchstarts[fetchmode * 4 + bplcon0_res]; fetchstart = 1 << fetchstart_shift; fetchstart_mask = fetchstart - 1; - /*fm_maxplane_shift = fm_maxplanes[fetchmode * 4 + bplcon0_res]; + fm_maxplane_shift = fm_maxplanes[fetchmode * 4 + bplcon0_res]; fm_maxplane = 1 << fm_maxplane_shift; - fetch_modulo_cycle = fetchunit - fetchstart; - if (is_bitplane_dma (hpos - 1)) cycle_line[hpos - 1] = 1;*/ + fetch_modulo_cycle = fetchunit - fetchstart; curr_diagram = cycle_diagram_table[fetchmode][bplcon0_res][bplcon0_planes_limit]; - //console.log(curr_diagram); - //console.log(fetchstart_mask); - //estimate_last_fetch_cycle (hpos); - //if (bpldmasetuphpos >= 0 && debug_dma) record_dma_event (DMA_EVENT_BPLFETCHUPDATE, hpos, vpos); - /*bpldmasetuphpos = -1; + this.estimate_last_fetch_cycle(hpos); + bpldmasetuphpos = -1; bpldmasetupphase = 0; - ddf_change = vpos;*/ - //console.log('setup_fmodes()', fetchstart, fetchstart_shift, fetchstart_mask, curr_diagram); + ddf_change = this.vpos; + } + + this.maybe_setup_fmodes = function(hpos) { + switch (bpldmasetupphase) { + case 0: + this.BPLCON0_Denise(hpos, bplcon0, false); + bpldmasetupphase++; + bpldmasetuphpos += (4 + (bplcon0_planes == 8 ? 1 : 0)) - BPLCON_DENISE_DELAY; + break; + case 1: + this.setup_fmodes(hpos); + break; + } } - this.is_bitplane_dma = function (hpos) { - if (hpos < this.state.dstart*2) //plfstrt) - return 0; - //if ((plf_state == plf_end && hpos >= thisline_decision.plfright) || hpos >= estimated_last_fetch_cycle) - if (hpos >= this.state.dstop*2) //|| hpos >= estimated_last_fetch_cycle) - return 0; + this.maybe_check = function(hpos) { + if (bpldmasetuphpos > 0 && hpos >= bpldmasetuphpos) + this.maybe_setup_fmodes(hpos); + } - //console.log(hpos - this.state.hstart); - //return curr_diagram[(hpos - cycle_diagram_shift) & fetchstart_mask]; - return curr_diagram[hpos & fetchstart_mask]; + this.compute_delay_offset = function() { + delayoffset = (16 << fetchmode) - (((plfstrt - HARD_DDF_START) & fetchstart_mask) << 1); + } + + this.compute_toscr_delay_1 = function(con1) { + var delay1 = (con1 & 0x0f) | ((con1 & 0x0c00) >> 6); + var delay2 = ((con1 >> 4) & 0x0f) | (((con1 >> 4) & 0x0c00) >> 6); + var shdelay1 = (con1 >> 12) & 3; + var shdelay2 = (con1 >> 8) & 3; + var delaymask; + var fetchwidth = 16 << fetchmode; + + delay1 += delayoffset; + delay2 += delayoffset; + delaymask = (fetchwidth - 1) >> toscr_res; + toscr_delay1 = (delay1 & delaymask) << toscr_res; + toscr_delay1 |= shdelay1 >> (RES_MAX - toscr_res); + toscr_delay2 = (delay2 & delaymask) << toscr_res; + toscr_delay2 |= shdelay2 >> (RES_MAX - toscr_res); } - this.get_data = function() { - return [ - this.state.hstart, - this.state.hstop - (16 << fetchmode), - cycle_diagram_total_cycles[fetchmode][this.GET_RES_AGNUS(this.bplcon0)][this.GET_PLANES_LIMIT(this.bplcon0)], - cycle_diagram_free_cycles[fetchmode][this.GET_RES_AGNUS(this.bplcon0)][this.GET_PLANES_LIMIT(this.bplcon0)] - ] + this.compute_toscr_delay = function(hpos, con1) { + this.update_denise(hpos); + this.compute_toscr_delay_1(con1); + } + + this.update_toscr_planes = function() { + if (toscr_nr_planes2 > thisline_decision.nr_planes) { + for (var j = thisline_decision.nr_planes; j < toscr_nr_planes2; j++) { + if (!thisline_changed) { + for (var i = 0; i < out_offs; i++) { + if (line_data[next_lineno][j][i]) { + thisline_changed = 1; + break; + } + } + } + for (var i = 0; i < out_offs; i++) line_data[next_lineno][j][i] = 0; //memset(ptr, 0, out_offs * 4); + } + thisline_decision.nr_planes = toscr_nr_planes2; + } + } + + this.maybe_first_bpl1dat = function(hpos) { + if (thisline_decision.plfleft >= 0) { + if (plfleft_real < 0) { + for (var i = 0; i < MAX_PLANES; i++) { + todisplay[i][0] = 0; +/*#ifdef AGA + todisplay[i][1] = 0; + todisplay[i][2] = 0; + todisplay[i][3] = 0; +#endif*/ + } + plfleft_real = hpos; + bpl1dat_early = true; + } + } else { + plfleft_real = thisline_decision.plfleft = hpos; + this.compute_delay_offset(); + } + } + + this.checklacecount = function(lace) { + if (lace === null) + lace = (bplcon0 & 4) != 0; + + if (!interlace_changed) { + if (nlace_cnt >= NLACE_CNT_NEEDED && lace) { + lof_togglecnt_lace = LOF_TOGGLES_NEEDED; + lof_togglecnt_nlace = 0; + //BUG.info('immediate lace'); + nlace_cnt = 0; + } else if (nlace_cnt <= -NLACE_CNT_NEEDED && !lace) { + lof_togglecnt_nlace = LOF_TOGGLES_NEEDED; + lof_togglecnt_lace = 0; + //BUG.info('immediate nlace'); + nlace_cnt = 0; + } + } + if (lace) { + if (nlace_cnt > 0) + nlace_cnt = 0; + nlace_cnt--; + if (nlace_cnt < -NLACE_CNT_NEEDED * 2) + nlace_cnt = -NLACE_CNT_NEEDED * 2; + } else if (!lace) { + if (nlace_cnt < 0) + nlace_cnt = 0; + nlace_cnt++; + if (nlace_cnt > NLACE_CNT_NEEDED * 2) + nlace_cnt = NLACE_CNT_NEEDED * 2; + } } + var dumpcnt = 100; + this.dumpsync = function() { + if (dumpcnt < 0) + return; + dumpcnt--; + BUG.info('BEAMCON0=%04X VTOTAL=%04X HTOTAL=%04X', new_beamcon0, this.vtotal, this.htotal); + BUG.info(' HSSTOP=%04X HBSTRT=%04X HBSTOP=%04X', this.hsstop, this.hbstrt, this.hbstop); + BUG.info(' VSSTOP=%04X VBSTRT=%04X VBSTOP=%04X', this.vsstop, this.vbstrt, this.vbstop); + BUG.info(' HSSTRT=%04X VSSTRT=%04X HCENTER=%04X', this.hsstrt, this.vsstrt, this.hcenter); + } + + this.varsync = function() { + //console.log('varsync()'); + if (!CUSTOM_SIMPLE) { + if (!(AMIGA.config.chipset.mask & CSMASK_ECS_AGNUS)) + return; + if (!(beamcon0 & 0x80)) + return; + this.vpos_count = 0; + //this.dumpsync(); + } + } + + this.count_frame = function() { + if (++this.framecnt >= AMIGA.config.video.framerate) + this.framecnt = 0; + } + + this.vsync_handle_redraw = function() { //(long_frame, lof_changed, bplcon0p, bplcon3p) + last_redraw_point++; + if (this.lof_changed || this.lof_store || interlace_seen <= 0 || doublescan < 0 || last_redraw_point >= 2) { + last_redraw_point = 0; + + if (this.framecnt == 0) + this.finish_drawing_frame(); +/*#if 0 + if (interlace_seen > 0) + interlace_seen = -1; + else if (interlace_seen == -1) { + interlace_seen = 0; + if (currprefs.scandoubler && currprefs.vresolution) + notice_screen_contents_lost (); + } +#endif*/ + this.count_frame(); + + if (this.framecnt == 0) + this.init_drawing_frame(); + } + } + + this.init_hardware_frame = function() { + first_bpl_vpos = -1; + next_lineno = 0; + prev_lineno = -1; + nextline_how = NLN_NORMAL; + diwstate = DIW_WAITING_START; + ddfstate = DIW_WAITING_START; + first_planes_vpos = 0; + last_planes_vpos = 0; + diwfirstword_total = max_diwlastword(); + diwlastword_total = 0; + ddffirstword_total = max_diwlastword(); + ddflastword_total = 0; + plflastline_total = 0; + plffirstline_total = this.current_maxvpos(); + autoscale_bordercolors = 0; + for (var i = 0; i < MAX_SPRITES; i++) + spr[i].ptxhpos = MAXHPOS; + } + + this.init_hardware_for_drawing_frame = function() { + if (prev_sprite_entries) { + var first_pixel = prev_sprite_entries[0].first_pixel; + var npixels = prev_sprite_entries[prev_next_sprite_entry].first_pixel - first_pixel; + for (var i = 0; i < npixels; i++) spixels[first_pixel + i] = 0; //memset (spixels + first_pixel, 0, npixels * sizeof *spixels); + for (var i = 0; i < npixels; i++) spixstate[first_pixel + i] = 0; //memset (spixstate.bytes + first_pixel, 0, npixels * sizeof *spixstate.bytes); + } + prev_next_sprite_entry = next_sprite_entry; + + next_color_change = 0; + next_sprite_entry = 0; + next_color_entry = 0; + remembered_color_entry = -1; + + prev_sprite_entries = sprite_entries[current_change_set]; + curr_sprite_entries = sprite_entries[current_change_set ^ 1]; + prev_color_changes = color_changes[current_change_set]; + curr_color_changes = color_changes[current_change_set ^ 1]; + prev_color_tables = color_tables[current_change_set]; + curr_color_tables = color_tables[current_change_set ^ 1]; + + prev_drawinfo = line_drawinfo[current_change_set]; + curr_drawinfo = line_drawinfo[current_change_set ^ 1]; + current_change_set ^= 1; + + color_src_match = color_dest_match = -1; + + curr_sprite_entries[0].first_pixel = current_change_set * MAX_SPR_PIXELS; + next_sprite_forced = 1; + } + + this.reset_decisions = function() { + if (this.nodraw()) + return; + + plfleft_real = -1; + toscr_nr_planes = toscr_nr_planes2 = 0; + + bpl1dat_written = false; + bpl1dat_written_at_least_once = false; + bpl1dat_early = false; + + thisline_decision.bplres = bplcon0_res; + thisline_decision.nr_planes = 0; + thisline_decision.plfleft = -1; + thisline_decision.plflinelen = -1; + thisline_decision.ham_seen = !!(bplcon0 & 0x800); + thisline_decision.ehb_seen = !!is_ehb(bplcon0, bplcon2); + thisline_decision.ham_at_start = !!(bplcon0 & 0x800); + + thisline_decision.diwfirstword = -1; + thisline_decision.diwlastword = -1; + if (hdiwstate == DIW_WAITING_STOP) { + thisline_decision.diwfirstword = 0; + if (SMART_UPDATE) { + if (thisline_decision.diwfirstword != line_decisions[next_lineno].diwfirstword) + thisline_changed = 1; //MARK_LINE_CHANGED; + } + } + thisline_decision.ctable = -1; + thisline_changed = 0; + + curr_drawinfo[next_lineno].first_color_change = next_color_change; + curr_drawinfo[next_lineno].first_sprite_entry = next_sprite_entry; + + next_sprite_forced = 1; + last_sprite_point = 0; + fetch_state = FETCH_NOT_STARTED; + bplcon1_hpos = -1; + if (bpldmasetuphpos >= 0) { + this.BPLCON0_Denise(0, bplcon0, true); + this.setup_fmodes(0); + } + bpldmasetuphpos = -1; + bpldmasetupphase = 0; + ddfstrt_old_hpos = -1; + + if (plf_state > PLF_ACTIVE || (plf_state == PLF_ACTIVE && !(AMIGA.config.chipset.mask & CSMASK_ECS_AGNUS))) + plf_state = PLF_IDLE; + + /*memset (todisplay, 0, sizeof todisplay); + memset (fetched, 0, sizeof fetched); + memset (fetched_aga0, 0, sizeof fetched_aga0); + memset (fetched_aga1, 0, sizeof fetched_aga1); + memset (outword, 0, sizeof outword);*/ + for (var i = 0; i < MAX_PLANES; i++) { + for (var j = 0; j < 4; j++) + todisplay[i][j] = 0; + + fetched[i] = 0; +/*#ifdef AGA + if (AMIGA.config.chipset.mask & CSMASK_AGA) { + fetched_aga0[i] = 0; + fetched_aga1[i] = 0; + } +#endif*/ + outword[i] = 0; + } + + last_decide_line_hpos = -1; + last_ddf_pix_hpos = -1; + last_sprite_hpos = -1; + last_fetch_hpos = -1; + + thisline_decision.bplcon0 = bplcon0; + thisline_decision.bplcon2 = bplcon2; + thisline_decision.bplcon3 = bplcon3; +/*#ifdef AGA + thisline_decision.bplcon4 = bplcon4; +#endif*/ + } + + this.record_diw_line = function(plfstrt, first, last) { + if (last > max_diwstop) + max_diwstop = last; + if (first < min_diwstart) { + min_diwstart = first; + /* + if (plfstrt * 2 > min_diwstart) + min_diwstart = plfstrt * 2; + */ + } + } + + this.sprites_differ = function(dip, dip_old) { + var this_first = curr_sprite_entries[dip.first_sprite_entry]; + var this_last = curr_sprite_entries[dip.last_sprite_entry]; + var prev_first = prev_sprite_entries[dip_old.first_sprite_entry]; + + if (dip.nr_sprites != dip_old.nr_sprites) + return 1; + + if (dip.nr_sprites == 0) + return 0; + + /*for (var i = 0; i < dip.nr_sprites; i++) { //FIXME + if (this_first[i].pos != prev_first[i].pos + || this_first[i].max != prev_first[i].max + || this_first[i].has_attached != prev_first[i].has_attached) + return 1; + }*/ + if (this_first.pos != prev_first.pos || this_first.max != prev_first.max || this_first.has_attached != prev_first.has_attached) //FIX + return 1; + + var npixels = this_last.first_pixel + (this_last.max - this_last.pos) - this_first.first_pixel; + + //if (memcmp (spixels + this_first.first_pixel, spixels + prev_first.first_pixel, npixels * sizeof (uae_u16)) != 0) return 1; + for (i = 0; i < npixels; i++) { + if (spixels[this_first.first_pixel + i] != spixels[prev_first.first_pixel + i]) + return 1; + } + //if (memcmp (spixstate.bytes + this_first.first_pixel, spixstate.bytes + prev_first.first_pixel, npixels) != 0) return 1; + for (i = 0; i < npixels; i++) { + if (spixstate[this_first.first_pixel + i] != spixstate[prev_first.first_pixel + i]) + return 1; + } + return 0; + } + + this.color_changes_differ = function(dip, dip_old) { + if (dip.nr_color_changes != dip_old.nr_color_changes) + return 1; + if (dip.nr_color_changes == 0) + return 0; + //if (memcmp(curr_color_changes + dip.first_color_change, prev_color_changes + dip_old.first_color_change, dip.nr_color_changes * sizeof *curr_color_changes) != 0) + for (i = 0; i < dip.nr_color_changes; i++) { + if (curr_color_changes[dip.first_color_change + i].cmp(prev_color_changes[dip_old.first_color_change + i]) != 0) + return 1; + } + return 0; + } + + this.finish_decisions = function() { + var hpos = this.maxhpos; + + if (this.nodraw()) + return; + + this.decide_diw(hpos); + this.decide_line(hpos); + this.decide_fetch(hpos); + + this.record_color_change2(hsyncstartpos, 0xffff, 0); + if (thisline_decision.plfleft >= 0 && thisline_decision.plflinelen < 0) { + if (fetch_state != FETCH_NOT_STARTED) { + BUG.info('finish_decisions() fetch_state=%d plfleft=%d,len=%d,vpos=%d,hpos=%d', fetch_state, thisline_decision.plfleft, thisline_decision.plflinelen, this.vpos, hpos); + Fatal(333, 'finish_decisions() fetch_state != FETCH_NOT_STARTED'); + } + thisline_decision.plfright = thisline_decision.plfleft; + thisline_decision.plflinelen = 0; + thisline_decision.bplres = RES_LORES; + } + if (hdiwstate == DIW_WAITING_STOP) { + thisline_decision.diwlastword = max_diwlastword(); + if (thisline_decision.diwfirstword < 0) + thisline_decision.diwfirstword = 0; + } + if (SMART_UPDATE) { + if (thisline_decision.diwfirstword != line_decisions[next_lineno].diwfirstword) + thisline_changed = 1; //MARK_LINE_CHANGED; + if (thisline_decision.diwlastword != line_decisions[next_lineno].diwlastword) + thisline_changed = 1; //MARK_LINE_CHANGED; + } + var dip = curr_drawinfo[next_lineno]; + var dip_old = prev_drawinfo[next_lineno]; + var dp = line_decisions[next_lineno]; + var changed = thisline_changed; + if (thisline_decision.plfleft >= 0 && thisline_decision.nr_planes > 0) + this.record_diw_line(thisline_decision.plfleft, diwfirstword, diwlastword); + + this.decide_sprites(hpos + 1); + + dip.last_sprite_entry = next_sprite_entry; + dip.last_color_change = next_color_change; + + if (thisline_decision.ctable < 0) + this.remember_ctable(); + + dip.nr_color_changes = next_color_change - dip.first_color_change; + dip.nr_sprites = next_sprite_entry - dip.first_sprite_entry; + + if (thisline_decision.plfleft != line_decisions[next_lineno].plfleft) + changed = 1; + if (!changed && this.color_changes_differ(dip, dip_old)) + changed = 1; + if (!changed && /* bitplane visible in this line OR border sprites enabled */ + (thisline_decision.plfleft >= 0 || ((thisline_decision.bplcon0 & 1) && (thisline_decision.bplcon3 & 0x02) && !(thisline_decision.bplcon3 & 0x20))) + && this.sprites_differ(dip, dip_old)) + changed = 1; + + if (changed) { + thisline_changed = 1; + dp.set(thisline_decision); //*dp = thisline_decision; + } else + line_decisions[next_lineno].ctable = thisline_decision.ctable; + + next_color_change += ((HBLANK_OFFSET + 1) >> 1); + + diw_hcounter += this.maxhpos * 2; + if (!(AMIGA.config.chipset.mask & CSMASK_ECS_DENISE) && this.vpos == this.get_equ_vblank_endline() - 1) + diw_hcounter++; + if ((AMIGA.config.chipset.mask & CSMASK_ECS_DENISE) || this.vpos > this.get_equ_vblank_endline() || (AMIGA.config.chipset.agnus_dip && this.vpos == 0)) { + diw_hcounter = this.maxhpos * 2; + last_hdiw = 1; //2 - 1; + } + if (next_color_change >= MAX_REG_CHANGE - 30) { + BUG.info('color_change buffer overflow!'); + next_color_change = 0; + dip.nr_color_changes = 0; + dip.first_color_change = 0; + dip.last_color_change = 0; + } + } + + this.hsync_record_line_state = function(lineno, how, changed) { + if (this.framecnt != 0) + return; + + //changed += ((frame_redraw_necessary ? 1 : 0) + ((lineno >= lightpen_y1 && lineno <= lightpen_y2) ? 1 : 0)); + changed += (frame_redraw_necessary ? 1 : 0) + + switch (how) { + case NLN_NORMAL: + linestate[lineno] = changed ? LINE_DECIDED : LINE_DONE; + break; + case NLN_DOUBLED: + linestate[lineno] = changed ? LINE_DECIDED_DOUBLE : LINE_DONE; + changed += (linestate[lineno + 1] != LINE_REMEMBERED_AS_PREVIOUS ? 1 : 0); + linestate[lineno + 1] = changed ? LINE_AS_PREVIOUS : LINE_DONE_AS_PREVIOUS; + break; + case NLN_NBLACK: + linestate[lineno] = changed ? LINE_DECIDED : LINE_DONE; + if (linestate[lineno + 1] != LINE_REMEMBERED_AS_BLACK) + linestate[lineno + 1] = LINE_BLACK; + break; + case NLN_LOWER: + if (linestate[lineno - 1] == LINE_UNDECIDED) + linestate[lineno - 1] = LINE_DECIDED; //LINE_BLACK; + linestate[lineno] = changed ? LINE_DECIDED : LINE_DONE; + break; + case NLN_UPPER: + linestate[lineno] = changed ? LINE_DECIDED : LINE_DONE; + if (linestate[lineno + 1] == LINE_UNDECIDED + || linestate[lineno + 1] == LINE_REMEMBERED_AS_PREVIOUS + || linestate[lineno + 1] == LINE_AS_PREVIOUS) + linestate[lineno + 1] = LINE_DECIDED; //LINE_BLACK; + break; + } + } + + this.get_equ_vblank_endline = function() { + return equ_vblank_endline + (equ_vblank_toggle ? (this.lof_current ? 1 : 0) : 0); + } + + this.decide_diw = function(hpos) { + var hdiw = hpos >= this.maxhpos ? this.maxhpos * 2 + 1 : hpos * 2 + 2; + if (!(AMIGA.config.chipset.mask & CSMASK_ECS_DENISE) && this.vpos <= this.get_equ_vblank_endline()) + hdiw = diw_hcounter; + + hdiw &= 511; + for (;;) { + var lhdiw = hdiw; + if (last_hdiw > lhdiw) + lhdiw = 512; + + if (lhdiw >= diw_hstrt && last_hdiw < diw_hstrt && hdiwstate == DIW_WAITING_START) { + if (thisline_decision.diwfirstword < 0) + thisline_decision.diwfirstword = diwfirstword < 0 ? 0 : diwfirstword; + hdiwstate = DIW_WAITING_STOP; + } + if (lhdiw >= diw_hstop && last_hdiw < diw_hstop && hdiwstate == DIW_WAITING_STOP) { + if (thisline_decision.diwlastword < 0) + thisline_decision.diwlastword = diwlastword < 0 ? 0 : diwlastword; + hdiwstate = DIW_WAITING_START; + } + if (lhdiw != 512) + break; + last_hdiw = -1; //0 - 1; + } + last_hdiw = hdiw; + } + + this.reset_bpl_vars = function(hpos) { + out_nbits = 0; + out_offs = 0; + toscr_nbits = 0; + thisline_decision.bplres = bplcon0_res; + } + + this.start_bpl_dma = function(hpos, hstart) { + if (first_bpl_vpos < 0) + first_bpl_vpos = this.vpos; + + if (this.doflickerfix() && interlace_seen > 0 && !scandoubled_line) { + for (var i = 0; i < 8; i++) { + prevbpl[this.lof_current][this.vpos][i] = bplptx[i]; + if (!this.lof_current && (bplcon0 & 4)) + bplpt[i] = prevbpl[1 - this.lof_current][this.vpos][i]; + if (!(bplcon0 & 4) || interlace_seen < 0) + prevbpl[1 - this.lof_current][this.vpos][i] = prevbpl[this.lof_current][this.vpos][i] = 0; + } + } + plfstrt_sprite = plfstrt; + fetch_state = FETCH_STARTED; + fetch_cycle = 0; + + ddfstate = DIW_WAITING_STOP; + this.compute_toscr_delay(last_fetch_hpos, bplcon1); + + if (bpl1dat_written_at_least_once && hstart > last_fetch_hpos) { + this.update_fetch_x(hstart, fetchmode); + bpl1dat_written_at_least_once = false; + } else + this.reset_bpl_vars(); +/*#if 0 + if (!this.nodraw ()) { + if (thisline_decision.plfleft >= 0) { + out_nbits = (plfstrt - thisline_decision.plfleft) << (1 + toscr_res); + out_offs = out_nbits >> 5; + out_nbits &= 31; + } + this.update_toscr_planes(); + } +#endif*/ + last_fetch_hpos = hstart; + cycle_diagram_shift = hstart; + } + + this.maybe_start_bpl_dma = function(hpos) { + //console.log('maybe_start_bpl_dma', hpos); + if (!(AMIGA.config.chipset.mask & CSMASK_ECS_AGNUS)) + return; + if (fetch_state != FETCH_NOT_STARTED) + return; + if (diwstate != DIW_WAITING_STOP) + return; + if (hpos <= plfstrt) + return; + if (hpos > plfstop - fetchunit) + return; + if (ddfstate != DIW_WAITING_START) + plf_state = PLF_PASSED_STOP; + + this.start_bpl_dma(hpos, hpos); + } + + this.decide_line = function(hpos) { + if (this.vpos == plffirstline) { + diwstate = DIW_WAITING_STOP; + ddf_change = this.vpos; + } + if (this.vpos == plflastline) { + diwstate = DIW_WAITING_START; + ddf_change = this.vpos; + } + if (hpos <= last_decide_line_hpos) + return; + + if (fetch_state == FETCH_NOT_STARTED && (diwstate == DIW_WAITING_STOP || (AMIGA.config.chipset.mask & CSMASK_ECS_AGNUS))) { + var ok = 0; + if (last_decide_line_hpos < plfstrt_start && hpos >= plfstrt_start) { + if (plf_state == PLF_IDLE) + plf_state = PLF_START; + } + if (last_decide_line_hpos < plfstrt && hpos >= plfstrt) { + if (plf_state == PLF_START) + plf_state = PLF_ACTIVE; + if (plf_state == PLF_ACTIVE) + ok = 1; + if (hpos - 2 == ddfstrt_old_hpos) + ok = 0; + } + if (ok && diwstate == DIW_WAITING_STOP) { + if (AMIGA.dmaen(DMAF_BPLEN)) { + this.start_bpl_dma(hpos, plfstrt); + this.estimate_last_fetch_cycle(plfstrt); + } + last_decide_line_hpos = hpos; + if (!CUSTOM_SIMPLE) + this.do_sprites(hpos); + + return; + } + } + if (!CUSTOM_SIMPLE) { + if (hpos > last_sprite_hpos && last_sprite_hpos < SPR0_HPOS + 4 * MAX_SPRITES) + this.do_sprites(hpos); + } + last_decide_line_hpos = hpos; + } + + /*---------------------------------*/ + /* to screen */ + + this.toscr_2_ecs = function(nbits) { + var delay1 = toscr_delay1; + var delay2 = toscr_delay2; + var mask = 0xffff >> (16 - nbits); + var i; + + for (i = 0; i < toscr_nr_planes2; i += 2) { + outword[i] <<= nbits; + outword[i] |= (todisplay[i][0] >> (16 - nbits + delay1)) & mask; + todisplay[i][0] <<= nbits; + } + for (i = 1; i < toscr_nr_planes2; i += 2) { + outword[i] <<= nbits; + outword[i] |= (todisplay[i][0] >> (16 - nbits + delay2)) & mask; + todisplay[i][0] <<= nbits; + } + } + + this.toscr_1 = function(nbits, fm) { + switch (fm) { + case 0: + this.toscr_2_ecs(nbits); + break; +/*#ifdef AGA + case 1: + this.toscr_3_aga(nbits, 1); + break; + case 2: + this.toscr_3_aga(nbits, 2); + break; +#endif*/ + } + out_nbits += nbits; + if (out_nbits == 32) { + for (var i = 0; i < thisline_decision.nr_planes; i++) { + if (line_data[next_lineno][i][out_offs] != outword[i]) { + thisline_changed = 1; + line_data[next_lineno][i][out_offs] = outword[i]; + } + outword[i] = 0; + } + out_offs++; + out_nbits = 0; + } + } + + this.toscr = function(nbits, fm) { + if (nbits > 16) { + this.toscr(16, fm); + nbits -= 16; + } + var t = 32 - out_nbits; + if (t < nbits) { + this.toscr_1(t, fm); + nbits -= t; + } + this.toscr_1(nbits, fm); + } + + this.flush_plane_data = function(fm) { + var i = 0; + + if (out_nbits <= 16) { + i += 16; + this.toscr_1(16, fm); + } + if (out_nbits != 0) { + i += 32 - out_nbits; + this.toscr_1(32 - out_nbits, fm); + } + i += 32; + + this.toscr_1(16, fm); + this.toscr_1(16, fm); + + if (fm == 2) { + // flush AGA full 64-bit shift register + i += 32; + this.toscr_1(16, fm); + this.toscr_1(16, fm); + } + if (bpl1dat_early) { + this.toscr_1(16, fm); + this.toscr_1(16, fm); + } + return i >> (1 + toscr_res); + } + + this.flush_display = function(fm) { + if (toscr_nbits > 0 && thisline_decision.plfleft >= 0) + this.toscr(toscr_nbits, fm); + toscr_nbits = 0; + } + + this.beginning_of_plane_block = function(hpos, fm) { + var oleft = thisline_decision.plfleft; + + this.flush_display(fm); + + if (fm == 0) + for (var i = 0; i < MAX_PLANES; i++) { + todisplay[i][0] |= fetched[i]; + } +/*#ifdef AGA + else + for (i = 0; i < MAX_PLANES; i++) { + if (fm == 2) + todisplay[i][1] = fetched_aga1[i]; + todisplay[i][0] = fetched_aga0[i]; + } +#endif*/ + + this.update_denise(hpos); + this.maybe_first_bpl1dat(hpos); + + bplcon1t2 = bplcon1t; + bplcon1t = bplcon1; + if (bplcon1_hpos != hpos || oleft < 0) + bplcon1t2 = bplcon1t; + + this.compute_toscr_delay(hpos, bplcon1t2); + } + + this.update_bpldats = function(hpos) { + for (var i = 0; i < MAX_PLANES; i++) { +/*#ifdef AGA + fetched_aga0[i] = bplxdat[i]; + fetched_aga1[i] = 0; +#endif*/ + fetched[i] = bplxdat[i]; + } + this.beginning_of_plane_block(hpos, fetchmode); + } + + /*---------------------------------*/ + /* fetch */ + + this.finish_final_fetch = function(pos, fm) { + if (thisline_decision.plfleft < 0 || plf_state == PLF_END) + return; + + plf_state = PLF_END; + ddfstate = DIW_WAITING_START; + pos += this.flush_plane_data(fm); + thisline_decision.plfright = pos; + thisline_decision.plflinelen = out_offs; + + if (this.vpos >= minfirstline && (thisframe_first_drawn_line < 0 || this.vpos < thisframe_first_drawn_line)) + thisframe_first_drawn_line = this.vpos; + thisframe_last_drawn_line = this.vpos; + + if (SMART_UPDATE) { + if (line_decisions[next_lineno].plflinelen != thisline_decision.plflinelen + || line_decisions[next_lineno].plfleft != thisline_decision.plfleft + || line_decisions[next_lineno].bplcon0 != thisline_decision.bplcon0 + || line_decisions[next_lineno].bplcon2 != thisline_decision.bplcon2 + || line_decisions[next_lineno].bplcon3 != thisline_decision.bplcon3 +/*#ifdef AGA + || line_decisions[next_lineno].bplcon4 != thisline_decision.bplcon4 +#endif*/ + ) thisline_changed = 1; + } else + thisline_changed = 1; + } + + this.long_fetch_ecs = function(plane, nwords, weird_number_of_bits, dma) { + //uae_u16 *real_pt = (uae_u16 *)pfield_xlateptr (bplpt[plane], nwords * 2); + var real_pt = bplpt[plane]; + var delay = (plane & 1) ? toscr_delay2 : toscr_delay1; + var tmp_nbits = out_nbits; + var shiftbuffer = todisplay[plane][0]; + var outval = outword[plane]; + var fetchval = fetched[plane]; + //var *dataptr = (uae_u32 *)(line_data[next_lineno] + 2 * plane * MAX_WORDS_PER_LINE + 4 * out_offs); + var dataptr = out_offs; + + if (dma) { + bplpt[plane] += nwords * 2; + bplptx[plane] += nwords * 2; + } + + //if (real_pt == 0) /* @@@ Don't do this, fall back on chipmem_wget instead. */ + //return; + + while (nwords > 0) { + var bits_left = 32 - tmp_nbits; + var t; + + shiftbuffer |= fetchval; + + t = (shiftbuffer >>> delay) & 0xFFFF; + + if (weird_number_of_bits && bits_left < 16) { + //outval <<= bits_left; + //outval |= t >>> (16 - bits_left); + outval = ((outval << bits_left) | (t >>> (16 - bits_left))) >>> 0; + //thisline_changed |= *dataptr ^ outval; *dataptr++ = outval; + thisline_changed |= line_data[next_lineno][plane][dataptr] ^ outval; line_data[next_lineno][plane][dataptr++] = outval; + outval = t; + tmp_nbits = 16 - bits_left; + //shiftbuffer <<= 16; + shiftbuffer = (shiftbuffer << 16) >>> 0; + } else { + outval = ((outval << 16) | t) >>> 0; + shiftbuffer = (shiftbuffer << 16) >>> 0; + tmp_nbits += 16; + if (tmp_nbits == 32) { + //thisline_changed |= *dataptr ^ outval; *dataptr++ = outval; + thisline_changed |= line_data[next_lineno][plane][dataptr] ^ outval; line_data[next_lineno][plane][dataptr++] = outval; + tmp_nbits = 0; + } + } + nwords--; + if (dma) { + //fetchval = do_get_mem_word (real_pt); real_pt++; + //fetchval = AMIGA.mem.load16_chip(real_pt); real_pt += 2; + fetchval = AMIGA.custom.last_value = AMIGA.mem.chip.data[real_pt >>> 1]; real_pt += 2; + } + } + fetched[plane] = fetchval; + todisplay[plane][0] = shiftbuffer; + outword[plane] = outval; + } + + this.do_long_fetch = function(hpos, nwords, dma, fm) { + var i; + + this.flush_display(fm); + switch (fm) { + case 0: + if (out_nbits & 15) { + for (i = 0; i < toscr_nr_planes; i++) + this.long_fetch_ecs(i, nwords, 1, dma); + } else { + for (i = 0; i < toscr_nr_planes; i++) + this.long_fetch_ecs(i, nwords, 0, dma); + } + break; +/*#ifdef AGA + case 1: + if (out_nbits & 15) { + for (i = 0; i < toscr_nr_planes; i++) + this.long_fetch_aga(i, nwords, 1, 1, dma); + } else { + for (i = 0; i < toscr_nr_planes; i++) + this.long_fetch_aga(i, nwords, 0, 1, dma); + } + break; + case 2: + if (out_nbits & 15) { + for (i = 0; i < toscr_nr_planes; i++) + this.long_fetch_aga(i, nwords, 1, 2, dma); + } else { + for (i = 0; i < toscr_nr_planes; i++) + this.long_fetch_aga(i, nwords, 0, 2, dma); + } + break; +#endif*/ + } + out_nbits += nwords * 16; + out_offs += out_nbits >> 5; + out_nbits &= 31; + + if (dma && toscr_nr_planes > 0) + fetch_state = FETCH_WAS_PLANE0; + } + + this.add_modulos = function() { + var m1, m2; + + if (fmode & 0x4000) { + if (((diwstrt >> 8) ^ this.vpos) & 1) + m1 = m2 = bpl2mod; + else + m1 = m2 = bpl1mod; + } else { + m1 = bpl1mod; + m2 = bpl2mod; + } + + switch (bplcon0_planes_limit) { +/*#ifdef AGA + case 8: bplpt[7] += m2; bplptx[7] += m2; + case 7: bplpt[6] += m1; bplptx[6] += m1; +#endif*/ + case 6: bplpt[5] += m2; bplptx[5] += m2; + case 5: bplpt[4] += m1; bplptx[4] += m1; + case 4: bplpt[3] += m2; bplptx[3] += m2; + case 3: bplpt[2] += m1; bplptx[2] += m1; + case 2: bplpt[1] += m2; bplptx[1] += m2; + case 1: bplpt[0] += m1; bplptx[0] += m1; + } + } + + this.fetch = function(nr, fm, hpos) { + if (nr < bplcon0_planes_limit) { + var p = bplpt[nr]; + bplpt[nr] += (2 << fm); + bplptx[nr] += (2 << fm); + if (nr == 0) + bpl1dat_written = true; + + switch (fm) { + case 0: + //fetched[nr] = bplxdat[nr] = last_custom_value1 = chipmem_wget_indirect (p); + //fetched[nr] = bplxdat[nr] = AMIGA.mem.load16_chip(p); + fetched[nr] = bplxdat[nr] = AMIGA.custom.last_value = AMIGA.mem.chip.data[p >>> 1]; + break; +/*#ifdef AGA + case 1: + fetched_aga0[nr] = chipmem_lget_indirect (p); + last_custom_value1 = (uae_u16)fetched_aga0[nr]; + break; + case 2: + fetched_aga1[nr] = chipmem_lget_indirect (p); + fetched_aga0[nr] = chipmem_lget_indirect (p + 4); + last_custom_value1 = (uae_u16)fetched_aga0[nr]; + break; +#endif*/ + } + if (plf_state == PLF_PASSED_STOP2 && fetch_cycle >= (fetch_cycle & ~fetchunit_mask) + fetch_modulo_cycle) { + var mod; + if (fmode & 0x4000) { + if (((diwstrt >> 8) ^ this.vpos) & 1) + mod = bpl2mod; + else + mod = bpl1mod; + } else if (nr & 1) + mod = bpl2mod; + else + mod = bpl1mod; + + bplpt[nr] += mod; + bplptx[nr] += mod; + } + } else { + if (nr < MAX_PLANES) //FIX for illegal memory access if not #ifdef AGA + fetched[nr] = bplxdat[nr]; + } + } + + this.one_fetch_cycle = function(pos, ddfstop_to_test, dma, fm) { + if (plf_state < PLF_PASSED_STOP && pos == ddfstop_to_test) + plf_state = PLF_PASSED_STOP; + + if ((fetch_cycle & fetchunit_mask) == 0) { + if (plf_state == PLF_PASSED_STOP2) { + this.finish_final_fetch(pos, fm); + return 1; + } + if (plf_state == PLF_PASSED_STOP) + plf_state = PLF_PASSED_STOP2; + else if (plf_state == PLF_PASSED_STOP2) + plf_state = PLF_END; + } + this.maybe_check(pos); + + if (dma) { + var cycle_start = fetch_cycle & fetchstart_mask; + switch (fm_maxplane) { + case 8: + switch (cycle_start) { + case 0: this.fetch(7, fm, pos); break; + case 1: this.fetch(3, fm, pos); break; + case 2: this.fetch(5, fm, pos); break; + case 3: this.fetch(1, fm, pos); break; + case 4: this.fetch(6, fm, pos); break; + case 5: this.fetch(2, fm, pos); break; + case 6: this.fetch(4, fm, pos); break; + case 7: this.fetch(0, fm, pos); break; + } + break; + case 4: + switch (cycle_start) { + case 0: this.fetch(3, fm, pos); break; + case 1: this.fetch(1, fm, pos); break; + case 2: this.fetch(2, fm, pos); break; + case 3: this.fetch(0, fm, pos); break; + } + break; + case 2: + switch (cycle_start) { + case 0: this.fetch(1, fm, pos); break; + case 1: this.fetch(0, fm, pos); break; + } + break; + } + } + if (bpl1dat_written) { + fetch_state = FETCH_WAS_PLANE0; + bpl1dat_written = false; + } + + fetch_cycle++; + toscr_nbits += (2 << toscr_res); + + if (toscr_nbits > 16) { + Fatal(333, sprintf('one_fetch_cycle() toscr_nbits > 16 (%d)', toscr_nbits)); + toscr_nbits = 0; + } + if (toscr_nbits == 16) + this.flush_display(fm); + + return 0; + } + + this.update_fetch = function(until, fm) { + var dma = AMIGA.dmaen(DMAF_BPLEN); + + if (this.nodraw() || plf_state == PLF_END) + return; + + var ddfstop_to_test = HARD_DDF_STOP; + if (ddfstop >= last_fetch_hpos && plfstop < ddfstop_to_test) + ddfstop_to_test = plfstop; + + this.update_toscr_planes(); + + var pos = last_fetch_hpos; + var pos2 = last_fetch_hpos; + cycle_diagram_shift = last_fetch_hpos - fetch_cycle; + + for (; ; pos++) { + if (pos == until) { + if (until >= this.maxhpos) { + this.finish_final_fetch(pos, fm); + return; + } + this.flush_display(fm); + return; + } + if (fetch_state == FETCH_WAS_PLANE0) + break; + + fetch_state = FETCH_STARTED; + if (this.one_fetch_cycle(pos, ddfstop_to_test, dma, fm)) + return; + } + + // Unrolled version of the for loop below. + if (1 + && plf_state < PLF_PASSED_STOP && ddf_change != this.vpos && ddf_change + 1 != this.vpos + && dma + && (fetch_cycle & fetchstart_mask) == (fm_maxplane & fetchstart_mask) + && !badmode + //&& (out_nbits & 15) == 0 + && toscr_nr_planes == thisline_decision.nr_planes) + { + var offs = (pos - fetch_cycle) & fetchunit_mask; + var ddf2 = ((ddfstop_to_test - offs + fetchunit - 1) & ~fetchunit_mask) + offs; + var ddf3 = ddf2 + fetchunit; + var stop = until < ddf2 ? until : until < ddf3 ? ddf2 : ddf3; + var count = stop - pos; + + if (count >= fetchstart) { + count &= ~fetchstart_mask; + + if (thisline_decision.plfleft < 0) { + this.compute_delay_offset(); + this.compute_toscr_delay_1(bplcon1); + } + + this.do_long_fetch(pos, count >> (3 - toscr_res), dma, fm); + + this.maybe_first_bpl1dat(pos); + + if (pos <= ddfstop_to_test && pos + count > ddfstop_to_test) + plf_state = PLF_PASSED_STOP; + if (pos <= ddfstop_to_test && pos + count > ddf2) + plf_state = PLF_PASSED_STOP2; + if (pos <= ddf2 && pos + count >= ddf2 + fm_maxplane) + this.add_modulos(); + pos += count; + fetch_cycle += count; + } + } + + for (; pos < until; pos++) { + if (fetch_state == FETCH_WAS_PLANE0) { + this.beginning_of_plane_block(pos, fm); + this.estimate_last_fetch_cycle(pos); + } + fetch_state = FETCH_STARTED; + if (this.one_fetch_cycle(pos, ddfstop_to_test, dma, fm)) + return; + } + if (until >= this.maxhpos) { + this.finish_final_fetch(pos, fm); + return; + } + this.flush_display(fm); + } + + this.update_fetch_x = function(until, fm) { + if (this.nodraw()) + return; + + var pos = last_fetch_hpos; + this.update_toscr_planes(); + + for (; pos < until; pos++) { + toscr_nbits += (2 << toscr_res); + if (toscr_nbits > 16) { + Fatal(333, sprintf('update_fetch_x() xtoscr_nbits > 16 (%d)', toscr_nbits)); + toscr_nbits = 0; + } + if (toscr_nbits == 16) + this.flush_display(fm); + } + if (until >= this.maxhpos) { + this.finish_final_fetch(pos, fm); + return; + } + this.flush_display(fm); + } + + this.decide_fetch = function(hpos) { + if (hpos > last_fetch_hpos) { + if (fetch_state != FETCH_NOT_STARTED) { + this.update_fetch(hpos, fetchmode); + //cycle_diagram_shift = hpos - fetch_cycle; + } else if (bpl1dat_written_at_least_once) { + this.update_fetch_x(hpos, fetchmode); + bpl1dat_written = false; + } + this.maybe_check(hpos); + last_fetch_hpos = hpos; + } + } + + this.decide_fetch_ce = function(hpos) { + if ((ddf_change == this.vpos || ddf_change + 1 == this.vpos) && this.vpos < this.current_maxvpos()) + this.decide_fetch(hpos); + } + + this.estimate_last_fetch_cycle = function(hpos) { + var fetchunit = fetchunits[fetchmode * 4 + bplcon0_res]; + + if (plf_state < PLF_PASSED_STOP) { + var stop = plfstop < hpos || plfstop > HARD_DDF_STOP ? HARD_DDF_STOP : plfstop; + var fetch_cycle_at_stop = fetch_cycle + (stop - hpos); + var starting_last_block_at = (fetch_cycle_at_stop + fetchunit - 1) & ~(fetchunit - 1); + + estimated_last_fetch_cycle = hpos + (starting_last_block_at - fetch_cycle) + fetchunit; + } else { + var starting_last_block_at = (fetch_cycle + fetchunit - 1) & ~(fetchunit - 1); + if (plf_state == PLF_PASSED_STOP2) + starting_last_block_at -= fetchunit; + + estimated_last_fetch_cycle = hpos + (starting_last_block_at - fetch_cycle) + fetchunit; + } + } + + /*---------------------------------*/ + + this.vsync_handler_post = function() { + if (bplcon0 & 4) + this.lof_store = this.lof_store ? 0 : 1; + this.lof_current = this.lof_store; + if (lof_togglecnt_lace >= LOF_TOGGLES_NEEDED) { + interlace_changed = this.notice_interlace_seen(true); + if (interlace_changed) + this.notice_screen_contents_lost(); + } else if (lof_togglecnt_nlace >= LOF_TOGGLES_NEEDED) { + interlace_changed = this.notice_interlace_seen(false); + if (interlace_changed) + this.notice_screen_contents_lost(); + } + if (this.lof_changing) { + // still same? Trigger change now. + if ((!this.lof_store && this.lof_changing < 0) || (this.lof_store && this.lof_changing > 0)) { + this.lof_changed = 1; + } + this.lof_changing = 0; + } + +/*#ifdef PICASSO96 + if (p96refresh_active) { + vpos_count = p96refresh_active; + vtotal = vpos_count; + } +#endif*/ + + if ((beamcon0 & (0x20 | 0x80)) != (new_beamcon0 & (0x20 | 0x80)) || (this.vpos_count > 0 && Math.abs(this.vpos_count - this.vpos_count_diff) > 1) || this.lof_changed) + this.init_hz(false); + else if (interlace_changed) + this.compute_framesync(); + + this.lof_changed = 0; + + AMIGA.copper.COPJMP(1, 1); + + this.init_hardware_frame(); + } + + this.hsync_scandoubler = function() { + console.log('hsync_scandoubler'); + var bpltmp = [0,0,0,0,0,0,0,0], bpltmpx = [0,0,0,0,0,0,0,0]; + + next_lineno++; + scandoubled_line = 1; + + for (var i = 0; i < 8; i++) { + bpltmp[i] = bplpt[i]; + bpltmpx[i] = bplptx[i]; + if (prevbpl[this.lof_store][this.vpos][i] && prevbpl[1 - this.lof_store][this.vpos][i]) { + var diff = prevbpl[this.lof_store][this.vpos][i] - prevbpl[1 - this.lof_store][this.vpos][i]; + if (this.lof_store) { + if (bplcon0 & 4) + bplpt[i] = prevbpl[this.lof_store][this.vpos][i] - diff; + } else { + if (bplcon0 & 4) + bplpt[i] = prevbpl[this.lof_store][this.vpos][i]; + else + bplpt[i] = bplpt[i] - diff; + + } + } + } + + this.reset_decisions(); + plf_state = PLF_IDLE; + + // copy color changes + var dip1 = curr_drawinfo[next_lineno - 1]; + for (var idx1 = dip1.first_color_change; idx1 < dip1.last_color_change; idx1++) { + var cs2 = curr_color_changes[idx1]; + var regno = cs2.regno; + var hpos = cs2.linepos; + if (regno < 0x1000 && hpos < HBLANK_OFFSET && !(beamcon0 & 0x80) && prev_lineno >= 0) { + var pdip = curr_drawinfo[next_lineno - 1]; + var idx = pdip.last_color_change; + pdip.last_color_change++; + pdip.nr_color_changes++; + curr_color_changes[idx].linepos = hpos + this.maxhpos + 1; + curr_color_changes[idx].regno = regno; + curr_color_changes[idx].value = cs2.value; + curr_color_changes[idx + 1].regno = -1; + } else { + var cs1 = curr_color_changes[next_color_change]; + cs1.set(cs2); //memcpy (cs1, cs2, sizeof (struct color_change)); + next_color_change++; + } + } + + curr_color_changes[next_color_change].regno = -1; + + this.finish_decisions(); + this.hsync_record_line_state(next_lineno, NLN_NORMAL, thisline_changed); + this.hardware_line_completed(next_lineno); + scandoubled_line = 0; + + for (var i = 0; i < 8; i++) { + bplpt[i] = bpltmp[i]; + bplptx[i] = bpltmpx[i]; + } + } + + this.hsync_handler_pre = function() { + this.finish_decisions(); + if (thisline_decision.plfleft >= 0) { + if (AMIGA.config.chipset.collision_level > 1) + this.do_sprite_collisions(); + if (AMIGA.config.chipset.collision_level > 2) + this.do_playfield_collisions(); + } + this.hsync_record_line_state(next_lineno, nextline_how, thisline_changed); + if (this.vpos == sprite_vblank_endline) { + //lightpen_triggered = 0; + sprite_0 = 0; + } + /*if (lightpen_cx > 0 && (bplcon0 & 8) && !lightpen_triggered && lightpen_cy == this.vpos) { + vpos_lpen = this.vpos; + hpos_lpen = lightpen_cx; + lightpen_triggered = 1; + }*/ + this.hardware_line_completed(next_lineno); + if (this.doflickerfix() && interlace_seen > 0) + this.hsync_scandoubler(); + } + + this.hsync_handler_pre_next_vpos = function(onvsync) { + if (this.is_linetoggle()) + this.lol ^= 1; + else + this.lol = 0; + + this.vpos++; + this.vpos_count++; + if (this.vpos >= this.maxvpos_total) + this.vpos = 0; + if (onvsync) { + this.vpos = 0; + //vsync_counter++; + } + this.maxhpos = this.maxhpos_short + this.lol; + } + + this.hsync_handler_post = function() { + if (this.vpos == equ_vblank_endline + 1) { + //if (this.lof_current != this.lof_store) {} + if (this.lof_store != this.lof_previous) { + if (lof_togglecnt_lace < LOF_TOGGLES_NEEDED) + lof_togglecnt_lace++; + if (lof_togglecnt_lace >= LOF_TOGGLES_NEEDED) + lof_togglecnt_nlace = 0; + } else { + if (lof_togglecnt_nlace < LOF_TOGGLES_NEEDED) + lof_togglecnt_nlace++; + if (lof_togglecnt_nlace >= LOF_TOGGLES_NEEDED) + lof_togglecnt_lace = 0; + } + this.lof_previous = this.lof_store; + } + } + + this.hsync_handler_post_nextline_how = function() { + var lineno = this.vpos; + if (lineno >= MAXVPOS) + lineno %= MAXVPOS; + nextline_how = NLN_NORMAL; + if (this.doflickerfix() && interlace_seen > 0) + lineno *= 2; + else if (AMIGA.config.video.vresolution && (doublescan <= 0 || interlace_seen > 0)) { + lineno *= 2; + nextline_how = AMIGA.config.video.vresolution > VRES_NONDOUBLE && AMIGA.config.video.scanlines == false ? NLN_DOUBLED : NLN_NBLACK; + if (interlace_seen) { + if (!this.lof_current) { + lineno++; + nextline_how = NLN_LOWER; + } else { + nextline_how = NLN_UPPER; + } + } + } + prev_lineno = next_lineno; + next_lineno = lineno; + this.reset_decisions(); + + plfstrt_sprite = plfstrt; + } + + this.hsync_handler_post_diw_change = function() { + if (GET_PLANES(bplcon0) > 0 && AMIGA.dmaen(DMAF_BPLEN)) { + if (this.vpos > last_planes_vpos) + last_planes_vpos = this.vpos; + if (this.vpos >= minfirstline && first_planes_vpos == 0) + first_planes_vpos = this.vpos > minfirstline ? this.vpos - 1 : this.vpos; + else if (this.vpos >= this.current_maxvpos() - 1) + last_planes_vpos = this.current_maxvpos(); + } + if (diw_change == 0) { + if (this.vpos >= first_planes_vpos && this.vpos <= last_planes_vpos) { + if (diwlastword > diwlastword_total) { + diwlastword_total = diwlastword; + if (diwlastword_total > coord_diw_to_window_x(hsyncstartpos * 2)) + diwlastword_total = coord_diw_to_window_x(hsyncstartpos * 2); + } + if (diwfirstword < diwfirstword_total) { + diwfirstword_total = diwfirstword; + if (diwfirstword_total < coord_diw_to_window_x(hsyncendpos * 2)) + diwfirstword_total = coord_diw_to_window_x(hsyncendpos * 2); + firstword_bplcon1 = bplcon1; + } + } + if (diwstate == DIW_WAITING_STOP) { + var f = 8 << fetchmode; + if (plfstrt + f < ddffirstword_total + f) + ddffirstword_total = plfstrt + f; + if (plfstop + 2 * f > ddflastword_total + 2 * f) + ddflastword_total = plfstop + 2 * f; + } + if ((plffirstline < plffirstline_total || (plffirstline_total == minfirstline && this.vpos > minfirstline)) && plffirstline < (this.vpos >> 1)) { + firstword_bplcon1 = bplcon1; + if (plffirstline < minfirstline) + plffirstline_total = minfirstline; + else + plffirstline_total = plffirstline; + } + if (plflastline > plflastline_total && plflastline > plffirstline_total && plflastline > (this.maxvpos >> 1)) + plflastline_total = plflastline; + } + if (diw_change > 0) + diw_change--; + } + + /*---------------------------------*/ + + this.getDiwstate = function() { + return diwstate; + } + + this.getData = function() { + return [ + thisline_decision.plfleft, + thisline_decision.plfright - (16 << fetchmode), + cycle_diagram_total_cycles[fetchmode][GET_RES_AGNUS(bplcon0)][GET_PLANES_LIMIT(bplcon0)], + cycle_diagram_free_cycles[fetchmode][GET_RES_AGNUS(bplcon0)][GET_PLANES_LIMIT(bplcon0)] + ]; + } + + /*---------------------------------*/ + + this.setup = function() { + if (cycle_diagram_table === null) + create_cycle_diagram_table(); + + if (AMIGA.video.available == 1) + alloc_colors64k(4,4,4, 8,4,0, 0,0,0, 0); + else + alloc_colors64k(5,6,5, 11,5,0, 0,0,0, 0); + + notice_new_xcolors(); + + this.setup_drawing(); + this.setup_sprites(); + } + + this.cleanup = function() { + this.cleanup_sprites(); + this.cleanup_drawing(); + } + + this.reset = function() { + /*lightpen_active = -1; + lightpen_triggered = 0; + lightpen_cx = lightpen_cy = -1;*/ + + update_mirrors(); + + if (!aga_mode) { + for (i = 0; i < 32; i++) { + current_colors.color_regs_ecs[i] = 0; + current_colors.acolors[i] = getxcolor(0); + } +/*#ifdef AGA + } else { + for (i = 0; i < 256; i++) { + current_colors.color_regs_aga[i] = 0; + current_colors.acolors[i] = getxcolor(0); + } +#endif*/ + } + + this.clxdat = 0; + + /* Clear the armed flags of all sprites. */ + for (var i = 0; i < MAX_SPRITES; i++) spr[i].clr(); + nr_armed = 0; + + bplcon0 = 0; + bplcon3 = 0x0C00; + bplcon4 = 0x0011; // Get AGA chipset into ECS compatibility mode + + diwhigh = 0; + diwhigh_written = false; + hdiwstate = DIW_WAITING_START; // this does not reset at vblank + + this.FMODE(0, 0); + this.CLXCON(0); + this.CLXCON2(0); + this.setup_fmodes(0); + sprite_width = GET_SPRITEWIDTH(fmode); + beamcon0 = new_beamcon0 = AMIGA.config.video.ntsc ? 0x00 : 0x20; + this.lof_store = this.lof_current = 1; + + this.vpos = 0; + this.vpos_count = this.vpos_count_diff = 0; + + //timehack_alive = 0; + + curr_sprite_entries = null; + prev_sprite_entries = null; + sprite_entries[0][0].first_pixel = 0; + sprite_entries[1][0].first_pixel = MAX_SPR_PIXELS; + sprite_entries[0][1].first_pixel = 0; + sprite_entries[1][1].first_pixel = MAX_SPR_PIXELS; + for (var i = 0; i < spixels.length; i++) spixels[i] = 0; //memset (spixels, 0, 2 * MAX_SPR_PIXELS * sizeof *spixels); + for (var i = 0; i < spixstate.length; i++) spixstate[i] = 0; //memset (&spixstate, 0, sizeof spixstate); + + diwstate = DIW_WAITING_START; + + this.init_hz(true); + //vpos_lpen = -1; + this.lof_changing = 0; + this.lof_previous = this.lof_store; + lof_togglecnt_nlace = lof_togglecnt_lace = 0; + nlace_cnt = NLACE_CNT_NEEDED; + + this.reset_sprites(); + this.init_hardware_frame(); + this.reset_drawing(); + this.reset_decisions(); + + sprres = expand_sprres(bplcon0, bplcon3); + sprite_width = GET_SPRITEWIDTH(fmode); + this.setup_fmodes(0); + +/*#ifdef PICASSO96 + picasso_reset(); +#endif*/ + } } diff --git a/sae/utils.js b/sae/utils.js index 3fba66f..d3db3f3 100644 --- a/sae/utils.js +++ b/sae/utils.js @@ -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); + } +} + + diff --git a/sae/video.js b/sae/video.js index 158b961..00124bc 100644 --- a/sae/video.js +++ b/sae/video.js @@ -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); + } }
    Supported browsers
    ChromeFastest
    FirefoxMedium speed
    ChromeVery fast
    FirefoxMedium speed
    OperaSlow speed, no audio
    IENo support
    OtherUntested