Merge branch 'sokol'
This commit is contained in:
		@@ -14,3 +14,4 @@ matrix:
 | 
				
			|||||||
        apt:
 | 
					        apt:
 | 
				
			||||||
          packages:
 | 
					          packages:
 | 
				
			||||||
            - libgtk-3-dev
 | 
					            - libgtk-3-dev
 | 
				
			||||||
 | 
					            - libasound2-dev
 | 
				
			||||||
 
 | 
				
			|||||||
 Submodule 3rd-party updated: 04a806d1e6...1ff2bf5d72
									
								
							
							
								
								
									
										168
									
								
								CMakeLists.txt
									
									
									
									
									
								
							
							
						
						
									
										168
									
								
								CMakeLists.txt
									
									
									
									
									
								
							@@ -217,6 +217,10 @@ target_include_directories(tic80core PRIVATE 3rd-party/fennel)
 | 
				
			|||||||
add_dependencies(tic80core lua lpeg wren squirrel giflib)
 | 
					add_dependencies(tic80core lua lpeg wren squirrel giflib)
 | 
				
			||||||
target_link_libraries(tic80core lua lpeg wren squirrel giflib)
 | 
					target_link_libraries(tic80core lua lpeg wren squirrel giflib)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if(LINUX)
 | 
				
			||||||
 | 
						target_link_libraries(tic80core m)
 | 
				
			||||||
 | 
					endif()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
################################
 | 
					################################
 | 
				
			||||||
# SDL2
 | 
					# SDL2
 | 
				
			||||||
################################
 | 
					################################
 | 
				
			||||||
@@ -239,7 +243,7 @@ endif()
 | 
				
			|||||||
if(NOT EMSCRIPTEN)
 | 
					if(NOT EMSCRIPTEN)
 | 
				
			||||||
	set(EXAMPLE_DIR examples)
 | 
						set(EXAMPLE_DIR examples)
 | 
				
			||||||
	set(EXAMPLE_SRC 
 | 
						set(EXAMPLE_SRC 
 | 
				
			||||||
		${EXAMPLE_DIR}/sdl-renderer.c
 | 
							${EXAMPLE_DIR}/sdl/main.c
 | 
				
			||||||
	)
 | 
						)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if(WIN32)
 | 
						if(WIN32)
 | 
				
			||||||
@@ -260,6 +264,77 @@ if(NOT EMSCRIPTEN)
 | 
				
			|||||||
	target_link_libraries(sdl-renderer tic80core SDL2-static SDL2main)
 | 
						target_link_libraries(sdl-renderer tic80core SDL2-static SDL2main)
 | 
				
			||||||
