Newer
Older
Atmosphere / docs / changelog.md
@Hylian Hylian on 24 Oct 2018 7 KB Update changelog.md

Changelog

0.7.3

  • Loader and fs.mitm now try to reload loader.ini before reading it. This allows for changing the override button combination/HBL title id at runtime.
  • Added a MitM between set:sys and qlaunch, used to override the system version string displayed in system settings.
    • The displayed system version will now display <Actual version> (AMS <x>.<y>.<z>).
  • General system stability improvements to enhance the user's experience.

0.7.2

  • Fixed a bug in fs.mitm's LayeredFS read implementation that caused some games to crash when trying to read files.
  • Fixed a bug affecting 1.0.0 that caused games to crash with fatal error 2001-0106 on boot.
  • Improved filenames output by the make dist target.
  • General system stability improvements to enhance the user's experience.

0.7.1

  • Fixed a bug preventing consoles on 4.0.0-4.1.0 from going to sleep and waking back up.
  • Fixed a bug preventing consoles on < 4.0.0 from booting without specific KIPs on the SD card.
  • An API was added to Atmosphère's Service Manager for deferring acquisition of all handles for specific services until after early initialization is completed.
  • General system stability improvements to enhance the user's experience.

0.7.0

  • First official release of Atmosphère.
  • Supports the following featureset:
    • Fusée, a custom bootloader.
      • Supports loading/customizing of arbitrary KIPs from the SD card.
      • Supports loading a custom kernel from the SD card ("/atmosphere/kernel.bin").
      • Supports compile-time defined kernel patches on a per-firmware basis.
      • All patches at paths like /atmosphere/kip_patches//.ips will be applied to the relevant KIPs, allowing for easy distribution of patches supporting multiple versions.
        • Both the IPS and IPS32 formats are supported.
      • All patches at paths like /atmosphere/kernel_patches//.ips will be applied to the kernel, allowing for easy distribution of patches supporting multiple versions.
        • Both the IPS and IPS32 formats are supported.
      • Configurable by editing BCT.ini on the SD card.
      • Atmosphère should also be launchable by the alternative hekate bootloader, for those who prefer it.
    • Exosphère, a fully-featured custom secure monitor.
      • Exosphere is a re-implementation of Nintendo's TrustZone firmware, fully replicating all of its features.
      • In addition, it has been extended to provide information on current Atmosphere API version, for homebrew wishing to make use of it.
    • Stratosphère, a set of custom system modules. This includes:
      • A loader system module.
        • Reimplementation of Nintendo's loader, fully replicating all original functionality.
        • Configurable by editing /atmosphere/loader.ini
        • First class support for the Homebrew Loader.
          • An exefs NSP (default "/atmosphere/hbl.nsp") will be used in place of the victim title's exefs.
          • By default, HBL will replace the album applet, but any application should also be supported.
        • Extended to support arbitrary redirection of executable content to the SD card.
          • Files will be preferentially loaded from /atmosphere/titles//exefs/, if present.
          • Files present in the original exefs a user wants to mark as not present may be "stubbed" by creating a .stub file on the SD.
          • If present, a PFS0 at /atmosphere/titles//exefs.nsp will fully replace the original exefs.
          • Redirection is optionally toggleable by holding down certain buttons (by default, holding R disables redirection).
        • Full support for patching NSO content is implemented.
          • All patches at paths like /atmosphere/exefs_patches//.ips will be applied, allowing for easy distribution of patches supporting multiple firmware versions and/or titles.
          • Both the IPS and IPS32 formats are supported.
        • Extended to support launching content from loose executable files on the SD card, without requiring any official installation.
          • This is done by specifying FsStorageId_None on launch.
      • A service manager system module.
        • Reimplementation of Nintendo's service manager, fully replicating all original functionality.
        • Compile-time support for reintroduction of "smhax", allowing clients to optionally skip service access verification by skipping initialization.
        • Extended to allow homebrew to acquire more handles to privileged services than Nintendo natively allows.
        • Extended to add a new API for installing Man-In-The-Middle listeners for arbitrary services.
          • API can additionally be used to safely detect whether a service has been registered in a non-blocking way with no side-effects.
          • Full API documentation to come.
      • A process manager system module.
        • Reimplementation of Nintendo's process manager, fully replicating all original functionality.
        • Extended to allow homebrew to acquire handles to arbitrary processes, and thus read/modify system memory without blocking execution.
        • Extended to allow homebrew to retrieve information about system resource limits.
        • Extended by embedding a full, extended implementation of Nintendo's boot2 system module.
          • Title launch order has been optimized in order to grant access to the SD card faster.
          • The error-collection system module is intentionally not launched, preventing many system telemetry error reports from being generated at all.
          • Users may place their own custom sysmodules on the SD card and flag them for automatic boot2 launch by creating a /atmosphere/titles//boot2.flag file on their SD card.</li> </ul> </li> </ul> </li> <li>A custom fs.mitm system module. <ul> <li>Uses Atmosphère's MitM API in order to provide an easy means for users to modify game content.</li> <li>Intercepts all FS commands sent by games, with special handling for commands used to mount RomFS/DLC content to enable easy creation and distribution of game/DLC mods. <ul> <li>fs.mitm will parse the base RomFS image for a game, a RomFS image located at /atmosphere/titles/<title ID>/romfs.bin, and all loose files in /atmosphere/titles/<title ID>/romfs/, and merge them together into a single RomFS image.</li> <li>When merging, loose files are preferred to content in the SD card romfs.bin image, and files from the SD card image are preferred to those in the base image.</li> </ul> </li> <li>Can additionally be used to intercept commands sent by arbitrary system titles (excepting those launched before SD card is active), by creating a /atmosphere/titles/<title ID>/fsmitm.flag file on the SD card.</li> <li>Can be forcibly disabled for any title, by creating a /atmosphere/titles/<title ID>/fsmitm_disable.flag file on the SD card.</li> <li>Redirection is optionally toggleable by holding down certain buttons (by default, holding R disables redirection).</li> </ul> </li> <li>A custom crash report system module. <ul> <li>Serves as a drop-in replacement for Nintendo's own creport system module.</li> <li>Generates detailed, human-readable reports on system crashes, saving to /atmosphere/crash_reports/<timestamp>_<title ID>.log.</li> <li>Because reports are not sent to the erpt sysmodule, this disables all crash report related telemetry.</li> </ul> </li> </ul> </li> <li>General system stability improvements to enhance the user's experience.</li> </ul> </li> </ul> </div> </div> </div> <script> $(function(){ $('a[rel*=facebox]').facebox({ 'loadingImage': 'https://source.perditum.com/assets/vendors/facebox/loading.gif?20260731193355', 'closeImage': 'https://source.perditum.com/assets/vendors/facebox/closelabel.png?20260731193355' }); $(document).on("click", ".js-fork-owner-select-target", function() { var account = $(this).text().replace("@", ""); $("#account").val(account); $("#fork").submit(); }); }); </script> </div> <script> $(function(){ $(".sidebar-toggle").on('click', function(e){ $.post('https://source.perditum.com/sidebar-collapse', { collapse: !$('body').hasClass('sidebar-collapse') }); }); }); </script> <script> const codeHighlighterHljsPath = "https://source.perditum.com/plugin-assets/code-highlighter/highlightjs"; </script> <script src="https://source.perditum.com/plugin-assets/code-highlighter/main.js" defer> </script> <script> </script> <link rel='stylesheet' href='https://source.perditum.com/plugin-assets/gme/admonition.css'> <link rel='stylesheet' href='https://source.perditum.com/plugin-assets/gme/katex/dist/katex.min.css'> <link rel='stylesheet' href='https://source.perditum.com/plugin-assets/gme/gme.css'> <script src="https://source.perditum.com/plugin-assets/gme/admonition.js" type="text/javascript"> </script> <script src="https://source.perditum.com/plugin-assets/gme/katex/dist/katex.min.js" type="text/javascript"> </script> <script src="https://source.perditum.com/plugin-assets/gme/mermaid/mermaid.min.js" type="text/javascript"> </script> <script src="https://source.perditum.com/plugin-assets/gme/wavedrom/default.js" type="text/javascript"> </script> <script src="https://source.perditum.com/plugin-assets/gme/wavedrom/wavedrom.min.js" type="text/javascript"> </script> <script src="https://source.perditum.com/plugin-assets/gme/vega/vega-6.2.0.js" type="text/javascript"> </script> <script src="https://source.perditum.com/plugin-assets/gme/vega/vega-lite-6.4.1.js" type="text/javascript"> </script> <script src="https://source.perditum.com/plugin-assets/gme/vega/vega-embed-7.0.2.js" type="text/javascript"> </script> <script src="https://source.perditum.com/plugin-assets/gme/gme.js" type="text/javascript"> </script> </body> </html> <script> $(window).on('load', function(){ window.onhashchange = function(){ updateHighlighting(); } const pre = $('pre.prettyprint'); function updateSourceLineNum() { $('.source-line-num').remove(); const pos = pre.find('ol.linenums').position(); if (pos) { $('<div class="source-line-num">').css({ height : pre.height(), width : '48px', cursor : 'pointer', position: 'absolute', top : pos.top + 'px', left : pos.left + 'px' }).click(function(e){ let pos = $(this).data("pos"); if (!pos) { pos = $('ol.linenums li').map(function(){ return { id: $(this).attr("id"), top: $(this).position().top} }).toArray(); $(this).data("pos",pos); } let i = 0; for(i = 0; i < pos.length - 1; i++){ if(pos[i + 1].top > e.pageY){ break; } } const line = pos[i].id.replace(/^L/,''); const hash = location.hash; const baseUrl = location.toString().split("#")[0]; if (e.shiftKey == true && hash.match(/#L\d+(-L\d+)?/)) { const fragments = hash.split('-'); window.history.pushState('', '', baseUrl + fragments[0] + '-L' + line); } else { const p = $("#L" + line).attr('id', ''); window.history.pushState('', '', baseUrl + '#L' + line); p.attr('id','L' + line); } $("#branchCtrlWrapper .btn .muted").text("tree:"); $("#branchCtrlWrapper .btn .strong").text("de688ee17a"); getSelection().empty(); updateHighlighting(); }).appendTo(pre); updateHighlighting(); } else { // Maybe code view is not initialized yet. Retry until succeed. setTimeout(updateSourceLineNum, 300); } } const repository = $('.blame-action').data('repository'); $('.blame-action').click(function(e){ if(history.pushState && $('pre.prettyprint.no-renderable').length){ e.preventDefault(); history.pushState(null, null, this.href); updateBlame(); } }); function updateBlame(){ const m = /\/(blame|blob)(\/.*)$/.exec(location.href); const mode = m[1]; $('.blame-action').toggleClass("active", mode=='blame').attr('href', repository + (m[1] == 'blame' ? '/blob' : '/blame') + m[2]); if(pre.parents("div.box-content-bottom").find(".blame").length){ pre.parent().toggleClass("blame-container", mode == 'blame'); updateSourceLineNum(); return; } if(mode == 'blob'){ updateSourceLineNum(); return; } $(document.body).toggleClass('no-box-shadow', document.body.style.boxShadow === undefined); $('.blame-action').addClass("active"); const base = $('<div class="blame">').css({height: pre.height()}).prependTo(pre.parents("div.box-content-bottom")); base.parent().addClass("blame-container"); updateSourceLineNum(); $.get($('.blame-action').data('url')).done(function(data){ let blame = data.blame; let lastDiv; const now = new Date().getTime(); const index = []; for(let i = 0; i < blame.length; i++){ for(let j = 0; j < blame[i].lines.length; j++){ index[blame[i].lines[j]] = blame[i]; } } $('pre.prettyprint ol.linenums li').each(function(i, e){ const p = $(e).position(); const h = $(e).height(); if(blame == index[i]){ lastDiv.css("min-height",(p.top + h + 1) - lastDiv.position().top); } else { $(e).addClass('blame-sep') blame = index[i]; const sha = $('<div class="blame-sha">') .append($('<a>').attr("href", data.root + '/commit/' + blame.id).text(blame.id.substr(0, 7))); if (blame.prev) { sha.append($('<br />')) .append($('<a class="muted-link">').text('prev').attr("href", data.root + '/blame/' + blame.prev + '/' + (blame.prevPath || data.path))); } lastDiv = $('<div class="blame-info">') .addClass('heat' + Math.min(10, Math.max(1, Math.ceil((now - blame.commited) / (24 * 3600 * 1000 * 70))))) .toggleClass('blame-last', blame.id == data.last) .data('line', (i + 1)) .css({ "top" : p.top + 'px', "min-height" : h + 'px' }) .append(sha) .append($(blame.avatar).addClass('avatar').css({"float": "left"})) .append($('<div class="blame-commit-title">').text(blame.message)) .append($('<div class="muted">').html(blame.author + " authed " + blame.authed)) .appendTo(base); } }); }); return false; }; $(document).on('expanded.pushMenu collapsed.pushMenu', function(e){ setTimeout(updateBlame, 300); }); updateBlame(); }); let scrolling = false; /** * Highlight lines which are specified by URL hash. */ function updateHighlighting() { const hash = location.hash; const isDark = false; if (hash.match(/#L\d+(-L\d+)?/)) { if (isDark) { $('li.highlight-dark').removeClass('highlight-dark'); } else { $('li.highlight').removeClass('highlight'); } const fragments = hash.substr(1).split('-'); if (fragments.length == 1) { if (isDark) { $('#' + fragments[0]).addClass('highlight-dark'); } else { $('#' + fragments[0]).addClass('highlight'); } if(!scrolling){ $(window).scrollTop($('#' + fragments[0]).offset().top); } } else if(fragments.length > 1){ const start = parseInt(fragments[0].substr(1)); const end = parseInt(fragments[1].substr(1)); for (let i = start; i <= end; i++) { if (isDark) { $('#L' + i).addClass('highlight-dark'); } else { $('#L' + i).addClass('highlight'); } } if (!scrolling) { $(window).scrollTop($('#' + fragments[0]).offset().top); } } } scrolling = true; } </script>