├── .bowerrc ├── .gitignore ├── Gruntfile.js ├── LICENSE ├── README.md ├── apiary.apib ├── app ├── images │ └── background.jpg ├── index.html ├── scripts │ ├── controllers │ │ └── server.ts │ ├── cpu.ts │ ├── filters │ │ └── hexadecimal.ts │ ├── nerve.ts │ ├── services │ │ ├── cpu.thread.ts │ │ ├── memory.ts │ │ └── server.provider.ts │ ├── ui.ts │ └── util.ts ├── styles │ ├── nerve.css │ └── ui.css └── views │ ├── cpu.html │ ├── files.html │ ├── general.html │ ├── gpu.html │ ├── intro.html │ ├── memory.html │ └── system.html ├── bower.json ├── dist ├── .gitignore └── externals │ └── capstone │ └── capstone-ppc.min.js ├── package.json └── tsd.json /.bowerrc: -------------------------------------------------------------------------------- 1 | { 2 | "directory": "dist/externals" 3 | } 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Visual Studio 2 | *.sln 3 | *.suo 4 | 5 | # Dependencies NPM and TSD 6 | node_modules/ 7 | typings/ 8 | 9 | # Images 10 | *.psd 11 | 12 | # Nerve 13 | dist/* 14 | !dist/.gitignore 15 | -------------------------------------------------------------------------------- /Gruntfile.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = function (grunt) { 4 | 5 | // Load tasks from grunt-* dependencies in package.json 6 | require('load-grunt-tasks')(grunt); 7 | 8 | // Time how long tasks take 9 | require('time-grunt')(grunt); 10 | 11 | // Project configuration 12 | grunt.initConfig({ 13 | yeoman: { 14 | app: 'app', 15 | dist: 'dist' 16 | }, 17 | copy: { 18 | app: { 19 | expand: true, 20 | filter: 'isFile', 21 | cwd: '<%= yeoman.app %>/', 22 | src: ['**/*.html', '**/*.jpg'], 23 | dest: '<%= yeoman.dist %>/' 24 | } 25 | }, 26 | wiredep: { 27 | app: { 28 | src: ['<%= yeoman.dist %>/index.html'] 29 | } 30 | }, 31 | typescript: { 32 | base: { 33 | src: ['<%= yeoman.app %>/scripts/**/*.ts'], 34 | dest: '<%= yeoman.dist %>/nerve.js', 35 | options: { 36 | target: 'es5' 37 | } 38 | } 39 | }, 40 | cssmin: { 41 | combine: { 42 | files: { 43 | '<%= yeoman.dist %>/nerve.css': [ 44 | '<%= yeoman.app %>/styles/**/*.css' 45 | ] 46 | } 47 | } 48 | }, 49 | htmlmin: { 50 | dist: { 51 | options: { 52 | removeComments: true, 53 | collapseWhitespace: true 54 | }, 55 | files: [{ 56 | expand: true, 57 | cwd: '<%= yeoman.dist %>', 58 | src: '{,*/}*.html', 59 | dest: '<%= yeoman.dist %>/' 60 | }] 61 | } 62 | }, 63 | uglify: { 64 | dist: { 65 | options: { 66 | mangle: false 67 | }, 68 | files: { 69 | '<%= yeoman.dist %>/nerve.js': [ 70 | '<%= yeoman.dist %>/nerve.js' 71 | ] 72 | } 73 | } 74 | }, 75 | connect: { 76 | options: { 77 | port: 9000, 78 | livereload: 35728, 79 | hostname: 'localhost', 80 | base: '<%= yeoman.dist %>' 81 | }, 82 | livereload: { 83 | options: { 84 | open: true 85 | } 86 | } 87 | }, 88 | watch: { 89 | scripts: { 90 | files: '<%= yeoman.app %>/scripts/{,*/}*.ts', 91 | tasks: ['typescript'] 92 | }, 93 | styles: { 94 | files: '<%= yeoman.app %>/styles/{,*/}*.css', 95 | tasks: ['cssmin'] 96 | }, 97 | views: { 98 | files: '<%= yeoman.app %>/{,*/}*.html', 99 | tasks: ['copy', 'wiredep', 'htmlmin'] 100 | }, 101 | livereload: { 102 | files: [ 103 | '<%= yeoman.dist %>/{,*/}*.html', 104 | '<%= yeoman.dist %>/*.js', 105 | '<%= yeoman.dist %>/*.css' 106 | ], 107 | options: { 108 | livereload: '<%= connect.options.livereload %>' 109 | } 110 | }, 111 | } 112 | }); 113 | 114 | // Project tasks 115 | grunt.registerTask('test', [ 116 | 117 | ]); 118 | grunt.registerTask('build', [ 119 | 'copy', 120 | 'wiredep', 121 | 'typescript', 122 | 'cssmin', 123 | 'htmlmin', 124 | 'uglify' 125 | ]); 126 | grunt.registerTask('serve', [ 127 | 'connect', 128 | 'watch' 129 | ]); 130 | grunt.registerTask('default', [ 131 | 'test', 132 | 'build', 133 | 'serve' 134 | ]); 135 | }; 136 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | {description} 294 | Copyright (C) {year} {fullname} 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License along 307 | with this program; if not, write to the Free Software Foundation, Inc., 308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) year name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | {signature of Ty Coon}, 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Lesser General 339 | Public License instead of this License. 340 | 341 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Nerve 2 | ===== 3 | [![Last Release](https://badge.fury.io/gh/AlexAltea%2Fnerve.svg)](https://github.com/AlexAltea/nerve/releases) 4 | 5 | Front-end for PlayStation 3 debuggers. Please, understand that I'm not interested on providing support, releases, or attention to any comments, issues or pull requests for now. 6 | 7 | ### Deploy 8 | To build the Nerve client, clone the *master* branch of this repository, and do the following: 9 | 10 | **1.** Install the development and client dependencies: 11 | ``` 12 | npm install 13 | bower install 14 | tsd reinstall 15 | ``` 16 | 17 | **2.** Finally, build the app with: 18 | ``` 19 | grunt build 20 | ``` 21 | -------------------------------------------------------------------------------- /apiary.apib: -------------------------------------------------------------------------------- 1 | FORMAT: 1A 2 | 3 | # Nerve API Documentation 4 | The Nerve API is based on REST principles and its goal is to provide a simple yet powerful way to interact with the LV2 system of the PlayStation 3 (both real consoles and emulators). An official [Nerve client](http://alexaltea.github.io/nerve/) is available. The back-end server has to match the specifications of this document, an example of such a server can be found in the [Nucleus](https://github.com/AlexAltea/nucleus) emulator. 5 | 6 | ##Allowed HTTP requests: 7 | - `POST` - Creates or updates a resource. 8 | - `PUT` - Updates a resource. 9 | - `GET` - Retrieves a resource or list of resources. 10 | - `DELETE` - Delete a resource. 11 | 12 | ##Typical server responses 13 | - `200` *OK* - The request was successful. 14 | - `201` *Created* - The request was successful and a resource was created. 15 | - `204` *No Content* - The request was successful and there is nothing to return. 16 | - `400` *Bad Request* - The request could not be understood or was missing required parameters. 17 | - `404` *Not Found* - Resource was not found. 18 | 19 | # Group Nerve 20 | Control the back-end server itself. 21 | 22 | ## Connection [/connect] 23 | Since the back-end server runs a RESTful API, no real connections take place here. The purpose of this method is validating and obtaining information about the back-end server for the client. 24 | 25 | ### Connect to the back-end [GET] 26 | + Response 200 (application/json) 27 | 28 | { 29 | "version": "1.0.0", 30 | "device": { 31 | "name": "Nucleus", 32 | "type": "emulator", 33 | "version": "0.0.1" 34 | }, 35 | "host": { 36 | "os": "Windows 7 SP1", 37 | "cpu": "64-bit" 38 | } 39 | } 40 | 41 | 42 | # Group CPU 43 | Controls the *Cell B.E.* processor. It provides a list of threads in the current process and allows to read/write their registers. 44 | 45 | ## Breakpoints Collection [/cpu/breakpoints] 46 | Allows to set CPU execution breakpoints 47 | 48 | ### List all breakpoints [GET] 49 | Provides a list of all breakpoints with following information: 50 | - **address**: Address where this breakpoint is placed. 51 | - **active**: Specifies whether a CPU thread will pause after hitting this breakpoint. 52 | - **count**: Amount of times this breakpoint was hit. 53 | 54 | + Response 200 (application/json) 55 | 56 | [{ 57 | "address": 0x0001022C, 58 | "active": true, 59 | "count": 1, 60 | }, { 61 | "address": 0x001C08E0, 62 | "active": true, 63 | "count": 37, 64 | }, { 65 | "address": 0x00030044, 66 | "active": false, 67 | "count": 0, 68 | }] 69 | 70 | ## Breakpoint [/cpu/breakpoints/{address}] 71 | + Parameters 72 | + address (required, number, `1`) ... Memory address of the target CPU instruction. 73 | 74 | ### Create a breakpoint [POST] 75 | + Response 201 (application/json) 76 | 77 | { 78 | "address": 0x10648, 79 | "active": true, 80 | "count": 0 81 | } 82 | 83 | ### Retrieve a breakpoint [GET] 84 | + Response 200 (application/json) 85 | 86 | { 87 | "address": 0x60408, 88 | "active": false, 89 | "count": 2 90 | } 91 | 92 | ### Remove a breakpoint [DELETE] 93 | + Response 204 94 | 95 | ## Threads Collection [/cpu/threads] 96 | Provides general information and IDs of all threads, and allows to create new ones. 97 | 98 | ### List all threads [GET] 99 | Provides a list of threads managed by LV2 in the current process, along with following information: 100 | - **id**: Unique 64-bit identifier of the thread. 101 | - **type**: Allowed values: `PPU`, `SPU`, `RAWSPU`. 102 | - **name**: Name of the thread. 103 | - **state**: Allowed values for *PPU* threads are: `IDLE`, `RUNNABLE`, `RUNNING`, `SLEEPING`, `STOPPED`, `ZOMBIE`, `DELETED`, `UNKNOWN`. 104 | 105 | + Response 200 (application/json) 106 | 107 | [{ 108 | "id": 1, 109 | "type": "PPU", 110 | "name": "MainThread", 111 | "state": "RUNNING" 112 | }, { 113 | "id": 2, 114 | "type": "PPU", 115 | "name": "WorkerThread", 116 | "state": "RUNNING" 117 | }, { 118 | "id": 3, 119 | "type": "SPU", 120 | "name": "", 121 | "state": "SLEEPING" 122 | }, { 123 | "id": 5, 124 | "type": "RAWSPU", 125 | "name": "VideoDecoder", 126 | "state": "ZOMBIE" 127 | }] 128 | 129 | ### Create a thread [POST] 130 | Creates a thread via LV2, requiring following arguments: 131 | - **type**: Allowed values: `PPU`, `SPU`, `RAWSPU`. 132 | - **function**: Address of the function's OPD as decimal number. 133 | - **argument**: Argument to be passed to the function. 134 | 135 | + Request (application/json) 136 | 137 | { 138 | "type": "PPU", 139 | "name": "NewThread", 140 | "function": 65792, 141 | "argument": 1234 142 | } 143 | 144 | + Response 201 (application/json) 145 | 146 | { 147 | "id": 3, 148 | "type": "PPU", 149 | "name": "NewThread", 150 | "state": "RUNNABLE" 151 | } 152 | 153 | ## Threads [/cpu/threads/{id}] 154 | A single thread object with all its properties. Registers will be passed as strings containing the hexadecimal value without the *0x* prefix. 155 | 156 | + Parameters 157 | + id (required, number, `1`) ... Numeric `id` of the thread to interact with. 158 | 159 | ### Retrieve a thread [GET] 160 | + Response 200 (application/json) 161 | 162 | { 163 | "id": 2, 164 | "type": "PPU", 165 | "name": "SomeThread", 166 | "state": "IDLE", 167 | "registers" : { 168 | "gpr": [ 169 | "0000000000000000", 170 | "0000000000000000", 171 | "0000000012345678", 172 | "00000000D000E580", 173 | "0000000000000000", 174 | "0000000000000000", 175 | "0000000000000000", 176 | "0000000000000000", 177 | "0000000000000000", 178 | "0000000000000000", 179 | "0000000000000000", 180 | "0000000000000000", 181 | "0000000000000000", 182 | "0000000000000000", 183 | "0000000000000000", 184 | "0000000000000000", 185 | "0000000000000000", 186 | "0000000000000000", 187 | "0000000000000000", 188 | "0000000000000000", 189 | "0000000000000000", 190 | "0000000000000000", 191 | "0000000000000000", 192 | "0000000000000000", 193 | "0000000000000000", 194 | "0000000000000000", 195 | "0000000000000000", 196 | "0000000000000000", 197 | "0000000000000000", 198 | "0000000000000000", 199 | "0000000000000000", 200 | "0000000000000000" 201 | ], 202 | "fpr": [ 203 | "0000000000000000", 204 | "0000000000000000", 205 | "0000000000000000", 206 | "0000000000000000", 207 | "0000000000000000", 208 | "0000000000000000", 209 | "0000000000000000", 210 | "0000000000000000", 211 | "0000000000000000", 212 | "0000000000000000", 213 | "0000000000000000", 214 | "0000000000000000", 215 | "0000000000000000", 216 | "0000000000000000", 217 | "0000000000000000", 218 | "0000000000000000", 219 | "0000000000000000", 220 | "0000000000000000", 221 | "0000000000000000", 222 | "0000000000000000", 223 | "0000000000000000", 224 | "0000000000000000", 225 | "0000000000000000", 226 | "0000000000000000", 227 | "0000000000000000", 228 | "0000000000000000", 229 | "0000000000000000", 230 | "0000000000000000", 231 | "0000000000000000", 232 | "0000000000000000", 233 | "0000000000000000", 234 | "0000000000000000" 235 | ], 236 | "vr": [ 237 | "00000000000000000000000000000000", 238 | "00000000000000000000000000000000", 239 | "00000000000000000000000000000000", 240 | "00000000000000000000000000000000", 241 | "00000000000000000000000000000000", 242 | "00000000000000000000000000000000", 243 | "00000000000000000000000000000000", 244 | "00000000000000000000000000000000", 245 | "00000000000000000000000000000000", 246 | "00000000000000000000000000000000", 247 | "00000000000000000000000000000000", 248 | "00000000000000000000000000000000", 249 | "00000000000000000000000000000000", 250 | "00000000000000000000000000000000", 251 | "00000000000000000000000000000000", 252 | "00000000000000000000000000000000", 253 | "00000000000000000000000000000000", 254 | "00000000000000000000000000000000", 255 | "00000000000000000000000000000000", 256 | "00000000000000000000000000000000", 257 | "00000000000000000000000000000000", 258 | "00000000000000000000000000000000", 259 | "00000000000000000000000000000000", 260 | "00000000000000000000000000000000", 261 | "00000000000000000000000000000000", 262 | "00000000000000000000000000000000", 263 | "00000000000000000000000000000000", 264 | "00000000000000000000000000000000", 265 | "00000000000000000000000000000000", 266 | "00000000000000000000000000000000", 267 | "00000000000000000000000000000000", 268 | "00000000000000000000000000000000" 269 | ], 270 | "cr": "00000000", 271 | "fpscr": "00000000", 272 | "vscr": "00000000", 273 | "xer": "00000000", 274 | "lr": "00000000", 275 | "ctr": "00000000", 276 | "pc": "00000000", 277 | "tbl": "00000000", 278 | "tbu": "00000000" 279 | } 280 | } 281 | 282 | ### Remove a thread [DELETE] 283 | + Response 204 284 | 285 | 286 | # Group GPU 287 | Controls the *Reality Synthesizer* (RSX). It provides information about used display buffers, the FIFO command buffer, reports, notifiers, fragment/vertex shaders and more. 288 | 289 | ## Breakpoints Collection [/gpu/breakpoints] 290 | Allows to set GPU command execution breakpoints 291 | 292 | ### List all breakpoints [GET] 293 | Provides a list of all breakpoints with following information: 294 | - **address**: Address where this breakpoint is placed. 295 | - **active**: Specifies whether the GPU command reader will pause after hitting this breakpoint. 296 | - **count**: Amount of times this breakpoint was hit. 297 | 298 | + Response 200 (application/json) 299 | 300 | [{ 301 | "address": 0x10010010, 302 | "active": true, 303 | "count": 1, 304 | }, { 305 | "address": 0x100108E0, 306 | "active": true, 307 | "count": 37, 308 | }, { 309 | "address": 0x10010F00, 310 | "active": false, 311 | "count": 0, 312 | }] 313 | 314 | ## Breakpoint [/gpu/breakpoints/{address}] 315 | + Parameters 316 | + address (required, number, `1`) ... Memory address of the target GPU command. 317 | 318 | ### Create a breakpoint [POST] 319 | + Response 201 (application/json) 320 | 321 | { 322 | "address": 0x10010648, 323 | "active": true, 324 | "count": 0 325 | } 326 | 327 | ### Retrieve a breakpoint [GET] 328 | + Response 200 (application/json) 329 | 330 | { 331 | "address": 0x10010408, 332 | "active": false, 333 | "count": 2 334 | } 335 | 336 | ### Remove a breakpoint [DELETE] 337 | + Response 204 338 | 339 | 340 | # Group Memory 341 | Provides additional information and statistics about the memory usage of the current process. 342 | 343 | ## Memory R/W [/memory/{address}] 344 | 345 | + Parameters 346 | + address (required, number, `65536`) ... Start address as a decimal value of the range to be accessed. 347 | 348 | ### Read memory [GET] 349 | Returns the 4 KB of memory preceding the given address as an array of bytes. The address must therefore be aligned to 4 KB. Returns an empty array if an access violation occurs. 350 | 351 | + Response 200 (application/json) 352 | 353 | { 354 | "address": 65536, 355 | "size": 4096, 356 | "data": "DEADBEEFABADCAFE0000000000010001000000001234567800000000FFFFFFFF000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDFE0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDFF821FF917C0802A62F80000041DE00148062803C780900207C0901CEFCFDFEFFDEADBEEFABADCAFE0000000000010001000000001234567800000000FFFFFFFFDEADBEEFABADCAFE0000000000010001000000001234567800000000FFFFFFFF000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDFE0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDFE0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDFE0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDFE0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFFDEADBEEFABADCAFE0000000000010001000000001234567800000000FFFFFFFFDEADBEEFABADCAFE0000000000010001000000001234567800000000FFFFFFFFDEADBEEFABADCAFE0000000000010001000000001234567800000000FFFFFFFFDEADBEEFABADCAFE0000000000010001000000001234567800000000FFFFFFFF000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDFE0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDFE0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDFE0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDFE0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDFE0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDFE0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDFE0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDFE0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFFDEADBEEFABADCAFE0000000000010001000000001234567800000000FFFFFFFF000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDFE0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF" 357 | } 358 | 359 | ## Breakpoints Collection [/memory/breakpoints] 360 | Allows to set memory read/write breakpoints 361 | 362 | ### List all breakpoints [GET] 363 | Provides a list of all breakpoints with following information: 364 | - **address**: Address where this breakpoint is placed. 365 | - **size**: Amount of bytes this breakpoint affects. 366 | - **watchR**: Break on memory read attempts. 367 | - **watchW**: Break on memory write attempts. 368 | - **active**: Specifies whether the corresponding CPU thread will pause after hitting this breakpoint. 369 | - **count**: Amount of times this breakpoint was hit. 370 | 371 | + Response 200 (application/json) 372 | 373 | [{ 374 | "address": 0xD0010F00, 375 | "size": 8, 376 | "watchR": true, 377 | "watchW": true, 378 | "active": true, 379 | "count": 1, 380 | }, { 381 | "address": 0xD00108E0, 382 | "size": 1, 383 | "watchR": false, 384 | "watchW": true, 385 | "active": true, 386 | "count": 37, 387 | }, { 388 | "address": 0xC0000400, 389 | "size": 4, 390 | "watchR": true, 391 | "watchW": false, 392 | "active": false, 393 | "count": 0, 394 | }] 395 | 396 | ## Breakpoint [/memory/breakpoints/{address}] 397 | + Parameters 398 | + address (required, number, `1`) ... Memory address of the target GPU command. 399 | 400 | ### Create a breakpoint [POST] 401 | + Request (application/json) 402 | 403 | { 404 | "size": 8, 405 | "watchR": false, 406 | "watchW": true, 407 | } 408 | 409 | + Response 201 (application/json) 410 | 411 | { 412 | "address": 0xD0010648, 413 | "size": 8, 414 | "watchR": false, 415 | "watchW": true, 416 | "active": true, 417 | "count": 0 418 | } 419 | 420 | ### Retrieve a breakpoint [GET] 421 | + Response 200 (application/json) 422 | 423 | { 424 | "address": 0xD0010408, 425 | "active": false, 426 | "count": 2 427 | } 428 | 429 | ### Remove a breakpoint [DELETE] 430 | + Response 204 431 | 432 | # Group Files 433 | Blah. 434 | 435 | 436 | # Group System 437 | Blah. 438 | -------------------------------------------------------------------------------- /app/images/background.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexAltea/nerve/cd9911628883dd745df2224b4b8d5164980ae3e4/app/images/background.jpg -------------------------------------------------------------------------------- /app/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Nerve 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 53 | 54 | 55 | 69 | 70 | 71 |
72 | 73 |
74 | 75 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | -------------------------------------------------------------------------------- /app/scripts/controllers/server.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * (c) 2014 Nerve project. All rights reserved. 3 | * Released under GPL v2 license. Read LICENSE for more details. 4 | */ 5 | 6 | 'use-strict'; 7 | 8 | // System that provides the LV2 environment 9 | interface IServerDevice { 10 | name: string; // E.g. 'PlayStation 3', 'Nucleus', 'RPCS3' 11 | type: string; // E.g. 'console', 'emulator' 12 | version: string; // E.g. '4.65 CEX', '1.0.0', '0.0.0.5' 13 | } 14 | 15 | // System that hosts the device providing the LV2 environment (emulators only) 16 | interface IServerHost { 17 | os: string; // E.g. 'Windows 7 SP1' 18 | cpu: string; // E.g. 'Intel Core i7-4770HQ (x86-64)' 19 | } 20 | 21 | // Information about the remote debugging server 22 | interface IServerInformation { 23 | version: string; // E.g. Version of Nerve designed for 24 | device: IServerDevice; 25 | host: IServerHost; 26 | } 27 | 28 | 29 | interface IServerControllerScope extends ng.IScope { 30 | // Represent server status 31 | connected: boolean; 32 | connecting: boolean; 33 | serverAddress: string; 34 | serverInfo: IServerInformation; 35 | 36 | // Manage $server address 37 | connect(string); 38 | disconnect(); 39 | } 40 | 41 | 42 | class ServerController { 43 | private scope: IServerControllerScope; 44 | 45 | constructor($scope: IServerControllerScope, $server: IServerProvider) { 46 | this.scope = $scope; 47 | 48 | $scope.connected = false; 49 | $scope.connecting = false; 50 | $scope.serverAddress = undefined; 51 | 52 | /** 53 | * Connect to the debugger back-end. 54 | * Since the back-end is a RESTful API, no real permanent connection is established, the only 55 | * putpose of this function is validating the user's server address and updating the UI. 56 | */ 57 | $scope.connect = (address: string) => { 58 | // Normalize server address 59 | address.trim(); 60 | if (!(/^http/).test(address)) { 61 | address = "http://" + address; 62 | } 63 | 64 | // Try to connect to the specified server 65 | $scope.connecting = true; 66 | $server.setAddress(address); 67 | $server.get('/connect', (resp) => { 68 | console.log("Connect: Success"); 69 | $scope.connected = true; 70 | $scope.connecting = false; 71 | $scope.serverAddress = address.replace("http://", ""); 72 | $scope.serverInfo = resp; 73 | },(err) => { 74 | console.log("Connect: Error"); 75 | $scope.connected = false; 76 | $scope.connecting = false; 77 | showModal({ 78 | title: "Connection error", 79 | body: "

