Skip to content

add libcurl example #72 #95

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open

Conversation

KorigamiK
Copy link
Contributor

Addressing #72

@sharkwouter
Copy link
Member

Thanks, I really appreciate the PR. I do feel it is a little more complex than it has to be for a basic example. Would it be okay if I changed it to only require curl, use pspdebug for output and slim it down to 2 files?

@KorigamiK
Copy link
Contributor Author

Sure, would be nicer for an example

@sharkwouter
Copy link
Member

Okay, I played around with this a bit now. I kind of forgot that the network dialog needs libgu to be initialized. It also turns out the pkgconfig of curl is kinda broken, since you need to include mbedtls, mbedcrypto and mbedx509 manually.

I have this now, but it freezes because it cannot show the dialog.

main.c:

#include <curl/curl.h>
#include <strings.h>
#include <pspsdk.h>
#include <pspnet_inet.h>
#include <psputility.h>
#include <pspgu.h>
#include <pspnet.h>
#include <pspnet_apctl.h>
#include <pspnet_resolver.h>

#include <pspdisplay.h>
#include <string.h>
#include <pspkernel.h>
#include <pspdebug.h>
#include <pspdisplay.h>
#include <stdlib.h>

// PSP_MODULE_INFO is required
PSP_MODULE_INFO("Curl Example", 0, 1, 0);
PSP_MAIN_THREAD_ATTR(PSP_THREAD_ATTR_USER);

int loading = 0;
int running = 1;
size_t buffer_size = 1024;


size_t writeCallback(char *contents, size_t size, size_t nmemb, void *userp) {
    size_t write_size = size * nmemb;
    if (write_size > buffer_size) {
        write_size = buffer_size;
    }
    strncpy((char *) userp, (char *)contents, write_size);
    return write_size;
}

CURLcode getRequest(const char * url, char * buffer) {
    CURL *curl = curl_easy_init();
    if (!curl) {
        return CURLE_FAILED_INIT;
    }

    curl_easy_setopt(curl, CURLOPT_URL, url);
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writeCallback);
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, buffer);
    curl_easy_setopt(curl, CURLOPT_BUFFERSIZE, buffer_size);
    curl_easy_setopt(curl, CURLOPT_VERBOSE, 0);
    curl_easy_setopt(curl, CURLOPT_USERAGENT, "curl/7.64.1");
    curl_easy_setopt(curl, CURLOPT_HTTPHEADER, curl_slist_append(NULL, "Accept: text/plain"));
    curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
    curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
    curl_easy_setopt(curl, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_2);
    curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 10L);
    curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
    curl_easy_setopt(curl, CURLOPT_MAXREDIRS, 20L);
    curl_easy_setopt(curl, CURLOPT_USE_SSL, CURLUSESSL_TRY);

    CURLcode res = curl_easy_perform(curl);

    curl_easy_cleanup(curl);
    return res;
}

char * getNewJoke() {
    char * response = calloc(sizeof(char), buffer_size);

    if (getRequest("https://icanhazdadjoke.com/", response) != CURLE_OK) {
        strcpy(response, "Failed to get joke :(");
    }

    return response;
}

int netDialog()
{
    int done = 0;

    pspUtilityNetconfData data;

    memset(&data, 0, sizeof(data));
    data.base.size = sizeof(data);
    data.base.language = PSP_SYSTEMPARAM_LANGUAGE_ENGLISH;
    data.base.buttonSwap = PSP_UTILITY_ACCEPT_CROSS;
    data.base.graphicsThread = 17;
    data.base.accessThread = 19;
    data.base.fontThread = 18;
    data.base.soundThread = 16;
    data.action = PSP_NETCONF_ACTION_CONNECTAP;

    struct pspUtilityNetconfAdhoc adhocparam;
    memset(&adhocparam, 0, sizeof(adhocparam));
    data.adhocparam = &adhocparam;

    sceUtilityNetconfInitStart(&data);

    while (!done)
    {
        sceDisplayWaitVblankStart();

        switch (sceUtilityNetconfGetStatus())
        {
        case PSP_UTILITY_DIALOG_NONE:
            break;

        case PSP_UTILITY_DIALOG_VISIBLE:
            sceUtilityNetconfUpdate(1);
            break;

        case PSP_UTILITY_DIALOG_QUIT:
            sceUtilityNetconfShutdownStart();
            break;

        case PSP_UTILITY_DIALOG_FINISHED:
            done = 1;
            break;

        default:
            break;
        }

        sceKernelDelayThread(10 * 1000); // 10 ms
    }

    return 1;
}

void startNetworking()
{
    sceUtilityLoadNetModule(PSP_NET_MODULE_COMMON);
    sceUtilityLoadNetModule(PSP_NET_MODULE_INET);

    sceNetInit(128 * 1024, 42, 4 * 1024, 42, 4 * 1024);
    sceNetInetInit();
    sceNetApctlInit(0x8000, 48);

    netDialog();
}

void stopNetworking()
{
    sceUtilityUnloadNetModule(PSP_NET_MODULE_INET);
    sceUtilityUnloadNetModule(PSP_NET_MODULE_COMMON);
    
    sceNetApctlTerm();
    sceNetInetTerm();
    sceNetTerm();
}

int exit_callback(int arg1, int arg2, void *common) {
    stopNetworking();
    sceKernelExitGame();
    return 0;
}

int callback_thread(SceSize args, void *argp) {
    int cbid = sceKernelCreateCallback("Exit Callback", exit_callback, NULL);
    sceKernelRegisterExitCallback(cbid);
    sceKernelSleepThreadCB();
    return 0;
}

int setup_callbacks(void) {
    int thid = sceKernelCreateThread("update_thread", callback_thread, 0x11, 0xFA0, 0, 0);
    if(thid >= 0)
        sceKernelStartThread(thid, 0, 0);
    return thid;
}

int main(void)  {
    // Use above functions to make exiting possible
    setup_callbacks();

    startNetworking();

    char * joke = getNewJoke();
    
    // Print the received joke! on a debug screen on a loop
    pspDebugScreenInit();
    pspDebugScreenClear();
    while(1) {
        pspDebugScreenSetXY(0, 0);
        pspDebugScreenPrintf("%s", joke);
        sceDisplayWaitVblankStart();
    }

    return 0;
}

CMakeLists.txt:

cmake_minimum_required(VERSION 3.14)

project(curl-example)

add_executable(${PROJECT_NAME} main.c)

find_package(CURL REQUIRED)

include(FindPkgConfig)
pkg_search_module(CURL REQUIRED libcurl)

target_link_libraries(${PROJECT_NAME} PRIVATE
  ${CURL_LIBRARIES}
  mbedtls
  mbedcrypto
  mbedx509
  pspdebug
  pspdisplay
  pspge
  pspnet 
  pspnet_apctl
)

# Create an EBOOT.PBP file
create_pbp_file(
    TARGET ${PROJECT_NAME}
    ICON_PATH NULL
    BACKGROUND_PATH NULL
    PREVIEW_PATH NULL
    TITLE ${PROJECT_NAME}
    VERSION 01.00
)

@KorigamiK
Copy link
Contributor Author

Ah yeah, i know this because you need to initialise graphics first to show the dialog :sad:

@KorigamiK
Copy link
Contributor Author

I may be wrong here but I do believe it's not required to have PSP_MODULE_INFO in the source files because you can configure it through cmake. I think that's better for this.

@sharkwouter
Copy link
Member

The reason you didn't need PSP_MODULE_INFO was because SDL2 makes it not needed, but I'm trying not to use SDL2. Maybe I could write the debug text to a texture.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants