12
12

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

mrubyAdvent Calendar 2015

Day 3

PSPでmrubyを動かしてみた話

Last updated at Posted at 2015-12-02

どうも、昔PSPを触ってた人です。
サークルでmrubyを触る機会があって、PSPでも動くかなーと思って試したら普通に動いたので、やり方のメモと言う形で書きたいと思います。

PSPの環境構築の話はここではしないので、各自ググるなりしてください。

mrubyの準備

まずはGithubからmrubyを落としてきます。
落としてきたら、build_config.rbにPSP用のmrubyライブラリを作るための設定を書いてあげます。
下のコードをbuild_config.rbに追記してください。

MRuby::Build.new("psp") do |conf|
  # load specific toolchain settings

  # Gets set by the VS command prompts.
  toolchain :gcc

  enable_debug

  # Use mrbgems
  # conf.gem 'examples/mrbgems/ruby_extension_example'
  # conf.gem 'examples/mrbgems/c_extension_example' do |g|
  #   g.cc.flags << '-g' # append cflags in this gem
  # end
  # conf.gem 'examples/mrbgems/c_and_ruby_extension_example'
  # conf.gem :github => 'masuidrive/mrbgems-example', :checksum_hash => '76518e8aecd131d047378448ac8055fa29d974a9'
  # conf.gem :git => 'git@github.com:masuidrive/mrbgems-example.git', :branch => 'master', :options => '-v'

  # include the default GEMs
  conf.gembox 'non-bin'
  # C compiler settings
  BASE_PATH = "/usr/local/pspdev/bin"
  PREFIX = "psp-"
  conf.cc do |cc|
    cc.command = ENV['CC'] || "#{BASE_PATH}/#{PREFIX}gcc"
    cc.flags = [ENV['CFLAGS'] || %w(-O2 -G0 -Wall -g -fno-exceptions)]
  #   cc.include_paths = ["#{root}/include"]
  #   cc.defines = %w(DISABLE_GEMS)
  #   cc.option_include_path = '-I%s'
  #   cc.option_define = '-D%s'
    cc.compile_options = "%{flags} -MMD -o %{outfile} -c %{infile}"
  end

  # mrbc settings
  # conf.mrbc do |mrbc|
  #   mrbc.compile_options = "-g -B%{funcname} -o-" # The -g option is required for line numbers
  # end

  # Linker settings
  # conf.linker do |linker|
  #   linker.command = ENV['LD'] || 'gcc'
  #   linker.flags = [ENV['LDFLAGS'] || []]
  #   linker.flags_before_libraries = []
  #   linker.libraries = %w()
  #   linker.flags_after_libraries = []
  #   linker.library_paths = []
  #   linker.option_library = '-l%s'
  #   linker.option_library_path = '-L%s'
  #   linker.link_options = "%{flags} -o %{outfile} %{objs} %{libs}"
  # end

  # Archiver settings
  conf.archiver do |archiver|
    archiver.command = ENV['AR'] || "#{BASE_PATH}/#{PREFIX}ar"
    archiver.archive_options = 'rs %{outfile} %{objs}'
  end

  # Parser generator settings
  # conf.yacc do |yacc|
  #   yacc.command = ENV['YACC'] || 'bison'
  #   yacc.compile_options = '-o %{outfile} %{infile}'
  # end

  # gperf settings
  # conf.gperf do |gperf|
  #   gperf.command = 'gperf'
  #   gperf.compile_options = '-L ANSI-C -C -p -j1 -i 1 -g -o -t -N mrb_reserved_word -k"1,3,$" %{infile} > %{outfile}'
  # end

  # file extensions
  # conf.exts do |exts|
  #   exts.object = '.o'
  #   exts.executable = '' # '.exe' if Windows
  #   exts.library = '.a'
  # end

  # file separetor
  # conf.file_separator = '/'

  # bintest
  # conf.enable_bintest
end

これはホスト用の設定をコピーしてきて、一部を変えただけです。
ポイントは使用するGCCとArchiverを変更している点です。
arをpspのものにしておかないと、リンクできないライブラリが生成されてしまいます。

あとは、使用するgemboxを変えています。

conf.gembox 'non-bin'

PSP用の実行ファイルを生成できないため、それらを除いたgemboxを指定しています。
下のオプションを追加することで実行ファイルは生成しなくなるみたいな情報があったんですが、普通に生成しようとするので無理やりgemboxを書き換える方針にしました。

conf.bins = []

non-binというgemboxは存在しないため、自分で作る必要があります。
まずはデフォルトのgemboxをコピーします。

$ cp mrbgems/default.gembox mrbgems/non-bin.gembox

mrbgems/non-bin.gemboxを開いて、mruby-bin-から始まるgemをコメントアウトします。

  ...

  # Use toplevel object (main) methods extension
  conf.gem :core => "mruby-toplevel-ext"

  # Generate mirb command
  # conf.gem :core => "mruby-bin-mirb"

  # Generate mruby command
  # conf.gem :core => "mruby-bin-mruby"

  # Generate mruby-strip command
  # conf.gem :core => "mruby-bin-strip"

  # Use Kernel module extension
  conf.gem :core => "mruby-kernel-ext"

  ...

