-
+
+
+
Display Settings
+
+
+
+
+
+
+
+
-
-
+
+
+
Keyboard Shortcuts
+
+
F1-F12: Function Keys
+
Enter: Confirm / OK
+
Esc / Ctrl: Back / Exit
+
Arrows: Navigation
+
PageUp / PageDown: Page Navigation
+
A-Z: Alpha Input
+
1-9: Numeric Keys
+
Backspace: F2 Key
+
Tab: Help
+
Shift: Shift Modifier
+
Space: Equals (=)
+
-
-
+
+
+ Fully opensource@github
+ NC1020 Emulator v2.0
+ Persistent Storage Enabled
+ 支持 PWA 离线使用
+ ROM文件下载地址
+
+
+
+
文曲星模拟器
+
+
-
-
- orginal: http://bbs.emsky.net/viewthread.php?tid=33474
- 目前只在chrome浏览器测试过,别的浏览器应该也有能跑的。
- 由于ROM文件有24M之大,若加载过慢,请自行下载到硬盘上,拖拽到模拟器的屏幕区域手动加载。
- 若想要离线使用能正常加载,请在chrome启动参数中加入`--allow-file-access-from-files`。
- ROM文件下载地址
-
-
-
+ return true;
+ }
+
+ function saveAppState(wqxInstance) {
+ // ★ 修复:未就绪时不保存,防止写入坏状态覆盖好存档
+ if (!isStateReadyToSave(wqxInstance)) return false;
+ try {
+ var state = wqxInstance.saveState();
+ localStorage.setItem(STATE_STORAGE_KEY, JSON.stringify(state));
+ setFlashStatus('💾 Auto-saved');
+ return true;
+ } catch (e) {
+ setFlashStatus('⚠️ Save failed: ' + e.message);
+ return false;
+ }
+ }
+
+ function loadAppState(wqxInstance) {
+ try {
+ var stored = localStorage.getItem(STATE_STORAGE_KEY);
+ if (!stored) return false;
+ var state = JSON.parse(stored);
+ // ★ 修复:存档里的 lcdbuffaddr 必须合法才允许恢复
+ if (!state || state.lcdbuffaddr === null || state.lcdbuffaddr === undefined || state.lcdbuffaddr <= 0x100) {
+ log('⚠️ 存档 lcdbuffaddr 不合法(值=' + (state && state.lcdbuffaddr) + '),丢弃存档');
+ localStorage.removeItem(STATE_STORAGE_KEY);
+ return false;
+ }
+ wqxInstance.loadState(state);
+ setFlashStatus('✅ Restored');
+ return true;
+ } catch (e) {
+ log('loadAppState error: ' + e);
+ return false;
+ }
+ }
+
+ function clearSavedState() {
+ localStorage.removeItem(STATE_STORAGE_KEY);
+ setFlashStatus('🗑️ Cleared');
+ setTimeout(() => location.reload(), 500);
+ }
+
+ (function () {
+ var btn = document.getElementById('reset');
+ var holdTimer = null;
+ var HOLD_MS = 2000;
+
+ function startHold() {
+ btn.classList.add('pressing');
+ holdTimer = setTimeout(function () { clearSavedState(); }, HOLD_MS);
+ }
+
+ function endHold() {
+ if (holdTimer !== null) {
+ clearTimeout(holdTimer);
+ holdTimer = null;
+ if (btn.classList.contains('pressing')) reset();
+ }
+ btn.classList.remove('pressing');
+ }
+
+ btn.addEventListener('mousedown', startHold);
+ btn.addEventListener('mouseup', endHold);
+ btn.addEventListener('mouseleave', endHold);
+ btn.addEventListener('touchstart', function(e){ e.preventDefault(); startHold(); });
+ btn.addEventListener('touchend', function(e){ e.preventDefault(); endHold(); });
+ })();
+
+ function log(msg, color) {
+ console.log(msg);
+ var logEl = document.getElementById('debug-log');
+ if (logEl) {
+ if (color === '#f00') logEl.style.display = 'block';
+ var div = document.createElement('div');
+ div.style.color = color || '#0f0';
+ div.textContent = '[' + new Date().toLocaleTimeString() + '] ' + msg;
+ logEl.appendChild(div);
+ logEl.scrollTop = logEl.scrollHeight;
+ }
+ }
+
+ window.onerror = function(msg, url, line, col, error) {
+ log('ERR: ' + msg + ' (' + line + ':' + col + ')', '#f00');
+ return false;
+ };
+ window.onunhandledrejection = function(event) {
+ log('PROMISE ERR: ' + event.reason, '#f00');
+ };
+
+ function setFlashStatus(msg) {
+ log(msg);
+ var el = document.getElementById('flash_status');
+ if (el) el.textContent = msg;
+ }
+
+ // ============================================================
+ // Device UI Rendering & Interaction
+ // ============================================================
+ var canvas = document.getElementById('key');
+ var ctx = canvas.getContext('2d');
+ var image = new Image();
+ var indicatorStates = new Array(9).fill(false);
+ var rulerCenters = [66.4, 98.6, 131.3, 163.8, 195.5, 227.5, 260.1, 292.2, 324.9];
+ var indicatorY = 177.5;
+
+ function redrawFrame() {
+ if (!image.complete) return;
+ ctx.clearRect(0, 0, canvas.width, canvas.height);
+ ctx.globalCompositeOperation = 'source-over';
+ ctx.drawImage(image, 0, 0);
+ ctx.globalCompositeOperation = 'destination-out';
+ ctx.fillRect(15, 14, 376, 163);
+ ctx.globalCompositeOperation = 'source-over';
+ for (var i = 0; i < indicatorStates.length; i++) {
+ if (indicatorStates[i]) renderIndicator(i);
+ }
+ }
+
+ image.onload = function () { redrawFrame(); updateLayout(); };
+ image.src = 'nc1020.png';
+
+ function renderIndicator(index) {
+ var x = rulerCenters[index];
+ var y = indicatorY;
+ ctx.fillStyle = "rgba(0, 0, 0, 0.85)";
+ ctx.beginPath();
+ ctx.moveTo(x - 4, y);
+ ctx.lineTo(x + 4, y);
+ ctx.lineTo(x, y + 5);
+ ctx.fill();
+ }
+
+ function drawIndicator(index, active) {
+ if (indicatorStates[index] === active) return;
+ indicatorStates[index] = active;
+ if (!image.complete) return;
+ if (active) {
+ renderIndicator(index);
+ } else {
+ ctx.drawImage(image, rulerCenters[index] - 5, 177, 10, 10, rulerCenters[index] - 5, 177, 10, 10);
+ }
+ }
+
+ function updateLayout() {
+ var device = document.getElementById('device');
+ var isFullscreen = document.body.classList.contains('fullscreen');
+ var h1 = document.querySelector('h1');
+ var h1Height = (h1 && h1.offsetParent && !isFullscreen) ? h1.offsetHeight + 20 : 0;
+ var availableWidth = window.innerWidth - (isFullscreen ? 0 : 40);
+ var availableHeight = window.innerHeight - h1Height - (isFullscreen ? 0 : 40);
+ var s = Math.min(availableWidth / 434, availableHeight / 543);
+ s = Math.max(0.2, Math.min(s, isFullscreen ? 2.5 : 1.5));
+ device.style.transform = "scale(" + s + ")";
+ }
+
+ window.addEventListener('resize', updateLayout);
+
+ function hasPhysicalKeyboard() {
+ return window.matchMedia('(hover: hover)').matches && window.matchMedia('(pointer: fine)').matches;
+ }
+
+ async function toggleFullscreen() {
+ if (!document.fullscreenElement) {
+ try {
+ const target = hasPhysicalKeyboard() ? document.getElementById('outScr') : document.documentElement;
+ await target.requestFullscreen();
+ } catch (err) { console.error('无法进入全屏:', err.message); }
+ } else {
+ try { await document.exitFullscreen(); }
+ catch (err) { console.error('无法退出全屏:', err.message); }
+ }
+ }
+
+ function updateScrLayout() {
+ var outScr = document.getElementById('outScr');
+ var scr = document.getElementById('scr');
+ var isFullscreen = !!document.fullscreenElement;
+ if (isFullscreen) {
+ document.body.classList.add('fullscreen');
+ if (document.fullscreenElement === outScr) {
+ var s = Math.min(window.innerWidth / 320, window.innerHeight / 160);
+ scr.style.transform = "scale(" + s + ")";
+ } else {
+ updateLayout();
+ }
+ } else {
+ document.body.classList.remove('fullscreen');
+ scr.style.transform = "scale(1)";
+ updateLayout();
+ }
+ }
+
+ document.addEventListener('fullscreenchange', updateScrLayout);
+
+ var keys = [
+ { name: 'F1', x: 403, y: 10, width: 28, height: 30 },
+ { name: 'F2', x: 403, y: 45, width: 28, height: 30 },
+ { name: 'F3', x: 403, y: 80, width: 28, height: 30 },
+ { name: 'F4', x: 403, y: 115, width: 28, height: 30 },
+ { name: 'F12', x: 400, y: 190, width: 32, height: 32 },
+ { name: 'Reset', x: 105, y: 390, width: 10, height: 10 },
+ { name: 'F8', x: 131, y: 370, width: 43, height: 35 },
+ { name: 'F9', x: 174, y: 370, width: 43, height: 35 },
+ { name: 'F10', x: 217, y: 370, width: 43, height: 35 },
+ { name: 'F7', x: 260, y: 370, width: 43, height: 35 },
+ { name: 'F6', x: 303, y: 370, width: 43, height: 35 },
+ { name: 'F5', x: 346, y: 370, width: 43, height: 35 },
+ { name: 'F11', x: 389, y: 370, width: 43, height: 35 },
+ { name: 'Q', x: 2, y: 407, width: 43, height: 32 },
+ { name: 'W', x: 45, y: 407, width: 43, height: 32 },
+ { name: 'E', x: 88, y: 407, width: 43, height: 32 },
+ { name: 'R', x: 131, y: 407, width: 43, height: 32 },
+ { name: 'T', x: 174, y: 407, width: 43, height: 32 },
+ { name: 'Y', x: 217, y: 407, width: 43, height: 32 },
+ { name: 'U', x: 260, y: 407, width: 43, height: 32 },
+ { name: 'I', x: 303, y: 407, width: 43, height: 32 },
+ { name: 'O', x: 346, y: 407, width: 43, height: 32 },
+ { name: 'P', x: 389, y: 407, width: 43, height: 32 },
+ { name: 'A', x: 2, y: 441, width: 43, height: 32 },
+ { name: 'S', x: 45, y: 441, width: 43, height: 32 },
+ { name: 'D', x: 88, y: 441, width: 43, height: 32 },
+ { name: 'F', x: 131, y: 441, width: 43, height: 32 },
+ { name: 'G', x: 174, y: 441, width: 43, height: 32 },
+ { name: 'H', x: 217, y: 441, width: 43, height: 32 },
+ { name: 'J', x: 260, y: 441, width: 43, height: 32 },
+ { name: 'K', x: 303, y: 441, width: 43, height: 32 },
+ { name: 'L', x: 346, y: 441, width: 43, height: 32 },
+ { name: 'Enter', x: 389, y: 441, width: 43, height: 32 },
+ { name: 'Z', x: 2, y: 476, width: 43, height: 32 },
+ { name: 'X', x: 45, y: 476, width: 43, height: 32 },
+ { name: 'C', x: 88, y: 476, width: 43, height: 32 },
+ { name: 'V', x: 131, y: 476, width: 43, height: 32 },
+ { name: 'B', x: 174, y: 476, width: 43, height: 32 },
+ { name: 'N', x: 217, y: 476, width: 43, height: 32 },
+ { name: 'M', x: 260, y: 476, width: 43, height: 32 },
+ { name: 'PgUp', x: 303, y: 476, width: 43, height: 32 },
+ { name: 'Up', x: 346, y: 476, width: 43, height: 32 },
+ { name: 'PgDn', x: 389, y: 476, width: 43, height: 32 },
+ { name: 'Tab', x: 2, y: 510, width: 43, height: 32 },
+ { name: 'Shift', x: 45, y: 510, width: 43, height: 32 },
+ { name: 'CapsLock', x: 88, y: 510, width: 43, height: 32 },
+ { name: 'Esc', x: 131, y: 510, width: 43, height: 32 },
+ { name: '0', x: 174, y: 510, width: 43, height: 32 },
+ { name: 'Period', x: 217, y: 510, width: 43, height: 32 },
+ { name: 'Equals', x: 260, y: 510, width: 43, height: 32 },
+ { name: 'Left', x: 303, y: 510, width: 43, height: 32 },
+ { name: 'Down', x: 346, y: 510, width: 43, height: 32 },
+ { name: 'Right', x: 389, y: 510, width: 43, height: 32 },
+ ];
+
+ function handleMouseEvent(e, isDown) {
+ var rect = canvas.getBoundingClientRect();
+ var s = rect.width / 434;
+ var x = (e.clientX - rect.left) / s;
+ var y = (e.clientY - rect.top) / s;
+ keyAction(getKeyAt(x, y), isDown);
+ }
+
+ canvas.addEventListener('mousedown', function(e) { handleMouseEvent(e, true); });
+ canvas.addEventListener('mouseup', function(e) { handleMouseEvent(e, false); });
+ canvas.addEventListener('mouseleave', function(e) { handleMouseEvent(e, false); });
+ canvas.addEventListener('touchstart', function(e) {
+ e.preventDefault();
+ var rect = canvas.getBoundingClientRect();
+ var s = rect.width / 434;
+ keyAction(getKeyAt((e.touches[0].clientX - rect.left) / s, (e.touches[0].clientY - rect.top) / s), true);
+ }, {passive: false});
+ canvas.addEventListener('touchend', function(e) {
+ e.preventDefault();
+ var rect = canvas.getBoundingClientRect();
+ var s = rect.width / 434;
+ keyAction(getKeyAt((e.changedTouches[0].clientX - rect.left) / s, (e.changedTouches[0].clientY - rect.top) / s), false);
+ }, {passive: false});
+
+ function getKeyAt(x, y) {
+ for (var i = 0; i < keys.length; i++) {
+ if (keys[i].x <= x && x <= keys[i].x + keys[i].width &&
+ keys[i].y <= y && y <= keys[i].y + keys[i].height) {
+ return keys[i].name;
+ }
+ }
+ return null;
+ }
+
+ function keyAction(name, isDown) {
+ if (name != null) {
+ if (isDown) {
+ keyInput.keyDown(name);
+ } else {
+ if (name === "Reset") reset();
+ else keyInput.keyUp(name);
+ }
+ }
+ }
+
+ // ============================================================
+ // Emulator Lifecycle
+ // ============================================================
+ var wqxDiv = document.getElementById('lcd');
+ var wqx = new Wqx(wqxDiv);
+ var keyInput = new WqxKeyInput(wqx, document.body);
+
+ // ★ 修复:monkey-patch updateLCD 时先检查 lcdbuffaddr 是否合法
+ var _origUpdateLCD = wqx.updateLCD.bind(wqx);
+ wqx.updateLCD = function(addr, value) {
+ // lcdbuffaddr 未就绪时直接跳过,避免 NaN 计算
+ if (!this.lcdbuffaddr || this.lcdbuffaddr <= 0x100) return;
+ var offset = addr - this.lcdbuffaddr;
+ if (offset < 0 || offset >= 1600) return;
+ var row = Math.floor(offset / 20);
+ var col = offset % 20;
+ if (col === 0) {
+ var active = (value & 0x80) !== 0;
+ if (row >= 64 && row <= 72) {
+ drawIndicator(row - 64, active);
+ }
+ }
+ _origUpdateLCD(addr, value);
+ };
+
+ // FLS 拖放更新
+ document.addEventListener('dragover', function(e) { e.preventDefault(); });
+ document.addEventListener('drop', function(e) {
+ e.preventDefault();
+ var file = e.dataTransfer.files[0];
+ if (!file || !file.name.endsWith('.fls')) return;
+ var reader = new FileReader();
+ reader.onload = function(ev) {
+ wqx.loadNorFlash(ev.target.result);
+ saveAppState(wqx);
+ setFlashStatus('💾 已加载 ' + file.name);
+ };
+ reader.readAsArrayBuffer(file);
+ });
+
+ var romLoaded = false;
+ var norLoaded = false;
+ var _stateRestored = false;
+
+ function check() {
+ if (!romLoaded || !norLoaded) return;
+ if (_stateRestored) {
+ wqx.syncCalendar();
+ wqx.startFrame();
+ setTimeout(() => { wqx.syncClock(); log('Delayed clock sync completed'); }, 2000);
+ } else {
+ wqx.run();
+ wqx.syncCalendar();
+ }
+ document.getElementById('run').disabled = true;
+ document.getElementById('stop').disabled = false;
+ }
+
+ function loadZip() {
+ log('Loading rom.zip...');
+ var xhrZip = new XMLHttpRequest();
+ xhrZip.open('GET', 'rom.zip', true);
+ xhrZip.responseType = 'arraybuffer';
+ xhrZip.onload = function() {
+ if (xhrZip.status === 200) {
+ log('rom.zip loaded, mounting BFS...');
+ mountBFS(xhrZip.response);
+ } else {
+ setFlashStatus('❌ ROM Load Error: ' + xhrZip.status);
+ }
+ };
+ xhrZip.onerror = function() { setFlashStatus('❌ Network Error'); };
+ xhrZip.send();
+ }
+
+ function mountBFS(zipData) {
+ try {
+ var Buffer = BrowserFS.BFSRequire('buffer').Buffer;
+ BrowserFS.configure({ fs: "ZipFS", options: { zipData: Buffer.from(zipData) } }, function(e) {
+ if (e) { setFlashStatus('❌ FS Error: ' + e); return; }
+ log('BFS configured, reading files...');
+ var fs = BrowserFS.BFSRequire('fs');
+ fs.readFile('/obj_lu.bin', function(err, data) {
+ if (err) { setFlashStatus('❌ Missing obj_lu.bin'); return; }
+ log('obj_lu.bin loaded');
+ wqx.loadBROM(data);
+ romLoaded = true;
+
+ // ★ 修复:ROM加载完成后再检查存档,保证 volume array 已就绪
+ if (loadAppState(wqx)) {
+ log('State restored from storage');
+ norLoaded = true;
+ _stateRestored = true;
+ check();
+ } else {
+ log('No valid saved state, reading nc1020.fls...');
+ fs.readFile('/nc1020.fls', function(err, data) {
+ if (err) { setFlashStatus('❌ Missing nc1020.fls'); return; }
+ log('nc1020.fls loaded');
+ wqx.loadNorFlash(data);
+ norLoaded = true;
+ _stateRestored = false;
+ check();
+ });
+ }
+ });
+ });
+ } catch (err) {
+ log('BFS Exception: ' + err);
+ }
+ }
+
+ function run() {
+ wqx.run();
+ document.getElementById('run').disabled = true;
+ document.getElementById('stop').disabled = false;
+ }
+ function stop() {
+ wqx.stop();
+ document.getElementById('stop').disabled = true;
+ document.getElementById('run').disabled = false;
+ }
+ function reset() { wqx.reset(); }
+
+ window.addEventListener('load', function() {
+ log('App started, initializing...');
+ try { loadZip(); }
+ catch(e) { log('Fatal initialization error: ' + e, '#f00'); }
+
+ window.addEventListener('pagehide', function() {
+ if (wqx) saveAppState(wqx);
+ });
+ document.addEventListener('visibilitychange', function() {
+ if (document.visibilityState === 'hidden' && wqx) saveAppState(wqx);
+ });
+
+ if ('serviceWorker' in navigator) {
+ var refreshing = false;
+ navigator.serviceWorker.addEventListener('controllerchange', function() {
+ if (refreshing) return;
+ refreshing = true;
+ window.location.reload();
+ });
+
+ navigator.serviceWorker.register('./sw.js').then(function(registration) {
+ log('SW registered: ' + registration.scope);
+ registration.onupdatefound = function() {
+ var installingWorker = registration.installing;
+ installingWorker.onstatechange = function() {
+ if (installingWorker.state === 'installed') {
+ if (navigator.serviceWorker.controller) {
+ log('新版本已就绪,将自动刷新...');
+ setFlashStatus('🔄 更新中...');
+ // 不弹 confirm,让 controllerchange 自动处理刷新
+ } else {
+ log('Content cached for offline use.');
+ }
+ }
+ };
+ };
+ }, function(err) {
+ log('SW registration failed: ' + err, '#f00');
+ });
+ }
+ });
+
+ // ============================================================
+ // PWA Install Logic
+ // ============================================================
+ let deferredPrompt;
+ const installBtn = document.getElementById('install-btn');
+
+ window.addEventListener('beforeinstallprompt', (e) => {
+ e.preventDefault();
+ deferredPrompt = e;
+ if (installBtn) installBtn.style.display = 'block';
+ log('PWA install prompt available');
+ });
+
+ async function installPWA() {
+ if (!deferredPrompt) return;
+ deferredPrompt.prompt();
+ const { outcome } = await deferredPrompt.userChoice;
+ log('User response: ' + outcome);
+ deferredPrompt = null;
+ if (installBtn) installBtn.style.display = 'none';
+ }
+
+ async function clearAppCache() {
+ if (confirm('确定要清除应用缓存并重新加载吗?')) {
+ try {
+ if ('serviceWorker' in navigator) {
+ const registrations = await navigator.serviceWorker.getRegistrations();
+ for (const r of registrations) await r.unregister();
+ }
+ if ('caches' in window) {
+ const names = await caches.keys();
+ for (const name of names) await caches.delete(name);
+ }
+ window.location.reload(true);
+ } catch (err) {
+ alert('清除缓存失败: ' + err.message);
+ }
+ }
+ }
+
+ window.addEventListener('appinstalled', () => {
+ log('PWA installed');
+ if (installBtn) installBtn.style.display = 'none';
+ });
+
+ canvas.addEventListener('webglcontextlost', function(e) { e.preventDefault(); log('Canvas context lost!', '#f00'); }, false);
+ canvas.addEventListener('contextrestored', function() { log('Canvas context restored'); redrawFrame(); }, false);
+
+
-
\ No newline at end of file
+
diff --git a/manifest.json b/manifest.json
new file mode 100644
index 0000000..53cd63f
--- /dev/null
+++ b/manifest.json
@@ -0,0 +1,26 @@
+{
+ "name": "文曲星 NC1020 模拟器",
+ "short_name": "WQX NC1020",
+ "description": "基于 JavaScript 的文曲星 NC1020 模拟器",
+ "start_url": "./index.html",
+ "display": "standalone",
+ "background_color": "#0d0d0f",
+ "theme_color": "#0a84ff",
+ "icons": [
+ {
+ "src": "icon-192.png",
+ "sizes": "192x192",
+ "type": "image/png"
+ },
+ {
+ "src": "icon-512.png",
+ "sizes": "512x512",
+ "type": "image/png"
+ },
+ {
+ "src": "nc1020.png",
+ "sizes": "434x543",
+ "type": "image/png"
+ }
+ ]
+}
diff --git a/nc1020.png b/nc1020.png
new file mode 100644
index 0000000..7324fcf
Binary files /dev/null and b/nc1020.png differ
diff --git a/rom.zip b/rom.zip
new file mode 100644
index 0000000..6e6e5a0
Binary files /dev/null and b/rom.zip differ
diff --git a/rom/nc1020.fls b/rom/nc1020.fls
deleted file mode 100644
index 4313896..0000000
Binary files a/rom/nc1020.fls and /dev/null differ
diff --git a/rom/obj_lu.bin b/rom/obj_lu.bin
deleted file mode 100644
index 9f9d549..0000000
Binary files a/rom/obj_lu.bin and /dev/null differ
diff --git a/src/keyinput.js b/src/keyinput.js
index 8ce7229..52e8cb5 100644
--- a/src/keyinput.js
+++ b/src/keyinput.js
@@ -49,6 +49,7 @@ var WqxKeyInput = function (){
38: 'Up',
34: 'PageDown',
9: 'Tab',
+ 16: 'Shift',
229: 'Shift',
20: 'CapsLock',
27: 'Esc',
@@ -57,10 +58,22 @@ var WqxKeyInput = function (){
187: 'Equals',
37: 'Left',
40: 'Down',
- 39: 'Right'
+ 39: 'Right',
+ 49: 'B',//1
+ 50: 'N',//2
+ 51: 'M',//3
+ 52: 'G',//4
+ 53: 'H',//5
+ 54: 'J',//6
+ 55: 'T',//7
+ 56: 'Y',//8
+ 57: 'U',//9
+ 32: 'Equals',//space
+ 8: 'F2',//bkspc
+ 17: 'Esc'
};
var keyNameToKeypadMatrixIndex = {
- 'F12': 0x02,
+ 'F12': 0x0F,
'F5': 0x08,
'F6': 0x09,
@@ -87,8 +100,7 @@ var WqxKeyInput = function (){
'N': 0x35, // 46 N
'M': 0x36, // 46 M
'PageUp': 0x37, // 47 PgUp
-
- 'A': 0x28, // 30 A
+ 'PgUp': 0x37, // 47 PgUp 'A': 0x28, // 30 A
'S': 0x29, // 31 S
'D': 0x2A, // 32 D
'F': 0x2B, // 33 F
@@ -113,6 +125,7 @@ var WqxKeyInput = function (){
'P': 0x1C, // 29 P
'Enter': 0x1D, // 39 Enter
'PageDown': 0x1E, // 49 PgDown
+ 'PgDn': 0x1E, // 49 PgDown
'Right': 0x1F, // 59 `->`
'F1': 0x10, // 12 F1
@@ -120,14 +133,13 @@ var WqxKeyInput = function (){
'F3': 0x12, // 14 F3
'F4': 0x13 // 15 F4
};
- WqxKeyInput.prototype._keyDownOrUp = function (key, downOrUp){
- var wqxKeyCode = keyNameToKeypadMatrixIndex[key];
- if (wqxKeyCode) {
- var col = wqxKeyCode >> 3;
- var row = wqxKeyCode & 0x07;
- this.wqx.keypadmatrix[row][col] = downOrUp ? 1 : 0;
- }
- };
+WqxKeyInput.prototype._keyDownOrUp = function (key, downOrUp){
+ var wqxKeyCode = keyNameToKeypadMatrixIndex[key];
+ if (wqxKeyCode !== undefined) {
+ // 改为调用setKey,走统一的位运算+唤醒逻辑
+ this.wqx.setKey(wqxKeyCode, downOrUp);
+ }
+};
WqxKeyInput.prototype.keyDown = function (key){
this._keyDownOrUp(key, true);
this.onpress(key);
@@ -147,4 +159,4 @@ var WqxKeyInput = function (){
WqxKeyInput.prototype.onpress = function (key){};
WqxKeyInput.prototype.onrelease = function (key){};
return WqxKeyInput;
-}();
\ No newline at end of file
+}();
diff --git a/src/m65c02.js b/src/m65c02.js
index 9324c4d..865e647 100644
--- a/src/m65c02.js
+++ b/src/m65c02.js
@@ -1,3 +1,4 @@
+// m65c02.js - 修复版本
function M65C02Context() {
this.ram = null;
this.memmap = null;
@@ -11,7 +12,6 @@ function M65C02Context() {
this.reg_y = 0;
this.reg_pc = 0;
this.reg_sp = 0x100;
- //this.reg_ps = 0;
this.flag_c = 0;
this.flag_z = 0;
this.flag_i = 0;
@@ -30,9 +30,11 @@ function M65C02Context() {
this._tmp2 = 0;
this._counters = new Uint32Array(0x100);
}
+
M65C02Context.prototype.get_reg_ps = function() {
return ((this.flag_c) | (this.flag_z << 1) | (this.flag_i << 2) | (this.flag_d << 3) | (this.flag_b << 4) | (this.flag_u << 5) | (this.flag_v << 6) | (this.flag_n << 7));
};
+
M65C02Context.prototype.set_reg_ps = function(ps) {
this.flag_c = (ps & 0x01);
this.flag_z = (ps & 0x02) >> 1;
@@ -44,153 +46,177 @@ M65C02Context.prototype.set_reg_ps = function(ps) {
this.flag_n = (ps & 0x80) >> 7;
return ps;
};
+
+// 辅助函数:读取内存(带IO)
+M65C02Context.prototype.readMem = function(addr) {
+ if (this.io_read_map[addr]) {
+ var value = this.io_read(addr);
+ // 唤醒检测 - 注意这里需要能访问 wqx 实例的 wakeUpPending
+ // 问题:M65C02Context 没有直接引用 Wqx 实例
+ if (this.wakeUpPending && addr === 0x45F) {
+ this.wakeUpPending = false;
+ return this.wakeUpValue;
+ }
+ return value;
+ }
+ return this.memmap[addr >> 13][addr & 0x1FFF];
+};
+
+// 辅助函数:写入内存(带IO)
+M65C02Context.prototype.writeMem = function(addr, value) {
+ if (this.io_write_map[addr]) {
+ this.io_write(addr, value);
+ } else {
+ this.memmap[addr >> 13][addr & 0x1FFF] = value;
+ }
+};
+
+// 修复后的 op_func_tbl
M65C02Context.prototype.op_func_tbl = [
+ // 0x00 BRK
function op00(this_) {
this_.reg_pc++;
- this_.ram[this_.reg_sp] = (this_.reg_pc >> 8);
+ this_.writeMem(this_.reg_sp, (this_.reg_pc >> 8));
this_.reg_sp = --this_.reg_sp & 0xFF | 0x100;
- this_.ram[this_.reg_sp] = (this_.reg_pc & 0xFF);
+ this_.writeMem(this_.reg_sp, (this_.reg_pc & 0xFF));
this_.reg_sp = --this_.reg_sp & 0xFF | 0x100;
this_.flag_b = 1;
- this_.ram[this_.reg_sp] = this_.get_reg_ps();
+ this_.writeMem(this_.reg_sp, this_.get_reg_ps());
this_.reg_sp = --this_.reg_sp & 0xFF | 0x100;
this_.flag_i = 1;
this_.reg_pc = (this_.memmap[7][0x1FFF] << 8) | (this_.memmap[7][0x1FFE]);
this_.cycles += 7;
},
+ // 0x01 ORA (indirect,X)
function op01(this_) {
- this_._tmp1 = (this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF] + this_.reg_x) & 0xFF;
- this_._addr = (((this_._tmp1 < 0xFFFF ? this_.memmap[(this_._tmp1 + 1) >> 13][(this_._tmp1 + 1) & 0x1FFF] : this_.ram[0]) << 8) | this_.memmap[this_._tmp1 >> 13][this_._tmp1 & 0x1FFF]);
+ this_._tmp1 = (this_.readMem(this_.reg_pc) + this_.reg_x) & 0xFF;
+ this_._addr = (this_.readMem((this_._tmp1 + 1) & 0xFF) << 8) | this_.readMem(this_._tmp1);
this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
- this_.reg_a |= (this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]);
+ this_.reg_a |= this_.readMem(this_._addr);
this_.flag_n = (this_.reg_a & 0x80) >> 7;
this_.flag_z = (this_.reg_a & 0xFF) ? 0 : 1;
this_.cycles += 6;
},
+ // 0x02 未使用
function op02(this_) {
this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
this_.cycles += 2;
},
+ // 0x03 未使用
function op03(this_) {
this_.cycles += 1;
},
+ // 0x04 TSB zp
function op04(this_) {
- this_._addr = this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF];
+ this_._addr = this_.readMem(this_.reg_pc);
this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
- this_._tmp1 = (this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]);
+ this_._tmp1 = this_.readMem(this_._addr);
this_.flag_z = (this_.reg_a & this_._tmp1) ? 0 : 1;
- if (this_.io_write_map[this_._addr]) {
- this_.io_write(this_._addr, (this_._tmp1 | this_.reg_a));
- } else {
- this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF] = (this_._tmp1 | this_.reg_a);
- }
+ this_.writeMem(this_._addr, (this_._tmp1 | this_.reg_a));
this_.cycles += 5;
},
+ // 0x05 ORA zp
function op05(this_) {
- this_._addr = this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF];
+ this_._addr = this_.readMem(this_.reg_pc);
this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
- this_.reg_a |= (this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]);
+ this_.reg_a |= this_.readMem(this_._addr);
this_.flag_n = (this_.reg_a & 0x80) >> 7;
this_.flag_z = (this_.reg_a & 0xFF) ? 0 : 1;
this_.cycles += 3;
},
+ // 0x06 ASL zp
function op06(this_) {
- this_._addr = this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF];
+ this_._addr = this_.readMem(this_.reg_pc);
this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
- this_._tmp1 = (this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]) << 1;
+ this_._tmp1 = this_.readMem(this_._addr) << 1;
this_.flag_c = (this_._tmp1 > 0xFF) ? 1 : 0;
+ this_.writeMem(this_._addr, (this_._tmp1 & 0xFF));
this_.flag_n = (this_._tmp1 & 0x80) >> 7;
this_.flag_z = (this_._tmp1 & 0xFF) ? 0 : 1;
- if (this_.io_write_map[this_._addr]) {
- this_.io_write(this_._addr, (this_._tmp1 & 0xFF));
- } else {
- this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF] = (this_._tmp1 & 0xFF);
- }
this_.cycles += 5;
},
+ // 0x07 RMB0 zp
function op07(this_) {
- this_._addr = this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF];
+ this_._addr = this_.readMem(this_.reg_pc);
this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
- this_._tmp1 = (this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]) & 0xFE;
+ this_._tmp1 = this_.readMem(this_._addr) & 0xFE;
+ this_.writeMem(this_._addr, this_._tmp1);
this_.flag_n = (this_._tmp1 & 0x80) >> 7;
this_.flag_z = (this_._tmp1 & 0xFF) ? 0 : 1;
- if (this_.io_write_map[this_._addr]) {
- this_.io_write(this_._addr, this_._tmp1);
- } else {
- this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF] = this_._tmp1;
- }
this_.cycles += 5;
},
+ // 0x08 PHP
function op08(this_) {
this_.flag_u = 1;
- this_.ram[this_.reg_sp] = this_.get_reg_ps();
+ this_.writeMem(this_.reg_sp, this_.get_reg_ps());
this_.reg_sp = --this_.reg_sp & 0xFF | 0x100;
this_.cycles += 3;
},
+ // 0x09 ORA imm
function op09(this_) {
this_._addr = this_.reg_pc;
this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
- this_.reg_a |= (this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]);
+ this_.reg_a |= this_.readMem(this_._addr);
this_.flag_n = (this_.reg_a & 0x80) >> 7;
this_.flag_z = (this_.reg_a & 0xFF) ? 0 : 1;
this_.cycles += 2;
},
+ // 0x0A ASL A
function op0A(this_) {
this_._tmp1 = this_.reg_a << 1;
this_.flag_c = (this_._tmp1 > 0xFF) ? 1 : 0;
- this_.flag_n = (this_._tmp1 & 0x80) >> 7;
- this_.flag_z = (this_._tmp1 & 0xFF) ? 0 : 1;
this_.reg_a = (this_._tmp1 & 0xFF);
+ this_.flag_n = (this_.reg_a & 0x80) >> 7;
+ this_.flag_z = (this_.reg_a & 0xFF) ? 0 : 1;
this_.cycles += 2;
},
+ // 0x0B 未使用
function op0B(this_) {
this_.cycles += 1;
},
+ // 0x0C TSB abs
function op0C(this_) {
- this_._addr = (((this_.reg_pc < 0xFFFF ? this_.memmap[(this_.reg_pc + 1) >> 13][(this_.reg_pc + 1) & 0x1FFF] : this_.ram[0]) << 8) | this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF]);
+ this_._addr = (this_.readMem(this_.reg_pc + 1) << 8) | this_.readMem(this_.reg_pc);
this_.reg_pc = (this_.reg_pc + 2) & 0xFFFF;
- this_._tmp1 = (this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]);
+ this_._tmp1 = this_.readMem(this_._addr);
this_.flag_z = (this_.reg_a & this_._tmp1) ? 0 : 1;
- if (this_.io_write_map[this_._addr]) {
- this_.io_write(this_._addr, (this_._tmp1 | this_.reg_a));
- } else {
- this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF] = (this_._tmp1 | this_.reg_a);
- }
+ this_.writeMem(this_._addr, (this_._tmp1 | this_.reg_a));
this_.cycles += 6;
},
+ // 0x0D ORA abs
function op0D(this_) {
- this_._addr = (((this_.reg_pc < 0xFFFF ? this_.memmap[(this_.reg_pc + 1) >> 13][(this_.reg_pc + 1) & 0x1FFF] : this_.ram[0]) << 8) | this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF]);
+ this_._addr = (this_.readMem(this_.reg_pc + 1) << 8) | this_.readMem(this_.reg_pc);
this_.reg_pc = (this_.reg_pc + 2) & 0xFFFF;
- this_.reg_a |= (this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]);
+ this_.reg_a |= this_.readMem(this_._addr);
this_.flag_n = (this_.reg_a & 0x80) >> 7;
this_.flag_z = (this_.reg_a & 0xFF) ? 0 : 1;
this_.cycles += 4;
},
+ // 0x0E ASL abs
function op0E(this_) {
- this_._addr = (((this_.reg_pc < 0xFFFF ? this_.memmap[(this_.reg_pc + 1) >> 13][(this_.reg_pc + 1) & 0x1FFF] : this_.ram[0]) << 8) | this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF]);
+ this_._addr = (this_.readMem(this_.reg_pc + 1) << 8) | this_.readMem(this_.reg_pc);
this_.reg_pc = (this_.reg_pc + 2) & 0xFFFF;
- this_._tmp1 = (this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]) << 1;
+ this_._tmp1 = this_.readMem(this_._addr) << 1;
this_.flag_c = (this_._tmp1 > 0xFF) ? 1 : 0;
+ this_.writeMem(this_._addr, (this_._tmp1 & 0xFF));
this_.flag_n = (this_._tmp1 & 0x80) >> 7;
this_.flag_z = (this_._tmp1 & 0xFF) ? 0 : 1;
- if (this_.io_write_map[this_._addr]) {
- this_.io_write(this_._addr, (this_._tmp1 & 0xFF));
- } else {
- this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF] = (this_._tmp1 & 0xFF);
- }
this_.cycles += 6;
},
+ // 0x0F BBR0
function op0F(this_) {
- this_._addr = this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF];
- this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
- if (!((this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]) & 0x01)) {
+ this_._addr = this_.readMem(this_.reg_pc);
+ this_._tmp2 = this_.readMem(this_.reg_pc + 1);
+ this_.reg_pc = (this_.reg_pc + 2) & 0xFFFF;
+ if (!(this_.readMem(this_._addr) & 0x01)) {
this_.reg_pc = (this_.reg_pc + this_._tmp2) & 0xFFFF;
this_.cycles++;
}
this_.cycles += 5;
},
+ // 0x10 BPL
function op10(this_) {
- this_._tmp1 = this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF];
+ this_._tmp1 = this_.readMem(this_.reg_pc);
this_._tmp2 = this_._tmp1 - ((this_._tmp1 & 0x80) << 1);
this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
if (!this_.flag_n) {
@@ -199,221 +225,236 @@ M65C02Context.prototype.op_func_tbl = [
}
this_.cycles += 2;
},
+ // 0x11 ORA (indirect),Y
function op11(this_) {
- this_._tmp1 = this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF];
- this_._addr = ((((this_._tmp1 < 0xFFFF ? this_.memmap[(this_._tmp1 + 1) >> 13][(this_._tmp1 + 1) & 0x1FFF] : this_.ram[0]) << 8) | this_.memmap[this_._tmp1 >> 13][this_._tmp1 & 0x1FFF]) + this_.reg_y) & 0xFFFF;
+ this_._tmp1 = this_.readMem(this_.reg_pc);
+ this_._addr = (this_.readMem((this_._tmp1 + 1) & 0xFF) << 8) | this_.readMem(this_._tmp1);
+ // 跨页检测
+ if ((this_._addr & 0xFF00) !== ((this_._addr + this_.reg_y) & 0xFF00)) {
+ this_.cycles++;
+ }
+ this_._addr = (this_._addr + this_.reg_y) & 0xFFFF;
this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
- this_.reg_a |= (this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]);
+ this_.reg_a |= this_.readMem(this_._addr);
this_.flag_n = (this_.reg_a & 0x80) >> 7;
this_.flag_z = (this_.reg_a & 0xFF) ? 0 : 1;
this_.cycles += 5;
},
+ // 0x12 ORA (indirect)
function op12(this_) {
- this_._tmp1 = this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF];
- this_._addr = ((this_._tmp1 < 0xFF ? this_.ram[this_._tmp1 + 1] : this_.ram[0]) << 8) | this_.ram[this_._tmp1];
+ this_._tmp1 = this_.readMem(this_.reg_pc);
+ this_._addr = (this_.readMem((this_._tmp1 + 1) & 0xFF) << 8) | this_.readMem(this_._tmp1);
this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
- this_.reg_a |= (this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]);
+ this_.reg_a |= this_.readMem(this_._addr);
this_.flag_n = (this_.reg_a & 0x80) >> 7;
this_.flag_z = (this_.reg_a & 0xFF) ? 0 : 1;
this_.cycles += 5;
},
+ // 0x13 未使用
function op13(this_) {
this_.cycles += 1;
},
+ // 0x14 TRB zp
function op14(this_) {
- this_._addr = this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF];
+ this_._addr = this_.readMem(this_.reg_pc);
this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
- this_._tmp1 = (this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]);
+ this_._tmp1 = this_.readMem(this_._addr);
this_.flag_z = (this_.reg_a & this_._tmp1) ? 0 : 1;
- if (this_.io_write_map[this_._addr]) {
- this_.io_write(this_._addr, (this_._tmp1 & ~this_.reg_a));
- } else {
- this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF] = (this_._tmp1 & ~this_.reg_a);
- }
+ this_.writeMem(this_._addr, (this_._tmp1 & ~this_.reg_a));
this_.cycles += 5;
},
+ // 0x15 ORA zp,X
function op15(this_) {
- this_._addr = (this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF] + this_.reg_x) & 0xFF;
+ this_._addr = (this_.readMem(this_.reg_pc) + this_.reg_x) & 0xFF;
this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
- this_.reg_a |= (this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]);
+ this_.reg_a |= this_.readMem(this_._addr);
this_.flag_n = (this_.reg_a & 0x80) >> 7;
this_.flag_z = (this_.reg_a & 0xFF) ? 0 : 1;
this_.cycles += 4;
},
+ // 0x16 ASL zp,X
function op16(this_) {
- this_._addr = (this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF] + this_.reg_x) & 0xFF;
+ this_._addr = (this_.readMem(this_.reg_pc) + this_.reg_x) & 0xFF;
this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
- this_._tmp1 = (this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]) << 1;
+ this_._tmp1 = this_.readMem(this_._addr) << 1;
this_.flag_c = (this_._tmp1 > 0xFF) ? 1 : 0;
+ this_.writeMem(this_._addr, (this_._tmp1 & 0xFF));
this_.flag_n = (this_._tmp1 & 0x80) >> 7;
this_.flag_z = (this_._tmp1 & 0xFF) ? 0 : 1;
- if (this_.io_write_map[this_._addr]) {
- this_.io_write(this_._addr, (this_._tmp1 & 0xFF));
- } else {
- this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF] = (this_._tmp1 & 0xFF);
- }
this_.cycles += 6;
},
+ // 0x17 RMB1 zp
function op17(this_) {
- this_._addr = this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF];
+ this_._addr = this_.readMem(this_.reg_pc);
this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
- this_._tmp1 = (this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]) & 0xFD;
+ this_._tmp1 = this_.readMem(this_._addr) & 0xFD;
+ this_.writeMem(this_._addr, this_._tmp1);
this_.flag_n = (this_._tmp1 & 0x80) >> 7;
this_.flag_z = (this_._tmp1 & 0xFF) ? 0 : 1;
- if (this_.io_write_map[this_._addr]) {
- this_.io_write(this_._addr, this_._tmp1);
- } else {
- this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF] = this_._tmp1;
- }
this_.cycles += 5;
},
+ // 0x18 CLC
function op18(this_) {
this_.flag_c = 0;
this_.cycles += 2;
},
+ // 0x19 ORA abs,Y
function op19(this_) {
- this_._addr = ((((this_.reg_pc < 0xFFFF ? this_.memmap[(this_.reg_pc + 1) >> 13][(this_.reg_pc + 1) & 0x1FFF] : this_.ram[0]) << 8) | this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF]) + this_.reg_y) & 0xFFFF;
+ this_._addr = (this_.readMem(this_.reg_pc + 1) << 8) | this_.readMem(this_.reg_pc);
+ // 跨页检测
+ if ((this_._addr & 0xFF00) !== ((this_._addr + this_.reg_y) & 0xFF00)) {
+ this_.cycles++;
+ }
+ this_._addr = (this_._addr + this_.reg_y) & 0xFFFF;
this_.reg_pc = (this_.reg_pc + 2) & 0xFFFF;
- this_.reg_a |= (this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]);
+ this_.reg_a |= this_.readMem(this_._addr);
this_.flag_n = (this_.reg_a & 0x80) >> 7;
this_.flag_z = (this_.reg_a & 0xFF) ? 0 : 1;
this_.cycles += 4;
},
+ // 0x1A INC A
function op1A(this_) {
this_.reg_a = (++this_.reg_a & 0xFF);
this_.flag_n = (this_.reg_a & 0x80) >> 7;
this_.flag_z = (this_.reg_a & 0xFF) ? 0 : 1;
this_.cycles += 2;
},
+ // 0x1B 未使用
function op1B(this_) {
this_.cycles += 1;
},
+ // 0x1C TRB abs
function op1C(this_) {
- this_._addr = (((this_.reg_pc < 0xFFFF ? this_.memmap[(this_.reg_pc + 1) >> 13][(this_.reg_pc + 1) & 0x1FFF] : this_.ram[0]) << 8) | this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF]);
+ this_._addr = (this_.readMem(this_.reg_pc + 1) << 8) | this_.readMem(this_.reg_pc);
this_.reg_pc = (this_.reg_pc + 2) & 0xFFFF;
- this_._tmp1 = (this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]);
+ this_._tmp1 = this_.readMem(this_._addr);
this_.flag_z = (this_.reg_a & this_._tmp1) ? 0 : 1;
- if (this_.io_write_map[this_._addr]) {
- this_.io_write(this_._addr, (this_._tmp1 & ~this_.reg_a));
- } else {
- this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF] = (this_._tmp1 & ~this_.reg_a);
- }
+ this_.writeMem(this_._addr, (this_._tmp1 & ~this_.reg_a));
this_.cycles += 6;
},
+ // 0x1D ORA abs,X
function op1D(this_) {
- this_._addr = ((((this_.reg_pc < 0xFFFF ? this_.memmap[(this_.reg_pc + 1) >> 13][(this_.reg_pc + 1) & 0x1FFF] : this_.ram[0]) << 8) | this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF]) + this_.reg_x) & 0xFFFF;
+ this_._addr = (this_.readMem(this_.reg_pc + 1) << 8) | this_.readMem(this_.reg_pc);
+ // 跨页检测
+ if ((this_._addr & 0xFF00) !== ((this_._addr + this_.reg_x) & 0xFF00)) {
+ this_.cycles++;
+ }
+ this_._addr = (this_._addr + this_.reg_x) & 0xFFFF;
this_.reg_pc = (this_.reg_pc + 2) & 0xFFFF;
- this_.reg_a |= (this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]);
+ this_.reg_a |= this_.readMem(this_._addr);
this_.flag_n = (this_.reg_a & 0x80) >> 7;
this_.flag_z = (this_.reg_a & 0xFF) ? 0 : 1;
this_.cycles += 4;
},
+ // 0x1E ASL abs,X
function op1E(this_) {
- this_._addr = ((((this_.reg_pc < 0xFFFF ? this_.memmap[(this_.reg_pc + 1) >> 13][(this_.reg_pc + 1) & 0x1FFF] : this_.ram[0]) << 8) | this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF]) + this_.reg_x) & 0xFFFF;
+ this_._addr = ((this_.readMem(this_.reg_pc + 1) << 8) | this_.readMem(this_.reg_pc)) + this_.reg_x;
this_.reg_pc = (this_.reg_pc + 2) & 0xFFFF;
- this_._tmp1 = (this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]) << 1;
+ this_._tmp1 = this_.readMem(this_._addr) << 1;
this_.flag_c = (this_._tmp1 > 0xFF) ? 1 : 0;
+ this_.writeMem(this_._addr, (this_._tmp1 & 0xFF));
this_.flag_n = (this_._tmp1 & 0x80) >> 7;
this_.flag_z = (this_._tmp1 & 0xFF) ? 0 : 1;
- if (this_.io_write_map[this_._addr]) {
- this_.io_write(this_._addr, (this_._tmp1 & 0xFF));
- } else {
- this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF] = (this_._tmp1 & 0xFF);
- }
this_.cycles += 6;
},
+ // 0x1F BBR1
function op1F(this_) {
- this_._addr = this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF];
- this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
- if (!((this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]) & 0x02)) {
+ this_._addr = this_.readMem(this_.reg_pc);
+ this_._tmp2 = this_.readMem(this_.reg_pc + 1);
+ this_.reg_pc = (this_.reg_pc + 2) & 0xFFFF;
+ if (!(this_.readMem(this_._addr) & 0x02)) {
this_.reg_pc = (this_.reg_pc + this_._tmp2) & 0xFFFF;
this_.cycles++;
}
this_.cycles += 5;
},
+ // 0x20 JSR
function op20(this_) {
- this_._addr = (((this_.reg_pc < 0xFFFF ? this_.memmap[(this_.reg_pc + 1) >> 13][(this_.reg_pc + 1) & 0x1FFF] : this_.ram[0]) << 8) | this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF]);
+ this_._addr = (this_.readMem(this_.reg_pc + 1) << 8) | this_.readMem(this_.reg_pc);
this_.reg_pc = (this_.reg_pc + 2) & 0xFFFF;
this_.reg_pc = (this_.reg_pc - 1) & 0xFFFF;
- this_.ram[this_.reg_sp] = (this_.reg_pc >> 8);
+ this_.writeMem(this_.reg_sp, (this_.reg_pc >> 8));
this_.reg_sp = --this_.reg_sp & 0xFF | 0x100;
- this_.ram[this_.reg_sp] = (this_.reg_pc & 0xFF);
+ this_.writeMem(this_.reg_sp, (this_.reg_pc & 0xFF));
this_.reg_sp = --this_.reg_sp & 0xFF | 0x100;
this_.reg_pc = this_._addr;
this_.cycles += 6;
},
+ // 0x21 AND (indirect,X)
function op21(this_) {
- this_._tmp1 = (this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF] + this_.reg_x) & 0xFF;
- this_._addr = (((this_._tmp1 < 0xFFFF ? this_.memmap[(this_._tmp1 + 1) >> 13][(this_._tmp1 + 1) & 0x1FFF] : this_.ram[0]) << 8) | this_.memmap[this_._tmp1 >> 13][this_._tmp1 & 0x1FFF]);
+ this_._tmp1 = (this_.readMem(this_.reg_pc) + this_.reg_x) & 0xFF;
+ this_._addr = (this_.readMem((this_._tmp1 + 1) & 0xFF) << 8) | this_.readMem(this_._tmp1);
this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
- this_.reg_a &= (this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]);
+ this_.reg_a &= this_.readMem(this_._addr);
this_.flag_n = (this_.reg_a & 0x80) >> 7;
this_.flag_z = (this_.reg_a & 0xFF) ? 0 : 1;
this_.cycles += 6;
},
+ // 0x22 未使用
function op22(this_) {
this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
this_.cycles += 2;
},
+ // 0x23 未使用
function op23(this_) {
this_.cycles += 1;
},
+ // 0x24 BIT zp
function op24(this_) {
- this_._addr = this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF];
+ this_._addr = this_.readMem(this_.reg_pc);
this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
- this_._tmp1 = (this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]);
+ this_._tmp1 = this_.readMem(this_._addr);
this_.flag_z = !(this_.reg_a & this_._tmp1) | 0;
this_.flag_n = (this_._tmp1 & 0x80) >> 7;
this_.flag_v = (this_._tmp1 & 0x40) >> 6;
this_.cycles += 3;
},
+ // 0x25 AND zp
function op25(this_) {
- this_._addr = this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF];
+ this_._addr = this_.readMem(this_.reg_pc);
this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
- this_.reg_a &= (this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]);
+ this_.reg_a &= this_.readMem(this_._addr);
this_.flag_n = (this_.reg_a & 0x80) >> 7;
this_.flag_z = (this_.reg_a & 0xFF) ? 0 : 1;
this_.cycles += 3;
},
+ // 0x26 ROL zp
function op26(this_) {
- this_._addr = this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF];
+ this_._addr = this_.readMem(this_.reg_pc);
this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
- this_._tmp1 = ((this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]) << 1) | this_.flag_c;
+ this_._tmp1 = (this_.readMem(this_._addr) << 1) | this_.flag_c;
this_.flag_c = (this_._tmp1 > 0xFF) ? 1 : 0;
+ this_.writeMem(this_._addr, (this_._tmp1 & 0xFF));
this_.flag_n = (this_._tmp1 & 0x80) >> 7;
this_.flag_z = (this_._tmp1 & 0xFF) ? 0 : 1;
- if (this_.io_write_map[this_._addr]) {
- this_.io_write(this_._addr, (this_._tmp1 & 0xFF));
- } else {
- this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF] = (this_._tmp1 & 0xFF);
- }
this_.cycles += 5;
},
+ // 0x27 RMB2 zp
function op27(this_) {
- this_._addr = this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF];
+ this_._addr = this_.readMem(this_.reg_pc);
this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
- this_._tmp1 = (this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]) & 0xFB;
+ this_._tmp1 = this_.readMem(this_._addr) & 0xFB;
+ this_.writeMem(this_._addr, this_._tmp1);
this_.flag_n = (this_._tmp1 & 0x80) >> 7;
this_.flag_z = (this_._tmp1 & 0xFF) ? 0 : 1;
- if (this_.io_write_map[this_._addr]) {
- this_.io_write(this_._addr, this_._tmp1);
- } else {
- this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF] = this_._tmp1;
- }
this_.cycles += 5;
},
+ // 0x28 PLP
function op28(this_) {
- this_.set_reg_ps(this_.ram[this_.reg_sp = ++this_.reg_sp & 0xFF | 0x100]);
+ this_.reg_sp = ++this_.reg_sp & 0xFF | 0x100;
+ this_.set_reg_ps(this_.readMem(this_.reg_sp));
this_.cycles += 4;
},
+ // 0x29 AND imm
function op29(this_) {
this_._addr = this_.reg_pc;
this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
- this_.reg_a &= (this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]);
+ this_.reg_a &= this_.readMem(this_._addr);
this_.flag_n = (this_.reg_a & 0x80) >> 7;
this_.flag_z = (this_.reg_a & 0xFF) ? 0 : 1;
this_.cycles += 2;
},
+ // 0x2A ROL A
function op2A(this_) {
this_._tmp1 = (this_.reg_a << 1) | this_.flag_c;
this_.flag_c = (this_._tmp1 > 0xFF) ? 1 : 0;
@@ -422,51 +463,54 @@ M65C02Context.prototype.op_func_tbl = [
this_.flag_z = (this_.reg_a & 0xFF) ? 0 : 1;
this_.cycles += 2;
},
+ // 0x2B 未使用
function op2B(this_) {
this_.cycles += 1;
},
+ // 0x2C BIT abs
function op2C(this_) {
- this_._addr = (((this_.reg_pc < 0xFFFF ? this_.memmap[(this_.reg_pc + 1) >> 13][(this_.reg_pc + 1) & 0x1FFF] : this_.ram[0]) << 8) | this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF]);
+ this_._addr = (this_.readMem(this_.reg_pc + 1) << 8) | this_.readMem(this_.reg_pc);
this_.reg_pc = (this_.reg_pc + 2) & 0xFFFF;
- this_._tmp1 = (this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]);
+ this_._tmp1 = this_.readMem(this_._addr);
this_.flag_z = !(this_.reg_a & this_._tmp1) | 0;
this_.flag_n = (this_._tmp1 & 0x80) >> 7;
this_.flag_v = (this_._tmp1 & 0x40) >> 6;
this_.cycles += 4;
},
+ // 0x2D AND abs
function op2D(this_) {
- this_._addr = (((this_.reg_pc < 0xFFFF ? this_.memmap[(this_.reg_pc + 1) >> 13][(this_.reg_pc + 1) & 0x1FFF] : this_.ram[0]) << 8) | this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF]);
+ this_._addr = (this_.readMem(this_.reg_pc + 1) << 8) | this_.readMem(this_.reg_pc);
this_.reg_pc = (this_.reg_pc + 2) & 0xFFFF;
- this_.reg_a &= (this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]);
+ this_.reg_a &= this_.readMem(this_._addr);
this_.flag_n = (this_.reg_a & 0x80) >> 7;
this_.flag_z = (this_.reg_a & 0xFF) ? 0 : 1;
this_.cycles += 4;
},
+ // 0x2E ROL abs
function op2E(this_) {
- this_._addr = (((this_.reg_pc < 0xFFFF ? this_.memmap[(this_.reg_pc + 1) >> 13][(this_.reg_pc + 1) & 0x1FFF] : this_.ram[0]) << 8) | this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF]);
+ this_._addr = (this_.readMem(this_.reg_pc + 1) << 8) | this_.readMem(this_.reg_pc);
this_.reg_pc = (this_.reg_pc + 2) & 0xFFFF;
- this_._tmp1 = ((this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]) << 1) | this_.flag_c;
+ this_._tmp1 = (this_.readMem(this_._addr) << 1) | this_.flag_c;
this_.flag_c = (this_._tmp1 > 0xFF) ? 1 : 0;
+ this_.writeMem(this_._addr, (this_._tmp1 & 0xFF));
this_.flag_n = (this_._tmp1 & 0x80) >> 7;
this_.flag_z = (this_._tmp1 & 0xFF) ? 0 : 1;
- if (this_.io_write_map[this_._addr]) {
- this_.io_write(this_._addr, (this_._tmp1 & 0xFF));
- } else {
- this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF] = (this_._tmp1 & 0xFF);
- }
this_.cycles += 6;
},
+ // 0x2F BBR2
function op2F(this_) {
- this_._addr = this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF];
- this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
- if (!((this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]) & 0x04)) {
+ this_._addr = this_.readMem(this_.reg_pc);
+ this_._tmp2 = this_.readMem(this_.reg_pc + 1);
+ this_.reg_pc = (this_.reg_pc + 2) & 0xFFFF;
+ if (!(this_.readMem(this_._addr) & 0x04)) {
this_.reg_pc = (this_.reg_pc + this_._tmp2) & 0xFFFF;
this_.cycles++;
}
this_.cycles += 5;
},
+ // 0x30 BMI
function op30(this_) {
- this_._tmp1 = this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF];
+ this_._tmp1 = this_.readMem(this_.reg_pc);
this_._tmp2 = this_._tmp1 - ((this_._tmp1 & 0x80) << 1);
this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
if (this_.flag_n) {
@@ -475,259 +519,279 @@ M65C02Context.prototype.op_func_tbl = [
}
this_.cycles += 2;
},
+ // 0x31 AND (indirect),Y
function op31(this_) {
- this_._tmp1 = this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF];
- this_._addr = ((((this_._tmp1 < 0xFFFF ? this_.memmap[(this_._tmp1 + 1) >> 13][(this_._tmp1 + 1) & 0x1FFF] : this_.ram[0]) << 8) | this_.memmap[this_._tmp1 >> 13][this_._tmp1 & 0x1FFF]) + this_.reg_y) & 0xFFFF;
+ this_._tmp1 = this_.readMem(this_.reg_pc);
+ this_._addr = (this_.readMem((this_._tmp1 + 1) & 0xFF) << 8) | this_.readMem(this_._tmp1);
+ if ((this_._addr & 0xFF00) !== ((this_._addr + this_.reg_y) & 0xFF00)) {
+ this_.cycles++;
+ }
+ this_._addr = (this_._addr + this_.reg_y) & 0xFFFF;
this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
- this_.reg_a &= (this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]);
+ this_.reg_a &= this_.readMem(this_._addr);
this_.flag_n = (this_.reg_a & 0x80) >> 7;
this_.flag_z = (this_.reg_a & 0xFF) ? 0 : 1;
this_.cycles += 5;
},
+ // 0x32 AND (indirect)
function op32(this_) {
- this_._tmp1 = this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF];
- this_._addr = ((this_._tmp1 < 0xFF ? this_.ram[this_._tmp1 + 1] : this_.ram[0]) << 8) | this_.ram[this_._tmp1];
+ this_._tmp1 = this_.readMem(this_.reg_pc);
+ this_._addr = (this_.readMem((this_._tmp1 + 1) & 0xFF) << 8) | this_.readMem(this_._tmp1);
this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
- this_.reg_a &= (this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]);
+ this_.reg_a &= this_.readMem(this_._addr);
this_.flag_n = (this_.reg_a & 0x80) >> 7;
this_.flag_z = (this_.reg_a & 0xFF) ? 0 : 1;
this_.cycles += 5;
},
+ // 0x33 未使用
function op33(this_) {
this_.cycles += 1;
},
+ // 0x34 BIT zp,X
function op34(this_) {
- this_._addr = (this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF] + this_.reg_x) & 0xFF;
+ this_._addr = (this_.readMem(this_.reg_pc) + this_.reg_x) & 0xFF;
this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
- this_._tmp1 = (this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]);
+ this_._tmp1 = this_.readMem(this_._addr);
this_.flag_z = !(this_.reg_a & this_._tmp1) | 0;
this_.flag_n = (this_._tmp1 & 0x80) >> 7;
this_.flag_v = (this_._tmp1 & 0x40) >> 6;
this_.cycles += 4;
},
+ // 0x35 AND zp,X
function op35(this_) {
- this_._addr = (this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF] + this_.reg_x) & 0xFF;
+ this_._addr = (this_.readMem(this_.reg_pc) + this_.reg_x) & 0xFF;
this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
- this_.reg_a &= (this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]);
+ this_.reg_a &= this_.readMem(this_._addr);
this_.flag_n = (this_.reg_a & 0x80) >> 7;
this_.flag_z = (this_.reg_a & 0xFF) ? 0 : 1;
this_.cycles += 4;
},
+ // 0x36 ROL zp,X
function op36(this_) {
- this_._addr = (this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF] + this_.reg_x) & 0xFF;
+ this_._addr = (this_.readMem(this_.reg_pc) + this_.reg_x) & 0xFF;
this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
- this_._tmp1 = ((this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]) << 1) | this_.flag_c;
+ this_._tmp1 = (this_.readMem(this_._addr) << 1) | this_.flag_c;
this_.flag_c = (this_._tmp1 > 0xFF) ? 1 : 0;
+ this_.writeMem(this_._addr, (this_._tmp1 & 0xFF));
this_.flag_n = (this_._tmp1 & 0x80) >> 7;
this_.flag_z = (this_._tmp1 & 0xFF) ? 0 : 1;
- if (this_.io_write_map[this_._addr]) {
- this_.io_write(this_._addr, (this_._tmp1 & 0xFF));
- } else {
- this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF] = (this_._tmp1 & 0xFF);
- }
this_.cycles += 6;
},
+ // 0x37 RMB3 zp
function op37(this_) {
- this_._addr = this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF];
+ this_._addr = this_.readMem(this_.reg_pc);
this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
- this_._tmp1 = (this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]) & 0xF7;
+ this_._tmp1 = this_.readMem(this_._addr) & 0xF7;
+ this_.writeMem(this_._addr, this_._tmp1);
this_.flag_n = (this_._tmp1 & 0x80) >> 7;
this_.flag_z = (this_._tmp1 & 0xFF) ? 0 : 1;
- if (this_.io_write_map[this_._addr]) {
- this_.io_write(this_._addr, this_._tmp1);
- } else {
- this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF] = this_._tmp1;
- }
this_.cycles += 5;
},
+ // 0x38 SEC
function op38(this_) {
this_.flag_c = 1;
this_.cycles += 2;
},
+ // 0x39 AND abs,Y
function op39(this_) {
- this_._addr = ((((this_.reg_pc < 0xFFFF ? this_.memmap[(this_.reg_pc + 1) >> 13][(this_.reg_pc + 1) & 0x1FFF] : this_.ram[0]) << 8) | this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF]) + this_.reg_y) & 0xFFFF;
+ this_._addr = (this_.readMem(this_.reg_pc + 1) << 8) | this_.readMem(this_.reg_pc);
+ if ((this_._addr & 0xFF00) !== ((this_._addr + this_.reg_y) & 0xFF00)) {
+ this_.cycles++;
+ }
+ this_._addr = (this_._addr + this_.reg_y) & 0xFFFF;
this_.reg_pc = (this_.reg_pc + 2) & 0xFFFF;
- this_.reg_a &= (this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]);
+ this_.reg_a &= this_.readMem(this_._addr);
this_.flag_n = (this_.reg_a & 0x80) >> 7;
this_.flag_z = (this_.reg_a & 0xFF) ? 0 : 1;
this_.cycles += 4;
},
+ // 0x3A DEC A
function op3A(this_) {
this_.reg_a = (--this_.reg_a & 0xFF);
this_.flag_n = (this_.reg_a & 0x80) >> 7;
this_.flag_z = (this_.reg_a & 0xFF) ? 0 : 1;
this_.cycles += 2;
},
+ // 0x3B 未使用
function op3B(this_) {
this_.cycles += 1;
},
+ // 0x3C BIT abs,X
function op3C(this_) {
- this_._addr = ((((this_.reg_pc < 0xFFFF ? this_.memmap[(this_.reg_pc + 1) >> 13][(this_.reg_pc + 1) & 0x1FFF] : this_.ram[0]) << 8) | this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF]) + this_.reg_x) & 0xFFFF;
+ this_._addr = ((this_.readMem(this_.reg_pc + 1) << 8) | this_.readMem(this_.reg_pc)) + this_.reg_x;
this_.reg_pc = (this_.reg_pc + 2) & 0xFFFF;
- this_._tmp1 = (this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]);
+ this_._tmp1 = this_.readMem(this_._addr);
this_.flag_z = !(this_.reg_a & this_._tmp1) | 0;
this_.flag_n = (this_._tmp1 & 0x80) >> 7;
this_.flag_v = (this_._tmp1 & 0x40) >> 6;
this_.cycles += 4;
},
+ // 0x3D AND abs,X
function op3D(this_) {
- this_._addr = ((((this_.reg_pc < 0xFFFF ? this_.memmap[(this_.reg_pc + 1) >> 13][(this_.reg_pc + 1) & 0x1FFF] : this_.ram[0]) << 8) | this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF]) + this_.reg_x) & 0xFFFF;
+ this_._addr = ((this_.readMem(this_.reg_pc + 1) << 8) | this_.readMem(this_.reg_pc)) + this_.reg_x;
this_.reg_pc = (this_.reg_pc + 2) & 0xFFFF;
- this_.reg_a &= (this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]);
+ this_.reg_a &= this_.readMem(this_._addr);
this_.flag_n = (this_.reg_a & 0x80) >> 7;
this_.flag_z = (this_.reg_a & 0xFF) ? 0 : 1;
this_.cycles += 4;
},
+ // 0x3E ROL abs,X
function op3E(this_) {
- this_._addr = ((((this_.reg_pc < 0xFFFF ? this_.memmap[(this_.reg_pc + 1) >> 13][(this_.reg_pc + 1) & 0x1FFF] : this_.ram[0]) << 8) | this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF]) + this_.reg_x) & 0xFFFF;
+ this_._addr = ((this_.readMem(this_.reg_pc + 1) << 8) | this_.readMem(this_.reg_pc)) + this_.reg_x;
this_.reg_pc = (this_.reg_pc + 2) & 0xFFFF;
- this_._tmp1 = ((this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]) << 1) | this_.flag_c;
+ this_._tmp1 = (this_.readMem(this_._addr) << 1) | this_.flag_c;
this_.flag_c = (this_._tmp1 > 0xFF) ? 1 : 0;
+ this_.writeMem(this_._addr, (this_._tmp1 & 0xFF));
this_.flag_n = (this_._tmp1 & 0x80) >> 7;
this_.flag_z = (this_._tmp1 & 0xFF) ? 0 : 1;
- if (this_.io_write_map[this_._addr]) {
- this_.io_write(this_._addr, (this_._tmp1 & 0xFF));
- } else {
- this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF] = (this_._tmp1 & 0xFF);
- }
this_.cycles += 6;
},
+ // 0x3F BBR3
function op3F(this_) {
- this_._addr = this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF];
- this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
- if (!((this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]) & 0x08)) {
+ this_._addr = this_.readMem(this_.reg_pc);
+ this_._tmp2 = this_.readMem(this_.reg_pc + 1);
+ this_.reg_pc = (this_.reg_pc + 2) & 0xFFFF;
+ if (!(this_.readMem(this_._addr) & 0x08)) {
this_.reg_pc = (this_.reg_pc + this_._tmp2) & 0xFFFF;
this_.cycles++;
}
this_.cycles += 5;
},
+ // 0x40 RTI
function op40(this_) {
- this_.set_reg_ps(this_.ram[this_.reg_sp = ++this_.reg_sp & 0xFF | 0x100]);
+ this_.reg_sp = ++this_.reg_sp & 0xFF | 0x100;
+ this_.set_reg_ps(this_.readMem(this_.reg_sp));
this_.irq = 1;
- this_.reg_pc = this_.ram[this_.reg_sp = ++this_.reg_sp & 0xFF | 0x100];
- this_.reg_pc |= (this_.ram[this_.reg_sp = ++this_.reg_sp & 0xFF | 0x100] << 8);
+ this_.reg_sp = ++this_.reg_sp & 0xFF | 0x100;
+ this_.reg_pc = this_.readMem(this_.reg_sp);
+ this_.reg_sp = ++this_.reg_sp & 0xFF | 0x100;
+ this_.reg_pc |= (this_.readMem(this_.reg_sp) << 8);
this_.cycles += 6;
},
+ // 0x41 EOR (indirect,X)
function op41(this_) {
- this_._tmp1 = (this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF] + this_.reg_x) & 0xFF;
- this_._addr = (((this_._tmp1 < 0xFFFF ? this_.memmap[(this_._tmp1 + 1) >> 13][(this_._tmp1 + 1) & 0x1FFF] : this_.ram[0]) << 8) | this_.memmap[this_._tmp1 >> 13][this_._tmp1 & 0x1FFF]);
+ this_._tmp1 = (this_.readMem(this_.reg_pc) + this_.reg_x) & 0xFF;
+ this_._addr = (this_.readMem((this_._tmp1 + 1) & 0xFF) << 8) | this_.readMem(this_._tmp1);
this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
- this_.reg_a ^= (this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]);
+ this_.reg_a ^= this_.readMem(this_._addr);
this_.flag_n = (this_.reg_a & 0x80) >> 7;
this_.flag_z = (this_.reg_a & 0xFF) ? 0 : 1;
this_.cycles += 6;
},
+ // 0x42 未使用
function op42(this_) {
this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
this_.cycles += 2;
},
+ // 0x43 未使用
function op43(this_) {
this_.cycles += 1;
},
+ // 0x44 未使用
function op44(this_) {
this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
this_.cycles += 3;
},
+ // 0x45 EOR zp
function op45(this_) {
- this_._addr = this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF];
+ this_._addr = this_.readMem(this_.reg_pc);
this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
- this_.reg_a ^= (this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]);
+ this_.reg_a ^= this_.readMem(this_._addr);
this_.flag_n = (this_.reg_a & 0x80) >> 7;
this_.flag_z = (this_.reg_a & 0xFF) ? 0 : 1;
this_.cycles += 3;
},
+ // 0x46 LSR zp
function op46(this_) {
- this_._addr = this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF];
+ this_._addr = this_.readMem(this_.reg_pc);
this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
- this_._tmp1 = (this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]);
+ this_._tmp1 = this_.readMem(this_._addr);
this_.flag_c = this_._tmp1 & 0x01;
- this_.flag_z = (this_._tmp1 ^ 0x01) ? 1 : 0;
- this_.flag_n = 0;
this_._tmp1 >>= 1;
- if (this_.io_write_map[this_._addr]) {
- this_.io_write(this_._addr, this_._tmp1);
- } else {
- this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF] = this_._tmp1;
- }
+ this_.writeMem(this_._addr, this_._tmp1);
+ this_.flag_n = 0;
+ this_.flag_z = (this_._tmp1 & 0xFF) ? 0 : 1;
this_.cycles += 5;
},
+ // 0x47 RMB4 zp
function op47(this_) {
- this_._addr = this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF];
+ this_._addr = this_.readMem(this_.reg_pc);
this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
- this_._tmp1 = (this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]) & 0xEF;
+ this_._tmp1 = this_.readMem(this_._addr) & 0xEF;
+ this_.writeMem(this_._addr, this_._tmp1);
this_.flag_n = (this_._tmp1 & 0x80) >> 7;
this_.flag_z = (this_._tmp1 & 0xFF) ? 0 : 1;
- if (this_.io_write_map[this_._addr]) {
- this_.io_write(this_._addr, this_._tmp1);
- } else {
- this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF] = this_._tmp1;
- }
this_.cycles += 5;
},
+ // 0x48 PHA
function op48(this_) {
- this_.ram[this_.reg_sp] = this_.reg_a;
+ this_.writeMem(this_.reg_sp, this_.reg_a);
this_.reg_sp = --this_.reg_sp & 0xFF | 0x100;
this_.cycles += 3;
},
+ // 0x49 EOR imm
function op49(this_) {
this_._addr = this_.reg_pc;
this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
- this_.reg_a ^= (this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]);
+ this_.reg_a ^= this_.readMem(this_._addr);
this_.flag_n = (this_.reg_a & 0x80) >> 7;
this_.flag_z = (this_.reg_a & 0xFF) ? 0 : 1;
this_.cycles += 2;
},
+ // 0x4A LSR A
function op4A(this_) {
this_.flag_c = (this_.reg_a & 0x01);
- this_.flag_n = 0;
this_.reg_a >>= 1;
- this_.flag_n = (this_.reg_a & 0x80) >> 7;
+ this_.flag_n = 0;
this_.flag_z = (this_.reg_a & 0xFF) ? 0 : 1;
this_.cycles += 2;
},
+ // 0x4B 未使用
function op4B(this_) {
this_.cycles += 1;
},
+ // 0x4C JMP abs
function op4C(this_) {
- this_._addr = (((this_.reg_pc < 0xFFFF ? this_.memmap[(this_.reg_pc + 1) >> 13][(this_.reg_pc + 1) & 0x1FFF] : this_.ram[0]) << 8) | this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF]);
+ this_._addr = (this_.readMem(this_.reg_pc + 1) << 8) | this_.readMem(this_.reg_pc);
this_.reg_pc = (this_.reg_pc + 2) & 0xFFFF;
this_.reg_pc = this_._addr;
this_.cycles += 3;
},
+ // 0x4D EOR abs
function op4D(this_) {
- this_._addr = (((this_.reg_pc < 0xFFFF ? this_.memmap[(this_.reg_pc + 1) >> 13][(this_.reg_pc + 1) & 0x1FFF] : this_.ram[0]) << 8) | this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF]);
+ this_._addr = (this_.readMem(this_.reg_pc + 1) << 8) | this_.readMem(this_.reg_pc);
this_.reg_pc = (this_.reg_pc + 2) & 0xFFFF;
- this_.reg_a ^= (this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]);
+ this_.reg_a ^= this_.readMem(this_._addr);
this_.flag_n = (this_.reg_a & 0x80) >> 7;
this_.flag_z = (this_.reg_a & 0xFF) ? 0 : 1;
this_.cycles += 4;
},
+ // 0x4E LSR abs
function op4E(this_) {
- this_._addr = (((this_.reg_pc < 0xFFFF ? this_.memmap[(this_.reg_pc + 1) >> 13][(this_.reg_pc + 1) & 0x1FFF] : this_.ram[0]) << 8) | this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF]);
+ this_._addr = (this_.readMem(this_.reg_pc + 1) << 8) | this_.readMem(this_.reg_pc);
this_.reg_pc = (this_.reg_pc + 2) & 0xFFFF;
- this_._tmp1 = (this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]);
+ this_._tmp1 = this_.readMem(this_._addr);
this_.flag_c = this_._tmp1 & 0x01;
- this_.flag_z = (this_._tmp1 ^ 0x01) ? 1 : 0;
- this_.flag_n = 0;
this_._tmp1 >>= 1;
- if (this_.io_write_map[this_._addr]) {
- this_.io_write(this_._addr, this_._tmp1);
- } else {
- this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF] = this_._tmp1;
- }
+ this_.writeMem(this_._addr, this_._tmp1);
+ this_.flag_n = 0;
+ this_.flag_z = (this_._tmp1 & 0xFF) ? 0 : 1;
this_.cycles += 6;
},
+ // 0x4F BBR4
function op4F(this_) {
- this_._addr = this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF];
- this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
- if (!((this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]) & 0x10)) {
+ this_._addr = this_.readMem(this_.reg_pc);
+ this_._tmp2 = this_.readMem(this_.reg_pc + 1);
+ this_.reg_pc = (this_.reg_pc + 2) & 0xFFFF;
+ if (!(this_.readMem(this_._addr) & 0x10)) {
this_.reg_pc = (this_.reg_pc + this_._tmp2) & 0xFFFF;
this_.cycles++;
}
this_.cycles += 5;
},
+ // 0x50 BVC
function op50(this_) {
- this_._tmp1 = this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF];
+ this_._tmp1 = this_.readMem(this_.reg_pc);
this_._tmp2 = this_._tmp1 - ((this_._tmp1 & 0x80) << 1);
this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
if (!this_.flag_v) {
@@ -736,142 +800,168 @@ M65C02Context.prototype.op_func_tbl = [
}
this_.cycles += 2;
},
+ // 0x51 EOR (indirect),Y
function op51(this_) {
- this_._tmp1 = this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF];
- this_._addr = ((((this_._tmp1 < 0xFFFF ? this_.memmap[(this_._tmp1 + 1) >> 13][(this_._tmp1 + 1) & 0x1FFF] : this_.ram[0]) << 8) | this_.memmap[this_._tmp1 >> 13][this_._tmp1 & 0x1FFF]) + this_.reg_y) & 0xFFFF;
+ this_._tmp1 = this_.readMem(this_.reg_pc);
+ this_._addr = (this_.readMem((this_._tmp1 + 1) & 0xFF) << 8) | this_.readMem(this_._tmp1);
+ if ((this_._addr & 0xFF00) !== ((this_._addr + this_.reg_y) & 0xFF00)) {
+ this_.cycles++;
+ }
+ this_._addr = (this_._addr + this_.reg_y) & 0xFFFF;
this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
- this_.reg_a ^= (this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]);
+ this_.reg_a ^= this_.readMem(this_._addr);
this_.flag_n = (this_.reg_a & 0x80) >> 7;
this_.flag_z = (this_.reg_a & 0xFF) ? 0 : 1;
this_.cycles += 5;
},
+ // 0x52 EOR (indirect)
function op52(this_) {
- this_._tmp1 = this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF];
- this_._addr = ((this_._tmp1 < 0xFF ? this_.ram[this_._tmp1 + 1] : this_.ram[0]) << 8) | this_.ram[this_._tmp1];
+ this_._tmp1 = this_.readMem(this_.reg_pc);
+ this_._addr = (this_.readMem((this_._tmp1 + 1) & 0xFF) << 8) | this_.readMem(this_._tmp1);
this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
- this_.reg_a ^= (this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]);
+ this_.reg_a ^= this_.readMem(this_._addr);
this_.flag_n = (this_.reg_a & 0x80) >> 7;
this_.flag_z = (this_.reg_a & 0xFF) ? 0 : 1;
this_.cycles += 5;
},
+ // 0x53 未使用
function op53(this_) {
this_.cycles += 1;
},
+ // 0x54 未使用
function op54(this_) {
this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
this_.cycles += 4;
},
+ // 0x55 EOR zp,X
function op55(this_) {
- this_._addr = (this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF] + this_.reg_x) & 0xFF;
+ this_._addr = (this_.readMem(this_.reg_pc) + this_.reg_x) & 0xFF;
this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
- this_.reg_a ^= (this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]);
+ this_.reg_a ^= this_.readMem(this_._addr);
this_.flag_n = (this_.reg_a & 0x80) >> 7;
this_.flag_z = (this_.reg_a & 0xFF) ? 0 : 1;
this_.cycles += 4;
},
+ // 0x56 LSR zp,X
function op56(this_) {
- this_._addr = (this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF] + this_.reg_x) & 0xFF;
+ this_._addr = (this_.readMem(this_.reg_pc) + this_.reg_x) & 0xFF;
this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
- this_._tmp1 = (this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]);
+ this_._tmp1 = this_.readMem(this_._addr);
this_.flag_c = this_._tmp1 & 0x01;
- this_.flag_z = (this_._tmp1 ^ 0x01) ? 1 : 0;
- this_.flag_n = 0;
this_._tmp1 >>= 1;
- if (this_.io_write_map[this_._addr]) {
- this_.io_write(this_._addr, this_._tmp1);
- } else {
- this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF] = this_._tmp1;
- }
+ this_.writeMem(this_._addr, this_._tmp1);
+ this_.flag_n = 0;
+ this_.flag_z = (this_._tmp1 & 0xFF) ? 0 : 1;
this_.cycles += 6;
},
+ // 0x57 RMB5 zp
function op57(this_) {
- this_._addr = this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF];
+ this_._addr = this_.readMem(this_.reg_pc);
this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
- this_._tmp1 = (this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]) & 0xDF;
+ this_._tmp1 = this_.readMem(this_._addr) & 0xDF;
+ this_.writeMem(this_._addr, this_._tmp1);
this_.flag_n = (this_._tmp1 & 0x80) >> 7;
this_.flag_z = (this_._tmp1 & 0xFF) ? 0 : 1;
- if (this_.io_write_map[this_._addr]) {
- this_.io_write(this_._addr, this_._tmp1);
- } else {
- this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF] = this_._tmp1;
- }
this_.cycles += 5;
},
+ // 0x58 CLI
function op58(this_) {
this_.flag_i = 0;
this_.cycles += 2;
},
+ // 0x59 EOR abs,Y
function op59(this_) {
- this_._addr = ((((this_.reg_pc < 0xFFFF ? this_.memmap[(this_.reg_pc + 1) >> 13][(this_.reg_pc + 1) & 0x1FFF] : this_.ram[0]) << 8) | this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF]) + this_.reg_y) & 0xFFFF;
+ this_._addr = (this_.readMem(this_.reg_pc + 1) << 8) | this_.readMem(this_.reg_pc);
+ if ((this_._addr & 0xFF00) !== ((this_._addr + this_.reg_y) & 0xFF00)) {
+ this_.cycles++;
+ }
+ this_._addr = (this_._addr + this_.reg_y) & 0xFFFF;
this_.reg_pc = (this_.reg_pc + 2) & 0xFFFF;
- this_.reg_a ^= (this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]);
+ this_.reg_a ^= this_.readMem(this_._addr);
this_.flag_n = (this_.reg_a & 0x80) >> 7;
this_.flag_z = (this_.reg_a & 0xFF) ? 0 : 1;
this_.cycles += 4;
},
+ // 0x5A PHY
function op5A(this_) {
- this_.ram[this_.reg_sp] = this_.reg_y;
+ this_.writeMem(this_.reg_sp, this_.reg_y);
this_.reg_sp = --this_.reg_sp & 0xFF | 0x100;
this_.cycles += 3;
},
+ // 0x5B 未使用
function op5B(this_) {
this_.cycles += 1;
},
+ // 0x5C 未使用
function op5C(this_) {
this_.reg_pc = (this_.reg_pc + 2) & 0xFFFF;
this_.cycles += 8;
},
+ // 0x5D EOR abs,X
function op5D(this_) {
- this_._addr = ((((this_.reg_pc < 0xFFFF ? this_.memmap[(this_.reg_pc + 1) >> 13][(this_.reg_pc + 1) & 0x1FFF] : this_.ram[0]) << 8) | this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF]) + this_.reg_x) & 0xFFFF;
+ this_._addr = ((this_.readMem(this_.reg_pc + 1) << 8) | this_.readMem(this_.reg_pc)) + this_.reg_x;
this_.reg_pc = (this_.reg_pc + 2) & 0xFFFF;
- this_.reg_a ^= (this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]);
+ this_.reg_a ^= this_.readMem(this_._addr);
this_.flag_n = (this_.reg_a & 0x80) >> 7;
this_.flag_z = (this_.reg_a & 0xFF) ? 0 : 1;
this_.cycles += 4;
},
+ // 0x5E LSR abs,X
function op5E(this_) {
- this_._addr = ((((this_.reg_pc < 0xFFFF ? this_.memmap[(this_.reg_pc + 1) >> 13][(this_.reg_pc + 1) & 0x1FFF] : this_.ram[0]) << 8) | this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF]) + this_.reg_x) & 0xFFFF;
+ this_._addr = ((this_.readMem(this_.reg_pc + 1) << 8) | this_.readMem(this_.reg_pc)) + this_.reg_x;
this_.reg_pc = (this_.reg_pc + 2) & 0xFFFF;
- this_._tmp1 = (this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]);
+ this_._tmp1 = this_.readMem(this_._addr);
this_.flag_c = this_._tmp1 & 0x01;
- this_.flag_z = (this_._tmp1 ^ 0x01) ? 1 : 0;
- this_.flag_n = 0;
this_._tmp1 >>= 1;
- if (this_.io_write_map[this_._addr]) {
- this_.io_write(this_._addr, this_._tmp1);
- } else {
- this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF] = this_._tmp1;
- }
+ this_.writeMem(this_._addr, this_._tmp1);
+ this_.flag_n = 0;
+ this_.flag_z = (this_._tmp1 & 0xFF) ? 0 : 1;
this_.cycles += 6;
},
+ // 0x5F BBR5
function op5F(this_) {
- this_._addr = this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF];
- this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
- if (!((this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]) & 0x20)) {
+ this_._addr = this_.readMem(this_.reg_pc);
+ this_._tmp2 = this_.readMem(this_.reg_pc + 1);
+ this_.reg_pc = (this_.reg_pc + 2) & 0xFFFF;
+ if (!(this_.readMem(this_._addr) & 0x20)) {
this_.reg_pc = (this_.reg_pc + this_._tmp2) & 0xFFFF;
this_.cycles++;
}
this_.cycles += 5;
},
+ // 0x60 RTS
function op60(this_) {
- this_.reg_pc = this_.ram[this_.reg_sp = ++this_.reg_sp & 0xFF | 0x100];
- this_.reg_pc |= (this_.ram[this_.reg_sp = ++this_.reg_sp & 0xFF | 0x100] << 8);
+ this_.reg_sp = ++this_.reg_sp & 0xFF | 0x100;
+ this_.reg_pc = this_.readMem(this_.reg_sp);
+ this_.reg_sp = ++this_.reg_sp & 0xFF | 0x100;
+ this_.reg_pc |= (this_.readMem(this_.reg_sp) << 8);
this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
this_.cycles += 6;
},
+ // 0x61 ADC (indirect,X)
function op61(this_) {
- this_._tmp1 = (this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF] + this_.reg_x) & 0xFF;
- this_._addr = (((this_._tmp1 < 0xFFFF ? this_.memmap[(this_._tmp1 + 1) >> 13][(this_._tmp1 + 1) & 0x1FFF] : this_.ram[0]) << 8) | this_.memmap[this_._tmp1 >> 13][this_._tmp1 & 0x1FFF]);
+ this_._tmp1 = (this_.readMem(this_.reg_pc) + this_.reg_x) & 0xFF;
+ this_._addr = (this_.readMem((this_._tmp1 + 1) & 0xFF) << 8) | this_.readMem(this_._tmp1);
this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
- this_._tmp1 = (this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]);
+ this_._tmp1 = this_.readMem(this_._addr);
if (this_.flag_d) {
- this_._tmp2 = ((this_.reg_a >> 4) * 10 + (this_.reg_a & 0x0F)) + ((this_._tmp1 >> 4) * 10 + (this_._tmp1 & 0x0F)) + this_.flag_c;
- this_.flag_c = (this_._tmp2 > 99) ? 1 : 0;
- this_._tmp2 %= 100;
- this_.reg_a = ((((this_._tmp2 / 10) % 10) << 4) | (this_._tmp2 % 10));
+ var a_lo = this_.reg_a & 0x0F;
+ var a_hi = (this_.reg_a >> 4) & 0x0F;
+ var m_lo = this_._tmp1 & 0x0F;
+ var m_hi = (this_._tmp1 >> 4) & 0x0F;
+ var sum = a_lo + m_lo + this_.flag_c;
+ var carry = 0;
+ if (sum >= 10) {
+ sum -= 10;
+ carry = 1;
+ }
+ sum += a_hi * 10 + m_hi * 10 + carry * 10;
+ this_.flag_c = (sum >= 100) ? 1 : 0;
+ sum = sum % 100;
+ this_.reg_a = ((Math.floor(sum / 10) << 4) | (sum % 10));
this_.flag_n = (this_.reg_a & 0x80) >> 7;
this_.flag_z = (this_.reg_a & 0xFF) ? 0 : 1;
- this_.cycles++
+ this_.cycles++;
} else {
this_._tmp2 = this_.reg_a + this_._tmp1 + this_.flag_c;
this_.flag_c = (this_._tmp2 > 0xFF) ? 1 : 0;
@@ -882,35 +972,45 @@ M65C02Context.prototype.op_func_tbl = [
}
this_.cycles += 6;
},
+ // 0x62 未使用
function op62(this_) {
this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
this_.cycles += 2;
},
+ // 0x63 未使用
function op63(this_) {
this_.cycles += 1;
},
+ // 0x64 STZ zp
function op64(this_) {
- this_._addr = this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF];
+ this_._addr = this_.readMem(this_.reg_pc);
this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
- if (this_.io_write_map[this_._addr]) {
- this_.io_write(this_._addr, 0);
- } else {
- this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF] = 0;
- }
+ this_.writeMem(this_._addr, 0);
this_.cycles += 3;
},
+ // 0x65 ADC zp
function op65(this_) {
- this_._addr = this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF];
+ this_._addr = this_.readMem(this_.reg_pc);
this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
- this_._tmp1 = (this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]);
+ this_._tmp1 = this_.readMem(this_._addr);
if (this_.flag_d) {
- this_._tmp2 = ((this_.reg_a >> 4) * 10 + (this_.reg_a & 0x0F)) + ((this_._tmp1 >> 4) * 10 + (this_._tmp1 & 0x0F)) + this_.flag_c;
- this_.flag_c = (this_._tmp2 > 99) ? 1 : 0;
- this_._tmp2 %= 100;
- this_.reg_a = ((((this_._tmp2 / 10) % 10) << 4) | (this_._tmp2 % 10));
+ var a_lo = this_.reg_a & 0x0F;
+ var a_hi = (this_.reg_a >> 4) & 0x0F;
+ var m_lo = this_._tmp1 & 0x0F;
+ var m_hi = (this_._tmp1 >> 4) & 0x0F;
+ var sum = a_lo + m_lo + this_.flag_c;
+ var carry = 0;
+ if (sum >= 10) {
+ sum -= 10;
+ carry = 1;
+ }
+ sum += a_hi * 10 + m_hi * 10 + carry * 10;
+ this_.flag_c = (sum >= 100) ? 1 : 0;
+ sum = sum % 100;
+ this_.reg_a = ((Math.floor(sum / 10) << 4) | (sum % 10));
this_.flag_n = (this_.reg_a & 0x80) >> 7;
this_.flag_z = (this_.reg_a & 0xFF) ? 0 : 1;
- this_.cycles++
+ this_.cycles++;
} else {
this_._tmp2 = this_.reg_a + this_._tmp1 + this_.flag_c;
this_.flag_c = (this_._tmp2 > 0xFF) ? 1 : 0;
@@ -921,53 +1021,59 @@ M65C02Context.prototype.op_func_tbl = [
}
this_.cycles += 3;
},
+ // 0x66 ROR zp
function op66(this_) {
- this_._addr = this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF];
+ this_._addr = this_.readMem(this_.reg_pc);
this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
- this_._tmp1 = (this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]);
- this_.tmp2 = this_.flag_c << 7;
+ this_._tmp1 = this_.readMem(this_._addr);
+ this_._tmp2 = (this_.flag_c << 7) | (this_._tmp1 >> 1);
this_.flag_c = (this_._tmp1 & 0x01);
- this_._tmp2 = (this_._tmp1 >> 1) | this_.tmp2;
+ this_.writeMem(this_._addr, this_._tmp2);
this_.flag_n = (this_._tmp2 & 0x80) >> 7;
this_.flag_z = (this_._tmp2 & 0xFF) ? 0 : 1;
- if (this_.io_write_map[this_._addr]) {
- this_.io_write(this_._addr, this_._tmp2);
- } else {
- this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF] = this_._tmp2;
- }
this_.cycles += 5;
},
+ // 0x67 RMB6 zp
function op67(this_) {
- this_._addr = this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF];
+ this_._addr = this_.readMem(this_.reg_pc);
this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
- this_._tmp1 = (this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]) & 0xBF;
+ this_._tmp1 = this_.readMem(this_._addr) & 0xBF;
+ this_.writeMem(this_._addr, this_._tmp1);
this_.flag_n = (this_._tmp1 & 0x80) >> 7;
this_.flag_z = (this_._tmp1 & 0xFF) ? 0 : 1;
- if (this_.io_write_map[this_._addr]) {
- this_.io_write(this_._addr, this_._tmp1);
- } else {
- this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF] = this_._tmp1;
- }
this_.cycles += 5;
},
+ // 0x68 PLA
function op68(this_) {
- this_.reg_a = this_.ram[this_.reg_sp = ++this_.reg_sp & 0xFF | 0x100];
+ this_.reg_sp = ++this_.reg_sp & 0xFF | 0x100;
+ this_.reg_a = this_.readMem(this_.reg_sp);
this_.flag_n = (this_.reg_a & 0x80) >> 7;
this_.flag_z = (this_.reg_a & 0xFF) ? 0 : 1;
this_.cycles += 4;
},
+ // 0x69 ADC imm
function op69(this_) {
this_._addr = this_.reg_pc;
this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
- this_._tmp1 = (this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]);
+ this_._tmp1 = this_.readMem(this_._addr);
if (this_.flag_d) {
- this_._tmp2 = ((this_.reg_a >> 4) * 10 + (this_.reg_a & 0x0F)) + ((this_._tmp1 >> 4) * 10 + (this_._tmp1 & 0x0F)) + this_.flag_c;
- this_.flag_c = (this_._tmp2 > 99) ? 1 : 0;
- this_._tmp2 %= 100;
- this_.reg_a = ((((this_._tmp2 / 10) % 10) << 4) | (this_._tmp2 % 10));
+ var a_lo = this_.reg_a & 0x0F;
+ var a_hi = (this_.reg_a >> 4) & 0x0F;
+ var m_lo = this_._tmp1 & 0x0F;
+ var m_hi = (this_._tmp1 >> 4) & 0x0F;
+ var sum = a_lo + m_lo + this_.flag_c;
+ var carry = 0;
+ if (sum >= 10) {
+ sum -= 10;
+ carry = 1;
+ }
+ sum += a_hi * 10 + m_hi * 10 + carry * 10;
+ this_.flag_c = (sum >= 100) ? 1 : 0;
+ sum = sum % 100;
+ this_.reg_a = ((Math.floor(sum / 10) << 4) | (sum % 10));
this_.flag_n = (this_.reg_a & 0x80) >> 7;
this_.flag_z = (this_.reg_a & 0xFF) ? 0 : 1;
- this_.cycles++
+ this_.cycles++;
} else {
this_._tmp2 = this_.reg_a + this_._tmp1 + this_.flag_c;
this_.flag_c = (this_._tmp2 > 0xFF) ? 1 : 0;
@@ -978,36 +1084,51 @@ M65C02Context.prototype.op_func_tbl = [
}
this_.cycles += 2;
},
+ // 0x6A ROR A
function op6A(this_) {
- this_.tmp1 = this_.flag_c << 7;
+ this_._tmp1 = this_.flag_c << 7;
this_.flag_c = (this_.reg_a & 0x01);
- this_.reg_a = (this_.reg_a >> 1) | this_.tmp1;
+ this_.reg_a = (this_.reg_a >> 1) | this_._tmp1;
this_.flag_n = (this_.reg_a & 0x80) >> 7;
this_.flag_z = (this_.reg_a & 0xFF) ? 0 : 1;
this_.cycles += 2;
},
+ // 0x6B 未使用
function op6B(this_) {
this_.cycles += 1;
},
+ // 0x6C JMP indirect
function op6C(this_) {
- this_._tmp1 = (((this_.reg_pc < 0xFFFF ? this_.memmap[(this_.reg_pc + 1) >> 13][(this_.reg_pc + 1) & 0x1FFF] : this_.ram[0]) << 8) | this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF]);
- this_._addr = (((this_._tmp1 < 0xFFFF ? this_.memmap[(this_._tmp1 + 1) >> 13][(this_._tmp1 + 1) & 0x1FFF] : this_.ram[0]) << 8) | this_.memmap[this_._tmp1 >> 13][this_._tmp1 & 0x1FFF]);
+ this_._tmp1 = (this_.readMem(this_.reg_pc + 1) << 8) | this_.readMem(this_.reg_pc);
+ // 65C02 修正:间接跳转跨页时正确处理
+ this_._addr = (this_.readMem((this_._tmp1 + 1) & 0xFFFF) << 8) | this_.readMem(this_._tmp1);
this_.reg_pc = (this_.reg_pc + 2) & 0xFFFF;
this_.reg_pc = this_._addr;
this_.cycles += 6;
},
+ // 0x6D ADC abs
function op6D(this_) {
- this_._addr = (((this_.reg_pc < 0xFFFF ? this_.memmap[(this_.reg_pc + 1) >> 13][(this_.reg_pc + 1) & 0x1FFF] : this_.ram[0]) << 8) | this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF]);
+ this_._addr = (this_.readMem(this_.reg_pc + 1) << 8) | this_.readMem(this_.reg_pc);
this_.reg_pc = (this_.reg_pc + 2) & 0xFFFF;
- this_._tmp1 = (this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]);
+ this_._tmp1 = this_.readMem(this_._addr);
if (this_.flag_d) {
- this_._tmp2 = ((this_.reg_a >> 4) * 10 + (this_.reg_a & 0x0F)) + ((this_._tmp1 >> 4) * 10 + (this_._tmp1 & 0x0F)) + this_.flag_c;
- this_.flag_c = (this_._tmp2 > 99) ? 1 : 0;
- this_._tmp2 %= 100;
- this_.reg_a = ((((this_._tmp2 / 10) % 10) << 4) | (this_._tmp2 % 10));
+ var a_lo = this_.reg_a & 0x0F;
+ var a_hi = (this_.reg_a >> 4) & 0x0F;
+ var m_lo = this_._tmp1 & 0x0F;
+ var m_hi = (this_._tmp1 >> 4) & 0x0F;
+ var sum = a_lo + m_lo + this_.flag_c;
+ var carry = 0;
+ if (sum >= 10) {
+ sum -= 10;
+ carry = 1;
+ }
+ sum += a_hi * 10 + m_hi * 10 + carry * 10;
+ this_.flag_c = (sum >= 100) ? 1 : 0;
+ sum = sum % 100;
+ this_.reg_a = ((Math.floor(sum / 10) << 4) | (sum % 10));
this_.flag_n = (this_.reg_a & 0x80) >> 7;
this_.flag_z = (this_.reg_a & 0xFF) ? 0 : 1;
- this_.cycles++
+ this_.cycles++;
} else {
this_._tmp2 = this_.reg_a + this_._tmp1 + this_.flag_c;
this_.flag_c = (this_._tmp2 > 0xFF) ? 1 : 0;
@@ -1018,33 +1139,32 @@ M65C02Context.prototype.op_func_tbl = [
}
this_.cycles += 4;
},
+ // 0x6E ROR abs
function op6E(this_) {
- this_._addr = (((this_.reg_pc < 0xFFFF ? this_.memmap[(this_.reg_pc + 1) >> 13][(this_.reg_pc + 1) & 0x1FFF] : this_.ram[0]) << 8) | this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF]);
+ this_._addr = (this_.readMem(this_.reg_pc + 1) << 8) | this_.readMem(this_.reg_pc);
this_.reg_pc = (this_.reg_pc + 2) & 0xFFFF;
- this_._tmp1 = (this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]);
- this_.tmp2 = this_.flag_c << 7;
+ this_._tmp1 = this_.readMem(this_._addr);
+ this_._tmp2 = (this_.flag_c << 7) | (this_._tmp1 >> 1);
this_.flag_c = (this_._tmp1 & 0x01);
- this_._tmp2 = (this_._tmp1 >> 1) | this_.tmp2;
+ this_.writeMem(this_._addr, this_._tmp2);
this_.flag_n = (this_._tmp2 & 0x80) >> 7;
this_.flag_z = (this_._tmp2 & 0xFF) ? 0 : 1;
- if (this_.io_write_map[this_._addr]) {
- this_.io_write(this_._addr, this_._tmp2);
- } else {
- this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF] = this_._tmp2;
- }
this_.cycles += 6;
},
+ // 0x6F BBR6
function op6F(this_) {
- this_._addr = this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF];
- this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
- if (!((this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]) & 0x40)) {
+ this_._addr = this_.readMem(this_.reg_pc);
+ this_._tmp2 = this_.readMem(this_.reg_pc + 1);
+ this_.reg_pc = (this_.reg_pc + 2) & 0xFFFF;
+ if (!(this_.readMem(this_._addr) & 0x40)) {
this_.reg_pc = (this_.reg_pc + this_._tmp2) & 0xFFFF;
this_.cycles++;
}
this_.cycles += 5;
},
+ // 0x70 BVS
function op70(this_) {
- this_._tmp1 = this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF];
+ this_._tmp1 = this_.readMem(this_.reg_pc);
this_._tmp2 = this_._tmp1 - ((this_._tmp1 & 0x80) << 1);
this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
if (this_.flag_v) {
@@ -1053,19 +1173,34 @@ M65C02Context.prototype.op_func_tbl = [
}
this_.cycles += 2;
},
+ // 0x71 ADC (indirect),Y
function op71(this_) {
- this_._tmp1 = this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF];
- this_._addr = ((((this_._tmp1 < 0xFFFF ? this_.memmap[(this_._tmp1 + 1) >> 13][(this_._tmp1 + 1) & 0x1FFF] : this_.ram[0]) << 8) | this_.memmap[this_._tmp1 >> 13][this_._tmp1 & 0x1FFF]) + this_.reg_y) & 0xFFFF;
+ this_._tmp1 = this_.readMem(this_.reg_pc);
+ this_._addr = (this_.readMem((this_._tmp1 + 1) & 0xFF) << 8) | this_.readMem(this_._tmp1);
+ if ((this_._addr & 0xFF00) !== ((this_._addr + this_.reg_y) & 0xFF00)) {
+ this_.cycles++;
+ }
+ this_._addr = (this_._addr + this_.reg_y) & 0xFFFF;
this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
- this_._tmp1 = (this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]);
+ this_._tmp1 = this_.readMem(this_._addr);
if (this_.flag_d) {
- this_._tmp2 = ((this_.reg_a >> 4) * 10 + (this_.reg_a & 0x0F)) + ((this_._tmp1 >> 4) * 10 + (this_._tmp1 & 0x0F)) + this_.flag_c;
- this_.flag_c = (this_._tmp2 > 99) ? 1 : 0;
- this_._tmp2 %= 100;
- this_.reg_a = ((((this_._tmp2 / 10) % 10) << 4) | (this_._tmp2 % 10));
+ var a_lo = this_.reg_a & 0x0F;
+ var a_hi = (this_.reg_a >> 4) & 0x0F;
+ var m_lo = this_._tmp1 & 0x0F;
+ var m_hi = (this_._tmp1 >> 4) & 0x0F;
+ var sum = a_lo + m_lo + this_.flag_c;
+ var carry = 0;
+ if (sum >= 10) {
+ sum -= 10;
+ carry = 1;
+ }
+ sum += a_hi * 10 + m_hi * 10 + carry * 10;
+ this_.flag_c = (sum >= 100) ? 1 : 0;
+ sum = sum % 100;
+ this_.reg_a = ((Math.floor(sum / 10) << 4) | (sum % 10));
this_.flag_n = (this_.reg_a & 0x80) >> 7;
this_.flag_z = (this_.reg_a & 0xFF) ? 0 : 1;
- this_.cycles++
+ this_.cycles++;
} else {
this_._tmp2 = this_.reg_a + this_._tmp1 + this_.flag_c;
this_.flag_c = (this_._tmp2 > 0xFF) ? 1 : 0;
@@ -1076,19 +1211,30 @@ M65C02Context.prototype.op_func_tbl = [
}
this_.cycles += 5;
},
+ // 0x72 ADC (indirect)
function op72(this_) {
- this_._tmp1 = this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF];
- this_._addr = ((this_._tmp1 < 0xFF ? this_.ram[this_._tmp1 + 1] : this_.ram[0]) << 8) | this_.ram[this_._tmp1];
+ this_._tmp1 = this_.readMem(this_.reg_pc);
+ this_._addr = (this_.readMem((this_._tmp1 + 1) & 0xFF) << 8) | this_.readMem(this_._tmp1);
this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
- this_._tmp1 = (this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]);
+ this_._tmp1 = this_.readMem(this_._addr);
if (this_.flag_d) {
- this_._tmp2 = ((this_.reg_a >> 4) * 10 + (this_.reg_a & 0x0F)) + ((this_._tmp1 >> 4) * 10 + (this_._tmp1 & 0x0F)) + this_.flag_c;
- this_.flag_c = (this_._tmp2 > 99) ? 1 : 0;
- this_._tmp2 %= 100;
- this_.reg_a = ((((this_._tmp2 / 10) % 10) << 4) | (this_._tmp2 % 10));
+ var a_lo = this_.reg_a & 0x0F;
+ var a_hi = (this_.reg_a >> 4) & 0x0F;
+ var m_lo = this_._tmp1 & 0x0F;
+ var m_hi = (this_._tmp1 >> 4) & 0x0F;
+ var sum = a_lo + m_lo + this_.flag_c;
+ var carry = 0;
+ if (sum >= 10) {
+ sum -= 10;
+ carry = 1;
+ }
+ sum += a_hi * 10 + m_hi * 10 + carry * 10;
+ this_.flag_c = (sum >= 100) ? 1 : 0;
+ sum = sum % 100;
+ this_.reg_a = ((Math.floor(sum / 10) << 4) | (sum % 10));
this_.flag_n = (this_.reg_a & 0x80) >> 7;
this_.flag_z = (this_.reg_a & 0xFF) ? 0 : 1;
- this_.cycles++
+ this_.cycles++;
} else {
this_._tmp2 = this_.reg_a + this_._tmp1 + this_.flag_c;
this_.flag_c = (this_._tmp2 > 0xFF) ? 1 : 0;
@@ -1099,31 +1245,40 @@ M65C02Context.prototype.op_func_tbl = [
}
this_.cycles += 5;
},
+ // 0x73 未使用
function op73(this_) {
this_.cycles += 1;
},
+ // 0x74 STZ zp,X
function op74(this_) {
- this_._addr = (this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF] + this_.reg_x) & 0xFF;
+ this_._addr = (this_.readMem(this_.reg_pc) + this_.reg_x) & 0xFF;
this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
- if (this_.io_write_map[this_._addr]) {
- this_.io_write(this_._addr, 0);
- } else {
- this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF] = 0;
- }
+ this_.writeMem(this_._addr, 0);
this_.cycles += 4;
},
+ // 0x75 ADC zp,X
function op75(this_) {
- this_._addr = (this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF] + this_.reg_x) & 0xFF;
+ this_._addr = (this_.readMem(this_.reg_pc) + this_.reg_x) & 0xFF;
this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
- this_._tmp1 = (this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]);
+ this_._tmp1 = this_.readMem(this_._addr);
if (this_.flag_d) {
- this_._tmp2 = ((this_.reg_a >> 4) * 10 + (this_.reg_a & 0x0F)) + ((this_._tmp1 >> 4) * 10 + (this_._tmp1 & 0x0F)) + this_.flag_c;
- this_.flag_c = (this_._tmp2 > 99) ? 1 : 0;
- this_._tmp2 %= 100;
- this_.reg_a = ((((this_._tmp2 / 10) % 10) << 4) | (this_._tmp2 % 10));
+ var a_lo = this_.reg_a & 0x0F;
+ var a_hi = (this_.reg_a >> 4) & 0x0F;
+ var m_lo = this_._tmp1 & 0x0F;
+ var m_hi = (this_._tmp1 >> 4) & 0x0F;
+ var sum = a_lo + m_lo + this_.flag_c;
+ var carry = 0;
+ if (sum >= 10) {
+ sum -= 10;
+ carry = 1;
+ }
+ sum += a_hi * 10 + m_hi * 10 + carry * 10;
+ this_.flag_c = (sum >= 100) ? 1 : 0;
+ sum = sum % 100;
+ this_.reg_a = ((Math.floor(sum / 10) << 4) | (sum % 10));
this_.flag_n = (this_.reg_a & 0x80) >> 7;
this_.flag_z = (this_.reg_a & 0xFF) ? 0 : 1;
- this_.cycles++
+ this_.cycles++;
} else {
this_._tmp2 = this_.reg_a + this_._tmp1 + this_.flag_c;
this_.flag_c = (this_._tmp2 > 0xFF) ? 1 : 0;
@@ -1134,51 +1289,60 @@ M65C02Context.prototype.op_func_tbl = [
}
this_.cycles += 4;
},
+ // 0x76 ROR zp,X
function op76(this_) {
- this_._addr = (this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF] + this_.reg_x) & 0xFF;
+ this_._addr = (this_.readMem(this_.reg_pc) + this_.reg_x) & 0xFF;
this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
- this_._tmp1 = (this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]);
- this_.tmp2 = this_.flag_c << 7;
+ this_._tmp1 = this_.readMem(this_._addr);
+ this_._tmp2 = (this_.flag_c << 7) | (this_._tmp1 >> 1);
this_.flag_c = (this_._tmp1 & 0x01);
- this_._tmp2 = (this_._tmp1 >> 1) | this_.tmp2;
+ this_.writeMem(this_._addr, this_._tmp2);
this_.flag_n = (this_._tmp2 & 0x80) >> 7;
this_.flag_z = (this_._tmp2 & 0xFF) ? 0 : 1;
- if (this_.io_write_map[this_._addr]) {
- this_.io_write(this_._addr, this_._tmp2);
- } else {
- this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF] = this_._tmp2;
- }
this_.cycles += 6;
},
+ // 0x77 RMB7 zp
function op77(this_) {
- this_._addr = this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF];
+ this_._addr = this_.readMem(this_.reg_pc);
this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
- this_._tmp1 = (this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]) & 0x7F;
+ this_._tmp1 = this_.readMem(this_._addr) & 0x7F;
+ this_.writeMem(this_._addr, this_._tmp1);
this_.flag_n = (this_._tmp1 & 0x80) >> 7;
this_.flag_z = (this_._tmp1 & 0xFF) ? 0 : 1;
- if (this_.io_write_map[this_._addr]) {
- this_.io_write(this_._addr, this_._tmp1);
- } else {
- this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF] = this_._tmp1;
- }
this_.cycles += 5;
},
+ // 0x78 SEI
function op78(this_) {
this_.flag_i = 1;
this_.cycles += 2;
},
+ // 0x79 ADC abs,Y
function op79(this_) {
- this_._addr = ((((this_.reg_pc < 0xFFFF ? this_.memmap[(this_.reg_pc + 1) >> 13][(this_.reg_pc + 1) & 0x1FFF] : this_.ram[0]) << 8) | this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF]) + this_.reg_y) & 0xFFFF;
+ this_._addr = (this_.readMem(this_.reg_pc + 1) << 8) | this_.readMem(this_.reg_pc);
+ if ((this_._addr & 0xFF00) !== ((this_._addr + this_.reg_y) & 0xFF00)) {
+ this_.cycles++;
+ }
+ this_._addr = (this_._addr + this_.reg_y) & 0xFFFF;
this_.reg_pc = (this_.reg_pc + 2) & 0xFFFF;
- this_._tmp1 = (this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]);
+ this_._tmp1 = this_.readMem(this_._addr);
if (this_.flag_d) {
- this_._tmp2 = ((this_.reg_a >> 4) * 10 + (this_.reg_a & 0x0F)) + ((this_._tmp1 >> 4) * 10 + (this_._tmp1 & 0x0F)) + this_.flag_c;
- this_.flag_c = (this_._tmp2 > 99) ? 1 : 0;
- this_._tmp2 %= 100;
- this_.reg_a = ((((this_._tmp2 / 10) % 10) << 4) | (this_._tmp2 % 10));
+ var a_lo = this_.reg_a & 0x0F;
+ var a_hi = (this_.reg_a >> 4) & 0x0F;
+ var m_lo = this_._tmp1 & 0x0F;
+ var m_hi = (this_._tmp1 >> 4) & 0x0F;
+ var sum = a_lo + m_lo + this_.flag_c;
+ var carry = 0;
+ if (sum >= 10) {
+ sum -= 10;
+ carry = 1;
+ }
+ sum += a_hi * 10 + m_hi * 10 + carry * 10;
+ this_.flag_c = (sum >= 100) ? 1 : 0;
+ sum = sum % 100;
+ this_.reg_a = ((Math.floor(sum / 10) << 4) | (sum % 10));
this_.flag_n = (this_.reg_a & 0x80) >> 7;
this_.flag_z = (this_.reg_a & 0xFF) ? 0 : 1;
- this_.cycles++
+ this_.cycles++;
} else {
this_._tmp2 = this_.reg_a + this_._tmp1 + this_.flag_c;
this_.flag_c = (this_._tmp2 > 0xFF) ? 1 : 0;
@@ -1189,34 +1353,49 @@ M65C02Context.prototype.op_func_tbl = [
}
this_.cycles += 4;
},
+ // 0x7A PLY
function op7A(this_) {
- this_.reg_y = this_.ram[this_.reg_sp = ++this_.reg_sp & 0xFF | 0x100];
+ this_.reg_sp = ++this_.reg_sp & 0xFF | 0x100;
+ this_.reg_y = this_.readMem(this_.reg_sp);
this_.flag_n = (this_.reg_y & 0x80) >> 7;
this_.flag_z = (this_.reg_y & 0xFF) ? 0 : 1;
this_.cycles += 4;
},
+ // 0x7B 未使用
function op7B(this_) {
this_.cycles += 1;
},
+ // 0x7C JMP indirect,X
function op7C(this_) {
- this_._tmp1 = (((this_.reg_pc < 0xFFFF ? this_.memmap[(this_.reg_pc + 1) >> 13][(this_.reg_pc + 1) & 0x1FFF] : this_.ram[0]) << 8) | this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF]) + this_.reg_x;
- this_._addr = (((this_._tmp1 < 0xFFFF ? this_.memmap[(this_._tmp1 + 1) >> 13][(this_._tmp1 + 1) & 0x1FFF] : this_.ram[0]) << 8) | this_.memmap[this_._tmp1 >> 13][this_._tmp1 & 0x1FFF]);
+ this_._tmp1 = ((this_.readMem(this_.reg_pc + 1) << 8) | this_.readMem(this_.reg_pc)) + this_.reg_x;
+ this_._addr = (this_.readMem((this_._tmp1 + 1) & 0xFFFF) << 8) | this_.readMem(this_._tmp1);
this_.reg_pc = (this_.reg_pc + 2) & 0xFFFF;
this_.reg_pc = this_._addr;
this_.cycles += 6;
},
+ // 0x7D ADC abs,X
function op7D(this_) {
- this_._addr = ((((this_.reg_pc < 0xFFFF ? this_.memmap[(this_.reg_pc + 1) >> 13][(this_.reg_pc + 1) & 0x1FFF] : this_.ram[0]) << 8) | this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF]) + this_.reg_x) & 0xFFFF;
+ this_._addr = ((this_.readMem(this_.reg_pc + 1) << 8) | this_.readMem(this_.reg_pc)) + this_.reg_x;
this_.reg_pc = (this_.reg_pc + 2) & 0xFFFF;
- this_._tmp1 = (this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]);
+ this_._tmp1 = this_.readMem(this_._addr);
if (this_.flag_d) {
- this_._tmp2 = ((this_.reg_a >> 4) * 10 + (this_.reg_a & 0x0F)) + ((this_._tmp1 >> 4) * 10 + (this_._tmp1 & 0x0F)) + this_.flag_c;
- this_.flag_c = (this_._tmp2 > 99) ? 1 : 0;
- this_._tmp2 %= 100;
- this_.reg_a = ((((this_._tmp2 / 10) % 10) << 4) | (this_._tmp2 % 10));
+ var a_lo = this_.reg_a & 0x0F;
+ var a_hi = (this_.reg_a >> 4) & 0x0F;
+ var m_lo = this_._tmp1 & 0x0F;
+ var m_hi = (this_._tmp1 >> 4) & 0x0F;
+ var sum = a_lo + m_lo + this_.flag_c;
+ var carry = 0;
+ if (sum >= 10) {
+ sum -= 10;
+ carry = 1;
+ }
+ sum += a_hi * 10 + m_hi * 10 + carry * 10;
+ this_.flag_c = (sum >= 100) ? 1 : 0;
+ sum = sum % 100;
+ this_.reg_a = ((Math.floor(sum / 10) << 4) | (sum % 10));
this_.flag_n = (this_.reg_a & 0x80) >> 7;
this_.flag_z = (this_.reg_a & 0xFF) ? 0 : 1;
- this_.cycles++
+ this_.cycles++;
} else {
this_._tmp2 = this_.reg_a + this_._tmp1 + this_.flag_c;
this_.flag_c = (this_._tmp2 > 0xFF) ? 1 : 0;
@@ -1227,161 +1406,148 @@ M65C02Context.prototype.op_func_tbl = [
}
this_.cycles += 4;
},
+ // 0x7E ROR abs,X
function op7E(this_) {
- this_._addr = ((((this_.reg_pc < 0xFFFF ? this_.memmap[(this_.reg_pc + 1) >> 13][(this_.reg_pc + 1) & 0x1FFF] : this_.ram[0]) << 8) | this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF]) + this_.reg_x) & 0xFFFF;
+ this_._addr = ((this_.readMem(this_.reg_pc + 1) << 8) | this_.readMem(this_.reg_pc)) + this_.reg_x;
this_.reg_pc = (this_.reg_pc + 2) & 0xFFFF;
- this_._tmp1 = (this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]);
- this_.tmp2 = this_.flag_c << 7;
+ this_._tmp1 = this_.readMem(this_._addr);
+ this_._tmp2 = (this_.flag_c << 7) | (this_._tmp1 >> 1);
this_.flag_c = (this_._tmp1 & 0x01);
- this_._tmp2 = (this_._tmp1 >> 1) | this_.tmp2;
+ this_.writeMem(this_._addr, this_._tmp2);
this_.flag_n = (this_._tmp2 & 0x80) >> 7;
this_.flag_z = (this_._tmp2 & 0xFF) ? 0 : 1;
- if (this_.io_write_map[this_._addr]) {
- this_.io_write(this_._addr, this_._tmp2);
- } else {
- this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF] = this_._tmp2;
- }
this_.cycles += 6;
},
+ // 0x7F BBR7
function op7F(this_) {
- this_._addr = this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF];
- this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
- if (!((this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]) & 0x80)) {
+ this_._addr = this_.readMem(this_.reg_pc);
+ this_._tmp2 = this_.readMem(this_.reg_pc + 1);
+ this_.reg_pc = (this_.reg_pc + 2) & 0xFFFF;
+ if (!(this_.readMem(this_._addr) & 0x80)) {
this_.reg_pc = (this_.reg_pc + this_._tmp2) & 0xFFFF;
this_.cycles++;
}
this_.cycles += 5;
},
+ // 0x80 BRA
function op80(this_) {
- this_._tmp1 = this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF];
+ this_._tmp1 = this_.readMem(this_.reg_pc);
this_._tmp2 = this_._tmp1 - ((this_._tmp1 & 0x80) << 1);
this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
this_.reg_pc = (this_.reg_pc + this_._tmp2) & 0xFFFF;
this_.cycles += 3;
},
+ // 0x81 STA (indirect,X)
function op81(this_) {
- this_._tmp1 = (this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF] + this_.reg_x) & 0xFF;
- this_._addr = (((this_._tmp1 < 0xFFFF ? this_.memmap[(this_._tmp1 + 1) >> 13][(this_._tmp1 + 1) & 0x1FFF] : this_.ram[0]) << 8) | this_.memmap[this_._tmp1 >> 13][this_._tmp1 & 0x1FFF]);
+ this_._tmp1 = (this_.readMem(this_.reg_pc) + this_.reg_x) & 0xFF;
+ this_._addr = (this_.readMem((this_._tmp1 + 1) & 0xFF) << 8) | this_.readMem(this_._tmp1);
this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
- if (this_.io_write_map[this_._addr]) {
- this_.io_write(this_._addr, this_.reg_a);
- } else {
- this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF] = this_.reg_a;
- }
+ this_.writeMem(this_._addr, this_.reg_a);
this_.cycles += 6;
},
+ // 0x82 未使用
function op82(this_) {
this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
this_.cycles += 2;
},
+ // 0x83 未使用
function op83(this_) {
this_.cycles += 1;
},
+ // 0x84 STY zp
function op84(this_) {
- this_._addr = this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF];
+ this_._addr = this_.readMem(this_.reg_pc);
this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
- if (this_.io_write_map[this_._addr]) {
- this_.io_write(this_._addr, this_.reg_y);
- } else {
- this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF] = this_.reg_y;
- }
+ this_.writeMem(this_._addr, this_.reg_y);
this_.cycles += 3;
},
+ // 0x85 STA zp
function op85(this_) {
- this_._addr = this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF];
+ this_._addr = this_.readMem(this_.reg_pc);
this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
- if (this_.io_write_map[this_._addr]) {
- this_.io_write(this_._addr, this_.reg_a);
- } else {
- this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF] = this_.reg_a;
- }
+ this_.writeMem(this_._addr, this_.reg_a);
this_.cycles += 3;
},
+ // 0x86 STX zp
function op86(this_) {
- this_._addr = this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF];
+ this_._addr = this_.readMem(this_.reg_pc);
this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
- if (this_.io_write_map[this_._addr]) {
- this_.io_write(this_._addr, this_.reg_x);
- } else {
- this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF] = this_.reg_x;
- }
+ this_.writeMem(this_._addr, this_.reg_x);
this_.cycles += 3;
},
+ // 0x87 SMB0 zp
function op87(this_) {
- this_._addr = this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF];
+ this_._addr = this_.readMem(this_.reg_pc);
this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
- this_._tmp1 = (this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]) | 0x01;
+ this_._tmp1 = this_.readMem(this_._addr) | 0x01;
+ this_.writeMem(this_._addr, this_._tmp1);
this_.flag_n = (this_._tmp1 & 0x80) >> 7;
this_.flag_z = (this_._tmp1 & 0xFF) ? 0 : 1;
- if (this_.io_write_map[this_._addr]) {
- this_.io_write(this_._addr, this_._tmp1);
- } else {
- this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF] = this_._tmp1;
- }
this_.cycles += 5;
},
+ // 0x88 DEY
function op88(this_) {
this_.reg_y = (--this_.reg_y & 0xFF);
this_.flag_n = (this_.reg_y & 0x80) >> 7;
this_.flag_z = (this_.reg_y & 0xFF) ? 0 : 1;
this_.cycles += 2;
},
+ // 0x89 BIT imm
function op89(this_) {
this_._addr = this_.reg_pc;
this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
- this_.flag_z = !(this_.reg_a & (this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF])) | 0;
+ this_._tmp1 = this_.readMem(this_._addr);
+ this_.flag_z = !(this_.reg_a & this_._tmp1) | 0;
+ this_.flag_n = (this_._tmp1 & 0x80) >> 7;
+ this_.flag_v = (this_._tmp1 & 0x40) >> 6;
this_.cycles += 2;
},
+ // 0x8A TXA
function op8A(this_) {
this_.reg_a = this_.reg_x;
this_.flag_n = (this_.reg_a & 0x80) >> 7;
this_.flag_z = (this_.reg_a & 0xFF) ? 0 : 1;
this_.cycles += 2;
},
+ // 0x8B 未使用
function op8B(this_) {
this_.cycles += 1;
},
+ // 0x8C STY abs
function op8C(this_) {
- this_._addr = (((this_.reg_pc < 0xFFFF ? this_.memmap[(this_.reg_pc + 1) >> 13][(this_.reg_pc + 1) & 0x1FFF] : this_.ram[0]) << 8) | this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF]);
+ this_._addr = (this_.readMem(this_.reg_pc + 1) << 8) | this_.readMem(this_.reg_pc);
this_.reg_pc = (this_.reg_pc + 2) & 0xFFFF;
- if (this_.io_write_map[this_._addr]) {
- this_.io_write(this_._addr, this_.reg_y);
- } else {
- this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF] = this_.reg_y;
- }
+ this_.writeMem(this_._addr, this_.reg_y);
this_.cycles += 4;
},
+ // 0x8D STA abs
function op8D(this_) {
- this_._addr = (((this_.reg_pc < 0xFFFF ? this_.memmap[(this_.reg_pc + 1) >> 13][(this_.reg_pc + 1) & 0x1FFF] : this_.ram[0]) << 8) | this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF]);
+ this_._addr = (this_.readMem(this_.reg_pc + 1) << 8) | this_.readMem(this_.reg_pc);
this_.reg_pc = (this_.reg_pc + 2) & 0xFFFF;
- if (this_.io_write_map[this_._addr]) {
- this_.io_write(this_._addr, this_.reg_a);
- } else {
- this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF] = this_.reg_a;
- }
+ this_.writeMem(this_._addr, this_.reg_a);
this_.cycles += 4;
},
+ // 0x8E STX abs
function op8E(this_) {
- this_._addr = (((this_.reg_pc < 0xFFFF ? this_.memmap[(this_.reg_pc + 1) >> 13][(this_.reg_pc + 1) & 0x1FFF] : this_.ram[0]) << 8) | this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF]);
+ this_._addr = (this_.readMem(this_.reg_pc + 1) << 8) | this_.readMem(this_.reg_pc);
this_.reg_pc = (this_.reg_pc + 2) & 0xFFFF;
- if (this_.io_write_map[this_._addr]) {
- this_.io_write(this_._addr, this_.reg_x);
- } else {
- this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF] = this_.reg_x;
- }
+ this_.writeMem(this_._addr, this_.reg_x);
this_.cycles += 4;
},
+ // 0x8F SMB1 zp
function op8F(this_) {
- this_._addr = this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF];
- this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
- if ((this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]) & 0x01) {
+ this_._addr = this_.readMem(this_.reg_pc);
+ this_._tmp2 = this_.readMem(this_.reg_pc + 1);
+ this_.reg_pc = (this_.reg_pc + 2) & 0xFFFF;
+ if (this_.readMem(this_._addr) & 0x01) {
this_.reg_pc = (this_.reg_pc + this_._tmp2) & 0xFFFF;
this_.cycles++;
}
this_.cycles += 5;
},
+ // 0x90 BCC
function op90(this_) {
- this_._tmp1 = this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF];
+ this_._tmp1 = this_.readMem(this_.reg_pc);
this_._tmp2 = this_._tmp1 - ((this_._tmp1 & 0x80) << 1);
this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
if (!this_.flag_c) {
@@ -1390,259 +1556,250 @@ M65C02Context.prototype.op_func_tbl = [
}
this_.cycles += 2;
},
+ // 0x91 STA (indirect),Y
function op91(this_) {
- this_._tmp1 = this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF];
- this_._addr = ((((this_._tmp1 < 0xFFFF ? this_.memmap[(this_._tmp1 + 1) >> 13][(this_._tmp1 + 1) & 0x1FFF] : this_.ram[0]) << 8) | this_.memmap[this_._tmp1 >> 13][this_._tmp1 & 0x1FFF]) + this_.reg_y) & 0xFFFF;
+ this_._tmp1 = this_.readMem(this_.reg_pc);
+ this_._addr = (this_.readMem((this_._tmp1 + 1) & 0xFF) << 8) | this_.readMem(this_._tmp1);
+ this_._addr = (this_._addr + this_.reg_y) & 0xFFFF;
this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
- if (this_.io_write_map[this_._addr]) {
- this_.io_write(this_._addr, this_.reg_a);
- } else {
- this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF] = this_.reg_a;
- }
+ this_.writeMem(this_._addr, this_.reg_a);
this_.cycles += 6;
},
+ // 0x92 STA (indirect)
function op92(this_) {
- this_._tmp1 = this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF];
- this_._addr = ((this_._tmp1 < 0xFF ? this_.ram[this_._tmp1 + 1] : this_.ram[0]) << 8) | this_.ram[this_._tmp1];
+ this_._tmp1 = this_.readMem(this_.reg_pc);
+ this_._addr = (this_.readMem((this_._tmp1 + 1) & 0xFF) << 8) | this_.readMem(this_._tmp1);
this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
- if (this_.io_write_map[this_._addr]) {
- this_.io_write(this_._addr, this_.reg_a);
- } else {
- this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF] = this_.reg_a;
- }
+ this_.writeMem(this_._addr, this_.reg_a);
this_.cycles += 5;
},
+ // 0x93 未使用
function op93(this_) {
this_.cycles += 1;
},
+ // 0x94 STY zp,X
function op94(this_) {
- this_._addr = (this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF] + this_.reg_x) & 0xFF;
+ this_._addr = (this_.readMem(this_.reg_pc) + this_.reg_x) & 0xFF;
this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
- if (this_.io_write_map[this_._addr]) {
- this_.io_write(this_._addr, this_.reg_y);
- } else {
- this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF] = this_.reg_y;
- }
+ this_.writeMem(this_._addr, this_.reg_y);
this_.cycles += 4;
},
+ // 0x95 STA zp,X
function op95(this_) {
- this_._addr = (this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF] + this_.reg_x) & 0xFF;
+ this_._addr = (this_.readMem(this_.reg_pc) + this_.reg_x) & 0xFF;
this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
- if (this_.io_write_map[this_._addr]) {
- this_.io_write(this_._addr, this_.reg_a);
- } else {
- this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF] = this_.reg_a;
- }
+ this_.writeMem(this_._addr, this_.reg_a);
this_.cycles += 4;
},
+ // 0x96 STX zp,Y
function op96(this_) {
- this_._addr = (this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF] + this_.reg_y) & 0xFF;
+ this_._addr = (this_.readMem(this_.reg_pc) + this_.reg_y) & 0xFF;
this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
- if (this_.io_write_map[this_._addr]) {
- this_.io_write(this_._addr, this_.reg_x);
- } else {
- this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF] = this_.reg_x;
- }
+ this_.writeMem(this_._addr, this_.reg_x);
this_.cycles += 4;
},
+ // 0x97 SMB2 zp
function op97(this_) {
- this_._addr = this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF];
+ this_._addr = this_.readMem(this_.reg_pc);
this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
- this_._tmp1 = (this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]) | 0x02;
+ this_._tmp1 = this_.readMem(this_._addr) | 0x02;
+ this_.writeMem(this_._addr, this_._tmp1);
this_.flag_n = (this_._tmp1 & 0x80) >> 7;
this_.flag_z = (this_._tmp1 & 0xFF) ? 0 : 1;
- if (this_.io_write_map[this_._addr]) {
- this_.io_write(this_._addr, this_._tmp1);
- } else {
- this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF] = this_._tmp1;
- }
this_.cycles += 5;
},
+ // 0x98 TYA
function op98(this_) {
this_.reg_a = this_.reg_y;
this_.flag_n = (this_.reg_a & 0x80) >> 7;
this_.flag_z = (this_.reg_a & 0xFF) ? 0 : 1;
this_.cycles += 2;
},
+ // 0x99 STA abs,Y
function op99(this_) {
- this_._addr = ((((this_.reg_pc < 0xFFFF ? this_.memmap[(this_.reg_pc + 1) >> 13][(this_.reg_pc + 1) & 0x1FFF] : this_.ram[0]) << 8) | this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF]) + this_.reg_y) & 0xFFFF;
+ this_._addr = ((this_.readMem(this_.reg_pc + 1) << 8) | this_.readMem(this_.reg_pc)) + this_.reg_y;
this_.reg_pc = (this_.reg_pc + 2) & 0xFFFF;
- if (this_.io_write_map[this_._addr]) {
- this_.io_write(this_._addr, this_.reg_a);
- } else {
- this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF] = this_.reg_a;
- }
+ this_.writeMem(this_._addr, this_.reg_a);
this_.cycles += 5;
},
+ // 0x9A TXS
function op9A(this_) {
this_.reg_sp = (this_.reg_x | 0x100);
this_.cycles += 2;
},
+ // 0x9B 未使用
function op9B(this_) {
this_.cycles += 1;
},
+ // 0x9C STZ abs
function op9C(this_) {
- this_._addr = (((this_.reg_pc < 0xFFFF ? this_.memmap[(this_.reg_pc + 1) >> 13][(this_.reg_pc + 1) & 0x1FFF] : this_.ram[0]) << 8) | this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF]);
+ this_._addr = (this_.readMem(this_.reg_pc + 1) << 8) | this_.readMem(this_.reg_pc);
this_.reg_pc = (this_.reg_pc + 2) & 0xFFFF;
- if (this_.io_write_map[this_._addr]) {
- this_.io_write(this_._addr, 0);
- } else {
- this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF] = 0;
- }
+ this_.writeMem(this_._addr, 0);
this_.cycles += 4;
},
+ // 0x9D STA abs,X
function op9D(this_) {
- this_._addr = ((((this_.reg_pc < 0xFFFF ? this_.memmap[(this_.reg_pc + 1) >> 13][(this_.reg_pc + 1) & 0x1FFF] : this_.ram[0]) << 8) | this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF]) + this_.reg_x) & 0xFFFF;
+ this_._addr = ((this_.readMem(this_.reg_pc + 1) << 8) | this_.readMem(this_.reg_pc)) + this_.reg_x;
this_.reg_pc = (this_.reg_pc + 2) & 0xFFFF;
- if (this_.io_write_map[this_._addr]) {
- this_.io_write(this_._addr, this_.reg_a);
- } else {
- this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF] = this_.reg_a;
- }
+ this_.writeMem(this_._addr, this_.reg_a);
this_.cycles += 5;
},
+ // 0x9E STZ abs,X
function op9E(this_) {
- this_._addr = ((((this_.reg_pc < 0xFFFF ? this_.memmap[(this_.reg_pc + 1) >> 13][(this_.reg_pc + 1) & 0x1FFF] : this_.ram[0]) << 8) | this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF]) + this_.reg_x) & 0xFFFF;
+ this_._addr = ((this_.readMem(this_.reg_pc + 1) << 8) | this_.readMem(this_.reg_pc)) + this_.reg_x;
this_.reg_pc = (this_.reg_pc + 2) & 0xFFFF;
- if (this_.io_write_map[this_._addr]) {
- this_.io_write(this_._addr, 0);
- } else {
- this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF] = 0;
- }
+ this_.writeMem(this_._addr, 0);
this_.cycles += 5;
},
+ // 0x9F SMB3 zp
function op9F(this_) {
- this_._addr = this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF];
- this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
- if ((this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]) & 0x02) {
+ this_._addr = this_.readMem(this_.reg_pc);
+ this_._tmp2 = this_.readMem(this_.reg_pc + 1);
+ this_.reg_pc = (this_.reg_pc + 2) & 0xFFFF;
+ if (this_.readMem(this_._addr) & 0x02) {
this_.reg_pc = (this_.reg_pc + this_._tmp2) & 0xFFFF;
this_.cycles++;
}
this_.cycles += 5;
},
+ // 0xA0 LDY imm
function opA0(this_) {
this_._addr = this_.reg_pc;
this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
- this_.reg_y = (this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]);
+ this_.reg_y = this_.readMem(this_._addr);
this_.flag_n = (this_.reg_y & 0x80) >> 7;
this_.flag_z = (this_.reg_y & 0xFF) ? 0 : 1;
this_.cycles += 2;
},
+ // 0xA1 LDA (indirect,X)
function opA1(this_) {
- this_._tmp1 = (this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF] + this_.reg_x) & 0xFF;
- this_._addr = (((this_._tmp1 < 0xFFFF ? this_.memmap[(this_._tmp1 + 1) >> 13][(this_._tmp1 + 1) & 0x1FFF] : this_.ram[0]) << 8) | this_.memmap[this_._tmp1 >> 13][this_._tmp1 & 0x1FFF]);
+ this_._tmp1 = (this_.readMem(this_.reg_pc) + this_.reg_x) & 0xFF;
+ this_._addr = (this_.readMem((this_._tmp1 + 1) & 0xFF) << 8) | this_.readMem(this_._tmp1);
this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
- this_.reg_a = (this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]);
+ this_.reg_a = this_.readMem(this_._addr);
this_.flag_n = (this_.reg_a & 0x80) >> 7;
this_.flag_z = (this_.reg_a & 0xFF) ? 0 : 1;
this_.cycles += 6;
},
+ // 0xA2 LDX imm
function opA2(this_) {
this_._addr = this_.reg_pc;
this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
- this_.reg_x = (this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]);
+ this_.reg_x = this_.readMem(this_._addr);
this_.flag_n = (this_.reg_x & 0x80) >> 7;
this_.flag_z = (this_.reg_x & 0xFF) ? 0 : 1;
this_.cycles += 2;
},
+ // 0xA3 未使用
function opA3(this_) {
this_.cycles += 1;
},
+ // 0xA4 LDY zp
function opA4(this_) {
- this_._addr = this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF];
+ this_._addr = this_.readMem(this_.reg_pc);
this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
- this_.reg_y = (this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]);
+ this_.reg_y = this_.readMem(this_._addr);
this_.flag_n = (this_.reg_y & 0x80) >> 7;
this_.flag_z = (this_.reg_y & 0xFF) ? 0 : 1;
this_.cycles += 3;
},
+ // 0xA5 LDA zp
function opA5(this_) {
- this_._addr = this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF];
+ this_._addr = this_.readMem(this_.reg_pc);
this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
- this_.reg_a = (this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]);
+ this_.reg_a = this_.readMem(this_._addr);
this_.flag_n = (this_.reg_a & 0x80) >> 7;
this_.flag_z = (this_.reg_a & 0xFF) ? 0 : 1;
this_.cycles += 3;
},
+ // 0xA6 LDX zp
function opA6(this_) {
- this_._addr = this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF];
+ this_._addr = this_.readMem(this_.reg_pc);
this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
- this_.reg_x = (this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]);
+ this_.reg_x = this_.readMem(this_._addr);
this_.flag_n = (this_.reg_x & 0x80) >> 7;
this_.flag_z = (this_.reg_x & 0xFF) ? 0 : 1;
this_.cycles += 3;
},
+ // 0xA7 SMB4 zp
function opA7(this_) {
- this_._addr = this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF];
+ this_._addr = this_.readMem(this_.reg_pc);
this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
- this_._tmp1 = (this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]) | 0x04;
+ this_._tmp1 = this_.readMem(this_._addr) | 0x04;
+ this_.writeMem(this_._addr, this_._tmp1);
this_.flag_n = (this_._tmp1 & 0x80) >> 7;
this_.flag_z = (this_._tmp1 & 0xFF) ? 0 : 1;
- if (this_.io_write_map[this_._addr]) {
- this_.io_write(this_._addr, this_._tmp1);
- } else {
- this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF] = this_._tmp1;
- }
this_.cycles += 5;
},
+ // 0xA8 TAY
function opA8(this_) {
this_.reg_y = this_.reg_a;
this_.flag_n = (this_.reg_y & 0x80) >> 7;
this_.flag_z = (this_.reg_y & 0xFF) ? 0 : 1;
this_.cycles += 2;
},
+ // 0xA9 LDA imm
function opA9(this_) {
this_._addr = this_.reg_pc;
this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
- this_.reg_a = (this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]);
+ this_.reg_a = this_.readMem(this_._addr);
this_.flag_n = (this_.reg_a & 0x80) >> 7;
this_.flag_z = (this_.reg_a & 0xFF) ? 0 : 1;
this_.cycles += 2;
},
+ // 0xAA TAX
function opAA(this_) {
this_.reg_x = this_.reg_a;
this_.flag_n = (this_.reg_x & 0x80) >> 7;
this_.flag_z = (this_.reg_x & 0xFF) ? 0 : 1;
this_.cycles += 2;
},
+ // 0xAB 未使用
function opAB(this_) {
this_.cycles += 1;
},
+ // 0xAC LDY abs
function opAC(this_) {
- this_._addr = (((this_.reg_pc < 0xFFFF ? this_.memmap[(this_.reg_pc + 1) >> 13][(this_.reg_pc + 1) & 0x1FFF] : this_.ram[0]) << 8) | this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF]);
+ this_._addr = (this_.readMem(this_.reg_pc + 1) << 8) | this_.readMem(this_.reg_pc);
this_.reg_pc = (this_.reg_pc + 2) & 0xFFFF;
- this_.reg_y = (this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]);
+ this_.reg_y = this_.readMem(this_._addr);
this_.flag_n = (this_.reg_y & 0x80) >> 7;
this_.flag_z = (this_.reg_y & 0xFF) ? 0 : 1;
this_.cycles += 4;
},
+ // 0xAD LDA abs
function opAD(this_) {
- this_._addr = (((this_.reg_pc < 0xFFFF ? this_.memmap[(this_.reg_pc + 1) >> 13][(this_.reg_pc + 1) & 0x1FFF] : this_.ram[0]) << 8) | this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF]);
+ this_._addr = (this_.readMem(this_.reg_pc + 1) << 8) | this_.readMem(this_.reg_pc);
this_.reg_pc = (this_.reg_pc + 2) & 0xFFFF;
- this_.reg_a = (this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]);
+ this_.reg_a = this_.readMem(this_._addr);
this_.flag_n = (this_.reg_a & 0x80) >> 7;
this_.flag_z = (this_.reg_a & 0xFF) ? 0 : 1;
this_.cycles += 4;
},
+ // 0xAE LDX abs
function opAE(this_) {
- this_._addr = (((this_.reg_pc < 0xFFFF ? this_.memmap[(this_.reg_pc + 1) >> 13][(this_.reg_pc + 1) & 0x1FFF] : this_.ram[0]) << 8) | this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF]);
+ this_._addr = (this_.readMem(this_.reg_pc + 1) << 8) | this_.readMem(this_.reg_pc);
this_.reg_pc = (this_.reg_pc + 2) & 0xFFFF;
- this_.reg_x = (this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]);
+ this_.reg_x = this_.readMem(this_._addr);
this_.flag_n = (this_.reg_x & 0x80) >> 7;
this_.flag_z = (this_.reg_x & 0xFF) ? 0 : 1;
this_.cycles += 4;
},
+ // 0xAF SMB5 zp
function opAF(this_) {
- this_._addr = this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF];
- this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
- if ((this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]) & 0x04) {
+ this_._addr = this_.readMem(this_.reg_pc);
+ this_._tmp2 = this_.readMem(this_.reg_pc + 1);
+ this_.reg_pc = (this_.reg_pc + 2) & 0xFFFF;
+ if (this_.readMem(this_._addr) & 0x04) {
this_.reg_pc = (this_.reg_pc + this_._tmp2) & 0xFFFF;
this_.cycles++;
}
this_.cycles += 5;
},
+ // 0xB0 BCS
function opB0(this_) {
- this_._tmp1 = this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF];
+ this_._tmp1 = this_.readMem(this_.reg_pc);
this_._tmp2 = this_._tmp1 - ((this_._tmp1 & 0x80) << 1);
this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
if (this_.flag_c) {
@@ -1651,256 +1808,282 @@ M65C02Context.prototype.op_func_tbl = [
}
this_.cycles += 2;
},
+ // 0xB1 LDA (indirect),Y
function opB1(this_) {
- this_._tmp1 = this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF];
- this_._addr = ((((this_._tmp1 < 0xFFFF ? this_.memmap[(this_._tmp1 + 1) >> 13][(this_._tmp1 + 1) & 0x1FFF] : this_.ram[0]) << 8) | this_.memmap[this_._tmp1 >> 13][this_._tmp1 & 0x1FFF]) + this_.reg_y) & 0xFFFF;
+ this_._tmp1 = this_.readMem(this_.reg_pc);
+ this_._addr = (this_.readMem((this_._tmp1 + 1) & 0xFF) << 8) | this_.readMem(this_._tmp1);
+ if ((this_._addr & 0xFF00) !== ((this_._addr + this_.reg_y) & 0xFF00)) {
+ this_.cycles++;
+ }
+ this_._addr = (this_._addr + this_.reg_y) & 0xFFFF;
this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
- this_.reg_a = (this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]);
+ this_.reg_a = this_.readMem(this_._addr);
this_.flag_n = (this_.reg_a & 0x80) >> 7;
this_.flag_z = (this_.reg_a & 0xFF) ? 0 : 1;
this_.cycles += 5;
},
+ // 0xB2 LDA (indirect)
function opB2(this_) {
- this_._tmp1 = this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF];
- this_._addr = ((this_._tmp1 < 0xFF ? this_.ram[this_._tmp1 + 1] : this_.ram[0]) << 8) | this_.ram[this_._tmp1];
+ this_._tmp1 = this_.readMem(this_.reg_pc);
+ this_._addr = (this_.readMem((this_._tmp1 + 1) & 0xFF) << 8) | this_.readMem(this_._tmp1);
this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
- this_.reg_a = (this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]);
+ this_.reg_a = this_.readMem(this_._addr);
this_.flag_n = (this_.reg_a & 0x80) >> 7;
this_.flag_z = (this_.reg_a & 0xFF) ? 0 : 1;
this_.cycles += 5;
},
+ // 0xB3 未使用
function opB3(this_) {
this_.cycles += 1;
},
+ // 0xB4 LDY zp,X
function opB4(this_) {
- this_._addr = (this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF] + this_.reg_x) & 0xFF;
+ this_._addr = (this_.readMem(this_.reg_pc) + this_.reg_x) & 0xFF;
this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
- this_.reg_y = (this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]);
+ this_.reg_y = this_.readMem(this_._addr);
this_.flag_n = (this_.reg_y & 0x80) >> 7;
this_.flag_z = (this_.reg_y & 0xFF) ? 0 : 1;
this_.cycles += 4;
},
+ // 0xB5 LDA zp,X
function opB5(this_) {
- this_._addr = (this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF] + this_.reg_x) & 0xFF;
+ this_._addr = (this_.readMem(this_.reg_pc) + this_.reg_x) & 0xFF;
this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
- this_.reg_a = (this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]);
+ this_.reg_a = this_.readMem(this_._addr);
this_.flag_n = (this_.reg_a & 0x80) >> 7;
this_.flag_z = (this_.reg_a & 0xFF) ? 0 : 1;
this_.cycles += 4;
},
+ // 0xB6 LDX zp,Y
function opB6(this_) {
- this_._addr = (this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF] + this_.reg_y) & 0xFF;
+ this_._addr = (this_.readMem(this_.reg_pc) + this_.reg_y) & 0xFF;
this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
- this_.reg_x = (this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]);
+ this_.reg_x = this_.readMem(this_._addr);
this_.flag_n = (this_.reg_x & 0x80) >> 7;
this_.flag_z = (this_.reg_x & 0xFF) ? 0 : 1;
this_.cycles += 4;
},
+ // 0xB7 SMB6 zp
function opB7(this_) {
- this_._addr = this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF];
+ this_._addr = this_.readMem(this_.reg_pc);
this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
- this_._tmp1 = (this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]) | 0x08;
+ this_._tmp1 = this_.readMem(this_._addr) | 0x08;
+ this_.writeMem(this_._addr, this_._tmp1);
this_.flag_n = (this_._tmp1 & 0x80) >> 7;
this_.flag_z = (this_._tmp1 & 0xFF) ? 0 : 1;
- if (this_.io_write_map[this_._addr]) {
- this_.io_write(this_._addr, this_._tmp1);
- } else {
- this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF] = this_._tmp1;
- }
this_.cycles += 5;
},
+ // 0xB8 CLV
function opB8(this_) {
this_.flag_v = 0;
this_.cycles += 2;
},
+ // 0xB9 LDA abs,Y
function opB9(this_) {
- this_._addr = ((((this_.reg_pc < 0xFFFF ? this_.memmap[(this_.reg_pc + 1) >> 13][(this_.reg_pc + 1) & 0x1FFF] : this_.ram[0]) << 8) | this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF]) + this_.reg_y) & 0xFFFF;
+ this_._addr = (this_.readMem(this_.reg_pc + 1) << 8) | this_.readMem(this_.reg_pc);
+ if ((this_._addr & 0xFF00) !== ((this_._addr + this_.reg_y) & 0xFF00)) {
+ this_.cycles++;
+ }
+ this_._addr = (this_._addr + this_.reg_y) & 0xFFFF;
this_.reg_pc = (this_.reg_pc + 2) & 0xFFFF;
- this_.reg_a = (this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]);
+ this_.reg_a = this_.readMem(this_._addr);
this_.flag_n = (this_.reg_a & 0x80) >> 7;
this_.flag_z = (this_.reg_a & 0xFF) ? 0 : 1;
this_.cycles += 4;
},
+ // 0xBA TSX
function opBA(this_) {
this_.reg_x = (this_.reg_sp & 0xFF);
this_.flag_n = (this_.reg_x & 0x80) >> 7;
this_.flag_z = (this_.reg_x & 0xFF) ? 0 : 1;
this_.cycles += 2;
},
+ // 0xBB 未使用
function opBB(this_) {
this_.cycles += 1;
},
+ // 0xBC LDY abs,X
function opBC(this_) {
- this_._addr = ((((this_.reg_pc < 0xFFFF ? this_.memmap[(this_.reg_pc + 1) >> 13][(this_.reg_pc + 1) & 0x1FFF] : this_.ram[0]) << 8) | this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF]) + this_.reg_x) & 0xFFFF;
+ this_._addr = ((this_.readMem(this_.reg_pc + 1) << 8) | this_.readMem(this_.reg_pc)) + this_.reg_x;
this_.reg_pc = (this_.reg_pc + 2) & 0xFFFF;
- this_.reg_y = (this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]);
+ this_.reg_y = this_.readMem(this_._addr);
this_.flag_n = (this_.reg_y & 0x80) >> 7;
this_.flag_z = (this_.reg_y & 0xFF) ? 0 : 1;
this_.cycles += 4;
},
+ // 0xBD LDA abs,X
function opBD(this_) {
- this_._addr = ((((this_.reg_pc < 0xFFFF ? this_.memmap[(this_.reg_pc + 1) >> 13][(this_.reg_pc + 1) & 0x1FFF] : this_.ram[0]) << 8) | this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF]) + this_.reg_x) & 0xFFFF;
+ this_._addr = ((this_.readMem(this_.reg_pc + 1) << 8) | this_.readMem(this_.reg_pc)) + this_.reg_x;
this_.reg_pc = (this_.reg_pc + 2) & 0xFFFF;
- this_.reg_a = (this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]);
+ this_.reg_a = this_.readMem(this_._addr);
this_.flag_n = (this_.reg_a & 0x80) >> 7;
this_.flag_z = (this_.reg_a & 0xFF) ? 0 : 1;
this_.cycles += 4;
},
+ // 0xBE LDX abs,Y
function opBE(this_) {
- this_._addr = ((((this_.reg_pc < 0xFFFF ? this_.memmap[(this_.reg_pc + 1) >> 13][(this_.reg_pc + 1) & 0x1FFF] : this_.ram[0]) << 8) | this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF]) + this_.reg_y) & 0xFFFF;
+ this_._addr = ((this_.readMem(this_.reg_pc + 1) << 8) | this_.readMem(this_.reg_pc)) + this_.reg_y;
this_.reg_pc = (this_.reg_pc + 2) & 0xFFFF;
- this_.reg_x = (this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]);
+ this_.reg_x = this_.readMem(this_._addr);
this_.flag_n = (this_.reg_x & 0x80) >> 7;
this_.flag_z = (this_.reg_x & 0xFF) ? 0 : 1;
this_.cycles += 4;
},
+ // 0xBF SMB7 zp
function opBF(this_) {
- this_._addr = this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF];
- this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
- if ((this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]) & 0x08) {
+ this_._addr = this_.readMem(this_.reg_pc);
+ this_._tmp2 = this_.readMem(this_.reg_pc + 1);
+ this_.reg_pc = (this_.reg_pc + 2) & 0xFFFF;
+ if (this_.readMem(this_._addr) & 0x08) {
this_.reg_pc = (this_.reg_pc + this_._tmp2) & 0xFFFF;
this_.cycles++;
}
this_.cycles += 5;
},
+ // 0xC0 CPY imm
function opC0(this_) {
this_._addr = this_.reg_pc;
this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
- this_._tmp1 = this_.reg_y - (this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]);
- this_.flag_c = this_._tmp1 < 0 ? 0 : 1;
+ this_._tmp1 = this_.reg_y - this_.readMem(this_._addr);
+ this_.flag_c = (this_._tmp1 >= 0) ? 1 : 0;
this_.flag_n = (this_._tmp1 & 0x80) >> 7;
this_.flag_z = (this_._tmp1 & 0xFF) ? 0 : 1;
this_.cycles += 2;
},
+ // 0xC1 CMP (indirect,X)
function opC1(this_) {
- this_._tmp1 = (this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF] + this_.reg_x) & 0xFF;
- this_._addr = (((this_._tmp1 < 0xFFFF ? this_.memmap[(this_._tmp1 + 1) >> 13][(this_._tmp1 + 1) & 0x1FFF] : this_.ram[0]) << 8) | this_.memmap[this_._tmp1 >> 13][this_._tmp1 & 0x1FFF]);
+ this_._tmp1 = (this_.readMem(this_.reg_pc) + this_.reg_x) & 0xFF;
+ this_._addr = (this_.readMem((this_._tmp1 + 1) & 0xFF) << 8) | this_.readMem(this_._tmp1);
this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
- this_._tmp1 = this_.reg_a - (this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]);
- this_.flag_c = this_._tmp1 < 0 ? 0 : 1;
+ this_._tmp1 = this_.reg_a - this_.readMem(this_._addr);
+ this_.flag_c = (this_._tmp1 >= 0) ? 1 : 0;
this_.flag_n = (this_._tmp1 & 0x80) >> 7;
this_.flag_z = (this_._tmp1 & 0xFF) ? 0 : 1;
this_.cycles += 6;
},
+ // 0xC2 未使用
function opC2(this_) {
this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
this_.cycles += 2;
},
+ // 0xC3 未使用
function opC3(this_) {
this_.cycles += 1;
},
+ // 0xC4 CPY zp
function opC4(this_) {
- this_._addr = this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF];
+ this_._addr = this_.readMem(this_.reg_pc);
this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
- this_._tmp1 = this_.reg_y - (this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]);
- this_.flag_c = this_._tmp1 < 0 ? 0 : 1;
+ this_._tmp1 = this_.reg_y - this_.readMem(this_._addr);
+ this_.flag_c = (this_._tmp1 >= 0) ? 1 : 0;
this_.flag_n = (this_._tmp1 & 0x80) >> 7;
this_.flag_z = (this_._tmp1 & 0xFF) ? 0 : 1;
this_.cycles += 3;
},
+ // 0xC5 CMP zp
function opC5(this_) {
- this_._addr = this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF];
+ this_._addr = this_.readMem(this_.reg_pc);
this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
- this_._tmp1 = this_.reg_a - (this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]);
- this_.flag_c = this_._tmp1 < 0 ? 0 : 1;
+ this_._tmp1 = this_.reg_a - this_.readMem(this_._addr);
+ this_.flag_c = (this_._tmp1 >= 0) ? 1 : 0;
this_.flag_n = (this_._tmp1 & 0x80) >> 7;
this_.flag_z = (this_._tmp1 & 0xFF) ? 0 : 1;
this_.cycles += 3;
},
+ // 0xC6 DEC zp
function opC6(this_) {
- this_._addr = this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF];
+ this_._addr = this_.readMem(this_.reg_pc);
this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
- this_._tmp1 = ((this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]) - 1) & 0xFF;
+ this_._tmp1 = (this_.readMem(this_._addr) - 1) & 0xFF;
+ this_.writeMem(this_._addr, this_._tmp1);
this_.flag_n = (this_._tmp1 & 0x80) >> 7;
this_.flag_z = (this_._tmp1 & 0xFF) ? 0 : 1;
- if (this_.io_write_map[this_._addr]) {
- this_.io_write(this_._addr, this_._tmp1);
- } else {
- this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF] = this_._tmp1;
- }
this_.cycles += 5;
},
+ // 0xC7 SMB0 (BBR0?) - 实际是 SMB0
function opC7(this_) {
- this_._addr = this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF];
+ this_._addr = this_.readMem(this_.reg_pc);
this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
- this_._tmp1 = (this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]) | 0x10;
+ this_._tmp1 = this_.readMem(this_._addr) | 0x10;
+ this_.writeMem(this_._addr, this_._tmp1);
this_.flag_n = (this_._tmp1 & 0x80) >> 7;
this_.flag_z = (this_._tmp1 & 0xFF) ? 0 : 1;
- if (this_.io_write_map[this_._addr]) {
- this_.io_write(this_._addr, this_._tmp1);
- } else {
- this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF] = this_._tmp1;
- }
this_.cycles += 5;
},
+ // 0xC8 INY
function opC8(this_) {
this_.reg_y = (++this_.reg_y & 0xFF);
this_.flag_n = (this_.reg_y & 0x80) >> 7;
this_.flag_z = (this_.reg_y & 0xFF) ? 0 : 1;
this_.cycles += 2;
},
+ // 0xC9 CMP imm
function opC9(this_) {
this_._addr = this_.reg_pc;
this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
- this_._tmp1 = this_.reg_a - (this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]);
- this_.flag_c = this_._tmp1 < 0 ? 0 : 1;
+ this_._tmp1 = this_.reg_a - this_.readMem(this_._addr);
+ this_.flag_c = (this_._tmp1 >= 0) ? 1 : 0;
this_.flag_n = (this_._tmp1 & 0x80) >> 7;
this_.flag_z = (this_._tmp1 & 0xFF) ? 0 : 1;
this_.cycles += 2;
},
+ // 0xCA DEX
function opCA(this_) {
this_.reg_x = (--this_.reg_x & 0xFF);
this_.flag_n = (this_.reg_x & 0x80) >> 7;
this_.flag_z = (this_.reg_x & 0xFF) ? 0 : 1;
this_.cycles += 2;
},
+ // 0xCB WAI
function opCB(this_) {
this_.reg_pc = (this_.reg_pc - 1) & 0xFFFF;
this_.wai = 1;
this_.cycles += 3;
},
+ // 0xCC CPY abs
function opCC(this_) {
- this_._addr = (((this_.reg_pc < 0xFFFF ? this_.memmap[(this_.reg_pc + 1) >> 13][(this_.reg_pc + 1) & 0x1FFF] : this_.ram[0]) << 8) | this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF]);
+ this_._addr = (this_.readMem(this_.reg_pc + 1) << 8) | this_.readMem(this_.reg_pc);
this_.reg_pc = (this_.reg_pc + 2) & 0xFFFF;
- this_._tmp1 = this_.reg_y - (this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]);
- this_.flag_c = this_._tmp1 < 0 ? 0 : 1;
+ this_._tmp1 = this_.reg_y - this_.readMem(this_._addr);
+ this_.flag_c = (this_._tmp1 >= 0) ? 1 : 0;
this_.flag_n = (this_._tmp1 & 0x80) >> 7;
this_.flag_z = (this_._tmp1 & 0xFF) ? 0 : 1;
this_.cycles += 4;
},
+ // 0xCD CMP abs
function opCD(this_) {
- this_._addr = (((this_.reg_pc < 0xFFFF ? this_.memmap[(this_.reg_pc + 1) >> 13][(this_.reg_pc + 1) & 0x1FFF] : this_.ram[0]) << 8) | this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF]);
+ this_._addr = (this_.readMem(this_.reg_pc + 1) << 8) | this_.readMem(this_.reg_pc);
this_.reg_pc = (this_.reg_pc + 2) & 0xFFFF;
- this_._tmp1 = this_.reg_a - (this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]);
- this_.flag_c = this_._tmp1 < 0 ? 0 : 1;
+ this_._tmp1 = this_.reg_a - this_.readMem(this_._addr);
+ this_.flag_c = (this_._tmp1 >= 0) ? 1 : 0;
this_.flag_n = (this_._tmp1 & 0x80) >> 7;
this_.flag_z = (this_._tmp1 & 0xFF) ? 0 : 1;
this_.cycles += 4;
},
+ // 0xCE DEC abs
function opCE(this_) {
- this_._addr = (((this_.reg_pc < 0xFFFF ? this_.memmap[(this_.reg_pc + 1) >> 13][(this_.reg_pc + 1) & 0x1FFF] : this_.ram[0]) << 8) | this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF]);
+ this_._addr = (this_.readMem(this_.reg_pc + 1) << 8) | this_.readMem(this_.reg_pc);
this_.reg_pc = (this_.reg_pc + 2) & 0xFFFF;
- this_._tmp1 = ((this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]) - 1) & 0xFF;
+ this_._tmp1 = (this_.readMem(this_._addr) - 1) & 0xFF;
+ this_.writeMem(this_._addr, this_._tmp1);
this_.flag_n = (this_._tmp1 & 0x80) >> 7;
this_.flag_z = (this_._tmp1 & 0xFF) ? 0 : 1;
- if (this_.io_write_map[this_._addr]) {
- this_.io_write(this_._addr, this_._tmp1);
- } else {
- this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF] = this_._tmp1;
- }
this_.cycles += 6;
},
+ // 0xCF SMB1 (BBR1?) - 实际是 SMB1
function opCF(this_) {
- this_._addr = this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF];
- this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
- if ((this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]) & 0x10) {
+ this_._addr = this_.readMem(this_.reg_pc);
+ this_._tmp2 = this_.readMem(this_.reg_pc + 1);
+ this_.reg_pc = (this_.reg_pc + 2) & 0xFFFF;
+ if (this_.readMem(this_._addr) & 0x10) {
this_.reg_pc = (this_.reg_pc + this_._tmp2) & 0xFFFF;
this_.cycles++;
}
this_.cycles += 5;
},
+ // 0xD0 BNE
function opD0(this_) {
- this_._tmp1 = this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF];
+ this_._tmp1 = this_.readMem(this_.reg_pc);
this_._tmp2 = this_._tmp1 - ((this_._tmp1 & 0x80) << 1);
this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
if (!this_.flag_z) {
@@ -1909,154 +2092,168 @@ M65C02Context.prototype.op_func_tbl = [
}
this_.cycles += 2;
},
+ // 0xD1 CMP (indirect),Y
function opD1(this_) {
- this_._tmp1 = this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF];
- this_._addr = ((((this_._tmp1 < 0xFFFF ? this_.memmap[(this_._tmp1 + 1) >> 13][(this_._tmp1 + 1) & 0x1FFF] : this_.ram[0]) << 8) | this_.memmap[this_._tmp1 >> 13][this_._tmp1 & 0x1FFF]) + this_.reg_y) & 0xFFFF;
+ this_._tmp1 = this_.readMem(this_.reg_pc);
+ this_._addr = (this_.readMem((this_._tmp1 + 1) & 0xFF) << 8) | this_.readMem(this_._tmp1);
+ if ((this_._addr & 0xFF00) !== ((this_._addr + this_.reg_y) & 0xFF00)) {
+ this_.cycles++;
+ }
+ this_._addr = (this_._addr + this_.reg_y) & 0xFFFF;
this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
- this_._tmp1 = this_.reg_a - (this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]);
- this_.flag_c = this_._tmp1 < 0 ? 0 : 1;
+ this_._tmp1 = this_.reg_a - this_.readMem(this_._addr);
+ this_.flag_c = (this_._tmp1 >= 0) ? 1 : 0;
this_.flag_n = (this_._tmp1 & 0x80) >> 7;
this_.flag_z = (this_._tmp1 & 0xFF) ? 0 : 1;
this_.cycles += 5;
},
+ // 0xD2 CMP (indirect)
function opD2(this_) {
- this_._tmp1 = this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF];
- this_._addr = ((this_._tmp1 < 0xFF ? this_.ram[this_._tmp1 + 1] : this_.ram[0]) << 8) | this_.ram[this_._tmp1];
+ this_._tmp1 = this_.readMem(this_.reg_pc);
+ this_._addr = (this_.readMem((this_._tmp1 + 1) & 0xFF) << 8) | this_.readMem(this_._tmp1);
this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
- this_._tmp1 = this_.reg_a - (this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]);
- this_.flag_c = this_._tmp1 < 0 ? 0 : 1;
+ this_._tmp1 = this_.reg_a - this_.readMem(this_._addr);
+ this_.flag_c = (this_._tmp1 >= 0) ? 1 : 0;
this_.flag_n = (this_._tmp1 & 0x80) >> 7;
this_.flag_z = (this_._tmp1 & 0xFF) ? 0 : 1;
this_.cycles += 5;
},
+ // 0xD3 未使用
function opD3(this_) {
this_.cycles += 1;
},
+ // 0xD4 未使用
function opD4(this_) {
this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
this_.cycles += 4;
},
+ // 0xD5 CMP zp,X
function opD5(this_) {
- this_._addr = (this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF] + this_.reg_x) & 0xFF;
+ this_._addr = (this_.readMem(this_.reg_pc) + this_.reg_x) & 0xFF;
this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
- this_._tmp1 = this_.reg_a - (this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]);
- this_.flag_c = this_._tmp1 < 0 ? 0 : 1;
+ this_._tmp1 = this_.reg_a - this_.readMem(this_._addr);
+ this_.flag_c = (this_._tmp1 >= 0) ? 1 : 0;
this_.flag_n = (this_._tmp1 & 0x80) >> 7;
this_.flag_z = (this_._tmp1 & 0xFF) ? 0 : 1;
this_.cycles += 4;
},
+ // 0xD6 DEC zp,X
function opD6(this_) {
- this_._addr = (this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF] + this_.reg_x) & 0xFF;
+ this_._addr = (this_.readMem(this_.reg_pc) + this_.reg_x) & 0xFF;
this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
- this_._tmp1 = ((this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]) - 1) & 0xFF;
+ this_._tmp1 = (this_.readMem(this_._addr) - 1) & 0xFF;
+ this_.writeMem(this_._addr, this_._tmp1);
this_.flag_n = (this_._tmp1 & 0x80) >> 7;
this_.flag_z = (this_._tmp1 & 0xFF) ? 0 : 1;
- if (this_.io_write_map[this_._addr]) {
- this_.io_write(this_._addr, this_._tmp1);
- } else {
- this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF] = this_._tmp1;
- }
this_.cycles += 6;
},
+ // 0xD7 SMB2 zp
function opD7(this_) {
- this_._addr = this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF];
+ this_._addr = this_.readMem(this_.reg_pc);
this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
- this_._tmp1 = (this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]) | 0x20;
+ this_._tmp1 = this_.readMem(this_._addr) | 0x20;
+ this_.writeMem(this_._addr, this_._tmp1);
this_.flag_n = (this_._tmp1 & 0x80) >> 7;
this_.flag_z = (this_._tmp1 & 0xFF) ? 0 : 1;
- if (this_.io_write_map[this_._addr]) {
- this_.io_write(this_._addr, this_._tmp1);
- } else {
- this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF] = this_._tmp1;
- }
this_.cycles += 5;
},
+ // 0xD8 CLD
function opD8(this_) {
this_.flag_d = 0;
this_.cycles += 2;
},
+ // 0xD9 CMP abs,Y
function opD9(this_) {
- this_._addr = ((((this_.reg_pc < 0xFFFF ? this_.memmap[(this_.reg_pc + 1) >> 13][(this_.reg_pc + 1) & 0x1FFF] : this_.ram[0]) << 8) | this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF]) + this_.reg_y) & 0xFFFF;
+ this_._addr = (this_.readMem(this_.reg_pc + 1) << 8) | this_.readMem(this_.reg_pc);
+ if ((this_._addr & 0xFF00) !== ((this_._addr + this_.reg_y) & 0xFF00)) {
+ this_.cycles++;
+ }
+ this_._addr = (this_._addr + this_.reg_y) & 0xFFFF;
this_.reg_pc = (this_.reg_pc + 2) & 0xFFFF;
- this_._tmp1 = this_.reg_a - (this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]);
- this_.flag_c = this_._tmp1 < 0 ? 0 : 1;
+ this_._tmp1 = this_.reg_a - this_.readMem(this_._addr);
+ this_.flag_c = (this_._tmp1 >= 0) ? 1 : 0;
this_.flag_n = (this_._tmp1 & 0x80) >> 7;
this_.flag_z = (this_._tmp1 & 0xFF) ? 0 : 1;
this_.cycles += 4;
},
+ // 0xDA PHX
function opDA(this_) {
- this_.ram[this_.reg_sp] = this_.reg_x;
+ this_.writeMem(this_.reg_sp, this_.reg_x);
this_.reg_sp = --this_.reg_sp & 0xFF | 0x100;
this_.cycles += 3;
},
+ // 0xDB STP
function opDB(this_) {
this_.reg_pc = (this_.reg_pc - 1) & 0xFFFF;
this_.stp = 1;
this_.cycles += 3;
},
+ // 0xDC 未使用
function opDC(this_) {
this_.reg_pc = (this_.reg_pc + 2) & 0xFFFF;
this_.cycles += 4;
},
+ // 0xDD CMP abs,X
function opDD(this_) {
- this_._addr = ((((this_.reg_pc < 0xFFFF ? this_.memmap[(this_.reg_pc + 1) >> 13][(this_.reg_pc + 1) & 0x1FFF] : this_.ram[0]) << 8) | this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF]) + this_.reg_x) & 0xFFFF;
+ this_._addr = ((this_.readMem(this_.reg_pc + 1) << 8) | this_.readMem(this_.reg_pc)) + this_.reg_x;
this_.reg_pc = (this_.reg_pc + 2) & 0xFFFF;
- this_._tmp1 = this_.reg_a - (this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]);
- this_.flag_c = this_._tmp1 < 0 ? 0 : 1;
+ this_._tmp1 = this_.reg_a - this_.readMem(this_._addr);
+ this_.flag_c = (this_._tmp1 >= 0) ? 1 : 0;
this_.flag_n = (this_._tmp1 & 0x80) >> 7;
this_.flag_z = (this_._tmp1 & 0xFF) ? 0 : 1;
this_.cycles += 4;
},
+ // 0xDE DEC abs,X
function opDE(this_) {
- this_._addr = ((((this_.reg_pc < 0xFFFF ? this_.memmap[(this_.reg_pc + 1) >> 13][(this_.reg_pc + 1) & 0x1FFF] : this_.ram[0]) << 8) | this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF]) + this_.reg_x) & 0xFFFF;
+ this_._addr = ((this_.readMem(this_.reg_pc + 1) << 8) | this_.readMem(this_.reg_pc)) + this_.reg_x;
this_.reg_pc = (this_.reg_pc + 2) & 0xFFFF;
- this_._tmp1 = ((this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]) - 1) & 0xFF;
+ this_._tmp1 = (this_.readMem(this_._addr) - 1) & 0xFF;
+ this_.writeMem(this_._addr, this_._tmp1);
this_.flag_n = (this_._tmp1 & 0x80) >> 7;
this_.flag_z = (this_._tmp1 & 0xFF) ? 0 : 1;
- if (this_.io_write_map[this_._addr]) {
- this_.io_write(this_._addr, this_._tmp1);
- } else {
- this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF] = this_._tmp1;
- }
this_.cycles += 6;
},
+ // 0xDF SMB3 zp
function opDF(this_) {
- this_._addr = this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF];
- this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
- if ((this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]) & 0x20) {
+ this_._addr = this_.readMem(this_.reg_pc);
+ this_._tmp2 = this_.readMem(this_.reg_pc + 1);
+ this_.reg_pc = (this_.reg_pc + 2) & 0xFFFF;
+ if (this_.readMem(this_._addr) & 0x20) {
this_.reg_pc = (this_.reg_pc + this_._tmp2) & 0xFFFF;
this_.cycles++;
}
this_.cycles += 5;
},
+ // 0xE0 CPX imm
function opE0(this_) {
this_._addr = this_.reg_pc;
this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
- this_._tmp1 = this_.reg_x - (this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]);
- this_.flag_c = this_._tmp1 < 0 ? 0 : 1;
+ this_._tmp1 = this_.reg_x - this_.readMem(this_._addr);
+ this_.flag_c = (this_._tmp1 >= 0) ? 1 : 0;
this_.flag_n = (this_._tmp1 & 0x80) >> 7;
this_.flag_z = (this_._tmp1 & 0xFF) ? 0 : 1;
this_.cycles += 2;
},
+ // 0xE1 SBC (indirect,X)
function opE1(this_) {
- this_._tmp1 = (this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF] + this_.reg_x) & 0xFF;
- this_._addr = (((this_._tmp1 < 0xFFFF ? this_.memmap[(this_._tmp1 + 1) >> 13][(this_._tmp1 + 1) & 0x1FFF] : this_.ram[0]) << 8) | this_.memmap[this_._tmp1 >> 13][this_._tmp1 & 0x1FFF]);
+ this_._tmp1 = (this_.readMem(this_.reg_pc) + this_.reg_x) & 0xFF;
+ this_._addr = (this_.readMem((this_._tmp1 + 1) & 0xFF) << 8) | this_.readMem(this_._tmp1);
this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
- this_._tmp1 = (this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]);
+ this_._tmp1 = this_.readMem(this_._addr);
if (this_.flag_d) {
- this_._tmp2 = ((this_.reg_a >> 4) * 10 + (this_.reg_a & 0x0F)) - ((this_._tmp1 >> 4) * 10 + (this_._tmp1 & 0x0F)) - 1 + this_.flag_c;
- this_.flag_c = (this_._tmp2 < 0) ? 0 : 1;
- this_._tmp2 %= 100;
- if (this_._tmp2 < 0) {
- this_._tmp2 += 100;
- }
- this_.reg_a = ((((this_._tmp2 / 10) % 10) << 4) | (this_._tmp2 % 10));
+ var a_val = (this_.reg_a >> 4) * 10 + (this_.reg_a & 0x0F);
+ var m_val = (this_._tmp1 >> 4) * 10 + (this_._tmp1 & 0x0F);
+ var result = a_val - m_val - 1 + this_.flag_c;
+ this_.flag_c = (result >= 0) ? 1 : 0;
+ if (result < 0) result += 100;
+ result = result % 100;
+ this_.reg_a = ((Math.floor(result / 10) << 4) | (result % 10));
this_.flag_n = (this_.reg_a & 0x80) >> 7;
this_.flag_z = (this_.reg_a & 0xFF) ? 0 : 1;
- this_.cycles++
+ this_.cycles++;
} else {
this_._tmp2 = this_.reg_a - this_._tmp1 - 1 + this_.flag_c;
- this_.flag_c = (this_._tmp2 < 0) ? 0 : 1;
+ this_.flag_c = (this_._tmp2 >= 0) ? 1 : 0;
this_.flag_v = ((this_.reg_a ^ this_._tmp1) & (this_.reg_a ^ this_._tmp2) & 0x80) >> 7;
this_.reg_a = (this_._tmp2 & 0xFF);
this_.flag_n = (this_.reg_a & 0x80) >> 7;
@@ -2064,40 +2261,44 @@ M65C02Context.prototype.op_func_tbl = [
}
this_.cycles += 6;
},
+ // 0xE2 未使用
function opE2(this_) {
this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
this_.cycles += 2;
},
+ // 0xE3 未使用
function opE3(this_) {
this_.cycles += 1;
},
+ // 0xE4 CPX zp
function opE4(this_) {
- this_._addr = this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF];
+ this_._addr = this_.readMem(this_.reg_pc);
this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
- this_._tmp1 = this_.reg_x - (this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]);
- this_.flag_c = this_._tmp1 < 0 ? 0 : 1;
+ this_._tmp1 = this_.reg_x - this_.readMem(this_._addr);
+ this_.flag_c = (this_._tmp1 >= 0) ? 1 : 0;
this_.flag_n = (this_._tmp1 & 0x80) >> 7;
this_.flag_z = (this_._tmp1 & 0xFF) ? 0 : 1;
this_.cycles += 3;
},
+ // 0xE5 SBC zp
function opE5(this_) {
- this_._addr = this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF];
+ this_._addr = this_.readMem(this_.reg_pc);
this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
- this_._tmp1 = (this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]);
+ this_._tmp1 = this_.readMem(this_._addr);
if (this_.flag_d) {
- this_._tmp2 = ((this_.reg_a >> 4) * 10 + (this_.reg_a & 0x0F)) - ((this_._tmp1 >> 4) * 10 + (this_._tmp1 & 0x0F)) - 1 + this_.flag_c;
- this_.flag_c = (this_._tmp2 < 0) ? 0 : 1;
- this_._tmp2 %= 100;
- if (this_._tmp2 < 0) {
- this_._tmp2 += 100;
- }
- this_.reg_a = ((((this_._tmp2 / 10) % 10) << 4) | (this_._tmp2 % 10));
+ var a_val = (this_.reg_a >> 4) * 10 + (this_.reg_a & 0x0F);
+ var m_val = (this_._tmp1 >> 4) * 10 + (this_._tmp1 & 0x0F);
+ var result = a_val - m_val - 1 + this_.flag_c;
+ this_.flag_c = (result >= 0) ? 1 : 0;
+ if (result < 0) result += 100;
+ result = result % 100;
+ this_.reg_a = ((Math.floor(result / 10) << 4) | (result % 10));
this_.flag_n = (this_.reg_a & 0x80) >> 7;
this_.flag_z = (this_.reg_a & 0xFF) ? 0 : 1;
- this_.cycles++
+ this_.cycles++;
} else {
this_._tmp2 = this_.reg_a - this_._tmp1 - 1 + this_.flag_c;
- this_.flag_c = (this_._tmp2 < 0) ? 0 : 1;
+ this_.flag_c = (this_._tmp2 >= 0) ? 1 : 0;
this_.flag_v = ((this_.reg_a ^ this_._tmp1) & (this_.reg_a ^ this_._tmp2) & 0x80) >> 7;
this_.reg_a = (this_._tmp2 & 0xFF);
this_.flag_n = (this_.reg_a & 0x80) >> 7;
@@ -2105,56 +2306,52 @@ M65C02Context.prototype.op_func_tbl = [
}
this_.cycles += 3;
},
+ // 0xE6 INC zp
function opE6(this_) {
- this_._addr = this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF];
+ this_._addr = this_.readMem(this_.reg_pc);
this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
- this_._tmp1 = ((this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]) + 1) & 0xFF;
+ this_._tmp1 = (this_.readMem(this_._addr) + 1) & 0xFF;
+ this_.writeMem(this_._addr, this_._tmp1);
this_.flag_n = (this_._tmp1 & 0x80) >> 7;
this_.flag_z = (this_._tmp1 & 0xFF) ? 0 : 1;
- if (this_.io_write_map[this_._addr]) {
- this_.io_write(this_._addr, this_._tmp1);
- } else {
- this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF] = this_._tmp1;
- }
this_.cycles += 5;
},
+ // 0xE7 SMB4 zp
function opE7(this_) {
- this_._addr = this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF];
+ this_._addr = this_.readMem(this_.reg_pc);
this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
- this_._tmp1 = (this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]) | 0x40;
+ this_._tmp1 = this_.readMem(this_._addr) | 0x40;
+ this_.writeMem(this_._addr, this_._tmp1);
this_.flag_n = (this_._tmp1 & 0x80) >> 7;
this_.flag_z = (this_._tmp1 & 0xFF) ? 0 : 1;
- if (this_.io_write_map[this_._addr]) {
- this_.io_write(this_._addr, this_._tmp1);
- } else {
- this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF] = this_._tmp1;
- }
this_.cycles += 5;
},
+ // 0xE8 INX
function opE8(this_) {
this_.reg_x = (++this_.reg_x & 0xFF);
this_.flag_n = (this_.reg_x & 0x80) >> 7;
this_.flag_z = (this_.reg_x & 0xFF) ? 0 : 1;
this_.cycles += 2;
},
+ // 0xE9 SBC imm
function opE9(this_) {
this_._addr = this_.reg_pc;
this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
- this_._tmp1 = (this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]);
+ this_._tmp1 = this_.readMem(this_._addr);
if (this_.flag_d) {
- this_._tmp2 = ((this_.reg_a >> 4) * 10 + (this_.reg_a & 0x0F)) - ((this_._tmp1 >> 4) * 10 + (this_._tmp1 & 0x0F)) - 1 + this_.flag_c;
- this_.flag_c = (this_._tmp2 < 0) ? 0 : 1;
- this_._tmp2 %= 100;
- if (this_._tmp2 < 0) {
- this_._tmp2 += 100;
- }
- this_.reg_a = ((((this_._tmp2 / 10) % 10) << 4) | (this_._tmp2 % 10));
+ var a_val = (this_.reg_a >> 4) * 10 + (this_.reg_a & 0x0F);
+ var m_val = (this_._tmp1 >> 4) * 10 + (this_._tmp1 & 0x0F);
+ var result = a_val - m_val - 1 + this_.flag_c;
+ this_.flag_c = (result >= 0) ? 1 : 0;
+ if (result < 0) result += 100;
+ result = result % 100;
+ this_.reg_a = ((Math.floor(result / 10) << 4) | (result % 10));
this_.flag_n = (this_.reg_a & 0x80) >> 7;
this_.flag_z = (this_.reg_a & 0xFF) ? 0 : 1;
- this_.cycles++
+ this_.cycles++;
} else {
this_._tmp2 = this_.reg_a - this_._tmp1 - 1 + this_.flag_c;
- this_.flag_c = (this_._tmp2 < 0) ? 0 : 1;
+ this_.flag_c = (this_._tmp2 >= 0) ? 1 : 0;
this_.flag_v = ((this_.reg_a ^ this_._tmp1) & (this_.reg_a ^ this_._tmp2) & 0x80) >> 7;
this_.reg_a = (this_._tmp2 & 0xFF);
this_.flag_n = (this_.reg_a & 0x80) >> 7;
@@ -2162,39 +2359,43 @@ M65C02Context.prototype.op_func_tbl = [
}
this_.cycles += 2;
},
+ // 0xEA NOP
function opEA(this_) {
this_.cycles += 2;
},
+ // 0xEB 未使用
function opEB(this_) {
this_.cycles += 1;
},
+ // 0xEC CPX abs
function opEC(this_) {
- this_._addr = (((this_.reg_pc < 0xFFFF ? this_.memmap[(this_.reg_pc + 1) >> 13][(this_.reg_pc + 1) & 0x1FFF] : this_.ram[0]) << 8) | this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF]);
+ this_._addr = (this_.readMem(this_.reg_pc + 1) << 8) | this_.readMem(this_.reg_pc);
this_.reg_pc = (this_.reg_pc + 2) & 0xFFFF;
- this_._tmp1 = this_.reg_x - (this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]);
- this_.flag_c = this_._tmp1 < 0 ? 0 : 1;
+ this_._tmp1 = this_.reg_x - this_.readMem(this_._addr);
+ this_.flag_c = (this_._tmp1 >= 0) ? 1 : 0;
this_.flag_n = (this_._tmp1 & 0x80) >> 7;
this_.flag_z = (this_._tmp1 & 0xFF) ? 0 : 1;
this_.cycles += 4;
},
+ // 0xED SBC abs
function opED(this_) {
- this_._addr = (((this_.reg_pc < 0xFFFF ? this_.memmap[(this_.reg_pc + 1) >> 13][(this_.reg_pc + 1) & 0x1FFF] : this_.ram[0]) << 8) | this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF]);
+ this_._addr = (this_.readMem(this_.reg_pc + 1) << 8) | this_.readMem(this_.reg_pc);
this_.reg_pc = (this_.reg_pc + 2) & 0xFFFF;
- this_._tmp1 = (this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]);
+ this_._tmp1 = this_.readMem(this_._addr);
if (this_.flag_d) {
- this_._tmp2 = ((this_.reg_a >> 4) * 10 + (this_.reg_a & 0x0F)) - ((this_._tmp1 >> 4) * 10 + (this_._tmp1 & 0x0F)) - 1 + this_.flag_c;
- this_.flag_c = (this_._tmp2 < 0) ? 0 : 1;
- this_._tmp2 %= 100;
- if (this_._tmp2 < 0) {
- this_._tmp2 += 100;
- }
- this_.reg_a = ((((this_._tmp2 / 10) % 10) << 4) | (this_._tmp2 % 10));
+ var a_val = (this_.reg_a >> 4) * 10 + (this_.reg_a & 0x0F);
+ var m_val = (this_._tmp1 >> 4) * 10 + (this_._tmp1 & 0x0F);
+ var result = a_val - m_val - 1 + this_.flag_c;
+ this_.flag_c = (result >= 0) ? 1 : 0;
+ if (result < 0) result += 100;
+ result = result % 100;
+ this_.reg_a = ((Math.floor(result / 10) << 4) | (result % 10));
this_.flag_n = (this_.reg_a & 0x80) >> 7;
this_.flag_z = (this_.reg_a & 0xFF) ? 0 : 1;
- this_.cycles++
+ this_.cycles++;
} else {
this_._tmp2 = this_.reg_a - this_._tmp1 - 1 + this_.flag_c;
- this_.flag_c = (this_._tmp2 < 0) ? 0 : 1;
+ this_.flag_c = (this_._tmp2 >= 0) ? 1 : 0;
this_.flag_v = ((this_.reg_a ^ this_._tmp1) & (this_.reg_a ^ this_._tmp2) & 0x80) >> 7;
this_.reg_a = (this_._tmp2 & 0xFF);
this_.flag_n = (this_.reg_a & 0x80) >> 7;
@@ -2202,30 +2403,30 @@ M65C02Context.prototype.op_func_tbl = [
}
this_.cycles += 4;
},
+ // 0xEE INC abs
function opEE(this_) {
- this_._addr = (((this_.reg_pc < 0xFFFF ? this_.memmap[(this_.reg_pc + 1) >> 13][(this_.reg_pc + 1) & 0x1FFF] : this_.ram[0]) << 8) | this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF]);
+ this_._addr = (this_.readMem(this_.reg_pc + 1) << 8) | this_.readMem(this_.reg_pc);
this_.reg_pc = (this_.reg_pc + 2) & 0xFFFF;
- this_._tmp1 = ((this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]) + 1) & 0xFF;
+ this_._tmp1 = (this_.readMem(this_._addr) + 1) & 0xFF;
+ this_.writeMem(this_._addr, this_._tmp1);
this_.flag_n = (this_._tmp1 & 0x80) >> 7;
this_.flag_z = (this_._tmp1 & 0xFF) ? 0 : 1;
- if (this_.io_write_map[this_._addr]) {
- this_.io_write(this_._addr, this_._tmp1);
- } else {
- this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF] = this_._tmp1;
- }
this_.cycles += 6;
},
+ // 0xEF SMB5 zp
function opEF(this_) {
- this_._addr = this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF];
- this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
- if ((this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]) & 0x40) {
+ this_._addr = this_.readMem(this_.reg_pc);
+ this_._tmp2 = this_.readMem(this_.reg_pc + 1);
+ this_.reg_pc = (this_.reg_pc + 2) & 0xFFFF;
+ if (this_.readMem(this_._addr) & 0x40) {
this_.reg_pc = (this_.reg_pc + this_._tmp2) & 0xFFFF;
this_.cycles++;
}
this_.cycles += 5;
},
+ // 0xF0 BEQ
function opF0(this_) {
- this_._tmp1 = this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF];
+ this_._tmp1 = this_.readMem(this_.reg_pc);
this_._tmp2 = this_._tmp1 - ((this_._tmp1 & 0x80) << 1);
this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
if (this_.flag_z) {
@@ -2234,25 +2435,30 @@ M65C02Context.prototype.op_func_tbl = [
}
this_.cycles += 2;
},
+ // 0xF1 SBC (indirect),Y
function opF1(this_) {
- this_._tmp1 = this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF];
- this_._addr = ((((this_._tmp1 < 0xFFFF ? this_.memmap[(this_._tmp1 + 1) >> 13][(this_._tmp1 + 1) & 0x1FFF] : this_.ram[0]) << 8) | this_.memmap[this_._tmp1 >> 13][this_._tmp1 & 0x1FFF]) + this_.reg_y) & 0xFFFF;
+ this_._tmp1 = this_.readMem(this_.reg_pc);
+ this_._addr = (this_.readMem((this_._tmp1 + 1) & 0xFF) << 8) | this_.readMem(this_._tmp1);
+ if ((this_._addr & 0xFF00) !== ((this_._addr + this_.reg_y) & 0xFF00)) {
+ this_.cycles++;
+ }
+ this_._addr = (this_._addr + this_.reg_y) & 0xFFFF;
this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
- this_._tmp1 = (this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]);
+ this_._tmp1 = this_.readMem(this_._addr);
if (this_.flag_d) {
- this_._tmp2 = ((this_.reg_a >> 4) * 10 + (this_.reg_a & 0x0F)) - ((this_._tmp1 >> 4) * 10 + (this_._tmp1 & 0x0F)) - 1 + this_.flag_c;
- this_.flag_c = (this_._tmp2 < 0) ? 0 : 1;
- this_._tmp2 %= 100;
- if (this_._tmp2 < 0) {
- this_._tmp2 += 100;
- }
- this_.reg_a = ((((this_._tmp2 / 10) % 10) << 4) | (this_._tmp2 % 10));
+ var a_val = (this_.reg_a >> 4) * 10 + (this_.reg_a & 0x0F);
+ var m_val = (this_._tmp1 >> 4) * 10 + (this_._tmp1 & 0x0F);
+ var result = a_val - m_val - 1 + this_.flag_c;
+ this_.flag_c = (result >= 0) ? 1 : 0;
+ if (result < 0) result += 100;
+ result = result % 100;
+ this_.reg_a = ((Math.floor(result / 10) << 4) | (result % 10));
this_.flag_n = (this_.reg_a & 0x80) >> 7;
this_.flag_z = (this_.reg_a & 0xFF) ? 0 : 1;
- this_.cycles++
+ this_.cycles++;
} else {
this_._tmp2 = this_.reg_a - this_._tmp1 - 1 + this_.flag_c;
- this_.flag_c = (this_._tmp2 < 0) ? 0 : 1;
+ this_.flag_c = (this_._tmp2 >= 0) ? 1 : 0;
this_.flag_v = ((this_.reg_a ^ this_._tmp1) & (this_.reg_a ^ this_._tmp2) & 0x80) >> 7;
this_.reg_a = (this_._tmp2 & 0xFF);
this_.flag_n = (this_.reg_a & 0x80) >> 7;
@@ -2260,25 +2466,26 @@ M65C02Context.prototype.op_func_tbl = [
}
this_.cycles += 5;
},
+ // 0xF2 SBC (indirect)
function opF2(this_) {
- this_._tmp1 = this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF];
- this_._addr = ((this_._tmp1 < 0xFF ? this_.ram[this_._tmp1 + 1] : this_.ram[0]) << 8) | this_.ram[this_._tmp1];
+ this_._tmp1 = this_.readMem(this_.reg_pc);
+ this_._addr = (this_.readMem((this_._tmp1 + 1) & 0xFF) << 8) | this_.readMem(this_._tmp1);
this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
- this_._tmp1 = (this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]);
+ this_._tmp1 = this_.readMem(this_._addr);
if (this_.flag_d) {
- this_._tmp2 = ((this_.reg_a >> 4) * 10 + (this_.reg_a & 0x0F)) - ((this_._tmp1 >> 4) * 10 + (this_._tmp1 & 0x0F)) - 1 + this_.flag_c;
- this_.flag_c = (this_._tmp2 < 0) ? 0 : 1;
- this_._tmp2 %= 100;
- if (this_._tmp2 < 0) {
- this_._tmp2 += 100;
- }
- this_.reg_a = ((((this_._tmp2 / 10) % 10) << 4) | (this_._tmp2 % 10));
+ var a_val = (this_.reg_a >> 4) * 10 + (this_.reg_a & 0x0F);
+ var m_val = (this_._tmp1 >> 4) * 10 + (this_._tmp1 & 0x0F);
+ var result = a_val - m_val - 1 + this_.flag_c;
+ this_.flag_c = (result >= 0) ? 1 : 0;
+ if (result < 0) result += 100;
+ result = result % 100;
+ this_.reg_a = ((Math.floor(result / 10) << 4) | (result % 10));
this_.flag_n = (this_.reg_a & 0x80) >> 7;
this_.flag_z = (this_.reg_a & 0xFF) ? 0 : 1;
- this_.cycles++
+ this_.cycles++;
} else {
this_._tmp2 = this_.reg_a - this_._tmp1 - 1 + this_.flag_c;
- this_.flag_c = (this_._tmp2 < 0) ? 0 : 1;
+ this_.flag_c = (this_._tmp2 >= 0) ? 1 : 0;
this_.flag_v = ((this_.reg_a ^ this_._tmp1) & (this_.reg_a ^ this_._tmp2) & 0x80) >> 7;
this_.reg_a = (this_._tmp2 & 0xFF);
this_.flag_n = (this_.reg_a & 0x80) >> 7;
@@ -2286,31 +2493,34 @@ M65C02Context.prototype.op_func_tbl = [
}
this_.cycles += 5;
},
+ // 0xF3 未使用
function opF3(this_) {
this_.cycles += 1;
},
+ // 0xF4 未使用
function opF4(this_) {
this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
this_.cycles += 4;
},
+ // 0xF5 SBC zp,X
function opF5(this_) {
- this_._addr = (this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF] + this_.reg_x) & 0xFF;
+ this_._addr = (this_.readMem(this_.reg_pc) + this_.reg_x) & 0xFF;
this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
- this_._tmp1 = (this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]);
+ this_._tmp1 = this_.readMem(this_._addr);
if (this_.flag_d) {
- this_._tmp2 = ((this_.reg_a >> 4) * 10 + (this_.reg_a & 0x0F)) - ((this_._tmp1 >> 4) * 10 + (this_._tmp1 & 0x0F)) - 1 + this_.flag_c;
- this_.flag_c = (this_._tmp2 < 0) ? 0 : 1;
- this_._tmp2 %= 100;
- if (this_._tmp2 < 0) {
- this_._tmp2 += 100;
- }
- this_.reg_a = ((((this_._tmp2 / 10) % 10) << 4) | (this_._tmp2 % 10));
+ var a_val = (this_.reg_a >> 4) * 10 + (this_.reg_a & 0x0F);
+ var m_val = (this_._tmp1 >> 4) * 10 + (this_._tmp1 & 0x0F);
+ var result = a_val - m_val - 1 + this_.flag_c;
+ this_.flag_c = (result >= 0) ? 1 : 0;
+ if (result < 0) result += 100;
+ result = result % 100;
+ this_.reg_a = ((Math.floor(result / 10) << 4) | (result % 10));
this_.flag_n = (this_.reg_a & 0x80) >> 7;
this_.flag_z = (this_.reg_a & 0xFF) ? 0 : 1;
- this_.cycles++
+ this_.cycles++;
} else {
this_._tmp2 = this_.reg_a - this_._tmp1 - 1 + this_.flag_c;
- this_.flag_c = (this_._tmp2 < 0) ? 0 : 1;
+ this_.flag_c = (this_._tmp2 >= 0) ? 1 : 0;
this_.flag_v = ((this_.reg_a ^ this_._tmp1) & (this_.reg_a ^ this_._tmp2) & 0x80) >> 7;
this_.reg_a = (this_._tmp2 & 0xFF);
this_.flag_n = (this_.reg_a & 0x80) >> 7;
@@ -2318,54 +2528,54 @@ M65C02Context.prototype.op_func_tbl = [
}
this_.cycles += 4;
},
+ // 0xF6 INC zp,X
function opF6(this_) {
- this_._addr = (this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF] + this_.reg_x) & 0xFF;
+ this_._addr = (this_.readMem(this_.reg_pc) + this_.reg_x) & 0xFF;
this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
- this_._tmp1 = ((this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]) + 1) & 0xFF;
+ this_._tmp1 = (this_.readMem(this_._addr) + 1) & 0xFF;
+ this_.writeMem(this_._addr, this_._tmp1);
this_.flag_n = (this_._tmp1 & 0x80) >> 7;
this_.flag_z = (this_._tmp1 & 0xFF) ? 0 : 1;
- if (this_.io_write_map[this_._addr]) {
- this_.io_write(this_._addr, this_._tmp1);
- } else {
- this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF] = this_._tmp1;
- }
this_.cycles += 6;
},
+ // 0xF7 SMB6 zp
function opF7(this_) {
- this_._addr = this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF];
+ this_._addr = this_.readMem(this_.reg_pc);
this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
- this_._tmp1 = (this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]) | 0x80;
+ this_._tmp1 = this_.readMem(this_._addr) | 0x80;
+ this_.writeMem(this_._addr, this_._tmp1);
this_.flag_n = (this_._tmp1 & 0x80) >> 7;
this_.flag_z = (this_._tmp1 & 0xFF) ? 0 : 1;
- if (this_.io_write_map[this_._addr]) {
- this_.io_write(this_._addr, this_._tmp1);
- } else {
- this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF] = this_._tmp1;
- }
this_.cycles += 5;
},
+ // 0xF8 SED
function opF8(this_) {
this_.flag_d = 1;
this_.cycles += 2;
},
+ // 0xF9 SBC abs,Y
function opF9(this_) {
- this_._addr = ((((this_.reg_pc < 0xFFFF ? this_.memmap[(this_.reg_pc + 1) >> 13][(this_.reg_pc + 1) & 0x1FFF] : this_.ram[0]) << 8) | this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF]) + this_.reg_y) & 0xFFFF;
+ this_._addr = (this_.readMem(this_.reg_pc + 1) << 8) | this_.readMem(this_.reg_pc);
+ if ((this_._addr & 0xFF00) !== ((this_._addr + this_.reg_y) & 0xFF00)) {
+ this_.cycles++;
+ }
+ this_._addr = (this_._addr + this_.reg_y) & 0xFFFF;
this_.reg_pc = (this_.reg_pc + 2) & 0xFFFF;
- this_._tmp1 = (this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]);
+ this_._tmp1 = this_.readMem(this_._addr);
if (this_.flag_d) {
- this_._tmp2 = ((this_.reg_a >> 4) * 10 + (this_.reg_a & 0x0F)) - ((this_._tmp1 >> 4) * 10 + (this_._tmp1 & 0x0F)) - 1 + this_.flag_c;
- this_.flag_c = (this_._tmp2 < 0) ? 0 : 1;
- this_._tmp2 %= 100;
- if (this_._tmp2 < 0) {
- this_._tmp2 += 100;
- }
- this_.reg_a = ((((this_._tmp2 / 10) % 10) << 4) | (this_._tmp2 % 10));
+ var a_val = (this_.reg_a >> 4) * 10 + (this_.reg_a & 0x0F);
+ var m_val = (this_._tmp1 >> 4) * 10 + (this_._tmp1 & 0x0F);
+ var result = a_val - m_val - 1 + this_.flag_c;
+ this_.flag_c = (result >= 0) ? 1 : 0;
+ if (result < 0) result += 100;
+ result = result % 100;
+ this_.reg_a = ((Math.floor(result / 10) << 4) | (result % 10));
this_.flag_n = (this_.reg_a & 0x80) >> 7;
this_.flag_z = (this_.reg_a & 0xFF) ? 0 : 1;
- this_.cycles++
+ this_.cycles++;
} else {
this_._tmp2 = this_.reg_a - this_._tmp1 - 1 + this_.flag_c;
- this_.flag_c = (this_._tmp2 < 0) ? 0 : 1;
+ this_.flag_c = (this_._tmp2 >= 0) ? 1 : 0;
this_.flag_v = ((this_.reg_a ^ this_._tmp1) & (this_.reg_a ^ this_._tmp2) & 0x80) >> 7;
this_.reg_a = (this_._tmp2 & 0xFF);
this_.flag_n = (this_.reg_a & 0x80) >> 7;
@@ -2373,37 +2583,42 @@ M65C02Context.prototype.op_func_tbl = [
}
this_.cycles += 4;
},
+ // 0xFA PLX
function opFA(this_) {
- this_.reg_x = this_.ram[this_.reg_sp = ++this_.reg_sp & 0xFF | 0x100];
+ this_.reg_sp = ++this_.reg_sp & 0xFF | 0x100;
+ this_.reg_x = this_.readMem(this_.reg_sp);
this_.flag_n = (this_.reg_x & 0x80) >> 7;
this_.flag_z = (this_.reg_x & 0xFF) ? 0 : 1;
this_.cycles += 4;
},
+ // 0xFB 未使用
function opFB(this_) {
this_.cycles += 1;
},
+ // 0xFC 未使用
function opFC(this_) {
this_.reg_pc = (this_.reg_pc + 2) & 0xFFFF;
this_.cycles += 4;
},
+ // 0xFD SBC abs,X
function opFD(this_) {
- this_._addr = ((((this_.reg_pc < 0xFFFF ? this_.memmap[(this_.reg_pc + 1) >> 13][(this_.reg_pc + 1) & 0x1FFF] : this_.ram[0]) << 8) | this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF]) + this_.reg_x) & 0xFFFF;
+ this_._addr = ((this_.readMem(this_.reg_pc + 1) << 8) | this_.readMem(this_.reg_pc)) + this_.reg_x;
this_.reg_pc = (this_.reg_pc + 2) & 0xFFFF;
- this_._tmp1 = (this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]);
+ this_._tmp1 = this_.readMem(this_._addr);
if (this_.flag_d) {
- this_._tmp2 = ((this_.reg_a >> 4) * 10 + (this_.reg_a & 0x0F)) - ((this_._tmp1 >> 4) * 10 + (this_._tmp1 & 0x0F)) - 1 + this_.flag_c;
- this_.flag_c = (this_._tmp2 < 0) ? 0 : 1;
- this_._tmp2 %= 100;
- if (this_._tmp2 < 0) {
- this_._tmp2 += 100;
- }
- this_.reg_a = ((((this_._tmp2 / 10) % 10) << 4) | (this_._tmp2 % 10));
+ var a_val = (this_.reg_a >> 4) * 10 + (this_.reg_a & 0x0F);
+ var m_val = (this_._tmp1 >> 4) * 10 + (this_._tmp1 & 0x0F);
+ var result = a_val - m_val - 1 + this_.flag_c;
+ this_.flag_c = (result >= 0) ? 1 : 0;
+ if (result < 0) result += 100;
+ result = result % 100;
+ this_.reg_a = ((Math.floor(result / 10) << 4) | (result % 10));
this_.flag_n = (this_.reg_a & 0x80) >> 7;
this_.flag_z = (this_.reg_a & 0xFF) ? 0 : 1;
- this_.cycles++
+ this_.cycles++;
} else {
this_._tmp2 = this_.reg_a - this_._tmp1 - 1 + this_.flag_c;
- this_.flag_c = (this_._tmp2 < 0) ? 0 : 1;
+ this_.flag_c = (this_._tmp2 >= 0) ? 1 : 0;
this_.flag_v = ((this_.reg_a ^ this_._tmp1) & (this_.reg_a ^ this_._tmp2) & 0x80) >> 7;
this_.reg_a = (this_._tmp2 & 0xFF);
this_.flag_n = (this_.reg_a & 0x80) >> 7;
@@ -2411,34 +2626,35 @@ M65C02Context.prototype.op_func_tbl = [
}
this_.cycles += 4;
},
+ // 0xFE INC abs,X
function opFE(this_) {
- this_._addr = ((((this_.reg_pc < 0xFFFF ? this_.memmap[(this_.reg_pc + 1) >> 13][(this_.reg_pc + 1) & 0x1FFF] : this_.ram[0]) << 8) | this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF]) + this_.reg_x) & 0xFFFF;
+ this_._addr = ((this_.readMem(this_.reg_pc + 1) << 8) | this_.readMem(this_.reg_pc)) + this_.reg_x;
this_.reg_pc = (this_.reg_pc + 2) & 0xFFFF;
- this_._tmp1 = ((this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]) + 1) & 0xFF;
+ this_._tmp1 = (this_.readMem(this_._addr) + 1) & 0xFF;
+ this_.writeMem(this_._addr, this_._tmp1);
this_.flag_n = (this_._tmp1 & 0x80) >> 7;
this_.flag_z = (this_._tmp1 & 0xFF) ? 0 : 1;
- if (this_.io_write_map[this_._addr]) {
- this_.io_write(this_._addr, this_._tmp1);
- } else {
- this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF] = this_._tmp1;
- }
this_.cycles += 6;
},
+ // 0xFF SMB7 zp
function opFF(this_) {
- this_._addr = this_.memmap[this_.reg_pc >> 13][this_.reg_pc & 0x1FFF];
- this_.reg_pc = (this_.reg_pc + 1) & 0xFFFF;
- if ((this_.io_read_map[this_._addr] ? this_.io_read(this_._addr) : this_.memmap[this_._addr >> 13][this_._addr & 0x1FFF]) & 0x80) {
+ this_._addr = this_.readMem(this_.reg_pc);
+ this_._tmp2 = this_.readMem(this_.reg_pc + 1);
+ this_.reg_pc = (this_.reg_pc + 2) & 0xFFFF;
+ if (this_.readMem(this_._addr) & 0x80) {
this_.reg_pc = (this_.reg_pc + this_._tmp2) & 0xFFFF;
this_.cycles++;
}
this_.cycles += 5;
}
];
+
M65C02Context.prototype.execute = function() {
this._code = this.memmap[this.reg_pc >> 13][this.reg_pc & 0x1FFF];
this.reg_pc = (this.reg_pc + 1) & 0xFFFF;
this.op_func_tbl[this._code](this);
};
+
M65C02Context.prototype.doIrq = function() {
if (!this.stp) {
if (!this.nmi) {
@@ -2446,12 +2662,12 @@ M65C02Context.prototype.doIrq = function() {
this.reg_pc = (this.reg_pc + 1) & 0xFFFF;
this.wai = 0;
}
- this.ram[this.reg_sp] = (this.reg_pc >> 8);
+ this.writeMem(this.reg_sp, (this.reg_pc >> 8));
this.reg_sp = --this.reg_sp & 0xFF | 0x100;
- this.ram[this.reg_sp] = (this.reg_pc & 0xFF);
+ this.writeMem(this.reg_sp, (this.reg_pc & 0xFF));
this.reg_sp = --this.reg_sp & 0xFF | 0x100;
this.flag_i = 1;
- this.ram[this.reg_sp] = this.get_reg_ps();
+ this.writeMem(this.reg_sp, this.get_reg_ps());
this.reg_sp = --this.reg_sp & 0xFF | 0x100;
this.reg_pc = (this.memmap[7][0x1FFB] << 8) | (this.memmap[7][0x1FFA]);
this.nmi = 1;
@@ -2463,12 +2679,12 @@ M65C02Context.prototype.doIrq = function() {
this.wai = 0;
}
if (!this.flag_i) {
- this.ram[this.reg_sp] = (this.reg_pc >> 8);
+ this.writeMem(this.reg_sp, (this.reg_pc >> 8));
this.reg_sp = --this.reg_sp & 0xFF | 0x100;
- this.ram[this.reg_sp] = (this.reg_pc & 0xFF);
+ this.writeMem(this.reg_sp, (this.reg_pc & 0xFF));
this.reg_sp = --this.reg_sp & 0xFF | 0x100;
this.flag_b = 0;
- this.ram[this.reg_sp] = this.get_reg_ps();
+ this.writeMem(this.reg_sp, this.get_reg_ps());
this.reg_sp = --this.reg_sp & 0xFF | 0x100;
this.reg_pc = (this.memmap[7][0x1FFF] << 8) | (this.memmap[7][0x1FFE]);
this.flag_i = 1;
diff --git a/src/wqx.js b/src/wqx.js
index faa3206..13a1d46 100644
--- a/src/wqx.js
+++ b/src/wqx.js
@@ -1,6 +1,12 @@
// cc800
// http://bbs.emsky.net/viewthread.php?tid=33474
+// ── 调试追踪开关 ──────────────────────────────────────────────────
+// 设为 true 可在控制台看到完整启动链和关键函数调用序列
+var WQX_TRACE = false;
+function _trace(name) { if (WQX_TRACE) console.log('[WQX] ' + name); }
+// ──────────────────────────────────────────────────────────────────
+
var Wqx = (function (){
var io00_bank_switch = 0x00;
var io01_int_enable = 0x01;
@@ -39,7 +45,7 @@ var Wqx = (function (){
var io1E_batt_detect = 0x1E;
var io20_JG = 0x20;
var io23_unknow = 0x23;
- var io_ROA_bit = 0x80; // RAM/ROM (io_bios_bsw)
+ var io_ROA_bit = 0x80;
var map0000 = 0;
var map2000 = 1;
@@ -88,21 +94,18 @@ var Wqx = (function (){
this.frameTimer = null;
this.totalInsts = 0;
- this.keypadmatrix = [
- [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],
- [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]
- ];
+ // 睡眠/唤醒状态,对应C++ slept/should_wake_up/wake_up_pending/wake_up_key
+ this.slept = false;
+ this.shouldWakeUp = false;
+ this.wakeUpPending = false;
+ this.wakeUpKey = 0;
+
+ // 对应C++ keypad_matrix: Uint8Array,每行一个字节,直接位运算
+ this.keypadmatrix = new Uint8Array(8); // REPLACED_MARKER
this.lcdoffshift0flag = 0;
this.lcdbuffaddr = null;
this.timer0started = false;
this.timer0value = 0;
-// this.timer0waveoutstart = false;
this.ptr40 = null;
this.zp40cache = null;
@@ -117,6 +120,9 @@ var Wqx = (function (){
this.bbsbankheader = [];
this.may4000ptr = null;
this.cpu = null;
+ this.clockRecords = new Uint8Array(80);
+ this.mayClockFlags = 0;
+
this.initLcd();
this.initRom();
this.initNor();
@@ -127,6 +133,7 @@ var Wqx = (function (){
}
Wqx.prototype.initLcd = function (){
+ _trace('initLcd');
var doc = this.div.ownerDocument;
var canvas = doc.createElement('canvas');
canvas.width = 320;
@@ -138,7 +145,9 @@ var Wqx = (function (){
this.canvasCtx.setTransform(2, 0, 0, 2, 0, 0);
this.canvasCtx.save();
};
+
Wqx.prototype.initRom = function (){
+ _trace('initRom');
this.rom = new Uint8Array(0x8000 * 768);
for (var i=0; i<256; i++) {
this.volume0array[i] = getByteArray(this.rom, 0x8000 * i, 0x8000);
@@ -146,19 +155,25 @@ var Wqx = (function (){
this.volume2array[i] = getByteArray(this.rom, 0x8000 * (i + 512), 0x8000);
}
};
+
Wqx.prototype.initNor = function (){
+ _trace('initNor');
this.nor = new Uint8Array(0x8000 * 32);
this.norbankheader = [];
for (var i=0; i<32; i++) {
this.norbankheader[i] = getByteArray(this.nor, 0x8000 * i, 0x8000);
}
};
+
Wqx.prototype.initRam = function (){
+ _trace('initRam');
this.ram = new Uint8Array(0x10000);
this.ptr40 = getByteArray(this.ram, 0x40, 0x40);
this.zp40cache = new Uint8Array(0x40);
};
+
Wqx.prototype.initMemmap = function (){
+ _trace('initMemmap');
this.memmap[map0000] = getByteArray(this.ram, 0, 0x2000);
this.ram2000_4000 = getByteArray(this.ram, 0x2000, 0x2000);
this.memmap[map2000] = this.ram2000_4000;
@@ -175,39 +190,18 @@ var Wqx = (function (){
this.may4000ptr = this.volume0array[0];
this.memmap[mapE000] = getByteArray(this.volume0array[0], 0x2000, 0x2000);
this.switch4000ToBFFF();
-// this._dbg_logMemmap();
};
function hex(num, len){
var str = num.toString(16).toUpperCase();
return new Array(len - str.length + 1).join('0') + str;
}
- var _dbg_mapNames = ['map0000','map2000','map4000','map6000','map8000','mapA000','mapC000','mapE000'];
- Wqx.prototype._dbg_ptrName = function (i){
- var ptr = this.memmap[i];
- var mapName = _dbg_mapNames[i];
- if (ptr.buffer === this.rom.buffer) {
- return mapName + ': ROM[0x' + hex(ptr.byteOffset, 8) + ']';
- } else if (ptr.buffer === this.nor.buffer) {
- return mapName + ': NOR[0x' + hex(ptr.byteOffset, 8) + ']';
- } else {
- return mapName + ': RAM[0x' + hex(ptr.byteOffset, 8) + ']';
- }
- };
- Wqx.prototype._dbg_logMemmap = function (){
- var buff = [];
- for (var i=0; i<_dbg_mapNames.length; i++) {
- buff.push(this._dbg_ptrName(i));
- }
- console.log(buff.join('\n'));
- };
Wqx.prototype.fillC000BIOSBank = function (volume_array){
this.bbsbankheader[0] = getByteArray(volume_array[0], 0, 0x2000);
this.bbsbankheader[1] = this.ramRomBank1;
this.bbsbankheader[2] = getByteArray(volume_array[0], 0x4000, 0x2000);
this.bbsbankheader[3] = getByteArray(volume_array[0], 0x6000, 0x2000);
- // 4567, 89AB, CDEF take first 4page 0000~7FFF in BROM
for (var i = 0; i < 3; i++) {
this.bbsbankheader[i * 4 + 4] = getByteArray(volume_array[i + 1], 0, 0x2000);
this.bbsbankheader[i * 4 + 5] = getByteArray(volume_array[i + 1], 0x2000, 0x2000);
@@ -215,143 +209,129 @@ var Wqx = (function (){
this.bbsbankheader[i * 4 + 7] = getByteArray(volume_array[i + 1], 0x6000, 0x2000);
}
};
+
Wqx.prototype.switch4000ToBFFF = function (){
this.memmap[map4000] = getByteArray(this.may4000ptr, 0, 0x2000);
this.memmap[map6000] = getByteArray(this.may4000ptr, 0x2000, 0x2000);
this.memmap[map8000] = getByteArray(this.may4000ptr, 0x4000, 0x2000);
this.memmap[mapA000] = getByteArray(this.may4000ptr, 0x6000, 0x2000);
-// this._dbg_logMemmap();
};
Wqx.prototype.initIo = function (){
+ _trace('initIo');
this.io_read_map = new Array(0x10000);
this.io_write_map = new Array(0x10000);
for (var i=0; i<0x10000; i++) {
this.io_read_map[i] = i < 0x40;
this.io_write_map[i] = i < 0x40 || i >= 0x4000;
}
+ // 对应C++ Load():0x045F读取时处理wakeUpPending
+ this.io_read_map[0x045F] = true;
this.io_read = this.readIO.bind(this);
this.io_write = this.writeIO.bind(this);
this._eraseBuff = new Uint8Array(256);
- // bit5 TIMER0 SOURCE CLOCK SELECT BIT1/TIMER CLOCK SELECT BIT2
- // bit3 TIMER1 SOURCE CLOCK SELECT BIT1/TIMER CLOCK SELECT BIT0
- // ([0C] & 3) * 1000 || [06] * 10 = LCDAddr
this.ram[io0C_timer01_ctrl] = 0x28;
this.ram[io1B_pwm_data] = 0;
- this.ram[io01_int_enable] = 0; // Disable all int
+ this.ram[io01_int_enable] = 0;
this.ram[io04_general_ctrl] = 0;
this.ram[io05_clock_ctrl] = 0;
this.ram[io08_port0_data] = 0;
this.ram[io00_bank_switch] = 0;
this.ram[io09_port1_data] = 0;
};
+
Wqx.prototype.readIO = function (addr){
-// console.log('readIO: ' + addr.toString(16) + ' @' + this._instCount);
+ // 对应C++ Load():Flash编程/擦除完成后返回0x88,复位状态机
+ if (addr >= 0x4000 && addr < 0xC000) {
+ if ((this._eraseStep === 4 && this._eraseType === 2) ||
+ (this._eraseStep === 6 && this._eraseType === 3)) {
+ this._eraseStep = 0;
+ this._eraseType = 0;
+ for (var i = 0x4000; i < 0xC000; i++) this.io_read_map[i] = false;
+ return 0x88;
+ }
+ return this.memmap[addr >> 13][addr & 0x1FFF];
+ }
switch (addr) {
- case 0x00:
- return this.read00BankSwitch();
- case 0x02:
- return this.read02Timer0Value();
- case 0x04:
- return this.read04StopTimer0();
- case 0x05:
- return this.read05StartTimer0;
- case 0x06:
- return this.read06StopTimer1();
- case 0x07:
- return this.read07StartTimer1();
- case 0x3B:
- return this.read3BUnknown();
- case 0x3F:
- return this.read3FClock();
- default:
- return this.ram[addr];
+ case 0x00: return this.read00BankSwitch();
+ case 0x02: return this.read02Timer0Value();
+ case 0x04: return this.read04StopTimer0();
+ case 0x05: return this.read05StartTimer0;
+ case 0x06: return this.read06StopTimer1();
+ case 0x07: return this.read07StartTimer1();
+ case 0x3B: return this.read3BUnknown();
+ case 0x3F: return this.read3FClock();
+ case 0x045F:
+ // 对应C++ Load():唤醒键值注入
+ if (this.wakeUpPending) {
+ this.wakeUpPending = false;
+ this.ram[0x045F] = this.wakeUpKey;
+ }
+ return this.ram[0x045F];
+ default: return this.ram[addr];
}
};
+
Wqx.prototype.read00BankSwitch = function (){
-// console.log('read00BankSwitch');
return this.ram[io00_bank_switch];
};
+
Wqx.prototype.read04StopTimer0 = function (){
if (this.timer0started) {
this.timer0value = this.read02Timer0Value();
this.timer0started = false;
}
-// if (this.timer0waveoutstart) {
-// this.timer0waveoutstart = false;
-// }
-// console.log('read04StopTimer0: ' + this.ram[io04_general_ctrl]);
return this.ram[io04_general_ctrl];
};
+
Wqx.prototype.read02Timer0Value = function (){
if (this.timer0started) {
this.timer0value = Math.floor((this.cpu.cycles - this.timer0startcycles) /
SPDC1016Frequency) & 0xFF;
}
-// console.log('read02Timer0Value: ' + this.timer0value);
return this.timer0value;
};
+
Wqx.prototype.read05StartTimer0 = function (){
- console.log('read05StartTimer0');
this.timer0started = true;
this.timer0startcycles = this.cpu.cycles;
-// if (this.read02Timer0Value() == 0x3F) {
-// //gTimer0WaveoutStarted = 1;
-// //mayTimer0Var1 = 0;
-// //maypTimer0VarA8 = (int)&unk_4586A8;
-// //mayTimer0Var2 = 0;
-// //mayIO2345Var1 = 0;
-// //ResetWaveout(&pwh);
-// //OpenWaveout((DWORD_PTR)&pwh, 0x1F40u);
-// this.timer0waveoutstart = true;
-// }
- return this.ram[io05_clock_ctrl]; // follow rulz by GGV
+ return this.ram[io05_clock_ctrl];
};
+
Wqx.prototype.read06StopTimer1 = function (){
- console.log('read06StopTimer1: ' + this.ram[io04_general_ctrl]);
- //todo
return this.ram[io06_lcd_config];
};
+
Wqx.prototype.read07StartTimer1 = function (){
- console.log('read06StopTimer1');
+ // todo
};
+
Wqx.prototype.read3BUnknown = function (){
if (!(this.ram[0x3d] & 0x03)) {
return this.clockRecords[0x3B] & 0xFE;
}
+ return this.ram[0x3B];
};
+
Wqx.prototype.read3FClock = function (){
return this.clockRecords[this.ram[62]] || 0;
};
+
Wqx.prototype.writeIO = function (addr, value){
-// console.log('writeIO: 0x' + addr.toString(16) + ', 0x' + value.toString(16) + ' @' + this._instCount);
switch (addr) {
- case 0x00:
- return this.write00BankSwitch(value);
- case 0x02:
- return this.write02Timer0Value(value);
- case 0x05:
- return this.write05ClockCtrl(value);
- case 0x06:
- return this.write06LCDStartAddr(value);
- case 0x08:
- return this.write08Port0(value);
- case 0x09:
- return this.write09Port1(value);
- case 0x0A:
- return this.write0AROABBS(value);
- case 0x0C:
- return this.writeTimer01Control(value);
- case 0x0D:
- return this.write0DVolumeIDLCDSegCtrl(value);
- case 0x0F:
- return this.write0FZeroPageBankswitch(value);
- case 0x20:
- return this.write20JG(value);
- case 0x23:
- return this.write23JGWav(value);
- case 0x3F:
- return this.write3FClock(value);
+ case 0x00: return this.write00BankSwitch(value);
+ case 0x02: return this.write02Timer0Value(value);
+ case 0x05: return this.write05ClockCtrl(value);
+ case 0x06: return this.write06LCDStartAddr(value);
+ case 0x08: return this.write08Port0(value);
+ case 0x09: return this.write09Port1(value);
+ case 0x0A: return this.write0AROABBS(value);
+ case 0x0C: return this.writeTimer01Control(value);
+ case 0x0D: return this.write0DVolumeIDLCDSegCtrl(value);
+ case 0x0F: return this.write0FZeroPageBankswitch(value);
+ case 0x20: return this.write20JG(value);
+ case 0x23: return this.write23JGWav(value);
+ case 0x3F: return this.write3FClock(value);
}
if (addr >= this.lcdbuffaddr && addr < this.lcdbuffaddr + 1600) {
return this.updateLCD(addr, value);
@@ -362,9 +342,7 @@ var Wqx = (function (){
this.ram[addr] = value;
};
- // decompiled.
Wqx.prototype.write00BankSwitch = function (bank){
-// console.log('write00BankSwitch: ' + bank);
if (this.ram[io00_bank_switch] !== bank) {
if (bank < 0x20) {
this.may4000ptr = this.norbankheader[bank];
@@ -381,8 +359,8 @@ var Wqx = (function (){
this.ram[io00_bank_switch] = bank;
}
};
+
Wqx.prototype.write02Timer0Value = function (value){
-// console.log('write02Timer0Value: ' + value);
if (this.timer0started) {
this.timer0startcycles = (this.cpu.cycles -
(value * SPDC1016Frequency / 10));
@@ -390,39 +368,72 @@ var Wqx = (function (){
this.timer0value = value;
}
};
+
+ // 修复:对应C++ Write05,bit3变化时控制睡眠状态
Wqx.prototype.write05ClockCtrl = function (value){
-// console.log('write05ClockCtrl: ' + value);
- // FROM WQXSIM
- // SPDC1016
- if (this.ram[io05_clock_ctrl] & 0x08) {
- // old bit3, LCDON
+ _trace('write05ClockCtrl');
+ var oldValue = this.ram[io05_clock_ctrl];
+ // bit3 变化控制睡眠(LCD on = 唤醒,LCD off = 睡眠)
+ if ((oldValue ^ value) & 0x08) {
+ this.slept = !(value & 0x08);
+ }
+ // 原有 lcdoffshift0flag 逻辑保留
+ if (oldValue & 0x08) {
if ((value & 0x0F) === 0) {
- // new bit0~bit3 is 0
this.lcdoffshift0flag = true;
}
}
this.ram[io05_clock_ctrl] = value;
};
+
+ // 对应C++ SetKey:处理按键的睡眠/唤醒逻辑
+ Wqx.prototype.setKey = function (keyId, downOrUp){
+ var row = keyId & 0x07;
+ var col = keyId >> 3;
+ var bits = (keyId === 0x0F) ? 0xFE : (1 << col);
+ var wakeUpKeyMap = {
+ 0x08: 0x00, 0x09: 0x0A, 0x0A: 0x08, 0x0B: 0x06,
+ 0x0C: 0x04, 0x0D: 0x02, 0x0E: 0x0C, 0x0F: 0x00
+ };
+
+ if (downOrUp) {
+ this.keypadmatrix[row] |= bits;
+ if (this.slept) {
+ if (keyId >= 0x08 && keyId <= 0x0F && keyId !== 0x0E) {
+ this.wakeUpKey = wakeUpKeyMap[keyId];
+ this.shouldWakeUp = true;
+ this.wakeUpPending = true;
+ this.slept = false;
+ }
+ } else {
+ if (keyId === 0x0F) {
+ this.slept = true;
+ }
+ }
+ } else {
+ this.keypadmatrix[row] &= ~bits;
+ }
+ };
+
Wqx.prototype.setLcdStartAddr = function (addr){
this.lcdbuffaddr = addr;
for (var i=0; i<1600; i++) {
this.io_write_map[this.lcdbuffaddr+i] = true;
}
- console.log('lcdAddr: ' + this.lcdbuffaddr);
};
+
Wqx.prototype.write06LCDStartAddr = function (value){
- console.log('write06LCDStartAddr: ' + value);
if (this.lcdbuffaddr == null) {
this.setLcdStartAddr(((this.ram[io0C_lcd_config] & 0x03) << 12) | (value << 4));
}
this.ram[io06_lcd_config] = value;
- // SPDC1016
- // don't know how wqxsim works.
- this.ram[io09_port1_data] &= 0xFE; // remove bit0 of port1 (keypad)
+ this.ram[io09_port1_data] &= 0xFE;
};
+
Wqx.prototype.write08Port0 = function (value){
this.ram[io0B_port3_data] &= 0xFE;
};
+
function buildByte(array){
return (array[0]) |
(array[1] << 1) |
@@ -433,16 +444,17 @@ var Wqx = (function (){
(array[6] << 6) |
(array[7] << 7);
}
+
Wqx.prototype.write09Port1 = function (value){
switch (value){
- case 0x01: this.ram[io08_port0_data] = buildByte(this.keypadmatrix[0]); break;
- case 0x02: this.ram[io08_port0_data] = buildByte(this.keypadmatrix[1]); break;
- case 0x04: this.ram[io08_port0_data] = buildByte(this.keypadmatrix[2]); break;
- case 0x08: this.ram[io08_port0_data] = buildByte(this.keypadmatrix[3]); break;
- case 0x10: this.ram[io08_port0_data] = buildByte(this.keypadmatrix[4]); break;
- case 0x20: this.ram[io08_port0_data] = buildByte(this.keypadmatrix[5]); break;
- case 0x40: this.ram[io08_port0_data] = buildByte(this.keypadmatrix[6]); break;
- case 0x80: this.ram[io08_port0_data] = buildByte(this.keypadmatrix[7]); break;
+ case 0x01: this.ram[io08_port0_data] = this.keypadmatrix[0]; break;
+ case 0x02: this.ram[io08_port0_data] = this.keypadmatrix[1]; break;
+ case 0x04: this.ram[io08_port0_data] = this.keypadmatrix[2]; break;
+ case 0x08: this.ram[io08_port0_data] = this.keypadmatrix[3]; break;
+ case 0x10: this.ram[io08_port0_data] = this.keypadmatrix[4]; break;
+ case 0x20: this.ram[io08_port0_data] = this.keypadmatrix[5]; break;
+ case 0x40: this.ram[io08_port0_data] = this.keypadmatrix[6]; break;
+ case 0x80: this.ram[io08_port0_data] = this.keypadmatrix[7]; break;
case 0:
this.ram[io0B_port3_data] |= 1;
if (this.keypadmatrix[7] === 0xFE) {
@@ -452,149 +464,111 @@ var Wqx = (function (){
case 0x7F:
if (this.ram[io15_port1_dir] === 0x7F) {
this.ram[io08_port0_data] = (
- buildByte(this.keypadmatrix[0]) |
- buildByte(this.keypadmatrix[1]) |
- buildByte(this.keypadmatrix[2]) |
- buildByte(this.keypadmatrix[3]) |
- buildByte(this.keypadmatrix[4]) |
- buildByte(this.keypadmatrix[5]) |
- buildByte(this.keypadmatrix[6]) |
- buildByte(this.keypadmatrix[7])
+ this.keypadmatrix[0] |
+ this.keypadmatrix[1] |
+ this.keypadmatrix[2] |
+ this.keypadmatrix[3] |
+ this.keypadmatrix[4] |
+ this.keypadmatrix[5] |
+ this.keypadmatrix[6] |
+ this.keypadmatrix[7]
);
break;
}
}
this.ram[io09_port1_data] = value;
};
+
+ // 修复:补充 map2000 切换
+ // 对应C++ Write0A + SwitchVolume 里 memmap[1] = roa_bbs & 0x04 ? ram_page2 : ram_page1
Wqx.prototype.write0AROABBS = function (value){
-// console.log('write0AROABBS: ' + value);
if (value !== this.ram[io0A_roa]) {
this.memmap[mapC000] = getByteArray(this.bbsbankheader[value & 0x0F], 0, 0x2000);
+ this.memmap[map2000] = (value & 0x04) ? this.ram4000_6000 : this.ram2000_4000;
this.ram[io0A_roa] = value;
}
};
+
Wqx.prototype.writeTimer01Control = function (value){
-// console.log('writeTimer01Control: ' + value);
if (this.lcdbuffaddr === null) {
this.lcdbuffaddr = ((value & 0x03) << 12) | (this.ram[io06_lcd_config] << 4);
- console.log('lcdAddr: ' + this.lcdbuffaddr);
}
this.ram[io0C_lcd_config] = value;
};
- // decompiled.
Wqx.prototype.write0DVolumeIDLCDSegCtrl = function (value){
-// console.log('write0DVolumeIDLCDSegCtrl: ' + value);
+ _trace('write0DVolumeIDLCDSegCtrl');
if (value !== this.ram[io0D_volumeid]) {
- // bit0 changed.
- // volume1,3 != volume0,2
var bank = this.ram[io00_bank_switch];
if ((value & 0x03) === 1) {
- // Volume1
this.fillC000BIOSBank(this.volume1array);
this.may4000ptr = this.volume1array[bank];
this.memmap[mapE000] = getByteArray(this.volume1array[0], 0x2000, 0x2000);
} else if ((value & 0x03) === 3) {
- // Volume2
this.fillC000BIOSBank(this.volume2array);
this.may4000ptr = this.volume2array[bank];
this.memmap[mapE000] = getByteArray(this.volume2array[0], 0x2000, 0x2000);
} else {
- // Volume0
this.fillC000BIOSBank(this.volume0array);
this.may4000ptr = this.volume0array[bank];
this.memmap[mapE000] = getByteArray(this.volume0array[0], 0x2000, 0x2000);
}
-
- var page2000 = this.ram4000_6000;
var roabbs = this.ram[io0A_roa];
- if (!(roabbs & 0x04)) {
- page2000 = this.ram2000_4000;
- }
- if (this.memmap[map2000] !== page2000) {
- this.memmap[map2000] = page2000;
-// this.canvasCtx.clearRect(0, 0, 160, 80);
- }
- this.memmap[mapC000] = this.bbsbankheader[roabbs & 0x0F];
+ // 对应C++ SwitchVolume: memmap[1] 根据 roa_bbs bit2 决定
+ this.memmap[map2000] = (roabbs & 0x04) ? this.ram4000_6000 : this.ram2000_4000;
+ this.memmap[mapC000] = getByteArray(this.bbsbankheader[roabbs & 0x0F], 0, 0x2000);
this.switch4000ToBFFF();
}
this.ram[io0D_volumeid] = value;
-// this._dbg_logMemmap();
};
+
Wqx.prototype.write0FZeroPageBankswitch = function (value){
-// console.log('write0FZeroPageBankswitch: ' + value);
var oldzpbank = this.ram[io0F_zp_bsw] & 0x07;
var newzpbank = (value & 0x07);
var newzpptr = this.getZeroPagePointer(newzpbank);
if (oldzpbank !== newzpbank) {
if (oldzpbank === 0) {
- // oldzpbank == 0
- memcpy(this.zp40cache, this.ptr40, 0x40); // backup fixed 40~80 to cache
- memcpy(this.ptr40, newzpptr, 0x40); // copy newbank to 40
+ memcpy(this.zp40cache, this.ptr40, 0x40);
+ memcpy(this.ptr40, newzpptr, 0x40);
} else {
- // dangerous if exchange 00 <-> 40
- // oldaddr maybe 0 or 200~300
var oldzpptr = this.getZeroPagePointer(oldzpbank);
memcpy(oldzpptr, this.ptr40, 0x40);
if (newzpbank !== 0) {
memcpy(this.ptr40, newzpptr, 0x40);
} else {
- memcpy(this.ptr40, this.zp40cache, 0x40); // copy backup to 40
+ memcpy(this.ptr40, this.zp40cache, 0x40);
}
}
}
this.ram[io0F_zp_bsw] = value;
};
+
Wqx.prototype.getZeroPagePointer = function (bank){
- //.text:0040BFD0 bank = byte ptr 4
- //.text:0040BFD0
- //.text:0040BFD0 mov al, [esp+bank]
- //.text:0040BFD4 cmp al, 4
- //.text:0040BFD6 jnb short loc_40BFE5 ; if (bank < 4) {
- //.text:0040BFD8 xor eax, eax ; bank == 0,1,2,3
- //.text:0040BFD8 ; set bank = 0
- //.text:0040BFDA and eax, 0FFFFh ; WORD(bank)
- //.text:0040BFDF add eax, offset gFixedRAM0 ; result = &gFixedRAM0[WORD(bank)];
- //.text:0040BFE4 retn ; }
- //.text:0040BFE5 ; ---------------------------------------------------------------------------
- //.text:0040BFE5
- //.text:0040BFE5 loc_40BFE5: ; CODE XREF: GetZeroPagePointer+6j
- //.text:0040BFE5 movzx ax, al ; 4,5,6,7
- //.text:0040BFE9 add eax, 4 ; bank+=4
- //.text:0040BFEC shl eax, 6 ; bank *= 40;
- //.text:0040BFEF and eax, 0FFFFh ; WORD(bank)
- //.text:0040BFF4 add eax, offset gFixedRAM0
- //.text:0040BFF9 retn
if (bank >= 4) {
- // 4,5,6,7
- // 4 -> 200 5-> 240
return getByteArray(this.ram, (bank + 4) << 6, 0x40);
} else {
- // 0,1,2,3
return getByteArray(this.ram, 0, 0x40);
}
};
+
Wqx.prototype.write20JG = function (value){
-// console.log('write20JG');
this.ram[io20_JG] = value;
if (value === 0x80 || value === 0x40) {
- // todo:
this.ram[io20_JG] = 0;
}
};
Wqx.prototype.write23JGWav = function (value){
-// console.log('write23JGWav');
this.ram[io23_unknow] = value;
if (value === 0xC2) {
- // gMayJGBuff2[(unsigned __int8)gMayJGIndex] = gZeroPage[34];
+ // todo
} else if (value === 0xC4) {
-
+ // todo
} else if (value === 0x80) {
this.ram[io20_JG] = 0x80;
- // todo:
}
};
+
Wqx.prototype.write3FClock = function (value){
if (this.ram[62] >= 0x07) {
if (this.ram[62] === 0x0B) {
@@ -608,7 +582,7 @@ var Wqx = (function (){
this.clockRecords[this.ram[62] % 80] = value;
}
} else {
- if (!(this.clockRecords[0x0B] & 0x80)) {
+ if (!(this.clockRecords[0x0B] & 0x80)) {
this.clockRecords[this.ram[62]] = value;
}
}
@@ -621,142 +595,142 @@ var Wqx = (function (){
Wqx.prototype._eraseTemp1 = 0;
Wqx.prototype._eraseTemp2 = 0;
Wqx.prototype._eraseBuff = null;
+
+ // 严格对照C++ Store()逻辑,else-if链完全一致
Wqx.prototype.writeGE4000 = function (addr, value){
-// console.log('writeGE4000: ' + addr.toString(16) + ', ' + value.toString(16));
- var buffer = this.memmap[addr >> 13].buffer;
- // writable bank.
- if (buffer === this.ram || buffer === this.ramRomBank1) {
- this.memmap[addr >> 13][addr & 0x1FFF] = value;
- if (buffer === this.ramRomBank1) {
- console.log('write to ramRomBank1');
- }
+ // 对应C++:ram_page2/ram_page3判断(普通RAM写,最常见路径优先)
+ var seg = this.memmap[addr >> 13];
+ if (seg.buffer === this.ram.buffer || seg === this.ramRomBank1) {
+ seg[addr & 0x1FFF] = value;
return;
}
+
if (addr >= 0xE000) {
return;
}
+
var bank = this.ram[io00_bank_switch];
if (bank >= 0x20) {
return;
}
- // ##############
- // # erasing ....
- var self = this;
- function erase_all_nor_banks(){
- for (var i=32; i--;) {
- for (var j=0x8000; j--;) {
- self.norbankheader[i][j] = 0xFF;
- }
- }
- }
- function erase_buff(){
- for (var j=256; j--;) {
- self._eraseBuff[j] = 0xFF;
- }
- }
+ // ── Flash命令状态机,严格对照C++ else-if链 ──────────────────
if (this._eraseStep === 0) {
if (addr === 0x5555 && value === 0xAA) {
this._eraseStep = 1;
- return;
- } else if (addr === 0x8000 && value === 0xF0) {
- return;
+ // 开启Flash读拦截,以便CPU能读到0x88完成状态
+ for (var i = 0x4000; i < 0xC000; i++) this.io_read_map[i] = true;
}
- } else if (this._eraseStep === 1) {
+ return;
+ }
+
+ // C++: if(fp_step==1){...} else if(fp_step==2){...} — 互斥!
+ if (this._eraseStep === 1) {
if (addr === 0xAAAA && value === 0x55) {
this._eraseStep = 2;
return;
}
+ // step1不匹配:fall through到最后的0x8000/0xF0检查
} else if (this._eraseStep === 2) {
if (addr === 0x5555) {
- switch (value){
- case 0x90:
- this._eraseSelectedBank = this.ram[io00_bank_switch];
- this._eraseTemp1 = this.norbankheader[this._eraseSelectedBank][0x4000];
- this._eraseTemp2 = this.norbankheader[this._eraseSelectedBank][0x4001];
- this.norbankheader[this._eraseSelectedBank][0x4000] = 0xC7;
- this.norbankheader[this._eraseSelectedBank][0x4001] = 0xD5;
+ var newType = 0;
+ switch (value) {
+ case 0x90: newType = 1; break;
+ case 0xA0: newType = 2; break;
+ case 0x80: newType = 3; break;
+ case 0xA8: newType = 4; break;
+ case 0x88: newType = 5; break;
+ case 0x78: newType = 6; break;
+ }
+ if (newType) {
+ this._eraseType = newType;
+ if (this._eraseType === 1) {
+ // ID读取:备份bank+0x4000处的两字节,写入识别码
+ this._eraseSelectedBank = bank;
+ this._eraseTemp1 = this.norbankheader[bank][0x4000];
+ this._eraseTemp2 = this.norbankheader[bank][0x4001];
+ // 对应C++:fp_step=3时才写识别码,这里只记录
+ }
this._eraseStep = 3;
- this._eraseType = 1;
return;
- case 0xA0: this._eraseStep = 3; this._eraseType = 2; return;
- case 0x80: this._eraseStep = 3; this._eraseType = 3; return;
- case 0xA8: this._eraseStep = 3; this._eraseType = 4; return;
- case 0x88: this._eraseStep = 3; this._eraseType = 5; return;
- case 0x78: this._eraseStep = 3; this._eraseType = 6; return;
}
}
+ // step2不匹配:fall through
} else if (this._eraseStep === 3) {
- switch (this._eraseType) {
- case 1:
+ if (this._eraseType === 1) {
if (value === 0xF0) {
+ // 恢复备份,退出ID模式
this.norbankheader[this._eraseSelectedBank][0x4000] = this._eraseTemp1;
this.norbankheader[this._eraseSelectedBank][0x4001] = this._eraseTemp2;
this._eraseStep = 0;
this._eraseType = 0;
- return;
}
- break;
- case 2:
- this.may4000ptr[addr - 0x4000] &= value;
+ return;
+ } else if (this._eraseType === 2) {
+ // 字节编程:bank基址 + (addr - 0x4000),对应C++ bank + addr - 0x4000
+ this.norbankheader[bank][addr - 0x4000] &= value;
this._eraseStep = 4;
return;
- case 4:
+ } else if (this._eraseType === 4) {
+ this._eraseBuff[addr & 0xFF] &= value;
this._eraseStep = 4;
- this._eraseBuff[addr % 256] &= value;
return;
- case 3:
- case 5:
+ } else if (this._eraseType === 3 || this._eraseType === 5) {
if (addr === 0x5555 && value === 0xAA) {
this._eraseStep = 4;
return;
}
- break;
}
+ // step3不匹配:fall through
} else if (this._eraseStep === 4) {
- switch (this._eraseType) {
- case 3:
- case 5:
+ if (this._eraseType === 3 || this._eraseType === 5) {
if (addr === 0xAAAA && value === 0x55) {
this._eraseStep = 5;
return;
}
- break;
}
+ // step4不匹配:fall through
} else if (this._eraseStep === 5) {
if (addr === 0x5555 && value === 0x10) {
- erase_all_nor_banks();
- this._eraseStep = 6;
+ // 全片擦除
+ for (var i = 0; i < 32; i++) {
+ for (var j = 0; j < 0x8000; j++) {
+ this.norbankheader[i][j] = 0xFF;
+ }
+ }
if (this._eraseType === 5) {
- erase_buff();
+ for (var j = 0; j < 256; j++) this._eraseBuff[j] = 0xFF;
}
+ this._eraseStep = 6;
return;
}
if (this._eraseType === 3 && value === 0x30) {
- var k = this.ram[io00_bank_switch];
- var a = addr - addr % 0x800 - 0x4000;
- for (var j=0x800; j--;) {
- this.norbankheader[k][a + j] = 0xFF;
+ // 扇区擦除:bank基址 + sector对齐偏移
+ var offset = addr - 0x4000;
+ var sectorBase = offset - (offset % 0x800);
+ for (var j = 0; j < 0x800; j++) {
+ this.norbankheader[bank][sectorBase + j] = 0xFF;
}
this._eraseStep = 6;
return;
}
if (this._eraseType === 5 && value === 0x48) {
- erase_buff();
+ for (var j = 0; j < 256; j++) this._eraseBuff[j] = 0xFF;
this._eraseStep = 6;
return;
}
+ // step5不匹配:fall through
}
- // ????.
+
+ // 任意step下:0x8000写0xF0复位状态机(对应C++末尾检查)
if (addr === 0x8000 && value === 0xF0) {
this._eraseStep = 0;
this._eraseType = 0;
- return;
}
- console.log('error occurs when operate in flash! ' + addr.toString(16) + ',' + value.toString(16));
};
Wqx.prototype.resetCpu = function (){
+ _trace('resetCpu');
this.cpu = new M65C02Context();
this.cpu.ram = this.ram;
this.cpu.memmap = this.memmap;
@@ -764,22 +738,30 @@ var Wqx = (function (){
this.cpu.io_write_map = this.io_write_map;
this.cpu.io_read = this.io_read;
this.cpu.io_write = this.io_write;
+ // RAM已就绪,在固件从复位向量启动前同步日期和时间
+ this.syncCalendar();
+ this.syncClock();
this.cpu.cycles = 0;
this.cpu.reg_a = 0;
this.cpu.reg_x = 0;
this.cpu.reg_y = 0;
- // 00100100 unused P(bit5) = 1, I(bit3) = 1, B(bit4) = 0
this.cpu.set_reg_ps(0x24);
- // assume 1FFC/1FFD in same stripe
this.cpu.reg_pc = (this.memmap[7][0x1FFD] << 8) | this.memmap[7][0x1FFC];
this.cpu.reg_sp = 0x01FF;
this.cpu.irq = 1;
this.cpu.nmi = 1;
this.cpu.wai = 0;
this.cpu.stp = 0;
+
+ // 重置睡眠状态
+ this.slept = false;
+ this.shouldWakeUp = false;
+ this.wakeUpPending = false;
+ this.wakeUpKey = 0;
};
Wqx.prototype.loadBROM = function (buffer){
+ _trace('loadBROM');
var byteOffset = 0;
while (byteOffset < buffer.byteLength) {
var bufferSrc1 = getByteArray(buffer, byteOffset, 0x4000);
@@ -790,10 +772,10 @@ var Wqx = (function (){
memcpy(bufferDest2, bufferSrc2, 0x4000);
byteOffset += 0x8000;
}
- this.resetCpu();
};
Wqx.prototype.loadNorFlash = function (buffer){
+ _trace('loadNorFlash');
var byteOffset = 0;
while (byteOffset < buffer.byteLength) {
var bufferSrc1 = getByteArray(buffer, byteOffset, 0x4000);
@@ -804,26 +786,27 @@ var Wqx = (function (){
memcpy(bufferDest2, bufferSrc2, 0x4000);
byteOffset += 0x8000;
}
- this.resetCpu();
};
+ function uint8ArrayToBase64(bytes) {
+ var binary = '';
+ var len = bytes.byteLength;
+ var chunk = 8192;
+ for (var i = 0; i < len; i += chunk) {
+ binary += String.fromCharCode.apply(null, bytes.subarray(i, i + chunk));
+ }
+ return btoa(binary);
+ }
+ function base64ToUint8Array(base64) {
+ var binaryString = atob(base64);
+ var len = binaryString.length;
+ var bytes = new Uint8Array(len);
+ for (var i = 0; i < len; i++) {
+ bytes[i] = binaryString.charCodeAt(i);
+ }
+ return bytes;
+ }
Wqx.prototype.updateLCD = function (addr, value){
-// var lcdBuffer = getByteArray(this.ram, this.lcdbuffaddr, 160*80/8);
-// this.canvasCtx.clearRect(0, 0, 160, 80);
-// for (var i=0; i<80; i++) {
-// for (var j=0; j<20; j++) {
-// var p = j * 8;
-// var pixelsByte = lcdBuffer[20*i+j];
-// if (pixelsByte & 0x80) if (j > 0) this.canvasCtx.fillRect(p + 0, i, 1, 1);
-// if (pixelsByte & 0x40) this.canvasCtx.fillRect(p + 1, i, 1, 1);
-// if (pixelsByte & 0x20) this.canvasCtx.fillRect(p + 2, i, 1, 1);
-// if (pixelsByte & 0x10) this.canvasCtx.fillRect(p + 3, i, 1, 1);
-// if (pixelsByte & 0x08) this.canvasCtx.fillRect(p + 4, i, 1, 1);
-// if (pixelsByte & 0x04) this.canvasCtx.fillRect(p + 5, i, 1, 1);
-// if (pixelsByte & 0x02) this.canvasCtx.fillRect(p + 6, i, 1, 1);
-// if (pixelsByte & 0x01) this.canvasCtx.fillRect(p + 7, i, 1, 1);
-// }
-// }
var offset = addr - this.lcdbuffaddr;
var oldValue = this.ram[addr];
var row = Math.floor(offset / 20);
@@ -832,77 +815,60 @@ var Wqx = (function (){
var changed = oldValue ^ value;
if (changed & 0x80) {
- if (value & 0x80) {
- if (col > 0) {
- this.canvasCtx.fillRect(p + 0, row, 1, 1);
- }
- } else {
- if (col > 0) {
- this.canvasCtx.clearRect(p + 0, row, 1, 1);
- }
- }
+ if (value & 0x80) { if (col > 0) this.canvasCtx.fillRect(p + 0, row, 1, 1); }
+ else { if (col > 0) this.canvasCtx.clearRect(p + 0, row, 1, 1); }
}
if (changed & 0x40) {
- if (value & 0x40) {
- this.canvasCtx.fillRect(p + 1, row, 1, 1);
- } else {
- this.canvasCtx.clearRect(p + 1, row, 1, 1);
- }
+ if (value & 0x40) this.canvasCtx.fillRect(p + 1, row, 1, 1);
+ else this.canvasCtx.clearRect(p + 1, row, 1, 1);
}
if (changed & 0x20) {
- if (value & 0x20) {
- this.canvasCtx.fillRect(p + 2, row, 1, 1);
- } else {
- this.canvasCtx.clearRect(p + 2, row, 1, 1);
- }
+ if (value & 0x20) this.canvasCtx.fillRect(p + 2, row, 1, 1);
+ else this.canvasCtx.clearRect(p + 2, row, 1, 1);
}
if (changed & 0x10) {
- if (value & 0x10) {
- this.canvasCtx.fillRect(p + 3, row, 1, 1);
- } else {
- this.canvasCtx.clearRect(p + 3, row, 1, 1);
- }
+ if (value & 0x10) this.canvasCtx.fillRect(p + 3, row, 1, 1);
+ else this.canvasCtx.clearRect(p + 3, row, 1, 1);
}
if (changed & 0x08) {
- if (value & 0x08) {
- this.canvasCtx.fillRect(p + 4, row, 1, 1);
- } else {
- this.canvasCtx.clearRect(p + 4, row, 1, 1);
- }
+ if (value & 0x08) this.canvasCtx.fillRect(p + 4, row, 1, 1);
+ else this.canvasCtx.clearRect(p + 4, row, 1, 1);
}
if (changed & 0x04) {
- if (value & 0x04) {
- this.canvasCtx.fillRect(p + 5, row, 1, 1);
- } else {
- this.canvasCtx.clearRect(p + 5, row, 1, 1);
- }
+ if (value & 0x04) this.canvasCtx.fillRect(p + 5, row, 1, 1);
+ else this.canvasCtx.clearRect(p + 5, row, 1, 1);
}
if (changed & 0x02) {
- if (value & 0x02) {
- this.canvasCtx.fillRect(p + 6, row, 1, 1);
- } else {
- this.canvasCtx.clearRect(p + 6, row, 1, 1);
- }
+ if (value & 0x02) this.canvasCtx.fillRect(p + 6, row, 1, 1);
+ else this.canvasCtx.clearRect(p + 6, row, 1, 1);
}
if (changed & 0x01) {
- if (value & 0x01) {
- this.canvasCtx.fillRect(p + 7, row, 1, 1);
- } else {
- this.canvasCtx.clearRect(p + 7, row, 1, 1);
- }
+ if (value & 0x01) this.canvasCtx.fillRect(p + 7, row, 1, 1);
+ else this.canvasCtx.clearRect(p + 7, row, 1, 1);
}
this.ram[addr] = value;
};
- Wqx.prototype.mayClockFlags = 0;
+ // 修复:小时进位用 &= 0xC0 保留高2位标志,对应C++ clock_buff[2] &= 0xC0
Wqx.prototype.adjustTime = function (){
+ _trace('adjustTime');
if (++this.clockRecords[0] >= 60) {
this.clockRecords[0] = 0;
if (++this.clockRecords[1] >= 60) {
this.clockRecords[1] = 0;
- if (++this.clockRecords[2] >= 24) {
- this.clockRecords[2] &= 0;
- ++this.clockRecords[3];
+ // 小时只用低6位计数,高2位是标志位
+ if ((this.clockRecords[2] & 0x3F) >= 23) {
+ this.clockRecords[2] &= 0xC0; // 保留高2位,清零小时计数
+ this.clockRecords[14] = (this.clockRecords[14] + 1) % 7;
+ if (++this.clockRecords[3] > 31) {
+ this.clockRecords[3] = 1;
+ if (++this.clockRecords[8] > 12) {
+ this.clockRecords[8] = 1;
+ this.clockRecords[9] = (this.clockRecords[9] + 1) % 100;
+ }
+ }
+ } else {
+ this.clockRecords[2]++;
}
}
}
@@ -918,83 +884,232 @@ var Wqx = (function (){
}
return false;
};
+Wqx.prototype.saveState = function (){
+ var state = {
+ ram: uint8ArrayToBase64(this.ram),
+ nor: uint8ArrayToBase64(this.nor),
+ ramRomBank1: uint8ArrayToBase64(this.ramRomBank1),
+ zp40cache: uint8ArrayToBase64(this.zp40cache),
+ cpu: {
+ reg_a: this.cpu.reg_a,
+ reg_x: this.cpu.reg_x,
+ reg_y: this.cpu.reg_y,
+ reg_pc: this.cpu.reg_pc,
+ reg_sp: this.cpu.reg_sp,
+ cycles: this.cpu.cycles,
+ flag_c: this.cpu.flag_c,
+ flag_z: this.cpu.flag_z,
+ flag_i: this.cpu.flag_i,
+ flag_d: this.cpu.flag_d,
+ flag_b: this.cpu.flag_b,
+ flag_u: this.cpu.flag_u,
+ flag_v: this.cpu.flag_v,
+ flag_n: this.cpu.flag_n
+ },
+ timer0started: this.timer0started,
+ timer0value: this.timer0value,
+ timer0startcycles: this.timer0startcycles, // ← 新增
+ timer1started: this.timer1started,
+ timer1value: this.timer1value,
+ mayClockFlags: this.mayClockFlags,
+ // 新增:保存 LCD 刷新所需的关键寄存器
+ lcdbuffaddr: this.lcdbuffaddr,
+ frameCounter: this.frameCounter,
+ nmiCounter: this.nmiCounter,
+ clockCounter: this.clockCounter,
+ shouldIrq: this.shouldIrq
+ };
+ return state; // 返回 state,不要在方法内写 localStorage,让调用者决定
+};
+
+Wqx.prototype.loadState = function (state){
+ try {
+ // 恢复 RAM
+ this.ram.set(base64ToUint8Array(state.ram));
+ this.nor.set(base64ToUint8Array(state.nor));
+ this.ramRomBank1.set(base64ToUint8Array(state.ramRomBank1));
+ this.zp40cache.set(base64ToUint8Array(state.zp40cache));
+
+ // 重建 NOR 视图(重要!)
+ for (var i = 0; i < 32; i++) {
+ this.norbankheader[i] = getByteArray(this.nor, 0x8000 * i, 0x8000);
+ }
+
+ // 重建 RAM 分段视图
+ this.ram2000_4000 = getByteArray(this.ram, 0x2000, 0x2000);
+ this.ram4000_6000 = getByteArray(this.ram, 0x4000, 0x2000);
+ this.memmap[map0000] = getByteArray(this.ram, 0, 0x2000);
+ this.memmap[map2000] = this.ram2000_4000;
+ this.memmap[map4000] = this.ram4000_6000;
+ this.memmap[map6000] = getByteArray(this.ram, 0x6000, 0x2000);
+ this.memmap[map8000] = getByteArray(this.ram, 0x8000, 0x2000);
+ this.memmap[mapA000] = getByteArray(this.ram, 0xA000, 0x2000);
+ this.memmap[mapC000] = getByteArray(this.ram, 0xC000, 0x2000);
+ this.memmap[mapE000] = getByteArray(this.ram, 0xE000, 0x2000);
+
+ // 恢复 CPU
+ this.cpu.reg_a = state.cpu.reg_a;
+ this.cpu.reg_x = state.cpu.reg_x;
+ this.cpu.reg_y = state.cpu.reg_y;
+ this.cpu.reg_pc = state.cpu.reg_pc;
+ this.cpu.reg_sp = state.cpu.reg_sp;
+ this.cpu.cycles = state.cpu.cycles;
+ this.cpu.flag_c = state.cpu.flag_c;
+ this.cpu.flag_z = state.cpu.flag_z;
+ this.cpu.flag_i = state.cpu.flag_i;
+ this.cpu.flag_d = state.cpu.flag_d;
+ this.cpu.flag_b = state.cpu.flag_b;
+ this.cpu.flag_u = state.cpu.flag_u;
+ this.cpu.flag_v = state.cpu.flag_v;
+ this.cpu.flag_n = state.cpu.flag_n;
+
+ this.timer0started = state.timer0started;
+ this.timer0value = state.timer0value;
+ this.timer0startcycles = state.timer0startcycles || 0; // ← 兼容旧存档
+ this.timer1started = state.timer1started;
+ this.timer1value = state.timer1value;
+ this.mayClockFlags = state.mayClockFlags;
+
+ // 恢复计数器
+ if (state.frameCounter !== undefined) this.frameCounter = state.frameCounter;
+ if (state.nmiCounter !== undefined) this.nmiCounter = state.nmiCounter;
+ if (state.clockCounter !== undefined) this.clockCounter = state.clockCounter;
+ if (state.shouldIrq !== undefined) this.shouldIrq = state.shouldIrq;
+
+ // 重映射所有 bank(基于恢复后的寄存器值)
+ var volumeid = this.ram[io0D_volumeid];
+ var bank = this.ram[io00_bank_switch];
+ var roabbs = this.ram[io0A_roa];
+
+ // 重建 BIOS bank
+ if ((volumeid & 0x03) === 1) {
+ this.fillC000BIOSBank(this.volume1array);
+ this.memmap[mapE000] = getByteArray(this.volume1array[0], 0x2000, 0x2000);
+ } else if ((volumeid & 0x03) === 3) {
+ this.fillC000BIOSBank(this.volume2array);
+ this.memmap[mapE000] = getByteArray(this.volume2array[0], 0x2000, 0x2000);
+ } else {
+ this.fillC000BIOSBank(this.volume0array);
+ this.memmap[mapE000] = getByteArray(this.volume0array[0], 0x2000, 0x2000);
+ }
+
+ // 重映射 4000-BFFF
+ if (bank < 0x20) {
+ this.may4000ptr = this.norbankheader[bank];
+ } else if (bank >= 0x80) {
+ if (volumeid & 0x01) {
+ this.may4000ptr = this.volume1array[bank];
+ } else if (volumeid & 0x02) {
+ this.may4000ptr = this.volume2array[bank];
+ } else {
+ this.may4000ptr = this.volume0array[bank];
+ }
+ }
+ this.switch4000ToBFFF();
+
+ // 重映射 C000
+ this.memmap[mapC000] = getByteArray(this.bbsbankheader[roabbs & 0x0F], 0, 0x2000);
+
+ // 重映射 2000
+ var page2000 = (roabbs & 0x04) ? this.ram4000_6000 : this.ram2000_4000;
+ this.memmap[map2000] = page2000;
+
+ // 恢复 LCD 缓冲区地址
+ var lcdAddr = ((this.ram[io0C_lcd_config] & 0x03) << 12) | (this.ram[io06_lcd_config] << 4);
+ this.setLcdStartAddr(lcdAddr);
+
+ // 如果保存了 lcdbuffaddr,直接恢复
+ if (state.lcdbuffaddr !== null && state.lcdbuffaddr !== undefined) {
+ this.lcdbuffaddr = state.lcdbuffaddr;
+ for (var i = 0; i < 1600; i++) {
+ this.io_write_map[this.lcdbuffaddr + i] = true;
+ }
+ }
+
+ // 重绘屏幕
+ this.refreshLCD();
+
+ console.log('State restored');
+ return true;
+ } catch (e) {
+ console.error('Failed to load state:', e);
+ return false;
+ }
+};
+
+// 辅助方法:全屏重绘
+Wqx.prototype.refreshLCD = function (){
+ if (!this.lcdbuffaddr) return;
+ for (var i = 0; i < 1600; i++) {
+ var addr = this.lcdbuffaddr + i;
+ this.updateLCD(addr, this.ram[addr]);
+ }
+};
+
+
+ // 时间同步:仅同步 时、分、秒,保留 clockRecords[2] 高2位标志位
+ Wqx.prototype.syncClock = function (){
+ _trace('syncClock');
+ var now = new Date();
+ this.clockRecords[0] = now.getSeconds();
+ this.clockRecords[1] = now.getMinutes();
+ this.clockRecords[2] = (this.clockRecords[2] & 0xC0) | (now.getHours() & 0x3F);
+ };
+
+ // 日期同步:同步 年、月、日、星期
+ Wqx.prototype.syncCalendar = function (){
+ _trace('syncCalendar');
+ var now = new Date();
+
+ // 兼容某些固件使用的 RAM 备份
+ this.ram[0x472] = now.getFullYear() - 1881; // 年份偏移1881
+ this.ram[0x473] = now.getMonth(); // 月份0-based
+ this.ram[0x474] = now.getDate() - 1; // 日
+ };
+
+ // 从存档恢复后调用:只启动帧定时器,不resetCpu,保留已恢复的CPU状态
+ Wqx.prototype.startFrame = function (){
+ _trace('startFrame');
+ if (!this.frameTimer) {
+ this.frameTimer = setInterval(this.frame.bind(this), 1000 / FrameRate);
+ }
+ };
Wqx.prototype.run = function (){
+ _trace('run');
this._timerCounter = 0;
this._instCount = 0;
- this.clockRecords = new Uint8Array(80);
+ this.resetCpu();
if (!this.frameTimer) {
this.frameTimer = setInterval(this.frame.bind(this), 1000 / FrameRate);
}
};
-// Wqx.prototype._loop = function (){
-// this.frame();
-// this.frameTimer = requestAnimationFrame(this._loop.bind(this), null);
-// };
-
Wqx.prototype.stop = function (){
clearInterval(this.frameTimer);
this.frameTimer = null;
};
Wqx.prototype.reset = function (){
+ _trace('reset');
this.resetCpu();
this.frameCounter = 0;
this.nmiCounter = 0;
+ this.clockCounter = 0;
+ this._eraseStep = 0;
+ this._eraseType = 0;
};
Wqx.prototype.frame = function (){
var frameCycles = CyclesPerFrame * (this.frameCounter + 1);
var nmiCycles = CyclesPerNMI * (this.nmiCounter + 1);
var clockCycles = CyclesPer4Ms * (this.clockCounter + 1);
- var lastCycles = 0;
+
while (this.cpu.cycles < frameCycles) {
-// if (this._instCount === 2854234) {
-// debugger;
-// }
- if (this._DEBUG &&
- typeof wqxsimlogs !== 'undefined' &&
- wqxsimlogs.length > 1) {
- if (this._instCount >= wqxsimlogs.START &&
- this._instCount < wqxsimlogs.START + wqxsimlogs.length - 1) {
- var log = wqxsimlogs[this._instCount - wqxsimlogs.START];
- var error = '';
- if (log.A !== this.cpu.reg_a) {
- error += ' A ';
- }
- if (log.X !== this.cpu.reg_x) {
- error += ' X ';
- }
- if (log.Y !== this.cpu.reg_y) {
- error += ' Y ';
- }
- if (log.PS !== this.cpu.get_reg_ps()) {
- error += ' PS ';
- }
- if (log.SP + 0x100 !== this.cpu.reg_sp) {
- error += ' SP ';
- }
- if (log.PC !== this.cpu.reg_pc) {
- error += ' PC ';
- }
- if (log.OP !== this.memmap[(this.cpu.reg_pc)>>13][(this.cpu.reg_pc)&0x1FFF]) {
- error += ' OP ';
- }
-// if (log.X !== this.ram[0x20]) {
-// error += ' X ';
-// }
- if (error) {
- console.log(this._instCount + ': ' + error);
- debugger;
- this.stop();
- return;
- }
- } else if (this._instCount === wqxsimlogs.START + wqxsimlogs.length - 1) {
- alert('good!');
- }
- }
+
this.cpu.execute();
+
+ // NMI / timer0(每0.5秒触发一次)
if (this.cpu.cycles >= nmiCycles) {
this.nmiCounter++;
nmiCycles += CyclesPerNMI;
@@ -1009,31 +1124,41 @@ var Wqx = (function (){
}
this.shouldIrq = true;
}
+
+ // IRQ 触发
if (this.shouldIrq && !this.cpu.flag_i) {
this.cpu.irq = 0;
this.shouldIrq = false;
this.cpu.doIrq();
}
- this._instCount ++;
+
+ this._instCount++;
+
+ // timer1(每4ms):含唤醒逻辑,对应C++ timer1_cycles 分支
if (this.cpu.cycles >= clockCycles) {
- this.clockCounter ++;
- this.clockRecords[4] ++;
+ this.clockCounter++;
clockCycles += CyclesPer4Ms;
- this.ram[io01_int_enable] |= 0x08;
- this.shouldIrq = true;
+ this.clockRecords[4]++;
+
+ if (this.shouldWakeUp) {
+ // 唤醒:对应C++ should_wake_up 分支
+ this.shouldWakeUp = false;
+ this.ram[io01_int_enable] |= 0x01;
+ this.ram[0x02] |= 0x01;
+ // 跳回复位向量重新启动
+ this.cpu.reg_pc = (this.memmap[7][0x1FFD] << 8) | this.memmap[7][0x1FFC];
+ } else {
+ this.ram[io01_int_enable] |= 0x08;
+ this.shouldIrq = true;
+ }
}
-// if ((this._instCount - 6000) % 6000 === 0) {
-// this.clockRecords[4] ++;
-// this.ram[io01_int_enable] |= 0x08;
-// this.shouldIrq = true;
-// console.log(this.cpu.cycles - lastCycles);
-// lastCycles = this.cpu.cycles;
-// }
+
this.totalInsts++;
}
- document.title = (this.frameCounter);
+
+ //document.title = String(this.frameCounter);
this.frameCounter++;
};
return Wqx;
-})();
\ No newline at end of file
+})();
diff --git a/sw.js b/sw.js
new file mode 100644
index 0000000..c8937a2
--- /dev/null
+++ b/sw.js
@@ -0,0 +1,45 @@
+const CACHE_NAME = 'wqx-nc1020-v3.1.1';
+const ASSETS = [
+ './',
+ './index.html',
+ './manifest.json',
+ './nc1020.png',
+ './icon-192.png',
+ './icon-512.png',
+ './rom.zip',
+ './src/m65c02.js',
+ './src/wqx.js',
+ './src/keyinput.js',
+ 'https://cdnjs.cloudflare.com/ajax/libs/BrowserFS/2.0.0/browserfs.min.js'
+];
+
+self.addEventListener('install', (event) => {
+ self.skipWaiting();
+ event.waitUntil(
+ caches.open(CACHE_NAME).then((cache) => {
+ return cache.addAll(ASSETS);
+ })
+ );
+});
+
+self.addEventListener('activate', (event) => {
+ event.waitUntil(
+ caches.keys().then((cacheNames) => {
+ return Promise.all(
+ cacheNames.map((cacheName) => {
+ if (cacheName !== CACHE_NAME) {
+ return caches.delete(cacheName);
+ }
+ })
+ ).then(() => self.clients.claim());
+ })
+ );
+});
+
+self.addEventListener('fetch', (event) => {
+ event.respondWith(
+ caches.match(event.request).then((response) => {
+ return response || fetch(event.request);
+ })
+ );
+});