diff --git a/gba3/console.html b/gba3/console.html index 93af5e1..87a49b6 100644 --- a/gba3/console.html +++ b/gba3/console.html @@ -48,29 +48,25 @@ function screenshot() { function savestate() { gbaCon.pause(); var state = core.freeze(); - console.log(state); + console.log('saveState:', state); Serializer.serializePNG(Serializer.serialize(state), document.getElementById('screen'), function(url) { var img = document.getElementById('saveState'); img.setAttribute('src', url); }); }; -var globalState; -function savestateDirct() { - gbaCon.pause(); - var state = core.freeze(); - console.log(state); - globalState = Serializer.serialize(state) -} function loadState() { - if (globalState) { - Serializer.deserialize(globalState, function (state) { - console.log(state); + let image = document.getElementById('saveState'); + if (image) { + Serializer.deserializeCurrentPNG(image, function (state) { + console.log('loadState', state); core.defrost(state); + core.DEBUG('Loaded state'); }); } } function loadSavestate(state) { Serializer.deserializePNG(state, function (result) { + console.log('loadSavestate', state); core.defrost(result); core.DEBUG('Loaded state'); }); @@ -164,9 +160,8 @@ window.onload = function() { - - - + +
diff --git a/gba3/js/io.js b/gba3/js/io.js index 3a8135a..d3a8882 100644 --- a/gba3/js/io.js +++ b/gba3/js/io.js @@ -164,12 +164,10 @@ GameBoyAdvanceIO.prototype.freeze = function() { GameBoyAdvanceIO.prototype.defrost = function(frost) { this.registers = new Uint16Array(frost.registers); // Video registers don't serialize themselves - // for (var i = 0; i <= this.BLDY; i += 2) { - // this.store16(this.registers[i >> 1]); - // } - // for (var i = 0; i <= this.registers.length; i += 2 ) { - // this.store16(i, this.registers[i >> 1]); - // } + // 将背景和背景类似的layer数据写回 + for (var i = 0; i < this.registers.length; i += 2 ) { + this.store16(i, this.registers[i >> 1]); + } }; GameBoyAdvanceIO.prototype.load8 = function(offset) { diff --git a/gba3/js/util.js b/gba3/js/util.js index ab17699..6b64b3f 100644 --- a/gba3/js/util.js +++ b/gba3/js/util.js @@ -185,68 +185,70 @@ Serializer = { return canvas; }, deserializeCurrentPNG: function(image, callback) { - var canvas = document.createElement('canvas'); - canvas.setAttribute('height', image.height); - canvas.setAttribute('width', image.width); - var context = canvas.getContext('2d'); - context.drawImage(image, 0, 0); - var pixels = context.getImageData(0, 0, canvas.width, canvas.height); - var data = []; - for (var y = 0; y < canvas.height; ++y) { - for (var x = 0; x < canvas.width; ++x) { - if (!pixels.data[(x + y * canvas.width) * 4 + 3]) { - data.push(pixels.data[(x + y * canvas.width) * 4 + 0]); - data.push(pixels.data[(x + y * canvas.width) * 4 + 1]); - data.push(pixels.data[(x + y * canvas.width) * 4 + 2]); - } else { - var byte = 0; - byte |= pixels.data[(x + y * canvas.width) * 4 + 0] & 7; - byte |= (pixels.data[(x + y * canvas.width) * 4 + 1] & 7) << 3; - byte |= (pixels.data[(x + y * canvas.width) * 4 + 2] & 7) << 6; - data.push(byte); - } + var canvas = document.createElement('canvas'); + canvas.setAttribute('height', image.height); + canvas.setAttribute('width', image.width); + var context = canvas.getContext('2d'); + context.drawImage(image, 0, 0); + var pixels = context.getImageData(0, 0, canvas.width, canvas.height); + var data = []; + for (var y = 0; y < canvas.height; ++y) { + for (var x = 0; x < canvas.width; ++x) { + if (!pixels.data[(x + y * canvas.width) * 4 + 3]) { + data.push(pixels.data[(x + y * canvas.width) * 4 + 0]); + data.push(pixels.data[(x + y * canvas.width) * 4 + 1]); + data.push(pixels.data[(x + y * canvas.width) * 4 + 2]); + } else { + var byte = 0; + byte |= pixels.data[(x + y * canvas.width) * 4 + 0] & 7; + byte |= (pixels.data[(x + y * canvas.width) * 4 + 1] & 7) << 3; + byte |= (pixels.data[(x + y * canvas.width) * 4 + 2] & 7) << 6; + data.push(byte); } } - newBlob = new Blob(data.map(function (byte) { - var array = new Uint8Array(1); - array[0] = byte; - return array; - }), { type: Serializer.TYPE}); - Serializer.deserialize(newBlob, callback); + } + var newBlob = new Blob(data.map(function (byte) { + var array = new Uint8Array(1); + array[0] = byte; + return array; + }), { type: Serializer.TYPE}); + Serializer.deserialize(newBlob, callback); }, deserializePNG: function(blob, callback) { var reader = new FileReader(); reader.onload = function(dataImg) { var image = document.createElement('img'); image.setAttribute('src', dataImg.target.result); - var canvas = document.createElement('canvas'); - canvas.setAttribute('height', image.height); - canvas.setAttribute('width', image.width); - var context = canvas.getContext('2d'); - context.drawImage(image, 0, 0); - var pixels = context.getImageData(0, 0, canvas.width, canvas.height); - var data = []; - for (var y = 0; y < canvas.height; ++y) { - for (var x = 0; x < canvas.width; ++x) { - if (!pixels.data[(x + y * canvas.width) * 4 + 3]) { - data.push(pixels.data[(x + y * canvas.width) * 4 + 0]); - data.push(pixels.data[(x + y * canvas.width) * 4 + 1]); - data.push(pixels.data[(x + y * canvas.width) * 4 + 2]); - } else { - var byte = 0; - byte |= pixels.data[(x + y * canvas.width) * 4 + 0] & 7; - byte |= (pixels.data[(x + y * canvas.width) * 4 + 1] & 7) << 3; - byte |= (pixels.data[(x + y * canvas.width) * 4 + 2] & 7) << 6; - data.push(byte); + image.onload = function () { + var canvas = document.createElement('canvas'); + canvas.setAttribute('height', image.height); + canvas.setAttribute('width', image.width); + var context = canvas.getContext('2d'); + context.drawImage(image, 0, 0); + var pixels = context.getImageData(0, 0, canvas.width, canvas.height); + var data = []; + for (var y = 0; y < canvas.height; ++y) { + for (var x = 0; x < canvas.width; ++x) { + if (!pixels.data[(x + y * canvas.width) * 4 + 3]) { + data.push(pixels.data[(x + y * canvas.width) * 4 + 0]); + data.push(pixels.data[(x + y * canvas.width) * 4 + 1]); + data.push(pixels.data[(x + y * canvas.width) * 4 + 2]); + } else { + var byte = 0; + byte |= pixels.data[(x + y * canvas.width) * 4 + 0] & 7; + byte |= (pixels.data[(x + y * canvas.width) * 4 + 1] & 7) << 3; + byte |= (pixels.data[(x + y * canvas.width) * 4 + 2] & 7) << 6; + data.push(byte); + } } } + var newBlob = new Blob(data.map(function (byte) { + var array = new Uint8Array(1); + array[0] = byte; + return array; + }), { type: Serializer.TYPE}); + Serializer.deserialize(newBlob, callback); } - newBlob = new Blob(data.map(function (byte) { - var array = new Uint8Array(1); - array[0] = byte; - return array; - }), { type: Serializer.TYPE}); - Serializer.deserialize(newBlob, callback); } reader.readAsDataURL(blob); } diff --git a/gba3/js/video/software.js b/gba3/js/video/software.js index 12db26e..677d3ce 100644 --- a/gba3/js/video/software.js +++ b/gba3/js/video/software.js @@ -854,30 +854,109 @@ GameBoyAdvanceSoftwareRenderer.prototype.clearSubsets = function(mmu, regions) { }; GameBoyAdvanceSoftwareRenderer.prototype.freeze = function() { - console.log('GameBoyAdvanceSoftwareRenderer.freeze', this.bg, this.pixelData); + console.log('GameBoyAdvanceSoftwareRenderer.freeze', this); return { - pixelData: Serializer.prefix(this.pixelData.data.buffer), - width: this.pixelData.width, - height: this.pixelData.height, - scanline: { - color: Serializer.prefix(this.scanline.color.buffer), - stencil: Serializer.prefix(this.scanline.stencil.buffer) - }, - palette: JSON.stringify(this.palette) + palette: this.palette.freeze(), + // oam: this.oam.freeze(), + vram: this.vram.freeze(), }; }; GameBoyAdvanceSoftwareRenderer.prototype.defrost = function(f) { - this.pixelData = f.pixelData; - // let backing = new ImageData(new Uint8ClampedArray(f.pixelData), f.width, f.height); - // this.setBacking(backing); - // this.scanline = { - // color: new Uint16Array(f.scanline.color), - // stencil: new Uint8Array(f.scanline.stencil) - // }; - // this.palette = eval("("+f.palette+")"); + // 游戏人物 + this.palette.defrost(f.palette); + // this.oam.defrost(f.oam); + // 恢复子弹, 血条等数据的显示 + this.vram.defrost(f.vram); }; +// GameBoyAdvanceOAM.prototype.freeze = function() { +// return { +// buffer: Serializer.prefix(this.buffer.buffer), +// oam: Serializer.prefix(this.oam.buffer), +// } +// } +// +// GameBoyAdvanceOAM.prototype.defrost = function(frost) { +// this.buffer = new Uint16Array(frost.buffer); +// this.oam = new Uint16Array(frost.oam); +// } + +GameBoyAdvancePalette.prototype.freeze = function() { + return { + colors: this.colors, + adjustedColors: this.adjustedColors, + passthroughColors: this.passthroughColors + } +}; +GameBoyAdvancePalette.prototype.defrost = function(frost) { + this.colors = frost.colors; + this.adjustedColors = frost.adjustedColors; + this.passthroughColors = frost.passthroughColors; +}; + + +GameBoyAdvanceVRAM.prototype.freeze = function() { + return { + buffer: Serializer.prefix(this.buffer.buffer), + vram: Serializer.prefix(this.vram.buffer), + } +} + +GameBoyAdvanceVRAM.prototype.defrost = function(frost) { + this.buffer = new Uint16Array(frost.buffer); + this.vram = new Uint16Array(frost.vram); +} + +// GameBoyAdvanceOBJ.prototype.freeze = function() { +// return { +// cachedHeight: this.cachedHeight, +// cachedWidth: this.cachedWidth, +// disable: this.disable, +// doublesize: this.doublesize, +// hflip: this.hflip, +// index: this.index, +// mode: this.mode, +// mosaic: this.mosaic, +// multipalette: this.multipalette, +// palette: this.palette, +// priority: this.priority, +// scalerot: this.scalerot, +// scalerotOam: this.scalerotOam, +// scalerotParam: this.scalerotParam, +// shape: this.shape, +// size: this.size, +// tileBase: this.tileBase, +// vflip: this.vflip, +// x: this.x, +// y: this.y, +// } +// } +// +// GameBoyAdvanceOBJ.prototype.defrost = function(f) { +// this.cachedHeight = f.cachedHeight; +// this.cachedWidth = f.cachedWidth; +// this.disable = f.disable; +// this.doublesize = f.doublesize; +// this.hflip = f.hflip; +// this.index = f.index; +// this.mode = f.mode; +// this.mosaic = f.mosaic; +// this.multipalette = f.multipalette; +// this.palette = f.palette; +// this.priority = f.priority; +// this.scalerot = f.scalerot; +// this.scalerotOam = f.scalerotOam; +// this.scalerotParam = f.scalerotParam; +// this.shape = f.shape; +// this.size = f.size; +// this.tileBase = f.tileBase; +// this.vflip = f.vflip; +// this.x = f.x; +// this.y = f.y; +// } + + GameBoyAdvanceSoftwareRenderer.prototype.setBacking = function(backing) { this.pixelData = backing;