From 9063766ed628152f339c9f4327addf0f40d94201 Mon Sep 17 00:00:00 2001
From: gdkchan <gab.dark.100@gmail.com>
Date: Sat, 10 Feb 2018 10:24:16 -0300
Subject: [PATCH] Add BRK instruction, fix wrong namespace on one of Am
 interfaces, and disable Debug/Trace logs by default

---
 Ryujinx.conf                                         |  4 ++--
 Ryujinx/Cpu/Decoder/ADecoder.cs                      |  3 ++-
 Ryujinx/Cpu/Decoder/AOpCodeException.cs              |  2 +-
 Ryujinx/Cpu/Instruction/AInstEmitException.cs        | 12 +++++++++++-
 .../{SvcEventArgs.cs => AExceptionEventArgs.cs}      |  4 ++--
 Ryujinx/Cpu/State/ARegisters.cs                      | 12 +++++++++---
 .../OsHle/Exceptions/GuestBrokeExecutionException.cs | 11 +++++++++++
 Ryujinx/OsHle/Objects/Am/IApplicationProxy.cs        |  3 +--
 Ryujinx/OsHle/Process.cs                             |  8 ++++++++
 Ryujinx/OsHle/ServiceCtx.cs                          |  2 +-
 Ryujinx/OsHle/Services/ServiceAppletOE.cs            |  2 +-
 Ryujinx/OsHle/Svc/SvcHandler.cs                      |  4 ++--
 12 files changed, 51 insertions(+), 16 deletions(-)
 rename Ryujinx/Cpu/State/{SvcEventArgs.cs => AExceptionEventArgs.cs} (61%)
 create mode 100644 Ryujinx/OsHle/Exceptions/GuestBrokeExecutionException.cs

diff --git a/Ryujinx.conf b/Ryujinx.conf
index 590318fe78..ee21ad904f 100644
--- a/Ryujinx.conf
+++ b/Ryujinx.conf
@@ -2,10 +2,10 @@
 Logging_Enable_Info = true
 
 #Enabled print trace logs
-Logging_Enable_Trace = true
+Logging_Enable_Trace = false
 
 #Enabled print debug logs
-Logging_Enable_Debug = true
+Logging_Enable_Debug = false
 
 #Enabled print warning logs
 Logging_Enable_Warn = true
diff --git a/Ryujinx/Cpu/Decoder/ADecoder.cs b/Ryujinx/Cpu/Decoder/ADecoder.cs
index 1d34003965..5eb0e0dd06 100644
--- a/Ryujinx/Cpu/Decoder/ADecoder.cs
+++ b/Ryujinx/Cpu/Decoder/ADecoder.cs
@@ -150,7 +150,8 @@ namespace ChocolArm64.Decoder
 
         private static bool IsException(AOpCode OpCode)
         {
-            return OpCode.Emitter == AInstEmit.Svc ||
+            return OpCode.Emitter == AInstEmit.Brk ||
+                   OpCode.Emitter == AInstEmit.Svc ||
                    OpCode.Emitter == AInstEmit.Und;
         }
 
diff --git a/Ryujinx/Cpu/Decoder/AOpCodeException.cs b/Ryujinx/Cpu/Decoder/AOpCodeException.cs
index 6d4a03861b..c3591a920b 100644
--- a/Ryujinx/Cpu/Decoder/AOpCodeException.cs
+++ b/Ryujinx/Cpu/Decoder/AOpCodeException.cs
@@ -8,7 +8,7 @@ namespace ChocolArm64.Decoder
 
         public AOpCodeException(AInst Inst, long Position, int OpCode) : base(Inst, Position)
         {
-            Id = (OpCode >> 5) & 0xfff;
+            Id = (OpCode >> 5) & 0xffff;
         }
     }
 }
