diff --git a/ONETROPHY/font/font.pgf b/ONETROPHY/font/font.pgf new file mode 100644 index 0000000..4aef6c2 Binary files /dev/null and b/ONETROPHY/font/font.pgf differ diff --git a/ONETROPHY/lang/Chinese_S.txt b/ONETROPHY/lang/Chinese_S.txt index 8364ead..73bafcc 100644 --- a/ONETROPHY/lang/Chinese_S.txt +++ b/ONETROPHY/lang/Chinese_S.txt @@ -4,15 +4,15 @@ STRINGS_MARK_TROPHIES = "标记/取消标记 奖杯" STRINGS_DEL_TROPHIES = "删除奖杯" STRINGS_SHOW_DETAILS = "显示详情" STRINGS_EMPTY = "没有奖杯!!!" -STRINGS_SORT = "Sort: " +STRINGS_SORT = "排序: " -STRINGS_RELOAD_TROPHIES = "需要先与奖杯气泡同步\n\n(非联网上传)" +STRINGS_RELOAD_TROPHIES = "需要先打开奖杯应用气泡刷新奖杯数据库\n\n(非联网上传)" STRINGS_GAME_NOT_INSTALLED = "游戏还没安装!!!" -STRINGS_SUB_TROPHIES = "Sub-奖杯:" +STRINGS_SUB_TROPHIES = "奖杯组:" -STRINGS_TROPHY_TYPE = "奖杯:" -STRINGS_TROPHY_STATUS = "数据:" -STRINGS_TROPHY_HIDDEN = "隐藏:" +STRINGS_TROPHY_TYPE = "奖杯:" +STRINGS_TROPHY_STATUS = "状态:" +STRINGS_TROPHY_HIDDEN = "隐藏:" STRINGS_TROPHY_UNLOCKED = "已解锁" STRINGS_TROPHY_LOCKED = "锁定" @@ -22,12 +22,12 @@ STRINGS_TROPHY_SILVER = "白银" STRINGS_TROPHY_BRONZE = "青铜" --Sort -STRING_SORT_ID = "Trophy id" -STRING_SORT_UNLOCKED = "Unlocked" -STRING_SORT_HIDDEN = "Hidden" -STRING_SORT_GROUP = "Group" -STRING_SORT_TITLE = "Title" -STRING_SORT_PROGRESS = "Progress" +STRING_SORT_ID = "奖杯ID" +STRING_SORT_UNLOCKED = "解锁状态" +STRING_SORT_HIDDEN = "隐藏状态" +STRING_SORT_GROUP = "分组" +STRING_SORT_TITLE = "标题" +STRING_SORT_PROGRESS = "进度" STRINGS_DELETE_QUESTION = "你确定要消除这些奖杯吗?" STRINGS_HIDDEN_YES = "是" @@ -36,6 +36,21 @@ STRINGS_HIDDEN_NO = "否" --color yellow STRINGS_TROPHY_WARNING_HIDDEN = "隐藏" ---Wifi is on +--Trophies App STRINGS_TROPHY_OPENAPP = "奖杯应用" -STRINGS_TROPHY_WIFI_ON = "记得关闭WI-FI,以防止上传奖杯" \ No newline at end of file +STRINGS_TROPHY_REBUILD = "重构奖杯数据库" +STRINGS_TROPHY_WIFI_ON = "记得关闭WI-FI,以防止上传奖杯" + +--Confirm +STRING_CONFIRM_EXIT = "你确定要退出软件吗?" +STRING_CONFIRM_UNLOCK = "是否确认修改该奖杯解锁状态?\n注意已经同步到PSN的奖杯将不会被修改影响\n修改时间戳将不会很精准" +STRING_CONFIRM_LOCK = "是否确认锁定该奖杯?\n注意已经同步到PSN的奖杯将不会被修改影响" +STRING_UNLOCKED = "修改成功" +STRING_LOCKED = "锁定成功" + +--Modify menu +STRINGS_MODIFY_TROPHY = "修改解锁状态" +STRINGS_APPLY_MODIFY = "应用修改" +STRINGS_CANCLE_MODIFY = "取消修改" +STRINGS_SWITCH_MODIFY = "切换修改部分" +STRINGS_MODIFY_VALUE = "修改数据" \ No newline at end of file diff --git a/ONETROPHY/lang/Chinese_T.txt b/ONETROPHY/lang/Chinese_T.txt index f52ea42..0f0a3b7 100644 --- a/ONETROPHY/lang/Chinese_T.txt +++ b/ONETROPHY/lang/Chinese_T.txt @@ -4,15 +4,15 @@ STRINGS_MARK_TROPHIES = "標記/取消標記 獎杯" STRINGS_DEL_TROPHIES = "刪除獎杯" STRINGS_SHOW_DETAILS = "顯示詳情" STRINGS_EMPTY = "沒有獎杯!!!" -STRINGS_SORT = "Sort: " +STRINGS_SORT = "排序: " -STRINGS_RELOAD_TROPHIES = "需要先與獎杯氣泡同歩\n\n(非聯網上傳)" +STRINGS_RELOAD_TROPHIES = "需要先打開奬杯應用氣泡刷新奬杯數據庫\n\n(非聯網上傳)" STRINGS_GAME_NOT_INSTALLED = "遊戲还沒安裝!!!" -STRINGS_SUB_TROPHIES = "Sub-獎杯:" +STRINGS_SUB_TROPHIES = "奬杯組:" -STRINGS_TROPHY_TYPE = "獎杯:" -STRINGS_TROPHY_STATUS = "數據:" -STRINGS_TROPHY_HIDDEN = "隱藏:" +STRINGS_TROPHY_TYPE = "獎杯:" +STRINGS_TROPHY_STATUS = "狀態:" +STRINGS_TROPHY_HIDDEN = "隱藏:" STRINGS_TROPHY_UNLOCKED = "已解鎖" STRINGS_TROPHY_LOCKED = "鎖定" @@ -22,12 +22,12 @@ STRINGS_TROPHY_SILVER = "白銀" STRINGS_TROPHY_BRONZE = "青銅" --Sort -STRING_SORT_ID = "Trophy id" -STRING_SORT_UNLOCKED = "Unlocked" -STRING_SORT_HIDDEN = "Hidden" -STRING_SORT_GROUP = "Group" -STRING_SORT_TITLE = "Title" -STRING_SORT_PROGRESS = "Progress" +STRING_SORT_ID = "奬杯ID" +STRING_SORT_UNLOCKED = "解鎖狀態" +STRING_SORT_HIDDEN = "隱藏狀態" +STRING_SORT_GROUP = "分組" +STRING_SORT_TITLE = "標題" +STRING_SORT_PROGRESS = "進度" STRINGS_DELETE_QUESTION = "你確定要消除這些獎杯嗎?" STRINGS_HIDDEN_YES = "是" @@ -36,6 +36,21 @@ STRINGS_HIDDEN_NO = "否" --color yellow STRINGS_TROPHY_WARNING_HIDDEN = "隱藏" ---Wifi is on +--Trophies App STRINGS_TROPHY_OPENAPP = "獎杯應用" -STRINGS_TROPHY_WIFI_ON = "記得關閉WI-FI,以防止上傳獎杯" \ No newline at end of file +STRINGS_TROPHY_REBUILD = "重構奬杯數據庫" +STRINGS_TROPHY_WIFI_ON = "記得關閉WI-FI,以防止上傳獎杯" + +--Confirm +STRING_CONFIRM_EXIT = "你確定要退出應用嗎?" +STRING_CONFIRM_UNLOCK = "是否確認修改該奬杯解鎖狀態?\n注意已經同步到PSN的奬杯將不會被修改影響\n修改時間戳將不會很精準" +STRING_CONFIRM_LOCK = "是否確認鎖定該奬杯?\n注意已經同步到PSN的奬杯將不會被修改影響" +STRING_UNLOCKED = "修改成功" +STRING_LOCKED = "鎖定成功" + +--Modify menu +STRINGS_MODIFY_TROPHY = "修改解鎖狀態" +STRINGS_APPLY_MODIFY = "應用修改" +STRINGS_CANCLE_MODIFY = "取消修改" +STRINGS_SWITCH_MODIFY = "切換修改部分" +STRINGS_MODIFY_VALUE = "修改數據" \ No newline at end of file diff --git a/ONETROPHY/lang/RUSSIAN.txt b/ONETROPHY/lang/RUSSIAN.txt index 474ff24..9f91ff0 100644 --- a/ONETROPHY/lang/RUSSIAN.txt +++ b/ONETROPHY/lang/RUSSIAN.txt @@ -20,6 +20,14 @@ STRINGS_TROPHY_GOLD = "Золото" STRINGS_TROPHY_SILVER = "Серебро" STRINGS_TROPHY_BRONZE = "Бронза" +--Sort +STRING_SORT_ID = "Trophy id" +STRING_SORT_UNLOCKED = "Unlocked" +STRING_SORT_HIDDEN = "Hidden" +STRING_SORT_GROUP = "Group" +STRING_SORT_TITLE = "Title" +STRING_SORT_PROGRESS = "Progress" + STRINGS_DELETE_QUESTION = "Хочешь удалить эти трофеи?" STRINGS_HIDDEN_YES = "Да" STRINGS_HIDDEN_NO = "Нет" @@ -27,6 +35,22 @@ STRINGS_HIDDEN_NO = "Нет" --color yellow STRINGS_TROPHY_WARNING_HIDDEN = "СКРЫТЫЙ" ---Wifi is on +--Trophies App STRINGS_TROPHY_OPENAPP = "Трофеи" +STRINGS_TROPHY_REBUILD = "Rebuild Trohhy Database" STRINGS_TROPHY_WIFI_ON = "Не забудь отключить Wi-Fi, чтобы не синхронизировать трофеи" + + +--Confirm +STRING_CONFIRM_EXIT = "Are you sure want to exit the app?" +STRING_CONFIRM_UNLOCK = "Are you sure want to modify the unlock status of this trophy?\nNote this will not affect the trophies which already synced to PSN\nThe timestamp may not that accurate" +STRING_CONFIRM_LOCK = "Are you sure want to lock this trophy?\nNote this will not affect the trophies which already synced to PSN" +STRING_UNLOCKED = "Unlock success" +STRING_LOCKED = "Lock success" + +--Modify menu +STRINGS_MODIFY_TROPHY = "Modify Trophy" +STRINGS_APPLY_MODIFY = "Apply Modify" +STRINGS_CANCLE_MODIFY = "Cancle Modify" +STRINGS_SWITCH_MODIFY = "Switch Modify Section" +STRINGS_MODIFY_VALUE = "Modify Value" \ No newline at end of file diff --git a/ONETROPHY/lang/english_us.txt b/ONETROPHY/lang/english_us.txt index 10e0708..1057f5b 100644 --- a/ONETROPHY/lang/english_us.txt +++ b/ONETROPHY/lang/english_us.txt @@ -3,7 +3,7 @@ STRINGS_MARK_TROPHIES = "Mark/Unmark Trophies" STRINGS_DEL_TROPHIES = "Delete Trophies" STRINGS_SHOW_DETAILS = "Show Details" -STRINGS_EMPTY = "Not Trophies !!!" +STRINGS_EMPTY = "No Trophies !!!" STRINGS_SORT = "Sort: " STRINGS_RELOAD_TROPHIES = "It is necessary to first synchronize the Trophies\n\nfrom the APP Trophies." @@ -36,6 +36,21 @@ STRINGS_HIDDEN_NO = "No" --color yellow STRINGS_TROPHY_WARNING_HIDDEN = "HIDDEN" ---Wifi is on +--Trophies App STRINGS_TROPHY_OPENAPP = "Trophies App" -STRINGS_TROPHY_WIFI_ON = "Remember To disable WI-FI to prevent synching trophies" \ No newline at end of file +STRINGS_TROPHY_REBUILD = "Rebuild Trohhy Database" +STRINGS_TROPHY_WIFI_ON = "Remember To disable WI-FI to prevent synching trophies" + +--Confirm +STRING_CONFIRM_EXIT = "Are you sure want to exit the app?" +STRING_CONFIRM_UNLOCK = "Are you sure want to modify the unlock status of this trophy?\nNote this will not affect the trophies which already synced to PSN\nThe timestamp may not that accurate" +STRING_CONFIRM_LOCK = "Are you sure want to lock this trophy?\nNote this will not affect the trophies which already synced to PSN" +STRING_UNLOCKED = "Unlock success" +STRING_LOCKED = "Lock success" + +--Modify menu +STRINGS_MODIFY_TROPHY = "Modify Status" +STRINGS_APPLY_MODIFY = "Apply Modify" +STRINGS_CANCLE_MODIFY = "Cancle Modify" +STRINGS_SWITCH_MODIFY = "Switch Modify Section" +STRINGS_MODIFY_VALUE = "Modify Value" \ No newline at end of file diff --git a/ONETROPHY/resources/buttons3.png b/ONETROPHY/resources/buttons3.png new file mode 100644 index 0000000..d5ecd57 Binary files /dev/null and b/ONETROPHY/resources/buttons3.png differ diff --git a/ONETROPHY/script.lua b/ONETROPHY/script.lua index cec2541..e3d5123 100644 --- a/ONETROPHY/script.lua +++ b/ONETROPHY/script.lua @@ -22,6 +22,8 @@ game.close() dofile("system/commons.lua") dofile("system/scroll.lua") +dofile("system/trophies_helper.lua") +dofile("system/trophies_modify.lua") dofile("system/trophies_title.lua") dofile("system/trophies_group.lua") dofile("system/trophies_list.lua") diff --git a/ONETROPHY/system/commons.lua b/ONETROPHY/system/commons.lua index 0c53f32..08693d8 100644 --- a/ONETROPHY/system/commons.lua +++ b/ONETROPHY/system/commons.lua @@ -35,17 +35,20 @@ __LANG = os.language() -- Loading language file dofile("lang/english_us.txt") -if not files.exists(__PATH_LANG.."english_us.txt") then files.copy("lang/english_us.txt",__PATH_LANG) end -if files.exists(__PATH_LANG..__LANG..".txt") then dofile(__PATH_LANG..__LANG..".txt") end + +if files.exists(__PATH_LANG..__LANG..".txt") then dofile(__PATH_LANG..__LANG..".txt") +elseif files.exists("lang/"..__LANG..".txt") then dofile("lang/"..__LANG..".txt") end -- Loading custom font -fnt = font.load(__PATH_FONT.."font.ttf") or font.load(__PATH_FONT.."font.pgf") or font.load(__PATH_FONT.."font.pvf") +fnt = font.load(__PATH_FONT.."font.ttf") or font.load(__PATH_FONT.."font.pgf") or font.load(__PATH_FONT.."font.pvf") or font.load("font/font.ttf") or font.load("font/font.pgf") or font.load("font/font.pvf") if fnt then font.setdefault(fnt) end --buttons asignation accept,cancel = "cross","circle" +accept_p,cancle_p = 0, 3 if buttons.assign()==0 then accept,cancel = "circle","cross" + accept_p,cancle_p = 3, 0 end --Load resources @@ -53,6 +56,7 @@ back = image.load("resources/background.png") img_trophies = image.load("resources/trophies.png",60,60) buttonskey = image.load("resources/buttons.png",20,20) buttonskey2 = image.load("resources/buttons2.png",30,20) +buttonskey3 = image.load("resources/buttons3.png",20,20) --sorts _SORT_L = { STRING_SORT_ID, STRING_SORT_UNLOCKED, STRING_SORT_HIDDEN } @@ -70,4 +74,4 @@ function draw.offsetgradrect(x,y,sx,sy,c1,c2,c3,c4,offset) local sizey = sy/2 draw.gradrect(x,y,sx,sizey + offset,c1,c2,c3,c4) draw.gradrect(x,y + sizey - offset,sx,sizey + offset,c3,c4,c1,c2) -end \ No newline at end of file +end diff --git a/ONETROPHY/system/trophies_group.lua b/ONETROPHY/system/trophies_group.lua index ec56509..681c4d2 100644 --- a/ONETROPHY/system/trophies_group.lua +++ b/ONETROPHY/system/trophies_group.lua @@ -196,7 +196,8 @@ function trophies_group(obj) collectgarbage("collect") os.delay(250) - return true + buttons.read() + break end end diff --git a/ONETROPHY/system/trophies_helper.lua b/ONETROPHY/system/trophies_helper.lua new file mode 100644 index 0000000..68d2481 --- /dev/null +++ b/ONETROPHY/system/trophies_helper.lua @@ -0,0 +1,140 @@ +--[[ + ----------Trophy Manager------------ + Tool to preview or modify your psvita trophies + + Licensed by GNU General Public License v3.0 + + Designed By: + - Gdljjrod (https://twitter.com/gdljjrod). + + trophies_helper.lua: constants & functions to help operate bytes or date related to trophy file + Origin by @ AnalogMan151 (https://github.com/AnalogMan151/PSVTrophyIsGreat) + Port & implement by @ indefined (https://github.com/indefined) +]] + +-- Constants +LOCKED, UNLOCKED = 0x0, 0x1 -- Values for locked and unlocked status of trophy +SYNCED, NOTSYNCED = 0x20, 0x00 -- Values for if a trophy was synced online or not +PL, GO, SI, BR = 0x1, 0x2, 0x3, 0x4 -- Values for trophy types (Platinum, Gold, Silver, Bronze) +NUMOFTROPHY = 0xFF -- OFFSET for Number of trophies, found in header of trptitle.dat +BASEPROGRESS = 0x124 -- OFFSET for base progress +GAMEID1 = 0X290 -- OFFSET FOR game GAMEID1 +GAMEID2 = 0X2D0 -- OFFSET FOR game GAMEID2 +BASETROP1 = 0X104 -- OFFSET FOR BASE TROP BLOCK1 +BASETROP2 = 0X164 -- OFFSET FOR BASE TROP BLOCK2 +GAMEIDSIZE = 9 -- SIZE OF ID +GROUPSIZE = 0x70 -- Size of a trophy group block +TRPBLOCK1 = 0x70 -- Size of TRPTITLE trophy data block1 +TRPBLOCK2 = 0x60 -- Size of TRPTITLE trophy data block2 +TRANBLOCK = 0xB0 -- Size of TRPTRANS trophy block +TROPHYID = 0x13 -- OFFSET for TROPHY ID, 0 for platinum +TROPTYPE = 0X14 -- OFFSET for TROPHY TYPE`in block1 +TROPGROUP = 0x24 -- OFFSET for trophy group id in block1 +TROPHYSTATE = 0x17 -- offset in block2, 0 for lock, 1 for unlock +TROPHYSSYNC = 0x1A -- offset in block2, 0x00 for unsynced and 0x20 for synced +TROPHYDATE1 = 0x20 -- offset in block2, Date trophy was unlocked +TROPHYDATE2 = 0x28 -- offset in block2, Date trophy was synced to PSN? +EMPTYDATE = string.char(0, 0, 0, 0, 0, 0, 0, 0) -- Empty date value + +-- Retrieve 4 bytes of data in big endian from passed data set starting at passed offset +function readBE4(data, offset) + local byteString = data:sub(offset + 1, offset + 4) + local num = 0 + for i = 1, 4 do num = bit.lshift(num,8) + byteString:byte(i) end + return num +end + +-- Convert int32 number to 4 bytes of data in big endian +function toBE4(num) + return string.char( + bit.rshift(num,24), + bit.rshift(bit.lshift(num,8),24), + bit.rshift(bit.lshift(num,16),24), + bit.band(num, 0xff) + ) +end + +-- Set a bit of a byte to 1 in position +function clearbit(chr, position) + local mask = 2^position + return mask == bit.band(chr, mask) and (chr - mask) or chr +end + +-- Clear a bit of a byte to 0 in position +function setbit(chr, position) + return bit.bor(chr, 2^position) +end + +-- Convert a string to HEX string +function toHex(str) + local hex = "" + for i = 1, #str do + hex = hex .. string.format("%02X", str:byte(i)) + end + return hex +end + +-- SonyTime Constants +TIMEDIFF = -3703570395.920896 -- UTC(0001-01-01 00:00:00.000,000) / 0XFFFFFF +TIMESCALE = 16.777252 -- supposed to be 0xFFFFFF / 1e6 = 16.777216, maybe there is error on lua calculation + +-- Convert a unix timestamp (seconds) to Sony time bytes +-- Only work with utc 1970 to 2400 or so otherwise it will overflow +function encodeTimestamp(utctime) + -- convert to microseconds since UTC 1-1-1 00:00:00, first 5 bytes + local itime = utctime / TIMESCALE - TIMEDIFF + -- convert remainder to 3 bytes, not accurate but just make it not 0 + local ptime = (itime % 1) * 0xffffff + local sonytimebytes = string.char( + 0, + bit.rshift(itime,24), + bit.rshift(bit.lshift(itime,8),24), + bit.rshift(bit.lshift(itime,16),24), + bit.band(itime, 0xff), + bit.rshift(ptime, 16), + bit.rshift(bit.band(ptime,0xffff),8), + bit.band(ptime, 0xff) + ) + -- print(string.format("encode time: %d, %X, %s", utctime, itime, toHex(sonytimebytes))) + return sonytimebytes +end + +-- Convert Sony time bytes to unix timestamp +function decodeTimestamp(sonytimebytes) + local sonytime = 0.0 + -- convert only byte 2 to byte 5 because lua can't deal with int64 caculation + for i = 2, 5 do + sonytime = sonytime * 256 + sonytimebytes:byte(i) + end + -- convert one more byte is enough as lua can only handle 1 second timestamp + local utctime = (sonytime + sonytimebytes:byte(6)/0xff + TIMEDIFF) * TIMESCALE + -- print(string.format("decode time: %s, %X", toHex(sonytimebytes), sonytime)) + return utctime +end + +-- Sort sony timebyte +function sortTimestamp(timea, timeb) + if timea == EMPTYDATE then return false + elseif timeb == EMPTYDATE then return true + else return timea < timeb end +end + +function formatTimestamp(utctime) + local timestring = os.date("%Y-%m-%d %H:%M:%S ", utctime) + if timestring==nil then + return "" + end + -- print(string.format("formatTimestamp: %d, %s", utctime, timestring)) + return timestring +end + +MONTHS = {31,28,31,30,31,30,31,31,30,31,30,31} +function maxDayOfMonth(year, month) + if (month > 12 or month <= 0) then + return 0 + elseif (month == 2 and (((year % 4 == 0) and (year % 100 ~= 0)) or (year % 400 == 0))) then + return 29 + else + return MONTHS[month] + end +end \ No newline at end of file diff --git a/ONETROPHY/system/trophies_list.lua b/ONETROPHY/system/trophies_list.lua index a9cfb6f..ae1d93a 100644 --- a/ONETROPHY/system/trophies_list.lua +++ b/ONETROPHY/system/trophies_list.lua @@ -20,7 +20,7 @@ local trophyL,gid = {},-1 -local trophies_type = { +trophies_type = { name = {STRINGS_TROPHY_PLATINUM, STRINGS_TROPHY_GOLD, STRINGS_TROPHY_SILVER, STRINGS_TROPHY_BRONZE }, num = { 0,1,2,3,4,5 }, win = {STRINGS_TROPHY_LOCKED, STRINGS_TROPHY_UNLOCKED }, @@ -34,6 +34,13 @@ function get_trophiesL(obj) if tmp and #tmp> 0 then + game.umount() + buttons.homepopup(0) + game.mount(DATA_TROPHY..obj.npcommid.."/") + local fp = io.open(DATA_TROPHY..obj.npcommid.."/TRPTITLE.DAT","r") + fp:seek("set", 0) + trptitle = fp:read("*a") + for i=1, #tmp do tmp[i].trophyid = tonumber(tmp[i].trophyid) tmp[i].groupid = tonumber(tmp[i].groupid) @@ -46,10 +53,23 @@ function get_trophiesL(obj) tmp[i].view = true end + local trophy_offset2 = readBE4(trptitle, BASETROP2) + (tmp[i].trophyid * TRPBLOCK2) + local trophyblock2 = string.sub(trptitle, trophy_offset2 + 1, trophy_offset2 + TRPBLOCK2) + + --# Checks if trophy is already unlocked and synced + tmp[i].unlocked = trophyblock2:byte(TROPHYSTATE+1) + tmp[i].synced = trophyblock2:byte(TROPHYSSYNC+1) + + -- Obtain unlocktime and synced time from trophy block 1 for later use + tmp[i].unlocktime = string.sub(trophyblock2, TROPHYDATE1 + 1, TROPHYDATE1 + 8) + tmp[i].synctime = string.sub(trophyblock2, TROPHYDATE2 + 1, TROPHYDATE2 + 8) + tmp[i].pathicon = ICONS_TROPHY..obj.npcommid.."/TROP"..string.rep("0", 3 - string.len(tmp[i].trophyid))..tmp[i].trophyid..".PNG" table.insert(trophyL,tmp[i]) end + game.umount() + buttons.homepopup(1) end end @@ -75,6 +95,7 @@ function trophies_list(obj) local maxim,inter,d_scroll,t_scroll,init_scroll,sort_L = 5,55,25,25,25,1 local scroll = newScroll(trophyL,maxim) + local splits = {" ", "-", "-", " ", ":", ":", ""} buttons.interval(12,5) while true do @@ -82,6 +103,7 @@ function trophies_list(obj) if back then back:blit(0,0) end if icon then icon:blit(0,0,85) end + local selectx, selecty ---------------------------Impresion en pantalla----------------------------------- if screen.textwidth(obj.title,1) > 870 then init_scroll = screen.print(init_scroll,35,obj.title,1,color.white,color.black,__SLEFT,860) @@ -133,7 +155,24 @@ function trophies_list(obj) end if trophyL[i].unlocked == 0 then cc=color.white else cc=color.green:a(200) end - screen.print(25, y + (inter/2), STRINGS_TROPHY_TYPE.." "..trophies_type.name[trophyL[i].type].." "..STRINGS_TROPHY_STATUS.." "..trophies_type.win[trophyL[i].unlocked + 1].." "..STRINGS_TROPHY_HIDDEN.." "..trophies_type.hid[trophyL[i].hidden+1],1,cc,color.blue:a(85)) + local textL = screen.print(25, y + (inter/2), STRINGS_TROPHY_TYPE.." "..trophies_type.name[trophyL[i].type]..", "..STRINGS_TROPHY_HIDDEN.." "..trophies_type.hid[trophyL[i].hidden+1]..", "..STRINGS_TROPHY_STATUS.." ",1,cc,color.blue:a(85)) + if editing.status == true and i == scroll.sel then + -- print the editing + local ey = y + (inter/2) + local ex = textL + 27 + textw = screen.textwidth(table.concat(editing.values)..table.concat(splits)) + 8 + draw.fillrect(ex-4, ey-6 , textw, 28, color.blue:a(125)) + for p, v in pairs(editing.values) do + local ox = screen.print(ex, ey, v,1,cc,color.red:a(85)) + if p == editing.position then + draw.fillrect(ex, ey -6, ox, 28, color.green:a(125)) + screen.print(ex, ey, v,1,cc,color.red:a(85)) + end + ex = ex + ox + screen.print(ex+ox, ey, splits[p],1,cc,color.red:a(85)) + end + else + screen.print(25+textL+2, y + (inter/2), trophies_type.win[trophyL[i].unlocked + 1].." "..formatTimestamp(decodeTimestamp(trophyL[i].unlocktime)),1,cc,color.blue:a(85)) + end --Blit icon if not trophyL[i].icon then @@ -169,6 +208,11 @@ function trophies_list(obj) end end + y+=inter + 15 + + end --for + + if editing.status == false then if trophyL[scroll.sel].hidden == 1 then if buttonskey then buttonskey:blitsprite(10,447,2) end --[] screen.print(40,450,STRINGS_SHOW_DETAILS,1,color.white,color.black,__ALEFT) @@ -177,9 +221,23 @@ function trophies_list(obj) if buttonskey2 then buttonskey2:blitsprite(5,467,0) end screen.print(40,470,STRINGS_SORT.._SORT_L[sort_L],1,color.white,color.black,__ALEFT) - y+=inter + 15 - - end --for + if buttonskey then buttonskey:blitsprite(940,467,accept_p) end --Accept to modify + screen.print(935,470,STRINGS_MODIFY_TROPHY,1,color.white,color.black,__ARIGHT) + else + -- modify trophy + if buttonskey3 then buttonskey3:blitsprite(5,447,0) end --Arrow left & right + if buttonskey3 then buttonskey3:blitsprite(25,447,1) end + screen.print(50,447,STRINGS_SWITCH_MODIFY,1,color.white,color.black,__ALEFT) + if buttonskey3 then buttonskey3:blitsprite(5,467,2) end --Arrow up & down + if buttonskey3 then buttonskey3:blitsprite(25,467,3) end + screen.print(50,470,STRINGS_MODIFY_VALUE,1,color.white,color.black,__ALEFT) + + if buttonskey then buttonskey:blitsprite(940,447,accept_p) end --Accept to apply modify + screen.print(935,450,STRINGS_APPLY_MODIFY,1,color.white,color.black,__ARIGHT) + + if buttonskey then buttonskey:blitsprite(940,467,cancle_p) end --Cancel + screen.print(935,470,STRINGS_CANCLE_MODIFY,1,color.white,color.black,__ARIGHT) + end else screen.print(480,272,STRINGS_EMPTY,1.5,color.yellow,color.black,__ACENTER) @@ -190,34 +248,43 @@ function trophies_list(obj) ----------------------------------Controls------------------------------- if scroll.maxim > 0 and trophyL then - if (buttons.up or buttons.held.l or buttons.analogly<-60) then - if scroll:up() then d_scroll,t_scroll,init_scroll = 25,25,25 end - end + if editing.status then + -- Button controls for modify values + modify_control(obj, trophyL[scroll.sel]) - if (buttons.down or buttons.held.r or buttons.analogly>60) then - if scroll:down() then d_scroll,t_scroll,init_scroll = 25,25,25 end - end + else + -- buttons controls when not in editing mode - if buttons.square and (trophyL[scroll.sel].unlocked == 0 and trophyL[scroll.sel].hidden == 1) then - --if trophyL[scroll.sel].unlocked == 0 then - --if trophyL[scroll.sel].hidden == 1 then - trophyL[scroll.sel].view = not trophyL[scroll.sel].view - --end - --end - end + if buttons[accept] then modify_start(trophyL[scroll.sel]) end -- Accept button to start modify - if buttons.select then - if sort_L == 1 then - sort_L = 2 - table.sort(trophyL, function (a,b) return a.unlocked>b.unlocked end) - elseif sort_L == 2 then - sort_L = 3 - table.sort(trophyL, function (a,b) return a.hidden>b.hidden end) - elseif sort_L == 3 then - sort_L = 1 - table.sort(trophyL, function (a,b) return a.trophyid60) then + if scroll:down() then d_scroll,t_scroll,init_scroll = 25,25,25 end + end + + if buttons.square then + if trophyL[scroll.sel].unlocked == 0 then + if trophyL[scroll.sel].hidden == 1 then + trophyL[scroll.sel].view = not trophyL[scroll.sel].view + end + end + end + + if buttons.select then + if sort_L == 1 then + sort_L = 2 + table.sort(trophyL, function (a,b) return sortTimestamp(a.unlocktime, b.unlocktime) end) + elseif sort_L == 2 then + sort_L = 3 + table.sort(trophyL, function (a,b) return a.hidden>b.hidden end) + elseif sort_L == 3 then + sort_L = 1 + table.sort(trophyL, function (a,b) return a.trophyid 1 then fptrans:write(toBE4(trans_synced - 1)) end + + -- # Loop through trophy blocks looking for trophy ID to remove + for i = 0, trans_num do + -- # If trophy block does not match, continue loop + --print(string.format("trans id: 0x%X, 0x%X", trans_trp_offset + (TRANBLOCK * i) + 0x30, readBE4(trptrans, trans_trp_offset + (TRANBLOCK * i) + 0x30))) + if readBE4(trptrans, trans_trp_offset + (TRANBLOCK * i) + 0x30) == id then + -- # When found, move each remaining entry up to prevent blank spaces + local trans_target_offset = trans_trp_offset + (TRANBLOCK * i) + 0x15 + print(string.format("found match trans id: 0x%02X", trans_target_offset)) + fptrans:seek("set", trans_target_offset + TRANBLOCK) + while i <= trans_num do + local blk = fptrans:read(0x3B) + fptrans:seek("cur", TRANBLOCK * -1 - 0x3B) + fptrans:write(blk) + fptrans:seek("cur", TRANBLOCK * 2 - 0x3B) + i = i + 1 + end + break + end + end + + -- # Cleanup final block to ensure it's empty + fptrans:write(EMPTYDATE) + end + + trop.unlocked = LOCKED + trop.unlocktime = EMPTYDATE + trop.synced = NOTSYNCED + + result = true + end + + if fptitle then fptitle:close() + else os.message("no fptitle") end + if fptrans then fptrans:close() + else os.message("no fptrans") end + + game.umount() + buttons.homepopup(1) + return result +end + +function modify_start(trop) + editing.status = true + editing.position = 1 + local stime = decodeTimestamp(trop.unlocktime) + local ptime = stime and os.date("*t", stime) or os.date("*t") + editing.values = { + trophies_type.win[trop.unlocked + 1], + ptime.year, + ptime.month, + ptime.day, + ptime.hour, + ptime.min, + ptime.sec + } +end + +function modify_control(obj, trop) + + if buttons[accept] then + editing.status = false + if editing.values[1] == trophies_type.win[2] then + -- unlock trophy (or edit timestamp) + if os.message(STRING_CONFIRM_UNLOCK, 1) == 1 then + local ts = os.time({ + year = editing.values[2], + month = editing.values[3], + day = editing.values[4], + hour = editing.values[5], + min = editing.values[6], + sec = editing.values[7] + }) + if (unlock_trophy(obj, trop, ts)) then + files.delete(TROP_TROPHY) + os.message(STRING_UNLOCKED) + end + end + else + -- lock + if trop.unlocked == 1 and os.message(STRING_CONFIRM_LOCK, 1) == 1 then + if (lock_trophy(obj, trop)) then + files.delete(TROP_TROPHY) + os.message(STRING_LOCKED) + end + end + end + elseif buttons[cancel] then + -- cancel editing + editing.status = false + buttons.read() + elseif buttons.left then + -- move editing position + editing.position = editing.position - 1 + if editing.position == 0 then editing.position = 7 end + elseif buttons.right then + -- move editing position + editing.position = editing.position + 1 + if editing.position == 8 then editing.position = 1 end + elseif buttons.up then + -- change values + if editing.position == 1 then + -- lock / unlock + if editing.values[1] == trophies_type.win[2] then + editing.values[1] = trophies_type.win[1] + else editing.values[1] = trophies_type.win[2] end + else + -- date + local value = editing.values[editing.position] + 1 + if editing.position ==2 then + -- year, limit to prevent convert overflow + if value > 2400 then value = 1980 end + elseif editing.position ==3 then + -- month + if value > 12 then value = 1 end + elseif editing.position ==4 then + -- day + local maxd = maxDayOfMonth(editing.values[2], editing.values[3]) + if (value > maxd) then value = 1 end + elseif editing.position ==5 then + if value > 23 then value = 0 end + else + if value > 59 then value = 0 end + end + editing.values[editing.position] = value + end + elseif buttons.down then + -- change values + if editing.position == 1 then + -- lock / unlock + if editing.values[1] == trophies_type.win[2] then + editing.values[1] = trophies_type.win[1] + else editing.values[1] = trophies_type.win[2] end + else + -- date + local value = editing.values[editing.position] - 1 + if editing.position ==2 then + -- year, limit to prevent convert overflow + if value < 1980 then value = 2400 end + elseif editing.position ==3 then + -- month + if value == 0 then value = 12 end + elseif editing.position ==4 then + -- day + if (value == 0) then value = maxDayOfMonth(editing.values[2], editing.values[3]) end + elseif editing.position ==5 then + if value < 0 then value = 23 end + else + if value < 0 then value = 59 end + end + editing.values[editing.position] = value + end + end +end \ No newline at end of file diff --git a/ONETROPHY/system/trophies_title.lua b/ONETROPHY/system/trophies_title.lua index b955fa0..197a640 100644 --- a/ONETROPHY/system/trophies_title.lua +++ b/ONETROPHY/system/trophies_title.lua @@ -188,18 +188,18 @@ function trophies_title() trophyT[i].icon0:blit(955 - (trophyT[i].icon0:getw()/2), y + (inter/2)) end - if buttonskey then buttonskey:blitsprite(10,437,2) end --[] - screen.print(40,440,STRINGS_MARK_TROPHIES,1,color.white,color.black,__ALEFT) + y+=inter + 15 - if buttonskey2 then buttonskey2:blitsprite(5,460,1) end --Start - screen.print(40,462,STRINGS_DEL_TROPHIES,1,color.white,color.black, __ALEFT) + end --for - if buttonskey2 then buttonskey2:blitsprite(5,483,0) end --select - screen.print(40,485,STRINGS_SORT.._SORT_T[sort_T],1,color.white,color.black,__ALEFT) + if buttonskey then buttonskey:blitsprite(10,437,2) end --[] + screen.print(40,440,STRINGS_MARK_TROPHIES,1,color.white,color.black,__ALEFT) - y+=inter + 15 + if buttonskey2 then buttonskey2:blitsprite(5,460,1) end --Start + screen.print(40,462,STRINGS_DEL_TROPHIES,1,color.white,color.black, __ALEFT) - end --for + if buttonskey2 then buttonskey2:blitsprite(5,483,0) end --select + screen.print(40,485,STRINGS_SORT.._SORT_T[sort_T],1,color.white,color.black,__ALEFT) else screen.print(480,202,STRINGS_EMPTY,1.5,color.yellow,color.black,__ACENTER) @@ -212,8 +212,13 @@ function trophies_title() end - if buttonskey then buttonskey:blitsprite(940,483,1) end --Triangle - screen.print(935,485,STRINGS_TROPHY_OPENAPP,1,color.white,color.black,__ARIGHT) + if buttonskey then buttonskey:blitsprite(940,460,1) end --Triangle + screen.print(935,462,STRINGS_TROPHY_OPENAPP,1,color.white,color.black,__ARIGHT) + + if buttonskey2 then buttonskey2:blitsprite(900,483,2) end --L1 + Triangle to force rebuild databse + if buttonskey then buttonskey:blitsprite(940,483,1) end + screen.print(938,483,"+",1,color.white,color.black,__ARIGHT) + screen.print(895,485,STRINGS_TROPHY_REBUILD,1,color.white,color.black,__ARIGHT) screen.flip() @@ -292,18 +297,30 @@ function trophies_title() if buttons.triangle then if wlan.isconnected() then os.message(STRINGS_TROPHY_WIFI_ON) else + -- hold L when open trophy app to force rebuild the trophy database + if buttons.held.l then + files.delete(TROP_TROPHY) + flag_delete_db = true + end if flag_delete_db then files.delete(DB_TROPHY) end + game.umount() + collectgarbage("collect") os.delay(500) - if flag_delete_db then buttons.homepopup(0) else buttons.homepopup(1) end - + -- if flag_delete_db then buttons.homepopup(0) else buttons.homepopup(1) end -- doesn't make sence when open another app but disable the pop? + buttons.homepopup(1) os.uri("pstc:") + if flag_delete_db then + os.delay(500) + os.exit() -- the app need to reload after rebuild database, so just exit the app + end end end - if buttons[cancel] then + if buttons[cancel] and os.message(STRING_CONFIRM_EXIT, 1) == 1 then if flag_delete_db then files.delete(DB_TROPHY) end buttons.homepopup(1) - os.exit() + if buttons.held.l then string.char(intention_crach_when_hold_l_on_exit_to_open_usb_mode) + else os.exit() end end end diff --git a/README.md b/README.md index 563be7b..839fad0 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,12 @@ *This Homebrew could help you delete the game trophies you won't like to synch.* ## IMPORTANT ## -**Everytime a trophy Is deleted, the trophy app/bubble must be launched to update the trophy db, we highly recomend you to disable the wifi in the PS Vita before launching the trophy app/bubble for this matter.** +**Everytime a trophy Is deleted/modified, the trophy app/bubble must be launched to update the trophy db, we highly recommend you to disable the wifi in the PS Vita before launching the trophy app/bubble for this matter.** + +**This app doesn't use the system call to unlock the trophies, it directly modify the trophy files.** +**We highly recommend you to backup your trophies files before modify and check the modify result in trophy app/bubble offline to prevent loss** + +**If your trophy disappear after modify, try L1+Triangle in Trophy Manager title screen to rebuild the trophy database. If that fail then you should maybe restore your backup. Provide the corrupted files to see if we can help locate the bug** ### Changelog 1.03 ### - Support for trophies in homebrews and ports.
@@ -29,22 +34,26 @@ - **Square:** Multi Selection.
- **Start:** Delete selected trophies.
- **Select:** Sort List: Title, Progress.
+- **Triangle:** Open the system Trophy App.
+- **L1+Triangle:** Delete trophy databse and open Trophy App to force rebuild it.
+ +![header](SCREENSHOOT2.jpg) -![header](SCREENSHOOT2.png) +![header](SCREENSHOOT3.jpg) *Trophy Screen* - **Square:** To preview details for a hidden trophy.
- **Select:** Sort List: Trophyid, Unlocked, Hidden.
+- **Accept:** Modify trophy status.
### NOTE: ### -*This app Is based from Trophax app, but Trophy Manager does not unlock trophies.* - -![header](SCREENSHOOT3.png) +*This app Is based from Trophax app, but it modify the trophies status with different way.* ### Credits ### - Silica for his Trophax app - Graphics By WZ-JK. - +- AnalogMan151 for his [PSVTrophyIsGreat](https://github.com/AnalogMan151/PSVTrophyIsGreat) +- indefined for port the PSVTrophyIsGreat ## Donation ## In case you want to support the work of the team on the vita, you can always donate for some coffee. Any amount is highly appreciated: diff --git a/SCREENSHOOT2.jpg b/SCREENSHOOT2.jpg new file mode 100644 index 0000000..5c2c1c6 Binary files /dev/null and b/SCREENSHOOT2.jpg differ diff --git a/SCREENSHOOT3.jpg b/SCREENSHOOT3.jpg new file mode 100644 index 0000000..d3e1c0a Binary files /dev/null and b/SCREENSHOOT3.jpg differ