Could not connect to the specified Nerve back-end server. Make sure the debugger is running, and the address is correct and entered in the format IP:Port.

For example: 127.0.0.1:8080

", 80 | footer: "" 81 | }); 82 | }); 83 | }; 84 | 85 | /** 86 | * Disconnect from the debugger back-end. 87 | * Since the back-end is a RESTful API, no real disconnection happens here, just the UI 88 | * is updated to allow the user connect to a different server. 89 | */ 90 | $scope.disconnect = () => { 91 | console.log("Disconnected"); 92 | $scope.connected = false; 93 | $scope.connecting = false; 94 | } 95 | 96 | //$scope.connect('private-26787-nerve.apiary-mock.com'); 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /app/scripts/cpu.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * (c) 2014 Nerve project. All rights reserved. 3 | * Released under GPL v2 license. Read LICENSE for more details. 4 | */ 5 | 6 | // Capstone.JS disassemblers 7 | declare var capstone: any; 8 | var csPPU = new capstone.Cs(capstone.ARCH_PPC, capstone.MODE_64 | capstone.MODE_BIG_ENDIAN); 9 | //var csSPU = new capstone.Cs(capstone.ARCH_SPU, capstone.MODE_64 | capstone.MODE_BIG_ENDIAN); 10 | 11 | interface INerveCpuControllerScope extends ng.IScope { 12 | // Threading 13 | threadList: IThread[]; 14 | threadCurrent: IThread; 15 | 16 | // Disassembler 17 | disasmAddress: number; 18 | disasmAddressHex: string; 19 | disasmHeight: number; 20 | disasmCache: IMemoryPage[]; 21 | disasmLines: any; 22 | 23 | // Memory 24 | memAddress: number; 25 | memAddressHex: string; 26 | memWidth: number; 27 | memHeight: number; 28 | memCache: IMemoryPage[]; 29 | memLines: any; 30 | 31 | // Registers 32 | regMode: string; 33 | 34 | // Stack 35 | stackAddress: number; 36 | stackAddressHex: string; 37 | stackCache: IMemoryPage[]; 38 | 39 | updateThreads(); 40 | updateDisassembler(); 41 | updateMemory(); 42 | setCurrentThread(IThread); 43 | } 44 | 45 | /** 46 | * CPU controller 47 | */ 48 | class NerveCpuController { 49 | public static $inject = ['$scope', '$server', 'ThreadResource', 'MemoryPageResource']; 50 | 51 | // Resources 52 | public Thread: IThreadResource; 53 | public MemoryPage: IMemoryPageResource; 54 | 55 | constructor($scope: INerveCpuControllerScope, $server: IServerProvider, Thread: IThreadResource, MemoryPage: IMemoryPageResource) { 56 | this.Thread = Thread; 57 | this.MemoryPage = MemoryPage; 58 | 59 | $scope.threadCurrent = undefined; 60 | 61 | // Update the list of threads 62 | $scope.updateThreads = () => { 63 | $scope.threadList = Thread.query(); 64 | } 65 | 66 | // Set current thread 67 | $scope.setCurrentThread = (thread: IThread) => { 68 | $scope.threadCurrent = thread; 69 | }; 70 | 71 | // Disassembler 72 | $scope.disasmHeight = 10; 73 | $scope.disasmAddress = 0x10200; 74 | $scope.disasmCache = []; 75 | $scope.disasmLines = []; 76 | 77 | $scope.$watch('disasmAddress', () => { 78 | $scope.disasmAddressHex = convertNumberToHex($scope.disasmAddress); 79 | this.updateMemoryCache($scope.disasmAddress, $scope.disasmCache); 80 | $scope.updateMemory(); 81 | }); 82 | $scope.$watch('disasmAddressHex', () => { 83 | if ($scope.disasmAddressHex.length == 8) { 84 | $scope.disasmAddress = convertHexToNumber($scope.disasmAddressHex); 85 | } 86 | }); 87 | $scope.$watch('disasmCache', () => { 88 | $scope.updateDisassembler(); 89 | }, true); 90 | 91 | 92 | // Memory 93 | $scope.memWidth = 16; 94 | $scope.memHeight = 10; 95 | $scope.memAddress = 0x10000; 96 | $scope.memCache = []; 97 | $scope.memLines = []; 98 | 99 | $scope.$watch('memAddress', () => { 100 | $scope.memAddressHex = convertNumberToHex($scope.memAddress); 101 | this.updateMemoryCache($scope.memAddress, $scope.memCache); 102 | $scope.updateMemory(); 103 | }); 104 | $scope.$watch('memWidth', () => { 105 | $scope.updateMemory(); 106 | }); 107 | $scope.$watch('memHeight', () => { 108 | $scope.updateMemory(); 109 | }); 110 | $scope.$watch('memCache', () => { 111 | $scope.updateMemory(); 112 | }, true); 113 | $scope.$watch('memAddressHex', () => { 114 | if ($scope.memAddressHex.length == 8) { 115 | $scope.memAddress = convertHexToNumber($scope.memAddressHex); 116 | } 117 | }); 118 | 119 | 120 | // Update content of disassembler panel 121 | $scope.updateDisassembler = () => { 122 | var start = $scope.disasmAddress; 123 | var end = $scope.disasmAddress + 4 * $scope.disasmHeight; 124 | 125 | var disasmLines = []; 126 | for (var addr = start; addr < end; addr += 4) { 127 | for (var i = 0; i < $scope.disasmCache.length; i++) { 128 | if (!$scope.disasmCache[i]) { 129 | return; 130 | } 131 | if ($scope.disasmCache[i].address <= addr && addr < $scope.disasmCache[i].address + $scope.disasmCache[i].size) { 132 | var buffer = []; 133 | for (var byteIndex = 0; byteIndex < 4; byteIndex++) { 134 | var byte = $scope.disasmCache[i].data.substr( 135 | (addr - $scope.disasmCache[i].address + byteIndex) * 2, 136 | 2 137 | ); 138 | buffer.push(parseInt(byte, 16)); 139 | } 140 | 141 | var instruction = csPPU.disasm(buffer, addr); 142 | if (!!instruction[0]) { 143 | disasmLines.push(instruction[0]); 144 | } else { 145 | disasmLines.push({ 146 | address: addr, 147 | bytes: buffer, 148 | mnemonic: '???', 149 | op_str: '' 150 | }); 151 | } 152 | break; 153 | } 154 | } 155 | } 156 | $scope.disasmLines = disasmLines; 157 | }; 158 | 159 | // Update content of memory panel 160 | $scope.updateMemory = () => { 161 | var start = $scope.memAddress; 162 | var end = $scope.memAddress + $scope.memWidth * $scope.memHeight; 163 | var step = $scope.memWidth; 164 | 165 | $scope.memLines = []; 166 | for (var line = start; line < end; line += step) { 167 | for (var i = 0; i < $scope.memCache.length; i++) { 168 | if (!$scope.memCache[i]) { 169 | return; 170 | } 171 | if ($scope.memCache[i].address <= line && line < $scope.memCache[i].address + $scope.memCache[i].size) { 172 | var bytes = $scope.memCache[i].data.substring( 173 | (line - $scope.memCache[i].address) * 2, 174 | (line - $scope.memCache[i].address + $scope.memWidth) * 2 175 | ); 176 | $scope.memLines.push({ 177 | addr: line, 178 | bytesHex: bytes.match(/.{2}/g), 179 | bytesStr: convertHexToString(bytes).split('') 180 | }); 181 | break; 182 | } 183 | } 184 | } 185 | }; 186 | 187 | // Registers 188 | $scope.regMode = 'Integer'; 189 | 190 | // Stack 191 | $scope.stackAddress = 0xD0001000; 192 | $scope.$watch('stackAddress', () => { 193 | $scope.stackAddressHex = convertNumberToHex($scope.stackAddress); 194 | }); 195 | $scope.$watch('stackAddressHex', () => { 196 | if ($scope.stackAddressHex.length == 8) { 197 | $scope.stackAddress = convertHexToNumber($scope.stackAddressHex); 198 | } 199 | }); 200 | } 201 | 202 | /** 203 | * Controller methods 204 | */ 205 | updateMemoryCache(currentAddress: number, cache: IMemoryPage[]) { 206 | var requiredPages = [ 207 | (currentAddress & ~(4096 - 1)) - 4096, 208 | (currentAddress & ~(4096 - 1)), 209 | (currentAddress & ~(4096 - 1)) + 4096 210 | ]; 211 | 212 | // Remove old cache 213 | for (var i = 0; i < cache.length; i++) { 214 | var requiredIndex = requiredPages.indexOf(cache[i].address); 215 | if (requiredIndex < 0) { 216 | cache.splice(i, 1); 217 | } else { 218 | requiredPages.splice(requiredIndex, 1); 219 | } 220 | } 221 | 222 | // Cache new pages 223 | for (var i = 0; i < requiredPages.length; i++) { 224 | console.log("Memory: Requested page: " + requiredPages[i]); 225 | cache.push(this.MemoryPage.get({ address: requiredPages[i] })); 226 | } 227 | } 228 | } 229 | -------------------------------------------------------------------------------- /app/scripts/filters/hexadecimal.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * (c) 2014 Nerve project. All rights reserved. 3 | * Released under GPL v2 license. Read LICENSE for more details. 4 | */ 5 | 6 | // Converts a number into a '%0#X' string, where # is the requested length 7 | function HexadecimalFilter() { 8 | return (value: any, length: number = 8) => { 9 | var str = '0000000000000000' + value.toString(16).toUpperCase(); 10 | return str.slice(-length); 11 | }; 12 | } 13 | -------------------------------------------------------------------------------- /app/scripts/nerve.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * (c) 2014 Nerve project. All rights reserved. 3 | * Released under GPL v2 license. Read LICENSE for more details. 4 | */ 5 | 6 | /// 7 | /// 8 | /// 9 | /// 10 | 11 | /** 12 | * Bootstrap 13 | */ 14 | 15 | // Enable Tooltips 16 | $('[data-toggle="tooltip"]').tooltip({ html: true }); 17 | 18 | 19 | /** 20 | * AngularJS 21 | */ 22 | var nerve = angular.module('nerve', ['ngResource', 'ngRoute']); 23 | 24 | // Config 25 | nerve.config(['$routeProvider', ($routeProvider) => { 26 | $routeProvider 27 | .when('/', { 28 | templateUrl: 'views/intro.html', 29 | }) 30 | .when('/general', { 31 | templateUrl: 'views/general.html', 32 | }) 33 | .when('/cpu', { 34 | templateUrl: 'views/cpu.html', 35 | controller: 'NerveCpuController' 36 | }) 37 | .when('/gpu', { 38 | templateUrl: 'views/gpu.html', 39 | }) 40 | .when('/memory', { 41 | templateUrl: 'views/memory.html', 42 | }) 43 | .when('/files', { 44 | templateUrl: 'views/files.html', 45 | }) 46 | .when('/system', { 47 | templateUrl: 'views/system.html', 48 | }) 49 | .otherwise({ 50 | redirectTo: '/' 51 | }); 52 | }]); 53 | 54 | // Services 55 | nerve.factory('$server', ($http) => new ServerProvider($http)); 56 | nerve.factory('MemoryPageResource', MemoryPageResource); 57 | 58 | // Factories 59 | nerve.factory('ThreadResource', ThreadResource); 60 | 61 | // Controllers 62 | nerve.controller('ServerController', ['$scope', '$server', ServerController]); 63 | nerve.controller('NerveCpuController', NerveCpuController); 64 | 65 | // Filters 66 | nerve.filter('hexadecimal', HexadecimalFilter); 67 | 68 | /** 69 | * Nerve UI 70 | */ 71 | 72 | // Directives 73 | nerve.directive('nuiToolbar', () => new nui.ToolbarDirective()); 74 | nerve.directive('nuiRadioGroup', () => new nui.RadioGroupDirective()); 75 | nerve.directive('nuiRadio', () => new nui.RadioDirective()); 76 | -------------------------------------------------------------------------------- /app/scripts/services/cpu.thread.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * (c) 2014 Nerve project. All rights reserved. 3 | * Released under GPL v2 license. Read LICENSE for more details. 4 | */ 5 | 6 | interface IThread extends ng.resource.IResource { 7 | id: number; 8 | type: string; 9 | name: string; 10 | state: string; 11 | } 12 | 13 | interface IThreadResource extends ng.resource.IResourceClass { 14 | } 15 | 16 | function ThreadResource($resource: ng.resource.IResourceService, $server: ServerProvider) { 17 | return $resource($server.getAddress() + '/cpu/threads/:id', { id: '@id' }); 18 | } 19 | -------------------------------------------------------------------------------- /app/scripts/services/memory.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * (c) 2014 Nerve project. All rights reserved. 3 | * Released under GPL v2 license. Read LICENSE for more details. 4 | */ 5 | 6 | interface IMemoryPage extends ng.resource.IResource { 7 | address: number; 8 | size: number; 9 | data: string; 10 | } 11 | 12 | interface IMemoryPageResource extends ng.resource.IResourceClass { 13 | } 14 | 15 | function MemoryPageResource($resource: ng.resource.IResourceService, $server: ServerProvider) { 16 | return $resource($server.getAddress() + '/memory/:address', { address: '@address' }); 17 | } 18 | -------------------------------------------------------------------------------- /app/scripts/services/server.provider.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * (c) 2014 Nerve project. All rights reserved. 3 | * Released under GPL v2 license. Read LICENSE for more details. 4 | */ 5 | 6 | 'use strict'; 7 | 8 | interface IServer { 9 | address: string; 10 | 11 | } 12 | 13 | interface IServerProvider { 14 | setAddress(string); 15 | get(string, successHandler, errorHandler): string; 16 | } 17 | 18 | class ServerProvider implements IServerProvider { 19 | private http: any; 20 | private address: string; 21 | 22 | constructor($http: ng.IHttpService) { 23 | this.http = $http; 24 | } 25 | 26 | getAddress(): string { 27 | return this.address; 28 | } 29 | 30 | setAddress(address: string) { 31 | this.address = address; 32 | } 33 | 34 | get(uri: string, successHandler, errorHandler): string { 35 | var url = this.address + uri; 36 | return this.http.get(url).success(successHandler).error(errorHandler); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /app/scripts/ui.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * (c) 2014 Nerve project. All rights reserved. 3 | * Released under GPL v2 license. Read LICENSE for more details. 4 | */ 5 | 6 | // Display Bootstrap Modal: Adjusts the Modal parameters and shows it 7 | function showModal(args) { 8 | $(".modal-title").html(args.title); 9 | $(".modal-body").html(args.body); 10 | $(".modal-footer").html(args.footer); 11 | $(".modal-close").focus(); 12 | $(".modal").modal('show'); 13 | } 14 | 15 | /** 16 | * Nerve UI 17 | */ 18 | module nui { 19 | 20 | // Toolbar 21 | export class ToolbarDirective implements ng.IDirective { 22 | restruct = 'E'; 23 | transclude = true; 24 | template = '
'; 25 | } 26 | 27 | // Radio 28 | export class RadioGroupDirective implements ng.IDirective { 29 | require = 'ngModel'; 30 | restrict = 'E'; 31 | transclude = true; 32 | template = '
'; 33 | link = (scope, element, attr, controller) => { 34 | var radioChildren = element[0].querySelectorAll('nui-radio'); 35 | 36 | // View -> Model 37 | angular.forEach(radioChildren, (child) => { 38 | $(child).bind('click', () => { 39 | scope.$apply(() => { 40 | var childValue = $(child).attr('ng-value'); 41 | controller.$setViewValue(childValue); 42 | controller.$render(); 43 | }); 44 | }); 45 | }); 46 | 47 | // Model -> View 48 | controller.$render = () => { 49 | angular.forEach(radioChildren, (child) => { 50 | var childValue = $(child).attr('ng-value'); 51 | var isEqual = angular.equals(controller.$modelValue, childValue); 52 | if (isEqual) { 53 | $(child).find("input").attr('checked'); 54 | } else { 55 | $(child).find("input").removeAttr('checked'); 56 | } 57 | }); 58 | }; 59 | } 60 | } 61 | 62 | export class RadioDirective implements ng.IDirective { 63 | restrict = 'E'; 64 | transclude = true; 65 | template = ''; 66 | } 67 | } -------------------------------------------------------------------------------- /app/scripts/util.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * (c) 2014 Nerve project. All rights reserved. 3 | * Released under GPL v2 license. Read LICENSE for more details. 4 | */ 5 | 6 | var printableCharacters = []; 7 | for (var i = 0x00; i < 0x020; i++) printableCharacters.push('.'); 8 | for (var i = 0x20; i < 0x07F; i++) printableCharacters.push(String.fromCharCode(i)); 9 | for (var i = 0x7F; i < 0x100; i++) printableCharacters.push('.'); 10 | 11 | // Converts a number into a "%08X" string 12 | function convertNumberToHex(n: number) { 13 | var str = '00000000' + n.toString(16).toUpperCase(); 14 | return str.slice(-8) 15 | } 16 | 17 | // Converts a "%08X" string into a number 18 | function convertHexToNumber(s: string) { 19 | return parseInt(s, 16); 20 | } 21 | 22 | // Converts a hexadecimal string "%02X%02X%02X" intro a string "aaa" 23 | function convertHexToString(hexStr: string) { 24 | var str = ''; 25 | for (var i = 0; i < hexStr.length; i += 2) { 26 | str += printableCharacters[parseInt(hexStr.substr(i, 2), 16)]; 27 | } 28 | return str; 29 | } 30 | -------------------------------------------------------------------------------- /app/styles/nerve.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Navbar 3 | */ 4 | .navbar { 5 | border: 0px; 6 | background: #3C3F41; 7 | color: #fff; 8 | font-weight: 400; 9 | font-size: 16px; 10 | } 11 | 12 | .nav > li > .navbar-brand { 13 | font-weight: 700; 14 | font-size: 18px; 15 | color: #fff; 16 | transition: text-shadow 0.2s; 17 | } 18 | 19 | .nav > li > .navbar-brand:hover { 20 | background: #3C3F41; 21 | color: #fff; 22 | text-shadow: 0px 2px 10px #000; 23 | } 24 | 25 | .nav > li > a { 26 | color: #ddd; 27 | transition: background 0.2s; 28 | } 29 | 30 | .nav > li > a:hover { 31 | background: #5D5F60; 32 | } 33 | 34 | /* TODO: Remove once we get rid of Bootstrap's :focus changes */ 35 | .nav > li > a:focus { 36 | background: #3C3F41; 37 | } 38 | 39 | .nav > li > .disabled { 40 | color: #888; 41 | cursor: default; 42 | } 43 | 44 | /** 45 | * Body 46 | */ 47 | html { 48 | height: 100%; 49 | } 50 | 51 | body { 52 | margin-top: 50px; 53 | height: calc(100% - 50px); 54 | overflow-y: hidden; 55 | font-family: "Roboto Condensed", sans-serif; 56 | font-size: 16px; 57 | } 58 | 59 | a { 60 | cursor: pointer; 61 | } 62 | 63 | /** 64 | * Jumbotron 65 | */ 66 | .jumbotron { 67 | background-image: url('../images/background.jpg'); 68 | background-size: 100%; 69 | color: #eee; 70 | } 71 | 72 | /** 73 | * Nerve 74 | */ 75 | #nerve-server-status { 76 | color: #ccc; 77 | cursor: default; 78 | font-weight: 300; 79 | padding: 15px; 80 | line-height: 20px; 81 | } 82 | 83 | .tab-content > .container { 84 | padding: 0px; 85 | } 86 | 87 | /** 88 | * CPU 89 | */ 90 | .nerve-cpu-disassembler td { 91 | font-family: 'Inconsolata'; 92 | font-size: 14px; 93 | } 94 | 95 | .nerve-cpu-registers td { 96 | font-family: 'Inconsolata'; 97 | font-size: 14px; 98 | padding-left: 10px; 99 | margin: 10px; 100 | } 101 | -------------------------------------------------------------------------------- /app/styles/ui.css: -------------------------------------------------------------------------------- 1 | /** 2 | * CSS Loading Spinner 3 | * https://twitter.com/lukehaas 4 | */ 5 | .loader { 6 | font-size: 10px; 7 | position: relative; 8 | text-indent: -9999em; 9 | border-top: 4px solid rgba(255, 255, 255, 0.2); 10 | border-right: 4px solid rgba(255, 255, 255, 0.2); 11 | border-bottom: 4px solid rgba(255, 255, 255, 0.2); 12 | border-left: 4px solid #ffffff; 13 | -webkit-animation: load8 1.1s infinite linear; 14 | animation: load8 1.1s infinite linear; 15 | } 16 | 17 | .loader, .loader:after { 18 | border-radius: 50%; 19 | width: 20px; 20 | height: 20px; 21 | } 22 | 23 | @-webkit-keyframes load8 { 24 | 0% { 25 | -webkit-transform: rotate(0deg); 26 | transform: rotate(0deg); 27 | } 28 | 100% { 29 | -webkit-transform: rotate(360deg); 30 | transform: rotate(360deg); 31 | } 32 | } 33 | 34 | @keyframes load8 { 35 | 0% { 36 | -webkit-transform: rotate(0deg); 37 | transform: rotate(0deg); 38 | } 39 | 100% { 40 | -webkit-transform: rotate(360deg); 41 | transform: rotate(360deg); 42 | } 43 | } 44 | 45 | /** 46 | * Static text box for the Bootstrap btn-group's 47 | * Equivalent to .input-group-addon 48 | */ 49 | .btn-group-sm > .btn-group-addon { 50 | padding: 5px 10px; 51 | font-size: 12px; 52 | line-height: 1.5; 53 | border-radius: 3px; 54 | } 55 | 56 | .btn-group > .btn-group-addon { 57 | position: relative; 58 | float: left; 59 | } 60 | .btn-group-addon { 61 | white-space: nowrap; 62 | vertical-align: middle; 63 | display: table-cell; 64 | padding: 6px 12px; 65 | font-size: 14px; 66 | font-weight: normal; 67 | line-height: 1; 68 | color: #555; 69 | text-align: center; 70 | background-color: #eee; 71 | border: 0px solid #ccc; 72 | margin: 1px 0px 1px 1px; 73 | border-radius: 4px; 74 | } 75 | .btn-group-addon:not(:first-child):not(:last-child) { 76 | border-radius: 0; 77 | } 78 | .btn-group-addon:first-child { 79 | border-right: 0; 80 | border-top-right-radius: 0; 81 | border-bottom-right-radius: 0; 82 | } 83 | .btn-group-addon:last-child { 84 | border-left: 0; 85 | border-top-left-radius: 0; 86 | border-bottom-left-radius: 0; 87 | } 88 | 89 | /** 90 | * Widgets 91 | */ 92 | .widget-title { 93 | font-family: "Roboto Condensed", sans-serif, bold; 94 | font-weight: 400; 95 | font-size: 20px; 96 | } 97 | 98 | .nui-toolbar > .widget-input { 99 | float: left; 100 | position: relative; 101 | display: inline-block; 102 | vertical-align: middle; 103 | margin-right: 2px; 104 | } 105 | 106 | .nui-toolbar > .widget-input > * { 107 | float: left; 108 | } 109 | 110 | .nui-toolbar > .widget-input > span { 111 | width: 60px; 112 | } 113 | 114 | .widget-input > .form-control { 115 | font-family: 'Inconsolata'; 116 | font-size: 14px; 117 | width: 80px; 118 | } 119 | 120 | .widget-content { 121 | padding: 5px 10px; 122 | background-color: #eee; 123 | } 124 | 125 | .widget-content .monospaced { 126 | font-family: 'Inconsolata'; 127 | font-size: 14px; 128 | } 129 | 130 | /** 131 | * UI-related 132 | */ 133 | .nui-toolbar { 134 | width: 100%; 135 | height: 36px; 136 | padding: 3px; 137 | background-color: #ccc; 138 | display: block; 139 | } 140 | 141 | .nui-input-group .nui-button { 142 | background-color: #fff; 143 | border: 1px solid transparent; 144 | border-color: #ccc; 145 | border-radius: 3px; 146 | 147 | font-size: 12px; 148 | font-weight: normal; 149 | text-align: center; 150 | 151 | padding: 5px 10px; 152 | line-height: 1.5; 153 | vertical-align: middle; 154 | cursor: pointer; 155 | } 156 | .nui-input-group .nui-button:hover { 157 | background-color: #eee; 158 | } 159 | -------------------------------------------------------------------------------- /app/views/cpu.html: -------------------------------------------------------------------------------- 1 | 2 |
3 | 4 | 5 | 6 | 7 |
8 |
9 | 10 |
11 | 22 | 32 |
33 | 34 | 35 | 36 |
37 |
38 | 39 |
40 |
41 |
42 |
Disassembler
43 | 44 |
45 | Address 46 | 47 |
48 |
49 |
50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 |
{{ line.address | hexadecimal }}{{ byte | hexadecimal:2 }}{{ line.mnemonic }}{{ line.op_str }}
61 |
62 |
63 |
64 |
Memory
65 | 66 |
67 | Address 68 | 69 |
70 |
71 | Width 72 | 73 |
74 |
75 | Height 76 | 77 |
78 |
79 |
80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 |
{{ line.addr | hexadecimal }}{{ byteHex }}{{ byteStr }}
89 |
90 |
91 |
92 | 93 |
94 |
95 |
Registers
96 | 97 | 98 | Integer 99 | Float 100 | Vector 101 | 102 | 103 |
104 |
105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 |
r0????????????????r16????????????????
r1????????????????r17????????????????
r2????????????????r18????????????????
r3????????????????r19????????????????
r4????????????????r20????????????????
r5????????????????r21????????????????
r6????????????????r22????????????????
r7????????????????r23????????????????
r8????????????????r24????????????????
r9????????????????r25????????????????
r10????????????????r26????????????????
r11????????????????r27????????????????
r12????????????????r28????????????????
r13????????????????r29????????????????
r14????????????????r30????????????????
r15????????????????r31????????????????
123 |
124 |
125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 |
fr0????????????????fr16????????????????
fr1????????????????fr17????????????????
fr2????????????????fr18????????????????
fr3????????????????fr19????????????????
fr4????????????????fr20????????????????
fr5????????????????fr21????????????????
fr6????????????????fr22????????????????
fr7????????????????fr23????????????????
fr8????????????????fr24????????????????
fr9????????????????fr25????????????????
fr10????????????????fr26????????????????
fr11????????????????fr27????????????????
fr12????????????????fr28????????????????
fr13????????????????fr29????????????????
fr14????????????????fr30????????????????
fr15????????????????fr31????????????????
143 |
144 |
145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 |
vr0???????? ???????? ???????? ????????
vr1???????? ???????? ???????? ????????
vr2???????? ???????? ???????? ????????
vr3???????? ???????? ???????? ????????
vr4???????? ???????? ???????? ????????
vr5???????? ???????? ???????? ????????
vr6???????? ???????? ???????? ????????
vr7???????? ???????? ???????? ????????
vr8???????? ???????? ???????? ????????
vr9???????? ???????? ???????? ????????
vr10???????? ???????? ???????? ????????
vr11???????? ???????? ???????? ????????
vr12???????? ???????? ???????? ????????
vr13???????? ???????? ???????? ????????
vr14???????? ???????? ???????? ????????
vr15???????? ???????? ???????? ????????
vr16???????? ???????? ???????? ????????
vr17???????? ???????? ???????? ????????
vr18???????? ???????? ???????? ????????
vr19???????? ???????? ???????? ????????
vr20???????? ???????? ???????? ????????
vr21???????? ???????? ???????? ????????
vr22???????? ???????? ???????? ????????
vr23???????? ???????? ???????? ????????
vr24???????? ???????? ???????? ????????
vr25???????? ???????? ???????? ????????
vr26???????? ???????? ???????? ????????
vr27???????? ???????? ???????? ????????
vr28???????? ???????? ???????? ????????
vr29???????? ???????? ???????? ????????
vr30???????? ???????? ???????? ????????
vr31???????? ???????? ???????? ????????
179 |
180 |
181 |
182 |
183 |
Stack
184 | 185 |
186 | Address 187 | 188 |
189 |
190 |
191 | Test 192 |
193 |
194 |
195 |
196 | -------------------------------------------------------------------------------- /app/views/files.html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexAltea/nerve/cd9911628883dd745df2224b4b8d5164980ae3e4/app/views/files.html -------------------------------------------------------------------------------- /app/views/general.html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexAltea/nerve/cd9911628883dd745df2224b4b8d5164980ae3e4/app/views/general.html -------------------------------------------------------------------------------- /app/views/gpu.html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexAltea/nerve/cd9911628883dd745df2224b4b8d5164980ae3e4/app/views/gpu.html -------------------------------------------------------------------------------- /app/views/intro.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |

Nerve

4 |

An online front-end for PlayStation 3 debuggers.

5 |
6 |
7 |
8 |
9 |
10 |

Connection

11 |

Enter the address of the debugger back-end server in the top right corner. All interaction with the device goes through the RESTful API the back-end server offers. More information at: Nerve API documentation.

12 |

Remember to enter the server's address in the IP:Port format (e.g. 127.0.0.1:8080). A mock server is available at:

13 |

private-26787-nerve.apiary-mock.com

14 |
15 |
16 |

Features

17 |

At the moment, Nerve is far from finished and the only back-end available for it is the PS3 emulator Nucleus. These are the offered debugging features:

18 |
    19 |
  • Nothing!
  • 20 |
21 |
22 |
23 |

Goals

24 |

For receiving news about Nerve and accessing its source code and API documentation, visit Nerve's repo. These are the features I have planned:

25 |
    26 |
  • PPU debugger
  • 27 |
  • Memory viewer
  • 28 |
  • LV2 kernel explorer
  • 29 |
30 |
31 |
32 |
33 | -------------------------------------------------------------------------------- /app/views/memory.html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexAltea/nerve/cd9911628883dd745df2224b4b8d5164980ae3e4/app/views/memory.html -------------------------------------------------------------------------------- /app/views/system.html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexAltea/nerve/cd9911628883dd745df2224b4b8d5164980ae3e4/app/views/system.html -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nerve", 3 | "version": "0.0.1", 4 | "description": "Front-end for PlayStation 3 debuggers", 5 | "authors": [ 6 | "Alexandro Sanchez Bach " 7 | ], 8 | "license": "GPL-2.0", 9 | "repository": { 10 | "type": "git", 11 | "url": "https://github.com/AlexAltea/nerve.git" 12 | }, 13 | "dependencies": { 14 | "angular": "^1.3.3", 15 | "angular-resource": "^1.3.3", 16 | "angular-route": "~1.3.4", 17 | "bootstrap": "^3.2.0" 18 | }, 19 | "devDependencies": {}, 20 | "private": true 21 | } 22 | -------------------------------------------------------------------------------- /dist/.gitignore: -------------------------------------------------------------------------------- 1 | # Allow external scripts not available in Bower 2 | !externals 3 | externals/* 4 | !externals/capstone/ 5 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nerve", 3 | "version": "0.0.1", 4 | "description": "Front-end for PlayStation 3 debuggers", 5 | "author": "Alexandro Sanchez Bach ", 6 | "license": "GPL-2.0", 7 | "repository": { 8 | "type": "git", 9 | "url": "https://github.com/AlexAltea/nerve.git" 10 | }, 11 | "dependencies": {}, 12 | "devDependencies": { 13 | "bower": "^1.3.12", 14 | "grunt": "^0.4.5", 15 | "grunt-cli": "^0.1.13", 16 | "grunt-contrib-connect": "^0.9.0", 17 | "grunt-contrib-copy": "^0.7.0", 18 | "grunt-contrib-cssmin": "^0.10.0", 19 | "grunt-contrib-htmlmin": "^0.3.0", 20 | "grunt-contrib-uglify": "^0.6.0", 21 | "grunt-contrib-watch": "^0.6.1", 22 | "grunt-typescript": "^0.6.1", 23 | "grunt-wiredep": "^1.9.0", 24 | "load-grunt-tasks": "^1.0.0", 25 | "time-grunt": "^1.0.0", 26 | "tsd": "next", 27 | "typescript": "^1.4.1" 28 | }, 29 | "bugs": { 30 | "url": "https://github.com/AlexAltea/nerve/issues" 31 | }, 32 | "scripts": { 33 | "test": "grunt test" 34 | }, 35 | "private": true 36 | } 37 | -------------------------------------------------------------------------------- /tsd.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "v4", 3 | "repo": "borisyankov/DefinitelyTyped", 4 | "ref": "master", 5 | "path": "typings", 6 | "bundle": "typings/tsd.d.ts", 7 | "installed": { 8 | "angularjs/angular.d.ts": { 9 | "commit": "b3324f69165309a3ea2bd02fd10e97841bf07c83" 10 | }, 11 | "angularjs/angular-resource.d.ts": { 12 | "commit": "b3324f69165309a3ea2bd02fd10e97841bf07c83" 13 | }, 14 | "bootstrap/bootstrap.d.ts": { 15 | "commit": "b3324f69165309a3ea2bd02fd10e97841bf07c83" 16 | }, 17 | "jquery/jquery.d.ts": { 18 | "commit": "b3324f69165309a3ea2bd02fd10e97841bf07c83" 19 | } 20 | } 21 | } 22 | --------------------------------------------------------------------------------