/*## (c) SECURITY EXPLORATIONS    2018 poland                                #*/
/*##     http://www.security-explorations.com                                #*/

/* THIS SOFTWARE IS PROTECTED BY DOMESTIC AND INTERNATIONAL COPYRIGHT LAWS    */
/* UNAUTHORISED COPYING OF THIS SOFTWARE IN EITHER SOURCE OR BINARY FORM IS   */
/* EXPRESSLY FORBIDDEN. ANY USE, INCLUDING THE REPRODUCTION, MODIFICATION,    */
/* DISTRIBUTION, TRANSMISSION, RE-PUBLICATION, STORAGE OR DISPLAY OF ANY      */
/* PART OF THE SOFTWARE, FOR COMMERCIAL OR ANY OTHER PURPOSES REQUIRES A      */
/* VALID LICENSE FROM THE COPYRIGHT HOLDER.                                   */

/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS    */
/* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,*/
/* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL    */
/* SECURITY EXPLORATIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, */
/* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF  */
/* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE     */
/* SOFTWARE.                                                                  */

import java.lang.*;

public class Memory {

 private static int readmem_internal(int addr) {
  addr&=0xfffffffc;

  if (!NativeCode.inited()) {
   return Helper.readmem(addr);
  } else {
   NativeCode nc=NativeCode.getInstance();
   return nc.readmem(addr);
  }
 }

 private static void writemem_internal(int addr,int val) {
  addr&=0xfffffffc;

  if (!NativeCode.inited()) {
   Helper.writemem(addr,val);
  } else {
   NativeCode nc=NativeCode.getInstance();
   nc.writemem(addr,val);
  }
 }

 public static int read_byte(int addr) {
  int val=readmem_internal(addr);
  int off=addr&0x03;

  switch(off) {
   case 0:
    val=val&0xff;
    break;
   case 1:
    val=(val>>8)&0xff;
    break;
   case 2:
    val=(val>>16)&0xff;
    break;
   case 3:
    val=(val>>24)&0xff;
    break;
  }

  return val;
 }

 public static int read_word(int addr) {
  int val=readmem_internal(addr);
  int off=addr&0x03;

  switch(off) {
   case 0:
    val=val&0xffff;
    break;
   case 2:
    val=(val>>16)&0xffff;
    break;
  }

  return val;
 }

 public static int read_dword(int addr) {
  int val=readmem_internal(addr);
  return val;
 }

 public static void write_byte(int addr,int val) {
  int oval=readmem_internal(addr);
  int off=addr&0x03;

  switch(off) {
   case 0:
    oval=(oval&0xffffff00)|(val&0xff);
    break;
   case 1:
    oval=(oval&0xffff00ff)|((val<<8)&0xff00);
    break;
   case 2:
    oval=(oval&0xff00ffff)|((val<<16)&0xff0000);
    break;
   case 3:
    oval=(oval&0x00ffffff)|((val<<24)&0xff000000);
    break;
  }

  writemem_internal(addr,oval);
 }

 public static void write_word(int addr,int val) {
  int oval=readmem_internal(addr);
  int off=addr&0x03;

  switch(off) {
   case 0:
    oval=(oval&0xffff0000)|(val&0xffff);
    break;
   case 2:
    oval=(oval&0x0000ffff)|((val<<16)&0xffff0000);
    break;
  }

  writemem_internal(addr,oval);
 }

 public static void write_dword(int addr,int val) {
  writemem_internal(addr,val);
 }

}
