very basic libretro core (no sound + limited controls)
This commit is contained in:
parent
e6b150136c
commit
529672f874
3
.gitmodules
vendored
3
.gitmodules
vendored
|
@ -1,3 +0,0 @@
|
||||||
[submodule "libretro/libretro-common"]
|
|
||||||
path = libretro/libretro-common
|
|
||||||
url = https://github.com/libretro/libretro-common.git
|
|
5
.vscode/settings.json
vendored
Normal file
5
.vscode/settings.json
vendored
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"files.associations": {
|
||||||
|
"libretro.h": "c"
|
||||||
|
}
|
||||||
|
}
|
2
Makefile
2
Makefile
|
@ -1,5 +1,5 @@
|
||||||
TARGET=chip8_libretro
|
TARGET=chip8_libretro
|
||||||
LIBRETRO_CORE=$(TARGET).so
|
LIBRETRO_CORE=$(TARGET).dylib
|
||||||
LIBRETRO_HEADER=$(TARGET).h
|
LIBRETRO_HEADER=$(TARGET).h
|
||||||
BUILD_VERSION=$(shell git rev-parse --short HEAD)
|
BUILD_VERSION=$(shell git rev-parse --short HEAD)
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,7 @@ const (
|
||||||
Width = 64
|
Width = 64
|
||||||
Height = 32
|
Height = 32
|
||||||
FPS = 60
|
FPS = 60
|
||||||
|
CyclesPerFrame = 8
|
||||||
SampleRate = 44100
|
SampleRate = 44100
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -98,6 +99,13 @@ func (emulator *Emulator) LoadFont() {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (emulator *Emulator) Update() {
|
||||||
|
emulator.UpdateTimers()
|
||||||
|
for cycle := 0; cycle < CyclesPerFrame; cycle++ {
|
||||||
|
emulator.Cycle()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (emulator *Emulator) UpdateTimers() {
|
func (emulator *Emulator) UpdateTimers() {
|
||||||
if emulator.ST != 0 {
|
if emulator.ST != 0 {
|
||||||
emulator.PlaySound()
|
emulator.PlaySound()
|
||||||
|
@ -110,6 +118,9 @@ func (emulator *Emulator) UpdateTimers() {
|
||||||
|
|
||||||
func (emulator *Emulator) Cycle() {
|
func (emulator *Emulator) Cycle() {
|
||||||
instruction := binary.BigEndian.Uint16(emulator.Memory[emulator.PC:])
|
instruction := binary.BigEndian.Uint16(emulator.Memory[emulator.PC:])
|
||||||
|
if instruction == 0x0000 {
|
||||||
|
return
|
||||||
|
}
|
||||||
emulator.PC += InstructionSize
|
emulator.PC += InstructionSize
|
||||||
|
|
||||||
nnn := instruction & 0x0FFF
|
nnn := instruction & 0x0FFF
|
||||||
|
|
1
go.mod
1
go.mod
|
@ -4,6 +4,7 @@ go 1.17
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/hajimehoshi/ebiten/v2 v2.2.5
|
github.com/hajimehoshi/ebiten/v2 v2.2.5
|
||||||
|
github.com/lanzafame/bobblehat v0.0.0-20190628174408-a0f0792c1691
|
||||||
github.com/stretchr/testify v1.7.0
|
github.com/stretchr/testify v1.7.0
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
2
go.sum
2
go.sum
|
@ -20,6 +20,8 @@ github.com/jfreymuth/vorbis v1.0.2/go.mod h1:DoftRo4AznKnShRl1GxiTFCseHr4zR9BN3T
|
||||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||||
|
github.com/lanzafame/bobblehat v0.0.0-20190628174408-a0f0792c1691 h1:o3aMwSNYkdM+w3zODsAQTGsP09c4r9E2DW42NjYRS0M=
|
||||||
|
github.com/lanzafame/bobblehat v0.0.0-20190628174408-a0f0792c1691/go.mod h1:CuWZprWAvuwcm4Sl0Vt1qL8foyta9HIBRLC5qyYtUW4=
|
||||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
|
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
|
||||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||||
github.com/pkg/browser v0.0.0-20180916011732-0a3d74bf9ce4/go.mod h1:4OwLy04Bl9Ef3GJJCoec+30X3LQs/0/m4HFRt/2LUSA=
|
github.com/pkg/browser v0.0.0-20180916011732-0a3d74bf9ce4/go.mod h1:4OwLy04Bl9Ef3GJJCoec+30X3LQs/0/m4HFRt/2LUSA=
|
||||||
|
|
|
@ -1,55 +0,0 @@
|
||||||
#include "libretro-common/include/libretro.h"
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
// RETRO_API void retro_set_environment(retro_environment_t);
|
|
||||||
// RETRO_API void retro_set_video_refresh(retro_video_refresh_t);
|
|
||||||
// RETRO_API void retro_set_audio_sample(retro_audio_sample_t);
|
|
||||||
// RETRO_API void retro_set_audio_sample_batch(retro_audio_sample_batch_t);
|
|
||||||
// RETRO_API void retro_set_input_poll(retro_input_poll_t);
|
|
||||||
// RETRO_API void retro_set_input_state(retro_input_state_t);
|
|
||||||
|
|
||||||
RETRO_API void retro_init(void)
|
|
||||||
{
|
|
||||||
void Initialize(void);
|
|
||||||
Initialize();
|
|
||||||
}
|
|
||||||
|
|
||||||
RETRO_API void retro_deinit(void)
|
|
||||||
{
|
|
||||||
void Deinitialize(void);
|
|
||||||
Deinitialize();
|
|
||||||
}
|
|
||||||
|
|
||||||
RETRO_API unsigned retro_api_version(void)
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
RETRO_API void retro_get_system_info(struct retro_system_info *info)
|
|
||||||
{
|
|
||||||
memset(info, 0, sizeof(*info));
|
|
||||||
void GetEmulatorInfo(struct retro_system_info * info);
|
|
||||||
GetEmulatorInfo(info);
|
|
||||||
}
|
|
||||||
|
|
||||||
RETRO_API void retro_get_system_av_info(struct retro_system_av_info *info)
|
|
||||||
{
|
|
||||||
memset(info, 0, sizeof(*info));
|
|
||||||
void GetEmulatorAVInfo(struct retro_system_av_info * info);
|
|
||||||
GetEmulatorAVInfo(info);
|
|
||||||
}
|
|
||||||
|
|
||||||
// RETRO_API void retro_set_controller_port_device(unsigned port, unsigned device);
|
|
||||||
// RETRO_API void retro_reset(void);
|
|
||||||
// RETRO_API void retro_run(void);
|
|
||||||
// RETRO_API size_t retro_serialize_size(void);
|
|
||||||
// RETRO_API bool retro_serialize(void *data, size_t size);
|
|
||||||
// RETRO_API bool retro_unserialize(const void *data, size_t size);
|
|
||||||
// RETRO_API void retro_cheat_reset(void);
|
|
||||||
// RETRO_API void retro_cheat_set(unsigned index, bool enabled, const char *code);
|
|
||||||
// RETRO_API bool retro_load_game(const struct retro_game_info *game);
|
|
||||||
// RETRO_API bool retro_load_game_special(unsigned game_type, const struct retro_game_info *info, size_t num_info);
|
|
||||||
// RETRO_API void retro_unload_game(void);
|
|
||||||
// RETRO_API unsigned retro_get_region(void);
|
|
||||||
// RETRO_API void *retro_get_memory_data(unsigned id);
|
|
||||||
// RETRO_API size_t retro_get_memory_size(unsigned id);
|
|
|
@ -1 +0,0 @@
|
||||||
Subproject commit 716bb5e7b761a3b4d44e069c84491d906d32aba0
|
|
162
libretro/libretro.c
Normal file
162
libretro/libretro.c
Normal file
|
@ -0,0 +1,162 @@
|
||||||
|
#include "libretro.h"
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
// callbacks
|
||||||
|
static retro_video_refresh_t retro_video_refresh = NULL;
|
||||||
|
static retro_input_poll_t retro_input_poll = NULL;
|
||||||
|
static retro_input_state_t retro_input_state = NULL;
|
||||||
|
|
||||||
|
// input params
|
||||||
|
static unsigned input_port = 0;
|
||||||
|
static unsigned input_device = 0;
|
||||||
|
|
||||||
|
RETRO_API void retro_set_environment(retro_environment_t cb)
|
||||||
|
{
|
||||||
|
// TODO: implement this
|
||||||
|
}
|
||||||
|
|
||||||
|
RETRO_API void retro_set_video_refresh(retro_video_refresh_t cb)
|
||||||
|
{
|
||||||
|
retro_video_refresh = cb;
|
||||||
|
}
|
||||||
|
|
||||||
|
RETRO_API void retro_set_audio_sample(retro_audio_sample_t cb)
|
||||||
|
{
|
||||||
|
// TODO: implement this
|
||||||
|
}
|
||||||
|
|
||||||
|
RETRO_API void retro_set_audio_sample_batch(retro_audio_sample_batch_t cb)
|
||||||
|
{
|
||||||
|
// TODO: implement this
|
||||||
|
}
|
||||||
|
|
||||||
|
RETRO_API void retro_set_input_poll(retro_input_poll_t cb)
|
||||||
|
{
|
||||||
|
retro_input_poll = cb;
|
||||||
|
}
|
||||||
|
|
||||||
|
RETRO_API void retro_set_input_state(retro_input_state_t cb)
|
||||||
|
{
|
||||||
|
retro_input_state = cb;
|
||||||
|
}
|
||||||
|
|
||||||
|
RETRO_API void retro_init(void)
|
||||||
|
{
|
||||||
|
void Initialize(void);
|
||||||
|
Initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
RETRO_API void retro_deinit(void)
|
||||||
|
{
|
||||||
|
void Deinitialize(void);
|
||||||
|
Deinitialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
RETRO_API unsigned retro_api_version(void)
|
||||||
|
{
|
||||||
|
return RETRO_API_VERSION;
|
||||||
|
}
|
||||||
|
|
||||||
|
RETRO_API void retro_get_system_info(struct retro_system_info *info)
|
||||||
|
{
|
||||||
|
memset(info, 0, sizeof(struct retro_system_info));
|
||||||
|
void GetEmulatorInfo(struct retro_system_info * info);
|
||||||
|
GetEmulatorInfo(info);
|
||||||
|
}
|
||||||
|
|
||||||
|
RETRO_API void retro_get_system_av_info(struct retro_system_av_info *info)
|
||||||
|
{
|
||||||
|
memset(info, 0, sizeof(struct retro_system_av_info));
|
||||||
|
void GetEmulatorAVInfo(struct retro_system_av_info * info);
|
||||||
|
GetEmulatorAVInfo(info);
|
||||||
|
}
|
||||||
|
|
||||||
|
RETRO_API void retro_set_controller_port_device(unsigned port, unsigned device)
|
||||||
|
{
|
||||||
|
input_port = port;
|
||||||
|
input_device = device;
|
||||||
|
}
|
||||||
|
|
||||||
|
RETRO_API void retro_reset(void)
|
||||||
|
{
|
||||||
|
void Reset(void);
|
||||||
|
Reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
RETRO_API void retro_run(void)
|
||||||
|
{
|
||||||
|
void Run(void);
|
||||||
|
Run();
|
||||||
|
}
|
||||||
|
|
||||||
|
RETRO_API size_t retro_serialize_size(void)
|
||||||
|
{
|
||||||
|
return 0; // TODO: implement this
|
||||||
|
}
|
||||||
|
|
||||||
|
RETRO_API bool retro_serialize(void *data, size_t size)
|
||||||
|
{
|
||||||
|
return true; // TODO: implement this
|
||||||
|
}
|
||||||
|
|
||||||
|
RETRO_API bool retro_unserialize(const void *data, size_t size)
|
||||||
|
{
|
||||||
|
return true; // TODO: implement this
|
||||||
|
}
|
||||||
|
|
||||||
|
RETRO_API void retro_cheat_reset(void)
|
||||||
|
{
|
||||||
|
// TODO: implement this
|
||||||
|
}
|
||||||
|
|
||||||
|
RETRO_API void retro_cheat_set(unsigned index, bool enabled, const char *code)
|
||||||
|
{
|
||||||
|
// TODO: implement this
|
||||||
|
}
|
||||||
|
|
||||||
|
RETRO_API bool retro_load_game(const struct retro_game_info *game)
|
||||||
|
{
|
||||||
|
bool LoadGame(struct retro_game_info *);
|
||||||
|
return LoadGame((struct retro_game_info *)game);
|
||||||
|
}
|
||||||
|
|
||||||
|
RETRO_API bool retro_load_game_special(unsigned game_type, const struct retro_game_info *info, size_t num_info)
|
||||||
|
{
|
||||||
|
return true; // TODO: implement this
|
||||||
|
}
|
||||||
|
|
||||||
|
RETRO_API void retro_unload_game(void)
|
||||||
|
{
|
||||||
|
// TODO: implement this
|
||||||
|
}
|
||||||
|
|
||||||
|
RETRO_API unsigned retro_get_region(void)
|
||||||
|
{
|
||||||
|
return RETRO_REGION_NTSC;
|
||||||
|
}
|
||||||
|
|
||||||
|
RETRO_API void *retro_get_memory_data(unsigned id)
|
||||||
|
{
|
||||||
|
return NULL; // TODO: implement this
|
||||||
|
}
|
||||||
|
|
||||||
|
RETRO_API size_t retro_get_memory_size(unsigned id)
|
||||||
|
{
|
||||||
|
return 0; // TODO: implement this
|
||||||
|
}
|
||||||
|
|
||||||
|
void VideoRefresh(const void *data, unsigned width, unsigned height, size_t pitch)
|
||||||
|
{
|
||||||
|
retro_video_refresh(data, width, height, pitch);
|
||||||
|
}
|
||||||
|
|
||||||
|
void InputPoll(void)
|
||||||
|
{
|
||||||
|
retro_input_poll();
|
||||||
|
}
|
||||||
|
|
||||||
|
int16_t InputState(unsigned id)
|
||||||
|
{
|
||||||
|
return retro_input_state(0, RETRO_DEVICE_JOYPAD, 0, id);
|
||||||
|
}
|
|
@ -1,27 +1,70 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
/*
|
/*
|
||||||
#include "libretro-common/include/libretro.h"
|
#include "libretro.h"
|
||||||
|
|
||||||
typedef struct retro_system_info retro_system_info;
|
typedef struct retro_system_info retro_system_info;
|
||||||
typedef struct retro_system_av_info retro_system_av_info;
|
typedef struct retro_system_av_info retro_system_av_info;
|
||||||
|
typedef struct retro_game_info retro_game_info;
|
||||||
|
|
||||||
|
void VideoRefresh(const void *data, unsigned width, unsigned height, size_t pitch);
|
||||||
|
void InputPoll(void);
|
||||||
|
int16_t InputState(unsigned id);
|
||||||
*/
|
*/
|
||||||
import "C"
|
import "C"
|
||||||
import (
|
import (
|
||||||
|
"image"
|
||||||
|
"image/draw"
|
||||||
|
"io/ioutil"
|
||||||
|
"log"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/lanzafame/bobblehat/sense/screen/color"
|
||||||
"github.com/tangzero/chip8-emulator/chip8"
|
"github.com/tangzero/chip8-emulator/chip8"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
RetroButtonB uint8 = iota
|
||||||
|
RetroButtonY
|
||||||
|
RetroButtonSelect
|
||||||
|
RetroButtonStart
|
||||||
|
RetroButtonUp
|
||||||
|
RetroButtonDown
|
||||||
|
RetroButtonLeft
|
||||||
|
RetroButtonRight
|
||||||
|
RetroButtonA
|
||||||
|
RetroButtonX
|
||||||
|
RetroButtonL
|
||||||
|
RetroButtonR
|
||||||
|
FirstRetroButton = RetroButtonB
|
||||||
|
LastRetroButton = RetroButtonR
|
||||||
|
)
|
||||||
|
|
||||||
|
var KeyMapping = map[uint8]uint8{
|
||||||
|
RetroButtonLeft: 0x04,
|
||||||
|
RetroButtonX: 0x05,
|
||||||
|
RetroButtonRight: 0x06,
|
||||||
|
}
|
||||||
|
|
||||||
var BuildVersion string
|
var BuildVersion string
|
||||||
var emulator *chip8.Emulator
|
var Emulator *chip8.Emulator
|
||||||
|
var FrameBuffer *color.RGB565
|
||||||
|
var KeysState [16]bool
|
||||||
|
|
||||||
//export Initialize
|
//export Initialize
|
||||||
func Initialize() {
|
func Initialize() {
|
||||||
emulator = chip8.NewEmulator(nil, nil)
|
playSound := func() {}
|
||||||
|
stopSound := func() {}
|
||||||
|
soundPlayer := func([]byte) (func(), func()) { return playSound, stopSound }
|
||||||
|
|
||||||
|
Emulator = chip8.NewEmulator(KeyPressed, soundPlayer)
|
||||||
|
|
||||||
|
FrameBuffer = color.NewRGB565(Emulator.Display.Rect)
|
||||||
}
|
}
|
||||||
|
|
||||||
//export Deinitialize
|
//export Deinitialize
|
||||||
func Deinitialize() {
|
func Deinitialize() {
|
||||||
emulator = nil
|
Emulator = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
//export GetEmulatorInfo
|
//export GetEmulatorInfo
|
||||||
|
@ -29,7 +72,7 @@ func GetEmulatorInfo(info *C.retro_system_info) {
|
||||||
info.library_name = C.CString("CHIP-8 Emulator by TangZero")
|
info.library_name = C.CString("CHIP-8 Emulator by TangZero")
|
||||||
info.library_version = C.CString(BuildVersion)
|
info.library_version = C.CString(BuildVersion)
|
||||||
info.valid_extensions = C.CString("ch8")
|
info.valid_extensions = C.CString("ch8")
|
||||||
info.need_fullpath = false
|
info.need_fullpath = true
|
||||||
info.block_extract = false
|
info.block_extract = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,4 +87,47 @@ func GetEmulatorAVInfo(info *C.retro_system_av_info) {
|
||||||
info.timing.sample_rate = 44100
|
info.timing.sample_rate = 44100
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//export Reset
|
||||||
|
func Reset() {
|
||||||
|
Emulator.Reset()
|
||||||
|
}
|
||||||
|
|
||||||
|
//export Run
|
||||||
|
func Run() {
|
||||||
|
C.InputPoll()
|
||||||
|
UpdateKeysState()
|
||||||
|
|
||||||
|
Emulator.Update()
|
||||||
|
|
||||||
|
// convert from RGBA to RGB565
|
||||||
|
draw.Draw(FrameBuffer, Emulator.Display.Rect, Emulator.Display, image.Point{}, draw.Src)
|
||||||
|
|
||||||
|
// draw frame
|
||||||
|
C.VideoRefresh(unsafe.Pointer(&FrameBuffer.Pix[0]), chip8.Width, chip8.Height, C.size_t(FrameBuffer.Stride))
|
||||||
|
}
|
||||||
|
|
||||||
|
//export LoadGame
|
||||||
|
func LoadGame(game *C.retro_game_info) bool {
|
||||||
|
data, err := ioutil.ReadFile(C.GoString(game.path))
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
Emulator.LoadROM(chip8.ROM{Data: data})
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func UpdateKeysState() {
|
||||||
|
for button := FirstRetroButton; button < LastRetroButton; button++ {
|
||||||
|
key, ok := KeyMapping[button]
|
||||||
|
if ok {
|
||||||
|
KeysState[key] = C.InputState(C.uint(button)) > 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func KeyPressed(key uint8) bool {
|
||||||
|
return KeysState[key]
|
||||||
|
}
|
||||||
|
|
||||||
func main() {}
|
func main() {}
|
||||||
|
|
3890
libretro/libretro.h
Normal file
3890
libretro/libretro.h
Normal file
File diff suppressed because it is too large
Load Diff
16
main.go
16
main.go
|
@ -4,7 +4,6 @@ import (
|
||||||
"bytes"
|
"bytes"
|
||||||
_ "embed"
|
_ "embed"
|
||||||
"log"
|
"log"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/hajimehoshi/ebiten/v2"
|
"github.com/hajimehoshi/ebiten/v2"
|
||||||
"github.com/hajimehoshi/ebiten/v2/audio"
|
"github.com/hajimehoshi/ebiten/v2/audio"
|
||||||
|
@ -57,24 +56,11 @@ type GUI struct {
|
||||||
Emulator *chip8.Emulator
|
Emulator *chip8.Emulator
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gui *GUI) Run() {
|
|
||||||
for {
|
|
||||||
gui.Emulator.Cycle()
|
|
||||||
time.Sleep(time.Millisecond * 2)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (gui *GUI) Update() error {
|
func (gui *GUI) Update() error {
|
||||||
if ebiten.IsKeyPressed(ebiten.KeyEscape) {
|
if ebiten.IsKeyPressed(ebiten.KeyEscape) {
|
||||||
gui.Emulator.Reset()
|
gui.Emulator.Reset()
|
||||||
}
|
}
|
||||||
switch gui.State {
|
gui.Emulator.Update()
|
||||||
case LoadingState:
|
|
||||||
go gui.Run()
|
|
||||||
gui.State = RunningState
|
|
||||||
case RunningState:
|
|
||||||
gui.Emulator.UpdateTimers()
|
|
||||||
}
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user