giongto35 / cloud-game Goto Github PK
View Code? Open in Web Editor NEWWeb-based Cloud Gaming service for Retro Game
Home Page: https://www.youtube.com/watch?v=GUBrJGAxZZg
License: Apache License 2.0
Web-based Cloud Gaming service for Retro Game
Home Page: https://www.youtube.com/watch?v=GUBrJGAxZZg
License: Apache License 2.0
Would be great to have some kind of external configuration file to read in runtime.
I1121 21:00:01.783005 50608 room.go:97] Warn: Room 47b72ee81a4a936d___anguna is not in online storage, error Get https://storage.googleapis.com/game-save/47b72ee81a4a936d___anguna: Get http://169.254.169.254/computeMetadata/v1/instance/service-accounts/default/token?scopes=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fdevstorage.full_control: dial tcp 169.254.169.254:80: connect: host is down
I1121 21:00:01.783033 50608 room.go:101] Room 47b72ee81a4a936d___anguna started. GamePath: assets/games/anguna.gba, GameName: anguna
I1121 21:00:01.784038 50608 nanoarch.go:240] error loading assets/emulator/libretro/cores/mgba_libretro.so, err 100
make: *** [dev.run] Error 1
I1121 21:00:01.787214 50607 cws.go:156] [!] read: websocket: close 1006 (abnormal closure): unexpected EOF
I1121 21:00:01.787248 50607 handlers.go:327] Unregister server from overlord
Including ROMs on the github will get Nintendo or other developers on your asses in no time. Please remove them so this won't be taken down within a week.
Investigate why IOS chrome browser doesn't work while Android is working. Refer to https://github.com/pion/webrtc/tree/master/examples/sfu-minimal
Expectation:
ping 10 in the same country (Singapore - Singapore host) (USWest - Seattle/ Los Angeles)
Ping 50 to the other nearby country (Singapore - Vietnam)
when i used libretro about ps2 core, it crashed. i even doubt it is a core problem, but i tried the same core in retroarch, i workd without crash. the crash program is overworker, it may crash from cgo think.
golang output is at pkg/emulator/libretro/nanoarch/nanoarch.go:367. it says receive a unreconginze signal.
c++ output is the following sentence:
#0 0x00007fffe25bca87 in CGSHandler::WriteRegisterMassively(std::vector<std::pair<unsigned char, unsigned long long>, std::allocator<std::pair<unsigned char, unsigned long long> > >, CGsPacketMetadata const*) () from assets/emulator/libretro/cores/play_libretro.so
#1 0x00007fffe2588b4a in CGIF::ProcessSinglePacket(unsigned char const*, unsigned int, unsigned int, CGsPacketMetadata const&) ()
from assets/emulator/libretro/cores/play_libretro.so
#2 0x00007fffe2588ed8 in CGIF::ProcessMultiplePackets(unsigned char const*, unsigned int, unsigned int, CGsPacketMetadata const&) ()
from assets/emulator/libretro/cores/play_libretro.so
#3 0x00007fffe2588f49 in CGIF::ReceiveDMA(unsigned int, unsigned int, unsigned int, bool) ()
from assets/emulator/libretro/cores/play_libretro.so
#4 0x00007fffe2606d10 in Dmac::CChannel::ExecuteNormal() () from assets/emulator/libretro/cores/play_libretro.so
#5 0x00007fffe2603422 in CDMAC::SetRegister(unsigned int, unsigned int) () from assets/emulator/libretro/cores/play_libretro.so
#6 0x00007fffe257f5d0 in Ee::CSubSystem::IOPortWriteHandler(unsigned int, unsigned int) ()
from assets/emulator/libretro/cores/play_libretro.so
#7 0x00007fffe25e12d5 in CMemoryMap_LSBF::SetWord(unsigned int, unsigned int) () from assets/emulator/libretro/cores/play_libretro.so
It seems like the commit history contains some test commits that are not relevant. Like the commits here - https://github.com/giongto35/cloud-game/commits?author=torvalds.
It's not a good practice having commits like this, that uses some other usernames.
Please clean up commit history-related this. Thanks.
Try scaling game output to 4k resolution and experience the latency. It's good to push the limit and see how much the infrastructure can provide.
Since they are copyrighted, it's better to remove them from the repo.
I was wondering whether it'd be useful to have libretro core downloader / updater inside overworkers based on sys.GOOS rather than using manual assets and hard coded dynamic lib names (so, dll, ...):
worker -download-cores
http://buildbot.libretro.com/nightly/{OS}/x86_64/latest/
worker -update-cores
The current implementation is only based on latency from user to each worker only. Each time a user connects to the master server (overlord), overlord will return all the addresses of workers and ask the user to fetch all latency to them. This latency check in the browser is conducted by an HTTP request to worker through /echo/ endpoint.
Overlord logic to return addresses list:
https://github.com/giongto35/cloud-game/blob/master/overlord/handlers.go#L201
Client logic to check all latency
https://github.com/giongto35/cloud-game/blob/master/static/js/ws.js#L88
The current implementation lacks:
Track ping and the gap between input and media stream to front-end
2 GoRoutines spawn in the same time
ListenToInputChannel writes keyPressed
Update reads keyPressed
3 approaches:
Add context to manager request response sessions
Any proposal for front-end will be welcome. We can set a plan to improve UI based on that design.
Joystick touch on mobile
Is it possible for two people to play in the same room? If so, I would like to request, and possibly help implement this feature. I imagine that the inputs from both clients would be sent such that a single game is controlled by both.
Thank you!
Pokemon Gold (Pokemon - Gold Version (UE) [C][!].gbc) crashes with segfault on the latests mgba core when you click "quit" button on the site.
Maybe it is worth to research (:/ further.
I1008 20:35:15.186391 5468 browser.go:58] Overlord: Received quit request from a browser
I1008 20:35:15.186391 5468 browser.go:59] Overlord: Relay quit request from a browser to worker
I1008 20:35:15.186391 11716 overlord.go:119] Received a quit request from overlord
I1008 20:35:15.187390 11716 overlord.go:121] Find b55674e8-fedb-412a-b63e-53093c53d9ce &{ 0xc0003961c0 17df6e2970cb3626|Pokemon - Gold Version (UE) [C][!]} true
I1008 20:35:15.187390 11716 handlers.go:96] Detach peerconnection
I1008 20:35:15.187390 11716 room.go:195] Cleaning session: 8ba84b50-23ae-48ea-bc44-a93408eb3e22
I1008 20:35:15.187390 11716 room.go:198] found session: 8ba84b50-23ae-48ea-bc44-a93408eb3e22
I1008 20:35:15.187390 11716 room.go:201] Removed session 8ba84b50-23ae-48ea-bc44-a93408eb3e22 from room: 17df6e2970cb3626|Pokemon - Gold Version (UE) [C][!]
I1008 20:35:15.187390 11716 handlers.go:106] No session in room
I1008 20:35:15.187390 11716 room.go:226] Closing room 17df6e2970cb3626|Pokemon - Gold Version (UE) [C][!]
I1008 20:35:15.187390 11716 room.go:227] Closing director of room 17df6e2970cb3626|Pokemon - Gold Version (UE) [C][!]
I1008 20:35:15.187390 11716 room.go:229] Closing input of room 17df6e2970cb3626|Pokemon - Gold Version (UE) [C][!]
I1008 20:35:15.187390 11716 handlers.go:109] Signal input chan
I1008 20:35:15.187390 11716 room.go:190] Peerconn done
Exception 0xc0000005 0x8 0x0 0x0
PC=0x0
runtime: unknown pc 0x6daf9384
stack: frame={sp:0x4fffda0, fp:0x0} stack=[0x0,0x4fffe80)
0000000004fffca0: 0000000002030000 000000c00035c000
0000000004fffcb0: 00000000000000c0 0000000000000008
0000000004fffcc0: 00000000032bd8a0 00007ffe2857fc11
0000000004fffcd0: 0000000002030000 000000c00035c000
0000000004fffce0: 0000000000000006 bf5f5019cb2b5b50
0000000004fffcf0: 00000000032bdb10 00007ffe2857fc11
0000000004fffd00: 000000010000001d 00000000032b0000
0000000004fffd10: 000000c000289d08 0000000000000000
0000000004fffd20: 0000000000000000 0000000000b97848
0000000004fffd30: 000000c000289d48 00007ffe28239cfc
0000000004fffd40: 00000000032a0000 000000c00034e180
0000000004fffd50: 00000000000000a0 0000000000000001
0000000004fffd60: 00000000032a0000 000000006db4d719
0000000004fffd70: 000000c00034e180 000000c000289d48
0000000004fffd80: 000000c000289d08 000000006db45a3b
0000000004fffd90: 0000000000000006 000000006daf9384
0000000004fffda0: <000000c00034e180 000000c000289d48
0000000004fffdb0: 000000c000289d08 00000000032b97e0
0000000004fffdc0: 00000000032b97e0 000000006daf7999
0000000004fffdd0: 0000000004fffe20 000000000043b6c7 <runtime.schedule+391>
0000000004fffde0: 000000c00006a900 0000000000000000
0000000004fffdf0: 000000c000289d48 000000006db48539
0000000004fffe00: 0000000004fffe20 000000c00006a900
0000000004fffe10: 000000c00034e180 000000c00040e000
0000000004fffe20: 0000000004fffe60 0000000000461bd3 <runtime.asmcgocall+115>
0000000004fffe30: 000000c000044f00 000000c00004de00
0000000004fffe40: 0000000000000000 000000c000060027
0000000004fffe50: 0000000000000000 0000000000000328
0000000004fffe60: 000000c00006a900 00000000004602fe <runtime.mcall+94>
0000000004fffe70: 000000c00004de00 00000000032b83f0
runtime: unknown pc 0x6daf9384
stack: frame={sp:0x4fffda0, fp:0x0} stack=[0x0,0x4fffe80)
0000000004fffca0: 0000000002030000 000000c00035c000
0000000004fffcb0: 00000000000000c0 0000000000000008
0000000004fffcc0: 00000000032bd8a0 00007ffe2857fc11
0000000004fffcd0: 0000000002030000 000000c00035c000
0000000004fffce0: 0000000000000006 bf5f5019cb2b5b50
0000000004fffcf0: 00000000032bdb10 00007ffe2857fc11
0000000004fffd00: 000000010000001d 00000000032b0000
0000000004fffd10: 000000c000289d08 0000000000000000
0000000004fffd20: 0000000000000000 0000000000b97848
0000000004fffd30: 000000c000289d48 00007ffe28239cfc
0000000004fffd40: 00000000032a0000 000000c00034e180
0000000004fffd50: 00000000000000a0 0000000000000001
0000000004fffd60: 00000000032a0000 000000006db4d719
0000000004fffd70: 000000c00034e180 000000c000289d48
0000000004fffd80: 000000c000289d08 000000006db45a3b
0000000004fffd90: 0000000000000006 000000006daf9384
0000000004fffda0: <000000c00034e180 000000c000289d48
0000000004fffdb0: 000000c000289d08 00000000032b97e0
0000000004fffdc0: 00000000032b97e0 000000006daf7999
0000000004fffdd0: 0000000004fffe20 000000000043b6c7 <runtime.schedule+391>
0000000004fffde0: 000000c00006a900 0000000000000000
0000000004fffdf0: 000000c000289d48 000000006db48539
0000000004fffe00: 0000000004fffe20 000000c00006a900
0000000004fffe10: 000000c00034e180 000000c00040e000
0000000004fffe20: 0000000004fffe60 0000000000461bd3 <runtime.asmcgocall+115>
0000000004fffe30: 000000c000044f00 000000c00004de00
0000000004fffe40: 0000000000000000 000000c000060027
0000000004fffe50: 0000000000000000 0000000000000328
0000000004fffe60: 000000c00006a900 00000000004602fe <runtime.mcall+94>
0000000004fffe70: 000000c00004de00 00000000032b83f0
goroutine 60 [syscall]:
github.com/giongto35/cloud-game/pkg/emulator/libretro/nanoarch._Cfunc_bridge_retro_unload_game(0x6db48510)
_cgo_gotypes.go:399 +0x48
github.com/giongto35/cloud-game/pkg/emulator/libretro/nanoarch.nanoarchShutdown.func1()
D:/Work/elysium/cloud-game/pkg/emulator/libretro/nanoarch/nanoarch.go:513 +0x64
github.com/giongto35/cloud-game/pkg/emulator/libretro/nanoarch.nanoarchShutdown()
D:/Work/elysium/cloud-game/pkg/emulator/libretro/nanoarch/nanoarch.go:513 +0x27
github.com/giongto35/cloud-game/pkg/emulator/libretro/nanoarch.(*naEmulator).Start(0xc0000d0370)
D:/Work/elysium/cloud-game/pkg/emulator/libretro/nanoarch/naemulator.go:143 +0x129
github.com/giongto35/cloud-game/pkg/worker/room.NewRoom.func1(0xc0000f22d0, 0xc000328420, 0xc0000d80e0, 0xc000542500, 0xc000328480, 0xc0003bc380, 0xddc866, 0x3, 0xc00013694d, 0x22, ...)
D:/Work/elysium/cloud-game/pkg/worker/room/room.go:113 +0x4bb
created by github.com/giongto35/cloud-game/pkg/worker/room.NewRoom
D:/Work/elysium/cloud-game/pkg/worker/room/room.go:90 +0x4a5
goroutine 1 [chan receive]:
I1008 20:35:15.224389 5468 cws.go:156] [!] read: websocket: close 1001 (going away)
main.main()
D:/Work/elysium/cloud-game/cmd/overworker/main.go:38 +0x59d
goroutine 6 [syscall]:
os/signal.signal_recv(0x0)
c:/go/src/runtime/sigqueue.go:147 +0xa3
os/signal.loop()
c:/go/src/os/signal/signal_unix.go:23 +0x29
created by os/signal.init.0
c:/go/src/os/signal/signal_unix.go:29 +0x48
goroutine 7 [chan receive]:
github.com/golang/glog.(*loggingT).flushDaemon(0x13ccb80)
C:/Users/sergy/go/pkg/mod/github.com/golang/[email protected]/glog.go:882 +0x92
created by github.com/golang/glog.init.0
C:/Users/sergy/go/pkg/mod/github.com/golang/[email protected]/glog.go:410 +0x276
goroutine 26 [chan receive]:
github.com/giongto35/cloud-game/pkg/cws.(*Client).Heartbeat(0xc00010e200)
D:/Work/elysium/cloud-game/pkg/cws/cws.go:140 +0xc9
created by github.com/giongto35/cloud-game/pkg/worker.(*Handler).Run
D:/Work/elysium/cloud-game/pkg/worker/handlers.go:66 +0xd1
goroutine 9 [IO wait]:
internal/poll.runtime_pollWait(0x2960dd8, 0x72, 0xedd060)
c:/go/src/runtime/netpoll.go:184 +0x5c
internal/poll.(*pollDesc).wait(0xc000338448, 0x72, 0xb98400, 0x0, 0x0)
c:/go/src/internal/poll/fd_poll_runtime.go:87 +0x4c
internal/poll.(*ioSrv).ExecIO(0x13c8160, 0xc000338298, 0xc000340160, 0x1, 0x0, 0x250)
c:/go/src/internal/poll/fd_windows.go:228 +0x121
internal/poll.(*FD).acceptOne(0xc000338280, 0x250, 0xc0003540f0, 0x2, 0x2, 0xc000338298, 0x1ec200, 0x203000000000000, 0x1effff, 0xc0000bbb78)
c:/go/src/internal/poll/fd_windows.go:896 +0xa9
internal/poll.(*FD).Accept(0xc000338280, 0xc0000bbc78, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, ...)
c:/go/src/internal/poll/fd_windows.go:930 +0x17a
net.(*netFD).accept(0xc000338280, 0xc0000bbd10, 0x6fe32b, 0xc0003440a0)
c:/go/src/net/fd_windows.go:193 +0x7b
net.(*TCPListener).accept(0xc000340020, 0x6fe2d5, 0x0, 0x49683d)
c:/go/src/net/tcpsock_posix.go:139 +0x39
net.(*TCPListener).Accept(0xc000340020, 0xc0000bbd60, 0x18, 0xc0000f8180, 0x6fd835)
c:/go/src/net/tcpsock.go:261 +0x4e
net/http.(*Server).Serve(0xc000344000, 0xeeb540, 0xc000340020, 0x0, 0x0)
c:/go/src/net/http/server.go:2896 +0x28d
net/http.(*Server).ListenAndServe(0xc000344000, 0xc000344000, 0x1)
c:/go/src/net/http/server.go:2825 +0xbe
net/http.ListenAndServe(...)
c:/go/src/net/http/server.go:3080
github.com/giongto35/cloud-game/pkg/worker.(*OverWorker).initializeWorker(0xc0000a81e0)
D:/Work/elysium/cloud-game/pkg/worker/overworker.go:84 +0x2e6
created by github.com/giongto35/cloud-game/pkg/worker.(*OverWorker).Run
D:/Work/elysium/cloud-game/pkg/worker/overworker.go:32 +0x46
goroutine 37 [select]:
go.opencensus.io/stats/view.(*worker).start(0xc00012c910)
C:/Users/sergy/go/pkg/mod/[email protected]/stats/view/worker.go:154 +0x107
created by go.opencensus.io/stats/view.init.0
C:/Users/sergy/go/pkg/mod/[email protected]/stats/view/worker.go:32 +0x5e
goroutine 10 [IO wait]:
internal/poll.runtime_pollWait(0x2960ea8, 0x72, 0xedd060)
c:/go/src/runtime/netpoll.go:184 +0x5c
internal/poll.(*pollDesc).wait(0xc00009b5c8, 0x72, 0xb98400, 0x0, 0x0)
c:/go/src/internal/poll/fd_poll_runtime.go:87 +0x4c
internal/poll.(*ioSrv).ExecIO(0x13c8160, 0xc00009b418, 0xc000004c60, 0x1, 0x0, 0x1ec)
c:/go/src/internal/poll/fd_windows.go:228 +0x121
internal/poll.(*FD).acceptOne(0xc00009b400, 0x1ec, 0xc00033c000, 0x2, 0x2, 0xc00009b418, 0x8ce5d9defb68d101, 0xc0000751e0, 0x8c00000000da0e20, 0xc0002b5a80)
c:/go/src/internal/poll/fd_windows.go:896 +0xa9
internal/poll.(*FD).Accept(0xc00009b400, 0xc0002b5bd0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, ...)
c:/go/src/internal/poll/fd_windows.go:930 +0x17a
net.(*netFD).accept(0xc00009b400, 0xc0002b5c38, 0x13cdac0, 0x190008)
c:/go/src/net/fd_windows.go:193 +0x7b
net.(*TCPListener).accept(0xc000004c40, 0xc0002b5c68, 0x40e94f, 0x30)
c:/go/src/net/tcpsock_posix.go:139 +0x39
net.(*TCPListener).Accept(0xc000004c40, 0xd5f160, 0xc000089770, 0xcc4e40, 0xbdf060)
c:/go/src/net/tcpsock.go:261 +0x4e
net/http.(*Server).Serve(0xc0002f6000, 0xeeb540, 0xc000004c40, 0x0, 0x0)
c:/go/src/net/http/server.go:2896 +0x28d
net/http.(*Server).ListenAndServe(0xc0002f6000, 0xc00002a550, 0xf)
c:/go/src/net/http/server.go:2825 +0xbe
github.com/giongto35/cloud-game/pkg/monitoring.(*ServerMonitoring).Run(0xc0000c6200, 0x0, 0xc0002b5fb8)
D:/Work/elysium/cloud-game/pkg/monitoring/monitoring.go:71 +0x240
github.com/giongto35/cloud-game/pkg/worker.(*OverWorker).RunMonitoringServer(0xc0000a81e0)
D:/Work/elysium/cloud-game/pkg/worker/overworker.go:39 +0x8e
created by github.com/giongto35/cloud-game/pkg/worker.(*OverWorker).Run
D:/Work/elysium/cloud-game/pkg/worker/overworker.go:33 +0x68
goroutine 14 [IO wait]:
internal/poll.runtime_pollWait(0x2960758, 0x72, 0xedd060)
c:/go/src/runtime/netpoll.go:184 +0x5c
internal/poll.(*pollDesc).wait(0xc0002a35c8, 0x72, 0xb98400, 0x0, 0x0)
c:/go/src/internal/poll/fd_poll_runtime.go:87 +0x4c
internal/poll.(*ioSrv).ExecIO(0x13c8160, 0xc0002a3418, 0xe17f68, 0xd61540, 0x0, 0x2)
c:/go/src/internal/poll/fd_windows.go:228 +0x121
internal/poll.(*FD).ReadFrom(0xc0002a3400, 0xc000454000, 0x2000, 0x2000, 0x0, 0x0, 0x0, 0x0, 0x0)
c:/go/src/internal/poll/fd_windows.go:667 +0x13d
net.(*netFD).readFrom(0xc0002a3400, 0xc000454000, 0x2000, 0x2000, 0xc000314ae0, 0xc0002b7e20, 0x2, 0x0, 0x0)
c:/go/src/net/fd_windows.go:158 +0x62
net.(*UDPConn).readFrom(0xc000104688, 0xc000454000, 0x2000, 0x2000, 0x40, 0xc000106360, 0x0, 0xc000326780)
c:/go/src/net/udpsock_posix.go:47 +0x71
net.(*UDPConn).ReadFrom(0xc000104688, 0xc000454000, 0x2000, 0x2000, 0x2000, 0xee3580, 0xc000106360, 0xef6d40, 0xc00010e4c0)
c:/go/src/net/udpsock.go:121 +0x64
github.com/pion/ice.(*candidateBase).recvLoop(0xc000154360)
C:/Users/sergy/go/pkg/mod/github.com/pion/[email protected]/candidate_base.go:92 +0x152
created by github.com/pion/ice.(*candidateBase).start
C:/Users/sergy/go/pkg/mod/github.com/pion/[email protected]/candidate_base.go:81 +0xe7
goroutine 21 [running]:
goroutine running on other thread; stack unavailable
created by github.com/giongto35/cloud-game/pkg/worker.(*OverWorker).initializeWorker
D:/Work/elysium/cloud-game/pkg/worker/overworker.go:60 +0xb8
goroutine 30 [IO wait]:
internal/poll.runtime_pollWait(0x29608f8, 0x72, 0xedd060)
c:/go/src/runtime/netpoll.go:184 +0x5c
internal/poll.(*pollDesc).wait(0xc000326bc8, 0x72, 0xb98400, 0x0, 0x0)
c:/go/src/internal/poll/fd_poll_runtime.go:87 +0x4c
internal/poll.(*ioSrv).ExecIO(0x13c8160, 0xc000326a18, 0xe17f68, 0x400, 0x29e2300, 0x29fffff)
c:/go/src/internal/poll/fd_windows.go:228 +0x121
internal/poll.(*FD).ReadFrom(0xc000326a00, 0xc000444000, 0x2000, 0x2000, 0x0, 0x0, 0x0, 0x0, 0x0)
c:/go/src/internal/poll/fd_windows.go:667 +0x13d
net.(*netFD).readFrom(0xc000326a00, 0xc000444000, 0x2000, 0x2000, 0xc000301ef0, 0x40e0a0, 0x1906b0, 0x65, 0xc000444000)
c:/go/src/net/fd_windows.go:158 +0x62
net.(*UDPConn).readFrom(0xc0000b8138, 0xc000444000, 0x2000, 0x2000, 0x0, 0x0, 0xc000301f20, 0x448313)
c:/go/src/net/udpsock_posix.go:47 +0x71
net.(*UDPConn).ReadFrom(0xc0000b8138, 0xc000444000, 0x2000, 0x2000, 0x43c08d, 0xe18688, 0xc000109430, 0xc, 0xf16f)
c:/go/src/net/udpsock.go:121 +0x64
github.com/pion/ice.(*candidateBase).recvLoop(0xc000362280)
C:/Users/sergy/go/pkg/mod/github.com/pion/[email protected]/candidate_base.go:92 +0x152
created by github.com/pion/ice.(*candidateBase).start
C:/Users/sergy/go/pkg/mod/github.com/pion/[email protected]/candidate_base.go:81 +0xe7
goroutine 54 [IO wait]:
internal/poll.runtime_pollWait(0x2960a98, 0x72, 0xedd060)
c:/go/src/runtime/netpoll.go:184 +0x5c
internal/poll.(*pollDesc).wait(0xc000338948, 0x72, 0xb98400, 0x0, 0x0)
c:/go/src/internal/poll/fd_poll_runtime.go:87 +0x4c
internal/poll.(*ioSrv).ExecIO(0x13c8160, 0xc000338798, 0xe17f68, 0x400, 0x29e2200, 0x29fffff)
c:/go/src/internal/poll/fd_windows.go:228 +0x121
internal/poll.(*FD).ReadFrom(0xc000338780, 0xc000442000, 0x2000, 0x2000, 0x0, 0x0, 0x0, 0x0, 0x0)
c:/go/src/internal/poll/fd_windows.go:667 +0x13d
net.(*netFD).readFrom(0xc000338780, 0xc000442000, 0x2000, 0x2000, 0xc000303ef0, 0x40e0a0, 0x191400, 0x65, 0xc000442000)
c:/go/src/net/fd_windows.go:158 +0x62
net.(*UDPConn).readFrom(0xc00034c068, 0xc000442000, 0x2000, 0x2000, 0x0, 0x0, 0xc000303f20, 0x448313)
c:/go/src/net/udpsock_posix.go:47 +0x71
net.(*UDPConn).ReadFrom(0xc00034c068, 0xc000442000, 0x2000, 0x2000, 0x43c08d, 0xe18688, 0xc000336330, 0x9, 0xf16d)
c:/go/src/net/udpsock.go:121 +0x64
github.com/pion/ice.(*candidateBase).recvLoop(0xc000382140)
C:/Users/sergy/go/pkg/mod/github.com/pion/[email protected]/candidate_base.go:92 +0x152
created by github.com/pion/ice.(*candidateBase).start
C:/Users/sergy/go/pkg/mod/github.com/pion/[email protected]/candidate_base.go:81 +0xe7
goroutine 13 [IO wait]:
internal/poll.runtime_pollWait(0x2960828, 0x72, 0xedd060)
c:/go/src/runtime/netpoll.go:184 +0x5c
internal/poll.(*pollDesc).wait(0xc0002a3348, 0x72, 0xb98400, 0x0, 0x0)
c:/go/src/internal/poll/fd_poll_runtime.go:87 +0x4c
internal/poll.(*ioSrv).ExecIO(0x13c8160, 0xc0002a3198, 0xe17f68, 0x60, 0x10, 0x20)
c:/go/src/internal/poll/fd_windows.go:228 +0x121
internal/poll.(*FD).ReadFrom(0xc0002a3180, 0xc00044e000, 0x2000, 0x2000, 0x0, 0x0, 0x0, 0x0, 0x0)
c:/go/src/internal/poll/fd_windows.go:667 +0x13d
net.(*netFD).readFrom(0xc0002a3180, 0xc00044e000, 0x2000, 0x2000, 0x0, 0x1, 0x50, 0xc00003c2a0, 0xc000142000)
c:/go/src/net/fd_windows.go:158 +0x62
net.(*UDPConn).readFrom(0xc000104670, 0xc00044e000, 0x2000, 0x2000, 0x46, 0xc00013e720, 0x0, 0xc000326780)
c:/go/src/net/udpsock_posix.go:47 +0x71
net.(*UDPConn).ReadFrom(0xc000104670, 0xc00044e000, 0x2000, 0x2000, 0x2000, 0xee3580, 0xc00013e720, 0xef6d40, 0xc00010e4c0)
c:/go/src/net/udpsock.go:121 +0x64
github.com/pion/ice.(*candidateBase).recvLoop(0xc0002dc8c0)
C:/Users/sergy/go/pkg/mod/github.com/pion/[email protected]/candidate_base.go:92 +0x152
created by github.com/pion/ice.(*candidateBase).start
C:/Users/sergy/go/pkg/mod/github.com/pion/[email protected]/candidate_base.go:81 +0xe7
goroutine 52 [IO wait]:
internal/poll.runtime_pollWait(0x2960c38, 0x72, 0xedd060)
c:/go/src/runtime/netpoll.go:184 +0x5c
internal/poll.(*pollDesc).wait(0xc0003386c8, 0x72, 0xb98400, 0x0, 0x0)
c:/go/src/internal/poll/fd_poll_runtime.go:87 +0x4c
internal/poll.(*ioSrv).ExecIO(0x13c8160, 0xc000338518, 0xe17f60, 0xffffffffffffffff, 0x1, 0x1)
c:/go/src/internal/poll/fd_windows.go:228 +0x121
internal/poll.(*FD).Read(0xc000338500, 0xc000384000, 0x1000, 0x1000, 0x0, 0x0, 0x0)
c:/go/src/internal/poll/fd_windows.go:527 +0x31c
net.(*netFD).Read(0xc000338500, 0xc000384000, 0x1000, 0x1000, 0x0, 0xc0002fd7d8, 0xc0002fd830)
c:/go/src/net/fd_windows.go:152 +0x56
net.(*conn).Read(0xc00034c058, 0xc000384000, 0x1000, 0x1000, 0x0, 0x0, 0x0)
c:/go/src/net/net.go:184 +0x6f
net/http.(*connReader).Read(0xc00033e3f0, 0xc000384000, 0x1000, 0x1000, 0xc0003385f0, 0x0, 0x5)
c:/go/src/net/http/server.go:785 +0xfb
bufio.(*Reader).fill(0xc0003280c0)
c:/go/src/bufio/bufio.go:100 +0x10a
bufio.(*Reader).ReadSlice(0xc0003280c0, 0xc00033860a, 0x0, 0xc0002fd9a8, 0x40e0a0, 0xc000386100, 0x100)
c:/go/src/bufio/bufio.go:359 +0x44
bufio.(*Reader).ReadLine(0xc0003280c0, 0xc0002fd9b0, 0xc000342380, 0x191400, 0x0, 0x3, 0x4a6599)
c:/go/src/bufio/bufio.go:388 +0x3b
net/textproto.(*Reader).readLineSlice(0xc00033e420, 0xc000386100, 0xc000338500, 0x0, 0x0, 0x495f24)
c:/go/src/net/textproto/reader.go:57 +0x73
net/textproto.(*Reader).ReadLine(...)
c:/go/src/net/textproto/reader.go:38
net/http.readRequest(0xc0003280c0, 0x0, 0xc000386100, 0x0, 0x0)
c:/go/src/net/http/request.go:1012 +0x99
net/http.(*conn).readRequest(0xc000382000, 0xeed240, 0xc00034a040, 0x0, 0x0, 0x0)
c:/go/src/net/http/server.go:965 +0x166
net/http.(*conn).serve(0xc000382000, 0xeed240, 0xc00034a040)
c:/go/src/net/http/server.go:1817 +0x6db
created by net/http.(*Server).Serve
c:/go/src/net/http/server.go:2927 +0x395
goroutine 55 [IO wait]:
internal/poll.runtime_pollWait(0x29609c8, 0x72, 0xedd060)
c:/go/src/runtime/netpoll.go:184 +0x5c
internal/poll.(*pollDesc).wait(0xc0002a30c8, 0x72, 0xb98400, 0x0, 0x0)
c:/go/src/internal/poll/fd_poll_runtime.go:87 +0x4c
internal/poll.(*ioSrv).ExecIO(0x13c8160, 0xc0002a2f18, 0xe17f68, 0x400, 0x29e2100, 0x29fffff)
c:/go/src/internal/poll/fd_windows.go:228 +0x121
internal/poll.(*FD).ReadFrom(0xc0002a2f00, 0xc000440000, 0x2000, 0x2000, 0x0, 0x0, 0x0, 0x0, 0x0)
c:/go/src/internal/poll/fd_windows.go:667 +0x13d
net.(*netFD).readFrom(0xc0002a2f00, 0xc000440000, 0x2000, 0x2000, 0xc0002ffef0, 0x40e0a0, 0x191400, 0xc000016065, 0xc000440000)
c:/go/src/net/fd_windows.go:158 +0x62
net.(*UDPConn).readFrom(0xc000104668, 0xc000440000, 0x2000, 0x2000, 0x4, 0xc0002fff08, 0xc0002fff20, 0x448313)
c:/go/src/net/udpsock_posix.go:47 +0x71
net.(*UDPConn).ReadFrom(0xc000104668, 0xc000440000, 0x2000, 0x2000, 0xc00034a110, 0x13e9840, 0x29a0001, 0xc0002fffc8, 0x6f2d6a)
c:/go/src/net/udpsock.go:121 +0x64
github.com/pion/ice.(*candidateBase).recvLoop(0xc0002dc820)
C:/Users/sergy/go/pkg/mod/github.com/pion/[email protected]/candidate_base.go:92 +0x152
created by github.com/pion/ice.(*candidateBase).start
C:/Users/sergy/go/pkg/mod/github.com/pion/[email protected]/candidate_base.go:81 +0xe7
goroutine 85 [chan receive]:
github.com/pion/sctp.(*Association).AcceptStream(...)
C:/Users/sergy/go/pkg/mod/github.com/pion/[email protected]/association.go:1047
github.com/pion/datachannel.Accept(0xc000116000, 0xc0003b3f88, 0x450e62, 0xc0000b65a8, 0xc000064501)
C:/Users/sergy/go/pkg/mod/github.com/pion/[email protected]/datachannel.go:128 +0x50
github.com/pion/webrtc/v2.(*SCTPTransport).acceptDataChannels(0xc0002d09a0, 0xc000116000)
C:/Users/sergy/go/pkg/mod/github.com/pion/webrtc/[email protected]/sctptransport.go:132 +0xcc
created by github.com/pion/webrtc/v2.(*SCTPTransport).Start
C:/Users/sergy/go/pkg/mod/github.com/pion/webrtc/[email protected]/sctptransport.go:98 +0x137
goroutine 29 [select]:
github.com/pion/ice.(*Agent).taskLoop(0xc000326780)
C:/Users/sergy/go/pkg/mod/github.com/pion/[email protected]/agent.go:696 +0x10e
created by github.com/pion/ice.NewAgent
C:/Users/sergy/go/pkg/mod/github.com/pion/[email protected]/agent.go:397 +0x810
goroutine 87 [sync.Cond.Wait]:
runtime.goparkunlock(...)
c:/go/src/runtime/proc.go:310
sync.runtime_notifyListWait(0xc000135490, 0xc000000001)
c:/go/src/runtime/sema.go:510 +0x106
sync.(*Cond).Wait(0xc000135480)
c:/go/src/sync/cond.go:56 +0xa4
github.com/pion/sctp.(*Stream).ReadSCTP(0xc00012eb40, 0xc000230000, 0xffff, 0xffff, 0x0, 0x0, 0x0, 0x0)
C:/Users/sergy/go/pkg/mod/github.com/pion/[email protected]/stream.go:107 +0xbd
github.com/pion/datachannel.(*DataChannel).ReadDataChannel(0xc0001600e0, 0xc000230000, 0xffff, 0xffff, 0xffff, 0xe18600, 0x0, 0x0)
C:/Users/sergy/go/pkg/mod/github.com/pion/[email protected]/datachannel.go:188 +0x61
github.com/pion/webrtc/v2.(*DataChannel).readLoop(0xc00045c000)
C:/Users/sergy/go/pkg/mod/github.com/pion/webrtc/[email protected]/datachannel.go:296 +0xac
created by github.com/pion/webrtc/v2.(*DataChannel).handleOpen
C:/Users/sergy/go/pkg/mod/github.com/pion/webrtc/[email protected]/datachannel.go:271 +0xf5
goroutine 98 [runnable]:
github.com/pion/transport/packetio.(*Buffer).Read(0xc0000b6c80, 0xc00009c000, 0x2000, 0x2000, 0x6000105, 0x0, 0xffffffffffffffff)
C:/Users/sergy/go/pkg/mod/github.com/pion/[email protected]/packetio/buffer.go:135 +0x41
github.com/pion/ice.(*Conn).Read(0xc000340040, 0xc00009c000, 0x2000, 0x2000, 0x0, 0x0, 0x0)
C:/Users/sergy/go/pkg/mod/github.com/pion/[email protected]/transport.go:79 +0x9d
github.com/pion/webrtc/v2/internal/mux.(*Mux).readLoop(0xc000072000)
C:/Users/sergy/go/pkg/mod/github.com/pion/webrtc/[email protected]/internal/mux/mux.go:105 +0xe3
created by github.com/pion/webrtc/v2/internal/mux.NewMux
C:/Users/sergy/go/pkg/mod/github.com/pion/webrtc/[email protected]/internal/mux/mux.go:43 +0x12e
goroutine 84 [chan receive]:
github.com/giongto35/cloud-game/pkg/webrtc.(*WebRTC).startStreaming.func2(0xc0003961c0, 0xc000154480)
D:/Work/elysium/cloud-game/pkg/webrtc/webrtc.go:305 +0x9f
created by github.com/giongto35/cloud-game/pkg/webrtc.(*WebRTC).startStreaming
D:/Work/elysium/cloud-game/pkg/webrtc/webrtc.go:297 +0xc0
goroutine 73 [chan receive]:
github.com/giongto35/cloud-game/pkg/encoder/vpx-encoder.(*VpxEncoder).startLooping(0xc000150100)
D:/Work/elysium/cloud-game/pkg/encoder/vpx-encoder/encoder.go:140 +0x11b
created by github.com/giongto35/cloud-game/pkg/encoder/vpx-encoder.(*VpxEncoder).init
D:/Work/elysium/cloud-game/pkg/encoder/vpx-encoder/encoder.go:120 +0x192
goroutine 83 [chan receive]:
github.com/giongto35/cloud-game/pkg/webrtc.(*WebRTC).startStreaming.func1(0xc0003961c0, 0xc0001543f0)
D:/Work/elysium/cloud-game/pkg/webrtc/webrtc.go:275 +0x9f
created by github.com/giongto35/cloud-game/pkg/webrtc.(*WebRTC).startStreaming
D:/Work/elysium/cloud-game/pkg/webrtc/webrtc.go:267 +0x94
goroutine 70 [chan receive]:
github.com/pion/srtp.(*SessionSRTP).AcceptStream(0xc000128310, 0xc000128310, 0x0, 0x0, 0x0)
C:/Users/sergy/go/pkg/mod/github.com/pion/[email protected]/session_srtp.go:81 +0x4c
github.com/pion/webrtc/v2.(*PeerConnection).drainSRTP.func1(0xc0003be000)
C:/Users/sergy/go/pkg/mod/github.com/pion/webrtc/[email protected]/peerconnection.go:1147 +0xa9
created by github.com/pion/webrtc/v2.(*PeerConnection).drainSRTP
C:/Users/sergy/go/pkg/mod/github.com/pion/webrtc/[email protected]/peerconnection.go:1139 +0x4a
goroutine 101 [chan receive]:
github.com/pion/transport/packetio.(*Buffer).Read(0xc0000720a0, 0xc00016e000, 0x2000, 0x2000, 0xc80160, 0x897101, 0xc00016e000)
C:/Users/sergy/go/pkg/mod/github.com/pion/[email protected]/packetio/buffer.go:135 +0x41
github.com/pion/webrtc/v2/internal/mux.(*Endpoint).Read(0xc00049d1a0, 0xc00016e000, 0x2000, 0x2000, 0x0, 0x0, 0xc0001403c0)
C:/Users/sergy/go/pkg/mod/github.com/pion/webrtc/[email protected]/internal/mux/endpoint.go:36 +0x54
github.com/pion/srtp.(*session).start.func1(0xc000128310, 0xc00049d8b0, 0xee9e00, 0xc000128310)
C:/Users/sergy/go/pkg/mod/github.com/pion/[email protected]/session.go:124 +0xd7
created by github.com/pion/srtp.(*session).start
C:/Users/sergy/go/pkg/mod/github.com/pion/[email protected]/session.go:111 +0x1e8
goroutine 102 [chan receive]:
github.com/pion/transport/packetio.(*Buffer).Read(0xc0000720f0, 0xc000172000, 0x2000, 0x2000, 0xc00022b17c, 0xee9d40, 0xc0002bfc50)
C:/Users/sergy/go/pkg/mod/github.com/pion/[email protected]/packetio/buffer.go:135 +0x41
github.com/pion/webrtc/v2/internal/mux.(*Endpoint).Read(0xc00049d1b0, 0xc000172000, 0x2000, 0x2000, 0x0, 0x0, 0x0)
C:/Users/sergy/go/pkg/mod/github.com/pion/webrtc/[email protected]/internal/mux/endpoint.go:36 +0x54
github.com/pion/srtp.(*session).start.func1(0xc000128380, 0xc00049d910, 0xee9dc0, 0xc000128380)
C:/Users/sergy/go/pkg/mod/github.com/pion/[email protected]/session.go:124 +0xd7
created by github.com/pion/srtp.(*session).start
C:/Users/sergy/go/pkg/mod/github.com/pion/[email protected]/session.go:111 +0x1e8
goroutine 103 [chan receive]:
github.com/pion/srtp.(*SessionSRTCP).AcceptStream(0xc000128380, 0xc000128380, 0x0, 0x0, 0x0)
C:/Users/sergy/go/pkg/mod/github.com/pion/[email protected]/session_srtcp.go:74 +0x4c
github.com/pion/webrtc/v2.(*PeerConnection).drainSRTP(0xc0003be000)
C:/Users/sergy/go/pkg/mod/github.com/pion/webrtc/[email protected]/peerconnection.go:1164 +0xcb
created by github.com/pion/webrtc/v2.(*PeerConnection).startTransports
C:/Users/sergy/go/pkg/mod/github.com/pion/webrtc/[email protected]/peerconnection.go:1885 +0x498
goroutine 104 [running]:
goroutine running on other thread; stack unavailable
created by github.com/pion/sctp.(*Association).init
C:/Users/sergy/go/pkg/mod/github.com/pion/[email protected]/association.go:281 +0xb1
goroutine 105 [runnable]:
github.com/pion/sctp.(*Association).writeLoop(0xc000116000)
C:/Users/sergy/go/pkg/mod/github.com/pion/[email protected]/association.go:437 +0x192
created by github.com/pion/sctp.(*Association).init
C:/Users/sergy/go/pkg/mod/github.com/pion/[email protected]/association.go:I1008 20:35:15.247388 11716 webrtc.go:165] Data channel closed
I1008 20:35:15.247388 11716 webrtc.go:166] Closed webrtc
282 +0xd6
goroutine 108 [chan receive]:
github.com/giongto35/cloud-game/pkg/worker/room.(*Room).startVideo(0xc0000f22d0, 0xa0, 0x90, 0xddc866, 0x3)
D:/Work/elysium/cloud-game/pkg/worker/room/media.go:188 +0x23b
created by github.com/giongto35/cloud-game/pkg/worker/room.NewRoom.func1
D:/Work/elysium/cloud-game/pkg/worker/room/room.go:111 +0x46f
goroutine 109 [chan receive]:
github.com/giongto35/cloud-game/pkg/worker/room.(*Room).startAudio(0xc0000f22d0, 0x8000)
D:/Work/elysium/cloud-game/pkg/worker/room/media.go:108 +0x2d4
created by github.com/giongto35/cloud-game/pkg/worker/room.NewRoom.func1
D:/Work/elysium/cloud-game/pkg/worker/room/room.go:112 +0x4a1
goroutine 74 [chan receive]:
github.com/giongto35/cloud-game/pkg/worker/room.(*Room).startVideo.func2(0xc000064420, 0xc0000f22d0)
D:/Work/elysium/cloud-game/pkg/worker/room/media.go:175 +0x10c
created by github.com/giongto35/cloud-game/pkg/worker/room.(*Room).startVideo
D:/Work/elysium/cloud-game/pkg/worker/room/media.go:167 +0x1fb
rax 0x6db45ee0
rbx 0x32a0000
rcx 0x6db99480
rdi 0xc000289d48
rsi 0xc00034e180
rbp 0xc000289d08
rsp 0x4fffd98
r8 0x5d86801
r9 0x1
r10 0x3
r11 0x4fffcd0
r12 0xbf5f5019cb2b5b50
r13 0x6
r14 0xc00035c000
r15 0x2030000
rip 0x0
rflags 0x10202
cs 0x33
fs 0x53
gs 0x2b
I1008 20:35:15.253389 5468 cws.go:156] [!] read: read tcp [::1]:8000->[::1]:58755: wsarecv: An existing connection was forcibly closed by the remote host.
I1008 20:35:15.253389 5468 handlers.go:311] Unregister server from overlord
error loading assets/emulator/libretro/cores/mgba_libretro.so, err 100
When trying to load Pokemon Gold ROM its graphics load oddly in a broken manner. Not sure if this is a ROM or emulator issue or something else, but worth looking into to make sure it can handle different ROMs.
https://github.com/go-bindata/go-bindata
GOOS=windows GOARCH=amd64 go build -ldflags -H=windowsgui
WebRTC Datachannel has some bug (when the connection disconnect abnormally)
ortc ERROR: 2019/10/23 19:24:00 Failed to accept data channel: unexpected packet type: WebRTC #Binary
In addition, WebRTC Datachannel seems not be currently supported by some browser.
Because game input payload is small, better use WebSocket for input.
Currently, cloud-game generates only one binary for both the program included in a single binary. While running we have to explicitly set flags to indicate which mode we intend it to run.
I am suggesting to split the two binaries into two different executables. They might share some of the same library packages but should live in different executables. I think there are some benefits - like -
1. we could include runtime flags specific to one program,
2. We could do different versioning for overlordhost and overlord,
3. one executable doesn't include the life cycle of the other one.
Here is some package restructure proposal that I think would suit nicely
cloud-game
|-- assets // includes all static .so or game file
|-- assests/games
|-- assests/lib
|-- cmd // will include all the executables
|-- cmd/overlord // will include the main.go for overlord. can use spf13/cobra
|-- cmd/overlordhost // main.go for overlordhost
|-- docs // includes all the static docs
|-- docs/design
|-- docs/userguide
|-- docs/site // includes static site pages for projects
|-- hack // Includes various scripts, build files
|-- hack/docker // includes docker build files
|-- hack/config // includes various config files like prometheus.conf
|-- hack/k8s // includes k8s runtime files
|-- hac/scripts // various scripts to build env or others
|-- pkg // includes all go/ cgo librarie codes. ie-
|-- pkg/api
|-- pkg/util
|-- pkg/config
|-- pkg/webrtc
| -- static // include project-level static resources like the logo
| -- static/logo
| -- static
|-- web // all the files for the web frontend
|-- web/
|-- vendor // go vendor directory
|-- Makefiles
|-- go.mod
|-- go.sum
|-- README.md
@giongto35 Let me know what you think about this? I can go forward with a PR if it seems okay. Thanks for this awesome project. ๐
hello giongto, it makes me happy to see and see that your project and the ideas I had and you told me a few months ago, come true ... ok now seeing the structure ... some questions arise.
regardless of the server where you are staying .. example a powerful one can I run demanding games say (ps2, xbox, xbox 360, game cube,? and another question can I add a frontend "launchbox" to the environment?
Integrate with Twitch API to stream game to Twitch, hence can gain more exposure.
I'am very appreciate this project
I was trying to make audio streaming work (again) and it is kinda working now. It's synced with the video but overly compressed for some reason (see example on the video down below).
So, here what I fixed so far:
After these fixes I was able to run the app with sound, but it's distorted. I think there is something with RTP opus packets or something on the client-side. No idea what to do next.
Maybe you have some (:?
Raw video with example (it's loud)
I got some error when starting the server and can't start any game on localhost:8000
.
2019/09/10 10:30:56 Listening at port: localhost:8000
2019/09/10 10:30:56 Running as worker
2019/09/10 10:30:56 Warn: Failed to create client: dialing: google: could not find default credentials. See https://developers.google.com/accounts/docs/application-default-credentials for more information.
2019/09/10 10:30:56 Listening at port: localhost: 9000
.....
.....
2019/09/10 10:31:04 === StartClient ===
2019/09/10 10:31:04 Start peerconnection 1b9e405b-1c5f-4e67-84a8-26d76d84d7de
2019/09/10 10:31:04 Error: Cannot create new webrtc session mDNS: failed to join multicast group
2019/09/10 10:31:04 Overlord: Received sdp request from a worker
2019/09/10 10:31:04 Overlord: Sending back sdp to browser
Connected
When escape function in the controller.js:
copyToClipboard(window.location.href.split('?')[0] + `?id=${escape(roomID)}`)
escapes roomId___gameName
then result link contains escaped characters for ;,/?:@&=+$
, as example:
Legend of Zelda, The - A Link To The Past Four Swords (U) [!] ->
Legend%20of%20Zelda%2C%20The%20-%20A%20Link%20To%20The%20Past%20Four%20Swords%20(U)%20%5B!%5D
but corresponding parser uses decodeURI
function, which leaves described above characters escaped, so on the server side it won't find the game by its name and a worker just crashes:
I1022 17:06:32.121056 11960 browser.go:88] Received room response from browser: 5e3024468942a6fd___Legend of Zelda%2C The - A Link To The Past Four Swords (U) [!]
I1022 17:06:32.122056 11812 room.go:101] Room 5e3024468942a6fd___Legend of Zelda%2C The - A Link To The Past Four Swords (U) [!] started. GamePath: , GameName:
I1022 17:06:32.122056 11812 nanoarch.go:237] error loading , err 34
It can be fixed by using decodeURIComponent function instead.
I've already fixed it in the new frontend, but not sure when I'll be ready to PR, so wanna let you know about this bug.
The instance can be respawned, so better store states on some cloud storage.
i had launch server and saw the website, but i can not see rom list. why?
Added proper nearest neighbour up/downscaling support with aspect ratio calculation.
Now it sets the initial viewport (output image) resolution to the base resolution from the loaded core upscaled by 2 to remove resampling artefacts (as on pictures below). So the manual resolution config for each core now removed completely.
A Sony BIOS intro now is being shown properly.
Need some testing.
There are host A, local host B and overlord(Master handles all session)
A person Y host a game on local host B with room_ID K
A person X connecting to host A. Person X enter room_ID K
.
Host A inform person X to create new offer. Offer is sent to overlord -> local host B (by websocket event)
Localhost creates new webRTC session based on the offer, attach to the room with roomID K. SDP is sent back from localhost to overlord and from overlord to Host A.
Browser create new peerconnection based on the SDP.
Host A maintains 1 single websocket connection with X. When X change room, the WS connection is still there, only the peer connection is updated.
It means: A WS session from host A to X can handle peerconnection to different host Y!! .
Current supported
Not tested yet
It seems there is no audio when you run games on the cloudretro.io or locally.
Maybe I missed that point in the docs, but does it support audio decode/playback right now?
Tried the latests versions:
W10 / Chrome (Stable, Dev, Canary),
Ubuntu 18 / Chrome (Stable),
Android 8 / Chrome (Stable).
There are a lot of c codes hardly coupled with the go codes. https://dave.cheney.net/2016/01/18/cgo-is-not-go. It is better to use to go as much as possible. I think there are some scopes to reduce some cgo codes. Let me know what is your thought about reducing the uses of cgo.
To enhance the collaborative playing experience. Need to show the number of players in the room + the ping from client to server.
The number is under share button
Test 1: On Single server
Test 2: On collaborative hosting
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.