mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-11-01 12:07:31 +01:00
- sceHeapDeleteHeap never freed the heap's memory. Allocation failure returned -1 rather than a null pointer, and a near-4GB size wrapped. - The USB wait timeout resumed threads that were no longer waiting on USB, and UsbUpdateState resumed them too, and never rescheduled. - The Mersenne Twister drew from mt_[index_] with the index taken from guest memory. It's now taken modulo the state size. sceSfmt19937 checks its index, and that fill arrays are at least a state long, which the library writes regardless of the length it's given. - sceCccEncodeUTF16's surrogate test also caught U+F800 - U+FFFF, which includes the fullwidth forms. - sceAudioRoutingSetVolumeMode stored the routing mode. - A sample rate of 0 to sceAudioInput or the camera mic divided by zero, and a huge sample count sized a host buffer. sceP3daBridgeCore's sizes could wrap. sceRtc's tz offset could overflow tm_min. - Camera shutdown freed the frame buffer and config without the lock the capture thread uses. GPS data is set from the platform's location thread, so it's now locked too, and the satellite index is bounded. - A loop in the sys event handler list hung the unregister. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
218 lines
6.5 KiB
C++
218 lines
6.5 KiB
C++
// Copyright (c) 2012- PPSSPP Project.
|
|
|
|
// This program is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License as published by
|
|
// the Free Software Foundation, version 2.0 or later versions.
|
|
|
|
// This program is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License 2.0 for more details.
|
|
|
|
// A copy of the GPL 2.0 should have been included with the program.
|
|
// If not, see http://www.gnu.org/licenses/
|
|
|
|
// Official git repository and contact information can be found at
|
|
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
|
|
|
|
#include <ctime>
|
|
#include <mutex>
|
|
|
|
#include "Common/System/System.h"
|
|
#include "Common/System/Request.h"
|
|
#include "Common/Serialize/Serializer.h"
|
|
#include "Common/Serialize/SerializeFuncs.h"
|
|
#include "Core/HLE/HLE.h"
|
|
#include "Core/HLE/FunctionWrappers.h"
|
|
#include "Core/HLE/sceUsbGps.h"
|
|
#include "Core/MemMapHelpers.h"
|
|
|
|
enum GpsStatus {
|
|
GPS_STATE_OFF = 0,
|
|
GPS_STATE_ACTIVATING1 = 1,
|
|
GPS_STATE_ACTIVATING2 = 2,
|
|
GPS_STATE_ON = 3,
|
|
};
|
|
|
|
constexpr int AUTO_UPDATE_GPSTIME = 10;
|
|
|
|
GpsStatus gpsStatus = GPS_STATE_OFF;
|
|
GpsData gpsData;
|
|
SatData satData;
|
|
time_t lastGPSTime;
|
|
// The platform's location callbacks set these from their own thread.
|
|
static std::recursive_mutex gpsLock;
|
|
|
|
void __UsbGpsInit() {
|
|
gpsStatus = GPS_STATE_OFF;
|
|
}
|
|
|
|
void __UsbGpsDoState(PointerWrap &p) {
|
|
const bool wasOn = gpsStatus == GPS_STATE_ON;
|
|
auto s = p.Section("sceUsbGps", 0, 1);
|
|
if (!s) {
|
|
// Older states didn't save it, so leave it off.
|
|
if (p.mode == p.MODE_READ) {
|
|
if (wasOn) {
|
|
System_GPSCommand("close");
|
|
}
|
|
gpsStatus = GPS_STATE_OFF;
|
|
}
|
|
return;
|
|
}
|
|
|
|
Do(p, gpsStatus);
|
|
if (p.mode == p.MODE_READ) {
|
|
if (gpsStatus == GPS_STATE_ON) {
|
|
GPS::init();
|
|
System_GPSCommand("open");
|
|
} else if (wasOn) {
|
|
System_GPSCommand("close");
|
|
}
|
|
}
|
|
}
|
|
|
|
void __UsbGpsShutdown() {
|
|
gpsStatus = GPS_STATE_OFF;
|
|
System_GPSCommand("close");
|
|
};
|
|
|
|
static int sceUsbGpsGetInitDataLocation(u32 addr) {
|
|
return 0;
|
|
}
|
|
|
|
static int sceUsbGpsGetState(u32 stateAddr) {
|
|
if (Memory::IsValidRange(stateAddr, 4)) {
|
|
Memory::WriteUnchecked_U32(gpsStatus, stateAddr);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static int sceUsbGpsOpen() {
|
|
GPS::init();
|
|
gpsStatus = GPS_STATE_ON;
|
|
System_GPSCommand("open");
|
|
return 0;
|
|
}
|
|
|
|
static int sceUsbGpsClose() {
|
|
gpsStatus = GPS_STATE_OFF;
|
|
System_GPSCommand("close");
|
|
return 0;
|
|
}
|
|
|
|
static int sceUsbGpsGetData(u32 gpsDataAddr, u32 satDataAddr) {
|
|
std::lock_guard<std::recursive_mutex> guard(gpsLock);
|
|
time_t currentTime;
|
|
time(¤tTime);
|
|
if (difftime(currentTime, lastGPSTime) > AUTO_UPDATE_GPSTIME)
|
|
{
|
|
/* Simulate fresh updates to satisfy MAPLUS 1/2 apps
|
|
* when real GPS data isn't available */
|
|
GPS::setGpsTime(¤tTime);
|
|
}
|
|
|
|
auto gpsData = PSPPointer<GpsData>::Create(gpsDataAddr);
|
|
if (gpsData.IsValid()) {
|
|
*gpsData = *GPS::getGpsData();
|
|
gpsData.NotifyWrite("UsbGpsGetData");
|
|
}
|
|
auto satData = PSPPointer<SatData>::Create(satDataAddr);
|
|
if (satData.IsValid()) {
|
|
*satData = *GPS::getSatData();
|
|
satData.NotifyWrite("UsbGpsGetData");
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
const HLEFunction sceUsbGps[] =
|
|
{
|
|
{0X268F95CA, nullptr, "sceUsbGpsSetInitDataLocation", '?', "" },
|
|
{0X31F95CDE, nullptr, "sceUsbGpsGetPowerSaveMode", '?', "" },
|
|
{0X54D26AA4, &WrapI_U<sceUsbGpsGetInitDataLocation>, "sceUsbGpsGetInitDataLocation", 'i', "x" },
|
|
{0X5881C826, nullptr, "sceUsbGpsGetStaticNavMode", '?', "" },
|
|
{0X63D1F89D, nullptr, "sceUsbGpsResetInitialPosition", '?', "" },
|
|
{0X69E4AAA8, nullptr, "sceUsbGpsSaveInitData", '?', "" },
|
|
{0X6EED4811, &WrapI_V<sceUsbGpsClose>, "sceUsbGpsClose", 'i', "" },
|
|
{0X7C16AC3A, &WrapI_U<sceUsbGpsGetState>, "sceUsbGpsGetState", 'i', "x" },
|
|
{0X934EC2B2, &WrapI_UU<sceUsbGpsGetData>, "sceUsbGpsGetData", 'i', "xx" },
|
|
{0X9D8F99E8, nullptr, "sceUsbGpsSetPowerSaveMode", '?', "" },
|
|
{0X9F267D34, &WrapI_V<sceUsbGpsOpen>, "sceUsbGpsOpen", 'i', "" },
|
|
{0XA259CD67, nullptr, "sceUsbGpsReset", '?', "" },
|
|
{0XA8ED0BC2, nullptr, "sceUsbGpsSetStaticNavMode", '?', "" },
|
|
};
|
|
|
|
void Register_sceUsbGps()
|
|
{
|
|
RegisterHLEModule("sceUsbGps", ARRAY_SIZE(sceUsbGps), sceUsbGps);
|
|
}
|
|
|
|
void GPS::init() {
|
|
time_t currentTime;
|
|
time(¤tTime);
|
|
setGpsTime(¤tTime);
|
|
|
|
gpsData.hdop = 1.0f;
|
|
gpsData.latitude = 51.510357f;
|
|
gpsData.longitude = -0.116773f;
|
|
gpsData.altitude = 19.0f;
|
|
gpsData.speed = 3.0f;
|
|
gpsData.bearing = 35.0f;
|
|
gpsData.garbage2 = 513;
|
|
|
|
satData.satellites_in_view = 12;
|
|
for (unsigned char i = 0; i < satData.satellites_in_view; i++) {
|
|
satData.satInfo[i].id = i + 1; // 1 .. 32
|
|
satData.satInfo[i].elevation = 20;
|
|
satData.satInfo[i].azimuth = i * (360/satData.satellites_in_view);
|
|
satData.satInfo[i].snr = 45;
|
|
satData.satInfo[i].good = !!(i % 3);
|
|
}
|
|
}
|
|
|
|
void GPS::setGpsTime(time_t *time) {
|
|
std::lock_guard<std::recursive_mutex> guard(gpsLock);
|
|
struct tm *gpsTime;
|
|
gpsTime = gmtime(time);
|
|
|
|
gpsData.year = (short)(gpsTime->tm_year + 1900);
|
|
gpsData.month = (short)(gpsTime->tm_mon + 1);
|
|
gpsData.date = (short)gpsTime->tm_mday;
|
|
gpsData.hour = (short)gpsTime->tm_hour;
|
|
gpsData.minute = (short)gpsTime->tm_min;
|
|
gpsData.second = (short)gpsTime->tm_sec;
|
|
}
|
|
|
|
void GPS::setGpsData(long long gpsTime, float hdop, float latitude, float longitude, float altitude, float speed, float bearing) {
|
|
std::lock_guard<std::recursive_mutex> guard(gpsLock);
|
|
lastGPSTime = (time_t)gpsTime;
|
|
setGpsTime(&lastGPSTime);
|
|
|
|
gpsData.hdop = hdop;
|
|
gpsData.latitude = latitude;
|
|
gpsData.longitude = longitude;
|
|
gpsData.altitude = altitude;
|
|
gpsData.speed = speed;
|
|
gpsData.bearing = bearing;
|
|
}
|
|
|
|
void GPS::setSatInfo(short index, unsigned char id, unsigned char elevation, short azimuth, unsigned char snr, unsigned char good) {
|
|
if (index < 0 || index >= (short)ARRAY_SIZE(satData.satInfo))
|
|
return;
|
|
std::lock_guard<std::recursive_mutex> guard(gpsLock);
|
|
satData.satInfo[index].id = id;
|
|
satData.satInfo[index].elevation = elevation;
|
|
satData.satInfo[index].azimuth = azimuth;
|
|
satData.satInfo[index].snr = snr;
|
|
satData.satInfo[index].good = good;
|
|
satData.satellites_in_view = index + 1;
|
|
}
|
|
|
|
GpsData* GPS::getGpsData() {
|
|
return &gpsData;
|
|
}
|
|
|
|
SatData* GPS::getSatData() {
|
|
return &satData;
|
|
}
|