\ No newline at end of file
diff --git a/Ryujinx/Cpu/Instruction/AInstEmitException.cs b/Ryujinx/Cpu/Instruction/AInstEmitException.cs
index 2f1edf7816..c343291a3c 100644
--- a/Ryujinx/Cpu/Instruction/AInstEmitException.cs
+++ b/Ryujinx/Cpu/Instruction/AInstEmitException.cs
@@ -7,7 +7,17 @@ namespace ChocolArm64.Instruction
 {
     static partial class AInstEmit
     {
+        public static void Brk(AILEmitterCtx Context)
+        {
+            EmitExceptionCall(Context, nameof(ARegisters.OnBreak));
+        }
+
         public static void Svc(AILEmitterCtx Context)
+        {
+            EmitExceptionCall(Context, nameof(ARegisters.OnSvcCall));
+        }
+
+        private static void EmitExceptionCall(AILEmitterCtx Context, string MthdName)
         {
             AOpCodeException Op = (AOpCodeException)Context.CurrOp;
 
@@ -17,7 +27,7 @@ namespace ChocolArm64.Instruction
 
             Context.EmitLdc_I4(Op.Id);
 
-            Context.EmitCall(typeof(ARegisters), nameof(ARegisters.OnSvcCall));
+            Context.EmitCall(typeof(ARegisters), MthdName);
 
             if (Context.CurrBlock.Next != null)
             {
diff --git a/Ryujinx/Cpu/State/SvcEventArgs.cs b/Ryujinx/Cpu/State/AExceptionEventArgs.cs
similarity index 61%
rename from Ryujinx/Cpu/State/SvcEventArgs.cs
rename to Ryujinx/Cpu/State/AExceptionEventArgs.cs
index 3a43241a64..53d2ed4821 100644
--- a/Ryujinx/Cpu/State/SvcEventArgs.cs
+++ b/Ryujinx/Cpu/State/AExceptionEventArgs.cs
@@ -2,11 +2,11 @@ using System;
 
 namespace ChocolArm64.State
 {
-    public class SvcEventArgs : EventArgs
+    public class AExceptionEventArgs : EventArgs
     {
         public int Id { get; private set; }
 
-        public SvcEventArgs(int Id)
+        public AExceptionEventArgs(int Id)
         {
             this.Id = Id;
         }
diff --git a/Ryujinx/Cpu/State/ARegisters.cs b/Ryujinx/Cpu/State/ARegisters.cs
index 76b8f9b3a6..1a8f2f13a3 100644
--- a/Ryujinx/Cpu/State/ARegisters.cs
+++ b/Ryujinx/Cpu/State/ARegisters.cs
@@ -42,12 +42,18 @@ namespace ChocolArm64.State
 
         public long CntpctEl0 => Environment.TickCount * TicksPerMS;
 
-        public event EventHandler<SvcEventArgs> SvcCall;
-        public event EventHandler<EventArgs>    Undefined;
+        public event EventHandler<AExceptionEventArgs> Break;
+        public event EventHandler<AExceptionEventArgs> SvcCall;
+        public event EventHandler<EventArgs>           Undefined;
+
+        public void OnBreak(int Imm)
+        {
+            Break?.Invoke(this, new AExceptionEventArgs(Imm));
+        }
 
         public void OnSvcCall(int Imm)
         {
-            SvcCall?.Invoke(this, new SvcEventArgs(Imm));
+            SvcCall?.Invoke(this, new AExceptionEventArgs(Imm));
         }
 
         public void OnUndefined()
diff --git a/Ryujinx/OsHle/Exceptions/GuestBrokeExecutionException.cs b/Ryujinx/OsHle/Exceptions/GuestBrokeExecutionException.cs
new file mode 100644
index 0000000000..1369c57b23
--- /dev/null
+++ b/Ryujinx/OsHle/Exceptions/GuestBrokeExecutionException.cs
@@ -0,0 +1,11 @@
+using System;
+
+namespace Ryujinx.OsHle.Exceptions
+{
+    public class GuestBrokeExecutionException : Exception
+    {
+        private const string ExMsg = "The guest program broke execution!";
+
+        public GuestBrokeExecutionException() : base(ExMsg) { }
+    }
+}
\ No newline at end of file
diff --git a/Ryujinx/OsHle/Objects/Am/IApplicationProxy.cs b/Ryujinx/OsHle/Objects/Am/IApplicationProxy.cs
index 15940f6708..3d692d6bc9 100644
--- a/Ryujinx/OsHle/Objects/Am/IApplicationProxy.cs
+++ b/Ryujinx/OsHle/Objects/Am/IApplicationProxy.cs
@@ -1,10 +1,9 @@
 using Ryujinx.OsHle.Ipc;
-using Ryujinx.OsHle.Objects.Am;
 using System.Collections.Generic;
 
 using static Ryujinx.OsHle.Objects.ObjHelper;
 
-namespace Ryujinx.OsHle.Objects
+namespace Ryujinx.OsHle.Objects.Am
 {
     class IApplicationProxy : IIpcInterface
     {
diff --git a/Ryujinx/OsHle/Process.cs b/Ryujinx/OsHle/Process.cs
index b723b165ce..3c91605a80 100644
--- a/Ryujinx/OsHle/Process.cs
+++ b/Ryujinx/OsHle/Process.cs
@@ -1,7 +1,9 @@
 using ChocolArm64;
 using ChocolArm64.Memory;
+using ChocolArm64.State;
 using Ryujinx.Loaders;
 using Ryujinx.Loaders.Executables;
+using Ryujinx.OsHle.Exceptions;
 using Ryujinx.OsHle.Handles;
 using Ryujinx.OsHle.Svc;
 using System;
@@ -135,6 +137,7 @@ namespace Ryujinx.OsHle
                 return -1;
             }
 
+            Thread.Registers.Break    += BreakHandler;
             Thread.Registers.SvcCall  += SvcHandler.SvcCall;
             Thread.Registers.ProcessId = ProcessId;
             Thread.Registers.ThreadId  = Ns.Os.IdGen.GenerateId();
@@ -148,6 +151,11 @@ namespace Ryujinx.OsHle
             return Handle;
         }
 
+        private void BreakHandler(object sender, AExceptionEventArgs e)
+        {
+            throw new GuestBrokeExecutionException();
+        }
+
         private int GetFreeTlsSlot(AThread Thread)
         {
             for (int Index = 1; Index < TotalTlsSlots; Index++)
diff --git a/Ryujinx/OsHle/ServiceCtx.cs b/Ryujinx/OsHle/ServiceCtx.cs
index 61356e6ccd..501d8d0f01 100644
--- a/Ryujinx/OsHle/ServiceCtx.cs
+++ b/Ryujinx/OsHle/ServiceCtx.cs
@@ -7,7 +7,7 @@ namespace Ryujinx.OsHle
 {
     class ServiceCtx
     {
-        public Switch       Ns         { get; private set; }
+        public Switch       Ns           { get; private set; }
         public AMemory      Memory       { get; private set; }
         public HSession     Session      { get; private set; }
         public IpcMessage   Request      { get; private set; }
diff --git a/Ryujinx/OsHle/Services/ServiceAppletOE.cs b/Ryujinx/OsHle/Services/ServiceAppletOE.cs
index cd0ed92bcb..9f2391df73 100644
--- a/Ryujinx/OsHle/Services/ServiceAppletOE.cs
+++ b/Ryujinx/OsHle/Services/ServiceAppletOE.cs
@@ -1,4 +1,4 @@
-using Ryujinx.OsHle.Objects;
+using Ryujinx.OsHle.Objects.Am;
 
 using static Ryujinx.OsHle.Objects.ObjHelper;
 
diff --git a/Ryujinx/OsHle/Svc/SvcHandler.cs b/Ryujinx/OsHle/Svc/SvcHandler.cs
index 9aea2dedb2..ccff71e4c9 100644
--- a/Ryujinx/OsHle/Svc/SvcHandler.cs
+++ b/Ryujinx/OsHle/Svc/SvcHandler.cs
@@ -63,7 +63,7 @@ namespace Ryujinx.OsHle.Svc
             Rng = new Random();
         }
 
-        public void SvcCall(object sender, SvcEventArgs e)
+        public void SvcCall(object sender, AExceptionEventArgs e)
         {
             ARegisters Registers = (ARegisters)sender;
 
@@ -75,7 +75,7 @@ namespace Ryujinx.OsHle.Svc
             }
             else
             {
-                throw new NotImplementedException(e.Id.ToString("x3"));
+                throw new NotImplementedException(e.Id.ToString("x4"));
             }
         }
     }