Saturday, January 30, 2016

The Definitive Guide to Custom ROMs for the LG G2

The Definitive Guide to Custom ROMs for the LG G2
Released in 2013, the LG G2 was a once the latest flagship device, sporting a full HD screen, the newest Snapdragon 800 Processor, 2GB of RAM, and Android Jellybean 4.2.2. Unfortunately, while the G2 still remains a great phone with specs that still fight for a spot in 2016, support has all but disappeared, leaving us G2 users stuck with LG’s year-old 5.0.1 Lollipop release. This guide will help you gain root access and flash custom ROMs (yes, even Marshmallow) on your aging G2, regardless of your skill level or experience.


***Before we begin, please be sure to understand the risks and benefits of rooting and flashing custom ROMs. I am not responsible for anything that happens to your phone.


To begin, you are first going to need root access on your phone. If you have already rooted your phone, you may disregard these steps.


  1. Make sure you have installed LG USB Drivers on your computer. The drivers can be found here: http://tool.xcdn.gdms.lge.com/dn/downloader.dev?fileKey=UW00120120425
  2. Enable developer options on your phone. To do this, go to “Settings > General > About Phone > Software Information and keep tapping “Build Number” until a message tells you that you are a developer.
  3. Go to Developer Options in settings and enable USB debugging.
  4. Install the program and launch it.
  5. Plug your phone into your computer via USB and allow the drivers to automatically install. This may take some time, be patient. If you’ve plugged your phone in before, the drivers may have already been installed.
  6. Click “ROOT” and let the program run. Once completed, click “FINISH” and your device will reboot.
  7. Check to see if root is successful by looking for the “SuperUser” app after the reboot.


Once you have obtained root access, the next step is to install a custom recovery. The most functional custom recovery for the G2 is TWRP, which can be easily installed using an app called Autorec. This app will automatically install TWRP for you. Here’s the link: https://play.google.com/store/search?q=autorec%20lg%20g2&c=apps&hl=en
Make sure to allow root permissions to the app when the SuperUser prompt comes up. Follow the app instructions to install TWRP on your device.


*You may want to update TWRP. To do this, simply go to https://twrp.me/devices/lgg2.html and download the latest version for your device. Then just boot into recovery and flash the file - more on flashing below.


Once TWRP has been successfully installed, you are now ready for custom ROM installations! Head over to http://forum.xda-developers.com/lg-g2 to look for custom ROMs, and remember to make sure that the ROM is compatible with your G2 variant. For those of you looking for a near-stock Marshmallow experience, here’s the link to the page: http://forum.xda-developers.com/lg-g2/orig-development/rom-official-cyanogenmod-13-lg-g2-t3264508


Download a ROM that you think suits you, and proceed to the next set of instructions.


  1. Before you begin the flashing process, make sure to save the file somewhere you can find and access while in TWRP’s recovery. Flashing is simply installing something to your device, in this case a different version of the Android operating system.
  2. Boot your phone to recovery. There are two ways to do this:
    1. Easy way - Go to the play store and search “boot to recovery.” Install any one of the apps that do this. After the app installs, click on it to boot to recovery. Make sure to allow the app superuser permissions.
    2. Manual boot - Turn off your phone, and let it shut down completely.  Then, simultaneously press and hold the power and volume down buttons. After the LG logo appears on the screen, quickly release the power button only, and immediately press and hold it again. The volume down button should stay pressed. A reset screen will then appear, at which point you can release the buttons. A prompt will appear asking you to erase all data. Select yes twice to confirm. If TWRP was properly installed, your phone will boot to recovery and your data will not be erased.
  3. Now that you have access to TWRP, you can finally install your custom ROM. Before you do so however, make sure to read over ALL instructions on flashing the custom ROM. Some ROMs have certain requirements such as installing different bootstacks or adding GApps.
  4. To install, first go to Wipe > Advanced Wipe. From the menu, select all partitions except for Internal Storage. This is important, as if you wipe your Internal Storage all your media will be erased (pictures, songs, files, etc.). By selecting these options, you will completely reset your phone while keeping saved files. Slide the button at the bottom of the screen to confirm the wipe. Note that while it is not always necessary to completely wipe your phone, it is required in most cases and will save you a lot of trouble.
  5. Next, hit the home button on the bottom left corner of the screen. Go to Install, and find your .zip file for the ROM. Click on the file and confirm the flash by sliding the button at the bottom of the screen. The install may take a while, but keep your patience.
  6. Depending on your ROM instructions, either hit Reboot System or repeat step 5 and install any other required patches. You can also click home and go to Reboot > System.
  7. Your phone will now boot for the first time in a new ROM! Allow a few minutes for your phone to start, as the first boot usually takes some time.
  8. Enjoy!

If you have any questions or comments, please feel free to leave a comment on this post. I will do my best to make sure everyone gets an answer. Thanks for reading!

Written by Basil Lin

Saturday, January 23, 2016

Creating Gameboy Color Cartridge Dumps Using Raspberry Pi

Intro

After wondering how the data on game cartridges was accessed for emulation, I decided to build a device to do this myself. I found this write up (https://blog.thijsalkema.de/blog/2013/05/14/game-boy-cartridge-dumping-on-a-raspberry-pi-part-1/)  by xnyhps about using a Raspberry Pi to do this and, since I had an unused one available, I decided make one myself.

 Parts


Raspberry Pi

I used a Model B Pi, but any model will work. Model B will require an IO expander though, as it doesn’t have enough GPIO pins. I used an SD card to boot Raspbian to program the Pi.



MCP23017 I/O Expander

Using two of these chips and a breadboard, I made the 26 GPIO pins that I needed available.




Cartridge Header

In order to connect to the cartridge without rending the cartridge unusable in the future, I used a cartridge header so I could solder to the pins on it rather than the cartridge. Since the part I used was actually a Nintendo DS Lite replacement, I had to break off some plastic on the sides. NDS cartridge headers were originally meant to only fit for Gameboy Advance games, but the pins are the same and Gameboy Color cartridges will fit after breaking the plastic that prevents them from just sliding on.





Connecting


I first soldered a wire to each pin on the cartridge header. The cartridge pinout can be found on page 8 of this document: 

Afterwards, I connected the data wires and the read and write pins to the MCP chips. A schematic is shown below.




I set up the MCP23017 chips I2C addresses as 0x20 and 0x21. By using i2cdetect –y 0 in the terminal, I tested that both I2C addresses were detected by the Pi. The type of memory bank controller and number of ROM banks can be determined by checking addresses 0x0147 and 0x0148, respectively. The code will depend on this information. The cartridge I was testing (Mickey Mouse Racing) is of type MBC5+RAM+BATTERY with 256 banks. This can be determined by comparing the data in the bits above with page 57 of this pdf: 



Finished product


Code

1.  #! /usr/bin/python  
2.    
3.  # Read a Game Boy/Game Boy Color cartridge connected to two MCP23017 IO expanders.  
4.  # By Logan Blankenbeckler. Based on code by Nathan Chantrell and Thijs Alkemade.  
5.  # GNU GPL V3  
6.    
7.  import smbus  
8.  import sys  
9.  import getopt  
10. import time  
11.   
12. f = None  
13.   
14. # For revision 2 Raspberry Pi, change to bus = smbus.SMBus(0) for revision 1.  
15. bus = smbus.SMBus(0)  
16.   
17. address0 = 0x20  
18. address1 = 0x21  
19. bus.write_byte_data(address0,0x00,0x00) # Set all of bank A of 0x20 to outputs  
20. bus.write_byte_data(address0,0x01,0x00) # Set all of bank B of 0x20 to outputs  
21. bus.write_byte_data(address1,0x00,0xff) # Set all of bank A of 0x21 to inputs  
22. bus.write_byte_data(address1,0x01,0x00) # Set all of bank B of 0x21 to outputs  
23.   
24. def checkbanks():  
25.         bus.write_byte_data(address0, 0x13, 0x47)  
26.         bus.write_byte_data(address0, 0x12, 0x01)  
27.         bus.write_byte_data(address1, 0x13, 0x00)  
28.         print(bus.read_byte_data(address1, 0x12))  
29.           
30. def write(address):  
31.     bus.write_byte_data(address0,0x13,address & 0xff)  
32.     bus.write_byte_data(address0,0x12,(address >> 8) & 0xff)  
33.   
34. # Set ~RD and WR.  
35. bus.write_byte_data(address1,0x13,0x02)  
36.   
37. def read(start, end):  
38.     for read_address in range(start, end):  
39.         write(read_address)  
40.         time.sleep(0.0001)  
41.   
42.         val = bus.read_byte_data(address1,0x12)  
43. #        print(val)  
44.           
45.         if (read_address & 0xff == 0x00):  
46.                 sys.stdout.write(".")  
47.                 sys.stdout.flush()  
48.         f.write('%c' % val)  
49.     f.close()  
50. def select(bank):  
51.     global f  
52.     tdelay = .001  
53.     f = open("file%d.gbc" % bank, 'w')  
54.     sys.stdout.write("\n%d: " % bank)  
55.   
56.     write(0x3100) # set address to 9th bit of bank  
57.     time.sleep(tdelay)  
58.     bus.write_byte_data(address1,0x00,0x00) # set data bus as output  
59.     time.sleep(tdelay)  
60.     bus.write_byte_data(address1,0x12, 0) #(bank >> 8) & 0x01) # write bit 9 of bank  
61.     time.sleep(tdelay)  
62.     bus.write_byte_data(address1,0x13,0x01) # toggle write enable  
63.     time.sleep(.1)  
64.       
65.     bus.write_byte_data(address1,0x13,0x02) # set back to read enable  
66.     time.sleep(tdelay)  
67.     #bus.write_byte_data(address1,0x12,0x00) # set data bus to zero  
68.       
69.     write(0x2100) # set address to lower 8 bits of bank  
70.     time.sleep(tdelay)  
71.     #bus.write_byte_data(address1,0x00,0x00) # set data bus as output  
72.     #time.sleep(tdelay)  
73.     bus.write_byte_data(address1,0x12,(bank & 0xff)) # write lower 8 bits of bank  
74.     time.sleep(tdelay)  
75.     bus.write_byte_data(address1,0x13,0x01) # toggle write enabl  
76.     print("Writing")  
77.     time.sleep(.01)  
78.     bus.write_byte_data(address1,0x13,0x02) # set back to read enable  
79.     time.sleep(tdelay)  
80.       
81.   
82.     time.sleep(tdelay)  
83.     bus.write_byte_data(address1,0x00,0xff) # set data bus as input  
84.   
85.     time.sleep(tdelay)  
86.   
87. select(0)  
88. checkbanks()  
89. read(0x0000, 0x4000)  
90.   
91. for bank in range(1,256):  
92.     select(bank)  
93.     checkbanks()  
94.     read(0x4000, 0x8000)  


This code successfully dumped Mickey Mouse Racing into files that could be properly read by an emulator. The files will need to be concatenated after running the code, however, as each memory bank is stored separately. The number of banks can be changed in the last loop of the code. However, the select function may need to be altered for memory bank controller types that are not MBC5, because MBC5 requires a ninth bit in the ROM bank select to be written while some others require just eight. The code takes a while to run (a little over an hour for me) but that will vary with the number of ROM banks that need to be read.


I hope to continue working on this project, perhaps making the code detect the memory bank controller type and number of banks and applying the methods necessary. Since Gameboy Advance cartridges fit the header and have essentially the same pin-out, using this device to dump them may be a possibility as well.


Hopefully more to come!





Written by Logan Blankenbeckler