mirror of https://github.com/mgba-emu/mgba.git
Merge branch 'master' into medusa
This commit is contained in:
commit
e654c188f9
|
@ -7,8 +7,8 @@ os: linux
|
||||||
env:
|
env:
|
||||||
- DOCKER_TAG=ubuntu:xenial
|
- DOCKER_TAG=ubuntu:xenial
|
||||||
- DOCKER_TAG=ubuntu:bionic
|
- DOCKER_TAG=ubuntu:bionic
|
||||||
- DOCKER_TAG=ubuntu:cosmic
|
|
||||||
- DOCKER_TAG=ubuntu:disco
|
- DOCKER_TAG=ubuntu:disco
|
||||||
|
- DOCKER_TAG=ubuntu:eoan
|
||||||
- DOCKER_TAG=3ds
|
- DOCKER_TAG=3ds
|
||||||
- DOCKER_TAG=wii
|
- DOCKER_TAG=wii
|
||||||
- DOCKER_TAG=vita
|
- DOCKER_TAG=vita
|
||||||
|
|
58
CHANGES
58
CHANGES
|
@ -41,6 +41,7 @@ Features:
|
||||||
- Qt: Add export button for tile view (closes mgba.io/i/1507)
|
- Qt: Add export button for tile view (closes mgba.io/i/1507)
|
||||||
- Qt: Add recent game list clearing (closes mgba.io/i/1380)
|
- Qt: Add recent game list clearing (closes mgba.io/i/1380)
|
||||||
- GB: Yanking gamepak now supported
|
- GB: Yanking gamepak now supported
|
||||||
|
- Qt: Memory range dumping (closes mgba.io/i/1298)
|
||||||
Emulation fixes:
|
Emulation fixes:
|
||||||
- GBA: All IRQs have 7 cycle delay (fixes mgba.io/i/539, mgba.io/i/1208)
|
- GBA: All IRQs have 7 cycle delay (fixes mgba.io/i/539, mgba.io/i/1208)
|
||||||
- GBA: Reset now reloads multiboot ROMs
|
- GBA: Reset now reloads multiboot ROMs
|
||||||
|
@ -48,39 +49,21 @@ Emulation fixes:
|
||||||
- GB Video: Delay LYC STAT check (fixes mgba.io/i/1331)
|
- GB Video: Delay LYC STAT check (fixes mgba.io/i/1331)
|
||||||
- GB Video: Fix window being enabled mid-scanline (fixes mgba.io/i/1328)
|
- GB Video: Fix window being enabled mid-scanline (fixes mgba.io/i/1328)
|
||||||
- GB I/O: Filter IE top bits properly (fixes mgba.io/i/1329)
|
- GB I/O: Filter IE top bits properly (fixes mgba.io/i/1329)
|
||||||
- GBA Video: Fix wrapped sprite mosaic clamping (fixes mgba.io/i/1432)
|
|
||||||
- GBA Memory: Fix STM to VRAM (fixes mgba.io/i/1430)
|
|
||||||
- GB Audio: Only reset channel 3 sample in DMG mode
|
- GB Audio: Only reset channel 3 sample in DMG mode
|
||||||
- GB Audio: Sample inactive channels (fixes mgba.io/i/1455, mgba.io/i/1456)
|
- GB Audio: Sample inactive channels (fixes mgba.io/i/1455, mgba.io/i/1456)
|
||||||
- GB Video: Increment BCPS/OCPS even in mode 3 (fixes mgba.io/i/1462)
|
|
||||||
- GB Audio: Deschedule channel 3 when disabled (fixes mgba.io/i/1463)
|
|
||||||
- GB Audio: Deschedule channel 1 when disabled by sweep (fixes mgba.io/i/1467)
|
|
||||||
- GBA Memory: Fix STM/LDM to invalid VRAM
|
|
||||||
- GB: Fix savedata initialization (fixes mgba.io/i/1473, mgba.io/i/1478)
|
|
||||||
- GB Memory: Better emulate 0xFEA0 region on DMG, MGB and AGB
|
- GB Memory: Better emulate 0xFEA0 region on DMG, MGB and AGB
|
||||||
- GB Printer: Reset printer buffer index after printing
|
|
||||||
- GB Video: Fix mode 0 window edge case (fixes mgba.io/i/1519)
|
- GB Video: Fix mode 0 window edge case (fixes mgba.io/i/1519)
|
||||||
- GBA Audio: Fix channel 4 aliasing (fixes mgba.io/i/1265)
|
- GB Audio: Fix channel 4 volume (fixes mgba.io/i/1529)
|
||||||
- GB Audio: Improve channel 4 supersampling
|
|
||||||
Other fixes:
|
Other fixes:
|
||||||
- Qt: Fix some Qt display driver race conditions
|
- Qt: Fix some Qt display driver race conditions
|
||||||
- Core: Improved lockstep driver reliability (Le Hoang Quyen)
|
- Core: Improved lockstep driver reliability (Le Hoang Quyen)
|
||||||
- Switch: Fix threading-related crash on second launch
|
|
||||||
- Qt: Fix FPS target maxing out at 59.727 (fixes mgba.io/i/1421)
|
|
||||||
- Core: Fix crashes if core directories aren't set
|
|
||||||
- Qt: Fix menu bar staying hidden in full screen (fixes mgba.io/i/317)
|
- Qt: Fix menu bar staying hidden in full screen (fixes mgba.io/i/317)
|
||||||
- GB SIO: Fix lockstep failing games aren't reloaded
|
- GB SIO: Fix lockstep failing games aren't reloaded
|
||||||
- Core: Fix crash when exiting game with cheats loaded
|
|
||||||
- GBA Cheats: Fix PARv3 Thumb hooks
|
|
||||||
- mGUI: Fix crash if last loaded ROM directory disappears (fixes mgba.io/i/1466)
|
|
||||||
- Libretro: Fix crash changing allowing opposing directions (hhromic)
|
- Libretro: Fix crash changing allowing opposing directions (hhromic)
|
||||||
- Qt: Fix race conditions initializing GDB stub
|
|
||||||
- GBA: Set up GPIO mapping on null and ELF ROM regions (fixes mgba.io/i/1481)
|
|
||||||
- GBA Cheats: Fix value incrementing in CB slide codes (fixes mgba.io/i/1501)
|
- GBA Cheats: Fix value incrementing in CB slide codes (fixes mgba.io/i/1501)
|
||||||
- Qt: Only show emulator restart warning once per settings saving
|
- Qt: Only show emulator restart warning once per settings saving
|
||||||
- Qt: Improve cheat view UX
|
|
||||||
- GB: Fix SGB controller incrementing (fixes mgba.io/i/1104)
|
|
||||||
- FFmpeg: Drain recording buffers
|
- FFmpeg: Drain recording buffers
|
||||||
|
- Shaders: Fix gba-color shader resolution (fixes mgba.io/i/1435)
|
||||||
Misc:
|
Misc:
|
||||||
- GBA Savedata: EEPROM performance fixes
|
- GBA Savedata: EEPROM performance fixes
|
||||||
- GBA Savedata: Automatically map 1Mbit Flash files as 1Mbit Flash
|
- GBA Savedata: Automatically map 1Mbit Flash files as 1Mbit Flash
|
||||||
|
@ -100,16 +83,47 @@ Misc:
|
||||||
- Qt: Add native FPS button to settings view
|
- Qt: Add native FPS button to settings view
|
||||||
- Qt: Improve sync code
|
- Qt: Improve sync code
|
||||||
- Switch: Dynamic display resizing
|
- Switch: Dynamic display resizing
|
||||||
- Qt: Make mute menu option also toggle fast-forward mute (fixes mgba.io/i/1424)
|
|
||||||
- Vita: L2/R2 and L3/R3 can now be mapped on PSTV (fixes mgba.io/i/1292)
|
- Vita: L2/R2 and L3/R3 can now be mapped on PSTV (fixes mgba.io/i/1292)
|
||||||
- mGUI: Remember name and position of last loaded game
|
- mGUI: Remember name and position of last loaded game
|
||||||
- Core: Create game-related paths if they don't exist (fixes mgba.io/i/1446)
|
- Core: Create game-related paths if they don't exist (fixes mgba.io/i/1446)
|
||||||
- Qt: Add option to pause on minimizing window (closes mgba.io/i/1379)
|
- Qt: Add option to pause on minimizing window (closes mgba.io/i/1379)
|
||||||
- Switch: Support file associations
|
- Switch: Support file associations
|
||||||
- Qt: Show error message if file failed to load
|
|
||||||
- Qt: Scale pixel color values to full range (fixes mgba.io/i/1511)
|
- Qt: Scale pixel color values to full range (fixes mgba.io/i/1511)
|
||||||
- Qt, OpenGL: Disable integer scaling for dimensions that don't fit
|
- Qt, OpenGL: Disable integer scaling for dimensions that don't fit
|
||||||
- Feature: Switch from ImageMagick to FFmpeg for GIF generation
|
- Feature: Switch from ImageMagick to FFmpeg for GIF generation
|
||||||
|
- OpenGL: Only resize textures when needed
|
||||||
|
- GBA BIOS: Fix clobbered registers in CpuSet (fixes mgba.io/i/1531)
|
||||||
|
- Qt: Remove What's This icon from dialogs
|
||||||
|
|
||||||
|
0.7.3: (2019-09-15)
|
||||||
|
Emulation fixes:
|
||||||
|
- GB: Fix savedata initialization (fixes mgba.io/i/1473, mgba.io/i/1478)
|
||||||
|
- GB: Fix SGB controller incrementing (fixes mgba.io/i/1104)
|
||||||
|
- GB Audio: Improve channel 4 supersampling
|
||||||
|
- GB Printer: Reset printer buffer index after printing
|
||||||
|
- GB Audio: Deschedule channel 3 when disabled (fixes mgba.io/i/1463)
|
||||||
|
- GB Audio: Deschedule channel 1 when disabled by sweep (fixes mgba.io/i/1467)
|
||||||
|
- GB Video: Increment BCPS/OCPS even in mode 3 (fixes mgba.io/i/1462)
|
||||||
|
- GBA Memory: Fix STM to VRAM (fixes mgba.io/i/1430)
|
||||||
|
- GBA Memory: Fix STM/LDM to invalid VRAM
|
||||||
|
- GBA Video: Fix wrapped sprite mosaic clamping (fixes mgba.io/i/1432)
|
||||||
|
- GBA Audio: Fix channel 4 aliasing (fixes mgba.io/i/1265)
|
||||||
|
Other fixes:
|
||||||
|
- Core: Fix crashes if core directories aren't set
|
||||||
|
- Core: Fix crash when exiting game with cheats loaded
|
||||||
|
- GBA: Set up GPIO mapping on null and ELF ROM regions (fixes mgba.io/i/1481)
|
||||||
|
- GBA Cheats: Fix PARv3 Thumb hooks
|
||||||
|
- GBA Cheats: Fix value incrementing in CB slide codes (fixes mgba.io/i/1501)
|
||||||
|
- Qt: Fix FPS target maxing out at 59.727 (fixes mgba.io/i/1421)
|
||||||
|
- Qt: Cap audio buffer size to 8192 (fixes mgba.io/i/1433)
|
||||||
|
- Qt: Fix race conditions initializing GDB stub
|
||||||
|
- Qt: Improve cheat view UX
|
||||||
|
- Libretro: Fix crash changing allowing opposing directions (hhromic)
|
||||||
|
- mGUI: Fix crash if last loaded ROM directory disappears (fixes mgba.io/i/1466)
|
||||||
|
- Switch: Fix threading-related crash on second launch
|
||||||
|
Misc:
|
||||||
|
- Qt: Make mute menu option also toggle fast-forward mute (fixes mgba.io/i/1424)
|
||||||
|
- Qt: Show error message if file failed to load
|
||||||
|
|
||||||
0.7.2: (2019-05-25)
|
0.7.2: (2019-05-25)
|
||||||
Emulation fixes:
|
Emulation fixes:
|
||||||
|
|
|
@ -7,6 +7,8 @@ passes=1
|
||||||
[pass.0]
|
[pass.0]
|
||||||
fragmentShader=gba-color.fs
|
fragmentShader=gba-color.fs
|
||||||
blend=1
|
blend=1
|
||||||
|
width=-1
|
||||||
|
height=-1
|
||||||
|
|
||||||
[pass.0.uniform.darken_screen]
|
[pass.0.uniform.darken_screen]
|
||||||
type=float
|
type=float
|
||||||
|
|
|
@ -770,7 +770,7 @@ static int32_t _updateSquareChannel(struct GBAudioSquareChannel* ch) {
|
||||||
|
|
||||||
static int16_t _coalesceNoiseChannel(struct GBAudioNoiseChannel* ch) {
|
static int16_t _coalesceNoiseChannel(struct GBAudioNoiseChannel* ch) {
|
||||||
if (!ch->nSamples) {
|
if (!ch->nSamples) {
|
||||||
return ch->sample;
|
return ch->sample << 3;
|
||||||
}
|
}
|
||||||
// TODO keep track of timing
|
// TODO keep track of timing
|
||||||
int16_t sample = (ch->samples << 3) / ch->nSamples;
|
int16_t sample = (ch->samples << 3) / ch->nSamples;
|
||||||
|
|
|
@ -45,7 +45,7 @@ static const struct mCoreChannelInfo _GBAudioChannels[] = {
|
||||||
|
|
||||||
static const struct mCoreMemoryBlock _GBMemoryBlocks[] = {
|
static const struct mCoreMemoryBlock _GBMemoryBlocks[] = {
|
||||||
{ -1, "mem", "All", "All", 0, 0x10000, 0x10000, mCORE_MEMORY_VIRTUAL },
|
{ -1, "mem", "All", "All", 0, 0x10000, 0x10000, mCORE_MEMORY_VIRTUAL },
|
||||||
{ GB_REGION_CART_BANK0, "cart0", "ROM Bank", "Game Pak (32kiB)", GB_BASE_CART_BANK0, GB_SIZE_CART_BANK0 * 2, 0x800000, mCORE_MEMORY_READ | mCORE_MEMORY_MAPPED, 511 },
|
{ GB_REGION_CART_BANK0, "cart0", "ROM Bank", "Game Pak (32kiB)", GB_BASE_CART_BANK0, GB_BASE_CART_BANK0 + GB_SIZE_CART_BANK0 * 2, 0x800000, mCORE_MEMORY_READ | mCORE_MEMORY_MAPPED, 511, GB_BASE_CART_BANK0 + GB_SIZE_CART_BANK0 },
|
||||||
{ GB_REGION_VRAM, "vram", "VRAM", "Video RAM (8kiB)", GB_BASE_VRAM, GB_BASE_VRAM + GB_SIZE_VRAM, GB_SIZE_VRAM, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED },
|
{ GB_REGION_VRAM, "vram", "VRAM", "Video RAM (8kiB)", GB_BASE_VRAM, GB_BASE_VRAM + GB_SIZE_VRAM, GB_SIZE_VRAM, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED },
|
||||||
{ GB_REGION_EXTERNAL_RAM, "sram", "SRAM", "External RAM (8kiB)", GB_BASE_EXTERNAL_RAM, GB_BASE_EXTERNAL_RAM + GB_SIZE_EXTERNAL_RAM, GB_SIZE_EXTERNAL_RAM * 4, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED, 3 },
|
{ GB_REGION_EXTERNAL_RAM, "sram", "SRAM", "External RAM (8kiB)", GB_BASE_EXTERNAL_RAM, GB_BASE_EXTERNAL_RAM + GB_SIZE_EXTERNAL_RAM, GB_SIZE_EXTERNAL_RAM * 4, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED, 3 },
|
||||||
{ GB_REGION_WORKING_RAM_BANK0, "wram", "WRAM", "Working RAM (8kiB)", GB_BASE_WORKING_RAM_BANK0, GB_BASE_WORKING_RAM_BANK0 + GB_SIZE_WORKING_RAM_BANK0 * 2 , GB_SIZE_WORKING_RAM_BANK0 * 2, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED },
|
{ GB_REGION_WORKING_RAM_BANK0, "wram", "WRAM", "Working RAM (8kiB)", GB_BASE_WORKING_RAM_BANK0, GB_BASE_WORKING_RAM_BANK0 + GB_SIZE_WORKING_RAM_BANK0 * 2 , GB_SIZE_WORKING_RAM_BANK0 * 2, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED },
|
||||||
|
@ -56,10 +56,10 @@ static const struct mCoreMemoryBlock _GBMemoryBlocks[] = {
|
||||||
|
|
||||||
static const struct mCoreMemoryBlock _GBCMemoryBlocks[] = {
|
static const struct mCoreMemoryBlock _GBCMemoryBlocks[] = {
|
||||||
{ -1, "mem", "All", "All", 0, 0x10000, 0x10000, mCORE_MEMORY_VIRTUAL },
|
{ -1, "mem", "All", "All", 0, 0x10000, 0x10000, mCORE_MEMORY_VIRTUAL },
|
||||||
{ GB_REGION_CART_BANK0, "cart0", "ROM Bank", "Game Pak (32kiB)", GB_BASE_CART_BANK0, GB_SIZE_CART_BANK0 * 2, 0x800000, mCORE_MEMORY_READ | mCORE_MEMORY_MAPPED, 511 },
|
{ GB_REGION_CART_BANK0, "cart0", "ROM Bank", "Game Pak (32kiB)", GB_BASE_CART_BANK0, GB_BASE_CART_BANK0 + GB_SIZE_CART_BANK0 * 2, 0x800000, mCORE_MEMORY_READ | mCORE_MEMORY_MAPPED, 511, GB_BASE_CART_BANK0 + GB_SIZE_CART_BANK0 },
|
||||||
{ GB_REGION_VRAM, "vram", "VRAM", "Video RAM (8kiB)", GB_BASE_VRAM, GB_BASE_VRAM + GB_SIZE_VRAM, GB_SIZE_VRAM * 2, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED, 1 },
|
{ GB_REGION_VRAM, "vram", "VRAM", "Video RAM (8kiB)", GB_BASE_VRAM, GB_BASE_VRAM + GB_SIZE_VRAM, GB_SIZE_VRAM * 2, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED, 1 },
|
||||||
{ GB_REGION_EXTERNAL_RAM, "sram", "SRAM", "External RAM (8kiB)", GB_BASE_EXTERNAL_RAM, GB_BASE_EXTERNAL_RAM + GB_SIZE_EXTERNAL_RAM, GB_SIZE_EXTERNAL_RAM * 4, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED, 3 },
|
{ GB_REGION_EXTERNAL_RAM, "sram", "SRAM", "External RAM (8kiB)", GB_BASE_EXTERNAL_RAM, GB_BASE_EXTERNAL_RAM + GB_SIZE_EXTERNAL_RAM, GB_SIZE_EXTERNAL_RAM * 4, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED, 3 },
|
||||||
{ GB_REGION_WORKING_RAM_BANK0, "wram", "WRAM", "Working RAM (8kiB)", GB_BASE_WORKING_RAM_BANK0, GB_BASE_WORKING_RAM_BANK0 + GB_SIZE_WORKING_RAM_BANK0 * 2, GB_SIZE_WORKING_RAM_BANK0 * 8, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED, 7 },
|
{ GB_REGION_WORKING_RAM_BANK0, "wram", "WRAM", "Working RAM (8kiB)", GB_BASE_WORKING_RAM_BANK0, GB_BASE_WORKING_RAM_BANK0 + GB_SIZE_WORKING_RAM_BANK0 * 2, GB_SIZE_WORKING_RAM_BANK0 * 8, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED, 7, GB_BASE_WORKING_RAM_BANK0 + GB_SIZE_WORKING_RAM_BANK0 },
|
||||||
{ GB_BASE_OAM, "oam", "OAM", "OBJ Attribute Memory", GB_BASE_OAM, GB_BASE_OAM + GB_SIZE_OAM, GB_SIZE_OAM, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED },
|
{ GB_BASE_OAM, "oam", "OAM", "OBJ Attribute Memory", GB_BASE_OAM, GB_BASE_OAM + GB_SIZE_OAM, GB_SIZE_OAM, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED },
|
||||||
{ GB_BASE_IO, "io", "MMIO", "Memory-Mapped I/O", GB_BASE_IO, GB_BASE_IO + GB_SIZE_IO, GB_SIZE_IO, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED },
|
{ GB_BASE_IO, "io", "MMIO", "Memory-Mapped I/O", GB_BASE_IO, GB_BASE_IO + GB_SIZE_IO, GB_SIZE_IO, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED },
|
||||||
{ GB_BASE_HRAM, "hram", "HRAM", "High RAM", GB_BASE_HRAM, GB_BASE_HRAM + GB_SIZE_HRAM, GB_SIZE_HRAM, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED },
|
{ GB_BASE_HRAM, "hram", "HRAM", "High RAM", GB_BASE_HRAM, GB_BASE_HRAM + GB_SIZE_HRAM, GB_SIZE_HRAM, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED },
|
||||||
|
|
|
@ -6,7 +6,7 @@ const uint8_t hleBios[SIZE_BIOS] = {
|
||||||
0x06, 0x00, 0x00, 0xea, 0xfe, 0xff, 0xff, 0xea, 0x0b, 0x00, 0x00, 0xea,
|
0x06, 0x00, 0x00, 0xea, 0xfe, 0xff, 0xff, 0xea, 0x0b, 0x00, 0x00, 0xea,
|
||||||
0xfe, 0xff, 0xff, 0xea, 0xfe, 0xff, 0xff, 0xea, 0x00, 0x00, 0xa0, 0xe1,
|
0xfe, 0xff, 0xff, 0xea, 0xfe, 0xff, 0xff, 0xea, 0x00, 0x00, 0xa0, 0xe1,
|
||||||
0x2c, 0x00, 0x00, 0xea, 0xfe, 0xff, 0xff, 0xea, 0x02, 0x03, 0xa0, 0xe3,
|
0x2c, 0x00, 0x00, 0xea, 0xfe, 0xff, 0xff, 0xea, 0x02, 0x03, 0xa0, 0xe3,
|
||||||
0x03, 0x10, 0xd0, 0xe5, 0xea, 0x00, 0x51, 0xe3, 0xec, 0x01, 0x9f, 0x15,
|
0x03, 0x10, 0xd0, 0xe5, 0xea, 0x00, 0x51, 0xe3, 0xf8, 0x01, 0x9f, 0x15,
|
||||||
0x10, 0xff, 0x2f, 0xe1, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x29, 0xe1,
|
0x10, 0xff, 0x2f, 0xe1, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x29, 0xe1,
|
||||||
0x00, 0x00, 0x5d, 0xe3, 0x01, 0xd3, 0xa0, 0x03, 0x20, 0xd0, 0x4d, 0x02,
|
0x00, 0x00, 0x5d, 0xe3, 0x01, 0xd3, 0xa0, 0x03, 0x20, 0xd0, 0x4d, 0x02,
|
||||||
0x00, 0x58, 0x2d, 0xe9, 0x02, 0xb0, 0x5e, 0xe5, 0x9c, 0xc0, 0xa0, 0xe3,
|
0x00, 0x58, 0x2d, 0xe9, 0x02, 0xb0, 0x5e, 0xe5, 0x9c, 0xc0, 0xa0, 0xe3,
|
||||||
|
@ -20,7 +20,7 @@ const uint8_t hleBios[SIZE_BIOS] = {
|
||||||
0x00, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00,
|
0x00, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00,
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x01, 0x00, 0x00,
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x01, 0x00, 0x00,
|
||||||
0xc8, 0x01, 0x00, 0x00, 0x0f, 0x50, 0x2d, 0xe9, 0x01, 0x03, 0xa0, 0xe3,
|
0xd4, 0x01, 0x00, 0x00, 0x0f, 0x50, 0x2d, 0xe9, 0x01, 0x03, 0xa0, 0xe3,
|
||||||
0x00, 0xe0, 0x8f, 0xe2, 0x04, 0xf0, 0x10, 0xe5, 0x0f, 0x50, 0xbd, 0xe8,
|
0x00, 0xe0, 0x8f, 0xe2, 0x04, 0xf0, 0x10, 0xe5, 0x0f, 0x50, 0xbd, 0xe8,
|
||||||
0x04, 0xf0, 0x5e, 0xe2, 0x00, 0x00, 0x00, 0x00, 0x02, 0xc0, 0x5e, 0xe5,
|
0x04, 0xf0, 0x5e, 0xe2, 0x00, 0x00, 0x00, 0x00, 0x02, 0xc0, 0x5e, 0xe5,
|
||||||
0x01, 0x00, 0xa0, 0xe3, 0x01, 0x10, 0xa0, 0xe3, 0x0c, 0x40, 0x2d, 0xe9,
|
0x01, 0x00, 0xa0, 0xe3, 0x01, 0x10, 0xa0, 0xe3, 0x0c, 0x40, 0x2d, 0xe9,
|
||||||
|
@ -29,18 +29,19 @@ const uint8_t hleBios[SIZE_BIOS] = {
|
||||||
0x01, 0x30, 0xc3, 0xe1, 0xb8, 0x30, 0x4c, 0xe1, 0x01, 0x03, 0xcc, 0xe5,
|
0x01, 0x30, 0xc3, 0xe1, 0xb8, 0x30, 0x4c, 0xe1, 0x01, 0x03, 0xcc, 0xe5,
|
||||||
0x08, 0x02, 0xcc, 0xe5, 0xb8, 0x30, 0x5c, 0xe1, 0x01, 0x30, 0x13, 0xe0,
|
0x08, 0x02, 0xcc, 0xe5, 0xb8, 0x30, 0x5c, 0xe1, 0x01, 0x30, 0x13, 0xe0,
|
||||||
0x01, 0x30, 0x23, 0x10, 0xb8, 0x30, 0x4c, 0x11, 0x08, 0x22, 0xcc, 0xe5,
|
0x01, 0x30, 0x23, 0x10, 0xb8, 0x30, 0x4c, 0x11, 0x08, 0x22, 0xcc, 0xe5,
|
||||||
0xf7, 0xff, 0xff, 0x0a, 0x0c, 0x80, 0xbd, 0xe8, 0x00, 0x40, 0x2d, 0xe9,
|
0xf7, 0xff, 0xff, 0x0a, 0x0c, 0x80, 0xbd, 0xe8, 0x30, 0x40, 0x2d, 0xe9,
|
||||||
0x02, 0x36, 0xa0, 0xe1, 0x01, 0x04, 0x12, 0xe3, 0x0f, 0x00, 0x00, 0x0a,
|
0x02, 0x46, 0xa0, 0xe1, 0x00, 0xc0, 0xa0, 0xe1, 0x01, 0x50, 0xa0, 0xe1,
|
||||||
0x01, 0x03, 0x12, 0xe3, 0x05, 0x00, 0x00, 0x0a, 0x23, 0x35, 0x81, 0xe0,
|
0x01, 0x04, 0x12, 0xe3, 0x0f, 0x00, 0x00, 0x0a, 0x01, 0x03, 0x12, 0xe3,
|
||||||
0x04, 0x00, 0xb0, 0xe8, 0x03, 0x00, 0x51, 0xe1, 0x04, 0x00, 0xa1, 0xb8,
|
0x05, 0x00, 0x00, 0x0a, 0x24, 0x45, 0x85, 0xe0, 0x08, 0x00, 0xbc, 0xe8,
|
||||||
0xfc, 0xff, 0xff, 0xba, 0x14, 0x00, 0x00, 0xea, 0x01, 0x00, 0xc0, 0xe3,
|
0x04, 0x00, 0x55, 0xe1, 0x08, 0x00, 0xa5, 0xb8, 0xfc, 0xff, 0xff, 0xba,
|
||||||
0x01, 0x10, 0xc1, 0xe3, 0xa3, 0x35, 0x81, 0xe0, 0xb0, 0x20, 0xd0, 0xe1,
|
0x14, 0x00, 0x00, 0xea, 0x01, 0xc0, 0xcc, 0xe3, 0x01, 0x50, 0xc5, 0xe3,
|
||||||
0x03, 0x00, 0x51, 0xe1, 0xb2, 0x20, 0xc1, 0xb0, 0xfc, 0xff, 0xff, 0xba,
|
0xa4, 0x45, 0x85, 0xe0, 0xb0, 0x30, 0xdc, 0xe1, 0x04, 0x00, 0x55, 0xe1,
|
||||||
0x0c, 0x00, 0x00, 0xea, 0x01, 0x03, 0x12, 0xe3, 0x05, 0x00, 0x00, 0x0a,
|
0xb2, 0x30, 0xc5, 0xb0, 0xfc, 0xff, 0xff, 0xba, 0x0c, 0x00, 0x00, 0xea,
|
||||||
0x23, 0x35, 0x81, 0xe0, 0x03, 0x00, 0x51, 0xe1, 0x04, 0x00, 0xb0, 0xb8,
|
0x01, 0x03, 0x12, 0xe3, 0x05, 0x00, 0x00, 0x0a, 0x24, 0x45, 0x85, 0xe0,
|
||||||
0x04, 0x00, 0xa1, 0xb8, 0xfb, 0xff, 0xff, 0xba, 0x04, 0x00, 0x00, 0xea,
|
0x04, 0x00, 0x55, 0xe1, 0x08, 0x00, 0xbc, 0xb8, 0x08, 0x00, 0xa5, 0xb8,
|
||||||
0xa3, 0x35, 0x81, 0xe0, 0x03, 0x00, 0x51, 0xe1, 0xb2, 0x20, 0xd0, 0xb0,
|
0xfb, 0xff, 0xff, 0xba, 0x04, 0x00, 0x00, 0xea, 0xa4, 0x45, 0x85, 0xe0,
|
||||||
0xb2, 0x20, 0xc1, 0xb0, 0xfb, 0xff, 0xff, 0xba, 0x00, 0x80, 0xbd, 0xe8,
|
0x04, 0x00, 0x55, 0xe1, 0xb2, 0x30, 0xdc, 0xb0, 0xb2, 0x30, 0xc5, 0xb0,
|
||||||
|
0xfb, 0xff, 0xff, 0xba, 0x17, 0x3e, 0xa0, 0xe3, 0x30, 0x80, 0xbd, 0xe8,
|
||||||
0xf0, 0x47, 0x2d, 0xe9, 0x01, 0x04, 0x12, 0xe3, 0x02, 0x36, 0xa0, 0xe1,
|
0xf0, 0x47, 0x2d, 0xe9, 0x01, 0x04, 0x12, 0xe3, 0x02, 0x36, 0xa0, 0xe1,
|
||||||
0x23, 0x25, 0x81, 0xe0, 0x0b, 0x00, 0x00, 0x0a, 0x00, 0x30, 0x90, 0xe5,
|
0x23, 0x25, 0x81, 0xe0, 0x0b, 0x00, 0x00, 0x0a, 0x00, 0x30, 0x90, 0xe5,
|
||||||
0x03, 0x40, 0xa0, 0xe1, 0x03, 0x50, 0xa0, 0xe1, 0x03, 0x60, 0xa0, 0xe1,
|
0x03, 0x40, 0xa0, 0xe1, 0x03, 0x50, 0xa0, 0xe1, 0x03, 0x60, 0xa0, 0xe1,
|
||||||
|
|
|
@ -15,4 +15,4 @@ hle-bios.c: hle-bios.bin
|
||||||
echo >> $@
|
echo >> $@
|
||||||
echo '#include <mgba/internal/gba/memory.h>' >> $@
|
echo '#include <mgba/internal/gba/memory.h>' >> $@
|
||||||
echo >> $@
|
echo >> $@
|
||||||
xxd -i $< | sed -e 's/unsigned char hle_bios_bin\[\]/const uint8_t hleBios[SIZE_BIOS]/' | grep -v hle_bios_bin_len >> $@
|
xxd -i $< | sed -e 's/unsigned char hle_bios_bin\[\]/const uint8_t hleBios[SIZE_BIOS]/' -e 's/^ \+/\t/' | grep -v hle_bios_bin_len >> $@
|
||||||
|
|
|
@ -65,7 +65,7 @@ swiTable:
|
||||||
.word ArcTan2
|
.word ArcTan2
|
||||||
.word CpuSet
|
.word CpuSet
|
||||||
.word CpuFastSet
|
.word CpuFastSet
|
||||||
# ... The rest of this table isn't needed if the rest aren't implemented
|
@ ... The rest of this table isn't needed if the rest aren't implemented
|
||||||
|
|
||||||
irqBase:
|
irqBase:
|
||||||
stmfd sp!, {r0-r3, r12, lr}
|
stmfd sp!, {r0-r3, r12, lr}
|
||||||
|
@ -83,7 +83,7 @@ mov r1, #1
|
||||||
IntrWait:
|
IntrWait:
|
||||||
stmfd sp!, {r2-r3, lr}
|
stmfd sp!, {r2-r3, lr}
|
||||||
mov r12, #0x04000000
|
mov r12, #0x04000000
|
||||||
# See if we want to return immediately
|
@ See if we want to return immediately
|
||||||
cmp r0, #0
|
cmp r0, #0
|
||||||
mov r0, #0
|
mov r0, #0
|
||||||
mov r2, #1
|
mov r2, #1
|
||||||
|
@ -91,11 +91,11 @@ beq 1f
|
||||||
ldrh r3, [r12, #-8]
|
ldrh r3, [r12, #-8]
|
||||||
bic r3, r1
|
bic r3, r1
|
||||||
strh r3, [r12, #-8]
|
strh r3, [r12, #-8]
|
||||||
# Halt
|
@ Halt
|
||||||
0:
|
0:
|
||||||
strb r0, [r12, #0x301]
|
strb r0, [r12, #0x301]
|
||||||
1:
|
1:
|
||||||
# Check which interrupts were acknowledged
|
@ Check which interrupts were acknowledged
|
||||||
strb r0, [r12, #0x208]
|
strb r0, [r12, #0x208]
|
||||||
ldrh r3, [r12, #-8]
|
ldrh r3, [r12, #-8]
|
||||||
ands r3, r1
|
ands r3, r1
|
||||||
|
@ -106,54 +106,57 @@ beq 0b
|
||||||
ldmfd sp!, {r2-r3, pc}
|
ldmfd sp!, {r2-r3, pc}
|
||||||
|
|
||||||
CpuSet:
|
CpuSet:
|
||||||
stmfd sp!, {lr}
|
stmfd sp!, {r4, r5, lr}
|
||||||
mov r3, r2, lsl #12
|
mov r4, r2, lsl #12
|
||||||
|
mov r12, r0
|
||||||
|
mov r5, r1
|
||||||
tst r2, #0x01000000
|
tst r2, #0x01000000
|
||||||
beq 0f
|
beq 0f
|
||||||
# Fill
|
@ Fill
|
||||||
tst r2, #0x04000000
|
tst r2, #0x04000000
|
||||||
beq 1f
|
beq 1f
|
||||||
# Word
|
@ Word
|
||||||
add r3, r1, r3, lsr #10
|
add r4, r5, r4, lsr #10
|
||||||
ldmia r0!, {r2}
|
ldmia r12!, {r3}
|
||||||
2:
|
2:
|
||||||
cmp r1, r3
|
cmp r5, r4
|
||||||
stmltia r1!, {r2}
|
stmltia r5!, {r3}
|
||||||
blt 2b
|
blt 2b
|
||||||
b 3f
|
b 3f
|
||||||
# Halfword
|
@ Halfword
|
||||||
1:
|
1:
|
||||||
bic r0, #1
|
bic r12, #1
|
||||||
bic r1, #1
|
bic r5, #1
|
||||||
add r3, r1, r3, lsr #11
|
add r4, r5, r4, lsr #11
|
||||||
ldrh r2, [r0]
|
ldrh r3, [r12]
|
||||||
2:
|
2:
|
||||||
cmp r1, r3
|
cmp r5, r4
|
||||||
strlth r2, [r1], #2
|
strlth r3, [r5], #2
|
||||||
blt 2b
|
blt 2b
|
||||||
b 3f
|
b 3f
|
||||||
# Copy
|
@ Copy
|
||||||
0:
|
0:
|
||||||
tst r2, #0x04000000
|
tst r2, #0x04000000
|
||||||
beq 1f
|
beq 1f
|
||||||
# Word
|
@ Word
|
||||||
add r3, r1, r3, lsr #10
|
add r4, r5, r4, lsr #10
|
||||||
2:
|
2:
|
||||||
cmp r1, r3
|
cmp r5, r4
|
||||||
ldmltia r0!, {r2}
|
ldmltia r12!, {r3}
|
||||||
stmltia r1!, {r2}
|
stmltia r5!, {r3}
|
||||||
blt 2b
|
blt 2b
|
||||||
b 3f
|
b 3f
|
||||||
# Halfword
|
@ Halfword
|
||||||
1:
|
1:
|
||||||
add r3, r1, r3, lsr #11
|
add r4, r5, r4, lsr #11
|
||||||
2:
|
2:
|
||||||
cmp r1, r3
|
cmp r5, r4
|
||||||
ldrlth r2, [r0], #2
|
ldrlth r3, [r12], #2
|
||||||
strlth r2, [r1], #2
|
strlth r3, [r5], #2
|
||||||
blt 2b
|
blt 2b
|
||||||
3:
|
3:
|
||||||
ldmfd sp!, {pc}
|
mov r3, #0x170 @ Match official BIOS's clobbered r3
|
||||||
|
ldmfd sp!, {r4, r5, pc}
|
||||||
|
|
||||||
CpuFastSet:
|
CpuFastSet:
|
||||||
stmfd sp!, {r4-r10, lr}
|
stmfd sp!, {r4-r10, lr}
|
||||||
|
@ -161,7 +164,7 @@ tst r2, #0x01000000
|
||||||
mov r3, r2, lsl #12
|
mov r3, r2, lsl #12
|
||||||
add r2, r1, r3, lsr #10
|
add r2, r1, r3, lsr #10
|
||||||
beq 0f
|
beq 0f
|
||||||
# Fill
|
@ Fill
|
||||||
ldr r3, [r0]
|
ldr r3, [r0]
|
||||||
mov r4, r3
|
mov r4, r3
|
||||||
mov r5, r3
|
mov r5, r3
|
||||||
|
@ -175,7 +178,7 @@ cmp r1, r2
|
||||||
stmltia r1!, {r3-r10}
|
stmltia r1!, {r3-r10}
|
||||||
blt 1b
|
blt 1b
|
||||||
b 2f
|
b 2f
|
||||||
# Copy
|
@ Copy
|
||||||
0:
|
0:
|
||||||
cmp r1, r2
|
cmp r1, r2
|
||||||
ldmltia r0!, {r3-r10}
|
ldmltia r0!, {r3-r10}
|
||||||
|
|
|
@ -178,6 +178,15 @@ static void mGLES2ContextSetDimensions(struct VideoBackend* v, unsigned width, u
|
||||||
#else
|
#else
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
size_t n;
|
||||||
|
for (n = 0; n < context->nShaders; ++n) {
|
||||||
|
if (context->shaders[n].width < 0 || context->shaders[n].height < 0) {
|
||||||
|
context->shaders[n].dirty = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
context->initialShader.dirty = true;
|
||||||
|
context->interframeShader.dirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mGLES2ContextDeinit(struct VideoBackend* v) {
|
static void mGLES2ContextDeinit(struct VideoBackend* v) {
|
||||||
|
@ -191,6 +200,7 @@ static void mGLES2ContextDeinit(struct VideoBackend* v) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mGLES2ContextResized(struct VideoBackend* v, unsigned w, unsigned h) {
|
static void mGLES2ContextResized(struct VideoBackend* v, unsigned w, unsigned h) {
|
||||||
|
struct mGLES2Context* context = (struct mGLES2Context*) v;
|
||||||
unsigned drawW = w;
|
unsigned drawW = w;
|
||||||
unsigned drawH = h;
|
unsigned drawH = h;
|
||||||
if (v->lockAspectRatio) {
|
if (v->lockAspectRatio) {
|
||||||
|
@ -208,6 +218,12 @@ static void mGLES2ContextResized(struct VideoBackend* v, unsigned w, unsigned h)
|
||||||
drawH -= drawH % v->height;
|
drawH -= drawH % v->height;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
size_t n;
|
||||||
|
for (n = 0; n < context->nShaders; ++n) {
|
||||||
|
if (context->shaders[n].width == 0 || context->shaders[n].height == 0) {
|
||||||
|
context->shaders[n].dirty = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||||
glViewport((w - drawW) / 2, (h - drawH) / 2, drawW, drawH);
|
glViewport((w - drawW) / 2, (h - drawH) / 2, drawW, drawH);
|
||||||
}
|
}
|
||||||
|
@ -221,8 +237,6 @@ static void mGLES2ContextClear(struct VideoBackend* v) {
|
||||||
|
|
||||||
void _drawShader(struct mGLES2Context* context, struct mGLES2Shader* shader) {
|
void _drawShader(struct mGLES2Context* context, struct mGLES2Shader* shader) {
|
||||||
GLint viewport[4];
|
GLint viewport[4];
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, shader->fbo);
|
|
||||||
|
|
||||||
glGetIntegerv(GL_VIEWPORT, viewport);
|
glGetIntegerv(GL_VIEWPORT, viewport);
|
||||||
int drawW = shader->width;
|
int drawW = shader->width;
|
||||||
int drawH = shader->height;
|
int drawH = shader->height;
|
||||||
|
@ -246,6 +260,19 @@ void _drawShader(struct mGLES2Context* context, struct mGLES2Shader* shader) {
|
||||||
drawW -= drawW % context->d.width;
|
drawW -= drawW % context->d.width;
|
||||||
drawH -= drawH % context->d.height;
|
drawH -= drawH % context->d.height;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (shader->dirty) {
|
||||||
|
if (shader->tex && (shader->width <= 0 || shader->height <= 0)) {
|
||||||
|
GLint oldTex;
|
||||||
|
glGetIntegerv(GL_TEXTURE_BINDING_2D, &oldTex);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, shader->tex);
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, drawW, drawH, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, oldTex);
|
||||||
|
}
|
||||||
|
shader->dirty = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, shader->fbo);
|
||||||
glViewport(padW, padH, drawW, drawH);
|
glViewport(padW, padH, drawW, drawH);
|
||||||
if (shader->blend) {
|
if (shader->blend) {
|
||||||
glEnable(GL_BLEND);
|
glEnable(GL_BLEND);
|
||||||
|
@ -256,14 +283,6 @@ void _drawShader(struct mGLES2Context* context, struct mGLES2Shader* shader) {
|
||||||
glClear(GL_COLOR_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (shader->tex && (shader->width <= 0 || shader->height <= 0)) {
|
|
||||||
GLint oldTex;
|
|
||||||
glGetIntegerv(GL_TEXTURE_BINDING_2D, &oldTex);
|
|
||||||
glBindTexture(GL_TEXTURE_2D, shader->tex);
|
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, drawW, drawH, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
|
|
||||||
glBindTexture(GL_TEXTURE_2D, oldTex);
|
|
||||||
}
|
|
||||||
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, shader->filter ? GL_LINEAR : GL_NEAREST);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, shader->filter ? GL_LINEAR : GL_NEAREST);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, shader->filter ? GL_LINEAR : GL_NEAREST);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, shader->filter ? GL_LINEAR : GL_NEAREST);
|
||||||
glUseProgram(shader->program);
|
glUseProgram(shader->program);
|
||||||
|
@ -340,6 +359,7 @@ void mGLES2ContextDrawFrame(struct VideoBackend* v) {
|
||||||
glGetIntegerv(GL_VIEWPORT, viewport);
|
glGetIntegerv(GL_VIEWPORT, viewport);
|
||||||
|
|
||||||
context->finalShader.filter = v->filter;
|
context->finalShader.filter = v->filter;
|
||||||
|
context->finalShader.dirty = true;
|
||||||
_drawShader(context, &context->initialShader);
|
_drawShader(context, &context->initialShader);
|
||||||
if (v->interframeBlending) {
|
if (v->interframeBlending) {
|
||||||
context->interframeShader.blend = true;
|
context->interframeShader.blend = true;
|
||||||
|
@ -404,6 +424,7 @@ void mGLES2ShaderInit(struct mGLES2Shader* shader, const char* vs, const char* f
|
||||||
shader->integerScaling = integerScaling;
|
shader->integerScaling = integerScaling;
|
||||||
shader->filter = false;
|
shader->filter = false;
|
||||||
shader->blend = false;
|
shader->blend = false;
|
||||||
|
shader->dirty = true;
|
||||||
shader->uniforms = uniforms;
|
shader->uniforms = uniforms;
|
||||||
shader->nUniforms = nUniforms;
|
shader->nUniforms = nUniforms;
|
||||||
glGenFramebuffers(1, &shader->fbo);
|
glGenFramebuffers(1, &shader->fbo);
|
||||||
|
|
|
@ -60,6 +60,7 @@ struct mGLES2Shader {
|
||||||
bool integerScaling;
|
bool integerScaling;
|
||||||
bool filter;
|
bool filter;
|
||||||
bool blend;
|
bool blend;
|
||||||
|
bool dirty;
|
||||||
GLuint tex;
|
GLuint tex;
|
||||||
GLuint fbo;
|
GLuint fbo;
|
||||||
GLuint vao;
|
GLuint vao;
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
using namespace QGBA;
|
using namespace QGBA;
|
||||||
|
|
||||||
ArchiveInspector::ArchiveInspector(const QString& filename, QWidget* parent)
|
ArchiveInspector::ArchiveInspector(const QString& filename, QWidget* parent)
|
||||||
: QDialog(parent)
|
: QDialog(parent, Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint)
|
||||||
{
|
{
|
||||||
m_ui.setupUi(this);
|
m_ui.setupUi(this);
|
||||||
connect(m_ui.archiveView, &LibraryController::doneLoading, [this]() {
|
connect(m_ui.archiveView, &LibraryController::doneLoading, [this]() {
|
||||||
|
|
|
@ -83,6 +83,7 @@ set(SOURCE_FILES
|
||||||
LogConfigModel.cpp
|
LogConfigModel.cpp
|
||||||
LogView.cpp
|
LogView.cpp
|
||||||
MapView.cpp
|
MapView.cpp
|
||||||
|
MemoryDump.cpp
|
||||||
MemoryModel.cpp
|
MemoryModel.cpp
|
||||||
MemorySearch.cpp
|
MemorySearch.cpp
|
||||||
MemoryView.cpp
|
MemoryView.cpp
|
||||||
|
@ -129,6 +130,7 @@ set(UI_FILES
|
||||||
LoadSaveState.ui
|
LoadSaveState.ui
|
||||||
LogView.ui
|
LogView.ui
|
||||||
MapView.ui
|
MapView.ui
|
||||||
|
MemoryDump.ui
|
||||||
MemorySearch.ui
|
MemorySearch.ui
|
||||||
MemoryView.ui
|
MemoryView.ui
|
||||||
ObjView.ui
|
ObjView.ui
|
||||||
|
|
|
@ -1024,7 +1024,7 @@ const QList<IOViewer::RegisterDescription>& IOViewer::registerDescriptions() {
|
||||||
}
|
}
|
||||||
|
|
||||||
IOViewer::IOViewer(std::shared_ptr<CoreController> controller, QWidget* parent)
|
IOViewer::IOViewer(std::shared_ptr<CoreController> controller, QWidget* parent)
|
||||||
: QDialog(parent)
|
: QDialog(parent, Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint)
|
||||||
, m_controller(controller)
|
, m_controller(controller)
|
||||||
{
|
{
|
||||||
m_ui.setupUi(this);
|
m_ui.setupUi(this);
|
||||||
|
|
|
@ -0,0 +1,120 @@
|
||||||
|
/* Copyright (c) 2013-2019 Jeffrey Pfau
|
||||||
|
*
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
#include "MemoryDump.h"
|
||||||
|
|
||||||
|
#include "CoreController.h"
|
||||||
|
#include "GBAApp.h"
|
||||||
|
#include "LogController.h"
|
||||||
|
|
||||||
|
using namespace QGBA;
|
||||||
|
|
||||||
|
MemoryDump::MemoryDump(std::shared_ptr<CoreController> controller, QWidget* parent)
|
||||||
|
: QDialog(parent, Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint)
|
||||||
|
, m_controller(controller)
|
||||||
|
{
|
||||||
|
m_ui.setupUi(this);
|
||||||
|
|
||||||
|
connect(this, &QDialog::accepted, this, &MemoryDump::save);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MemoryDump::save() {
|
||||||
|
QString filename = GBAApp::app()->getSaveFileName(this, tr("Save memory region"));
|
||||||
|
if (filename.isNull()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
QFile outfile(filename);
|
||||||
|
if (!outfile.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
|
||||||
|
LOG(QT, WARN) << tr("Failed to open output file: %1").arg(filename);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
QByteArray out(serialize());
|
||||||
|
outfile.write(out);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MemoryDump::setAddress(uint32_t start) {
|
||||||
|
m_ui.address->setValue(start);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MemoryDump::setSegment(int seg) {
|
||||||
|
m_ui.segment->setValue(seg);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MemoryDump::setByteCount(uint32_t count) {
|
||||||
|
m_ui.bytes->setValue(count);
|
||||||
|
}
|
||||||
|
|
||||||
|
QByteArray MemoryDump::serialize() {
|
||||||
|
CoreController::Interrupter interrupter(m_controller);
|
||||||
|
mCore* core = m_controller->thread()->core;
|
||||||
|
const mCoreMemoryBlock* blocks;
|
||||||
|
size_t nBlocks = core->listMemoryBlocks(core, &blocks);
|
||||||
|
|
||||||
|
int size = m_ui.bytes->value();
|
||||||
|
uint32_t start = m_ui.address->value();
|
||||||
|
int segment = m_ui.segment->value();
|
||||||
|
bool spanSegments = m_ui.spanSegments->isChecked();
|
||||||
|
|
||||||
|
QByteArray mem;
|
||||||
|
while (size) {
|
||||||
|
const mCoreMemoryBlock* bestMatch = NULL;
|
||||||
|
const char* block = NULL;
|
||||||
|
size_t blockSize = 0;
|
||||||
|
for (size_t i = 0; i < nBlocks; ++i) {
|
||||||
|
if (blocks[i].end <= start) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (blocks[i].start > start) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
block = static_cast<const char*>(core->getMemoryBlock(core, blocks[i].id, &blockSize));
|
||||||
|
if (block) {
|
||||||
|
bestMatch = &blocks[i];
|
||||||
|
break;
|
||||||
|
} else if (!bestMatch) {
|
||||||
|
bestMatch = &blocks[i];
|
||||||
|
blockSize = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!spanSegments) {
|
||||||
|
blockSize = bestMatch->end - bestMatch->start;
|
||||||
|
} else if (!blockSize) {
|
||||||
|
blockSize = bestMatch->size;
|
||||||
|
}
|
||||||
|
size_t segmentSize = bestMatch->end - bestMatch->start;
|
||||||
|
if (bestMatch->segmentStart) {
|
||||||
|
segmentSize = bestMatch->segmentStart - bestMatch->start;
|
||||||
|
}
|
||||||
|
if (segment > 0) {
|
||||||
|
start += segment * segmentSize;
|
||||||
|
}
|
||||||
|
int maxFromRegion = blockSize - (start - bestMatch->start);
|
||||||
|
if (maxFromRegion <= 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
int fromRegion = std::min(size, maxFromRegion);
|
||||||
|
if (block && (segment >= 0 || segmentSize == blockSize)) {
|
||||||
|
block = &block[start - bestMatch->start];
|
||||||
|
mem.append(QByteArray::fromRawData(block, fromRegion));
|
||||||
|
size -= fromRegion;
|
||||||
|
start += fromRegion;
|
||||||
|
if (spanSegments) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (int i = 0; i < 16; ++i) {
|
||||||
|
char datum = core->rawRead8(core, start, segment);
|
||||||
|
mem.append(datum);
|
||||||
|
++start;
|
||||||
|
--size;
|
||||||
|
if (!size) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return mem;
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
/* Copyright (c) 2013-2019 Jeffrey Pfau
|
||||||
|
*
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "ui_MemoryDump.h"
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
namespace QGBA {
|
||||||
|
|
||||||
|
class CoreController;
|
||||||
|
|
||||||
|
class MemoryDump : public QDialog {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
MemoryDump(std::shared_ptr<CoreController> controller, QWidget* parent = nullptr);
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void setSegment(int);
|
||||||
|
void setAddress(uint32_t address);
|
||||||
|
void setByteCount(uint32_t);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void save();
|
||||||
|
|
||||||
|
private:
|
||||||
|
QByteArray serialize();
|
||||||
|
|
||||||
|
Ui::MemoryDump m_ui;
|
||||||
|
|
||||||
|
std::shared_ptr<CoreController> m_controller;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,159 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>MemoryDump</class>
|
||||||
|
<widget class="QDialog" name="MemoryDump">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>448</width>
|
||||||
|
<height>208</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Save Memory Range</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QFormLayout" name="formLayout">
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QLabel" name="label">
|
||||||
|
<property name="text">
|
||||||
|
<string>Start Address:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="1">
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QSpinBox" name="segment">
|
||||||
|
<property name="minimum">
|
||||||
|
<number>-1</number>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<number>511</number>
|
||||||
|
</property>
|
||||||
|
<property name="displayIntegerBase">
|
||||||
|
<number>16</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_3">
|
||||||
|
<property name="text">
|
||||||
|
<string>:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QSpinBox" name="address">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="accelerated">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="prefix">
|
||||||
|
<string>0x</string>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<number>268435455</number>
|
||||||
|
</property>
|
||||||
|
<property name="singleStep">
|
||||||
|
<number>16</number>
|
||||||
|
</property>
|
||||||
|
<property name="displayIntegerBase">
|
||||||
|
<number>16</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="0">
|
||||||
|
<widget class="QLabel" name="label_2">
|
||||||
|
<property name="text">
|
||||||
|
<string>Byte Count:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="1">
|
||||||
|
<widget class="QSpinBox" name="bytes">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="prefix">
|
||||||
|
<string>0x</string>
|
||||||
|
</property>
|
||||||
|
<property name="minimum">
|
||||||
|
<number>1</number>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<number>268435456</number>
|
||||||
|
</property>
|
||||||
|
<property name="value">
|
||||||
|
<number>256</number>
|
||||||
|
</property>
|
||||||
|
<property name="displayIntegerBase">
|
||||||
|
<number>16</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="0" colspan="2">
|
||||||
|
<widget class="QCheckBox" name="spanSegments">
|
||||||
|
<property name="text">
|
||||||
|
<string>Dump across banks</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="0" colspan="2">
|
||||||
|
<widget class="QDialogButtonBox" name="buttonBox">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="standardButtons">
|
||||||
|
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Save</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<resources/>
|
||||||
|
<connections>
|
||||||
|
<connection>
|
||||||
|
<sender>buttonBox</sender>
|
||||||
|
<signal>accepted()</signal>
|
||||||
|
<receiver>MemoryDump</receiver>
|
||||||
|
<slot>accept()</slot>
|
||||||
|
<hints>
|
||||||
|
<hint type="sourcelabel">
|
||||||
|
<x>248</x>
|
||||||
|
<y>254</y>
|
||||||
|
</hint>
|
||||||
|
<hint type="destinationlabel">
|
||||||
|
<x>157</x>
|
||||||
|
<y>274</y>
|
||||||
|
</hint>
|
||||||
|
</hints>
|
||||||
|
</connection>
|
||||||
|
<connection>
|
||||||
|
<sender>buttonBox</sender>
|
||||||
|
<signal>rejected()</signal>
|
||||||
|
<receiver>MemoryDump</receiver>
|
||||||
|
<slot>reject()</slot>
|
||||||
|
<hints>
|
||||||
|
<hint type="sourcelabel">
|
||||||
|
<x>316</x>
|
||||||
|
<y>260</y>
|
||||||
|
</hint>
|
||||||
|
<hint type="destinationlabel">
|
||||||
|
<x>286</x>
|
||||||
|
<y>274</y>
|
||||||
|
</hint>
|
||||||
|
</hints>
|
||||||
|
</connection>
|
||||||
|
</connections>
|
||||||
|
</ui>
|
|
@ -7,6 +7,7 @@
|
||||||
#include "MemoryView.h"
|
#include "MemoryView.h"
|
||||||
|
|
||||||
#include "CoreController.h"
|
#include "CoreController.h"
|
||||||
|
#include "MemoryDump.h"
|
||||||
|
|
||||||
#include <mgba/core/core.h>
|
#include <mgba/core/core.h>
|
||||||
|
|
||||||
|
@ -44,6 +45,7 @@ MemoryView::MemoryView(std::shared_ptr<CoreController> controller, QWidget* pare
|
||||||
connect(m_ui.setAddress, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged),
|
connect(m_ui.setAddress, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged),
|
||||||
this, static_cast<void (MemoryView::*)(uint32_t)>(&MemoryView::jumpToAddress));
|
this, static_cast<void (MemoryView::*)(uint32_t)>(&MemoryView::jumpToAddress));
|
||||||
connect(m_ui.hexfield, &MemoryModel::selectionChanged, this, &MemoryView::updateSelection);
|
connect(m_ui.hexfield, &MemoryModel::selectionChanged, this, &MemoryView::updateSelection);
|
||||||
|
connect(m_ui.saveRange, &QAbstractButton::clicked, this, &MemoryView::saveRange);
|
||||||
|
|
||||||
connect(controller.get(), &CoreController::stopping, this, &QWidget::close);
|
connect(controller.get(), &CoreController::stopping, this, &QWidget::close);
|
||||||
|
|
||||||
|
@ -69,6 +71,7 @@ void MemoryView::setIndex(int index) {
|
||||||
m_region = qMakePair(info.start, info.end);
|
m_region = qMakePair(info.start, info.end);
|
||||||
m_ui.segments->setValue(-1);
|
m_ui.segments->setValue(-1);
|
||||||
m_ui.segments->setVisible(info.maxSegment > 0);
|
m_ui.segments->setVisible(info.maxSegment > 0);
|
||||||
|
m_ui.segmentColon->setVisible(info.maxSegment > 0);
|
||||||
m_ui.segments->setMaximum(info.maxSegment);
|
m_ui.segments->setMaximum(info.maxSegment);
|
||||||
m_ui.hexfield->setRegion(info.start, info.end - info.start, info.shortName);
|
m_ui.hexfield->setRegion(info.start, info.end - info.start, info.shortName);
|
||||||
}
|
}
|
||||||
|
@ -142,3 +145,12 @@ void MemoryView::updateStatus() {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MemoryView::saveRange() {
|
||||||
|
MemoryDump* memdump = new MemoryDump(m_controller);
|
||||||
|
memdump->setAttribute(Qt::WA_DeleteOnClose);
|
||||||
|
memdump->setAddress(m_selection.first);
|
||||||
|
memdump->setSegment(m_ui.segments->value());
|
||||||
|
memdump->setByteCount(m_selection.second - m_selection.first);
|
||||||
|
memdump->show();
|
||||||
|
}
|
|
@ -28,6 +28,7 @@ private slots:
|
||||||
void setSegment(int);
|
void setSegment(int);
|
||||||
void updateSelection(uint32_t start, uint32_t end);
|
void updateSelection(uint32_t start, uint32_t end);
|
||||||
void updateStatus();
|
void updateStatus();
|
||||||
|
void saveRange();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Ui::MemoryView m_ui;
|
Ui::MemoryView m_ui;
|
||||||
|
|
|
@ -6,8 +6,8 @@
|
||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>822</width>
|
<width>874</width>
|
||||||
<height>886</height>
|
<height>900</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
|
@ -52,6 +52,13 @@
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="segmentColon">
|
||||||
|
<property name="text">
|
||||||
|
<string>:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QSpinBox" name="setAddress">
|
<widget class="QSpinBox" name="setAddress">
|
||||||
<property name="accelerated">
|
<property name="accelerated">
|
||||||
|
@ -271,6 +278,13 @@
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="saveRange">
|
||||||
|
<property name="text">
|
||||||
|
<string>Save Range</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QPushButton" name="load">
|
<widget class="QPushButton" name="load">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
using namespace QGBA;
|
using namespace QGBA;
|
||||||
|
|
||||||
PlacementControl::PlacementControl(std::shared_ptr<CoreController> controller, QWidget* parent)
|
PlacementControl::PlacementControl(std::shared_ptr<CoreController> controller, QWidget* parent)
|
||||||
: QDialog(parent)
|
: QDialog(parent, Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint)
|
||||||
, m_controller(controller)
|
, m_controller(controller)
|
||||||
{
|
{
|
||||||
m_ui.setupUi(this);
|
m_ui.setupUi(this);
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
using namespace QGBA;
|
using namespace QGBA;
|
||||||
|
|
||||||
PrinterView::PrinterView(std::shared_ptr<CoreController> controller, QWidget* parent)
|
PrinterView::PrinterView(std::shared_ptr<CoreController> controller, QWidget* parent)
|
||||||
: QDialog(parent)
|
: QDialog(parent, Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint)
|
||||||
, m_controller(controller)
|
, m_controller(controller)
|
||||||
{
|
{
|
||||||
m_ui.setupUi(this);
|
m_ui.setupUi(this);
|
||||||
|
|
Loading…
Reference in New Issue