mrubyのコンパイル

準備が終わったらコンパイルするだけです。

$ make

...

================================================
      Config Name: psp
 Output Directory: build/psp
    Included Gems:
             mruby-sprintf - standard Kernel#sprintf method
             mruby-print - standard print/puts/p
             mruby-math - standard Math module
             mruby-time - standard Time class
             mruby-struct - standard Struct class
             mruby-enum-ext - Enumerable module extension
             mruby-string-ext - String class extension
             mruby-numeric-ext - Numeric class extension
             mruby-array-ext - Array class extension
             mruby-hash-ext - Hash class extension
             mruby-range-ext - Range class extension
             mruby-proc-ext - Proc class extension
             mruby-symbol-ext - Symbol class extension
             mruby-random - Random class
             mruby-object-ext - Object class extension
             mruby-objectspace - ObjectSpace class
             mruby-fiber - Fiber class
             mruby-enumerator - Enumerator class
             mruby-enum-lazy - Enumerable::Lazy class
             mruby-toplevel-ext - toplevel object (main) methods extension
             mruby-kernel-ext - Kernel module extension
             mruby-compiler - mruby compiler library
================================================

Config Name: pspといった表示が出ていればコンパイル成功です。
生成されたライブラリはbuild/psp/lib/の中にlibmruby.aという名前で入っているはずです。

PSPアプリを作る

それではPSPでrubyのコードを動かしてみましょう。
とりあえずhello worldですかね。

mrubyのディレクトリと同じ階層にアプリを作る用のディレクトリを用意して、先ほど生成したlibmruby.aとmrubyの関数群が入っているディレクトリもコピーします。

$ ls
mruby/
$ mkdir mruby-psp
$ ls
mruby/  mruby-psp/
$ cp mruby/build/psp/lib/libmruby.a mruby-psp/
$ cp -r mruby/include/ mruby-psp/
$ cd mruby-psp
$ ls
include/  libmruby.a

このディレクトリにコードやMakefileを設置しましょう

main.c
#include <pspkernel.h>
#include <pspmodulemgr.h>
#include <pspdisplay.h>
#include <pspdebug.h>
#include <pspthreadman.h>
#include <pspctrl.h>
#include <pspsdk.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <mruby.h>
#include <mruby/proc.h>
#include <mruby/compile.h>
#include <mruby/string.h>

#define printf pspDebugScreenPrintf

PSP_MODULE_INFO("Mruby", 0, 0, 1);
PSP_MAIN_THREAD_ATTR(0);
PSP_HEAP_SIZE_KB(-512);

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

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


/* setup the callback thread */
int SetupCallbacks(void){
	int thid = 0;
	thid = sceKernelCreateThread("update_thread", CallbackThread, 0x11, 0xFA0, 0, 0);
	if(thid >= 0)
		sceKernelStartThread(thid, 0, 0);
	return thid;
}

mrb_value myputs(mrb_state *mrb, mrb_value self){
	mrb_value val;
	mrb_get_args(mrb, "S", &val);
	printf(RSTRING_PTR(val));
	return mrb_nil_value();
}

int main(){
	/* exit callback */
	SetupCallbacks();

	/* setup debug info handler */
	pspDebugScreenInit();

	mrb_state *mrb = mrb_open();

	//Objectクラスにmyputsをメソッドとして定義
	mrb_define_method(mrb, mrb->object_class,"myputs", myputs, ARGS_REQ(1));

	mrb_load_string(mrb, "myputs 'hello world!'");

	mrb_close(mrb);

	while (1) {
		sceKernelDelayThread(10*1000*1000);
	}

	sceKernelExitGame();
}

ポイントは、PSP_HEAP_SIZE_KB(-512);でヒープ領域を多めに確保することです。
PSP_HEAP_SIZE_KBにマイナス値を渡すと、メモリの上限から指定した値を引いただけヒープを確保します(確か)

Makefile
TARGET = mruby
OBJS = main.o

OPTION_FLAGS =

INCDIR = ./include
CFLAGS = -O2 -G0 -Wall -g $(OPTION_FLAGS)
CXXFLAGS = $(CFLAGS) -fno-exceptions -fno-rtti
ASFLAGS = $(CFLAGS)

BUILD_PRX = 1

LIBDIR =
LDFLAGS =
LIBS = libmruby.a
LIBS += -lm -lc

EXTRA_TARGETS = EBOOT.PBP
PSP_EBOOT_TITLE = mruby

PSPSDK=$(shell psp-config --pspsdk-path)
include $(PSPSDK)/lib/build.mak

INCDIRに先ほどコピーしたincludeディレクトリを、LIBSにはlibmruby.aを指定します。

あとはmakeすればEBOOT.PBPが生成されると思います。
PSPにコピーして起動し、無事に「wello world!」が表示されれば成功です。

感想とか

たぶん需要はすごく少ないんじゃないかと思います。
ただ、PSPをrubyで動かすことができるのは面白そうかなと思います。
最初、mrubyからPSPのAPIを叩けるライブラリとか作ろうかなと思いましたが、他にもしたいことがあったので、やめました。
興味がある人は是非挑戦して公開して欲しいです。

12
12
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12
12

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?