mirror of
https://github.com/Lorenzooone/Pokemon-Gen3-to-Gen-X.git
synced 2026-03-21 17:24:39 -05:00
Kind of optimize sprites for space
Enabled stripping of top row when always empty (all pokemon but smoochum). Did not enable 3bpp. It would save 7 KBs extra, but it's extremely slow...
This commit is contained in:
parent
8ff3741c83
commit
08bde102bd
Binary file not shown.
1
data/sprites_info.bin
Normal file
1
data/sprites_info.bin
Normal file
|
|
@ -0,0 +1 @@
|
|||
UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUEUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU
|
||||
BIN
data_raw/sprites_uncmp.bin
Normal file
BIN
data_raw/sprites_uncmp.bin
Normal file
Binary file not shown.
211
dump_reader.py
211
dump_reader.py
|
|
@ -1,211 +0,0 @@
|
|||
import usb.core
|
||||
import usb.util
|
||||
import signal
|
||||
import sys
|
||||
import traceback
|
||||
import time
|
||||
import os
|
||||
|
||||
dev = None
|
||||
sleep_timer = 0.01
|
||||
sram_transfer_val = 2
|
||||
rom_transfer_val = 1
|
||||
rom_bank_size = 0x40
|
||||
rom_banks = [2,4,8,16,32,64,128,256,512,0,0,0,0,0,0,0,0,0,72,80,96]
|
||||
sram_banks_sizes = [0,8,0x20,0x20,0x20,0x20,2]
|
||||
sram_banks = [0,1,1,4,16,8,1]
|
||||
section_size = 0x100
|
||||
normal_nybble = 0x10
|
||||
check_nybble = 0x40
|
||||
|
||||
def rom_transfer(data, transfer_size):
|
||||
print("Starting ROM dump...")
|
||||
size = rom_bank_size
|
||||
banks = rom_banks[transfer_size]
|
||||
|
||||
return transfer_bank(data, size, banks)
|
||||
|
||||
def sram_transfer(data, transfer_size):
|
||||
print("Starting SRAM dump...")
|
||||
size = sram_banks_sizes[transfer_size]
|
||||
banks = sram_banks[transfer_size]
|
||||
|
||||
return transfer_bank(data, size, banks)
|
||||
|
||||
def transfer_bank(data, size, banks):
|
||||
if(banks == 0):
|
||||
print("Nothing to dump!")
|
||||
return None
|
||||
|
||||
res = []
|
||||
for i in range(banks):
|
||||
print("Bank " + str(i+ 1) + " out of " + str(banks) + "!")
|
||||
for j in range(size):
|
||||
print("Section " + str(j+ 1) + " out of " + str(size) + "!")
|
||||
res += read_section(data)
|
||||
return res
|
||||
|
||||
def read_section(data):
|
||||
buf = []
|
||||
checked = False
|
||||
half = False
|
||||
|
||||
while(not checked):
|
||||
for i in range(2):
|
||||
accepted = False
|
||||
while not accepted:
|
||||
sleep_func()
|
||||
sendByte(data[i])
|
||||
recv = receiveByte()
|
||||
high_recv = recv & 0xF0
|
||||
if(high_recv == check_nybble or high_recv == normal_nybble):
|
||||
#print("send: 0x%02x" % data[i])
|
||||
#print("recv: 0x%02x" % recv)
|
||||
if(high_recv == check_nybble):
|
||||
if(half):
|
||||
checked = True
|
||||
half = True
|
||||
accepted = True
|
||||
data[i] = recv & 0xF;
|
||||
#else:
|
||||
#print("BAD RECV: 0x%02x" % recv)
|
||||
val = (data[1] | (data[0] << 4))
|
||||
if(checked):
|
||||
if(val == 0):
|
||||
checked = False
|
||||
buf = []
|
||||
else:
|
||||
buf += [val]
|
||||
#print("Data: 0x%02x" % val)
|
||||
if(half):
|
||||
# Handle a "nybble" desync
|
||||
sleep_func()
|
||||
sendByte(data[0])
|
||||
recv = receiveByte()
|
||||
half = False
|
||||
|
||||
return buf[0:len(buf)-1] # There is an extra transfer in order to ensure the last byte is correct. Discard it
|
||||
|
||||
def transfer_func():
|
||||
print("Waiting for the transfer to start...")
|
||||
|
||||
data = [0,0]
|
||||
buf = read_section(data) # Read the starting information
|
||||
|
||||
if(len(buf) > 2):
|
||||
print("The transfer was previously interrupted. Please reset the GameBoy!")
|
||||
return
|
||||
|
||||
transfer_type = buf[0]
|
||||
transfer_size = buf[1]
|
||||
if(transfer_type == rom_transfer_val):
|
||||
res = rom_transfer(data, transfer_size)
|
||||
elif(transfer_type == sram_transfer_val):
|
||||
res = sram_transfer(data, transfer_size)
|
||||
|
||||
if res is not None:
|
||||
if(len(sys.argv) > 1):
|
||||
target = sys.argv[1]
|
||||
else:
|
||||
target = input("Please enter where to save the dump: ")
|
||||
|
||||
newFile = open(target, "wb")
|
||||
newFile.write(bytearray(res))
|
||||
newFile.close()
|
||||
return
|
||||
|
||||
# Function needed in order to make sure there is enough time for the slave to prepare the next byte.
|
||||
def sleep_func():
|
||||
time.sleep(sleep_timer)
|
||||
|
||||
# Code dependant on this connection method
|
||||
def sendByte(byte_to_send):
|
||||
epOut.write(byte_to_send.to_bytes(1, byteorder='big'))
|
||||
return
|
||||
|
||||
def receiveByte():
|
||||
return int.from_bytes(epIn.read(epIn.wMaxPacketSize, 100), byteorder='big')
|
||||
|
||||
# Things for the USB connection part
|
||||
def exit_gracefully():
|
||||
if dev is not None:
|
||||
usb.util.dispose_resources(dev)
|
||||
if(os.name != "nt"):
|
||||
if reattach:
|
||||
dev.attach_kernel_driver(0)
|
||||
print('Done.')
|
||||
|
||||
def signal_handler(sig, frame):
|
||||
print('You pressed Ctrl+C!')
|
||||
exit_gracefully()
|
||||
|
||||
signal.signal(signal.SIGINT, signal_handler)
|
||||
|
||||
# The execution path
|
||||
try:
|
||||
devices = list(usb.core.find(find_all=True,idVendor=0xcafe, idProduct=0x4011))
|
||||
for d in devices:
|
||||
#print('Device: %s' % d.product)
|
||||
dev = d
|
||||
|
||||
if dev is None:
|
||||
raise ValueError('Device not found')
|
||||
|
||||
reattach = False
|
||||
if(os.name != "nt"):
|
||||
if dev.is_kernel_driver_active(0):
|
||||
try:
|
||||
reattach = True
|
||||
dev.detach_kernel_driver(0)
|
||||
print("kernel driver detached")
|
||||
except usb.core.USBError as e:
|
||||
sys.exit("Could not detach kernel driver: %s" % str(e))
|
||||
else:
|
||||
print("no kernel driver attached")
|
||||
|
||||
dev.reset()
|
||||
|
||||
dev.set_configuration()
|
||||
|
||||
cfg = dev.get_active_configuration()
|
||||
|
||||
#print('Configuration: %s' % cfg)
|
||||
|
||||
intf = cfg[(2,0)] # Or find interface with class 0xff
|
||||
|
||||
#print('Interface: %s' % intf)
|
||||
|
||||
epIn = usb.util.find_descriptor(
|
||||
intf,
|
||||
custom_match = \
|
||||
lambda e: \
|
||||
usb.util.endpoint_direction(e.bEndpointAddress) == \
|
||||
usb.util.ENDPOINT_IN)
|
||||
|
||||
assert epIn is not None
|
||||
|
||||
#print('EP In: %s' % epIn)
|
||||
|
||||
epOut = usb.util.find_descriptor(
|
||||
intf,
|
||||
# match the first OUT endpoint
|
||||
custom_match = \
|
||||
lambda e: \
|
||||
usb.util.endpoint_direction(e.bEndpointAddress) == \
|
||||
usb.util.ENDPOINT_OUT)
|
||||
|
||||
assert epOut is not None
|
||||
|
||||
#print('EP Out: %s' % epOut)
|
||||
|
||||
# Control transfer to enable webserial on device
|
||||
#print("control transfer out...")
|
||||
dev.ctrl_transfer(bmRequestType = 1, bRequest = 0x22, wIndex = 2, wValue = 0x01)
|
||||
|
||||
transfer_func()
|
||||
|
||||
exit_gracefully()
|
||||
except:
|
||||
#traceback.print_exc()
|
||||
print("Unexpected exception: ", sys.exc_info()[0])
|
||||
exit_gracefully()
|
||||
|
|
@ -3,23 +3,55 @@
|
|||
|
||||
#include "gender_symbols_bin.h"
|
||||
|
||||
#define MAX_SIZE_POKEMON_SPRITE 0x400
|
||||
#define GRAPHICS_BUFFER_SHIFT 10
|
||||
#define GRAPHICS_BUFFER_SIZE (1 << GRAPHICS_BUFFER_SHIFT)
|
||||
|
||||
#define CPUFASTSET_FILL (0x1000000)
|
||||
|
||||
void init_gender_symbols(){
|
||||
u8 colors[] = {0,1};
|
||||
convert_1bpp(gender_symbols_bin, (u32*)(VRAM+(0x88<<5)), gender_symbols_bin_size, colors, 1);
|
||||
}
|
||||
|
||||
void load_pokemon_sprite_gfx(u32 src, u32 dst, u8 info){
|
||||
u8 is_3bpp = info&2;
|
||||
u8 zero_fill = info&1;
|
||||
u32 zero = 0;
|
||||
|
||||
u32 buffer[2][MAX_SIZE_POKEMON_SPRITE>>2];
|
||||
LZ77UnCompWram(src, buffer[0]);
|
||||
|
||||
if(is_3bpp) {
|
||||
u8 colors[8];
|
||||
for(int i = 0; i < 8; i++)
|
||||
colors[i] = (buffer[0][0]>>(4*i))&0xF;
|
||||
if(zero_fill) {
|
||||
CpuFastSet(&zero, buffer[1], (MAX_SIZE_POKEMON_SPRITE>>2)|CPUFASTSET_FILL);
|
||||
convert_3bpp(buffer[0]+1, (u32*)(((u32)buffer[1])+0x80), (((MAX_SIZE_POKEMON_SPRITE>>2)*3)>>1)-0x60, colors, 0);
|
||||
convert_3bpp(buffer[0]+1+(((((MAX_SIZE_POKEMON_SPRITE>>2)*3)>>1)-0x60)>>2), (u32*)(((u32)buffer[1])+0x280), (((MAX_SIZE_POKEMON_SPRITE>>2)*3)>>1)-0x60, colors, 0);
|
||||
CpuFastSet(buffer[1], dst, (MAX_SIZE_POKEMON_SPRITE>>2));
|
||||
}
|
||||
else
|
||||
convert_3bpp(buffer[0]+1, dst, (MAX_SIZE_POKEMON_SPRITE>>2)*3, colors, 0);
|
||||
}
|
||||
else {
|
||||
if(zero_fill) {
|
||||
CpuFastSet(&zero, buffer[1], (MAX_SIZE_POKEMON_SPRITE>>2)|CPUFASTSET_FILL);
|
||||
CpuFastSet(buffer[0], ((u32)buffer[1])+0x80, ((MAX_SIZE_POKEMON_SPRITE>>1)-0x80)>>2);
|
||||
CpuFastSet(buffer[0]+(((MAX_SIZE_POKEMON_SPRITE>>1)-0x80)>>2), ((u32)buffer[1])+0x280, ((MAX_SIZE_POKEMON_SPRITE>>1)-0x80)>>2);
|
||||
CpuFastSet(buffer[1], dst, (MAX_SIZE_POKEMON_SPRITE>>2));
|
||||
}
|
||||
else
|
||||
CpuFastSet(buffer[0], dst, MAX_SIZE_POKEMON_SPRITE>>2);
|
||||
}
|
||||
}
|
||||
|
||||
void convert_xbpp(u8* src, u32* dst, u16 src_size, u8* colors, u8 is_forward, u8 num_bpp) {
|
||||
const u16 buffer_size = GRAPHICS_BUFFER_SIZE>>2;
|
||||
u32 buffer[buffer_size];
|
||||
if(num_bpp == 0 || num_bpp > 4)
|
||||
return;
|
||||
const u16 limit = buffer_size-1;
|
||||
u16 base = 0;
|
||||
u16 num_rows = Div(src_size, num_bpp);
|
||||
if(DivMod(src_size, 8*num_bpp))
|
||||
if(DivMod(src_size, num_bpp))
|
||||
num_rows += 1;
|
||||
for(int i = 0; i < num_rows; i++) {
|
||||
u32 src_data = 0;
|
||||
|
|
@ -31,15 +63,8 @@ void convert_xbpp(u8* src, u32* dst, u16 src_size, u8* colors, u8 is_forward, u8
|
|||
row |= (colors[(src_data>>(num_bpp*j))&((1<<num_bpp)-1)]&0xF) << (4*j);
|
||||
else
|
||||
row |= (colors[(src_data>>(num_bpp*j))&((1<<num_bpp)-1)]&0xF) << (4*(7-j));
|
||||
buffer[i-base] = row;
|
||||
if((i-base) == limit) {
|
||||
CpuFastSet(buffer, dst + (base<<2), buffer_size);
|
||||
base += buffer_size;
|
||||
}
|
||||
dst[i] = row;
|
||||
}
|
||||
u16 remaining = num_rows-base;
|
||||
if(remaining)
|
||||
CpuFastSet(buffer, dst + (base<<2), remaining);
|
||||
}
|
||||
|
||||
void convert_1bpp(u8* src, u32* dst, u16 src_size, u8* colors, u8 is_forward) {
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@
|
|||
|
||||
void init_gender_symbols();
|
||||
|
||||
void load_pokemon_sprite_gfx(u32, u32, u8);
|
||||
|
||||
void convert_xbpp(u8*, u32*, u16, u8*, u8, u8);
|
||||
void convert_1bpp(u8*, u32*, u16, u8*, u8);
|
||||
void convert_2bpp(u8*, u32*, u16, u8*, u8);
|
||||
|
|
|
|||
|
|
@ -118,6 +118,8 @@ void start_gen2_slave(void)
|
|||
#define E_MAIN_GAME_CODE 0x2
|
||||
#define E_SUB_GAME_CODE 0x0
|
||||
|
||||
#define VALID_MAPS 36
|
||||
|
||||
#include "party_handler.h"
|
||||
#include "text_handler.h"
|
||||
#include "sprite_handler.h"
|
||||
|
|
@ -131,6 +133,8 @@ const u16 pokedex_extra_pos_1 [] = {0x938, 0x5F8, 0x988};
|
|||
const u16 pokedex_extra_pos_2 [] = {0xC0C, 0xB98, 0xCA4};
|
||||
const u16 mail_pos [] = {0xC4C, 0xDD0, 0xCE0};
|
||||
const u16 ribbon_pos [] = {0x290, 0x21C, 0x328};
|
||||
const u16 special_area [] = {0, 9, 9};
|
||||
const u16 rs_valid_maps[VALID_MAPS] = {0x0202, 0x0203, 0x0301, 0x0302, 0x0405, 0x0406, 0x0503, 0x0504, 0x0603, 0x0604, 0x0700, 0x0701, 0x0804, 0x0805, 0x090a, 0x090b, 0x0a05, 0x0a06, 0x0b05, 0x0b06, 0x0c02, 0x0c03, 0x0d06, 0x0d07, 0x0e03, 0x0e04, 0x0f02, 0x0f03, 0x100c, 0x100d, 0x100a, 0x1918, 0x1919, 0x191a, 0x191b, 0x1a05};
|
||||
|
||||
u8 game_is_jp;
|
||||
u8 game_main_version;
|
||||
|
|
@ -785,6 +789,7 @@ int main(void)
|
|||
returned_val = handle_input_main_menu(&cursor_y_pos, keys, &update, &target, ®ion, &master);
|
||||
print_main_menu(update, target, region, master);
|
||||
//print_pokemon_page1(update, 1, &parties_3[0].mons[0]);
|
||||
//print_trade_menu(update, 2, 1);
|
||||
update_cursor_y(BASE_Y_CURSOR_MAIN_MENU + (BASE_Y_CURSOR_INCREMENT_MAIN_MENU * cursor_y_pos));
|
||||
if(returned_val == START_MULTIBOOT) {
|
||||
curr_state = MULTIBOOT;
|
||||
|
|
|
|||
|
|
@ -2,6 +2,26 @@
|
|||
#include "party_handler.h"
|
||||
#include "text_handler.h"
|
||||
#include "sprite_handler.h"
|
||||
#include "graphics_handler.h"
|
||||
|
||||
#include "pokemon_moves_pp_gen1_bin.h"
|
||||
#include "pokemon_moves_pp_bin.h"
|
||||
#include "pokemon_gender_bin.h"
|
||||
#include "pokemon_names_bin.h"
|
||||
#include "item_names_bin.h"
|
||||
#include "gen2_names_jap_bin.h"
|
||||
#include "sprites_cmp_bin.h"
|
||||
#include "sprites_info_bin.h"
|
||||
#include "palettes_references_bin.h"
|
||||
#include "item_gen3_to_12_bin.h"
|
||||
#include "gen3_to_1_conv_table_bin.h"
|
||||
#include "gen1_to_3_conv_table_bin.h"
|
||||
#include "pokemon_exp_groups_bin.h"
|
||||
#include "exp_table_bin.h"
|
||||
#include "pokemon_stats_bin.h"
|
||||
#include "pokemon_stats_gen1_bin.h"
|
||||
#include "pokemon_types_gen1_bin.h"
|
||||
#include "pokemon_natures_bin.h"
|
||||
|
||||
u8 decrypt_data(struct gen3_mon*, u32*);
|
||||
u8 is_egg_gen3(struct gen3_mon*, struct gen3_mon_misc*);
|
||||
|
|
@ -32,24 +52,7 @@ u8 gender_thresholds_gen12[] = {8, 0, 2, 4, 12, 14, 16, 17};
|
|||
#define UNOWN_V_LETTER 21
|
||||
#define INITIAL_MAIL_GEN3 121
|
||||
#define LAST_MAIL_GEN3 132
|
||||
const u8 pokemon_moves_pp_gen1_bin[];
|
||||
const u8 pokemon_moves_pp_bin[];
|
||||
const u8 pokemon_gender_bin[];
|
||||
const u8 pokemon_names_bin[];
|
||||
const u8 item_names_bin[];
|
||||
const u8 gen2_names_international_bin[];
|
||||
const u8 gen2_names_jap_bin[];
|
||||
const u8 sprites_cmp_bin[];
|
||||
const u8 palettes_references_bin[];
|
||||
const u8 item_gen3_to_12_bin[];
|
||||
const u8 gen3_to_1_conv_table_bin[];
|
||||
const u8 gen1_to_3_conv_table_bin[];
|
||||
const u8 pokemon_exp_groups_bin[];
|
||||
const u8 exp_table_bin[];
|
||||
const u8 pokemon_stats_bin[];
|
||||
const u8 pokemon_stats_gen1_bin[];
|
||||
const u8 pokemon_types_gen1_bin[];
|
||||
const u8 pokemon_natures_bin[];
|
||||
|
||||
const struct exp_level* exp_table = (const struct exp_level*)exp_table_bin;
|
||||
const struct stats_gen_23* stats_table = (const struct stats_gen_23*)pokemon_stats_bin;
|
||||
const struct stats_gen_1* stats_table_gen1 = (const struct stats_gen_1*)pokemon_stats_gen1_bin;
|
||||
|
|
@ -184,6 +187,11 @@ const u8* get_pokemon_sprite_pointer(int index, u32 pid, u8 is_egg){
|
|||
return get_table_pointer(sprites_cmp_bin, get_mon_index(index, pid, is_egg));
|
||||
}
|
||||
|
||||
u8 get_pokemon_sprite_info(int index, u32 pid, u8 is_egg){
|
||||
u16 mon_index = get_mon_index(index, pid, is_egg);
|
||||
return (sprites_info_bin[mon_index>>2]>>(2*(mon_index&3)))&3;
|
||||
}
|
||||
|
||||
u8 get_palette_references(int index, u32 pid, u8 is_egg){
|
||||
return palettes_references_bin[get_mon_index(index, pid, is_egg)];
|
||||
}
|
||||
|
|
@ -192,7 +200,7 @@ void load_pokemon_sprite(int index, u32 pid, u8 is_egg, u8 has_item, u16 y, u16
|
|||
u8 sprite_counter = get_sprite_counter();
|
||||
u32 address = get_pokemon_sprite_pointer(index, pid, is_egg);
|
||||
u8 palette = get_palette_references(index, pid, is_egg);
|
||||
LZ77UnCompVram(address, get_vram_pos());
|
||||
load_pokemon_sprite_gfx(address, get_vram_pos(), get_pokemon_sprite_info(index, pid, is_egg));
|
||||
set_attributes(y, x |(1<<15), (32*sprite_counter)|(palette<<12));
|
||||
inc_sprite_counter();
|
||||
if(!is_egg && has_item)
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
#define OAM 0x7000000
|
||||
#define BASE_CURSOR_X 2
|
||||
#define BASE_CURSOR_Y 8
|
||||
#define CPUFASTSET_FILL (0x1000000)
|
||||
|
||||
const u8 sprite_cursor_bin[];
|
||||
const u32 sprite_cursor_bin_size;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user