"use strict"; import { Platform, Base6502Platform, BaseMAMEPlatform, getOpcodeMetadata_6502, cpuStateToLongString_6502, getToolForFilename_6502, dumpStackToString } from "../baseplatform"; import { PLATFORMS, RAM, newAddressDecoder, padBytes, noise, setKeyboardFromMap, AnimationTimer, RasterVideo, Keys, makeKeycodeMap, dumpRAM } from "../emu"; import { hex, lpad, lzgmini } from "../util"; import { CodeAnalyzer_nes } from "../analysis"; import { SampleAudio } from "../audio"; declare var jsnes : any; const JSNES_PRESETS = [ {id:'ex0.asm', name:'Initialization (ASM)'}, {id:'ex1.asm', name:'Scrolling Demo (ASM)'}, {id:'ex2.asm', name:'Sprite Demo (ASM)'}, {id:'neslib1.c', name:'Text'}, {id:'neslib2.c', name:'Sprites'}, {id:'neslib3.c', name:'Cursor'}, {id:'neslib4.c', name:'Metasprites'}, {id:'neslib5.c', name:'RLE Unpack'}, {id:'music.c', name:'Music Player'}, {id:'siegegame.c', name:'Siege Game'}, {id:'shoot2.c', name:'Solarian Game'}, {id:'scrollrt.asm', name:'Split Screen Scroll (ASM)'}, {id:'road.asm', name:'3-D Road (ASM)'}, {id:'musicdemo.asm', name:'Famitone Demo (ASM)'}, ]; const NES_NESLIB_PRESETS = [ {id:'neslib1.c', name:'Text'}, {id:'neslib2.c', name:'Sprites'}, {id:'neslib3.c', name:'Cursor'}, {id:'neslib4.c', name:'Metasprites'}, {id:'chase/game.c', name:'Chase (example game)'}, ]; const NES_CONIO_PRESETS = [ {id:'ex0.asm', name:'ASM: Initialization'}, {id:'ex1.asm', name:'ASM: Scrolling Demo'}, {id:'hello.c', name:'C: Hello PPU'}, {id:'conio.c', name:'C: Hello Console I/O'}, {id:'siegegame.c', name:'C: Siege Game'}, ]; /// JSNES const JSNES_KEYCODE_MAP = makeKeycodeMap([ [Keys.VK_Z, 0, 0], [Keys.VK_X, 0, 1], [Keys.VK_2, 0, 2], [Keys.VK_1, 0, 3], [Keys.VK_UP, 0, 4], [Keys.VK_DOWN, 0, 5], [Keys.VK_LEFT, 0, 6], [Keys.VK_RIGHT, 0, 7], [Keys.VK_Q, 1, 0], [Keys.VK_E, 1, 1], [Keys.VK_4, 1, 2], [Keys.VK_3, 1, 3], [Keys.VK_W, 1, 4], [Keys.VK_S, 1, 5], [Keys.VK_A, 1, 6], [Keys.VK_D, 1, 7], ]); const _JSNESPlatform = function(mainElement) { var nes; var rom; var video, audio, timer; const audioFrequency = 44030; //44100 var frameindex = 0; var nsamples = 0; class JSNESPlatform extends Base6502Platform { debugPCDelta = 1; getPresets() { return JSNES_PRESETS; } start() { var self = this; video = new RasterVideo(mainElement,256,224); audio = new SampleAudio(audioFrequency); video.create(); var idata = video.getFrameData(); nes = new jsnes.NES({ onFrame: function(frameBuffer) { for (var i=0; iframe0; }); } getCPUState() { var c = nes.cpu.toJSON(); this.copy6502REGvars(c); return c; } // TODO don't need to save ROM? saveState() { //var s = $.extend(true, {}, nes); var s = nes.toJSON(); s.c = s.cpu; this.copy6502REGvars(s.c); s.b = s.cpu.mem = s.cpu.mem.slice(0); s.ppu.vramMem = s.ppu.vramMem.slice(0); s.ppu.spriteMem = s.ppu.spriteMem.slice(0); s.ctrl = this.saveControlsState(); return s; } loadState(state) { nes.fromJSON(state); //nes.cpu.fromJSON(state.cpu); //nes.mmap.fromJSON(state.mmap); //nes.ppu.fromJSON(state.ppu); nes.cpu.mem = state.cpu.mem.slice(0); nes.ppu.vramMem = state.ppu.vramMem.slice(0); nes.ppu.spriteMem = state.ppu.spriteMem.slice(0); this.loadControlsState(state.ctrl); //$.extend(nes, state); } saveControlsState() { return { c1: nes.controllers[1].state.slice(0), c2: nes.controllers[2].state.slice(0), }; } loadControlsState(state) { nes.controllers[1].state = state.c1; nes.controllers[2].state = state.c2; } readAddress(addr) { return nes.cpu.mem[addr] & 0xff; } copy6502REGvars(c) { c.T = 0; c.PC = c.REG_PC; c.A = c.REG_ACC; c.X = c.REG_X; c.Y = c.REG_Y; c.SP = c.REG_SP & 0xff; c.Z = c.F_ZERO; c.N = c.F_SIGN; c.V = c.F_OVERFLOW; c.D = c.F_DECIMAL; c.C = c.F_CARRY; c.I = c.F_INTERRUPT; c.R = 1; c.o = this.readAddress(c.PC+1); return c; } getDebugCategories() { return ['CPU','ZPRAM','Stack','PPU']; } getDebugInfo(category, state) { switch (category) { case 'CPU': return cpuStateToLongString_6502(state.c); case 'ZPRAM': return dumpRAM(state.b, 0x0, 0x100); case 'Stack': return dumpStackToString(this, state.b, 0x100, 0x1ff, 0x100+state.c.SP, 0x20); case 'PPU': return this.ppuStateToLongString(state.ppu, state.b); } } ppuStateToLongString(ppu, mem) { var s = ''; var PPUFLAGS = [ ["f_nmiOnVblank","NMI_ON_VBLANK"], ["f_spVisibility","SPRITES"], ["f_spClipping","CLIP_SPRITES"], ["f_dispType","MONOCHROME"], ["f_bgVisibility","BACKGROUND"], ["f_bgClipping","CLIP_BACKGROUND"], ]; for (var i=0; i