endif()
 | 
					endif()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					################################
 | 
				
			||||||
 | 
					# Sokol
 | 
				
			||||||
 | 
					################################
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					set(SOKOL_LIB_SRC src/system/sokol_gfx.c)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if(APPLE)
 | 
				
			||||||
 | 
					    set(SOKOL_LIB_SRC ${SOKOL_LIB_SRC} src/system/sokol_impl.m)
 | 
				
			||||||
 | 
					else()
 | 
				
			||||||
 | 
						set(SOKOL_LIB_SRC ${SOKOL_LIB_SRC} src/system/sokol_impl.c)
 | 
				
			||||||
 | 
					endif()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					add_library(sokol ${SOKOL_LIB_SRC})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if(APPLE)
 | 
				
			||||||
 | 
						target_compile_definitions(sokol PRIVATE SOKOL_METAL)
 | 
				
			||||||
 | 
					elseif(WIN32)
 | 
				
			||||||
 | 
						target_compile_definitions(sokol PRIVATE SOKOL_D3D11 SOKOL_D3D11_SHADER_COMPILER)
 | 
				
			||||||
 | 
					elseif(LINUX)
 | 
				
			||||||
 | 
						target_compile_definitions(sokol PRIVATE SOKOL_GLCORE33)
 | 
				
			||||||
 | 
					endif()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if(APPLE)
 | 
				
			||||||
 | 
						set_property (TARGET sokol APPEND_STRING PROPERTY 
 | 
				
			||||||
 | 
					    	COMPILE_FLAGS "-fobjc-arc")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						target_link_libraries(sokol 
 | 
				
			||||||
 | 
							"-framework Cocoa" 
 | 
				
			||||||
 | 
							"-framework QuartzCore"
 | 
				
			||||||
 | 
							"-framework Metal"
 | 
				
			||||||
 | 
							"-framework MetalKit"
 | 
				
			||||||
 | 
							"-framework AudioToolbox"
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
					elseif(WIN32)
 | 
				
			||||||
 | 
						target_link_libraries(sokol D3D11)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if(MINGW)
 | 
				
			||||||
 | 
							target_link_libraries(sokol D3dcompiler_47)
 | 
				
			||||||
 | 
						endif()
 | 
				
			||||||
 | 
					elseif(LINUX)
 | 
				
			||||||
 | 
						set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pthread")
 | 
				
			||||||
 | 
						target_link_libraries(sokol X11 GL m dl asound)
 | 
				
			||||||
 | 
					endif()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					target_include_directories(sokol PRIVATE 3rd-party/sokol)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					################################
 | 
				
			||||||
 | 
					# Sokol renderer example
 | 
				
			||||||
 | 
					################################
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					set(SOKOL_SRC 
 | 
				
			||||||
 | 
						${EXAMPLE_DIR}/sokol/main.c
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if(WIN32)
 | 
				
			||||||
 | 
						add_executable(sokol-renderer WIN32 ${SOKOL_SRC})
 | 
				
			||||||
 | 
					else()
 | 
				
			||||||
 | 
						add_executable(sokol-renderer ${SOKOL_SRC})
 | 
				
			||||||
 | 
					endif()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if(MINGW)
 | 
				
			||||||
 | 
						target_link_libraries(sokol-renderer mingw32)
 | 
				
			||||||
 | 
					endif()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					target_include_directories(sokol-renderer PRIVATE include)
 | 
				
			||||||
 | 
					target_include_directories(sokol-renderer PRIVATE 3rd-party/sokol)
 | 
				
			||||||
 | 
					target_include_directories(sokol-renderer PRIVATE src)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					add_dependencies(sokol-renderer tic80core sokol)
 | 
				
			||||||
 | 
					target_link_libraries(sokol-renderer tic80core sokol)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
################################
 | 
					################################
 | 
				
			||||||
# SDL GPU
 | 
					# SDL GPU
 | 
				
			||||||
################################
 | 
					################################
 | 
				
			||||||
@@ -445,22 +520,24 @@ target_compile_definitions(tic80prolib PRIVATE TIC80_PRO)
 | 
				
			|||||||
# TIC-80 app
 | 
					# TIC-80 app
 | 
				
			||||||
################################
 | 
					################################
 | 
				
			||||||
 | 
					
 | 
				
			||||||
set(TIC80_DIR src)
 | 
					 | 
				
			||||||
set(TIC80_SRC
 | 
					 | 
				
			||||||
	${TIC80_DIR}/net.c
 | 
					 | 
				
			||||||
	${TIC80_DIR}/system.c
 | 
					 | 
				
			||||||
	${TIC80_DIR}/ext/file_dialog.c
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
if(APPLE)
 | 
					 | 
				
			||||||
	set(TIC80_SRC ${TIC80_SRC} ${TIC80_DIR}/ext/file_dialog.m)
 | 
					 | 
				
			||||||
endif()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
foreach(TIC80_OUTPUT ${TIC80_OUTPUTS})
 | 
					foreach(TIC80_OUTPUT ${TIC80_OUTPUTS})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						set(TIC80_SRC src/ext/file_dialog.c)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if(APPLE)
 | 
				
			||||||
 | 
							set(TIC80_SRC ${TIC80_SRC} src/ext/file_dialog.m)
 | 
				
			||||||
 | 
						endif()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						set(TIC80_SRC ${TIC80_SRC} src/net.c src/system/sdlgpu.c)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if(WIN32)
 | 
						if(WIN32)
 | 
				
			||||||
		set(TIC80_SRC ${TIC80_SRC} build/windows/tic80.rc)
 | 
							set(TIC80_SRC ${TIC80_SRC} build/windows/tic80.rc)
 | 
				
			||||||
		add_executable(${TIC80_OUTPUT} WIN32 ${TIC80_SRC})
 | 
							if(CMAKE_BUILD_TYPE STREQUAL "Debug")
 | 
				
			||||||
 | 
							else()
 | 
				
			||||||
 | 
								set(SYSTEM_TYPE WIN32)
 | 
				
			||||||
 | 
							endif()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							add_executable(${TIC80_OUTPUT} ${SYSTEM_TYPE} ${TIC80_SRC})
 | 
				
			||||||
	elseif(APPLE)
 | 
						elseif(APPLE)
 | 
				
			||||||
		add_executable(${TIC80_OUTPUT} MACOSX_BUNDLE ${TIC80_SRC} build/macosx/tic80.icns)
 | 
							add_executable(${TIC80_OUTPUT} MACOSX_BUNDLE ${TIC80_SRC} build/macosx/tic80.icns)
 | 
				
			||||||
		set_source_files_properties(build/macosx/tic80.icns PROPERTIES MACOSX_PACKAGE_LOCATION RESOURCES)
 | 
							set_source_files_properties(build/macosx/tic80.icns PROPERTIES MACOSX_PACKAGE_LOCATION RESOURCES)
 | 
				
			||||||
@@ -470,9 +547,11 @@ foreach(TIC80_OUTPUT ${TIC80_OUTPUTS})
 | 
				
			|||||||
	endif()
 | 
						endif()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	target_include_directories(${TIC80_OUTPUT} PRIVATE include)
 | 
						target_include_directories(${TIC80_OUTPUT} PRIVATE include)
 | 
				
			||||||
	target_include_directories(${TIC80_OUTPUT} PRIVATE 3rd-party/SDL2-2.0.8/include)
 | 
						target_include_directories(${TIC80_OUTPUT} PRIVATE src)
 | 
				
			||||||
	target_include_directories(${TIC80_OUTPUT} PRIVATE 3rd-party/sdl-gpu/include)
 | 
					 | 
				
			||||||
	target_include_directories(${TIC80_OUTPUT} PRIVATE 3rd-party/SDL2_net-2.0.1)
 | 
						target_include_directories(${TIC80_OUTPUT} PRIVATE 3rd-party/SDL2_net-2.0.1)
 | 
				
			||||||
 | 
						target_include_directories(${TIC80_OUTPUT} PRIVATE 3rd-party/SDL2-2.0.8/include)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						target_include_directories(${TIC80_OUTPUT} PRIVATE 3rd-party/sdl-gpu/include)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if(MINGW)
 | 
						if(MINGW)
 | 
				
			||||||
		target_link_libraries(${TIC80_OUTPUT} mingw32)
 | 
							target_link_libraries(${TIC80_OUTPUT} mingw32)
 | 
				
			||||||
@@ -499,3 +578,62 @@ foreach(TIC80_OUTPUT ${TIC80_OUTPUTS})
 | 
				
			|||||||
	endif()
 | 
						endif()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
endforeach()
 | 
					endforeach()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					################################
 | 
				
			||||||
 | 
					# TIC-80 app (Sokol)
 | 
				
			||||||
 | 
					################################
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					foreach(TIC80_OUTPUT ${TIC80_OUTPUTS})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						set(TIC80_SRC src/ext/file_dialog.c)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if(APPLE)
 | 
				
			||||||
 | 
							set(TIC80_SRC ${TIC80_SRC} src/ext/file_dialog.m)
 | 
				
			||||||
 | 
						endif()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						set(TIC80_SRC ${TIC80_SRC} src/system/sokol.c)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if(WIN32)
 | 
				
			||||||
 | 
							set(TIC80_SRC ${TIC80_SRC} build/windows/tic80.rc)
 | 
				
			||||||
 | 
							if(CMAKE_BUILD_TYPE STREQUAL "Debug")
 | 
				
			||||||
 | 
							else()
 | 
				
			||||||
 | 
								set(SYSTEM_TYPE WIN32)
 | 
				
			||||||
 | 
							endif()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							add_executable(${TIC80_OUTPUT}-sokol ${SYSTEM_TYPE} ${TIC80_SRC})
 | 
				
			||||||
 | 
						elseif(APPLE)
 | 
				
			||||||
 | 
							add_executable(${TIC80_OUTPUT}-sokol MACOSX_BUNDLE ${TIC80_SRC} build/macosx/tic80.icns)
 | 
				
			||||||
 | 
							set_source_files_properties(build/macosx/tic80.icns PROPERTIES MACOSX_PACKAGE_LOCATION RESOURCES)
 | 
				
			||||||
 | 
							set_target_properties(${TIC80_OUTPUT}-sokol PROPERTIES MACOSX_BUNDLE_INFO_PLIST build/macosx/${TIC80_OUTPUT}-sokol.plist)
 | 
				
			||||||
 | 
						else()
 | 
				
			||||||
 | 
							add_executable(${TIC80_OUTPUT}-sokol ${TIC80_SRC})
 | 
				
			||||||
 | 
						endif()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						target_include_directories(${TIC80_OUTPUT}-sokol PRIVATE include)
 | 
				
			||||||
 | 
						target_include_directories(${TIC80_OUTPUT}-sokol PRIVATE src)
 | 
				
			||||||
 | 
						target_include_directories(${TIC80_OUTPUT}-sokol PRIVATE 3rd-party/SDL2_net-2.0.1)
 | 
				
			||||||
 | 
						target_include_directories(${TIC80_OUTPUT}-sokol PRIVATE 3rd-party/SDL2-2.0.8/include)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						target_include_directories(${TIC80_OUTPUT}-sokol PRIVATE 3rd-party/sokol)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if(MINGW)
 | 
				
			||||||
 | 
							target_link_libraries(${TIC80_OUTPUT}-sokol mingw32)
 | 
				
			||||||
 | 
						endif()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						add_dependencies(${TIC80_OUTPUT}-sokol ${TIC80_OUTPUT}lib sokol)
 | 
				
			||||||
 | 
						target_link_libraries(${TIC80_OUTPUT}-sokol ${TIC80_OUTPUT}lib sokol)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if(LINUX)
 | 
				
			||||||
 | 
							include(FindPkgConfig)
 | 
				
			||||||
 | 
							if(NOT PKG_CONFIG_FOUND) 
 | 
				
			||||||
 | 
								message(FATAL_ERROR "We need pkg-config to compile this project")
 | 
				
			||||||
 | 
							endif()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							pkg_check_modules(GTK REQUIRED gtk+-3.0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							target_include_directories(${TIC80_OUTPUT}-sokol PRIVATE ${GTK_INCLUDE_DIRS})
 | 
				
			||||||
 | 
							target_link_libraries(${TIC80_OUTPUT}-sokol ${GTK_LIBRARIES})
 | 
				
			||||||
 | 
						endif()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					endforeach()
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										28
									
								
								appveyor.yml
									
									
									
									
									
								
							
							
						
						
									
										28
									
								
								appveyor.yml
									
									
									
									
									
								
							@@ -1,22 +1,18 @@
 | 
				
			|||||||
version: '{build}'
 | 
					version: '{build}'
 | 
				
			||||||
image: Visual Studio 2017
 | 
					image: Visual Studio 2015
 | 
				
			||||||
 | 
					 | 
				
			||||||
configuration:
 | 
					 | 
				
			||||||
- Release
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
platform:
 | 
					 | 
				
			||||||
- x64
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
environment:
 | 
					environment:
 | 
				
			||||||
  matrix:
 | 
					  matrix:
 | 
				
			||||||
  - arch: Win64
 | 
					    - COMPILER: MSVC
 | 
				
			||||||
 | 
					    - COMPILER: MSVC64
 | 
				
			||||||
 | 
					    - COMPILER: MinGW-w64
 | 
				
			||||||
 | 
					
 | 
				
			||||||
install: git submodule update --init --recursive
 | 
					install: 
 | 
				
			||||||
 | 
					  - git submodule update --init --recursive
 | 
				
			||||||
 | 
					  - if [%COMPILER%]==[MinGW-w64] set PATH=C:\mingw-w64\x86_64-7.3.0-posix-seh-rt_v5-rev0\mingw64\bin;%PATH%
 | 
				
			||||||
 | 
					
 | 
				
			||||||
before_build:
 | 
					build_script:
 | 
				
			||||||
  cmd: cmake -G "Visual Studio 15 2017 Win64"   
 | 
					  - if [%COMPILER%]==[MinGW-w64] cmake -G "MinGW Makefiles" -DCMAKE_BUILD_TYPE=MinSizeRel -DCMAKE_SH=CMAKE_SH-NOTFOUND .
 | 
				
			||||||
 | 
					  - if [%COMPILER%]==[MSVC] cmake -G "Visual Studio 14 2015" -DCMAKE_BUILD_TYPE=MinSizeRel .
 | 
				
			||||||
build:
 | 
					  - if [%COMPILER%]==[MSVC64] cmake -G "Visual Studio 14 2015 Win64" -DCMAKE_BUILD_TYPE=MinSizeRel .
 | 
				
			||||||
  project: c:\projects\tic-80\TIC-80.sln
 | 
					  - cmake --build .
 | 
				
			||||||
  verbosity: minimal
 | 
					 | 
				
			||||||
  parallel: true
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										30
									
								
								build/macosx/tic80-sokol.plist
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								build/macosx/tic80-sokol.plist
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,30 @@
 | 
				
			|||||||
 | 
					<?xml version="1.0" encoding="UTF-8"?>
 | 
				
			||||||
 | 
					<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
 | 
				
			||||||
 | 
					<plist version="1.0">
 | 
				
			||||||
 | 
					<dict>
 | 
				
			||||||
 | 
					  <key>CFBundleDevelopmentRegion</key>
 | 
				
			||||||
 | 
					  <string>en</string>
 | 
				
			||||||
 | 
					  <key>CFBundleDisplayName</key>
 | 
				
			||||||
 | 
					  <string>TIC-80 Sokol</string>
 | 
				
			||||||
 | 
					  <key>CFBundleExecutable</key>
 | 
				
			||||||
 | 
					  <string>tic80-sokol</string>
 | 
				
			||||||
 | 
					  <key>CFBundleIconFile</key>
 | 
				
			||||||
 | 
					  <string>tic80.icns</string>
 | 
				
			||||||
 | 
					  <key>CFBundleIdentifier</key>
 | 
				
			||||||
 | 
					  <string>com.nesbox.tic</string>
 | 
				
			||||||
 | 
					  <key>CFBundleInfoDictionaryVersion</key>
 | 
				
			||||||
 | 
					  <string>6.0</string>
 | 
				
			||||||
 | 
					  <key>CFBundleName</key>
 | 
				
			||||||
 | 
					  <string>TIC-80 Sokol</string>
 | 
				
			||||||
 | 
					  <key>CFBundlePackageType</key>
 | 
				
			||||||
 | 
					  <string>APPL</string>
 | 
				
			||||||
 | 
					  <key>CFBundleShortVersionString</key>
 | 
				
			||||||
 | 
					  <string>0.70.6</string>
 | 
				
			||||||
 | 
					  <key>CFBundleVersion</key>
 | 
				
			||||||
 | 
					  <string>0.70.6</string>
 | 
				
			||||||
 | 
					  <key>NSHumanReadableCopyright</key>
 | 
				
			||||||
 | 
					  <string>http://tic.computer © 2017</string>
 | 
				
			||||||
 | 
					  <key>NSHighResolutionCapable</key>
 | 
				
			||||||
 | 
					  <true/>
 | 
				
			||||||
 | 
					</dict>
 | 
				
			||||||
 | 
					</plist>
 | 
				
			||||||
							
								
								
									
										30
									
								
								build/macosx/tic80pro-sokol.plist
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								build/macosx/tic80pro-sokol.plist
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,30 @@
 | 
				
			|||||||
 | 
					<?xml version="1.0" encoding="UTF-8"?>
 | 
				
			||||||
 | 
					<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
 | 
				
			||||||
 | 
					<plist version="1.0">
 | 
				
			||||||
 | 
					<dict>
 | 
				
			||||||
 | 
					  <key>CFBundleDevelopmentRegion</key>
 | 
				
			||||||
 | 
					  <string>en</string>
 | 
				
			||||||
 | 
					  <key>CFBundleDisplayName</key>
 | 
				
			||||||
 | 
					  <string>TIC-80 Pro Sokol</string>
 | 
				
			||||||
 | 
					  <key>CFBundleExecutable</key>
 | 
				
			||||||
 | 
					  <string>tic80pro-sokol</string>
 | 
				
			||||||
 | 
					  <key>CFBundleIconFile</key>
 | 
				
			||||||
 | 
					  <string>tic80.icns</string>
 | 
				
			||||||
 | 
					  <key>CFBundleIdentifier</key>
 | 
				
			||||||
 | 
					  <string>com.nesbox.tic</string>
 | 
				
			||||||
 | 
					  <key>CFBundleInfoDictionaryVersion</key>
 | 
				
			||||||
 | 
					  <string>6.0</string>
 | 
				
			||||||
 | 
					  <key>CFBundleName</key>
 | 
				
			||||||
 | 
					  <string>TIC-80 Pro Sokol</string>
 | 
				
			||||||
 | 
					  <key>CFBundlePackageType</key>
 | 
				
			||||||
 | 
					  <string>APPL</string>
 | 
				
			||||||
 | 
					  <key>CFBundleShortVersionString</key>
 | 
				
			||||||
 | 
					  <string>0.70.6</string>
 | 
				
			||||||
 | 
					  <key>CFBundleVersion</key>
 | 
				
			||||||
 | 
					  <string>0.70.6</string>
 | 
				
			||||||
 | 
					  <key>NSHumanReadableCopyright</key>
 | 
				
			||||||
 | 
					  <string>http://tic.computer © 2017</string>
 | 
				
			||||||
 | 
					  <key>NSHighResolutionCapable</key>
 | 
				
			||||||
 | 
					  <true/>
 | 
				
			||||||
 | 
					</dict>
 | 
				
			||||||
 | 
					</plist>
 | 
				
			||||||
@@ -1,23 +0,0 @@
 | 
				
			|||||||
CC=gcc
 | 
					 | 
				
			||||||
OPT=-O3 -Wall -std=c99
 | 
					 | 
				
			||||||
INCLUDES= \
 | 
					 | 
				
			||||||
	-I../include \
 | 
					 | 
				
			||||||
	-I../include/sdl2 \
 | 
					 | 
				
			||||||
	-I../include/tic80
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
LINKER_FLAGS= \
 | 
					 | 
				
			||||||
	-L../lib/mingw \
 | 
					 | 
				
			||||||
	-L../bin \
 | 
					 | 
				
			||||||
	-ltic80 \
 | 
					 | 
				
			||||||
	-lmingw32 -lSDL2main -lSDL2.dll \
 | 
					 | 
				
			||||||
	-mwindows
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
SOURCES=\
 | 
					 | 
				
			||||||
	sdl-renderer.c
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
SDL_RENDERER = ../bin/sdl-renderer.exe
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
all: $(SDL_RENDERER)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
$(SDL_RENDERER): $(SOURCES)
 | 
					 | 
				
			||||||
	$(CC) $(INCLUDES) $< $(OPT) $(LINKER_FLAGS) -o $@
 | 
					 | 
				
			||||||
							
								
								
									
										119
									
								
								examples/sokol/main.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										119
									
								
								examples/sokol/main.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,119 @@
 | 
				
			|||||||
 | 
					#include "system/sokol.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <stdio.h>
 | 
				
			||||||
 | 
					#include <stdlib.h>
 | 
				
			||||||
 | 
					#include <string.h>
 | 
				
			||||||
 | 
					#include <limits.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <tic80.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static tic80* tic = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void app_init(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    saudio_desc desc = {0};
 | 
				
			||||||
 | 
					    desc.num_channels = 2;
 | 
				
			||||||
 | 
					    saudio_setup(&desc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    FILE* file = fopen("cart.tic", "rb");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if(file)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        fseek(file, 0, SEEK_END);
 | 
				
			||||||
 | 
					        int size = ftell(file);
 | 
				
			||||||
 | 
					        fseek(file, 0, SEEK_SET);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        void* cart = malloc(size);
 | 
				
			||||||
 | 
					        if(cart) fread(cart, size, 1, file);
 | 
				
			||||||
 | 
					        fclose(file);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if(cart)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            printf("%s\n", "cart loaded");
 | 
				
			||||||
 | 
					            tic = tic80_create(saudio_sample_rate());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if(tic)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                printf("%s\n", "tic created");
 | 
				
			||||||
 | 
					                tic80_load(tic, cart, size);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    sokol_gfx_init(TIC80_FULLWIDTH, TIC80_FULLHEIGHT, 1, 1, false, false);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static tic80_input tic_input;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void app_frame(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if(tic)
 | 
				
			||||||
 | 
					        tic80_tick(tic, tic_input);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    sokol_gfx_draw(tic->screen);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    static float floatSamples[44100 / 60 * 2];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for(s32 i = 0; i < tic->sound.count; i++)
 | 
				
			||||||
 | 
					        floatSamples[i] = (float)tic->sound.samples[i] / SHRT_MAX;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    saudio_push(floatSamples, tic->sound.count / 2);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void app_input(const sapp_event* event)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    static const sapp_keycode Keys[] = 
 | 
				
			||||||
 | 
					    { 
 | 
				
			||||||
 | 
					        SAPP_KEYCODE_UP,
 | 
				
			||||||
 | 
					        SAPP_KEYCODE_DOWN,
 | 
				
			||||||
 | 
					        SAPP_KEYCODE_LEFT,
 | 
				
			||||||
 | 
					        SAPP_KEYCODE_RIGHT,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        SAPP_KEYCODE_Z,
 | 
				
			||||||
 | 
					        SAPP_KEYCODE_X,
 | 
				
			||||||
 | 
					        SAPP_KEYCODE_A,
 | 
				
			||||||
 | 
					        SAPP_KEYCODE_S,
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    switch (event->type)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					    case SAPP_EVENTTYPE_KEY_DOWN:
 | 
				
			||||||
 | 
					    case SAPP_EVENTTYPE_KEY_UP:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for (int i = 0; i < sizeof Keys / sizeof Keys[0]; i++)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if (event->key_code == Keys[i])
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                if(event->type == SAPP_EVENTTYPE_KEY_DOWN)
 | 
				
			||||||
 | 
					                    tic_input.gamepads.first.data |= (1 << i);
 | 
				
			||||||
 | 
					                else
 | 
				
			||||||
 | 
					                    tic_input.gamepads.first.data &= ~(1 << i);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					    default:
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void app_cleanup(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if(tic)
 | 
				
			||||||
 | 
					        tic80_delete(tic);
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    sg_shutdown();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sapp_desc sokol_main(int argc, char* argv[]) {
 | 
				
			||||||
 | 
					    // args_init(argc, argv);
 | 
				
			||||||
 | 
					    return (sapp_desc) {
 | 
				
			||||||
 | 
					        .init_cb = app_init,
 | 
				
			||||||
 | 
					        .frame_cb = app_frame,
 | 
				
			||||||
 | 
					        .event_cb = app_input,
 | 
				
			||||||
 | 
					        .cleanup_cb = app_cleanup,
 | 
				
			||||||
 | 
					        .width = 3 * TIC80_FULLWIDTH,
 | 
				
			||||||
 | 
					        .height = 3 * TIC80_FULLHEIGHT,
 | 
				
			||||||
 | 
					        .window_title = "TIC-80 with Sokol renderer",
 | 
				
			||||||
 | 
					        .ios_keyboard_resizes_canvas = true
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -22,6 +22,12 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#pragma once
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if !defined(TIC_BUILD_WITH_LUA) && \
 | 
				
			||||||
 | 
						!defined(TIC_BUILD_WITH_MOON) && \
 | 
				
			||||||
 | 
						!defined(TIC_BUILD_WITH_FENNEL) && \
 | 
				
			||||||
 | 
						!defined(TIC_BUILD_WITH_JS) && \
 | 
				
			||||||
 | 
						!defined(TIC_BUILD_WITH_WREN)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define TIC_BUILD_WITH_LUA 		1
 | 
					#define TIC_BUILD_WITH_LUA 		1
 | 
				
			||||||
#define TIC_BUILD_WITH_MOON 	1
 | 
					#define TIC_BUILD_WITH_MOON 	1
 | 
				
			||||||
#define TIC_BUILD_WITH_FENNEL 	1
 | 
					#define TIC_BUILD_WITH_FENNEL 	1
 | 
				
			||||||
@@ -29,6 +35,8 @@
 | 
				
			|||||||
#define TIC_BUILD_WITH_WREN 	1
 | 
					#define TIC_BUILD_WITH_WREN 	1
 | 
				
			||||||
#define TIC_BUILD_WITH_SQUIRREL 1
 | 
					#define TIC_BUILD_WITH_SQUIRREL 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if defined(__APPLE__)
 | 
					#if defined(__APPLE__)
 | 
				
			||||||
// TODO: this disables macos config 
 | 
					// TODO: this disables macos config 
 | 
				
			||||||
#	include "AvailabilityMacros.h"
 | 
					#	include "AvailabilityMacros.h"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -22,9 +22,9 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include "file_dialog.h"
 | 
					#include "file_dialog.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <SDL.h>
 | 
					#include <tic80_config.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if defined(__WINDOWS__)
 | 
					#if defined(__TIC_WINDOWS__)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <windows.h>
 | 
					#include <windows.h>
 | 
				
			||||||
#include <commdlg.h>
 | 
					#include <commdlg.h>
 | 
				
			||||||
@@ -36,7 +36,7 @@ wchar_t* wcscpy(wchar_t *, const wchar_t *);
 | 
				
			|||||||
void file_dialog_load(file_dialog_load_callback callback, void* data)
 | 
					void file_dialog_load(file_dialog_load_callback callback, void* data)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	OPENFILENAMEW ofn;
 | 
						OPENFILENAMEW ofn;
 | 
				
			||||||
	SDL_zero(ofn);
 | 
						memset(&ofn, 0, sizeof ofn);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	wchar_t filename[MAX_PATH];
 | 
						wchar_t filename[MAX_PATH];
 | 
				
			||||||
	memset(filename, 0, sizeof(filename));
 | 
						memset(filename, 0, sizeof(filename));
 | 
				
			||||||
@@ -83,7 +83,7 @@ void file_dialog_load(file_dialog_load_callback callback, void* data)
 | 
				
			|||||||
void file_dialog_save(file_dialog_save_callback callback, const char* name, const u8* buffer, size_t size, void* data, u32 mode)
 | 
					void file_dialog_save(file_dialog_save_callback callback, const char* name, const u8* buffer, size_t size, void* data, u32 mode)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	OPENFILENAMEW ofn;
 | 
						OPENFILENAMEW ofn;
 | 
				
			||||||
	SDL_zero(ofn);
 | 
						memset(&ofn, 0, sizeof ofn);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	wchar_t filename[MAX_PATH];
 | 
						wchar_t filename[MAX_PATH];
 | 
				
			||||||
	mbstowcs(filename, name, MAX_PATH);
 | 
						mbstowcs(filename, name, MAX_PATH);
 | 
				
			||||||
@@ -102,7 +102,7 @@ void file_dialog_save(file_dialog_save_callback callback, const char* name, cons
 | 
				
			|||||||
			fwrite(buffer, 1, size, file);
 | 
								fwrite(buffer, 1, size, file);
 | 
				
			||||||
			fclose(file);
 | 
								fclose(file);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if !defined(__WINDOWS__)
 | 
					#if !defined(__TIC_WINDOWS__)
 | 
				
			||||||
			chmod(filename, mode);
 | 
								chmod(filename, mode);
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
			callback(true, data);
 | 
								callback(true, data);
 | 
				
			||||||
@@ -157,7 +157,7 @@ void file_dialog_save(file_dialog_save_callback callback, const char* name, cons
 | 
				
			|||||||
	callback(true, data);
 | 
						callback(true, data);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#elif defined(__LINUX__)
 | 
					#elif defined(__TIC_LINUX__)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <stdlib.h>
 | 
					#include <stdlib.h>
 | 
				
			||||||
#include <string.h>
 | 
					#include <string.h>
 | 
				
			||||||
@@ -267,7 +267,7 @@ void file_dialog_save(file_dialog_save_callback callback, const char* name, cons
 | 
				
			|||||||
		callback(false, data);
 | 
							callback(false, data);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#elif defined(__MACOSX__)
 | 
					#elif defined(__TIC_MACOSX__)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <string.h>
 | 
					#include <string.h>
 | 
				
			||||||
#include <stdio.h>
 | 
					#include <stdio.h>
 | 
				
			||||||
@@ -345,7 +345,7 @@ void file_dialog_save(file_dialog_save_callback callback, const char* name, cons
 | 
				
			|||||||
		callback(false, data);
 | 
							callback(false, data);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#elif defined(__ANDROID__)
 | 
					#elif defined(__TIC_ANDROID__)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <jni.h>
 | 
					#include <jni.h>
 | 
				
			||||||
#include <sys/stat.h>
 | 
					#include <sys/stat.h>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,6 +3,9 @@
 | 
				
			|||||||
#include "ticapi.h"
 | 
					#include "ticapi.h"
 | 
				
			||||||
#include "ext/file_dialog.h"
 | 
					#include "ext/file_dialog.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define TIC80_OFFSET_LEFT ((TIC80_FULLWIDTH-TIC80_WIDTH)/2)
 | 
				
			||||||
 | 
					#define TIC80_OFFSET_TOP ((TIC80_FULLHEIGHT-TIC80_HEIGHT)/2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct
 | 
					typedef struct
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	void	(*setClipboardText)(const char* text);
 | 
						void	(*setClipboardText)(const char* text);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,683 +0,0 @@
 | 
				
			|||||||
#include "../system.h"
 | 
					 | 
				
			||||||
#include "../net.h"
 | 
					 | 
				
			||||||
#include "../tools.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <stdlib.h>
 | 
					 | 
				
			||||||
#include <stdio.h>
 | 
					 | 
				
			||||||
#include <time.h>
 | 
					 | 
				
			||||||
#include <SDL.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define STUDIO_UI_SCALE 2
 | 
					 | 
				
			||||||
#define STUDIO_PIXEL_FORMAT SDL_PIXELFORMAT_ABGR8888
 | 
					 | 
				
			||||||
#define TEXTURE_SIZE (TIC80_FULLWIDTH)
 | 
					 | 
				
			||||||
#define OFFSET_LEFT ((TIC80_FULLWIDTH-TIC80_WIDTH)/2)
 | 
					 | 
				
			||||||
#define OFFSET_TOP ((TIC80_FULLHEIGHT-TIC80_HEIGHT)/2)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static struct
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	Studio* studio;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	SDL_Window* window;
 | 
					 | 
				
			||||||
	SDL_Renderer* renderer;
 | 
					 | 
				
			||||||
	SDL_Texture* texture;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	struct
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		SDL_Joystick* ports[TIC_GAMEPADS];
 | 
					 | 
				
			||||||
		tic80_gamepads joystick;
 | 
					 | 
				
			||||||
	} gamepad;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	struct
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		SDL_Texture* texture;
 | 
					 | 
				
			||||||
		const u8* src;
 | 
					 | 
				
			||||||
	} mouse;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	Net* net;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	struct
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		SDL_AudioSpec 		spec;
 | 
					 | 
				
			||||||
		SDL_AudioDeviceID 	device;
 | 
					 | 
				
			||||||
		SDL_AudioCVT 		cvt;
 | 
					 | 
				
			||||||
	} audio;
 | 
					 | 
				
			||||||
} platform;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void initSound()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	SDL_AudioSpec want =
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		.freq = 44100,
 | 
					 | 
				
			||||||
		.format = AUDIO_S16,
 | 
					 | 
				
			||||||
		.channels = 1,
 | 
					 | 
				
			||||||
		.userdata = NULL,
 | 
					 | 
				
			||||||
	};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	platform.audio.device = SDL_OpenAudioDevice(NULL, 0, &want, &platform.audio.spec, SDL_AUDIO_ALLOW_ANY_CHANGE);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	SDL_BuildAudioCVT(&platform.audio.cvt, want.format, want.channels, platform.audio.spec.freq, platform.audio.spec.format, platform.audio.spec.channels, platform.audio.spec.freq);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if(platform.audio.cvt.needed)
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		platform.audio.cvt.len = platform.audio.spec.freq * sizeof(s16) / TIC_FRAMERATE;
 | 
					 | 
				
			||||||
		platform.audio.cvt.buf = SDL_malloc(platform.audio.cvt.len * platform.audio.cvt.len_mult);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static u8* getSpritePtr(tic_tile* tiles, s32 x, s32 y)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	enum { SheetCols = (TIC_SPRITESHEET_SIZE / TIC_SPRITESIZE) };
 | 
					 | 
				
			||||||
	return tiles[x / TIC_SPRITESIZE + y / TIC_SPRITESIZE * SheetCols].data;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static u8 getSpritePixel(tic_tile* tiles, s32 x, s32 y)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	return tic_tool_peek4(getSpritePtr(tiles, x, y), (x % TIC_SPRITESIZE) + (y % TIC_SPRITESIZE) * TIC_SPRITESIZE);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void calcTextureRect(SDL_Rect* rect)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	SDL_GetWindowSize(platform.window, &rect->w, &rect->h);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		enum{Width = TIC80_WIDTH, Height = TIC80_HEIGHT};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		s32 discreteHeight = rect->h - rect->h % Height;
 | 
					 | 
				
			||||||
		s32 discreteWidth = Width * discreteHeight / Height;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		rect->x = (rect->w - discreteWidth) / 2;
 | 
					 | 
				
			||||||
		rect->y = (rect->h - discreteHeight) / 2;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		rect->w = discreteWidth;
 | 
					 | 
				
			||||||
		rect->h = discreteHeight;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void processMouse()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	s32 mx = 0, my = 0;
 | 
					 | 
				
			||||||
	s32 mb = SDL_GetMouseState(&mx, &my);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	tic80_input* input = &platform.studio->tic->ram.input;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		input->mouse.x = input->mouse.y = 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		SDL_Rect rect = {0, 0, 0, 0};
 | 
					 | 
				
			||||||
		calcTextureRect(&rect);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if(rect.w) input->mouse.x = (mx - rect.x) * TIC80_WIDTH / rect.w;
 | 
					 | 
				
			||||||
		if(rect.h) input->mouse.y = (my - rect.y) * TIC80_HEIGHT / rect.h;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		input->mouse.left = mb & SDL_BUTTON_LMASK ? 1 : 0;
 | 
					 | 
				
			||||||
		input->mouse.middle = mb & SDL_BUTTON_MMASK ? 1 : 0;
 | 
					 | 
				
			||||||
		input->mouse.right = mb & SDL_BUTTON_RMASK ? 1 : 0;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void processKeyboard()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	static const u8 KeyboardCodes[] = 
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		#include "../keycodes.c"
 | 
					 | 
				
			||||||
	};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	tic80_input* input = &platform.studio->tic->ram.input;
 | 
					 | 
				
			||||||
	input->keyboard.data = 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	const u8* keyboard = SDL_GetKeyboardState(NULL);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	for(s32 i = 0, c = 0; i < COUNT_OF(KeyboardCodes) && c < COUNT_OF(input->keyboard.keys); i++)
 | 
					 | 
				
			||||||
		if(keyboard[i] && KeyboardCodes[i] > tic_key_unknown)
 | 
					 | 
				
			||||||
			input->keyboard.keys[c++] = KeyboardCodes[i];
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static s32 getAxisMask(SDL_Joystick* joystick)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	s32 mask = 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	s32 axesCount = SDL_JoystickNumAxes(joystick);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	for (s32 a = 0; a < axesCount; a++)
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		s32 axe = SDL_JoystickGetAxis(joystick, a);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if (axe)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			if (a == 0)
 | 
					 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
				if (axe > 16384) mask |= SDL_HAT_RIGHT;
 | 
					 | 
				
			||||||
				else if(axe < -16384) mask |= SDL_HAT_LEFT;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			else if (a == 1)
 | 
					 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
				if (axe > 16384) mask |= SDL_HAT_DOWN;
 | 
					 | 
				
			||||||
				else if (axe < -16384) mask |= SDL_HAT_UP;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return mask;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static s32 getJoystickHatMask(s32 hat)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	tic80_gamepads gamepad;
 | 
					 | 
				
			||||||
	gamepad.data = 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	gamepad.first.up = hat & SDL_HAT_UP;
 | 
					 | 
				
			||||||
	gamepad.first.down = hat & SDL_HAT_DOWN;
 | 
					 | 
				
			||||||
	gamepad.first.left = hat & SDL_HAT_LEFT;
 | 
					 | 
				
			||||||
	gamepad.first.right = hat & SDL_HAT_RIGHT;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return gamepad.data;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void processJoysticks()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	platform.gamepad.joystick.data = 0;
 | 
					 | 
				
			||||||
	s32 index = 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	for(s32 i = 0; i < COUNT_OF(platform.gamepad.ports); i++)
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		SDL_Joystick* joystick = platform.gamepad.ports[i];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if(joystick && SDL_JoystickGetAttached(joystick))
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			tic80_gamepad* gamepad = NULL;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			switch(index)
 | 
					 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
			case 0: gamepad = &platform.gamepad.joystick.first; break;
 | 
					 | 
				
			||||||
			case 1: gamepad = &platform.gamepad.joystick.second; break;
 | 
					 | 
				
			||||||
			case 2: gamepad = &platform.gamepad.joystick.third; break;
 | 
					 | 
				
			||||||
			case 3: gamepad = &platform.gamepad.joystick.fourth; break;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			if(gamepad)
 | 
					 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
				gamepad->data |= getJoystickHatMask(getAxisMask(joystick));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				for (s32 h = 0; h < SDL_JoystickNumHats(joystick); h++)
 | 
					 | 
				
			||||||
					gamepad->data |= getJoystickHatMask(SDL_JoystickGetHat(joystick, h));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				s32 numButtons = SDL_JoystickNumButtons(joystick);
 | 
					 | 
				
			||||||
				if(numButtons >= 2)
 | 
					 | 
				
			||||||
				{
 | 
					 | 
				
			||||||
					gamepad->a = SDL_JoystickGetButton(joystick, 0);
 | 
					 | 
				
			||||||
					gamepad->b = SDL_JoystickGetButton(joystick, 1);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
					if(numButtons >= 4)
 | 
					 | 
				
			||||||
					{
 | 
					 | 
				
			||||||
						gamepad->x = SDL_JoystickGetButton(joystick, 2);
 | 
					 | 
				
			||||||
						gamepad->y = SDL_JoystickGetButton(joystick, 3);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
						for(s32 i = 5; i < numButtons; i++)
 | 
					 | 
				
			||||||
						{
 | 
					 | 
				
			||||||
							s32 back = SDL_JoystickGetButton(joystick, i);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
							if(back)
 | 
					 | 
				
			||||||
							{
 | 
					 | 
				
			||||||
								tic_mem* tic = platform.studio->tic;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
								for(s32 i = 0; i < TIC80_KEY_BUFFER; i++)
 | 
					 | 
				
			||||||
								{
 | 
					 | 
				
			||||||
									if(!tic->ram.input.keyboard.keys[i])
 | 
					 | 
				
			||||||
									{
 | 
					 | 
				
			||||||
										tic->ram.input.keyboard.keys[i] = tic_key_escape;
 | 
					 | 
				
			||||||
										break;
 | 
					 | 
				
			||||||
									}
 | 
					 | 
				
			||||||
								}
 | 
					 | 
				
			||||||
							}
 | 
					 | 
				
			||||||
						}
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				index++;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void processGamepad()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	processJoysticks();
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		platform.studio->tic->ram.input.gamepads.data = 0;
 | 
					 | 
				
			||||||
		platform.studio->tic->ram.input.gamepads.data |= platform.gamepad.joystick.data;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void pollEvent()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	tic80_input* input = &platform.studio->tic->ram.input;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		input->mouse.btns = 0;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	SDL_Event event;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	while(SDL_PollEvent(&event))
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		switch(event.type)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		case SDL_MOUSEWHEEL:
 | 
					 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
				input->mouse.scrollx = event.wheel.x;
 | 
					 | 
				
			||||||
				input->mouse.scrolly = event.wheel.y;				
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
		case SDL_JOYDEVICEADDED:
 | 
					 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
				s32 id = event.jdevice.which;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				if (id < TIC_GAMEPADS)
 | 
					 | 
				
			||||||
				{
 | 
					 | 
				
			||||||
					if(platform.gamepad.ports[id])
 | 
					 | 
				
			||||||
						SDL_JoystickClose(platform.gamepad.ports[id]);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
					platform.gamepad.ports[id] = SDL_JoystickOpen(id);
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		case SDL_JOYDEVICEREMOVED:
 | 
					 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
				s32 id = event.jdevice.which;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				if (id < TIC_GAMEPADS && platform.gamepad.ports[id])
 | 
					 | 
				
			||||||
				{
 | 
					 | 
				
			||||||
					SDL_JoystickClose(platform.gamepad.ports[id]);
 | 
					 | 
				
			||||||
					platform.gamepad.ports[id] = NULL;
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
		case SDL_WINDOWEVENT:
 | 
					 | 
				
			||||||
			switch(event.window.event)
 | 
					 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
			case SDL_WINDOWEVENT_FOCUS_GAINED: platform.studio->updateProject(); break;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
		case SDL_QUIT:
 | 
					 | 
				
			||||||
			platform.studio->exit();
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
		default:
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	processMouse();
 | 
					 | 
				
			||||||
	processKeyboard();
 | 
					 | 
				
			||||||
	processGamepad();
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void blitTexture()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	tic_mem* tic = platform.studio->tic;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	SDL_Rect rect = {0, 0, 0, 0};
 | 
					 | 
				
			||||||
	calcTextureRect(&rect);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	void* pixels = NULL;
 | 
					 | 
				
			||||||
	s32 pitch = 0;
 | 
					 | 
				
			||||||
	SDL_LockTexture(platform.texture, NULL, &pixels, &pitch);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	platform.studio->tick();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	memcpy(pixels, tic->screen, sizeof tic->screen);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	SDL_UnlockTexture(platform.texture);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		enum {Top = OFFSET_TOP};
 | 
					 | 
				
			||||||
		enum {Left = OFFSET_LEFT};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		SDL_Rect srcRect = {Left, Top, TIC80_WIDTH, TIC80_HEIGHT};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		SDL_RenderCopy(platform.renderer, platform.texture, &srcRect, &rect);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void blitSound()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	tic_mem* tic = platform.studio->tic;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	SDL_PauseAudioDevice(platform.audio.device, 0);
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
	if(platform.audio.cvt.needed)
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		SDL_memcpy(platform.audio.cvt.buf, tic->samples.buffer, tic->samples.size);
 | 
					 | 
				
			||||||
		SDL_ConvertAudio(&platform.audio.cvt);
 | 
					 | 
				
			||||||
		SDL_QueueAudio(platform.audio.device, platform.audio.cvt.buf, platform.audio.cvt.len_cvt);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	else SDL_QueueAudio(platform.audio.device, tic->samples.buffer, tic->samples.size);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void blitCursor(const u8* in)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	if(!platform.mouse.texture)
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		platform.mouse.texture = SDL_CreateTexture(platform.renderer, STUDIO_PIXEL_FORMAT, SDL_TEXTUREACCESS_STREAMING, TIC_SPRITESIZE, TIC_SPRITESIZE);
 | 
					 | 
				
			||||||
		SDL_SetTextureBlendMode(platform.mouse.texture, SDL_BLENDMODE_BLEND);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if(platform.mouse.src != in)
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		platform.mouse.src = in;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		void* pixels = NULL;
 | 
					 | 
				
			||||||
		s32 pitch = 0;
 | 
					 | 
				
			||||||
		SDL_LockTexture(platform.mouse.texture, NULL, &pixels, &pitch);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			const u8* end = in + sizeof(tic_tile);
 | 
					 | 
				
			||||||
			const u32* pal = tic_palette_blit(&platform.studio->tic->ram.vram.palette);
 | 
					 | 
				
			||||||
			u32* out = pixels;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			while(in != end)
 | 
					 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
				u8 low = *in & 0x0f;
 | 
					 | 
				
			||||||
				u8 hi = (*in & 0xf0) >> TIC_PALETTE_BPP;
 | 
					 | 
				
			||||||
				*out++ = low ? (*(pal + low) | 0xff000000) : 0;
 | 
					 | 
				
			||||||
				*out++ = hi ? (*(pal + hi) | 0xff000000) : 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				in++;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		SDL_UnlockTexture(platform.mouse.texture);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	SDL_Rect rect = {0, 0, 0, 0};
 | 
					 | 
				
			||||||
	calcTextureRect(&rect);
 | 
					 | 
				
			||||||
	s32 scale = rect.w / TIC80_WIDTH;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	SDL_Rect src = {0, 0, TIC_SPRITESIZE, TIC_SPRITESIZE};
 | 
					 | 
				
			||||||
	SDL_Rect dst = {0, 0, TIC_SPRITESIZE * scale, TIC_SPRITESIZE * scale};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	SDL_GetMouseState(&dst.x, &dst.y);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if(platform.studio->config()->theme.cursor.pixelPerfect)
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		dst.x -= (dst.x - rect.x) % scale;
 | 
					 | 
				
			||||||
		dst.y -= (dst.y - rect.y) % scale;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if(SDL_GetWindowFlags(platform.window) & SDL_WINDOW_MOUSE_FOCUS)
 | 
					 | 
				
			||||||
		SDL_RenderCopy(platform.renderer, platform.mouse.texture, &src, &dst);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void renderCursor()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	if(platform.studio->tic->ram.vram.vars.cursor.system)
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		switch(platform.studio->tic->ram.vram.vars.cursor.sprite)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		case tic_cursor_hand: 
 | 
					 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
				if(platform.studio->config()->theme.cursor.hand >= 0)
 | 
					 | 
				
			||||||
				{
 | 
					 | 
				
			||||||
					SDL_ShowCursor(SDL_DISABLE);
 | 
					 | 
				
			||||||
					blitCursor(platform.studio->config()->cart->bank0.tiles.data[platform.studio->config()->theme.cursor.hand].data);
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				else
 | 
					 | 
				
			||||||
				{
 | 
					 | 
				
			||||||
					SDL_ShowCursor(SDL_ENABLE);
 | 
					 | 
				
			||||||
					SDL_SetCursor(SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_HAND));
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
		case tic_cursor_ibeam:
 | 
					 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
				if(platform.studio->config()->theme.cursor.ibeam >= 0)
 | 
					 | 
				
			||||||
				{
 | 
					 | 
				
			||||||
					SDL_ShowCursor(SDL_DISABLE);
 | 
					 | 
				
			||||||
					blitCursor(platform.studio->config()->cart->bank0.tiles.data[platform.studio->config()->theme.cursor.ibeam].data);
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				else
 | 
					 | 
				
			||||||
				{
 | 
					 | 
				
			||||||
					SDL_ShowCursor(SDL_ENABLE);
 | 
					 | 
				
			||||||
					SDL_SetCursor(SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_IBEAM));
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
		default:
 | 
					 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
				if(platform.studio->config()->theme.cursor.arrow >= 0)
 | 
					 | 
				
			||||||
				{
 | 
					 | 
				
			||||||
					SDL_ShowCursor(SDL_DISABLE);
 | 
					 | 
				
			||||||
					blitCursor(platform.studio->config()->cart->bank0.tiles.data[platform.studio->config()->theme.cursor.arrow].data);
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				else
 | 
					 | 
				
			||||||
				{
 | 
					 | 
				
			||||||
					SDL_ShowCursor(SDL_ENABLE);
 | 
					 | 
				
			||||||
					SDL_SetCursor(SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_ARROW));
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	else
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		SDL_ShowCursor(SDL_DISABLE);
 | 
					 | 
				
			||||||
		blitCursor(platform.studio->tic->ram.sprites.data[platform.studio->tic->ram.vram.vars.cursor.sprite].data);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// 	if(platform.mode == TIC_RUN_MODE && !platform.studio.tic->input.mouse)
 | 
					 | 
				
			||||||
// 	{
 | 
					 | 
				
			||||||
// 		SDL_ShowCursor(SDL_DISABLE);
 | 
					 | 
				
			||||||
// 		return;
 | 
					 | 
				
			||||||
// 	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void tick()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	pollEvent();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if(platform.studio->quit)
 | 
					 | 
				
			||||||
		return;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	SDL_RenderClear(platform.renderer);
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
	blitTexture();
 | 
					 | 
				
			||||||
	renderCursor();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	SDL_RenderPresent(platform.renderer);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	blitSound();
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static const char* getAppFolder()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	static char appFolder[FILENAME_MAX];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	char* path = SDL_GetPrefPath(TIC_PACKAGE, TIC_NAME);
 | 
					 | 
				
			||||||
	strcpy(appFolder, path);
 | 
					 | 
				
			||||||
	SDL_free(path);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return appFolder;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void setClipboardText(const char* text)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	SDL_SetClipboardText(text);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static bool hasClipboardText()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	return SDL_HasClipboardText();
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static char* getClipboardText()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	return SDL_GetClipboardText();
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void freeClipboardText(const char* text)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	SDL_free((void*)text);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static u64 getPerformanceCounter()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	return SDL_GetPerformanceCounter();
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static u64 getPerformanceFrequency()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	return SDL_GetPerformanceFrequency();
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void goFullscreen()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	SDL_SetWindowFullscreen(platform.window, SDL_GetWindowFlags(platform.window) & SDL_WINDOW_FULLSCREEN_DESKTOP ? 0 : SDL_WINDOW_FULLSCREEN_DESKTOP);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void showMessageBox(const char* title, const char* message)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_WARNING, title, message, NULL);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void setWindowTitle(const char* title)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	SDL_SetWindowTitle(platform.window, title);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#if defined(__WINDOWS__) || defined(__LINUX__) || defined(__MACOSX__)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void openSystemPath(const char* path)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	char command[FILENAME_MAX];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#if defined(__WINDOWS__)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	sprintf(command, "explorer \"%s\"", path);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	wchar_t wcommand[FILENAME_MAX];
 | 
					 | 
				
			||||||
	mbstowcs(wcommand, command, FILENAME_MAX);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	_wsystem(wcommand);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#elif defined(__LINUX__)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	sprintf(command, "xdg-open \"%s\"", path);
 | 
					 | 
				
			||||||
	system(command);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#elif defined(__MACOSX__)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	sprintf(command, "open \"%s\"", path);
 | 
					 | 
				
			||||||
	system(command);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#else
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void openSystemPath(const char* path) {}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void* getUrlRequest(const char* url, s32* size)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	return netGetRequest(platform.net, url, size);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void preseed()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
#if defined(__MACOSX__)
 | 
					 | 
				
			||||||
	srandom(time(NULL));
 | 
					 | 
				
			||||||
	random();
 | 
					 | 
				
			||||||
#else
 | 
					 | 
				
			||||||
	srand(time(NULL));
 | 
					 | 
				
			||||||
	rand();
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void updateConfig() {}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static System systemInterface = 
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	.setClipboardText = setClipboardText,
 | 
					 | 
				
			||||||
	.hasClipboardText = hasClipboardText,
 | 
					 | 
				
			||||||
	.getClipboardText = getClipboardText,
 | 
					 | 
				
			||||||
	.freeClipboardText = freeClipboardText,
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
	.getPerformanceCounter = getPerformanceCounter,
 | 
					 | 
				
			||||||
	.getPerformanceFrequency = getPerformanceFrequency,
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	.getUrlRequest = getUrlRequest,
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	.fileDialogLoad = file_dialog_load,
 | 
					 | 
				
			||||||
	.fileDialogSave = file_dialog_save,
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	.goFullscreen = goFullscreen,
 | 
					 | 
				
			||||||
	.showMessageBox = showMessageBox,
 | 
					 | 
				
			||||||
	.setWindowTitle = setWindowTitle,
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	.openSystemPath = openSystemPath,
 | 
					 | 
				
			||||||
	.preseed = preseed,
 | 
					 | 
				
			||||||
	.poll = pollEvent,
 | 
					 | 
				
			||||||
	.updateConfig = updateConfig,
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
s32 main(s32 argc, char **argv)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	const char* folder = getAppFolder();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_JOYSTICK);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	initSound();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	platform.net = createNet();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	platform.window = SDL_CreateWindow( TIC_TITLE, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
 | 
					 | 
				
			||||||
		(TIC80_FULLWIDTH) * STUDIO_UI_SCALE,
 | 
					 | 
				
			||||||
		(TIC80_FULLHEIGHT) * STUDIO_UI_SCALE,
 | 
					 | 
				
			||||||
		SDL_WINDOW_SHOWN | SDL_WINDOW_FULLSCREEN_DESKTOP);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	platform.studio = studioInit(argc, argv, platform.audio.spec.freq, folder, &systemInterface);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	platform.renderer = SDL_CreateRenderer(platform.window, -1, SDL_RENDERER_SOFTWARE);
 | 
					 | 
				
			||||||
	platform.texture = SDL_CreateTexture(platform.renderer, STUDIO_PIXEL_FORMAT, SDL_TEXTUREACCESS_STREAMING, TEXTURE_SIZE, TEXTURE_SIZE);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		u64 nextTick = SDL_GetPerformanceCounter();
 | 
					 | 
				
			||||||
		const u64 Delta = SDL_GetPerformanceFrequency() / TIC_FRAMERATE;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		while (!platform.studio->quit)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			nextTick += Delta;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			tick();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
				s64 delay = nextTick - SDL_GetPerformanceCounter();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				if(delay < 0) nextTick -= delay;
 | 
					 | 
				
			||||||
				else SDL_Delay((u32)(delay * 1000 / SDL_GetPerformanceFrequency()));
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	platform.studio->close();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	closeNet(platform.net);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if(platform.audio.cvt.buf)
 | 
					 | 
				
			||||||
		SDL_free(platform.audio.cvt.buf);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if(platform.mouse.texture)
 | 
					 | 
				
			||||||
		SDL_DestroyTexture(platform.mouse.texture);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	SDL_DestroyTexture(platform.texture);
 | 
					 | 
				
			||||||
	SDL_DestroyRenderer(platform.renderer);
 | 
					 | 
				
			||||||
	SDL_DestroyWindow(platform.window);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	SDL_CloseAudioDevice(platform.audio.device);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,3 +1,25 @@
 | 
				
			|||||||
 | 
					// MIT License
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Copyright (c) 2017 Vadim Grigoruk @nesbox // grigoruk@gmail.com
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
				
			||||||
 | 
					// of this software and associated documentation files (the "Software"), to deal
 | 
				
			||||||
 | 
					// in the Software without restriction, including without limitation the rights
 | 
				
			||||||
 | 
					// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
				
			||||||
 | 
					// copies of the Software, and to permit persons to whom the Software is
 | 
				
			||||||
 | 
					// furnished to do so, subject to the following conditions:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// The above copyright notice and this permission notice shall be included in all
 | 
				
			||||||
 | 
					// copies or substantial portions of the Software.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
				
			||||||
 | 
					// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
				
			||||||
 | 
					// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | 
				
			||||||
 | 
					// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
				
			||||||
 | 
					// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
				
			||||||
 | 
					// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 | 
				
			||||||
 | 
					// SOFTWARE.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "system.h"
 | 
					#include "system.h"
 | 
				
			||||||
#include "net.h"
 | 
					#include "net.h"
 | 
				
			||||||
#include "tools.h"
 | 
					#include "tools.h"
 | 
				
			||||||
@@ -14,8 +36,6 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#define STUDIO_PIXEL_FORMAT GPU_FORMAT_RGBA
 | 
					#define STUDIO_PIXEL_FORMAT GPU_FORMAT_RGBA
 | 
				
			||||||
#define TEXTURE_SIZE (TIC80_FULLWIDTH)
 | 
					#define TEXTURE_SIZE (TIC80_FULLWIDTH)
 | 
				
			||||||
#define OFFSET_LEFT ((TIC80_FULLWIDTH-TIC80_WIDTH)/2)
 | 
					 | 
				
			||||||
#define OFFSET_TOP ((TIC80_FULLHEIGHT-TIC80_HEIGHT)/2)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define KBD_COLS 22
 | 
					#define KBD_COLS 22
 | 
				
			||||||
#define KBD_ROWS 17
 | 
					#define KBD_ROWS 17
 | 
				
			||||||
@@ -345,7 +365,7 @@ static void calcTextureRect(SDL_Rect* rect)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
			rect->y = rect->w > rect->h 
 | 
								rect->y = rect->w > rect->h 
 | 
				
			||||||
				? (rect->h - discreteHeight) / 2 
 | 
									? (rect->h - discreteHeight) / 2 
 | 
				
			||||||
				: OFFSET_TOP*discreteWidth/Width;
 | 
									: TIC80_OFFSET_TOP*discreteWidth/Width;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			rect->w = discreteWidth;
 | 
								rect->w = discreteWidth;
 | 
				
			||||||
			rect->h = discreteHeight;
 | 
								rect->h = discreteHeight;
 | 
				
			||||||
@@ -381,8 +401,8 @@ static void processMouse()
 | 
				
			|||||||
		s32 x = -1, y = -1;
 | 
							s32 x = -1, y = -1;
 | 
				
			||||||
		if(crtMonitorEnabled())
 | 
							if(crtMonitorEnabled())
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			if(rect.w) x = (mx - rect.x) * TIC80_FULLWIDTH / rect.w - OFFSET_LEFT;
 | 
								if(rect.w) x = (mx - rect.x) * TIC80_FULLWIDTH / rect.w - TIC80_OFFSET_LEFT;
 | 
				
			||||||
			if(rect.h) y = (my - rect.y) * TIC80_FULLHEIGHT / rect.h - OFFSET_TOP;
 | 
								if(rect.h) y = (my - rect.y) * TIC80_FULLHEIGHT / rect.h - TIC80_OFFSET_TOP;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		else
 | 
							else
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
@@ -833,7 +853,7 @@ static void blitGpuTexture(GPU_Target* screen, GPU_Image* texture)
 | 
				
			|||||||
	SDL_Rect rect = {0, 0, 0, 0};
 | 
						SDL_Rect rect = {0, 0, 0, 0};
 | 
				
			||||||
	calcTextureRect(&rect);
 | 
						calcTextureRect(&rect);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	enum {Header = OFFSET_TOP, Top = OFFSET_TOP, Left = OFFSET_LEFT};
 | 
						enum {Header = TIC80_OFFSET_TOP, Top = TIC80_OFFSET_TOP, Left = TIC80_OFFSET_LEFT};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	s32 width = 0;
 | 
						s32 width = 0;
 | 
				
			||||||
	SDL_GetWindowSize(platform.window, &width, NULL);
 | 
						SDL_GetWindowSize(platform.window, &width, NULL);
 | 
				
			||||||
@@ -887,7 +907,7 @@ static void renderKeyboard()
 | 
				
			|||||||
	SDL_Rect rect;
 | 
						SDL_Rect rect;
 | 
				
			||||||
	SDL_GetWindowSize(platform.window, &rect.w, &rect.h);
 | 
						SDL_GetWindowSize(platform.window, &rect.w, &rect.h);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	GPU_Rect src = {OFFSET_LEFT, OFFSET_TOP, KBD_COLS*TIC_SPRITESIZE, KBD_ROWS*TIC_SPRITESIZE};
 | 
						GPU_Rect src = {TIC80_OFFSET_LEFT, TIC80_OFFSET_TOP, KBD_COLS*TIC_SPRITESIZE, KBD_ROWS*TIC_SPRITESIZE};
 | 
				
			||||||
	float scale = rect.w/src.w;
 | 
						float scale = rect.w/src.w;
 | 
				
			||||||
	GPU_Rect dst = (GPU_Rect){0, rect.h - KBD_ROWS*TIC_SPRITESIZE*scale, scale, scale};
 | 
						GPU_Rect dst = (GPU_Rect){0, rect.h - KBD_ROWS*TIC_SPRITESIZE*scale, scale, scale};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -911,11 +931,11 @@ static void renderKeyboard()
 | 
				
			|||||||
			{
 | 
								{
 | 
				
			||||||
				if(key == KbdLayout[k])
 | 
									if(key == KbdLayout[k])
 | 
				
			||||||
				{
 | 
									{
 | 
				
			||||||
					GPU_Rect src = {(k % Cols)*TIC_SPRITESIZE + OFFSET_LEFT, (k / Cols)*TIC_SPRITESIZE + OFFSET_TOP, 
 | 
										GPU_Rect src = {(k % Cols)*TIC_SPRITESIZE + TIC80_OFFSET_LEFT, (k / Cols)*TIC_SPRITESIZE + TIC80_OFFSET_TOP, 
 | 
				
			||||||
						TIC_SPRITESIZE, TIC_SPRITESIZE};
 | 
											TIC_SPRITESIZE, TIC_SPRITESIZE};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
					GPU_BlitScale(platform.keyboard.texture.down, &src, platform.gpu.screen, 
 | 
										GPU_BlitScale(platform.keyboard.texture.down, &src, platform.gpu.screen, 
 | 
				
			||||||
						(src.x - OFFSET_LEFT) * dst.w, (src.y - OFFSET_TOP) * dst.h + dst.y, dst.w, dst.h);
 | 
											(src.x - TIC80_OFFSET_LEFT) * dst.w, (src.y - TIC80_OFFSET_TOP) * dst.h + dst.y, dst.w, dst.h);
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}		
 | 
							}		
 | 
				
			||||||
							
								
								
									
										421
									
								
								src/system/sokol.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										421
									
								
								src/system/sokol.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,421 @@
 | 
				
			|||||||
 | 
					// MIT License
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Copyright (c) 2017 Vadim Grigoruk @nesbox // grigoruk@gmail.com
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
				
			||||||
 | 
					// of this software and associated documentation files (the "Software"), to deal
 | 
				
			||||||
 | 
					// in the Software without restriction, including without limitation the rights
 | 
				
			||||||
 | 
					// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
				
			||||||
 | 
					// copies of the Software, and to permit persons to whom the Software is
 | 
				
			||||||
 | 
					// furnished to do so, subject to the following conditions:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// The above copyright notice and this permission notice shall be included in all
 | 
				
			||||||
 | 
					// copies or substantial portions of the Software.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
				
			||||||
 | 
					// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
				
			||||||
 | 
					// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | 
				
			||||||
 | 
					// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
				
			||||||
 | 
					// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
				
			||||||
 | 
					// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 | 
				
			||||||
 | 
					// SOFTWARE.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <stdio.h>
 | 
				
			||||||
 | 
					#include <stdlib.h>
 | 
				
			||||||
 | 
					#include <time.h>
 | 
				
			||||||
 | 
					#include <limits.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "system.h"
 | 
				
			||||||
 | 
					#include "system/sokol.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						Studio* studio;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							bool state[tic_keys_count];
 | 
				
			||||||
 | 
						} keyboard;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							saudio_desc desc;
 | 
				
			||||||
 | 
							float* samples;
 | 
				
			||||||
 | 
						} audio;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						char* clipboard;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} platform;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void setClipboardText(const char* text)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if(platform.clipboard)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							free(platform.clipboard);
 | 
				
			||||||
 | 
							platform.clipboard = NULL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						platform.clipboard = strdup(text);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static bool hasClipboardText()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return platform.clipboard != NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static char* getClipboardText()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return platform.clipboard ? strdup(platform.clipboard) : NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void freeClipboardText(const char* text)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						free((void*)text);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static u64 getPerformanceCounter()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static u64 getPerformanceFrequency()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return 1000;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void* getUrlRequest(const char* url, s32* size)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void goFullscreen()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void showMessageBox(const char* title, const char* message)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void setWindowTitle(const char* title)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void openSystemPath(const char* path)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void preseed()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					#if defined(__TIC_MACOSX__)
 | 
				
			||||||
 | 
						srandom(time(NULL));
 | 
				
			||||||
 | 
						random();
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
						srand(time(NULL));
 | 
				
			||||||
 | 
						rand();
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void pollEvent()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void updateConfig()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static System systemInterface = 
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						.setClipboardText = setClipboardText,
 | 
				
			||||||
 | 
						.hasClipboardText = hasClipboardText,
 | 
				
			||||||
 | 
						.getClipboardText = getClipboardText,
 | 
				
			||||||
 | 
						.freeClipboardText = freeClipboardText,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						.getPerformanceCounter = getPerformanceCounter,
 | 
				
			||||||
 | 
						.getPerformanceFrequency = getPerformanceFrequency,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						.getUrlRequest = getUrlRequest,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						.fileDialogLoad = file_dialog_load,
 | 
				
			||||||
 | 
						.fileDialogSave = file_dialog_save,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						.goFullscreen = goFullscreen,
 | 
				
			||||||
 | 
						.showMessageBox = showMessageBox,
 | 
				
			||||||
 | 
						.setWindowTitle = setWindowTitle,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						.openSystemPath = openSystemPath,
 | 
				
			||||||
 | 
						.preseed = preseed,
 | 
				
			||||||
 | 
						.poll = pollEvent,
 | 
				
			||||||
 | 
						.updateConfig = updateConfig,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void app_init(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						sokol_gfx_init(TIC80_FULLWIDTH, TIC80_FULLHEIGHT, 1, 1, false, true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						platform.audio.samples = calloc(sizeof platform.audio.samples[0], saudio_sample_rate() / TIC_FRAMERATE * TIC_STEREO_CHANNLES);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void handleKeyboard()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						tic_mem* tic = platform.studio->tic;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						tic80_input* input = &tic->ram.input;
 | 
				
			||||||
 | 
						input->keyboard.data = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						enum{BufSize = COUNT_OF(input->keyboard.keys)};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for(s32 i = 0, c = 0; i < COUNT_OF(platform.keyboard.state) && c < BufSize; i++)
 | 
				
			||||||
 | 
							if(platform.keyboard.state[i])
 | 
				
			||||||
 | 
								input->keyboard.keys[c++] = i;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void app_frame(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						tic_mem* tic = platform.studio->tic;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if(platform.studio->quit) exit(0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						tic80_input* input = &tic->ram.input;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						input->gamepads.data = 0;
 | 
				
			||||||
 | 
						handleKeyboard();
 | 
				
			||||||
 | 
						platform.studio->tick();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sokol_gfx_draw(platform.studio->tic->screen);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						s32 count = tic->samples.size / sizeof tic->samples.buffer[0];
 | 
				
			||||||
 | 
						for(s32 i = 0; i < count; i++)
 | 
				
			||||||
 | 
							platform.audio.samples[i] = (float)tic->samples.buffer[i] / SHRT_MAX;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						saudio_push(platform.audio.samples, count / 2);
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						input->mouse.scrollx = input->mouse.scrolly = 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void handleKeydown(sapp_keycode keycode, bool down)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						static const tic_keycode KeyboardCodes[] = 
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_INVALID] = tic_key_unknown,
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_SPACE] = tic_key_space,
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_APOSTROPHE] = tic_key_apostrophe,
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_COMMA] = tic_key_comma,
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_MINUS] = tic_key_minus,
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_PERIOD] = tic_key_period,
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_SLASH] = tic_key_slash,
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_0] = tic_key_0,
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_1] = tic_key_1,
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_2] = tic_key_2,
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_3] = tic_key_3,
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_4] = tic_key_4,
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_5] = tic_key_5,
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_6] = tic_key_6,
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_7] = tic_key_7,
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_8] = tic_key_8,
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_9] = tic_key_9,
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_SEMICOLON] = tic_key_semicolon,
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_EQUAL] = tic_key_equals,
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_A] = tic_key_a,
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_B] = tic_key_b,
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_C] = tic_key_c,
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_D] = tic_key_d,
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_E] = tic_key_e,
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_F] = tic_key_f,
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_G] = tic_key_g,
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_H] = tic_key_h,
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_I] = tic_key_i,
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_J] = tic_key_j,
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_K] = tic_key_k,
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_L] = tic_key_l,
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_M] = tic_key_m,
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_N] = tic_key_n,
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_O] = tic_key_o,
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_P] = tic_key_p,
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_Q] = tic_key_q,
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_R] = tic_key_r,
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_S] = tic_key_s,
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_T] = tic_key_t,
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_U] = tic_key_u,
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_V] = tic_key_v,
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_W] = tic_key_w,
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_X] = tic_key_x,
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_Y] = tic_key_y,
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_Z] = tic_key_z,
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_LEFT_BRACKET] = tic_key_leftbracket,
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_BACKSLASH] = tic_key_backslash,
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_RIGHT_BRACKET] = tic_key_rightbracket,
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_GRAVE_ACCENT] = tic_key_grave,
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_WORLD_1] = tic_key_unknown,
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_WORLD_2] = tic_key_unknown,
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_ESCAPE] = tic_key_escape,
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_ENTER] = tic_key_return,
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_TAB] = tic_key_tab,
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_BACKSPACE] = tic_key_backspace,
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_INSERT] = tic_key_insert,
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_DELETE] = tic_key_delete,
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_RIGHT] = tic_key_right,
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_LEFT] = tic_key_left,
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_DOWN] = tic_key_down,
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_UP] = tic_key_up,
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_PAGE_UP] = tic_key_pageup,
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_PAGE_DOWN] = tic_key_pagedown,
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_HOME] = tic_key_home,
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_END] = tic_key_end,
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_CAPS_LOCK] = tic_key_capslock,
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_SCROLL_LOCK] = tic_key_unknown,
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_NUM_LOCK] = tic_key_unknown,
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_PRINT_SCREEN] = tic_key_unknown,
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_PAUSE] = tic_key_unknown,
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_F1] = tic_key_f1,
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_F2] = tic_key_f2,
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_F3] = tic_key_f3,
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_F4] = tic_key_f4,
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_F5] = tic_key_f5,
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_F6] = tic_key_f6,
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_F7] = tic_key_f7,
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_F8] = tic_key_f8,
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_F9] = tic_key_f9,
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_F10] = tic_key_f10,
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_F11] = tic_key_f11,
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_F12] = tic_key_f12,
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_F13] = tic_key_unknown,
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_F14] = tic_key_unknown,
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_F15] = tic_key_unknown,
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_F16] = tic_key_unknown,
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_F17] = tic_key_unknown,
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_F18] = tic_key_unknown,
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_F19] = tic_key_unknown,
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_F20] = tic_key_unknown,
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_F21] = tic_key_unknown,
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_F22] = tic_key_unknown,
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_F23] = tic_key_unknown,
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_F24] = tic_key_unknown,
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_F25] = tic_key_unknown,
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_KP_0] = tic_key_0,
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_KP_1] = tic_key_1,
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_KP_2] = tic_key_2,
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_KP_3] = tic_key_3,
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_KP_4] = tic_key_4,
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_KP_5] = tic_key_5,
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_KP_6] = tic_key_6,
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_KP_7] = tic_key_7,
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_KP_8] = tic_key_8,
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_KP_9] = tic_key_9,
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_KP_DECIMAL] = tic_key_unknown,
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_KP_DIVIDE] = tic_key_unknown,
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_KP_MULTIPLY] = tic_key_unknown,
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_KP_SUBTRACT] = tic_key_unknown,
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_KP_ADD] = tic_key_unknown,
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_KP_ENTER] = tic_key_return,
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_KP_EQUAL] = tic_key_equals,
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_LEFT_SHIFT] = tic_key_shift,
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_LEFT_CONTROL] = tic_key_ctrl,
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_LEFT_ALT] = tic_key_alt,
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_LEFT_SUPER] = tic_key_unknown,
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_RIGHT_SHIFT] = tic_key_shift,
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_RIGHT_CONTROL] = tic_key_ctrl,
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_RIGHT_ALT] = tic_key_alt,
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_RIGHT_SUPER] = tic_key_unknown,
 | 
				
			||||||
 | 
							[SAPP_KEYCODE_MENU] = tic_key_unknown,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						tic_key key = KeyboardCodes[keycode];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if(key > tic_key_unknown)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							// ALT+TAB fix
 | 
				
			||||||
 | 
							if(key == tic_key_tab && platform.keyboard.state[tic_key_alt])
 | 
				
			||||||
 | 
								platform.keyboard.state[tic_key_alt] = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							platform.keyboard.state[key] = down;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void processMouse(sapp_mousebutton btn, s32 down)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						tic80_input* input = &platform.studio->tic->ram.input;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						switch(btn)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
						case SAPP_MOUSEBUTTON_LEFT: input->mouse.left = down; break;
 | 
				
			||||||
 | 
						case SAPP_MOUSEBUTTON_MIDDLE: input->mouse.middle = down; break;
 | 
				
			||||||
 | 
						case SAPP_MOUSEBUTTON_RIGHT: input->mouse.right = down; break;
 | 
				
			||||||
 | 
						default: break;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void app_input(const sapp_event* event)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						tic80_input* input = &platform.studio->tic->ram.input;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						switch(event->type)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
						case SAPP_EVENTTYPE_KEY_DOWN:
 | 
				
			||||||
 | 
							handleKeydown(event->key_code, true);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case SAPP_EVENTTYPE_KEY_UP:
 | 
				
			||||||
 | 
							handleKeydown(event->key_code, false);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case SAPP_EVENTTYPE_MOUSE_MOVE:
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								struct {s32 x, y, w, h;}rect;
 | 
				
			||||||
 | 
					    		sokol_calc_viewport(&rect.x, &rect.y, &rect.w, &rect.h);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    		s32 mx = -1, my = -1;
 | 
				
			||||||
 | 
								if(rect.w) mx = ((s32)event->mouse_x - rect.x) * TIC80_FULLWIDTH / rect.w - TIC80_OFFSET_LEFT;
 | 
				
			||||||
 | 
								if(rect.h) my = ((s32)event->mouse_y - rect.y) * TIC80_FULLHEIGHT / rect.h - TIC80_OFFSET_TOP;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								input->mouse.x = mx >= 0 && mx < 0xff ? mx : 0xff;
 | 
				
			||||||
 | 
								input->mouse.y = my >= 0 && my < 0xff ? my : 0xff;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case SAPP_EVENTTYPE_MOUSE_DOWN: 
 | 
				
			||||||
 | 
							processMouse(event->mouse_button, 1); break;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case SAPP_EVENTTYPE_MOUSE_UP:
 | 
				
			||||||
 | 
							processMouse(event->mouse_button, 0); break;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case SAPP_EVENTTYPE_MOUSE_SCROLL:
 | 
				
			||||||
 | 
							input->mouse.scrollx = event->scroll_x;
 | 
				
			||||||
 | 
							input->mouse.scrolly = event->scroll_y;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void app_cleanup(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						platform.studio->close();
 | 
				
			||||||
 | 
						free(platform.audio.samples);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sapp_desc sokol_main(s32 argc, char* argv[])
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						memset(&platform, 0, sizeof platform);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						platform.audio.desc.num_channels = TIC_STEREO_CHANNLES;
 | 
				
			||||||
 | 
						saudio_setup(&platform.audio.desc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						platform.studio = studioInit(argc, argv, saudio_sample_rate(), "./", &systemInterface);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						const s32 Width = TIC80_FULLWIDTH * platform.studio->config()->uiScale;
 | 
				
			||||||
 | 
						const s32 Height = TIC80_FULLHEIGHT * platform.studio->config()->uiScale;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return(sapp_desc)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							.init_cb = app_init,
 | 
				
			||||||
 | 
							.frame_cb = app_frame,
 | 
				
			||||||
 | 
							.event_cb = app_input,
 | 
				
			||||||
 | 
							.cleanup_cb = app_cleanup,
 | 
				
			||||||
 | 
							.width = Width,
 | 
				
			||||||
 | 
							.height = Height,
 | 
				
			||||||
 | 
							.window_title = TIC_TITLE,
 | 
				
			||||||
 | 
							.ios_keyboard_resizes_canvas = true,
 | 
				
			||||||
 | 
							.high_dpi = true,
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										34
									
								
								src/system/sokol.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								src/system/sokol.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,34 @@
 | 
				
			|||||||
 | 
					// MIT License
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Copyright (c) 2017 Vadim Grigoruk @nesbox // grigoruk@gmail.com
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
				
			||||||
 | 
					// of this software and associated documentation files (the "Software"), to deal
 | 
				
			||||||
 | 
					// in the Software without restriction, including without limitation the rights
 | 
				
			||||||
 | 
					// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
				
			||||||
 | 
					// copies of the Software, and to permit persons to whom the Software is
 | 
				
			||||||
 | 
					// furnished to do so, subject to the following conditions:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// The above copyright notice and this permission notice shall be included in all
 | 
				
			||||||
 | 
					// copies or substantial portions of the Software.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
				
			||||||
 | 
					// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
				
			||||||
 | 
					// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | 
				
			||||||
 | 
					// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
				
			||||||
 | 
					// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
				
			||||||
 | 
					// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 | 
				
			||||||
 | 
					// SOFTWARE.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "sokol_app.h"
 | 
				
			||||||
 | 
					#include "sokol_gfx.h"
 | 
				
			||||||
 | 
					#include "sokol_time.h"
 | 
				
			||||||
 | 
					#include "sokol_audio.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <stdint.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void sokol_calc_viewport(int* x, int* y, int* w, int* h);
 | 
				
			||||||
 | 
					void sokol_gfx_init(int w, int h, int sx, int sy, bool integer_scale, bool portrait_top_align);
 | 
				
			||||||
 | 
					void sokol_gfx_draw(const uint32_t* ptr);
 | 
				
			||||||
							
								
								
									
										268
									
								
								src/system/sokol_gfx.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										268
									
								
								src/system/sokol_gfx.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,268 @@
 | 
				
			|||||||
 | 
					#include "sokol.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct 
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    sg_draw_state upscale_draw_state;
 | 
				
			||||||
 | 
					    sg_pass upscale_pass;
 | 
				
			||||||
 | 
					    sg_draw_state draw_state;
 | 
				
			||||||
 | 
					    int fb_width;
 | 
				
			||||||
 | 
					    int fb_height;
 | 
				
			||||||
 | 
					    int fb_aspect_scale_x;
 | 
				
			||||||
 | 
					    int fb_aspect_scale_y;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    bool integer_scale;
 | 
				
			||||||
 | 
					    bool portrait_top_align;
 | 
				
			||||||
 | 
					} sokol_gfx;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if defined(SOKOL_GLCORE33)
 | 
				
			||||||
 | 
					static const char* gfx_vs_src =
 | 
				
			||||||
 | 
					    "#version 330\n"
 | 
				
			||||||
 | 
					    "in vec2 in_pos;\n"
 | 
				
			||||||
 | 
					    "in vec2 in_uv;\n"
 | 
				
			||||||
 | 
					    "out vec2 uv;\n"
 | 
				
			||||||
 | 
					    "void main() {\n"
 | 
				
			||||||
 | 
					    "  gl_Position = vec4(in_pos*2.0-1.0, 0.5, 1.0);\n"
 | 
				
			||||||
 | 
					    "  uv = in_uv;\n"
 | 
				
			||||||
 | 
					    "}\n";
 | 
				
			||||||
 | 
					static const char* gfx_fs_src =
 | 
				
			||||||
 | 
					    "#version 330\n"
 | 
				
			||||||
 | 
					    "uniform sampler2D tex;\n"
 | 
				
			||||||
 | 
					    "in vec2 uv;\n"
 | 
				
			||||||
 | 
					    "out vec4 frag_color;\n"
 | 
				
			||||||
 | 
					    "void main() {\n"
 | 
				
			||||||
 | 
					    "  frag_color = texture(tex, uv);\n"
 | 
				
			||||||
 | 
					    "}\n";
 | 
				
			||||||
 | 
					#elif defined(SOKOL_GLES2)
 | 
				
			||||||
 | 
					static const char* gfx_vs_src =
 | 
				
			||||||
 | 
					    "attribute vec2 in_pos;\n"
 | 
				
			||||||
 | 
					    "attribute vec2 in_uv;\n"
 | 
				
			||||||
 | 
					    "varying vec2 uv;\n"
 | 
				
			||||||
 | 
					    "void main() {\n"
 | 
				
			||||||
 | 
					    "  gl_Position = vec4(in_pos*2.0-1.0, 0.5, 1.0);\n"
 | 
				
			||||||
 | 
					    "  uv = in_uv;\n"
 | 
				
			||||||
 | 
					    "}\n";
 | 
				
			||||||
 | 
					static const char* gfx_fs_src =
 | 
				
			||||||
 | 
					    "precision mediump float;\n"
 | 
				
			||||||
 | 
					    "uniform sampler2D tex;"
 | 
				
			||||||
 | 
					    "varying vec2 uv;\n"
 | 
				
			||||||
 | 
					    "void main() {\n"
 | 
				
			||||||
 | 
					    "  gl_FragColor = texture2D(tex, uv);\n"
 | 
				
			||||||
 | 
					    "}\n";
 | 
				
			||||||
 | 
					#elif defined(SOKOL_METAL)
 | 
				
			||||||
 | 
					static const char* gfx_vs_src =
 | 
				
			||||||
 | 
					    "#include <metal_stdlib>\n"
 | 
				
			||||||
 | 
					    "using namespace metal;\n"
 | 
				
			||||||
 | 
					    "struct vs_in {\n"
 | 
				
			||||||
 | 
					    "  float2 pos [[attribute(0)]];\n"
 | 
				
			||||||
 | 
					    "  float2 uv [[attribute(1)]];\n"
 | 
				
			||||||
 | 
					    "};\n"
 | 
				
			||||||
 | 
					    "struct vs_out {\n"
 | 
				
			||||||
 | 
					    "  float4 pos [[position]];\n"
 | 
				
			||||||
 | 
					    "  float2 uv;\n"
 | 
				
			||||||
 | 
					    "};\n"
 | 
				
			||||||
 | 
					    "vertex vs_out _main(vs_in in [[stage_in]]) {\n"
 | 
				
			||||||
 | 
					    "  vs_out out;\n"
 | 
				
			||||||
 | 
					    "  out.pos = float4(in.pos*2.0-1.0, 0.5, 1.0);\n"
 | 
				
			||||||
 | 
					    "  out.uv = in.uv;\n"
 | 
				
			||||||
 | 
					    "  return out;\n"
 | 
				
			||||||
 | 
					    "}\n";
 | 
				
			||||||
 | 
					static const char* gfx_fs_src =
 | 
				
			||||||
 | 
					    "#include <metal_stdlib>\n"
 | 
				
			||||||
 | 
					    "using namespace metal;\n"
 | 
				
			||||||
 | 
					    "struct fs_in {\n"
 | 
				
			||||||
 | 
					    "  float2 uv;\n"
 | 
				
			||||||
 | 
					    "};\n"
 | 
				
			||||||
 | 
					    "fragment float4 _main(fs_in in [[stage_in]], texture2d<float> tex [[texture(0)]], sampler smp [[sampler(0)]]) {\n"
 | 
				
			||||||
 | 
					    "  return tex.sample(smp, in.uv);\n"
 | 
				
			||||||
 | 
					    "}\n";
 | 
				
			||||||
 | 
					#elif defined(SOKOL_D3D11)
 | 
				
			||||||
 | 
					static const char* gfx_vs_src =
 | 
				
			||||||
 | 
					    "struct vs_in {\n"
 | 
				
			||||||
 | 
					    "  float2 pos: POS;\n"
 | 
				
			||||||
 | 
					    "  float2 uv:  UV;\n"
 | 
				
			||||||
 | 
					    "};\n"
 | 
				
			||||||
 | 
					    "struct vs_out {\n"
 | 
				
			||||||
 | 
					    "  float2 uv: TEXCOORD0;\n"
 | 
				
			||||||
 | 
					    "  float4 pos: SV_Position;\n"
 | 
				
			||||||
 | 
					    "};\n"
 | 
				
			||||||
 | 
					    "vs_out main(vs_in inp) {\n"
 | 
				
			||||||
 | 
					    "  vs_out outp;\n"
 | 
				
			||||||
 | 
					    "  outp.pos = float4(inp.pos*2.0-1.0, 0.5, 1.0);\n"
 | 
				
			||||||
 | 
					    "  outp.uv = inp.uv;\n"
 | 
				
			||||||
 | 
					    "  return outp;\n"
 | 
				
			||||||
 | 
					    "}\n";
 | 
				
			||||||
 | 
					static const char* gfx_fs_src =
 | 
				
			||||||
 | 
					    "Texture2D<float4> tex: register(t0);\n"
 | 
				
			||||||
 | 
					    "sampler smp: register(s0);\n"
 | 
				
			||||||
 | 
					    "float4 main(float2 uv: TEXCOORD0): SV_Target0 {\n"
 | 
				
			||||||
 | 
					    "  return tex.Sample(smp, uv);\n"
 | 
				
			||||||
 | 
					    "}\n";
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void sokol_gfx_init(int w, int h, int sx, int sy, bool integer_scale, bool portrait_top_align) {
 | 
				
			||||||
 | 
					    sokol_gfx.fb_width = w;
 | 
				
			||||||
 | 
					    sokol_gfx.fb_height = h;
 | 
				
			||||||
 | 
					    sokol_gfx.fb_aspect_scale_x = sx;
 | 
				
			||||||
 | 
					    sokol_gfx.fb_aspect_scale_y = sy;
 | 
				
			||||||
 | 
					    sokol_gfx.integer_scale = integer_scale;
 | 
				
			||||||
 | 
					    sokol_gfx.portrait_top_align = portrait_top_align;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    sg_setup(&(sg_desc){
 | 
				
			||||||
 | 
					        .mtl_device = sapp_metal_get_device(),
 | 
				
			||||||
 | 
					        .mtl_renderpass_descriptor_cb = sapp_metal_get_renderpass_descriptor,
 | 
				
			||||||
 | 
					        .mtl_drawable_cb = sapp_metal_get_drawable,
 | 
				
			||||||
 | 
					        .d3d11_device = sapp_d3d11_get_device(),
 | 
				
			||||||
 | 
					        .d3d11_device_context = sapp_d3d11_get_device_context(),
 | 
				
			||||||
 | 
					        .d3d11_render_target_view_cb = sapp_d3d11_get_render_target_view,
 | 
				
			||||||
 | 
					        .d3d11_depth_stencil_view_cb = sapp_d3d11_get_depth_stencil_view
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* quad vertex buffers with and without flipped UVs */
 | 
				
			||||||
 | 
					    float verts[] = {
 | 
				
			||||||
 | 
					        0.0f, 0.0f, 0.0f, 0.0f,
 | 
				
			||||||
 | 
					        1.0f, 0.0f, 1.0f, 0.0f,
 | 
				
			||||||
 | 
					        0.0f, 1.0f, 0.0f, 1.0f,
 | 
				
			||||||
 | 
					        1.0f, 1.0f,  1.0f, 1.0f
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    float verts_flipped[] = {
 | 
				
			||||||
 | 
					        0.0f, 0.0f, 0.0f, 1.0f,
 | 
				
			||||||
 | 
					        1.0f, 0.0f, 1.0f, 1.0f,
 | 
				
			||||||
 | 
					        0.0f, 1.0f, 0.0f, 0.0f,
 | 
				
			||||||
 | 
					        1.0f, 1.0f,  1.0f, 0.0f
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    sokol_gfx.upscale_draw_state.vertex_buffers[0] = sg_make_buffer(&(sg_buffer_desc){
 | 
				
			||||||
 | 
					        .size = sizeof(verts),
 | 
				
			||||||
 | 
					        .content = verts,
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					    sokol_gfx.draw_state.vertex_buffers[0] = sg_make_buffer(&(sg_buffer_desc){
 | 
				
			||||||
 | 
					        .size = sizeof(verts),
 | 
				
			||||||
 | 
					        .content = sg_query_feature(SG_FEATURE_ORIGIN_TOP_LEFT) ? verts : verts_flipped
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* a shader to render a textured quad */
 | 
				
			||||||
 | 
					    sg_shader fsq_shd = sg_make_shader(&(sg_shader_desc){
 | 
				
			||||||
 | 
					        .fs.images = {
 | 
				
			||||||
 | 
					            [0] = { .name="tex", .type=SG_IMAGETYPE_2D },
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        .vs.source = gfx_vs_src,
 | 
				
			||||||
 | 
					        .fs.source = gfx_fs_src,
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* 2 pipeline-state-objects, one for upscaling, one for rendering */
 | 
				
			||||||
 | 
					    sg_pipeline_desc pip_desc = {
 | 
				
			||||||
 | 
					        .layout = {
 | 
				
			||||||
 | 
					            .attrs[0] = { .name="in_pos", .sem_name="POS", .format=SG_VERTEXFORMAT_FLOAT2 },
 | 
				
			||||||
 | 
					            .attrs[1] = { .name="in_uv", .sem_name="UV", .format=SG_VERTEXFORMAT_FLOAT2 }
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        .shader = fsq_shd,
 | 
				
			||||||
 | 
					        .primitive_type = SG_PRIMITIVETYPE_TRIANGLE_STRIP
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    sokol_gfx.draw_state.pipeline = sg_make_pipeline(&pip_desc);
 | 
				
			||||||
 | 
					    pip_desc.blend.depth_format = SG_PIXELFORMAT_NONE;
 | 
				
			||||||
 | 
					    sokol_gfx.upscale_draw_state.pipeline = sg_make_pipeline(&pip_desc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* a texture with the emulator's raw pixel data */
 | 
				
			||||||
 | 
					    sokol_gfx.upscale_draw_state.fs_images[0] = sg_make_image(&(sg_image_desc){
 | 
				
			||||||
 | 
					        .width = sokol_gfx.fb_width,
 | 
				
			||||||
 | 
					        .height = sokol_gfx.fb_height,
 | 
				
			||||||
 | 
					        .pixel_format = SG_PIXELFORMAT_RGBA8,
 | 
				
			||||||
 | 
					        .usage = SG_USAGE_STREAM,
 | 
				
			||||||
 | 
					        .min_filter = SG_FILTER_NEAREST,
 | 
				
			||||||
 | 
					        .mag_filter = SG_FILTER_NEAREST,
 | 
				
			||||||
 | 
					        .wrap_u = SG_WRAP_CLAMP_TO_EDGE,
 | 
				
			||||||
 | 
					        .wrap_v = SG_WRAP_CLAMP_TO_EDGE
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					    /* a 2x upscaled render-target-texture */
 | 
				
			||||||
 | 
					    sokol_gfx.draw_state.fs_images[0] = sg_make_image(&(sg_image_desc){
 | 
				
			||||||
 | 
					        .render_target = true,
 | 
				
			||||||
 | 
					        .width = 2*sokol_gfx.fb_width,
 | 
				
			||||||
 | 
					        .height = 2*sokol_gfx.fb_height,
 | 
				
			||||||
 | 
					        .pixel_format = SG_PIXELFORMAT_RGBA8,
 | 
				
			||||||
 | 
					        .min_filter = SG_FILTER_LINEAR,
 | 
				
			||||||
 | 
					        .mag_filter = SG_FILTER_LINEAR,
 | 
				
			||||||
 | 
					        .wrap_u = SG_WRAP_CLAMP_TO_EDGE,
 | 
				
			||||||
 | 
					        .wrap_v = SG_WRAP_CLAMP_TO_EDGE
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* a render pass for the 2x upscaling */
 | 
				
			||||||
 | 
					    sokol_gfx.upscale_pass = sg_make_pass(&(sg_pass_desc){
 | 
				
			||||||
 | 
					        .color_attachments[0].image = sokol_gfx.draw_state.fs_images[0]
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const sg_pass_action gfx_upscale_pass_action = {
 | 
				
			||||||
 | 
					    .colors[0] = { .action = SG_ACTION_DONTCARE }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const sg_pass_action gfx_draw_pass_action = {
 | 
				
			||||||
 | 
					    .colors[0] = { .action = SG_ACTION_CLEAR, .val = { 0.05f, 0.05f, 0.05f, 1.0f } }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void sokol_calc_viewport(int* x, int* y, int* w, int* h)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    int vp_x = 0, vp_y = 0, vp_w = sapp_width(), vp_h = sapp_height();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (vp_w * sokol_gfx.fb_height < vp_h * sokol_gfx.fb_width)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        int discreteWidth = vp_w - (sokol_gfx.integer_scale ? vp_w % sokol_gfx.fb_width : 0);
 | 
				
			||||||
 | 
					        int discreteHeight = sokol_gfx.fb_height * discreteWidth / sokol_gfx.fb_width;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        vp_x = (vp_w - discreteWidth) / 2;
 | 
				
			||||||
 | 
					        vp_y = sokol_gfx.portrait_top_align && vp_w < vp_h
 | 
				
			||||||
 | 
					            ? 0 
 | 
				
			||||||
 | 
					            : (vp_h - discreteHeight) / 2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        vp_w = discreteWidth;
 | 
				
			||||||
 | 
					        vp_h = discreteHeight;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        int discreteHeight = vp_h - (sokol_gfx.integer_scale ? vp_h % sokol_gfx.fb_height : 0);
 | 
				
			||||||
 | 
					        int discreteWidth = sokol_gfx.fb_width * discreteHeight / sokol_gfx.fb_height;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        vp_x = (vp_w - discreteWidth) / 2;
 | 
				
			||||||
 | 
					        vp_y = (vp_h - discreteHeight) / 2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        vp_w = discreteWidth;
 | 
				
			||||||
 | 
					        vp_h = discreteHeight;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    *x = vp_x;
 | 
				
			||||||
 | 
					    *y = vp_y;
 | 
				
			||||||
 | 
					    *w = vp_w;
 | 
				
			||||||
 | 
					    *h = vp_h;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void apply_viewport(void) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    int vp_x, vp_y, vp_w, vp_h;
 | 
				
			||||||
 | 
					    sokol_calc_viewport(&vp_x, &vp_y, &vp_w, &vp_h);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    sg_apply_viewport(vp_x, vp_y, vp_w, vp_h, true);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void sokol_gfx_draw(const uint32_t* ptr) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* copy emulator pixel data into upscaling source texture */
 | 
				
			||||||
 | 
					    sg_update_image(sokol_gfx.upscale_draw_state.fs_images[0], &(sg_image_content){
 | 
				
			||||||
 | 
					        .subimage[0][0] = { 
 | 
				
			||||||
 | 
					            .ptr = ptr,
 | 
				
			||||||
 | 
					            .size = sokol_gfx.fb_width*sokol_gfx.fb_height*sizeof ptr[0]
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* upscale the original framebuffer 2x with nearest filtering */
 | 
				
			||||||
 | 
					    sg_begin_pass(sokol_gfx.upscale_pass, &gfx_upscale_pass_action);
 | 
				
			||||||
 | 
					    sg_apply_draw_state(&sokol_gfx.upscale_draw_state);
 | 
				
			||||||
 | 
					    sg_draw(0, 4, 1);
 | 
				
			||||||
 | 
					    sg_end_pass();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* draw the final pass with linear filtering */
 | 
				
			||||||
 | 
					    sg_begin_default_pass(&gfx_draw_pass_action, sapp_width(), sapp_height());
 | 
				
			||||||
 | 
					    apply_viewport();
 | 
				
			||||||
 | 
					    sg_apply_draw_state(&sokol_gfx.draw_state);
 | 
				
			||||||
 | 
					    sg_draw(0, 4, 1);
 | 
				
			||||||
 | 
					    sg_end_pass();
 | 
				
			||||||
 | 
					    sg_commit();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										36
									
								
								src/system/sokol_impl.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								src/system/sokol_impl.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,36 @@
 | 
				
			|||||||
 | 
					// MIT License
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Copyright (c) 2017 Vadim Grigoruk @nesbox // grigoruk@gmail.com
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
				
			||||||
 | 
					// of this software and associated documentation files (the "Software"), to deal
 | 
				
			||||||
 | 
					// in the Software without restriction, including without limitation the rights
 | 
				
			||||||
 | 
					// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
				
			||||||
 | 
					// copies of the Software, and to permit persons to whom the Software is
 | 
				
			||||||
 | 
					// furnished to do so, subject to the following conditions:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// The above copyright notice and this permission notice shall be included in all
 | 
				
			||||||
 | 
					// copies or substantial portions of the Software.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
				
			||||||
 | 
					// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
				
			||||||
 | 
					// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | 
				
			||||||
 | 
					// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
				
			||||||
 | 
					// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
				
			||||||
 | 
					// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 | 
				
			||||||
 | 
					// SOFTWARE.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define SOKOL_IMPL
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if defined(WIN32)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef WM_MOUSEHWHEEL
 | 
				
			||||||
 | 
					#define WM_MOUSEHWHEEL 0x020E
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "sokol_app.h"
 | 
				
			||||||
 | 
					#include "sokol_gfx.h"
 | 
				
			||||||
 | 
					#include "sokol_time.h"
 | 
				
			||||||
 | 
					#include "sokol_audio.h"
 | 
				
			||||||
							
								
								
									
										28
									
								
								src/system/sokol_impl.m
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								src/system/sokol_impl.m
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,28 @@
 | 
				
			|||||||
 | 
					// MIT License
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Copyright (c) 2017 Vadim Grigoruk @nesbox // grigoruk@gmail.com
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
				
			||||||
 | 
					// of this software and associated documentation files (the "Software"), to deal
 | 
				
			||||||
 | 
					// in the Software without restriction, including without limitation the rights
 | 
				
			||||||
 | 
					// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
				
			||||||
 | 
					// copies of the Software, and to permit persons to whom the Software is
 | 
				
			||||||
 | 
					// furnished to do so, subject to the following conditions:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// The above copyright notice and this permission notice shall be included in all
 | 
				
			||||||
 | 
					// copies or substantial portions of the Software.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
				
			||||||
 | 
					// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
				
			||||||
 | 
					// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | 
				
			||||||
 | 
					// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
				
			||||||
 | 
					// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
				
			||||||
 | 
					// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 | 
				
			||||||
 | 
					// SOFTWARE.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define SOKOL_IMPL
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "sokol_app.h"
 | 
				
			||||||
 | 
					#include "sokol_gfx.h"
 | 
				
			||||||
 | 
					#include "sokol_time.h"
 | 
				
			||||||
 | 
					#include "sokol_audio.h"
 | 
				
			||||||
		Reference in New Issue
	
	Block a user