Compare commits
244
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5a44afcd9f | ||
|
|
3c282b5022 | ||
|
|
f4d40bd55f | ||
|
|
465fea8bb3 | ||
|
|
d47e20b54e | ||
|
|
4e9f9b7e0e | ||
|
|
9650139470 | ||
|
|
054a40a4b2 | ||
|
|
972ee5cf76 | ||
|
|
aef02cb347 | ||
|
|
36e485b2a3 | ||
|
|
d23c51e707 | ||
|
|
0db437aadd | ||
|
|
e351c1e62a | ||
|
|
b541de4f8c | ||
|
|
604bc40021 | ||
|
|
be8ddebd80 | ||
|
|
b2a36850cb | ||
|
|
8353c1efdd | ||
|
|
d19a2e0912 | ||
|
|
07432c0381 | ||
|
|
4fb3b63152 | ||
|
|
85b736620a | ||
|
|
9f770993d4 | ||
|
|
4bd02ad325 | ||
|
|
6e7b45d15c | ||
|
|
99ebca51d5 | ||
|
|
24eb888af3 | ||
|
|
09ce33abb9 | ||
|
|
044ff158a1 | ||
|
|
36c68d055c | ||
|
|
ddf7d7cdcb | ||
|
|
38950d580f | ||
|
|
707701f317 | ||
|
|
09507d635b | ||
|
|
ab85d6a693 | ||
|
|
5011b17f88 | ||
|
|
7bef45f701 | ||
|
|
40cbce8f9f | ||
|
|
70a70084c9 | ||
|
|
b6da6359d3 | ||
|
|
97075ca5c5 | ||
|
|
e94737945a | ||
|
|
57f15e0213 | ||
|
|
2eae9b197c | ||
|
|
68c7620349 | ||
|
|
7a3faf34e7 | ||
|
|
d401644447 | ||
|
|
dfc349b230 | ||
|
|
be3e5a964d | ||
|
|
687d2bd894 | ||
|
|
78b642cf2d | ||
|
|
cb3b6ca34b | ||
|
|
ad15bf0ea3 | ||
|
|
56021ed999 | ||
|
|
3d22a5906f | ||
|
|
b6d771b48f | ||
|
|
ab30fb2e5e | ||
|
|
618d9e4cdf | ||
|
|
bf78ad9c75 | ||
|
|
918a4e8cd9 | ||
|
|
e90c84c9ac | ||
|
|
a9209a4887 | ||
|
|
0a3e7ba09f | ||
|
|
eb132b08c0 | ||
|
|
82407c3560 | ||
|
|
f1a8210663 | ||
|
|
1d722be4bc | ||
|
|
62a660bfe1 | ||
|
|
2984795175 | ||
|
|
da706d89a5 | ||
|
|
a8005d5cec | ||
|
|
793ccff6e6 | ||
|
|
e7db9bf1fd | ||
|
|
88d62c93a1 | ||
|
|
d73532d019 | ||
|
|
84d3d23936 | ||
|
|
717947843b | ||
|
|
968584a316 | ||
|
|
ccd67f621a | ||
|
|
80b301dbbe | ||
|
|
001e61d39d | ||
|
|
19c98a436a | ||
|
|
8dd6d7cfdd | ||
|
|
7456b6e02c | ||
|
|
5e8096f74c | ||
|
|
6af77afc44 | ||
|
|
42eeb7bdf5 | ||
|
|
6f4b1e5125 | ||
|
|
22e65cdda8 | ||
|
|
9d342d0f3d | ||
|
|
9583bed718 | ||
|
|
b69ce75712 | ||
|
|
a1cd19b023 | ||
|
|
6e50710b25 | ||
|
|
989a971d27 | ||
|
|
24ee56ce7a | ||
|
|
52f99dd9c1 | ||
|
|
6374fda570 | ||
|
|
cdd2d6323e | ||
|
|
c508a7ea78 | ||
|
|
1380a394c7 | ||
|
|
2c937099d4 | ||
|
|
0a936b3bba | ||
|
|
0a31e0a65e | ||
|
|
8627a18452 | ||
|
|
be528adea5 | ||
|
|
5eb4ed8391 | ||
|
|
9a00d30c0c | ||
|
|
71237c5e11 | ||
|
|
9c6e32a1ab | ||
|
|
1bc18801c8 | ||
|
|
221f2a956e | ||
|
|
b450abdf4d | ||
|
|
d36eed3c09 | ||
|
|
43ee791d4a | ||
|
|
c921945922 | ||
|
|
5f8c77e752 | ||
|
|
064db977aa | ||
|
|
5868cd9777 | ||
|
|
b0ddde996a | ||
|
|
e03c3766f0 | ||
|
|
953c0d7451 | ||
|
|
97b303c362 | ||
|
|
2ffe736a20 | ||
|
|
21f2032f34 | ||
|
|
2f66207205 | ||
|
|
5a14b09c1f | ||
|
|
7e9da92dbe | ||
|
|
a27550b95b | ||
|
|
556883487d | ||
|
|
96f8533479 | ||
|
|
f3cca27448 | ||
|
|
252563725d | ||
|
|
9a934a55e2 | ||
|
|
f07d5d381e | ||
|
|
3faab66ef4 | ||
|
|
2a023246be | ||
|
|
006e7fe8f8 | ||
|
|
1a7ff21a04 | ||
|
|
98cb0fdcb2 | ||
|
|
1fd7e9cdac | ||
|
|
0a2eac4d3a | ||
|
|
9ac6fffd4d | ||
|
|
da20f4a087 | ||
|
|
dbf822ced9 | ||
|
|
095842f4aa | ||
|
|
8c290d7597 | ||
|
|
8a6f4db9af | ||
|
|
99186a86db | ||
|
|
c67bf97f7b | ||
|
|
33a1540fcd | ||
|
|
529b0d643a | ||
|
|
4576efbe5c | ||
|
|
185375ece1 | ||
|
|
d11521954e | ||
|
|
41c4300ec2 | ||
|
|
51d5023f29 | ||
|
|
d2878f8834 | ||
|
|
7808159d23 | ||
|
|
e759431948 | ||
|
|
268ccce955 | ||
|
|
f2d3432bf5 | ||
|
|
2da89f1946 | ||
|
|
6153733df4 | ||
|
|
d280b39f9f | ||
|
|
236e7b8d45 | ||
|
|
dcccf672c9 | ||
|
|
03f81bed16 | ||
|
|
fc51c1ba88 | ||
|
|
83d20a72ab | ||
|
|
d50c1ab6d7 | ||
|
|
984c2ff8d6 | ||
|
|
74646acdca | ||
|
|
45ffe87ba6 | ||
|
|
37eb8cfa57 | ||
|
|
a0f903f162 | ||
|
|
f1f0782256 | ||
|
|
0e9a825f63 | ||
|
|
5c53a90eea | ||
|
|
55c6ba6d12 | ||
|
|
6617382f54 | ||
|
|
dd499a410f | ||
|
|
c04ba992a7 | ||
|
|
27c053cd48 | ||
|
|
7d68c0598c | ||
|
|
201c725dc7 | ||
|
|
e47e58a982 | ||
|
|
c05068f22f | ||
|
|
f5cb473f3d | ||
|
|
c5b72f24b5 | ||
|
|
57b2316c42 | ||
|
|
fe682a8071 | ||
|
|
bf44a054a1 | ||
|
|
eca9c60d9b | ||
|
|
cf42c35b9f | ||
|
|
a364068abb | ||
|
|
e88093d9cf | ||
|
|
5e532a76cf | ||
|
|
fb9c459269 | ||
|
|
7c34733eea | ||
|
|
a6898bd1cd | ||
|
|
ff474d18ee | ||
|
|
f15d3be263 | ||
|
|
19e5366c5b | ||
|
|
346dee019c | ||
|
|
18914f22f2 | ||
|
|
1219ecf818 | ||
|
|
b6923d0d0d | ||
|
|
393ade780c | ||
|
|
8b2e6ea17b | ||
|
|
8c31682723 | ||
|
|
7c87b5259a | ||
|
|
e8969b0645 | ||
|
|
7932c1af6f | ||
|
|
95b4228d3c | ||
|
|
a0ff44043f | ||
|
|
1e15816057 | ||
|
|
a4566e9496 | ||
|
|
18f88c28dd | ||
|
|
b8dc1b13df | ||
|
|
33c03f1e7a | ||
|
|
7e5ae71714 | ||
|
|
b574ed0b1b | ||
|
|
01c621832b | ||
|
|
608cc66d78 | ||
|
|
35103ad810 | ||
|
|
5ac0262654 | ||
|
|
c361285790 | ||
|
|
a168b5e2b9 | ||
|
|
f70c38a853 | ||
|
|
4c05c063a9 | ||
|
|
e1e45ad3ad | ||
|
|
ca9b001c9f | ||
|
|
3976d80867 | ||
|
|
1ee10457f8 | ||
|
|
116bcd0cb1 | ||
|
|
fcdccb96aa | ||
|
|
723286826b | ||
|
|
b190f09aea | ||
|
|
ff6358b031 | ||
|
|
c68c61975e | ||
|
|
7e31536ff9 | ||
|
|
c2cf6f17d1 |
No files matched your search
+8
-8
@@ -4,7 +4,6 @@
|
||||
*.plg
|
||||
*.suo
|
||||
*.vcproj.*.*.user
|
||||
*.kate-swp
|
||||
Win32_LIB_ASM_Debug
|
||||
Win32_LIB_ASM_Release
|
||||
*.bsc
|
||||
@@ -14,16 +13,17 @@ Win32_LIB_ASM_Release
|
||||
*.dgb
|
||||
*.debug
|
||||
*.debug.txt
|
||||
/bin/VC10/
|
||||
/objs/VC10/
|
||||
*.user
|
||||
*.db
|
||||
*.opendb
|
||||
/.vs
|
||||
/debian
|
||||
/assets/debian
|
||||
compile.sh
|
||||
*.gz
|
||||
.vscode/
|
||||
out
|
||||
build
|
||||
/make
|
||||
/bin
|
||||
/build
|
||||
/build/*
|
||||
/CMakeUserPresets.json
|
||||
/out
|
||||
/objs/VC10
|
||||
*.kate-swp
|
||||
@@ -1,2 +0,0 @@
|
||||
# DON'T REMOVE
|
||||
# This keeps the folder from disappearing
|
||||
@@ -1,2 +0,0 @@
|
||||
# DON'T REMOVE
|
||||
# This keeps the folder from disappearing
|
||||
@@ -1 +0,0 @@
|
||||
/lsdlsrb2
|
||||
@@ -1,3 +0,0 @@
|
||||
/lsdlsrb2
|
||||
/pnd
|
||||
/*.mo
|
||||
@@ -1 +0,0 @@
|
||||
/lsdlsrb2
|
||||
@@ -1 +0,0 @@
|
||||
/lsdl2srb2kart
|
||||
@@ -1,4 +0,0 @@
|
||||
*.exe
|
||||
*.mo
|
||||
r_opengl.dll
|
||||
*.bat
|
||||
@@ -1,4 +0,0 @@
|
||||
*.exe
|
||||
*.mo
|
||||
r_opengl.dll
|
||||
*.bat
|
||||
@@ -1,3 +0,0 @@
|
||||
/srb2sdl.exe
|
||||
/srb2win.exe
|
||||
/r_opengl.dll
|
||||
@@ -1,4 +0,0 @@
|
||||
*.exe
|
||||
*.mo
|
||||
r_opengl.dll
|
||||
*.bat
|
||||
@@ -1,2 +0,0 @@
|
||||
# DON'T REMOVE
|
||||
# This keeps the folder from disappearing
|
||||
@@ -1,2 +0,0 @@
|
||||
# DON'T REMOVE
|
||||
# This keeps the folder from disappearing
|
||||
@@ -1,2 +0,0 @@
|
||||
# DON'T REMOVE
|
||||
# This keeps the folder from disappearing
|
||||
@@ -42,3 +42,4 @@ compversion() {
|
||||
|
||||
[ -f "$path/comptime.c" ] && compversion "$@"
|
||||
exit 2
|
||||
|
||||
+1
-5
@@ -31,8 +31,4 @@ and don't forget to build r_opengl.dll for srb2dd.
|
||||
|
||||
Updated 2/17/2024 (v1.6 Saturn)
|
||||
No i threw everthing into dll-binaries
|
||||
theres no reason at all to have stuff spread across multiple directories
|
||||
|
||||
Updated 3/19/2025 (v1.6; Neptune)
|
||||
We're using some C++ code now, so we need to have a few more DLLs.
|
||||
Otherwise, it's about the same as prior.
|
||||
theres no reason at all to have stuff spread across multiple directories
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,191 @@
|
||||
/* include/curl/curlbuild.h. Generated from curlbuild.h.in by configure. */
|
||||
#ifndef __CURL_CURLBUILD_H
|
||||
#define __CURL_CURLBUILD_H
|
||||
/***************************************************************************
|
||||
* _ _ ____ _
|
||||
* Project ___| | | | _ \| |
|
||||
* / __| | | | |_) | |
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2009, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
* are also available at http://curl.haxx.se/docs/copyright.html.
|
||||
*
|
||||
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||
* copies of the Software, and permit persons to whom the Software is
|
||||
* furnished to do so, under the terms of the COPYING file.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
/* ================================================================ */
|
||||
/* NOTES FOR CONFIGURE CAPABLE SYSTEMS */
|
||||
/* ================================================================ */
|
||||
|
||||
/*
|
||||
* NOTE 1:
|
||||
* -------
|
||||
*
|
||||
* Nothing in this file is intended to be modified or adjusted by the
|
||||
* curl library user nor by the curl library builder.
|
||||
*
|
||||
* If you think that something actually needs to be changed, adjusted
|
||||
* or fixed in this file, then, report it on the libcurl development
|
||||
* mailing list: http://cool.haxx.se/mailman/listinfo/curl-library/
|
||||
*
|
||||
* This header file shall only export symbols which are 'curl' or 'CURL'
|
||||
* prefixed, otherwise public name space would be polluted.
|
||||
*
|
||||
* NOTE 2:
|
||||
* -------
|
||||
*
|
||||
* Right now you might be staring at file include/curl/curlbuild.h.in or
|
||||
* at file include/curl/curlbuild.h, this is due to the following reason:
|
||||
*
|
||||
* On systems capable of running the configure script, the configure process
|
||||
* will overwrite the distributed include/curl/curlbuild.h file with one that
|
||||
* is suitable and specific to the library being configured and built, which
|
||||
* is generated from the include/curl/curlbuild.h.in template file.
|
||||
*
|
||||
*/
|
||||
|
||||
/* ================================================================ */
|
||||
/* DEFINITION OF THESE SYMBOLS SHALL NOT TAKE PLACE ANYWHERE ELSE */
|
||||
/* ================================================================ */
|
||||
|
||||
#ifdef CURL_SIZEOF_LONG
|
||||
# error "CURL_SIZEOF_LONG shall not be defined except in curlbuild.h"
|
||||
Error Compilation_aborted_CURL_SIZEOF_LONG_already_defined
|
||||
#endif
|
||||
|
||||
#ifdef CURL_TYPEOF_CURL_SOCKLEN_T
|
||||
# error "CURL_TYPEOF_CURL_SOCKLEN_T shall not be defined except in curlbuild.h"
|
||||
Error Compilation_aborted_CURL_TYPEOF_CURL_SOCKLEN_T_already_defined
|
||||
#endif
|
||||
|
||||
#ifdef CURL_SIZEOF_CURL_SOCKLEN_T
|
||||
# error "CURL_SIZEOF_CURL_SOCKLEN_T shall not be defined except in curlbuild.h"
|
||||
Error Compilation_aborted_CURL_SIZEOF_CURL_SOCKLEN_T_already_defined
|
||||
#endif
|
||||
|
||||
#ifdef CURL_TYPEOF_CURL_OFF_T
|
||||
# error "CURL_TYPEOF_CURL_OFF_T shall not be defined except in curlbuild.h"
|
||||
Error Compilation_aborted_CURL_TYPEOF_CURL_OFF_T_already_defined
|
||||
#endif
|
||||
|
||||
#ifdef CURL_FORMAT_CURL_OFF_T
|
||||
# error "CURL_FORMAT_CURL_OFF_T shall not be defined except in curlbuild.h"
|
||||
Error Compilation_aborted_CURL_FORMAT_CURL_OFF_T_already_defined
|
||||
#endif
|
||||
|
||||
#ifdef CURL_FORMAT_CURL_OFF_TU
|
||||
# error "CURL_FORMAT_CURL_OFF_TU shall not be defined except in curlbuild.h"
|
||||
Error Compilation_aborted_CURL_FORMAT_CURL_OFF_TU_already_defined
|
||||
#endif
|
||||
|
||||
#ifdef CURL_FORMAT_OFF_T
|
||||
# error "CURL_FORMAT_OFF_T shall not be defined except in curlbuild.h"
|
||||
Error Compilation_aborted_CURL_FORMAT_OFF_T_already_defined
|
||||
#endif
|
||||
|
||||
#ifdef CURL_SIZEOF_CURL_OFF_T
|
||||
# error "CURL_SIZEOF_CURL_OFF_T shall not be defined except in curlbuild.h"
|
||||
Error Compilation_aborted_CURL_SIZEOF_CURL_OFF_T_already_defined
|
||||
#endif
|
||||
|
||||
#ifdef CURL_SUFFIX_CURL_OFF_T
|
||||
# error "CURL_SUFFIX_CURL_OFF_T shall not be defined except in curlbuild.h"
|
||||
Error Compilation_aborted_CURL_SUFFIX_CURL_OFF_T_already_defined
|
||||
#endif
|
||||
|
||||
#ifdef CURL_SUFFIX_CURL_OFF_TU
|
||||
# error "CURL_SUFFIX_CURL_OFF_TU shall not be defined except in curlbuild.h"
|
||||
Error Compilation_aborted_CURL_SUFFIX_CURL_OFF_TU_already_defined
|
||||
#endif
|
||||
|
||||
/* ================================================================ */
|
||||
/* EXTERNAL INTERFACE SETTINGS FOR CONFIGURE CAPABLE SYSTEMS ONLY */
|
||||
/* ================================================================ */
|
||||
|
||||
/* Configure process defines this to 1 when it finds out that system */
|
||||
/* header file ws2tcpip.h must be included by the external interface. */
|
||||
#define CURL_PULL_WS2TCPIP_H 1
|
||||
#ifdef CURL_PULL_WS2TCPIP_H
|
||||
# ifndef WIN32_LEAN_AND_MEAN
|
||||
# define WIN32_LEAN_AND_MEAN 1
|
||||
# endif
|
||||
# include <windows.h>
|
||||
# include <winsock2.h>
|
||||
# include <ws2tcpip.h>
|
||||
#endif
|
||||
|
||||
/* Configure process defines this to 1 when it finds out that system */
|
||||
/* header file sys/types.h must be included by the external interface. */
|
||||
#define CURL_PULL_SYS_TYPES_H 1
|
||||
#ifdef CURL_PULL_SYS_TYPES_H
|
||||
# include <sys/types.h>
|
||||
#endif
|
||||
|
||||
/* Configure process defines this to 1 when it finds out that system */
|
||||
/* header file stdint.h must be included by the external interface. */
|
||||
#define CURL_PULL_STDINT_H 1
|
||||
#ifdef CURL_PULL_STDINT_H
|
||||
# include <stdint.h>
|
||||
#endif
|
||||
|
||||
/* Configure process defines this to 1 when it finds out that system */
|
||||
/* header file inttypes.h must be included by the external interface. */
|
||||
#define CURL_PULL_INTTYPES_H 1
|
||||
#ifdef CURL_PULL_INTTYPES_H
|
||||
# include <inttypes.h>
|
||||
#endif
|
||||
|
||||
/* Configure process defines this to 1 when it finds out that system */
|
||||
/* header file sys/socket.h must be included by the external interface. */
|
||||
/* #undef CURL_PULL_SYS_SOCKET_H */
|
||||
#ifdef CURL_PULL_SYS_SOCKET_H
|
||||
# include <sys/socket.h>
|
||||
#endif
|
||||
|
||||
/* The size of `long', as computed by sizeof. */
|
||||
#define CURL_SIZEOF_LONG 4
|
||||
|
||||
/* Integral data type used for curl_socklen_t. */
|
||||
#define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
|
||||
|
||||
/* The size of `curl_socklen_t', as computed by sizeof. */
|
||||
#define CURL_SIZEOF_CURL_SOCKLEN_T 4
|
||||
|
||||
/* Data type definition of curl_socklen_t. */
|
||||
typedef CURL_TYPEOF_CURL_SOCKLEN_T curl_socklen_t;
|
||||
|
||||
/* Signed integral data type used for curl_off_t. */
|
||||
#define CURL_TYPEOF_CURL_OFF_T int64_t
|
||||
|
||||
/* Data type definition of curl_off_t. */
|
||||
typedef CURL_TYPEOF_CURL_OFF_T curl_off_t;
|
||||
|
||||
/* curl_off_t formatting string directive without "%" conversion specifier. */
|
||||
#define CURL_FORMAT_CURL_OFF_T "I64d"
|
||||
|
||||
/* unsigned curl_off_t formatting string without "%" conversion specifier. */
|
||||
#define CURL_FORMAT_CURL_OFF_TU "I64u"
|
||||
|
||||
/* curl_off_t formatting string directive with "%" conversion specifier. */
|
||||
#define CURL_FORMAT_OFF_T "%I64d"
|
||||
|
||||
/* The size of `curl_off_t', as computed by sizeof. */
|
||||
#define CURL_SIZEOF_CURL_OFF_T 8
|
||||
|
||||
/* curl_off_t constant suffix. */
|
||||
#define CURL_SUFFIX_CURL_OFF_T LL
|
||||
|
||||
/* unsigned curl_off_t constant suffix. */
|
||||
#define CURL_SUFFIX_CURL_OFF_TU ULL
|
||||
|
||||
#endif /* __CURL_CURLBUILD_H */
|
||||
@@ -0,0 +1,261 @@
|
||||
#ifndef __CURL_CURLRULES_H
|
||||
#define __CURL_CURLRULES_H
|
||||
/***************************************************************************
|
||||
* _ _ ____ _
|
||||
* Project ___| | | | _ \| |
|
||||
* / __| | | | |_) | |
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
* are also available at http://curl.haxx.se/docs/copyright.html.
|
||||
*
|
||||
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||
* copies of the Software, and permit persons to whom the Software is
|
||||
* furnished to do so, under the terms of the COPYING file.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
/* ================================================================ */
|
||||
/* COMPILE TIME SANITY CHECKS */
|
||||
/* ================================================================ */
|
||||
|
||||
/*
|
||||
* NOTE 1:
|
||||
* -------
|
||||
*
|
||||
* All checks done in this file are intentionally placed in a public
|
||||
* header file which is pulled by curl/curl.h when an application is
|
||||
* being built using an already built libcurl library. Additionally
|
||||
* this file is also included and used when building the library.
|
||||
*
|
||||
* If compilation fails on this file it is certainly sure that the
|
||||
* problem is elsewhere. It could be a problem in the curlbuild.h
|
||||
* header file, or simply that you are using different compilation
|
||||
* settings than those used to build the library.
|
||||
*
|
||||
* Nothing in this file is intended to be modified or adjusted by the
|
||||
* curl library user nor by the curl library builder.
|
||||
*
|
||||
* Do not deactivate any check, these are done to make sure that the
|
||||
* library is properly built and used.
|
||||
*
|
||||
* You can find further help on the libcurl development mailing list:
|
||||
* http://cool.haxx.se/mailman/listinfo/curl-library/
|
||||
*
|
||||
* NOTE 2
|
||||
* ------
|
||||
*
|
||||
* Some of the following compile time checks are based on the fact
|
||||
* that the dimension of a constant array can not be a negative one.
|
||||
* In this way if the compile time verification fails, the compilation
|
||||
* will fail issuing an error. The error description wording is compiler
|
||||
* dependent but it will be quite similar to one of the following:
|
||||
*
|
||||
* "negative subscript or subscript is too large"
|
||||
* "array must have at least one element"
|
||||
* "-1 is an illegal array size"
|
||||
* "size of array is negative"
|
||||
*
|
||||
* If you are building an application which tries to use an already
|
||||
* built libcurl library and you are getting this kind of errors on
|
||||
* this file, it is a clear indication that there is a mismatch between
|
||||
* how the library was built and how you are trying to use it for your
|
||||
* application. Your already compiled or binary library provider is the
|
||||
* only one who can give you the details you need to properly use it.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Verify that some macros are actually defined.
|
||||
*/
|
||||
|
||||
#ifndef CURL_SIZEOF_LONG
|
||||
# error "CURL_SIZEOF_LONG definition is missing!"
|
||||
Error Compilation_aborted_CURL_SIZEOF_LONG_is_missing
|
||||
#endif
|
||||
|
||||
#ifndef CURL_TYPEOF_CURL_SOCKLEN_T
|
||||
# error "CURL_TYPEOF_CURL_SOCKLEN_T definition is missing!"
|
||||
Error Compilation_aborted_CURL_TYPEOF_CURL_SOCKLEN_T_is_missing
|
||||
#endif
|
||||
|
||||
#ifndef CURL_SIZEOF_CURL_SOCKLEN_T
|
||||
# error "CURL_SIZEOF_CURL_SOCKLEN_T definition is missing!"
|
||||
Error Compilation_aborted_CURL_SIZEOF_CURL_SOCKLEN_T_is_missing
|
||||
#endif
|
||||
|
||||
#ifndef CURL_TYPEOF_CURL_OFF_T
|
||||
# error "CURL_TYPEOF_CURL_OFF_T definition is missing!"
|
||||
Error Compilation_aborted_CURL_TYPEOF_CURL_OFF_T_is_missing
|
||||
#endif
|
||||
|
||||
#ifndef CURL_FORMAT_CURL_OFF_T
|
||||
# error "CURL_FORMAT_CURL_OFF_T definition is missing!"
|
||||
Error Compilation_aborted_CURL_FORMAT_CURL_OFF_T_is_missing
|
||||
#endif
|
||||
|
||||
#ifndef CURL_FORMAT_CURL_OFF_TU
|
||||
# error "CURL_FORMAT_CURL_OFF_TU definition is missing!"
|
||||
Error Compilation_aborted_CURL_FORMAT_CURL_OFF_TU_is_missing
|
||||
#endif
|
||||
|
||||
#ifndef CURL_FORMAT_OFF_T
|
||||
# error "CURL_FORMAT_OFF_T definition is missing!"
|
||||
Error Compilation_aborted_CURL_FORMAT_OFF_T_is_missing
|
||||
#endif
|
||||
|
||||
#ifndef CURL_SIZEOF_CURL_OFF_T
|
||||
# error "CURL_SIZEOF_CURL_OFF_T definition is missing!"
|
||||
Error Compilation_aborted_CURL_SIZEOF_CURL_OFF_T_is_missing
|
||||
#endif
|
||||
|
||||
#ifndef CURL_SUFFIX_CURL_OFF_T
|
||||
# error "CURL_SUFFIX_CURL_OFF_T definition is missing!"
|
||||
Error Compilation_aborted_CURL_SUFFIX_CURL_OFF_T_is_missing
|
||||
#endif
|
||||
|
||||
#ifndef CURL_SUFFIX_CURL_OFF_TU
|
||||
# error "CURL_SUFFIX_CURL_OFF_TU definition is missing!"
|
||||
Error Compilation_aborted_CURL_SUFFIX_CURL_OFF_TU_is_missing
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Macros private to this header file.
|
||||
*/
|
||||
|
||||
#define CurlchkszEQ(t, s) sizeof(t) == s ? 1 : -1
|
||||
|
||||
#define CurlchkszGE(t1, t2) sizeof(t1) >= sizeof(t2) ? 1 : -1
|
||||
|
||||
/*
|
||||
* Verify that the size previously defined and expected for long
|
||||
* is the same as the one reported by sizeof() at compile time.
|
||||
*/
|
||||
|
||||
typedef char
|
||||
__curl_rule_01__
|
||||
[CurlchkszEQ(long, CURL_SIZEOF_LONG)];
|
||||
|
||||
/*
|
||||
* Verify that the size previously defined and expected for
|
||||
* curl_off_t is actually the the same as the one reported
|
||||
* by sizeof() at compile time.
|
||||
*/
|
||||
|
||||
typedef char
|
||||
__curl_rule_02__
|
||||
[CurlchkszEQ(curl_off_t, CURL_SIZEOF_CURL_OFF_T)];
|
||||
|
||||
/*
|
||||
* Verify at compile time that the size of curl_off_t as reported
|
||||
* by sizeof() is greater or equal than the one reported for long
|
||||
* for the current compilation.
|
||||
*/
|
||||
|
||||
typedef char
|
||||
__curl_rule_03__
|
||||
[CurlchkszGE(curl_off_t, long)];
|
||||
|
||||
/*
|
||||
* Verify that the size previously defined and expected for
|
||||
* curl_socklen_t is actually the the same as the one reported
|
||||
* by sizeof() at compile time.
|
||||
*/
|
||||
|
||||
typedef char
|
||||
__curl_rule_04__
|
||||
[CurlchkszEQ(curl_socklen_t, CURL_SIZEOF_CURL_SOCKLEN_T)];
|
||||
|
||||
/*
|
||||
* Verify at compile time that the size of curl_socklen_t as reported
|
||||
* by sizeof() is greater or equal than the one reported for int for
|
||||
* the current compilation.
|
||||
*/
|
||||
|
||||
typedef char
|
||||
__curl_rule_05__
|
||||
[CurlchkszGE(curl_socklen_t, int)];
|
||||
|
||||
/* ================================================================ */
|
||||
/* EXTERNALLY AND INTERNALLY VISIBLE DEFINITIONS */
|
||||
/* ================================================================ */
|
||||
|
||||
/*
|
||||
* CURL_ISOCPP and CURL_OFF_T_C definitions are done here in order to allow
|
||||
* these to be visible and exported by the external libcurl interface API,
|
||||
* while also making them visible to the library internals, simply including
|
||||
* setup.h, without actually needing to include curl.h internally.
|
||||
* If some day this section would grow big enough, all this should be moved
|
||||
* to its own header file.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Figure out if we can use the ## preprocessor operator, which is supported
|
||||
* by ISO/ANSI C and C++. Some compilers support it without setting __STDC__
|
||||
* or __cplusplus so we need to carefully check for them too.
|
||||
*/
|
||||
|
||||
#if defined(__STDC__) || defined(_MSC_VER) || defined(__cplusplus) || \
|
||||
defined(__HP_aCC) || defined(__BORLANDC__) || defined(__LCC__) || \
|
||||
defined(__POCC__) || defined(__SALFORDC__) || defined(__HIGHC__) || \
|
||||
defined(__ILEC400__)
|
||||
/* This compiler is believed to have an ISO compatible preprocessor */
|
||||
#define CURL_ISOCPP
|
||||
#else
|
||||
/* This compiler is believed NOT to have an ISO compatible preprocessor */
|
||||
#undef CURL_ISOCPP
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Macros for minimum-width signed and unsigned curl_off_t integer constants.
|
||||
*/
|
||||
|
||||
#if defined(__BORLANDC__) && (__BORLANDC__ == 0x0551)
|
||||
# define __CURL_OFF_T_C_HLPR2(x) x
|
||||
# define __CURL_OFF_T_C_HLPR1(x) __CURL_OFF_T_C_HLPR2(x)
|
||||
# define CURL_OFF_T_C(Val) __CURL_OFF_T_C_HLPR1(Val) ## \
|
||||
__CURL_OFF_T_C_HLPR1(CURL_SUFFIX_CURL_OFF_T)
|
||||
# define CURL_OFF_TU_C(Val) __CURL_OFF_T_C_HLPR1(Val) ## \
|
||||
__CURL_OFF_T_C_HLPR1(CURL_SUFFIX_CURL_OFF_TU)
|
||||
#else
|
||||
# ifdef CURL_ISOCPP
|
||||
# define __CURL_OFF_T_C_HLPR2(Val,Suffix) Val ## Suffix
|
||||
# else
|
||||
# define __CURL_OFF_T_C_HLPR2(Val,Suffix) Val/**/Suffix
|
||||
# endif
|
||||
# define __CURL_OFF_T_C_HLPR1(Val,Suffix) __CURL_OFF_T_C_HLPR2(Val,Suffix)
|
||||
# define CURL_OFF_T_C(Val) __CURL_OFF_T_C_HLPR1(Val,CURL_SUFFIX_CURL_OFF_T)
|
||||
# define CURL_OFF_TU_C(Val) __CURL_OFF_T_C_HLPR1(Val,CURL_SUFFIX_CURL_OFF_TU)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Get rid of macros private to this header file.
|
||||
*/
|
||||
|
||||
#undef CurlchkszEQ
|
||||
#undef CurlchkszGE
|
||||
|
||||
/*
|
||||
* Get rid of macros not intended to exist beyond this point.
|
||||
*/
|
||||
|
||||
#undef CURL_PULL_WS2TCPIP_H
|
||||
#undef CURL_PULL_SYS_TYPES_H
|
||||
#undef CURL_PULL_SYS_SOCKET_H
|
||||
#undef CURL_PULL_STDINT_H
|
||||
#undef CURL_PULL_INTTYPES_H
|
||||
|
||||
#undef CURL_TYPEOF_CURL_SOCKLEN_T
|
||||
#undef CURL_TYPEOF_CURL_OFF_T
|
||||
|
||||
#ifdef CURL_NO_OLDIES
|
||||
#undef CURL_FORMAT_OFF_T /* not required since 7.19.0 - obsoleted in 7.20.0 */
|
||||
#endif
|
||||
|
||||
#endif /* __CURL_CURLRULES_H */
|
||||
@@ -0,0 +1 @@
|
||||
/* not used */
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+94
-94
@@ -1,94 +1,94 @@
|
||||
# CMake project definition file.
|
||||
project(libgme)
|
||||
|
||||
include (CheckCXXCompilerFlag)
|
||||
|
||||
# When version is changed, also change the one in gme/gme.h to match
|
||||
set(GME_VERSION 0.6.2 CACHE INTERNAL "libgme Version")
|
||||
|
||||
# 2.6+ always assumes FATAL_ERROR, but 2.4 and below don't.
|
||||
# Of course, 2.4 might work, in which case you're welcome to drop
|
||||
# down the requirement, but I can't test that.
|
||||
cmake_minimum_required(VERSION 2.6 FATAL_ERROR)
|
||||
|
||||
# Default emulators to build (all of them! ;)
|
||||
if (NOT DEFINED USE_GME_AY)
|
||||
SET(USE_GME_AY 1 CACHE BOOL "Enable support for Spectrum ZX music emulation")
|
||||
endif()
|
||||
|
||||
if (NOT DEFINED USE_GME_GBS)
|
||||
SET(USE_GME_GBS 1 CACHE BOOL "Enable support for Game Boy music emulation")
|
||||
endif()
|
||||
|
||||
if (NOT DEFINED USE_GME_GYM)
|
||||
SET(USE_GME_GYM 1 CACHE BOOL "Enable Sega MegaDrive/Genesis music emulation")
|
||||
endif()
|
||||
|
||||
if (NOT DEFINED USE_GME_HES)
|
||||
SET(USE_GME_HES 1 CACHE BOOL "Enable PC Engine/TurboGrafx-16 music emulation")
|
||||
endif()
|
||||
|
||||
if (NOT DEFINED USE_GME_KSS)
|
||||
SET(USE_GME_KSS 1 CACHE BOOL "Enable MSX or other Z80 systems music emulation")
|
||||
endif()
|
||||
|
||||
if (NOT DEFINED USE_GME_NSF)
|
||||
SET(USE_GME_NSF 1 CACHE BOOL "Enable NES NSF music emulation")
|
||||
endif()
|
||||
|
||||
if (NOT DEFINED USE_GME_NSFE)
|
||||
SET(USE_GME_NSFE 1 CACHE BOOL "Enable NES NSFE and NSF music emulation")
|
||||
endif()
|
||||
|
||||
if (NOT DEFINED USE_GME_SAP)
|
||||
SET(USE_GME_SAP 1 CACHE BOOL "Enable Atari SAP music emulation")
|
||||
endif()
|
||||
|
||||
if (NOT DEFINED USE_GME_SPC)
|
||||
SET(USE_GME_SPC 1 CACHE BOOL "Enable SNES SPC music emulation")
|
||||
endif()
|
||||
|
||||
if (NOT DEFINED USE_GME_VGM)
|
||||
SET(USE_GME_VGM 1 CACHE BOOL "Enable Sega VGM/VGZ music emulation")
|
||||
endif()
|
||||
|
||||
if (USE_GME_NSFE AND NOT USE_GME_NSF)
|
||||
MESSAGE(" -- NSFE support requires NSF, enabling NSF support. --")
|
||||
SET(USE_GME_NSF 1 CACHE BOOL "Enable NES NSF music emulation" FORCE)
|
||||
endif()
|
||||
|
||||
option(BUILD_SHARED_LIBS "Build shared library (set to OFF for static library)" ON)
|
||||
|
||||
# Check for GCC "visibility" support.
|
||||
if (CMAKE_COMPILER_IS_GNUCXX)
|
||||
check_cxx_compiler_flag (-fvisibility=hidden __LIBGME_TEST_VISIBILITY)
|
||||
set (ENABLE_VISIBILITY OFF)
|
||||
if (__LIBGME_TEST_VISIBILITY)
|
||||
# get the gcc version
|
||||
exec_program(${CMAKE_CXX_COMPILER} ARGS --version OUTPUT_VARIABLE _gcc_version_info)
|
||||
string (REGEX MATCH "[3-9]\\.[0-9]\\.[0-9]" _gcc_version "${_gcc_version_info}")
|
||||
|
||||
# gcc <4.1 had poor support for symbol visibility
|
||||
if ((${_gcc_version} VERSION_GREATER "4.1") OR (${_gcc_version} VERSION_EQUAL "4.1"))
|
||||
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=hidden")
|
||||
set (ENABLE_VISIBILITY ON)
|
||||
add_definitions (-DLIBGME_VISIBILITY)
|
||||
|
||||
# GCC >= 4.2 also correctly supports making inline members have hidden
|
||||
# visibility by default.
|
||||
if ((${_gcc_version} VERSION_GREATER "4.2") OR (${_gcc_version} VERSION_EQUAL "4.2"))
|
||||
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility-inlines-hidden")
|
||||
endif()
|
||||
endif()
|
||||
endif() # test visibility
|
||||
|
||||
# Cache this result
|
||||
set( LIBGME_HAVE_GCC_VISIBILITY ${ENABLE_VISIBILITY} CACHE BOOL "GCC support for hidden visibility")
|
||||
endif (CMAKE_COMPILER_IS_GNUCXX)
|
||||
|
||||
# Shared library defined here
|
||||
add_subdirectory(gme)
|
||||
|
||||
# EXCLUDE_FROM_ALL adds build rules but keeps it out of default build
|
||||
add_subdirectory(player EXCLUDE_FROM_ALL)
|
||||
add_subdirectory(demo EXCLUDE_FROM_ALL)
|
||||
# CMake project definition file.
|
||||
project(libgme)
|
||||
|
||||
include (CheckCXXCompilerFlag)
|
||||
|
||||
# When version is changed, also change the one in gme/gme.h to match
|
||||
set(GME_VERSION 0.6.2 CACHE INTERNAL "libgme Version")
|
||||
|
||||
# 2.6+ always assumes FATAL_ERROR, but 2.4 and below don't.
|
||||
# Of course, 2.4 might work, in which case you're welcome to drop
|
||||
# down the requirement, but I can't test that.
|
||||
cmake_minimum_required(VERSION 2.6 FATAL_ERROR)
|
||||
|
||||
# Default emulators to build (all of them! ;)
|
||||
if (NOT DEFINED USE_GME_AY)
|
||||
SET(USE_GME_AY 1 CACHE BOOL "Enable support for Spectrum ZX music emulation")
|
||||
endif()
|
||||
|
||||
if (NOT DEFINED USE_GME_GBS)
|
||||
SET(USE_GME_GBS 1 CACHE BOOL "Enable support for Game Boy music emulation")
|
||||
endif()
|
||||
|
||||
if (NOT DEFINED USE_GME_GYM)
|
||||
SET(USE_GME_GYM 1 CACHE BOOL "Enable Sega MegaDrive/Genesis music emulation")
|
||||
endif()
|
||||
|
||||
if (NOT DEFINED USE_GME_HES)
|
||||
SET(USE_GME_HES 1 CACHE BOOL "Enable PC Engine/TurboGrafx-16 music emulation")
|
||||
endif()
|
||||
|
||||
if (NOT DEFINED USE_GME_KSS)
|
||||
SET(USE_GME_KSS 1 CACHE BOOL "Enable MSX or other Z80 systems music emulation")
|
||||
endif()
|
||||
|
||||
if (NOT DEFINED USE_GME_NSF)
|
||||
SET(USE_GME_NSF 1 CACHE BOOL "Enable NES NSF music emulation")
|
||||
endif()
|
||||
|
||||
if (NOT DEFINED USE_GME_NSFE)
|
||||
SET(USE_GME_NSFE 1 CACHE BOOL "Enable NES NSFE and NSF music emulation")
|
||||
endif()
|
||||
|
||||
if (NOT DEFINED USE_GME_SAP)
|
||||
SET(USE_GME_SAP 1 CACHE BOOL "Enable Atari SAP music emulation")
|
||||
endif()
|
||||
|
||||
if (NOT DEFINED USE_GME_SPC)
|
||||
SET(USE_GME_SPC 1 CACHE BOOL "Enable SNES SPC music emulation")
|
||||
endif()
|
||||
|
||||
if (NOT DEFINED USE_GME_VGM)
|
||||
SET(USE_GME_VGM 1 CACHE BOOL "Enable Sega VGM/VGZ music emulation")
|
||||
endif()
|
||||
|
||||
if (USE_GME_NSFE AND NOT USE_GME_NSF)
|
||||
MESSAGE(" -- NSFE support requires NSF, enabling NSF support. --")
|
||||
SET(USE_GME_NSF 1 CACHE BOOL "Enable NES NSF music emulation" FORCE)
|
||||
endif()
|
||||
|
||||
option(BUILD_SHARED_LIBS "Build shared library (set to OFF for static library)" ON)
|
||||
|
||||
# Check for GCC "visibility" support.
|
||||
if (CMAKE_COMPILER_IS_GNUCXX)
|
||||
check_cxx_compiler_flag (-fvisibility=hidden __LIBGME_TEST_VISIBILITY)
|
||||
set (ENABLE_VISIBILITY OFF)
|
||||
if (__LIBGME_TEST_VISIBILITY)
|
||||
# get the gcc version
|
||||
exec_program(${CMAKE_CXX_COMPILER} ARGS --version OUTPUT_VARIABLE _gcc_version_info)
|
||||
string (REGEX MATCH "[3-9]\\.[0-9]\\.[0-9]" _gcc_version "${_gcc_version_info}")
|
||||
|
||||
# gcc <4.1 had poor support for symbol visibility
|
||||
if ((${_gcc_version} VERSION_GREATER "4.1") OR (${_gcc_version} VERSION_EQUAL "4.1"))
|
||||
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=hidden")
|
||||
set (ENABLE_VISIBILITY ON)
|
||||
add_definitions (-DLIBGME_VISIBILITY)
|
||||
|
||||
# GCC >= 4.2 also correctly supports making inline members have hidden
|
||||
# visibility by default.
|
||||
if ((${_gcc_version} VERSION_GREATER "4.2") OR (${_gcc_version} VERSION_EQUAL "4.2"))
|
||||
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility-inlines-hidden")
|
||||
endif()
|
||||
endif()
|
||||
endif() # test visibility
|
||||
|
||||
# Cache this result
|
||||
set( LIBGME_HAVE_GCC_VISIBILITY ${ENABLE_VISIBILITY} CACHE BOOL "GCC support for hidden visibility")
|
||||
endif (CMAKE_COMPILER_IS_GNUCXX)
|
||||
|
||||
# Shared library defined here
|
||||
add_subdirectory(gme)
|
||||
|
||||
# EXCLUDE_FROM_ALL adds build rules but keeps it out of default build
|
||||
add_subdirectory(player EXCLUDE_FROM_ALL)
|
||||
add_subdirectory(demo EXCLUDE_FROM_ALL)
|
||||
@@ -1,5 +1,5 @@
|
||||
Game_Music_Emu Change Log
|
||||
-------------------------
|
||||
|
||||
Please see the git version history (e.g. git shortlog tags/0.6.0..tags/0.6.1)
|
||||
for the accurate change log.
|
||||
Game_Music_Emu Change Log
|
||||
-------------------------
|
||||
|
||||
Please see the git version history (e.g. git shortlog tags/0.6.0..tags/0.6.1)
|
||||
for the accurate change log.
|
||||
+194
-194
@@ -1,194 +1,194 @@
|
||||
Game_Music_Emu 0.6.0 Design
|
||||
---------------------------
|
||||
This might be slightly out-of-date at times, but will be a big help in
|
||||
understanding the library implementation.
|
||||
|
||||
|
||||
Architecture
|
||||
------------
|
||||
The library is essentially a bunch of independent game music file
|
||||
emulators unified with a common interface.
|
||||
|
||||
Gme_File and Music_Emu provide a common interface to the emulators. The
|
||||
virtual functions are protected rather than public to allow pre- and
|
||||
post-processing of arguments and data in one place. This allows the
|
||||
emulator classes to assume that everything is set up properly when
|
||||
starting a track and playing samples.
|
||||
|
||||
All file input is done with the Data_Reader interface. Many derived
|
||||
classes are present, for the usual disk-based file and block of memory,
|
||||
to specialized adaptors for things like reading a subset of data or
|
||||
combining a block of memory with a Data_Reader to the remaining data.
|
||||
This makes the library much more flexible with regard to the source of
|
||||
game music file data. I still added a specialized load_mem() function to
|
||||
have the emulator keep a pointer to data already read in memory, for
|
||||
those formats whose files can be absolutely huge (GYM, some VGMs). This
|
||||
is important if for some reason the caller must load the data ahead of
|
||||
time, but doesn't want the emulator needlessly making a copy.
|
||||
|
||||
Since silence checking and fading are relatively complex, they are kept
|
||||
separate from basic file loading and track information, which are
|
||||
handled in the base class Gme_File. My original intent was to use
|
||||
Gme_File as the common base class for full emulators and track
|
||||
information-only readers, but implementing the C interface was much
|
||||
simpler if both derived from Music_Emu. User C++ code can still benefit
|
||||
from static checking by using Gme_File where only track information will
|
||||
be accessed.
|
||||
|
||||
Each emulator generally has three components: main emulator, CPU
|
||||
emulator, and sound chip emulator(s). Each component has minimal
|
||||
coupling, so use in a full emulator or stand alone is fairly easy. This
|
||||
modularity really helps reduce complexity. Blip_Buffer helps a lot with
|
||||
simplifying the APU interfaces and implementation.
|
||||
|
||||
The "classic" emulators derive from Classic_Emu, which handles
|
||||
Blip_Buffer filling and multiple channels. It uses Multi_Buffer for
|
||||
output, allowing you to derive a custom buffer that could output each
|
||||
voice to a separate sound channel and do different processing on each.
|
||||
At some point I'm going to implement a better Effects_Buffer that allows
|
||||
individual control of every channel.
|
||||
|
||||
In implementing the C interface, I wanted a way to specify an emulator
|
||||
type that didn't require linking in all the emulators. For each emulator
|
||||
type there is a global object with pointers to functions to create the
|
||||
emulator or a track information reader. The emulator type is thus a
|
||||
pointer to this, which conveniently allows for a NULL value. The user
|
||||
referencing this emulator type object is what ultimately links the
|
||||
emulator in (unless new Foo_Emu is used in C++, of course). This type
|
||||
also serves as a useful substitute for RTTI on older C++ compilers.
|
||||
|
||||
Addendum: I have since added gme_type_list(), which causes all listed
|
||||
emulators to be linked in. To avoid this, I make the list itself
|
||||
editable in blargg_config.h. Having a built-in list allows
|
||||
gme_load_file() to take a path and give back an emulator with the file
|
||||
loaded, which is extremely useful for new users.
|
||||
|
||||
|
||||
Interface conventions
|
||||
----------------------
|
||||
If a function retains a pointer to or replaces the value of an object
|
||||
passed, it takes a pointer so that it will be clear in the caller's
|
||||
source code that care is required.
|
||||
|
||||
Multi-word names have an underscore '_' separator between individual
|
||||
words.
|
||||
|
||||
Functions are named with lowercase words. Functions which perform an
|
||||
action with side-effects are named with a verb phrase (i.e. load, move,
|
||||
run). Functions which return the value of a piece of state are named
|
||||
using a noun phrase (i.e. loaded, moved, running).
|
||||
|
||||
Classes are named with capitalized words. Only the first letter of an
|
||||
acronym is capitalized. Class names are nouns, sometimes suggestive of
|
||||
what they do (i.e. File_Scanner).
|
||||
|
||||
Structure, enumeration, and typedefs to these and built-in types are
|
||||
named using lowercase words with a _t suffix.
|
||||
|
||||
Macros are named with all-uppercase words.
|
||||
|
||||
Internal names which can't be hidden due to technical reasons have an
|
||||
underscore '_' suffix.
|
||||
|
||||
|
||||
Managing Complexity
|
||||
-------------------
|
||||
Complexity has been a factor in most library decisions. Many features
|
||||
have been passed by due to the complexity they would add. Once
|
||||
complexity goes past a certain level, it mentally grasping the library
|
||||
in its entirety, at which point more defects will occur and be hard to
|
||||
find.
|
||||
|
||||
I chose 16-bit signed samples because it seems to be the most common
|
||||
format. Supporting multiple formats would add too much complexity to be
|
||||
worth it. Other formats can be obtained via conversion.
|
||||
|
||||
I've kept interfaces fairly lean, leaving many possible features
|
||||
untapped but easy to add if necessary. For example the classic emulators
|
||||
could have volume and frequency equalization adjusted separately for
|
||||
each channel, since they each have an associated Blip_Synth.
|
||||
|
||||
Source files of 400 lines or less seem to be the best size to limit
|
||||
complexity. In a few cases there is no reasonable way to split longer
|
||||
files, or there is benefit from having the source together in one file.
|
||||
|
||||
|
||||
Preventing Bugs
|
||||
---------------
|
||||
I've done many things to reduce the opportunity for defects. A general
|
||||
principle is to write code so that defects will be as visible as
|
||||
possible. I've used several techniques to achieve this.
|
||||
|
||||
I put assertions at key points where defects seem likely or where
|
||||
corruption due to a defect is likely to be visible. I've also put
|
||||
assertions where violations of the interface are likely. In emulators
|
||||
where I am unsure of exact hardware operation in a particular case, I
|
||||
output a debug-only message noting that this has occurred; many times I
|
||||
haven't implemented a hardware feature because nothing uses it. I've
|
||||
made code brittle where there is no clear reason flexibility; code
|
||||
written to handle every possibility sacrifices quality and reliability
|
||||
to handle vaguely defined situations.
|
||||
|
||||
|
||||
Flexibility through indirection
|
||||
-------------------------------
|
||||
I've tried to allow the most flexibility of modules by using indirection
|
||||
to allow extension by the user. This keeps each module simpler and more
|
||||
focused on its unique task.
|
||||
|
||||
The classic emulators use Multi_Buffer, which potentially allows a
|
||||
separate Blip_Buffer for each channel. This keeps emulators free of
|
||||
typical code to allow output in mono, stereo, panning, etc.
|
||||
|
||||
All emulators use a reader object to access file data, allowing it to be
|
||||
stored in a regular file, compressed archive, memory, or generated
|
||||
on-the-fly. Again, the library can be kept free of the particulars of
|
||||
file access and changes required to support new formats.
|
||||
|
||||
|
||||
Emulators in general
|
||||
--------------------
|
||||
When I wrote the first NES sound emulator, I stored most of the state in
|
||||
an emulator-specific format, with significant redundancy. In the
|
||||
register write function I decoded everything into named variables. I
|
||||
became tired of the verbosity and wanted to more closely model the
|
||||
hardware, so I moved to a style of storing the last written value to
|
||||
each register, along with as little other state as possible, mostly the
|
||||
internal hardware registers. While this involves slightly more
|
||||
recalculation, in most cases the emulation code is of comparable size.
|
||||
It also makes state save/restore (for use in a full emulator) much
|
||||
simpler. Finally, it makes debugging easier since the hardware registers
|
||||
used in emulation are obvious.
|
||||
|
||||
|
||||
CPU Cores
|
||||
---------
|
||||
I've spent lots of time coming up with techniques to optimize the CPU
|
||||
cores. Some of the most important: execute multiple instructions during
|
||||
an emulation call, keep state in local variables to allow register
|
||||
assignment, optimize state representation for most common instructions,
|
||||
defer status flag calculation until actually needed, read program code
|
||||
directly without a call to the memory read function, always pre-fetch
|
||||
the operand byte before decoding instruction, and emulate instructions
|
||||
using common blocks of code.
|
||||
|
||||
I've successfully used Nes_Cpu in a fairly complete NES emulator, and
|
||||
I'd like to make all the CPU emulators suitable for use in emulators. It
|
||||
seems a waste for them to be used only for the small amount of emulation
|
||||
necessary for game music files.
|
||||
|
||||
I debugged the CPU cores by writing a test shell that ran them in
|
||||
parallel with other CPU cores and compared all memory accesses and
|
||||
processor states at each step. This provided good value at little cost.
|
||||
|
||||
The CPU mapping page size is adjustable to allow the best tradeoff
|
||||
between memory/cache usage and handler granularity. The interface allows
|
||||
code to be somewhat independent of the page size.
|
||||
|
||||
I optimize program memory accesses to direct reads rather than calls to
|
||||
the memory read function. My assumption is that it would be difficult to
|
||||
get useful code out of hardware I/O addresses, so no software will
|
||||
intentionally execute out of I/O space. Since the page size can be
|
||||
changed easily, most program memory mapping schemes can be accommodated.
|
||||
This greatly reduces memory access function calls.
|
||||
|
||||
Game_Music_Emu 0.6.0 Design
|
||||
---------------------------
|
||||
This might be slightly out-of-date at times, but will be a big help in
|
||||
understanding the library implementation.
|
||||
|
||||
|
||||
Architecture
|
||||
------------
|
||||
The library is essentially a bunch of independent game music file
|
||||
emulators unified with a common interface.
|
||||
|
||||
Gme_File and Music_Emu provide a common interface to the emulators. The
|
||||
virtual functions are protected rather than public to allow pre- and
|
||||
post-processing of arguments and data in one place. This allows the
|
||||
emulator classes to assume that everything is set up properly when
|
||||
starting a track and playing samples.
|
||||
|
||||
All file input is done with the Data_Reader interface. Many derived
|
||||
classes are present, for the usual disk-based file and block of memory,
|
||||
to specialized adaptors for things like reading a subset of data or
|
||||
combining a block of memory with a Data_Reader to the remaining data.
|
||||
This makes the library much more flexible with regard to the source of
|
||||
game music file data. I still added a specialized load_mem() function to
|
||||
have the emulator keep a pointer to data already read in memory, for
|
||||
those formats whose files can be absolutely huge (GYM, some VGMs). This
|
||||
is important if for some reason the caller must load the data ahead of
|
||||
time, but doesn't want the emulator needlessly making a copy.
|
||||
|
||||
Since silence checking and fading are relatively complex, they are kept
|
||||
separate from basic file loading and track information, which are
|
||||
handled in the base class Gme_File. My original intent was to use
|
||||
Gme_File as the common base class for full emulators and track
|
||||
information-only readers, but implementing the C interface was much
|
||||
simpler if both derived from Music_Emu. User C++ code can still benefit
|
||||
from static checking by using Gme_File where only track information will
|
||||
be accessed.
|
||||
|
||||
Each emulator generally has three components: main emulator, CPU
|
||||
emulator, and sound chip emulator(s). Each component has minimal
|
||||
coupling, so use in a full emulator or stand alone is fairly easy. This
|
||||
modularity really helps reduce complexity. Blip_Buffer helps a lot with
|
||||
simplifying the APU interfaces and implementation.
|
||||
|
||||
The "classic" emulators derive from Classic_Emu, which handles
|
||||
Blip_Buffer filling and multiple channels. It uses Multi_Buffer for
|
||||
output, allowing you to derive a custom buffer that could output each
|
||||
voice to a separate sound channel and do different processing on each.
|
||||
At some point I'm going to implement a better Effects_Buffer that allows
|
||||
individual control of every channel.
|
||||
|
||||
In implementing the C interface, I wanted a way to specify an emulator
|
||||
type that didn't require linking in all the emulators. For each emulator
|
||||
type there is a global object with pointers to functions to create the
|
||||
emulator or a track information reader. The emulator type is thus a
|
||||
pointer to this, which conveniently allows for a NULL value. The user
|
||||
referencing this emulator type object is what ultimately links the
|
||||
emulator in (unless new Foo_Emu is used in C++, of course). This type
|
||||
also serves as a useful substitute for RTTI on older C++ compilers.
|
||||
|
||||
Addendum: I have since added gme_type_list(), which causes all listed
|
||||
emulators to be linked in. To avoid this, I make the list itself
|
||||
editable in blargg_config.h. Having a built-in list allows
|
||||
gme_load_file() to take a path and give back an emulator with the file
|
||||
loaded, which is extremely useful for new users.
|
||||
|
||||
|
||||
Interface conventions
|
||||
----------------------
|
||||
If a function retains a pointer to or replaces the value of an object
|
||||
passed, it takes a pointer so that it will be clear in the caller's
|
||||
source code that care is required.
|
||||
|
||||
Multi-word names have an underscore '_' separator between individual
|
||||
words.
|
||||
|
||||
Functions are named with lowercase words. Functions which perform an
|
||||
action with side-effects are named with a verb phrase (i.e. load, move,
|
||||
run). Functions which return the value of a piece of state are named
|
||||
using a noun phrase (i.e. loaded, moved, running).
|
||||
|
||||
Classes are named with capitalized words. Only the first letter of an
|
||||
acronym is capitalized. Class names are nouns, sometimes suggestive of
|
||||
what they do (i.e. File_Scanner).
|
||||
|
||||
Structure, enumeration, and typedefs to these and built-in types are
|
||||
named using lowercase words with a _t suffix.
|
||||
|
||||
Macros are named with all-uppercase words.
|
||||
|
||||
Internal names which can't be hidden due to technical reasons have an
|
||||
underscore '_' suffix.
|
||||
|
||||
|
||||
Managing Complexity
|
||||
-------------------
|
||||
Complexity has been a factor in most library decisions. Many features
|
||||
have been passed by due to the complexity they would add. Once
|
||||
complexity goes past a certain level, it mentally grasping the library
|
||||
in its entirety, at which point more defects will occur and be hard to
|
||||
find.
|
||||
|
||||
I chose 16-bit signed samples because it seems to be the most common
|
||||
format. Supporting multiple formats would add too much complexity to be
|
||||
worth it. Other formats can be obtained via conversion.
|
||||
|
||||
I've kept interfaces fairly lean, leaving many possible features
|
||||
untapped but easy to add if necessary. For example the classic emulators
|
||||
could have volume and frequency equalization adjusted separately for
|
||||
each channel, since they each have an associated Blip_Synth.
|
||||
|
||||
Source files of 400 lines or less seem to be the best size to limit
|
||||
complexity. In a few cases there is no reasonable way to split longer
|
||||
files, or there is benefit from having the source together in one file.
|
||||
|
||||
|
||||
Preventing Bugs
|
||||
---------------
|
||||
I've done many things to reduce the opportunity for defects. A general
|
||||
principle is to write code so that defects will be as visible as
|
||||
possible. I've used several techniques to achieve this.
|
||||
|
||||
I put assertions at key points where defects seem likely or where
|
||||
corruption due to a defect is likely to be visible. I've also put
|
||||
assertions where violations of the interface are likely. In emulators
|
||||
where I am unsure of exact hardware operation in a particular case, I
|
||||
output a debug-only message noting that this has occurred; many times I
|
||||
haven't implemented a hardware feature because nothing uses it. I've
|
||||
made code brittle where there is no clear reason flexibility; code
|
||||
written to handle every possibility sacrifices quality and reliability
|
||||
to handle vaguely defined situations.
|
||||
|
||||
|
||||
Flexibility through indirection
|
||||
-------------------------------
|
||||
I've tried to allow the most flexibility of modules by using indirection
|
||||
to allow extension by the user. This keeps each module simpler and more
|
||||
focused on its unique task.
|
||||
|
||||
The classic emulators use Multi_Buffer, which potentially allows a
|
||||
separate Blip_Buffer for each channel. This keeps emulators free of
|
||||
typical code to allow output in mono, stereo, panning, etc.
|
||||
|
||||
All emulators use a reader object to access file data, allowing it to be
|
||||
stored in a regular file, compressed archive, memory, or generated
|
||||
on-the-fly. Again, the library can be kept free of the particulars of
|
||||
file access and changes required to support new formats.
|
||||
|
||||
|
||||
Emulators in general
|
||||
--------------------
|
||||
When I wrote the first NES sound emulator, I stored most of the state in
|
||||
an emulator-specific format, with significant redundancy. In the
|
||||
register write function I decoded everything into named variables. I
|
||||
became tired of the verbosity and wanted to more closely model the
|
||||
hardware, so I moved to a style of storing the last written value to
|
||||
each register, along with as little other state as possible, mostly the
|
||||
internal hardware registers. While this involves slightly more
|
||||
recalculation, in most cases the emulation code is of comparable size.
|
||||
It also makes state save/restore (for use in a full emulator) much
|
||||
simpler. Finally, it makes debugging easier since the hardware registers
|
||||
used in emulation are obvious.
|
||||
|
||||
|
||||
CPU Cores
|
||||
---------
|
||||
I've spent lots of time coming up with techniques to optimize the CPU
|
||||
cores. Some of the most important: execute multiple instructions during
|
||||
an emulation call, keep state in local variables to allow register
|
||||
assignment, optimize state representation for most common instructions,
|
||||
defer status flag calculation until actually needed, read program code
|
||||
directly without a call to the memory read function, always pre-fetch
|
||||
the operand byte before decoding instruction, and emulate instructions
|
||||
using common blocks of code.
|
||||
|
||||
I've successfully used Nes_Cpu in a fairly complete NES emulator, and
|
||||
I'd like to make all the CPU emulators suitable for use in emulators. It
|
||||
seems a waste for them to be used only for the small amount of emulation
|
||||
necessary for game music files.
|
||||
|
||||
I debugged the CPU cores by writing a test shell that ran them in
|
||||
parallel with other CPU cores and compared all memory accesses and
|
||||
processor states at each step. This provided good value at little cost.
|
||||
|
||||
The CPU mapping page size is adjustable to allow the best tradeoff
|
||||
between memory/cache usage and handler granularity. The interface allows
|
||||
code to be somewhat independent of the page size.
|
||||
|
||||
I optimize program memory accesses to direct reads rather than calls to
|
||||
the memory read function. My assumption is that it would be difficult to
|
||||
get useful code out of hardware I/O addresses, so no software will
|
||||
intentionally execute out of I/O space. Since the page size can be
|
||||
changed easily, most program memory mapping schemes can be accommodated.
|
||||
This greatly reduces memory access function calls.
|
||||
|
||||
+376
-376
@@ -1,376 +1,376 @@
|
||||
Game_Music_Emu 0.6.2
|
||||
--------------------
|
||||
Author : Shay Green <gblargg@gmail.com>
|
||||
Maintainer : Michael Pyne <mpyne@purinchu.net>
|
||||
Website : https://bitbucket.org/mpyne/game-music-emu/
|
||||
Source : https://bitbucket.org/mpyne/game-music-emu/
|
||||
License : GNU Lesser General Public License (LGPL), see LICENSE.txt
|
||||
|
||||
Contents
|
||||
--------
|
||||
* Overview
|
||||
* Error handling
|
||||
* Emulator types
|
||||
* M3U playlist support
|
||||
* Information fields
|
||||
* Track length
|
||||
* Loading file data
|
||||
* Sound parameters
|
||||
* VGM/GYM YM2413 & YM2612 FM sound
|
||||
* Modular construction
|
||||
* Obscure features
|
||||
* Solving problems
|
||||
* Thanks
|
||||
|
||||
|
||||
Overview
|
||||
--------
|
||||
This library can open game music files, play tracks, and read game and
|
||||
track information tags. To play a game music file, do the following:
|
||||
|
||||
* Open the file with gme_open_file()
|
||||
* Start a track with gme_start_track();
|
||||
* Generate samples as needed with gme_play()
|
||||
* Play samples through speaker using your operating system
|
||||
* Delete emulator when done with gme_delete()
|
||||
|
||||
Your code must arrange for the generated samples to be played through
|
||||
the computer's speaker using whatever method your operating system
|
||||
requires.
|
||||
|
||||
There are many additional features available; you can:
|
||||
|
||||
* Determine of the type of a music file without opening it with
|
||||
gme_identify_*()
|
||||
* Load just the file's information tags with gme_info_only
|
||||
* Load from a block of memory rather than a file with gme_load_data()
|
||||
* Arrange for a fade-out at a particular time with gme_set_fade
|
||||
* Find when a track has ended with gme_track_ended()
|
||||
* Seek to a new time in the track with gme_seek()
|
||||
* Load an extended m3u playlist with gme_load_m3u()
|
||||
* Get a list of the voices (channels) and mute them individually with
|
||||
gme_voice_names() and gme_mute_voice()
|
||||
* Change the playback tempo without affecting pitch with gme_set_tempo()
|
||||
* Adjust treble/bass equalization with gme_set_equalizer()
|
||||
* Associate your own data with an emulator and later get it back with
|
||||
gme_set_user_data()
|
||||
* Register a function of yours to be called back when the emulator is
|
||||
deleted with gme_set_user_cleanup()
|
||||
|
||||
Refer to gme.h for a comprehensive summary of features.
|
||||
|
||||
|
||||
Error handling
|
||||
--------------
|
||||
Functions which can fail have a return type of gme_err_t, which is a
|
||||
pointer to an error string (const char*). If a function is successful it
|
||||
returns NULL. Errors that you can easily avoid are checked with debug
|
||||
assertions; gme_err_t return values are only used for genuine run-time
|
||||
errors that can't be easily predicted in advance (out of memory, I/O
|
||||
errors, incompatible file data). Your code should check all error
|
||||
values.
|
||||
|
||||
When loading a music file in the wrong emulator or trying to load a
|
||||
non-music file, gme_wrong_file_type is returned. You can check for this
|
||||
error in C++ like this:
|
||||
|
||||
gme_err_t err = gme_open_file( path, &emu );
|
||||
if ( err == gme_wrong_file_type )
|
||||
...
|
||||
|
||||
To check for minor problems, call gme_warning() to get a string
|
||||
describing the last warning. Your player should allow the user some way
|
||||
of knowing when this is the case, since these minor errors could affect
|
||||
playback. Without this information the user can't solve problems as
|
||||
well. When playing a track, gme_warning() returns minor playback-related
|
||||
problems (major playback problems end the track immediately and set the
|
||||
warning string).
|
||||
|
||||
|
||||
Emulator types
|
||||
--------------
|
||||
The library includes several game music emulators that each support a
|
||||
different file type. Each is identified by a gme_type_t constant defined
|
||||
in gme.h, for example gme_nsf_emu is for the NSF emulator. If you use
|
||||
gme_open_file() or gme_open_data(), the library does the work of
|
||||
determining the file type and creating an appropriate emulator. If you
|
||||
want more control over this process, read on.
|
||||
|
||||
There are two basic ways to identify a game music file's type: look at
|
||||
its file extension, or read the header data. The library includes
|
||||
functions to help with both methods. The first is preferable because it
|
||||
is fast and the most common way to identify files. Sometimes the
|
||||
extension is lost or wrong, so the header must be read.
|
||||
|
||||
Use gme_identify_extension() to find the correct game music type based
|
||||
on a filename. To identify a file based on its extension and header
|
||||
contents, use gme_identify_file(). If you read the header data yourself,
|
||||
use gme_identify_header().
|
||||
|
||||
If you want to remove support for some music types to reduce your
|
||||
executable size, edit GME_TYPE_LIST in blargg_config.h. For example, to
|
||||
support just NSF and GBS, use this:
|
||||
|
||||
#define GME_TYPE_LIST \
|
||||
gme_nsf_type,\
|
||||
gme_gbs_type
|
||||
|
||||
|
||||
M3U playlist support
|
||||
--------------------
|
||||
The library supports playlists in an extended m3u format with
|
||||
gme_load_m3u() to give track names and times to multi-song formats: AY,
|
||||
GBS, HES, KSS, NSF, NSFE, and SAP. Some aspects of the file format
|
||||
itself is not well-defined so some m3u files won't work properly
|
||||
(particularly those provided with KSS files). Only m3u files referencing
|
||||
a single file are supported; your code must handle m3u files covering
|
||||
more than one game music file, though it can use the built-in m3u
|
||||
parsing provided by the library.
|
||||
|
||||
|
||||
Information fields
|
||||
------------------
|
||||
Support is provided for the various text fields and length information
|
||||
in a file with gme_track_info(). If you just need track information for
|
||||
a file (for example, building a playlist), use gme_new_info() in place
|
||||
of gme_new_emu(), load the file normally, then you can access the track
|
||||
count and info, but nothing else.
|
||||
|
||||
M3U VGM GYM SPC SAP NSFE NSF AY GBS HES KSS
|
||||
-------------------------------------------------------
|
||||
Track Count | * * * * * * * * *
|
||||
|
|
||||
System | * * * * * * * * * *
|
||||
|
|
||||
Game | * * * * * * *
|
||||
|
|
||||
Song | * * * * * * *
|
||||
|
|
||||
Author | * * * * * * * *
|
||||
|
|
||||
Copyright | * * * * * * * *
|
||||
|
|
||||
Comment | * * * *
|
||||
|
|
||||
Dumper | * * * *
|
||||
|
|
||||
Length | * * * * * *
|
||||
|
|
||||
Intro Length| * * *
|
||||
|
|
||||
Loop Length | * * *
|
||||
|
||||
As listed above, the HES and KSS file formats don't include a track
|
||||
count, and tracks are often scattered over the 0-255 range, so an m3u
|
||||
playlist for these is a must.
|
||||
|
||||
Unavailable text fields are set to an empty string and times to -1. Your
|
||||
code should be prepared for any combination of available and unavailable
|
||||
fields, as a particular music file might not use all of the supported
|
||||
fields listed above.
|
||||
|
||||
Currently text fields are truncated to 255 characters. Obscure fields of
|
||||
some formats are not currently decoded; contact me if you want one
|
||||
added.
|
||||
|
||||
|
||||
Track length
|
||||
------------
|
||||
The library leaves it up to you as to when to stop playing a track. You
|
||||
can ask for available length information and then tell the library what
|
||||
time it should start fading the track with gme_set_fade(). By default it
|
||||
also continually checks for 6 or more seconds of silence to mark the end
|
||||
of a track. Here is a reasonable algorithm you can use to decide how
|
||||
long to play a track:
|
||||
|
||||
* If the track length is > 0, use it
|
||||
* If the loop length > 0, play for intro + loop * 2
|
||||
* Otherwise, default to 2.5 minutes (150000 msec)
|
||||
|
||||
If you want to play a track longer than normal, be sure the loop length
|
||||
isn't zero. See Music_Player.cpp around line 145 for example code.
|
||||
|
||||
By default, the library skips silence at the beginning of a track. It
|
||||
also continually checks for the end of a non-looping track by watching
|
||||
for 6 seconds of unbroken silence. When doing this is scans *ahead* by
|
||||
several seconds so it can report the end of the track after only one
|
||||
second of silence has actually played. This feature can be disabled with
|
||||
gme_ignore_silence().
|
||||
|
||||
|
||||
Loading file data
|
||||
-----------------
|
||||
The library allows file data to be loaded in many different ways. All
|
||||
load functions return an error which you should check. The following
|
||||
examples assume these variables:
|
||||
|
||||
Music_Emu* emu;
|
||||
gme_err_t error;
|
||||
|
||||
If you're letting the library determine a file's type, you can use
|
||||
either gme_open_file() or gme_open_data():
|
||||
|
||||
error = gme_open_file( pathname, &emu );
|
||||
error = gme_open_data( pointer, size, &emu );
|
||||
|
||||
If you're manually determining file type and using used gme_new_emu() to
|
||||
create an emulator, you can use the following methods of loading:
|
||||
|
||||
* From a block of memory:
|
||||
|
||||
error = gme_load_data( emu, pointer, size );
|
||||
|
||||
* Have library call your function to read data:
|
||||
|
||||
gme_err_t my_read( void* my_data, void* out, long count )
|
||||
{
|
||||
// code that reads 'count' bytes into 'out' buffer
|
||||
// and return 0 if no error
|
||||
}
|
||||
|
||||
error = gme_load_custom( emu, my_read, file_size, my_data );
|
||||
|
||||
|
||||
Sound parameters
|
||||
----------------
|
||||
All emulators support an arbitrary output sampling rate. A rate of 44100
|
||||
Hz should work well on most systems. Since band-limited synthesis is
|
||||
used, a sampling rate above 48000 Hz is not necessary and will actually
|
||||
reduce sound quality and performance.
|
||||
|
||||
All emulators also support adjustable gain, mainly for the purpose of
|
||||
getting consistent volume between different music formats and avoiding
|
||||
excessive modulation. The gain can only be set *before* setting the
|
||||
emulator's sampling rate, so it's not useful as a general volume
|
||||
control. The default gains of emulators are set so that they give
|
||||
generally similar volumes, though some soundtracks are significantly
|
||||
louder or quieter than normal.
|
||||
|
||||
Some emulators support adjustable treble and bass frequency equalization
|
||||
(AY, GBS, HES, KSS, NSF, NSFE, SAP, VGM) using set_equalizer().
|
||||
Parameters are specified using gme_equalizer_t eq = { treble_dB,
|
||||
bass_freq }. Treble_dB sets the treble level (in dB), where 0.0 dB gives
|
||||
normal treble; -200.0 dB is quite muffled, and 5.0 dB emphasizes treble
|
||||
for an extra crisp sound. Bass_freq sets the frequency where bass
|
||||
response starts to diminish; 15 Hz is normal, 0 Hz gives maximum bass,
|
||||
and 15000 Hz removes all bass. For example, the following makes the
|
||||
sound extra-crisp but lacking bass:
|
||||
|
||||
gme_equalizer_t eq = { 5.0, 1000 };
|
||||
gme_set_equalizer( music_emu, &eq );
|
||||
|
||||
Each emulator's equalization defaults to approximate the particular
|
||||
console's sound quality; this default can be determined by calling
|
||||
equalizer() just after creating the emulator. The Music_Emu::tv_eq
|
||||
profile gives sound as if coming from a TV speaker, and some emulators
|
||||
include other profiles for different versions of the system. For
|
||||
example, to use Famicom sound equalization with the NSF emulator, do the
|
||||
following:
|
||||
|
||||
music_emu->set_equalizer( Nsf_Emu::famicom_eq );
|
||||
|
||||
|
||||
VGM/GYM YM2413 & YM2612 FM sound
|
||||
--------------------------------
|
||||
The library plays Sega Genesis/Mega Drive music using a YM2612 FM sound
|
||||
chip emulator based on the Gens project. Because this has some
|
||||
inaccuracies, other YM2612 emulators can be used in its place by
|
||||
re-implementing the interface in YM2612_Emu.h. Available on my website
|
||||
is a modified version of MAME's YM2612 emulator, which sounds better in
|
||||
some ways and whose author is still making improvements.
|
||||
|
||||
VGM music files using the YM2413 FM sound chip are also supported, but a
|
||||
YM2413 emulator isn't included with the library due to technical
|
||||
reasons. I have put one of the available YM2413 emulators on my website
|
||||
that can be used directly.
|
||||
|
||||
|
||||
Modular construction
|
||||
--------------------
|
||||
The library is made of many fairly independent modules. If you're using
|
||||
only one music file emulator, you can eliminate many of the library
|
||||
sources from your program. Refer to the files list in readme.txt to get
|
||||
a general idea of what can be removed, and be sure to edit GME_TYPE_LIST
|
||||
(see "Emulator types" above). Post to the forum if you'd like me to put
|
||||
together a smaller version for a particular use, as this only takes me a
|
||||
few minutes to do.
|
||||
|
||||
If you want to use one of the individual sound chip emulators (or CPU
|
||||
cores) in your own console emulator, first check the libraries page on
|
||||
my website since I have released several of them as stand alone
|
||||
libraries with included documentation and examples on their use. If you
|
||||
don't find it as a standalone library, contact me and I'll consider
|
||||
separating it.
|
||||
|
||||
The "classic" sound chips use my Blip_Buffer library, which greatly
|
||||
simplifies their implementation and efficiently handles band-limited
|
||||
synthesis. It is also available as a stand alone library with
|
||||
documentation and many examples.
|
||||
|
||||
|
||||
Obscure features
|
||||
----------------
|
||||
The library's flexibility allows many possibilities. Contact me if you
|
||||
want help implementing ideas or removing limitations.
|
||||
|
||||
* Uses no global/static variables, allowing multiple instances of any
|
||||
emulator. This is useful in a music player if you want to allow
|
||||
simultaneous recording or scanning of other tracks while one is already
|
||||
playing. This will also be useful if your platform disallows global
|
||||
data.
|
||||
|
||||
* Emulators that support a custom sound buffer can have *every* voice
|
||||
routed to a different Blip_Buffer, allowing custom processing on each
|
||||
voice. For example you could record a Game Boy track as a 4-channel
|
||||
sound file.
|
||||
|
||||
* Defining BLIP_BUFFER_FAST uses lower quality, less-multiply-intensive
|
||||
synthesis on "classic" emulators, which might help on some really old
|
||||
processors. This significantly lowers sound quality and prevents treble
|
||||
equalization. Try this if your platform's processor isn't fast enough
|
||||
for normal quality. Even on my ten-year-old 400 MHz Mac, this reduces
|
||||
processor usage at most by about 0.6% (from 4% to 3.4%), hardly worth
|
||||
the quality loss.
|
||||
|
||||
|
||||
Solving problems
|
||||
----------------
|
||||
If you're having problems, try the following:
|
||||
|
||||
* If you're getting garbled sound, try this simple siren generator in
|
||||
place of your call to play(). This will quickly tell whether the problem
|
||||
is in the library or in your code.
|
||||
|
||||
static void play_siren( long count, short* out )
|
||||
{
|
||||
static double a, a2;
|
||||
while ( count-- )
|
||||
*out++ = 0x2000 * sin( a += .1 + .05*sin( a2+=.00005 ) );
|
||||
}
|
||||
|
||||
* Enable debugging support in your environment. This enables assertions
|
||||
and other run-time checks.
|
||||
|
||||
* Turn the compiler's optimizer is off. Sometimes an optimizer generates
|
||||
bad code.
|
||||
|
||||
* If multiple threads are being used, ensure that only one at a time is
|
||||
accessing a given set of objects from the library. This library is not
|
||||
in general thread-safe, though independent objects can be used in
|
||||
separate threads.
|
||||
|
||||
* If all else fails, see if the demos work.
|
||||
|
||||
|
||||
Thanks
|
||||
------
|
||||
Big thanks to Chris Moeller (kode54) for help with library testing and
|
||||
feedback, for maintaining the Foobar2000 plugin foo_gep based on it, and
|
||||
for original work on openspc++ that was used when developing Spc_Emu.
|
||||
Brad Martin's excellent OpenSPC SNES DSP emulator worked well from the
|
||||
start. Also thanks to Richard Bannister, Mahendra Tallur, Shazz,
|
||||
nenolod, theHobbit, Johan Samuelsson, and nes6502 for testing, using,
|
||||
and giving feedback for the library in their respective game music
|
||||
players. More recently, Lucas Paul and Michael Pyne have helped nudge the
|
||||
library into a public repository and get its interface more stable for use
|
||||
in shared libraries.
|
||||
Game_Music_Emu 0.6.2
|
||||
--------------------
|
||||
Author : Shay Green <gblargg@gmail.com>
|
||||
Maintainer : Michael Pyne <mpyne@purinchu.net>
|
||||
Website : https://bitbucket.org/mpyne/game-music-emu/
|
||||
Source : https://bitbucket.org/mpyne/game-music-emu/
|
||||
License : GNU Lesser General Public License (LGPL), see LICENSE.txt
|
||||
|
||||
Contents
|
||||
--------
|
||||
* Overview
|
||||
* Error handling
|
||||
* Emulator types
|
||||
* M3U playlist support
|
||||
* Information fields
|
||||
* Track length
|
||||
* Loading file data
|
||||
* Sound parameters
|
||||
* VGM/GYM YM2413 & YM2612 FM sound
|
||||
* Modular construction
|
||||
* Obscure features
|
||||
* Solving problems
|
||||
* Thanks
|
||||
|
||||
|
||||
Overview
|
||||
--------
|
||||
This library can open game music files, play tracks, and read game and
|
||||
track information tags. To play a game music file, do the following:
|
||||
|
||||
* Open the file with gme_open_file()
|
||||
* Start a track with gme_start_track();
|
||||
* Generate samples as needed with gme_play()
|
||||
* Play samples through speaker using your operating system
|
||||
* Delete emulator when done with gme_delete()
|
||||
|
||||
Your code must arrange for the generated samples to be played through
|
||||
the computer's speaker using whatever method your operating system
|
||||
requires.
|
||||
|
||||
There are many additional features available; you can:
|
||||
|
||||
* Determine of the type of a music file without opening it with
|
||||
gme_identify_*()
|
||||
* Load just the file's information tags with gme_info_only
|
||||
* Load from a block of memory rather than a file with gme_load_data()
|
||||
* Arrange for a fade-out at a particular time with gme_set_fade
|
||||
* Find when a track has ended with gme_track_ended()
|
||||
* Seek to a new time in the track with gme_seek()
|
||||
* Load an extended m3u playlist with gme_load_m3u()
|
||||
* Get a list of the voices (channels) and mute them individually with
|
||||
gme_voice_names() and gme_mute_voice()
|
||||
* Change the playback tempo without affecting pitch with gme_set_tempo()
|
||||
* Adjust treble/bass equalization with gme_set_equalizer()
|
||||
* Associate your own data with an emulator and later get it back with
|
||||
gme_set_user_data()
|
||||
* Register a function of yours to be called back when the emulator is
|
||||
deleted with gme_set_user_cleanup()
|
||||
|
||||
Refer to gme.h for a comprehensive summary of features.
|
||||
|
||||
|
||||
Error handling
|
||||
--------------
|
||||
Functions which can fail have a return type of gme_err_t, which is a
|
||||
pointer to an error string (const char*). If a function is successful it
|
||||
returns NULL. Errors that you can easily avoid are checked with debug
|
||||
assertions; gme_err_t return values are only used for genuine run-time
|
||||
errors that can't be easily predicted in advance (out of memory, I/O
|
||||
errors, incompatible file data). Your code should check all error
|
||||
values.
|
||||
|
||||
When loading a music file in the wrong emulator or trying to load a
|
||||
non-music file, gme_wrong_file_type is returned. You can check for this
|
||||
error in C++ like this:
|
||||
|
||||
gme_err_t err = gme_open_file( path, &emu );
|
||||
if ( err == gme_wrong_file_type )
|
||||
...
|
||||
|
||||
To check for minor problems, call gme_warning() to get a string
|
||||
describing the last warning. Your player should allow the user some way
|
||||
of knowing when this is the case, since these minor errors could affect
|
||||
playback. Without this information the user can't solve problems as
|
||||
well. When playing a track, gme_warning() returns minor playback-related
|
||||
problems (major playback problems end the track immediately and set the
|
||||
warning string).
|
||||
|
||||
|
||||
Emulator types
|
||||
--------------
|
||||
The library includes several game music emulators that each support a
|
||||
different file type. Each is identified by a gme_type_t constant defined
|
||||
in gme.h, for example gme_nsf_emu is for the NSF emulator. If you use
|
||||
gme_open_file() or gme_open_data(), the library does the work of
|
||||
determining the file type and creating an appropriate emulator. If you
|
||||
want more control over this process, read on.
|
||||
|
||||
There are two basic ways to identify a game music file's type: look at
|
||||
its file extension, or read the header data. The library includes
|
||||
functions to help with both methods. The first is preferable because it
|
||||
is fast and the most common way to identify files. Sometimes the
|
||||
extension is lost or wrong, so the header must be read.
|
||||
|
||||
Use gme_identify_extension() to find the correct game music type based
|
||||
on a filename. To identify a file based on its extension and header
|
||||
contents, use gme_identify_file(). If you read the header data yourself,
|
||||
use gme_identify_header().
|
||||
|
||||
If you want to remove support for some music types to reduce your
|
||||
executable size, edit GME_TYPE_LIST in blargg_config.h. For example, to
|
||||
support just NSF and GBS, use this:
|
||||
|
||||
#define GME_TYPE_LIST \
|
||||
gme_nsf_type,\
|
||||
gme_gbs_type
|
||||
|
||||
|
||||
M3U playlist support
|
||||
--------------------
|
||||
The library supports playlists in an extended m3u format with
|
||||
gme_load_m3u() to give track names and times to multi-song formats: AY,
|
||||
GBS, HES, KSS, NSF, NSFE, and SAP. Some aspects of the file format
|
||||
itself is not well-defined so some m3u files won't work properly
|
||||
(particularly those provided with KSS files). Only m3u files referencing
|
||||
a single file are supported; your code must handle m3u files covering
|
||||
more than one game music file, though it can use the built-in m3u
|
||||
parsing provided by the library.
|
||||
|
||||
|
||||
Information fields
|
||||
------------------
|
||||
Support is provided for the various text fields and length information
|
||||
in a file with gme_track_info(). If you just need track information for
|
||||
a file (for example, building a playlist), use gme_new_info() in place
|
||||
of gme_new_emu(), load the file normally, then you can access the track
|
||||
count and info, but nothing else.
|
||||
|
||||
M3U VGM GYM SPC SAP NSFE NSF AY GBS HES KSS
|
||||
-------------------------------------------------------
|
||||
Track Count | * * * * * * * * *
|
||||
|
|
||||
System | * * * * * * * * * *
|
||||
|
|
||||
Game | * * * * * * *
|
||||
|
|
||||
Song | * * * * * * *
|
||||
|
|
||||
Author | * * * * * * * *
|
||||
|
|
||||
Copyright | * * * * * * * *
|
||||
|
|
||||
Comment | * * * *
|
||||
|
|
||||
Dumper | * * * *
|
||||
|
|
||||
Length | * * * * * *
|
||||
|
|
||||
Intro Length| * * *
|
||||
|
|
||||
Loop Length | * * *
|
||||
|
||||
As listed above, the HES and KSS file formats don't include a track
|
||||
count, and tracks are often scattered over the 0-255 range, so an m3u
|
||||
playlist for these is a must.
|
||||
|
||||
Unavailable text fields are set to an empty string and times to -1. Your
|
||||
code should be prepared for any combination of available and unavailable
|
||||
fields, as a particular music file might not use all of the supported
|
||||
fields listed above.
|
||||
|
||||
Currently text fields are truncated to 255 characters. Obscure fields of
|
||||
some formats are not currently decoded; contact me if you want one
|
||||
added.
|
||||
|
||||
|
||||
Track length
|
||||
------------
|
||||
The library leaves it up to you as to when to stop playing a track. You
|
||||
can ask for available length information and then tell the library what
|
||||
time it should start fading the track with gme_set_fade(). By default it
|
||||
also continually checks for 6 or more seconds of silence to mark the end
|
||||
of a track. Here is a reasonable algorithm you can use to decide how
|
||||
long to play a track:
|
||||
|
||||
* If the track length is > 0, use it
|
||||
* If the loop length > 0, play for intro + loop * 2
|
||||
* Otherwise, default to 2.5 minutes (150000 msec)
|
||||
|
||||
If you want to play a track longer than normal, be sure the loop length
|
||||
isn't zero. See Music_Player.cpp around line 145 for example code.
|
||||
|
||||
By default, the library skips silence at the beginning of a track. It
|
||||
also continually checks for the end of a non-looping track by watching
|
||||
for 6 seconds of unbroken silence. When doing this is scans *ahead* by
|
||||
several seconds so it can report the end of the track after only one
|
||||
second of silence has actually played. This feature can be disabled with
|
||||
gme_ignore_silence().
|
||||
|
||||
|
||||
Loading file data
|
||||
-----------------
|
||||
The library allows file data to be loaded in many different ways. All
|
||||
load functions return an error which you should check. The following
|
||||
examples assume these variables:
|
||||
|
||||
Music_Emu* emu;
|
||||
gme_err_t error;
|
||||
|
||||
If you're letting the library determine a file's type, you can use
|
||||
either gme_open_file() or gme_open_data():
|
||||
|
||||
error = gme_open_file( pathname, &emu );
|
||||
error = gme_open_data( pointer, size, &emu );
|
||||
|
||||
If you're manually determining file type and using used gme_new_emu() to
|
||||
create an emulator, you can use the following methods of loading:
|
||||
|
||||
* From a block of memory:
|
||||
|
||||
error = gme_load_data( emu, pointer, size );
|
||||
|
||||
* Have library call your function to read data:
|
||||
|
||||
gme_err_t my_read( void* my_data, void* out, long count )
|
||||
{
|
||||
// code that reads 'count' bytes into 'out' buffer
|
||||
// and return 0 if no error
|
||||
}
|
||||
|
||||
error = gme_load_custom( emu, my_read, file_size, my_data );
|
||||
|
||||
|
||||
Sound parameters
|
||||
----------------
|
||||
All emulators support an arbitrary output sampling rate. A rate of 44100
|
||||
Hz should work well on most systems. Since band-limited synthesis is
|
||||
used, a sampling rate above 48000 Hz is not necessary and will actually
|
||||
reduce sound quality and performance.
|
||||
|
||||
All emulators also support adjustable gain, mainly for the purpose of
|
||||
getting consistent volume between different music formats and avoiding
|
||||
excessive modulation. The gain can only be set *before* setting the
|
||||
emulator's sampling rate, so it's not useful as a general volume
|
||||
control. The default gains of emulators are set so that they give
|
||||
generally similar volumes, though some soundtracks are significantly
|
||||
louder or quieter than normal.
|
||||
|
||||
Some emulators support adjustable treble and bass frequency equalization
|
||||
(AY, GBS, HES, KSS, NSF, NSFE, SAP, VGM) using set_equalizer().
|
||||
Parameters are specified using gme_equalizer_t eq = { treble_dB,
|
||||
bass_freq }. Treble_dB sets the treble level (in dB), where 0.0 dB gives
|
||||
normal treble; -200.0 dB is quite muffled, and 5.0 dB emphasizes treble
|
||||
for an extra crisp sound. Bass_freq sets the frequency where bass
|
||||
response starts to diminish; 15 Hz is normal, 0 Hz gives maximum bass,
|
||||
and 15000 Hz removes all bass. For example, the following makes the
|
||||
sound extra-crisp but lacking bass:
|
||||
|
||||
gme_equalizer_t eq = { 5.0, 1000 };
|
||||
gme_set_equalizer( music_emu, &eq );
|
||||
|
||||
Each emulator's equalization defaults to approximate the particular
|
||||
console's sound quality; this default can be determined by calling
|
||||
equalizer() just after creating the emulator. The Music_Emu::tv_eq
|
||||
profile gives sound as if coming from a TV speaker, and some emulators
|
||||
include other profiles for different versions of the system. For
|
||||
example, to use Famicom sound equalization with the NSF emulator, do the
|
||||
following:
|
||||
|
||||
music_emu->set_equalizer( Nsf_Emu::famicom_eq );
|
||||
|
||||
|
||||
VGM/GYM YM2413 & YM2612 FM sound
|
||||
--------------------------------
|
||||
The library plays Sega Genesis/Mega Drive music using a YM2612 FM sound
|
||||
chip emulator based on the Gens project. Because this has some
|
||||
inaccuracies, other YM2612 emulators can be used in its place by
|
||||
re-implementing the interface in YM2612_Emu.h. Available on my website
|
||||
is a modified version of MAME's YM2612 emulator, which sounds better in
|
||||
some ways and whose author is still making improvements.
|
||||
|
||||
VGM music files using the YM2413 FM sound chip are also supported, but a
|
||||
YM2413 emulator isn't included with the library due to technical
|
||||
reasons. I have put one of the available YM2413 emulators on my website
|
||||
that can be used directly.
|
||||
|
||||
|
||||
Modular construction
|
||||
--------------------
|
||||
The library is made of many fairly independent modules. If you're using
|
||||
only one music file emulator, you can eliminate many of the library
|
||||
sources from your program. Refer to the files list in readme.txt to get
|
||||
a general idea of what can be removed, and be sure to edit GME_TYPE_LIST
|
||||
(see "Emulator types" above). Post to the forum if you'd like me to put
|
||||
together a smaller version for a particular use, as this only takes me a
|
||||
few minutes to do.
|
||||
|
||||
If you want to use one of the individual sound chip emulators (or CPU
|
||||
cores) in your own console emulator, first check the libraries page on
|
||||
my website since I have released several of them as stand alone
|
||||
libraries with included documentation and examples on their use. If you
|
||||
don't find it as a standalone library, contact me and I'll consider
|
||||
separating it.
|
||||
|
||||
The "classic" sound chips use my Blip_Buffer library, which greatly
|
||||
simplifies their implementation and efficiently handles band-limited
|
||||
synthesis. It is also available as a stand alone library with
|
||||
documentation and many examples.
|
||||
|
||||
|
||||
Obscure features
|
||||
----------------
|
||||
The library's flexibility allows many possibilities. Contact me if you
|
||||
want help implementing ideas or removing limitations.
|
||||
|
||||
* Uses no global/static variables, allowing multiple instances of any
|
||||
emulator. This is useful in a music player if you want to allow
|
||||
simultaneous recording or scanning of other tracks while one is already
|
||||
playing. This will also be useful if your platform disallows global
|
||||
data.
|
||||
|
||||
* Emulators that support a custom sound buffer can have *every* voice
|
||||
routed to a different Blip_Buffer, allowing custom processing on each
|
||||
voice. For example you could record a Game Boy track as a 4-channel
|
||||
sound file.
|
||||
|
||||
* Defining BLIP_BUFFER_FAST uses lower quality, less-multiply-intensive
|
||||
synthesis on "classic" emulators, which might help on some really old
|
||||
processors. This significantly lowers sound quality and prevents treble
|
||||
equalization. Try this if your platform's processor isn't fast enough
|
||||
for normal quality. Even on my ten-year-old 400 MHz Mac, this reduces
|
||||
processor usage at most by about 0.6% (from 4% to 3.4%), hardly worth
|
||||
the quality loss.
|
||||
|
||||
|
||||
Solving problems
|
||||
----------------
|
||||
If you're having problems, try the following:
|
||||
|
||||
* If you're getting garbled sound, try this simple siren generator in
|
||||
place of your call to play(). This will quickly tell whether the problem
|
||||
is in the library or in your code.
|
||||
|
||||
static void play_siren( long count, short* out )
|
||||
{
|
||||
static double a, a2;
|
||||
while ( count-- )
|
||||
*out++ = 0x2000 * sin( a += .1 + .05*sin( a2+=.00005 ) );
|
||||
}
|
||||
|
||||
* Enable debugging support in your environment. This enables assertions
|
||||
and other run-time checks.
|
||||
|
||||
* Turn the compiler's optimizer is off. Sometimes an optimizer generates
|
||||
bad code.
|
||||
|
||||
* If multiple threads are being used, ensure that only one at a time is
|
||||
accessing a given set of objects from the library. This library is not
|
||||
in general thread-safe, though independent objects can be used in
|
||||
separate threads.
|
||||
|
||||
* If all else fails, see if the demos work.
|
||||
|
||||
|
||||
Thanks
|
||||
------
|
||||
Big thanks to Chris Moeller (kode54) for help with library testing and
|
||||
feedback, for maintaining the Foobar2000 plugin foo_gep based on it, and
|
||||
for original work on openspc++ that was used when developing Spc_Emu.
|
||||
Brad Martin's excellent OpenSPC SNES DSP emulator worked well from the
|
||||
start. Also thanks to Richard Bannister, Mahendra Tallur, Shazz,
|
||||
nenolod, theHobbit, Johan Samuelsson, and nes6502 for testing, using,
|
||||
and giving feedback for the library in their respective game music
|
||||
players. More recently, Lucas Paul and Michael Pyne have helped nudge the
|
||||
library into a public repository and get its interface more stable for use
|
||||
in shared libraries.
|
||||
@@ -1,89 +0,0 @@
|
||||
/* Included at the beginning of library source files, after all other #include lines.
|
||||
* Sets up helpful macros and services used in my source code. They don't need
|
||||
* module an annoying module prefix on their names since they are defined after
|
||||
* all other #include lines. */
|
||||
|
||||
#ifndef BLARGG_SOURCE_H
|
||||
#define BLARGG_SOURCE_H
|
||||
|
||||
/* If debugging is enabled, abort program if expr is false. Meant for checking
|
||||
* internal state and consistency. A failed assertion indicates a bug in the module.
|
||||
* void assert( bool expr ); */
|
||||
#include <assert.h>
|
||||
|
||||
/* If debugging is enabled and expr is false, abort program. Meant for checking
|
||||
* caller-supplied parameters and operations that are outside the control of the
|
||||
* module. A failed requirement indicates a bug outside the module.
|
||||
* void require( bool expr ); */
|
||||
#undef require
|
||||
#define require( expr ) assert( expr )
|
||||
|
||||
/* Use to provide hints to compiler for optimized code layout in situations where we
|
||||
* can almost always expect a conditional to go one way or the other. Should only be
|
||||
* used in situations where an unexpected branch is truly exceptional though! */
|
||||
#undef likely
|
||||
#undef unlikely
|
||||
#ifdef __GNUC__
|
||||
#define likely( x ) __builtin_expect(x, 1)
|
||||
#define unlikely( x ) __builtin_expect(x, 0)
|
||||
#else
|
||||
#define likely( x ) (x)
|
||||
#define unlikely( x ) (x)
|
||||
#endif
|
||||
|
||||
/* Like printf() except output goes to debug log file. Might be defined to do
|
||||
* nothing (not even evaluate its arguments).
|
||||
* void debug_printf( const char* format, ... ); */
|
||||
#if defined(__cplusplus)
|
||||
static inline void blargg_dprintf_( const char* fmt_str, ... ) { (void) fmt_str; }
|
||||
#undef debug_printf
|
||||
#define debug_printf (1) ? (void) 0 : blargg_dprintf_
|
||||
#endif
|
||||
|
||||
/* If enabled, evaluate expr and if false, make debug log entry with source file
|
||||
* and line. Meant for finding situations that should be examined further, but that
|
||||
* don't indicate a problem. In all cases, execution continues normally. */
|
||||
#undef check
|
||||
#define check( expr ) ((void) 0)
|
||||
|
||||
/* If expr yields error string, return it from current function, otherwise continue. */
|
||||
#undef RETURN_ERR
|
||||
#define RETURN_ERR( expr ) do { \
|
||||
blargg_err_t blargg_return_err_ = (expr); \
|
||||
if ( blargg_return_err_ ) return blargg_return_err_; \
|
||||
} while ( 0 )
|
||||
|
||||
/* If ptr is 0, return out of memory error string. */
|
||||
#undef CHECK_ALLOC
|
||||
#define CHECK_ALLOC( ptr ) do { if ( (ptr) == 0 ) return "Out of memory"; } while ( 0 )
|
||||
|
||||
/* TODO: good idea? bad idea? */
|
||||
#undef byte
|
||||
#define byte byte_
|
||||
typedef unsigned char byte;
|
||||
|
||||
/* Setup compiler defines useful for exporting required public API symbols in gme.cpp */
|
||||
#ifndef BLARGG_EXPORT
|
||||
#if defined (_WIN32)
|
||||
#if defined(BLARGG_BUILD_DLL)
|
||||
#define BLARGG_EXPORT __declspec(dllexport)
|
||||
#else
|
||||
#define BLARGG_EXPORT /* Leave blank: friendly with both static and shared linking */
|
||||
#endif
|
||||
#elif defined (LIBGME_VISIBILITY) && defined(__cplusplus)
|
||||
#define BLARGG_EXPORT __attribute__((visibility ("default")))
|
||||
#else
|
||||
#define BLARGG_EXPORT
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* deprecated */
|
||||
#define BLARGG_CHECK_ALLOC CHECK_ALLOC
|
||||
#define BLARGG_RETURN_ERR RETURN_ERR
|
||||
|
||||
/* BLARGG_SOURCE_BEGIN: If defined, #included, allowing redefition of debug_printf and check */
|
||||
#ifdef BLARGG_SOURCE_BEGIN
|
||||
#include BLARGG_SOURCE_BEGIN
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -1,339 +0,0 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Lesser General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) year name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License.
|
||||
+504
-504
File diff suppressed because it is too large.
Load diff
+231
-231
@@ -1,231 +1,231 @@
|
||||
Game_Music_Emu 0.6.2: Game Music Emulators
|
||||
------------------------------------------
|
||||
Game_Music_Emu is a collection of video game music file emulators that
|
||||
support the following formats and systems:
|
||||
|
||||
AY ZX Spectrum/Amstrad CPC
|
||||
GBS Nintendo Game Boy
|
||||
GYM Sega Genesis/Mega Drive
|
||||
HES NEC TurboGrafx-16/PC Engine
|
||||
KSS MSX Home Computer/other Z80 systems (doesn't support FM sound)
|
||||
NSF/NSFE Nintendo NES/Famicom (with VRC 6, Namco 106, and FME-7 sound)
|
||||
SAP Atari systems using POKEY sound chip
|
||||
SPC Super Nintendo/Super Famicom
|
||||
VGM/VGZ Sega Master System/Mark III, Sega Genesis/Mega Drive,BBC Micro
|
||||
|
||||
Features:
|
||||
* C interface for use in C, C++, and other compatible languages
|
||||
* High emphasis has been placed on making the library very easy to use
|
||||
* One set of common functions work with all emulators the same way
|
||||
* Several code examples, including music player using SDL
|
||||
* Portable code for use on any system with modern or older C++ compilers
|
||||
* Adjustable output sample rate using quality band-limited resampling
|
||||
* Uniform access to text information fields and track timing information
|
||||
* End-of-track fading and automatic look ahead silence detection
|
||||
* Treble/bass and stereo echo for AY/GBS/HES/KSS/NSF/NSFE/SAP/VGM
|
||||
* Tempo can be adjusted and individual voices can be muted while playing
|
||||
* Can read music data from file, memory, or custom reader function/class
|
||||
* Can access track information without having to load into full emulator
|
||||
* M3U track listing support for multi-track formats
|
||||
* Modular design allows elimination of unneeded emulators/features
|
||||
|
||||
This library has been used in game music players for Windows, Linux on
|
||||
several architectures, Mac OS, MorphOS, Xbox, PlayStation Portable,
|
||||
GP2X, and Nintendo DS.
|
||||
|
||||
Author : Shay Green <gblargg@gmail.com>
|
||||
Website: https://bitbucket.org/mpyne/game-music-emu/wiki/Home
|
||||
License: GNU Lesser General Public License (LGPL)
|
||||
|
||||
Current Maintainer: Michael Pyne <mpyne@purinchu.net>
|
||||
|
||||
Getting Started
|
||||
---------------
|
||||
Build a program consisting of demo/basics.c, demo/Wave_Writer.cpp, and
|
||||
all source files in gme/.
|
||||
|
||||
Or, if you have CMake 2.6 or later, execute at a command prompt (from the
|
||||
extracted source directory):
|
||||
|
||||
mkdir build
|
||||
cd build
|
||||
cmake ../ # <-- Pass any needed CMake flags here
|
||||
make # To build the library
|
||||
cd demo
|
||||
make # To build the demo itself
|
||||
|
||||
Be sure "test.nsf" is in the same directory as the demo program. Running it
|
||||
should generate the recording "out.wav".
|
||||
|
||||
You can use "make install" to install the library. To choose where to install
|
||||
the library to, use the CMake argument "-DCMAKE_INSTALL_PREFIX=/usr/local"
|
||||
(and replace /usr/local with the base path you wish to use). Alternately, you
|
||||
can specify the base path to install to when you run "make install" by passing
|
||||
'DESTDIR=/usr/local' on the make install command line (again, replace
|
||||
/usr/local as appropriate).
|
||||
|
||||
To build a static library instead of shared (the default), pass
|
||||
-DBUILD_SHARED_LIBS=OFF to the cmake command when running cmake.
|
||||
|
||||
A slightly more extensive demo application is available in the player/
|
||||
directory. It requires SDL to build.
|
||||
|
||||
Read gme.txt for more information. Post to the discussion forum for
|
||||
assistance.
|
||||
|
||||
Files
|
||||
-----
|
||||
gme.txt General notes about the library
|
||||
changes.txt Changes made since previous releases
|
||||
design.txt Library design notes
|
||||
license.txt GNU Lesser General Public License
|
||||
CMakeLists.txt CMake build rules
|
||||
|
||||
test.nsf Test file for NSF emulator
|
||||
test.m3u Test m3u playlist for features.c demo
|
||||
|
||||
demo/
|
||||
basics.c Records NSF file to wave sound file
|
||||
features.c Demonstrates many additional features
|
||||
Wave_Writer.h WAVE sound file writer used for demo output
|
||||
Wave_Writer.cpp
|
||||
CMakeLists.txt CMake build rules
|
||||
|
||||
player/ Player using the SDL multimedia library
|
||||
player.cpp Simple music player with waveform display
|
||||
Music_Player.cpp Stand alone player for background music
|
||||
Music_Player.h
|
||||
Audio_Scope.cpp Audio waveform scope
|
||||
Audio_Scope.h
|
||||
CMakeLists.txt CMake build rules
|
||||
|
||||
gme/
|
||||
blargg_config.h Library configuration (modify this file as needed)
|
||||
|
||||
gme.h Library interface header file
|
||||
gme.cpp
|
||||
|
||||
Ay_Emu.h ZX Spectrum AY emulator
|
||||
Ay_Emu.cpp
|
||||
Ay_Apu.cpp
|
||||
Ay_Apu.h
|
||||
Ay_Cpu.cpp
|
||||
Ay_Cpu.h
|
||||
|
||||
Gbs_Emu.h Nintendo Game Boy GBS emulator
|
||||
Gbs_Emu.cpp
|
||||
Gb_Apu.cpp
|
||||
Gb_Apu.h
|
||||
Gb_Cpu.cpp
|
||||
Gb_Cpu.h
|
||||
gb_cpu_io.h
|
||||
Gb_Oscs.cpp
|
||||
Gb_Oscs.h
|
||||
|
||||
Hes_Emu.h TurboGrafx-16/PC Engine HES emulator
|
||||
Hes_Apu.cpp
|
||||
Hes_Apu.h
|
||||
Hes_Cpu.cpp
|
||||
Hes_Cpu.h
|
||||
hes_cpu_io.h
|
||||
Hes_Emu.cpp
|
||||
|
||||
Kss_Emu.h MSX Home Computer/other Z80 systems KSS emulator
|
||||
Kss_Emu.cpp
|
||||
Kss_Cpu.cpp
|
||||
Kss_Cpu.h
|
||||
Kss_Scc_Apu.cpp
|
||||
Kss_Scc_Apu.h
|
||||
Ay_Apu.h
|
||||
Ay_Apu.cpp
|
||||
Sms_Apu.h
|
||||
Sms_Apu.cpp
|
||||
Sms_Oscs.h
|
||||
|
||||
Nsf_Emu.h Nintendo NES NSF/NSFE emulator
|
||||
Nsf_Emu.cpp
|
||||
Nes_Apu.cpp
|
||||
Nes_Apu.h
|
||||
Nes_Cpu.cpp
|
||||
Nes_Cpu.h
|
||||
nes_cpu_io.h
|
||||
Nes_Oscs.cpp
|
||||
Nes_Oscs.h
|
||||
Nes_Fme7_Apu.cpp
|
||||
Nes_Fme7_Apu.h
|
||||
Nes_Namco_Apu.cpp
|
||||
Nes_Namco_Apu.h
|
||||
Nes_Vrc6_Apu.cpp
|
||||
Nes_Vrc6_Apu.h
|
||||
Nsfe_Emu.h NSFE support
|
||||
Nsfe_Emu.cpp
|
||||
|
||||
Spc_Emu.h Super Nintendo SPC emulator
|
||||
Spc_Emu.cpp
|
||||
Snes_Spc.cpp
|
||||
Snes_Spc.h
|
||||
Spc_Cpu.cpp
|
||||
Spc_Cpu.h
|
||||
Spc_Dsp.cpp
|
||||
Spc_Dsp.h
|
||||
Fir_Resampler.cpp
|
||||
Fir_Resampler.h
|
||||
|
||||
Sap_Emu.h Atari SAP emulator
|
||||
Sap_Emu.cpp
|
||||
Sap_Apu.cpp
|
||||
Sap_Apu.h
|
||||
Sap_Cpu.cpp
|
||||
Sap_Cpu.h
|
||||
sap_cpu_io.h
|
||||
|
||||
Vgm_Emu.h Sega VGM emulator
|
||||
Vgm_Emu_Impl.cpp
|
||||
Vgm_Emu_Impl.h
|
||||
Vgm_Emu.cpp
|
||||
Ym2413_Emu.cpp
|
||||
Ym2413_Emu.h
|
||||
Gym_Emu.h Sega Genesis GYM emulator
|
||||
Gym_Emu.cpp
|
||||
Sms_Apu.cpp Common Sega emulator files
|
||||
Sms_Apu.h
|
||||
Sms_Oscs.h
|
||||
Ym2612_Emu.cpp
|
||||
Ym2612_Emu.h
|
||||
Dual_Resampler.cpp
|
||||
Dual_Resampler.h
|
||||
Fir_Resampler.cpp
|
||||
Fir_Resampler.h
|
||||
|
||||
M3u_Playlist.h M3U playlist support
|
||||
M3u_Playlist.cpp
|
||||
|
||||
Effects_Buffer.h Sound buffer with stereo echo and panning
|
||||
Effects_Buffer.cpp
|
||||
|
||||
blargg_common.h Common files needed by all emulators
|
||||
blargg_endian.h
|
||||
blargg_source.h
|
||||
Blip_Buffer.cpp
|
||||
Blip_Buffer.h
|
||||
Gme_File.h
|
||||
Gme_File.cpp
|
||||
Music_Emu.h
|
||||
Music_Emu.cpp
|
||||
Classic_Emu.h
|
||||
Classic_Emu.cpp
|
||||
Multi_Buffer.h
|
||||
Multi_Buffer.cpp
|
||||
Data_Reader.h
|
||||
Data_Reader.cpp
|
||||
|
||||
CMakeLists.txt CMake build rules
|
||||
|
||||
|
||||
Legal
|
||||
-----
|
||||
Game_Music_Emu library copyright (C) 2003-2009 Shay Green.
|
||||
Sega Genesis YM2612 emulator copyright (C) 2002 Stephane Dallongeville.
|
||||
|
||||
--
|
||||
Shay Green <gblargg@gmail.com>
|
||||
Game_Music_Emu 0.6.2: Game Music Emulators
|
||||
------------------------------------------
|
||||
Game_Music_Emu is a collection of video game music file emulators that
|
||||
support the following formats and systems:
|
||||
|
||||
AY ZX Spectrum/Amstrad CPC
|
||||
GBS Nintendo Game Boy
|
||||
GYM Sega Genesis/Mega Drive
|
||||
HES NEC TurboGrafx-16/PC Engine
|
||||
KSS MSX Home Computer/other Z80 systems (doesn't support FM sound)
|
||||
NSF/NSFE Nintendo NES/Famicom (with VRC 6, Namco 106, and FME-7 sound)
|
||||
SAP Atari systems using POKEY sound chip
|
||||
SPC Super Nintendo/Super Famicom
|
||||
VGM/VGZ Sega Master System/Mark III, Sega Genesis/Mega Drive,BBC Micro
|
||||
|
||||
Features:
|
||||
* C interface for use in C, C++, and other compatible languages
|
||||
* High emphasis has been placed on making the library very easy to use
|
||||
* One set of common functions work with all emulators the same way
|
||||
* Several code examples, including music player using SDL
|
||||
* Portable code for use on any system with modern or older C++ compilers
|
||||
* Adjustable output sample rate using quality band-limited resampling
|
||||
* Uniform access to text information fields and track timing information
|
||||
* End-of-track fading and automatic look ahead silence detection
|
||||
* Treble/bass and stereo echo for AY/GBS/HES/KSS/NSF/NSFE/SAP/VGM
|
||||
* Tempo can be adjusted and individual voices can be muted while playing
|
||||
* Can read music data from file, memory, or custom reader function/class
|
||||
* Can access track information without having to load into full emulator
|
||||
* M3U track listing support for multi-track formats
|
||||
* Modular design allows elimination of unneeded emulators/features
|
||||
|
||||
This library has been used in game music players for Windows, Linux on
|
||||
several architectures, Mac OS, MorphOS, Xbox, PlayStation Portable,
|
||||
GP2X, and Nintendo DS.
|
||||
|
||||
Author : Shay Green <gblargg@gmail.com>
|
||||
Website: https://bitbucket.org/mpyne/game-music-emu/wiki/Home
|
||||
License: GNU Lesser General Public License (LGPL)
|
||||
|
||||
Current Maintainer: Michael Pyne <mpyne@purinchu.net>
|
||||
|
||||
Getting Started
|
||||
---------------
|
||||
Build a program consisting of demo/basics.c, demo/Wave_Writer.cpp, and
|
||||
all source files in gme/.
|
||||
|
||||
Or, if you have CMake 2.6 or later, execute at a command prompt (from the
|
||||
extracted source directory):
|
||||
|
||||
mkdir build
|
||||
cd build
|
||||
cmake ../ # <-- Pass any needed CMake flags here
|
||||
make # To build the library
|
||||
cd demo
|
||||
make # To build the demo itself
|
||||
|
||||
Be sure "test.nsf" is in the same directory as the demo program. Running it
|
||||
should generate the recording "out.wav".
|
||||
|
||||
You can use "make install" to install the library. To choose where to install
|
||||
the library to, use the CMake argument "-DCMAKE_INSTALL_PREFIX=/usr/local"
|
||||
(and replace /usr/local with the base path you wish to use). Alternately, you
|
||||
can specify the base path to install to when you run "make install" by passing
|
||||
'DESTDIR=/usr/local' on the make install command line (again, replace
|
||||
/usr/local as appropriate).
|
||||
|
||||
To build a static library instead of shared (the default), pass
|
||||
-DBUILD_SHARED_LIBS=OFF to the cmake command when running cmake.
|
||||
|
||||
A slightly more extensive demo application is available in the player/
|
||||
directory. It requires SDL to build.
|
||||
|
||||
Read gme.txt for more information. Post to the discussion forum for
|
||||
assistance.
|
||||
|
||||
Files
|
||||
-----
|
||||
gme.txt General notes about the library
|
||||
changes.txt Changes made since previous releases
|
||||
design.txt Library design notes
|
||||
license.txt GNU Lesser General Public License
|
||||
CMakeLists.txt CMake build rules
|
||||
|
||||
test.nsf Test file for NSF emulator
|
||||
test.m3u Test m3u playlist for features.c demo
|
||||
|
||||
demo/
|
||||
basics.c Records NSF file to wave sound file
|
||||
features.c Demonstrates many additional features
|
||||
Wave_Writer.h WAVE sound file writer used for demo output
|
||||
Wave_Writer.cpp
|
||||
CMakeLists.txt CMake build rules
|
||||
|
||||
player/ Player using the SDL multimedia library
|
||||
player.cpp Simple music player with waveform display
|
||||
Music_Player.cpp Stand alone player for background music
|
||||
Music_Player.h
|
||||
Audio_Scope.cpp Audio waveform scope
|
||||
Audio_Scope.h
|
||||
CMakeLists.txt CMake build rules
|
||||
|
||||
gme/
|
||||
blargg_config.h Library configuration (modify this file as needed)
|
||||
|
||||
gme.h Library interface header file
|
||||
gme.cpp
|
||||
|
||||
Ay_Emu.h ZX Spectrum AY emulator
|
||||
Ay_Emu.cpp
|
||||
Ay_Apu.cpp
|
||||
Ay_Apu.h
|
||||
Ay_Cpu.cpp
|
||||
Ay_Cpu.h
|
||||
|
||||
Gbs_Emu.h Nintendo Game Boy GBS emulator
|
||||
Gbs_Emu.cpp
|
||||
Gb_Apu.cpp
|
||||
Gb_Apu.h
|
||||
Gb_Cpu.cpp
|
||||
Gb_Cpu.h
|
||||
gb_cpu_io.h
|
||||
Gb_Oscs.cpp
|
||||
Gb_Oscs.h
|
||||
|
||||
Hes_Emu.h TurboGrafx-16/PC Engine HES emulator
|
||||
Hes_Apu.cpp
|
||||
Hes_Apu.h
|
||||
Hes_Cpu.cpp
|
||||
Hes_Cpu.h
|
||||
hes_cpu_io.h
|
||||
Hes_Emu.cpp
|
||||
|
||||
Kss_Emu.h MSX Home Computer/other Z80 systems KSS emulator
|
||||
Kss_Emu.cpp
|
||||
Kss_Cpu.cpp
|
||||
Kss_Cpu.h
|
||||
Kss_Scc_Apu.cpp
|
||||
Kss_Scc_Apu.h
|
||||
Ay_Apu.h
|
||||
Ay_Apu.cpp
|
||||
Sms_Apu.h
|
||||
Sms_Apu.cpp
|
||||
Sms_Oscs.h
|
||||
|
||||
Nsf_Emu.h Nintendo NES NSF/NSFE emulator
|
||||
Nsf_Emu.cpp
|
||||
Nes_Apu.cpp
|
||||
Nes_Apu.h
|
||||
Nes_Cpu.cpp
|
||||
Nes_Cpu.h
|
||||
nes_cpu_io.h
|
||||
Nes_Oscs.cpp
|
||||
Nes_Oscs.h
|
||||
Nes_Fme7_Apu.cpp
|
||||
Nes_Fme7_Apu.h
|
||||
Nes_Namco_Apu.cpp
|
||||
Nes_Namco_Apu.h
|
||||
Nes_Vrc6_Apu.cpp
|
||||
Nes_Vrc6_Apu.h
|
||||
Nsfe_Emu.h NSFE support
|
||||
Nsfe_Emu.cpp
|
||||
|
||||
Spc_Emu.h Super Nintendo SPC emulator
|
||||
Spc_Emu.cpp
|
||||
Snes_Spc.cpp
|
||||
Snes_Spc.h
|
||||
Spc_Cpu.cpp
|
||||
Spc_Cpu.h
|
||||
Spc_Dsp.cpp
|
||||
Spc_Dsp.h
|
||||
Fir_Resampler.cpp
|
||||
Fir_Resampler.h
|
||||
|
||||
Sap_Emu.h Atari SAP emulator
|
||||
Sap_Emu.cpp
|
||||
Sap_Apu.cpp
|
||||
Sap_Apu.h
|
||||
Sap_Cpu.cpp
|
||||
Sap_Cpu.h
|
||||
sap_cpu_io.h
|
||||
|
||||
Vgm_Emu.h Sega VGM emulator
|
||||
Vgm_Emu_Impl.cpp
|
||||
Vgm_Emu_Impl.h
|
||||
Vgm_Emu.cpp
|
||||
Ym2413_Emu.cpp
|
||||
Ym2413_Emu.h
|
||||
Gym_Emu.h Sega Genesis GYM emulator
|
||||
Gym_Emu.cpp
|
||||
Sms_Apu.cpp Common Sega emulator files
|
||||
Sms_Apu.h
|
||||
Sms_Oscs.h
|
||||
Ym2612_Emu.cpp
|
||||
Ym2612_Emu.h
|
||||
Dual_Resampler.cpp
|
||||
Dual_Resampler.h
|
||||
Fir_Resampler.cpp
|
||||
Fir_Resampler.h
|
||||
|
||||
M3u_Playlist.h M3U playlist support
|
||||
M3u_Playlist.cpp
|
||||
|
||||
Effects_Buffer.h Sound buffer with stereo echo and panning
|
||||
Effects_Buffer.cpp
|
||||
|
||||
blargg_common.h Common files needed by all emulators
|
||||
blargg_endian.h
|
||||
blargg_source.h
|
||||
Blip_Buffer.cpp
|
||||
Blip_Buffer.h
|
||||
Gme_File.h
|
||||
Gme_File.cpp
|
||||
Music_Emu.h
|
||||
Music_Emu.cpp
|
||||
Classic_Emu.h
|
||||
Classic_Emu.cpp
|
||||
Multi_Buffer.h
|
||||
Multi_Buffer.cpp
|
||||
Data_Reader.h
|
||||
Data_Reader.cpp
|
||||
|
||||
CMakeLists.txt CMake build rules
|
||||
|
||||
|
||||
Legal
|
||||
-----
|
||||
Game_Music_Emu library copyright (C) 2003-2009 Shay Green.
|
||||
Sega Genesis YM2612 emulator copyright (C) 2002 Stephane Dallongeville.
|
||||
|
||||
--
|
||||
Shay Green <gblargg@gmail.com>
|
||||
@@ -1,5 +1,5 @@
|
||||
/* backtrace.h -- Public header file for stack backtrace library.
|
||||
Copyright (C) 2012-2021 Free Software Foundation, Inc.
|
||||
Copyright (C) 2012-2024 Free Software Foundation, Inc.
|
||||
Written by Ian Lance Taylor, Google.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
|
||||
Binary file not shown.
@@ -1,11 +0,0 @@
|
||||
#All folders
|
||||
SRB2.res
|
||||
depend.dep
|
||||
depend.ped
|
||||
*.o
|
||||
buildvm*
|
||||
minilua*
|
||||
lj_vm.S
|
||||
#VC9 folder only
|
||||
/VC9/Win32
|
||||
/VC9/x64
|
||||
@@ -1,2 +0,0 @@
|
||||
# DON'T REMOVE
|
||||
# This keeps the folder from disappearing
|
||||
@@ -1,2 +0,0 @@
|
||||
# DON'T REMOVE
|
||||
# This keeps the folder from disappearing
|
||||
@@ -1,2 +0,0 @@
|
||||
# DON'T REMOVE
|
||||
# This keeps the folder from disappearing
|
||||
@@ -1,2 +0,0 @@
|
||||
# DON'T REMOVE
|
||||
# This keeps the folder from disappearing
|
||||
@@ -1,2 +0,0 @@
|
||||
# DON'T REMOVE
|
||||
# This keeps the folder from disappearing
|
||||
@@ -1,2 +0,0 @@
|
||||
# DON'T REMOVE
|
||||
# This keeps the folder from disappearing
|
||||
@@ -1,2 +0,0 @@
|
||||
# DON'T REMOVE
|
||||
# This keeps the folder from disappearing
|
||||
@@ -1,2 +0,0 @@
|
||||
# DON'T REMOVE
|
||||
# This keeps the folder from disappearing
|
||||
@@ -1,2 +0,0 @@
|
||||
# DON'T REMOVE
|
||||
# This keeps the folder from disappearing
|
||||
@@ -1,2 +0,0 @@
|
||||
# DON'T REMOVE
|
||||
# This keeps the folder from disappearing
|
||||
@@ -1,2 +0,0 @@
|
||||
# DON'T REMOVE
|
||||
# This keeps the folder from disappearing
|
||||
@@ -1,2 +0,0 @@
|
||||
# DON'T REMOVE
|
||||
# This keeps the folder from disappearing
|
||||
@@ -1,2 +0,0 @@
|
||||
# DON'T REMOVE
|
||||
# This keeps the folder from disappearing
|
||||
@@ -1,2 +0,0 @@
|
||||
# DON'T REMOVE
|
||||
# This keeps the folder from disappearing
|
||||
@@ -1,2 +0,0 @@
|
||||
# DON'T REMOVE
|
||||
# This keeps the folder from disappearing
|
||||
@@ -1,2 +0,0 @@
|
||||
# DON'T REMOVE
|
||||
# This keeps the folder from disappearing
|
||||
@@ -1,2 +0,0 @@
|
||||
# DON'T REMOVE
|
||||
# This keeps the folder from disappearing
|
||||
@@ -1,2 +0,0 @@
|
||||
# DON'T REMOVE
|
||||
# This keeps the folder from disappearing
|
||||
@@ -1,2 +0,0 @@
|
||||
# DON'T REMOVE
|
||||
# This keeps the folder from disappearing
|
||||
@@ -1,2 +0,0 @@
|
||||
# DON'T REMOVE
|
||||
# This keeps the folder from disappearing
|
||||
+13
-1
@@ -228,6 +228,14 @@ set(SRB2_CONFIG_STATIC_OPENGL OFF CACHE BOOL
|
||||
"Use statically linked OpenGL. NOT RECOMMENDED.")
|
||||
set(SRB2_CONFIG_USE_FBO_OGL ON CACHE BOOL
|
||||
"Enable OpenGL FBO Downsampling support.")
|
||||
set(SRB2_CONFIG_DEDICATED OFF CACHE BOOL
|
||||
"Build a dedicated server.")
|
||||
|
||||
if(${SRB2_CONFIG_DEDICATED})
|
||||
set(SRB2_CONFIG_HAVE_GME NO)
|
||||
set(SRB2_CONFIG_HAVE_OPENMPT NO)
|
||||
set(SRB2_CONFIG_HWRENDER NO)
|
||||
endif()
|
||||
|
||||
### use internal libraries?
|
||||
if(${CMAKE_SYSTEM} MATCHES "Windows") ###set on Windows only
|
||||
@@ -554,7 +562,11 @@ add_definitions(-DCMAKECONFIG)
|
||||
# ${SRB2_BLUA_HEADERS}
|
||||
#)
|
||||
|
||||
add_subdirectory(sdl)
|
||||
if(${SRB2_CONFIG_DEDICATED})
|
||||
add_subdirectory(dedicated)
|
||||
else()
|
||||
add_subdirectory(sdl)
|
||||
endif()
|
||||
|
||||
if(NOT ${SRB2_SDL2_AVAILABLE} AND NOT ${SRB2_WIN32_AVAILABLE})
|
||||
message(FATAL_ERROR "There are no targets available to build an SRB2Kart executable. :(")
|
||||
|
||||
+348
-745
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,19 @@
|
||||
makedir:=$(makedir)/Dedicated
|
||||
|
||||
sources+=$(call List,dedicated/Sourcefile)
|
||||
|
||||
opts+=-DDEDICATED
|
||||
|
||||
ifdef MINGW
|
||||
libs+=-mconsole
|
||||
endif
|
||||
|
||||
ifndef NOTHREADS
|
||||
opts+=-DHAVE_THREADS
|
||||
sources+=dedicated/i_threads.c
|
||||
endif
|
||||
|
||||
NOOPENMPT=1
|
||||
NOGME=1
|
||||
NOHW=1
|
||||
NOUPNP=1
|
||||
@@ -0,0 +1,124 @@
|
||||
#
|
||||
# Detect the host system and compiler version.
|
||||
#
|
||||
|
||||
# Previously featured:\
|
||||
PANDORA\
|
||||
DUMMY\
|
||||
DJGPPDOS\
|
||||
SOLARIS\
|
||||
MACOSX\
|
||||
|
||||
all_systems:=\
|
||||
LINUX64\
|
||||
MINGW64\
|
||||
MINGW\
|
||||
UNIX\
|
||||
LINUX\
|
||||
FREEBSD\
|
||||
HAIKU\
|
||||
|
||||
# check for user specified system
|
||||
ifeq (,$(filter $(all_systems),$(.VARIABLES)))
|
||||
ifeq ($(OS),Windows_NT) # all windows are Windows_NT...
|
||||
|
||||
ifeq ($(shell uname -s | grep -o MINGW64),MINGW64) # 64-bit MinGW
|
||||
_m=Detected a Windows system,\
|
||||
compiling for 64-bit MinGW SDL...)
|
||||
$(call Print,$(_m))
|
||||
MINGW64=1
|
||||
else # 32-bit MinGW
|
||||
_m=Detected a Windows system,\
|
||||
compiling for 32-bit MinGW SDL...)
|
||||
$(call Print,$(_m))
|
||||
MINGW=1
|
||||
endif
|
||||
|
||||
NOOBJDUMP=1
|
||||
else # if you on the *nix
|
||||
|
||||
system:=$(shell uname -s)
|
||||
|
||||
ifeq ($(system),Linux)
|
||||
new_system:=LINUX
|
||||
else ifeq ($(system),Haiku)
|
||||
new_system:=HAIKU
|
||||
else
|
||||
|
||||
$(error \
|
||||
Could not automatically detect your system,\
|
||||
try specifying a system manually)
|
||||
|
||||
endif
|
||||
|
||||
ifeq ($(shell getconf LONG_BIT),64)
|
||||
system+=64-bit
|
||||
new_system:=$(new_system)64
|
||||
endif
|
||||
|
||||
$(call Print,Detected $(system) ($(new_system))...)
|
||||
$(new_system):=1
|
||||
|
||||
endif
|
||||
endif
|
||||
|
||||
# This must have high to low order.
|
||||
gcc_versions:=\
|
||||
151 150 15\
|
||||
142 141 140 14\
|
||||
132 131 130 13\
|
||||
123 122 121 120 12\
|
||||
114 113 112 111 110 11\
|
||||
105 104 103 102 101 100 10\
|
||||
95 94 93 92 91 90\
|
||||
85 84 83 82 81 80\
|
||||
75 74 73 72 71 70\
|
||||
64 63 62 61 60\
|
||||
55 54 53 52 51 50\
|
||||
49 48 47 46 45 44 43 42 41 40
|
||||
|
||||
latest_gcc_version:=15.1.1
|
||||
|
||||
# Automatically set version flag, but not if one was
|
||||
# manually set. And don't bother if this is a clean only
|
||||
# run.
|
||||
ifeq (,$(call Wildvar,GCC% destructive))
|
||||
|
||||
# can't use $(CC) --version here since that uses argv[0] to display the name
|
||||
# also gcc outputs the information to stderr, so I had to do 2>&1
|
||||
# this program really doesn't like identifying itself
|
||||
shellversion:=$(shell $(CC) -v 2>&1)
|
||||
# Try to remove "-win32"
|
||||
version:=$(subst -win32,.0,$(shellversion))
|
||||
|
||||
# check if this is in fact GCC
|
||||
ifneq (,$(findstring gcc version,$(version)))
|
||||
|
||||
# in stark contrast to the name, gcc will give me a nicely formatted version number for free
|
||||
shellversion:=$(shell $(CC) -dumpfullversion)
|
||||
|
||||
# Try to remove "-win32"
|
||||
version:=$(subst -win32,.0,$(shellversion))
|
||||
|
||||
# Turn version into words of major, minor
|
||||
v:=$(subst ., ,$(version))
|
||||
# concat. major minor
|
||||
v:=$(word 1,$(v))$(word 2,$(v))
|
||||
|
||||
# If this version is not in the list,
|
||||
# default to the latest supported
|
||||
ifeq (,$(filter $(v),$(gcc_versions)))
|
||||
define line =
|
||||
Your compiler version, GCC $(version), \
|
||||
is not supported by the Makefile.
|
||||
The Makefile will assume GCC $(latest_gcc_version).
|
||||
endef
|
||||
$(call Print,$(line))
|
||||
GCC$(subst .,,$(latest_gcc_version)):=1
|
||||
else
|
||||
$(call Print,Detected GCC $(version) (GCC$(v)))
|
||||
GCC$(v):=1
|
||||
endif
|
||||
|
||||
endif
|
||||
endif
|
||||
@@ -0,0 +1,106 @@
|
||||
#
|
||||
# Makefile for feature flags.
|
||||
#
|
||||
|
||||
passthru_opts+=\
|
||||
NOHW NOMD5 NOPOSTPROCESSING\
|
||||
MOBJCONSISTANCY PACKETDROP ZDEBUG\
|
||||
HAVE_MINIUPNPC\
|
||||
HAVE_DISCORDRPC DEVELOP\
|
||||
NOBLUAJIT
|
||||
|
||||
# build with debugging information
|
||||
ifdef DEBUGMODE
|
||||
PACKETDROP=1
|
||||
opts+=-DPARANOIA -DRANGECHECK
|
||||
endif
|
||||
|
||||
ifndef NOHW
|
||||
opts+=-DHWRENDER
|
||||
|
||||
ifndef NOSCREENFBO
|
||||
opts+=-DUSE_FBO_OGL
|
||||
endif
|
||||
|
||||
sources+=$(call List,hardware/Sourcefile)
|
||||
endif
|
||||
|
||||
ifndef NOMD5
|
||||
sources+=md5.c
|
||||
endif
|
||||
|
||||
ifndef NONET
|
||||
ifndef NOSATURNJOIN
|
||||
opts+=-DDOSATURNJOIN
|
||||
endif
|
||||
ifndef NOSATURNPAK
|
||||
opts+=-DDOSATURNPAK
|
||||
endif
|
||||
endif
|
||||
|
||||
ifndef NOZLIB
|
||||
ifndef NOPNG
|
||||
ifdef PNG_PKGCONFIG
|
||||
$(eval $(call Use_pkg_config,PNG_PKGCONFIG))
|
||||
else
|
||||
PNG_CONFIG?=$(call Prefix,libpng-config)
|
||||
$(eval $(call Configure,PNG,$(PNG_CONFIG) \
|
||||
$(if $(PNG_STATIC),--static),,--ldflags))
|
||||
endif
|
||||
ifdef LINUX
|
||||
opts+=-D_LARGEFILE64_SOURCE
|
||||
endif
|
||||
opts+=-DHAVE_PNG
|
||||
sources+=apng.c
|
||||
endif
|
||||
endif
|
||||
|
||||
ifndef NOCURL
|
||||
CURLCONFIG?=curl-config
|
||||
$(eval $(call Configure,CURL,$(CURLCONFIG)))
|
||||
opts+=-DHAVE_CURL
|
||||
endif
|
||||
|
||||
ifdef HAVE_MINIUPNPC
|
||||
MINIUPNPC_PKGCONFIG?=miniupnpc
|
||||
$(eval $(call Use_pkg_config,MINIUPNPC))
|
||||
HAVE_MINIUPNPC=1
|
||||
opts+=-DHAVE_MINIUPNPC
|
||||
endif
|
||||
|
||||
ifndef NOLIBBACKTRACE
|
||||
$(eval $(call Propogate_flags,LIBBACKTRACE))
|
||||
libs+=-lbacktrace
|
||||
opts+=-DHAVE_LIBBACKTRACE
|
||||
endif
|
||||
|
||||
#windoze hack
|
||||
ifdef MINGW
|
||||
ifndef NODISCORDRPC
|
||||
HAVE_DISCORDRPC=1
|
||||
endif
|
||||
endif
|
||||
|
||||
ifdef HAVE_DISCORDRPC
|
||||
$(eval $(call Propogate_flags,DISCORDRPC))
|
||||
libs+=-ldiscord-rpc
|
||||
opts+=-DUSE_STUN
|
||||
sources+=discord.c stun.c
|
||||
endif
|
||||
|
||||
# (Valgrind is a memory debugger.)
|
||||
ifdef VALGRIND
|
||||
VALGRIND_PKGCONFIG?=valgrind
|
||||
VALGRIND_LDFLAGS=
|
||||
$(eval $(call Use_pkg_config,VALGRIND))
|
||||
ZDEBUG=1
|
||||
opts+=-DHAVE_VALGRIND
|
||||
endif
|
||||
|
||||
default_packages:=\
|
||||
GME/libgme/LIBGME\
|
||||
OPENMPT/libopenmpt/LIBOPENMPT\
|
||||
ZLIB/zlib\
|
||||
|
||||
$(foreach p,$(default_packages),\
|
||||
$(eval $(call Check_pkg_config,$(p))))
|
||||
@@ -0,0 +1,71 @@
|
||||
#
|
||||
# Makefile options for Haiku
|
||||
#
|
||||
|
||||
opts+=-DUNIXCOMMON -DLUA_USE_POSIX
|
||||
|
||||
ifndef DEDICATED
|
||||
ifndef DUMMY
|
||||
SDL?=1
|
||||
DEDICATED?=0
|
||||
endif
|
||||
endif
|
||||
|
||||
NOEXECINFO=1
|
||||
|
||||
ifeq (${SDL},1)
|
||||
EXENAME?=srb2haiku
|
||||
else ifeq (${DEDICATED},1)
|
||||
EXENAME?=srb2haikud
|
||||
endif
|
||||
|
||||
ifndef NONET
|
||||
libs+=-lnetwork
|
||||
endif
|
||||
|
||||
define _set =
|
||||
$(1)_CFLAGS?=$($(1)_opts)
|
||||
$(1)_LDFLAGS?=$($(1)_libs)
|
||||
endef
|
||||
|
||||
lib:=../libs/gme
|
||||
LIBGME_opts:=-I$(lib)/include
|
||||
LIBGME_libs:=-l:libgme.so.0
|
||||
$(eval $(call _set,LIBGME))
|
||||
|
||||
lib:=../libs/libopenmpt
|
||||
LIBOPENMPT_opts:=-I$(lib)/inc
|
||||
LIBOPENMPT_libs:=-l:libopenmpt.so.0
|
||||
$(eval $(call _set,LIBOPENMPT))
|
||||
|
||||
ifdef SDL
|
||||
lib:=../libs/SDL2_mixer
|
||||
mixer_opts:=-I$(lib)/include
|
||||
mixer_libs:=-l:libSDL2_mixer-2.0.so.0
|
||||
|
||||
lib:=../libs/SDL2
|
||||
SDL_opts:=-I$(lib)/include $(mixer_opts)
|
||||
SDL_libs:=$(mixer_libs) -l:libSDL2-2.0.so.0
|
||||
$(eval $(call _set,SDL))
|
||||
endif
|
||||
|
||||
lib:=../libs/zlib
|
||||
ZLIB_opts:=-I$(lib)
|
||||
ZLIB_libs:=-l:libz.so.1
|
||||
$(eval $(call _set,ZLIB))
|
||||
|
||||
ifndef PNG_CONFIG
|
||||
PNG_opts:=
|
||||
PNG_libs:=-l:libpng16.so.16
|
||||
$(eval $(call _set,PNG))
|
||||
endif
|
||||
|
||||
lib:=../libs/curl
|
||||
CURL_opts:=-I$(lib)/include
|
||||
CURL_libs:=-l:libcurl.so.4
|
||||
$(eval $(call _set,CURL))
|
||||
|
||||
lib:=../libs/miniupnpc
|
||||
MINIUPNPC_opts:=-I$(lib)/include
|
||||
MINIUPNPC_libs:=-l:libminiupnpc.so.17
|
||||
$(eval $(call _set,MINIUPNPC))
|
||||
@@ -0,0 +1,47 @@
|
||||
#
|
||||
# Makefile options for unices (linux, bsd...)
|
||||
#
|
||||
|
||||
|
||||
opts+=-DUNIXCOMMON -DLUA_USE_POSIX
|
||||
# Use -rdynamic so a backtrace log shows function names
|
||||
# instead of addresses
|
||||
libs+=-lm -rdynamic
|
||||
|
||||
ifndef NOHW
|
||||
opts+=-I/usr/X11R6/include
|
||||
libs+=-L/usr/X11R6/lib
|
||||
endif
|
||||
|
||||
ifndef DEDICATED
|
||||
SDL?=1
|
||||
DEDICATED?=0
|
||||
endif
|
||||
|
||||
ifeq (${SDL},1)
|
||||
EXENAME?=lsdl2srb2kart
|
||||
endif
|
||||
|
||||
ifeq (${DEDICATED},1)
|
||||
EXENAME?=lsrb2kartd
|
||||
endif
|
||||
|
||||
# In common usage.
|
||||
ifdef LINUX
|
||||
libs+=-lrt
|
||||
passthru_opts+=NOTERMIOS
|
||||
endif
|
||||
|
||||
# Tested by Steel, as of release 2.2.8.
|
||||
ifdef FREEBSD
|
||||
opts+=-I/usr/X11R6/include -DLINUX -DFREEBSD
|
||||
libs+=-L/usr/X11R6/lib -lkvm -lexecinfo
|
||||
endif
|
||||
|
||||
# FIXME: UNTESTED
|
||||
#ifdef SOLARIS
|
||||
#NOIPX=1
|
||||
#opts+=-I/usr/local/include -I/opt/sfw/include \
|
||||
# -DSOLARIS -DINADDR_NONE=INADDR_ANY -DBSD_COMP
|
||||
#libs+=-L/opt/sfw/lib -lsocket -lnsl
|
||||
#endif
|
||||
@@ -0,0 +1,16 @@
|
||||
#
|
||||
# Warn about old build directories and offer to purge.
|
||||
#
|
||||
|
||||
_old:=$(wildcard $(addprefix ../bin/,FreeBSD Linux \
|
||||
Linux64 Mingw Mingw64 SDL dummy) ../objs ../dep)
|
||||
|
||||
ifdef _old
|
||||
$(foreach v,$(_old),$(info $(abspath $(v))))
|
||||
$(info )
|
||||
$(info These directories are no longer\
|
||||
required and should be removed.)
|
||||
$(info You may remove them manually or\
|
||||
by using 'make distclean')
|
||||
$(error )
|
||||
endif
|
||||
@@ -0,0 +1,76 @@
|
||||
#
|
||||
# Platform specific options.
|
||||
#
|
||||
|
||||
PKG_CONFIG?=pkg-config
|
||||
|
||||
ifdef WINDOWSHELL
|
||||
rmrf=-2>NUL DEL /S /Q
|
||||
mkdir=-2>NUL MD
|
||||
cat=TYPE
|
||||
else
|
||||
rmrf=rm -rf
|
||||
mkdir=mkdir -p
|
||||
cat=cat
|
||||
endif
|
||||
|
||||
ifdef LINUX64
|
||||
LINUX=1
|
||||
endif
|
||||
|
||||
ifdef MINGW64
|
||||
MINGW=1
|
||||
endif
|
||||
|
||||
ifdef LINUX
|
||||
UNIX=1
|
||||
ifdef LINUX64
|
||||
NONX86=1
|
||||
# LINUX64 does not imply X86_64=1;
|
||||
# could mean ARM64 or Itanium
|
||||
platform=linux/64
|
||||
else
|
||||
platform=linux
|
||||
endif
|
||||
else ifdef FREEBSD
|
||||
UNIX=1
|
||||
platform=freebsd
|
||||
else ifdef HAIKU
|
||||
# Give Haiku its own configuration, since it
|
||||
# isn't actually UNIX.
|
||||
include Makefile.d/haiku.mk
|
||||
else ifdef SOLARIS # FIXME: UNTESTED
|
||||
UNIX=1
|
||||
platform=solaris
|
||||
else ifdef CYGWIN32 # FIXME: UNTESTED
|
||||
platform=cygwin
|
||||
else ifdef MINGW
|
||||
ifdef MINGW64
|
||||
NONX86=1
|
||||
NOASM=1
|
||||
# MINGW64 should not necessarily imply X86_64=1,
|
||||
# but we make that assumption elsewhere
|
||||
# Once that changes, remove this
|
||||
X86_64=1
|
||||
platform=mingw/64
|
||||
else
|
||||
platform=mingw
|
||||
endif
|
||||
include Makefile.d/win32.mk
|
||||
endif
|
||||
|
||||
ifdef platform
|
||||
makedir:=$(makedir)/$(platform)
|
||||
endif
|
||||
|
||||
ifdef UNIX
|
||||
include Makefile.d/nix.mk
|
||||
endif
|
||||
|
||||
ifeq ($(SDL), 1)
|
||||
include Makefile.d/sdl.mk
|
||||
else ifeq ($(DEDICATED), 1)
|
||||
include Makefile.d/dedicated.mk
|
||||
else
|
||||
include Makefile.d/dummy.mk
|
||||
endif
|
||||
@@ -0,0 +1,71 @@
|
||||
#
|
||||
# Makefile options for SDL2 backend.
|
||||
#
|
||||
|
||||
#
|
||||
# SDL...., *looks at Alam*, THIS IS A MESS!
|
||||
#
|
||||
# ...a little bird flexes its muscles...
|
||||
#
|
||||
|
||||
makedir:=$(makedir)/SDL
|
||||
|
||||
opts+=-DDIRECTFULLSCREEN -DHAVE_SDL
|
||||
sources+=$(call List,sdl/Sourcefile)
|
||||
|
||||
NOUPNP=1
|
||||
|
||||
# FIXME: UNTESTED
|
||||
#ifdef PANDORA
|
||||
#include sdl/SRB2Pandora/Makefile.cfg
|
||||
#endif #ifdef PANDORA
|
||||
|
||||
# FIXME: UNTESTED
|
||||
#ifdef CYGWIN32
|
||||
#include sdl/MakeCYG.cfg
|
||||
#endif #ifdef CYGWIN32
|
||||
|
||||
ifndef NOHW
|
||||
sources+=sdl/ogl_sdl.c
|
||||
endif
|
||||
|
||||
ifdef NOMIXER
|
||||
sources+=sdl/sdl_sound.c
|
||||
else
|
||||
opts+=-DHAVE_MIXER
|
||||
sources+=sdl/mixer_sound.c
|
||||
|
||||
ifndef HAIKU # Haiku has a special import path
|
||||
libs+=-lSDL2_mixer
|
||||
endif
|
||||
endif
|
||||
|
||||
ifndef NOTHREADS
|
||||
opts+=-DHAVE_THREADS
|
||||
sources+=sdl/i_threads.c
|
||||
endif
|
||||
|
||||
ifdef SDL_PKGCONFIG
|
||||
$(eval $(call Use_pkg_config,SDL))
|
||||
else
|
||||
SDL_CONFIG?=$(call Prefix,sdl2-config)
|
||||
SDL_CFLAGS?=$(shell $(SDL_CONFIG) --cflags)
|
||||
SDL_LDFLAGS?=$(shell $(SDL_CONFIG) \
|
||||
$(if $(STATIC),--static-libs,--libs))
|
||||
$(eval $(call Propogate_flags,SDL))
|
||||
endif
|
||||
|
||||
ifdef MINGW
|
||||
ifndef NOSDLMAIN
|
||||
SDLMAIN=1
|
||||
endif
|
||||
endif
|
||||
|
||||
ifdef SDLMAIN
|
||||
opts+=-DSDLMAIN
|
||||
else
|
||||
ifdef MINGW
|
||||
opts+=-Umain
|
||||
libs+=-mconsole
|
||||
endif
|
||||
endif
|
||||
@@ -0,0 +1,93 @@
|
||||
#
|
||||
# Utility macros for the rest of the Makefiles.
|
||||
#
|
||||
|
||||
Ifnot=$(if $(1),$(3),$(2))
|
||||
Ifndef=$(call Ifnot,$($(1)),$(2),$(3))
|
||||
|
||||
# Match and expand a list of variables by pattern.
|
||||
Wildvar=$(foreach v,$(filter $(1),$(.VARIABLES)),$($(v)))
|
||||
|
||||
# Read a list of words from file and prepend each with the
|
||||
# directory of the file.
|
||||
_cat=$(shell $(cat) $(call Windows_path,$(1)))
|
||||
List=$(addprefix $(dir $(1)),$(call _cat,$(1)))
|
||||
|
||||
# Convert path separators to backslash on Windows.
|
||||
Windows_path=$(if $(WINDOWSHELL),$(subst /,\,$(1)),$(1))
|
||||
|
||||
define Propogate_flags =
|
||||
opts+=$$($(1)_CFLAGS)
|
||||
libs+=$$($(1)_LDFLAGS)
|
||||
endef
|
||||
|
||||
# Set library's _CFLAGS and _LDFLAGS from some command.
|
||||
# Automatically propogates the flags too.
|
||||
# 1: variable prefix (e.g. CURL)
|
||||
# 2: start of command (e.g. curl-config)
|
||||
# --- optional ----
|
||||
# 3: CFLAGS command arguments, default '--cflags'
|
||||
# 4: LDFLAGS command arguments, default '--libs'
|
||||
# 5: common command arguments at the end of command
|
||||
define Configure =
|
||||
$(1)_CFLAGS?=$$(shell $(2) $(or $(3),--cflags) $(5))
|
||||
$(1)_LDFLAGS?=$$(shell $(2) $(or $(4),--libs) $(5))
|
||||
$(call Propogate_flags,$(1))
|
||||
endef
|
||||
|
||||
# Configure library with pkg-config. The package name is
|
||||
# taken from a _PKGCONFIG variable.
|
||||
# 1: variable prefix
|
||||
#
|
||||
# LIBGME_PKGCONFIG=libgme
|
||||
# $(eval $(call Use_pkg_config,LIBGME))
|
||||
define Use_pkg_config =
|
||||
$(call Configure,$(1),$(PKG_CONFIG),,,$($(1)_PKGCONFIG))
|
||||
endef
|
||||
|
||||
# Check disabling flag and configure package in one step
|
||||
# according to delimited argument.
|
||||
# (There is only one argument, but it split by slash.)
|
||||
# 1/: short form library name (uppercase). This is
|
||||
# prefixed with 'NO' and 'HAVE_'. E.g. NOGME, HAVE_GME
|
||||
# /2: package name (e.g. libgme)
|
||||
# /3: variable prefix
|
||||
#
|
||||
# The following example would check if NOGME is not
|
||||
# defined before attempting to define LIBGME_CFLAGS and
|
||||
# LIBGME_LDFLAGS as with Use_pkg_config.
|
||||
#
|
||||
# $(eval $(call Check_pkg_config,GME/libgme/LIBGME))
|
||||
define Check_pkg_config =
|
||||
_p:=$(subst /, ,$(1))
|
||||
_v1:=$$(word 1,$$(_p))
|
||||
_v2:=$$(or $$(word 3,$$(_p)),$$(_v1))
|
||||
ifndef NO$$(_v1)
|
||||
$$(_v2)_PKGCONFIG?=$$(word 2,$$(_p))
|
||||
$$(eval $$(call Use_pkg_config,$$(_v2)))
|
||||
opts+=-DHAVE_$$(_v1)
|
||||
endif
|
||||
endef
|
||||
|
||||
# $(call Prefix,gcc)
|
||||
Prefix=$(if $(PREFIX),$(PREFIX)-)$(1)
|
||||
|
||||
Echo=
|
||||
Echo_name=
|
||||
Print=
|
||||
|
||||
ifndef SILENT
|
||||
Echo=@echo $(1)
|
||||
ifndef ECHO
|
||||
ifndef NOECHOFILENAMES
|
||||
Echo_name=$(call Echo,-- $(1) ...)
|
||||
endif
|
||||
endif
|
||||
ifndef MAKE_RESTARTS
|
||||
ifndef destructive
|
||||
Print=$(info $(1))
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
.=$(call Ifndef,ECHO,@)
|
||||
@@ -0,0 +1,181 @@
|
||||
#
|
||||
# Flags to put a sock in GCC!
|
||||
#
|
||||
|
||||
# See the versions list in detect.mk
|
||||
# This will define all version flags going backward.
|
||||
# Yes, it's magic.
|
||||
define _predecessor =
|
||||
ifdef GCC$(firstword $(1))
|
||||
GCC$(lastword $(1)):=1
|
||||
endif
|
||||
endef
|
||||
_n:=$(words $(gcc_versions))
|
||||
$(foreach v,$(join $(wordlist 2,$(_n),- $(gcc_versions)),\
|
||||
$(addprefix =,$(wordlist 2,$(_n),$(gcc_versions)))),\
|
||||
$(and $(findstring =,$(v)),\
|
||||
$(eval $(call _predecessor,$(subst =, ,$(v))))))
|
||||
|
||||
# aggregate returns seem to happen alot in c++ so just supress em lel
|
||||
CXXFLAGS+= -Wno-aggregate-return
|
||||
|
||||
# -W -Wno-unused
|
||||
|
||||
ifdef GCC150
|
||||
opts+=-std=gnu17
|
||||
endif
|
||||
WFLAGS:=-Wall -Wno-trigraphs
|
||||
ifndef GCC295
|
||||
#WFLAGS+=-Wno-packed
|
||||
endif
|
||||
ifndef RELAXWARNINGS
|
||||
WFLAGS+=-W
|
||||
#WFLAGS+=-Wno-sign-compare
|
||||
ifndef GCC295
|
||||
WFLAGS+=-Wno-div-by-zero
|
||||
endif
|
||||
#WFLAGS+=-Wsystem-headers
|
||||
WFLAGS+=-Wfloat-equal
|
||||
#WFLAGS+=-Wtraditional
|
||||
WFLAGS+=-Wundef
|
||||
ifndef GCC295
|
||||
WFLAGS+=-Wendif-labels
|
||||
endif
|
||||
ifdef GCC41
|
||||
WFLAGS+=-Wshadow
|
||||
endif
|
||||
#WFLAGS+=-Wlarger-than-%len%
|
||||
WFLAGS+=-Wpointer-arith -Wbad-function-cast
|
||||
ifdef GCC45
|
||||
#WFLAGS+=-Wc++-compat
|
||||
endif
|
||||
WFLAGS+=-Wcast-qual
|
||||
ifndef NOCASTALIGNWARN
|
||||
WFLAGS+=-Wcast-align
|
||||
endif
|
||||
WFLAGS+=-Wwrite-strings
|
||||
ifndef ERRORMODE
|
||||
#WFLAGS+=-Wconversion
|
||||
ifdef GCC43
|
||||
#WFLAGS+=-Wno-sign-conversion
|
||||
endif
|
||||
endif
|
||||
WFLAGS+=-Wsign-compare
|
||||
ifdef GCC91
|
||||
WFLAGS+=-Wno-error=address-of-packed-member
|
||||
endif
|
||||
ifdef GCC45
|
||||
WFLAGS+=-Wlogical-op
|
||||
endif
|
||||
WFLAGS+=-Waggregate-return
|
||||
ifdef HAIKU
|
||||
ifdef GCC41
|
||||
#WFLAGS+=-Wno-attributes
|
||||
endif
|
||||
endif
|
||||
#WFLAGS+=-Wstrict-prototypes
|
||||
ifdef GCC40
|
||||
WFLAGS+=-Wold-style-definition
|
||||
endif
|
||||
WFLAGS+=-Wmissing-prototypes -Wmissing-declarations
|
||||
ifdef GCC40
|
||||
WFLAGS+=-Wmissing-field-initializers
|
||||
endif
|
||||
WFLAGS+=-Wmissing-noreturn
|
||||
#WFLAGS+=-Wmissing-format-attribute
|
||||
#WFLAGS+=-Wno-multichar
|
||||
#WFLAGS+=-Wno-deprecated-declarations
|
||||
#WFLAGS+=-Wpacked
|
||||
#WFLAGS+=-Wpadded
|
||||
#WFLAGS+=-Wredundant-decls
|
||||
WFLAGS+=-Wnested-externs
|
||||
#WFLAGS+=-Wunreachable-code
|
||||
WFLAGS+=-Winline
|
||||
ifdef DEBUGMODE
|
||||
WFLAGS+=-Wno-error=inline
|
||||
endif
|
||||
ifdef GCC43
|
||||
WFLAGS+=-funit-at-a-time
|
||||
WFLAGS+=-Wlogical-op
|
||||
endif
|
||||
ifndef GCC295
|
||||
WFLAGS+=-Wdisabled-optimization
|
||||
endif
|
||||
endif
|
||||
WFLAGS+=-Wformat-y2k
|
||||
ifdef GCC71
|
||||
WFLAGS+=-Wno-error=format-overflow=2
|
||||
endif
|
||||
WFLAGS+=-Wformat-security
|
||||
ifndef GCC29
|
||||
#WFLAGS+=-Winit-self
|
||||
endif
|
||||
ifdef GCC46
|
||||
WFLAGS+=-Wno-suggest-attribute=noreturn
|
||||
endif
|
||||
|
||||
ifdef NOLDWARNING
|
||||
LDFLAGS+=-Wl,--as-needed
|
||||
endif
|
||||
|
||||
ifdef ERRORMODE
|
||||
WFLAGS+=-Werror
|
||||
endif
|
||||
|
||||
ifdef GCC43
|
||||
#WFLAGS+=-Wno-error=clobbered
|
||||
endif
|
||||
ifdef GCC44
|
||||
#WFLAGS+=-Wno-error=array-bounds
|
||||
endif
|
||||
ifdef GCC46
|
||||
WFLAGS+=-Wno-error=suggest-attribute=noreturn
|
||||
endif
|
||||
ifdef GCC54
|
||||
WFLAGS+=-Wno-logical-op -Wno-error=logical-op
|
||||
endif
|
||||
ifdef GCC61
|
||||
WFLAGS+=-Wno-tautological-compare -Wno-error=tautological-compare
|
||||
endif
|
||||
ifdef GCC71
|
||||
WFLAGS+=-Wimplicit-fallthrough=4
|
||||
endif
|
||||
ifdef GCC81
|
||||
WFLAGS+=-Wno-error=format-overflow
|
||||
WFLAGS+=-Wno-format-overflow
|
||||
WFLAGS+=-Wno-error=multistatement-macros
|
||||
endif
|
||||
|
||||
ifdef NONX86
|
||||
ifdef X86_64 # yeah that SEEMS contradictory
|
||||
opts+=-march=nocona
|
||||
endif
|
||||
else
|
||||
ifndef GCC29
|
||||
opts+=-msse3 -mfpmath=sse
|
||||
else
|
||||
opts+=-mpentium
|
||||
endif
|
||||
endif
|
||||
|
||||
ifdef DEBUGMODE
|
||||
ifdef GCC48
|
||||
opts+=-Og
|
||||
else
|
||||
opts+=-O0
|
||||
endif
|
||||
endif
|
||||
|
||||
ifdef VALGRIND
|
||||
ifdef GCC46
|
||||
WFLAGS+=-Wno-error=unused-but-set-variable
|
||||
WFLAGS+=-Wno-unused-but-set-variable
|
||||
endif
|
||||
endif
|
||||
|
||||
# Lua
|
||||
ifdef GCC43
|
||||
ifndef GCC44
|
||||
WFLAGS+=-Wno-logical-op
|
||||
endif
|
||||
endif
|
||||
@@ -0,0 +1,124 @@
|
||||
#
|
||||
# Mingw, if you don't know, that's Win32/Win64
|
||||
#
|
||||
|
||||
ifndef MINGW64
|
||||
EXENAME?=srb2kart-saturn_32bit.exe
|
||||
else
|
||||
EXENAME?=srb2kart-saturn_64bit.exe
|
||||
endif
|
||||
|
||||
# disable dynamicbase if under msys2
|
||||
ifdef MSYSTEM
|
||||
libs+=-Wl,--disable-dynamicbase
|
||||
endif
|
||||
|
||||
sources+=win32/Srb2win.rc
|
||||
opts+=-DSTDC_HEADERS
|
||||
libs+=-ladvapi32 -lkernel32 -lmsvcrt -luser32
|
||||
|
||||
ifndef DEDICATED
|
||||
ifndef DUMMY
|
||||
SDL?=1
|
||||
endif
|
||||
endif
|
||||
|
||||
ifndef NOHW
|
||||
opts+=-DUSE_WGL_SWAP
|
||||
endif
|
||||
|
||||
ifdef MINGW64
|
||||
libs+=-lws2_32
|
||||
else
|
||||
#ifndef HAVE_IPV6
|
||||
#libs+=-lwsock32
|
||||
#else
|
||||
libs+=-lws2_32
|
||||
#endif
|
||||
endif
|
||||
|
||||
ifndef MINGW64
|
||||
libs+=-Wl,--large-address-aware
|
||||
NOLIBBACKTRACE=1
|
||||
endif
|
||||
|
||||
ifndef MINGW64
|
||||
32=32
|
||||
x86=x86
|
||||
i686=i686
|
||||
else
|
||||
32=64
|
||||
x86=x86_64
|
||||
i686=x86_64
|
||||
endif
|
||||
|
||||
mingw:=$(i686)-w64-mingw32
|
||||
|
||||
define _set =
|
||||
$(1)_CFLAGS?=$($(1)_opts)
|
||||
$(1)_LDFLAGS?=$($(1)_libs)
|
||||
endef
|
||||
|
||||
lib:=../libs/gme
|
||||
LIBGME_opts:=-I$(lib)/include
|
||||
LIBGME_libs:=-L$(lib)/win$(32) -lgme
|
||||
$(eval $(call _set,LIBGME))
|
||||
|
||||
lib:=../libs/libopenmpt
|
||||
LIBOPENMPT_opts:=-I$(lib)/inc
|
||||
LIBOPENMPT_libs:=-L$(lib)/lib/$(x86)/mingw -lopenmpt
|
||||
$(eval $(call _set,LIBOPENMPT))
|
||||
|
||||
lib:=../libs/SDL2_mixer/$(mingw)
|
||||
|
||||
ifdef SDL
|
||||
mixer_opts:=-I$(lib)/include/SDL2
|
||||
mixer_libs:=-L$(lib)/lib
|
||||
|
||||
lib:=../libs/SDL2/$(mingw)
|
||||
SDL_opts:=-I$(lib)/include/SDL2\
|
||||
$(mixer_opts) -Dmain=SDL_main
|
||||
SDL_libs:=-L$(lib)/lib $(mixer_libs)\
|
||||
-lmingw32 -lSDL2main -lSDL2 -mwindows
|
||||
$(eval $(call _set,SDL))
|
||||
endif
|
||||
|
||||
ifdef MINGW64
|
||||
lib:=../libs/libbacktrace
|
||||
LIBBACKTRACE_opts:=-I$(lib)/include
|
||||
LIBBACKTRACE_libs:=-L$(lib)/lib/x86_64 -lbacktrace
|
||||
$(eval $(call _set,LIBBACKTRACE))
|
||||
else
|
||||
lib:=../libs/drmingw
|
||||
opts+=-I$(lib)/include
|
||||
libs+=-L$(lib)/lib/win32 -lmgwhelp -lexchndl
|
||||
endif
|
||||
|
||||
lib:=../libs/zlib
|
||||
ZLIB_opts:=-I$(lib)
|
||||
ZLIB_libs:=-L$(lib)/win32 -l:libz$(32).a
|
||||
$(eval $(call _set,ZLIB))
|
||||
|
||||
ifndef PNG_CONFIG
|
||||
lib:=../libs/libpng-src
|
||||
PNG_opts:=-I$(lib)
|
||||
PNG_libs:=-L$(lib)/projects -lpng$(32)
|
||||
$(eval $(call _set,PNG))
|
||||
endif
|
||||
|
||||
lib:=../libs/curl
|
||||
CURL_opts:=-I$(lib)/include
|
||||
CURL_libs:=-L$(lib)/lib$(32) -lcurl
|
||||
$(eval $(call _set,CURL))
|
||||
|
||||
ifndef MINGW64 # miniupnc is broken with MINGW64
|
||||
lib:=../libs/miniupnpc
|
||||
MINIUPNPC_opts:=-I$(lib)/include -DMINIUPNP_STATICLIB
|
||||
MINIUPNPC_libs:=-L$(lib)/mingw$(32) -lminiupnpc -lws2_32 -liphlpapi
|
||||
$(eval $(call _set,MINIUPNPC))
|
||||
endif
|
||||
|
||||
lib:=../libs/discord-rpc/win$(32)-dynamic
|
||||
DISCORDRPC_opts+=-I$(lib)/include
|
||||
DISCORDRPC_libs+=-L$(lib)/lib -ldiscord-rpc
|
||||
$(eval $(call _set,DISCORDRPC))
|
||||
@@ -0,0 +1,97 @@
|
||||
am_map.c
|
||||
b_bot.c
|
||||
command.c
|
||||
console.c
|
||||
d_clisrv.c
|
||||
d_main.c
|
||||
d_net.c
|
||||
d_netcmd.c
|
||||
d_netfil.c
|
||||
d_protocol.c
|
||||
dehacked.c
|
||||
f_finale.c
|
||||
f_wipe.c
|
||||
filesrch.c
|
||||
g_game.c
|
||||
g_input.c
|
||||
hu_stuff.c
|
||||
i_tcp.c
|
||||
i_time.c
|
||||
info.c
|
||||
lzf.c
|
||||
m_aatree.c
|
||||
m_anigif.c
|
||||
m_argv.c
|
||||
m_bbox.c
|
||||
m_cheat.c
|
||||
m_cond.c
|
||||
m_fixed.c
|
||||
m_menu.c
|
||||
m_textinput.c
|
||||
m_misc.c
|
||||
m_perfstats.c
|
||||
m_queue.c
|
||||
m_random.c
|
||||
mserv.c
|
||||
http-mserv.c
|
||||
qs22j.c
|
||||
s_sound.c
|
||||
screen.c
|
||||
sounds.c
|
||||
st_stuff.c
|
||||
string.c
|
||||
tables.c
|
||||
v_video.c
|
||||
w_wad.c
|
||||
y_inter.c
|
||||
z_zone.c
|
||||
r_bsp.c
|
||||
r_data.c
|
||||
r_draw.c
|
||||
r_fps.c
|
||||
r_main.cpp
|
||||
r_patch.c
|
||||
r_patchrotation.c
|
||||
r_plane.cpp
|
||||
r_segs.cpp
|
||||
r_skins.c
|
||||
r_sky.c
|
||||
r_splats.c
|
||||
r_things.cpp
|
||||
r_portal.c
|
||||
p_ceilng.c
|
||||
p_enemy.c
|
||||
p_floor.c
|
||||
p_inter.c
|
||||
p_lights.c
|
||||
p_map.c
|
||||
p_maputl.c
|
||||
p_mobj.c
|
||||
p_polyobj.c
|
||||
p_saveg.c
|
||||
p_setup.c
|
||||
p_sight.c
|
||||
p_slopes.c
|
||||
p_spec.c
|
||||
p_telept.c
|
||||
p_tick.c
|
||||
p_user.c
|
||||
k_director.c
|
||||
k_kart.c
|
||||
k_stats.c
|
||||
lua_baselib.c
|
||||
lua_blockmaplib.c
|
||||
lua_consolelib.c
|
||||
lua_hooklib.c
|
||||
lua_hudlib.c
|
||||
lua_hudlib_drawlist.c
|
||||
lua_infolib.c
|
||||
lua_maplib.c
|
||||
lua_mathlib.c
|
||||
lua_mobjlib.c
|
||||
lua_playerlib.c
|
||||
lua_script.c
|
||||
lua_skinlib.c
|
||||
lua_thinkerlib.c
|
||||
lua_udatalib.c
|
||||
lua_glib.c
|
||||
+10
-7
@@ -197,7 +197,7 @@ static fixed_t scale_mtof = (fixed_t)INITSCALEMTOF;
|
||||
// used by FTOM to scale from frame-buffer-to-map coords (=1/scale_mtof)
|
||||
static fixed_t scale_ftom;
|
||||
|
||||
static player_t *plr; // the player represented by an arrow
|
||||
static player_t *plr = NULL; // the player represented by an arrow
|
||||
|
||||
static boolean followplayer = true; // specifies whether to follow the player around
|
||||
|
||||
@@ -237,7 +237,7 @@ static inline void AM_restoreScaleAndLoc(void)
|
||||
m_x = old_m_x;
|
||||
m_y = old_m_y;
|
||||
}
|
||||
else
|
||||
else if (plr && plr->mo)
|
||||
{
|
||||
m_x = (plr->mo->x >> FRACTOMAPBITS) - m_w/2;
|
||||
m_y = (plr->mo->y >> FRACTOMAPBITS) - m_h/2;
|
||||
@@ -312,14 +312,14 @@ static void AM_initVariables(void)
|
||||
m_h = FTOM(f_h);
|
||||
|
||||
// find player to center on initially
|
||||
if (!players[pnum = consoleplayer].ingame)
|
||||
if (!playeringame[pnum = consoleplayer])
|
||||
for (pnum = 0; pnum < MAXPLAYERS; pnum++)
|
||||
if (players[pnum].ingame)
|
||||
if (playeringame[pnum])
|
||||
break;
|
||||
|
||||
plr = &players[pnum];
|
||||
|
||||
if (plr != NULL && plr->mo != NULL)
|
||||
if (plr && plr->mo)
|
||||
{
|
||||
m_x = (plr->mo->x >> FRACTOMAPBITS) - m_w/2;
|
||||
m_y = (plr->mo->y >> FRACTOMAPBITS) - m_h/2;
|
||||
@@ -341,7 +341,7 @@ static void AM_FrameBufferInit(void)
|
||||
f_x = f_y = 0;
|
||||
f_w = vid.width;
|
||||
f_h = vid.height;
|
||||
am_buf = screens[0];
|
||||
am_buf = vid.screens[0];
|
||||
}
|
||||
|
||||
//
|
||||
@@ -598,6 +598,9 @@ static inline void AM_changeWindowScale(void)
|
||||
|
||||
static inline void AM_doFollowPlayer(void)
|
||||
{
|
||||
if (!plr || !plr->mo)
|
||||
return;
|
||||
|
||||
if (f_oldloc.x != plr->mo->x || f_oldloc.y != plr->mo->y)
|
||||
{
|
||||
m_x = FTOM(MTOF(plr->mo->x >> FRACTOMAPBITS)) - m_w/2;
|
||||
@@ -1228,7 +1231,7 @@ static inline void AM_drawPlayers(void)
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (!players[i].ingame || players[i].spectator)
|
||||
if (!playeringame[i] || players[i].spectator)
|
||||
continue;
|
||||
|
||||
if (!players[i].mo)
|
||||
|
||||
@@ -46,7 +46,6 @@ INT32 VID_SetMode(INT32 modenum)
|
||||
vid.modenum = 0;
|
||||
vid.width = 320;
|
||||
vid.height = 240;
|
||||
vid.bpp = 1;
|
||||
vid.buffer = android_surface;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,57 +0,0 @@
|
||||
ifdef UNIXCOMMON
|
||||
LUA_CFLAGS+=-DLUA_USE_POSIX
|
||||
endif
|
||||
ifdef LINUX
|
||||
LUA_CFLAGS+=-DLUA_USE_POSIX
|
||||
endif
|
||||
ifdef GCC43
|
||||
ifndef GCC44
|
||||
WFLAGS+=-Wno-logical-op
|
||||
endif
|
||||
endif
|
||||
|
||||
OBJS:=$(OBJS) \
|
||||
$(OBJDIR)/lapi.o \
|
||||
$(OBJDIR)/lbaselib.o \
|
||||
$(OBJDIR)/ldo.o \
|
||||
$(OBJDIR)/ldblib.o \
|
||||
$(OBJDIR)/lfunc.o \
|
||||
$(OBJDIR)/linit.o \
|
||||
$(OBJDIR)/liolib.o \
|
||||
$(OBJDIR)/llex.o \
|
||||
$(OBJDIR)/lmem.o \
|
||||
$(OBJDIR)/lobject.o \
|
||||
$(OBJDIR)/lstate.o \
|
||||
$(OBJDIR)/lstrlib.o \
|
||||
$(OBJDIR)/ltablib.o \
|
||||
$(OBJDIR)/lundump.o \
|
||||
$(OBJDIR)/lzio.o \
|
||||
$(OBJDIR)/lauxlib.o \
|
||||
$(OBJDIR)/lcode.o \
|
||||
$(OBJDIR)/ldebug.o \
|
||||
$(OBJDIR)/ldump.o \
|
||||
$(OBJDIR)/lgc.o \
|
||||
$(OBJDIR)/lopcodes.o \
|
||||
$(OBJDIR)/lparser.o \
|
||||
$(OBJDIR)/lstring.o \
|
||||
$(OBJDIR)/ltable.o \
|
||||
$(OBJDIR)/ltm.o \
|
||||
$(OBJDIR)/lvm.o \
|
||||
$(OBJDIR)/lua_script.o \
|
||||
$(OBJDIR)/lua_baselib.o \
|
||||
$(OBJDIR)/lua_blockmaplib.o \
|
||||
$(OBJDIR)/lua_mathlib.o \
|
||||
$(OBJDIR)/lua_hooklib.o \
|
||||
$(OBJDIR)/lua_consolelib.o \
|
||||
$(OBJDIR)/lua_infolib.o \
|
||||
$(OBJDIR)/lua_mobjlib.o \
|
||||
$(OBJDIR)/lua_playerlib.o \
|
||||
$(OBJDIR)/lua_skinlib.o \
|
||||
$(OBJDIR)/lua_thinkerlib.o \
|
||||
$(OBJDIR)/lua_maplib.o \
|
||||
$(OBJDIR)/hashtable.o \
|
||||
$(OBJDIR)/lua_hudlib.o \
|
||||
$(OBJDIR)/lua_hudlib_drawlist.o \
|
||||
$(OBJDIR)/lua_udatalib.o \
|
||||
$(OBJDIR)/lua_glib.o
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
lapi.c
|
||||
lauxlib.c
|
||||
lbaselib.c
|
||||
ldblib.c
|
||||
lcode.c
|
||||
ldebug.c
|
||||
ldo.c
|
||||
ldump.c
|
||||
lfunc.c
|
||||
lgc.c
|
||||
linit.c
|
||||
liolib.c
|
||||
llex.c
|
||||
lmem.c
|
||||
lobject.c
|
||||
lopcodes.c
|
||||
lparser.c
|
||||
lstate.c
|
||||
lstring.c
|
||||
lstrlib.c
|
||||
ltable.c
|
||||
ltablib.c
|
||||
ltm.c
|
||||
lundump.c
|
||||
lvm.c
|
||||
lzio.c
|
||||
+70
-5
@@ -17,14 +17,27 @@
|
||||
|
||||
#include "lauxlib.h"
|
||||
#include "lualib.h"
|
||||
#include "../i_system.h"
|
||||
#include "../doomdef.h"
|
||||
#include "../d_main.h"
|
||||
#include "../m_misc.h"
|
||||
|
||||
|
||||
|
||||
#define IO_INPUT 1
|
||||
#define IO_OUTPUT 2
|
||||
|
||||
#define FILELIMIT 1024*1024 // Size limit for reading/writing files
|
||||
|
||||
|
||||
static const char *const fnames[] = {"input", "output"};
|
||||
static const char *whitelist[] = { // Allow scripters to write files of these types to SRB2's folder
|
||||
".txt",
|
||||
".sav2",
|
||||
".cfg",
|
||||
".png",
|
||||
".bmp"
|
||||
};
|
||||
|
||||
|
||||
static int pushresult (lua_State *L, int i, const char *filename) {
|
||||
@@ -146,12 +159,59 @@ static int io_tostring (lua_State *L) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int StartsWith(const char *a, const char *b) // this is wolfs being lazy yet again
|
||||
{
|
||||
if(strncmp(a, b, strlen(b)) == 0) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int io_open (lua_State *L) {
|
||||
const char *filename = luaL_checkstring(L, 1);
|
||||
const char *mode = luaL_optstring(L, 2, "r");
|
||||
FILE **pf = newfile(L);
|
||||
*pf = fopen(filename, mode);
|
||||
return (*pf == NULL) ? pushresult(L, 0, filename) : 1;
|
||||
FILE **pf;
|
||||
const char *filename = luaL_checkstring(L, 1);
|
||||
int pass = 0;
|
||||
size_t i;
|
||||
int length = strlen(filename);
|
||||
char *splitter, *forward, *backward;
|
||||
char *destFilename;
|
||||
const char *mode = luaL_optstring(L, 2, "r");
|
||||
|
||||
for (i = 0; i < (sizeof (whitelist) / sizeof(const char *)); i++)
|
||||
{
|
||||
if (!stricmp(&filename[length - strlen(whitelist[i])], whitelist[i]))
|
||||
{
|
||||
pass = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (strstr(filename, "..") || strchr(filename, ':') || StartsWith(filename, "\\")
|
||||
|| StartsWith(filename, "/") || !pass)
|
||||
{
|
||||
luaL_error(L,"access denied to %s", filename);
|
||||
return pushresult(L,0,filename);
|
||||
}
|
||||
|
||||
destFilename = va("%s"PATHSEP"luafiles"PATHSEP"%s", srb2home, filename);
|
||||
|
||||
// Make directories as needed
|
||||
splitter = destFilename;
|
||||
|
||||
forward = strchr(splitter, '/');
|
||||
backward = strchr(splitter, '\\');
|
||||
while ((splitter = (forward && backward) ? min(forward, backward) : (forward ?: backward)))
|
||||
{
|
||||
*splitter = 0;
|
||||
I_mkdir(destFilename, 0755);
|
||||
*splitter = '/';
|
||||
splitter++;
|
||||
|
||||
forward = strchr(splitter, '/');
|
||||
backward = strchr(splitter, '\\');
|
||||
}
|
||||
|
||||
pf = newfile(L);
|
||||
*pf = fopen(destFilename, mode);
|
||||
return (*pf == NULL) ? pushresult(L, 0, filename) : 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -394,6 +454,11 @@ static int g_write (lua_State *L, FILE *f, int arg) {
|
||||
else {
|
||||
size_t l;
|
||||
const char *s = luaL_checklstring(L, arg, &l);
|
||||
if (ftell(f) + l > FILELIMIT)
|
||||
{
|
||||
luaL_error(L,"write limit bypassed in file. Changes have been discarded.");
|
||||
break;
|
||||
}
|
||||
status = status && (fwrite(s, sizeof(char), l, f) == l);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
luajit
|
||||
luajit.h
|
||||
luajit_relver.txt
|
||||
lj_bcdef.h
|
||||
lj_ffdef.h
|
||||
lj_libdef.h
|
||||
lj_recdef.h
|
||||
lj_folddef.h
|
||||
lj_vm.[sS]
|
||||
@@ -1,408 +0,0 @@
|
||||
##############################################################################
|
||||
# LuaJIT Makefile. Requires GNU Make.
|
||||
#
|
||||
# Please read doc/install.html before changing any variables!
|
||||
#
|
||||
# Suitable for POSIX platforms (Linux, *BSD, OSX etc.).
|
||||
# Also works with MinGW and Cygwin on Windows.
|
||||
# Please check msvcbuild.bat for building with MSVC on Windows.
|
||||
#
|
||||
# Copyright (C) 2005-2023 Mike Pall. See Copyright Notice in luajit.h
|
||||
##############################################################################
|
||||
|
||||
# this is a very dumbed down version of the LuaJIT makefile.
|
||||
# to get the original makefile, visit
|
||||
# https://github.com/GenericHeroGuy/bluajit
|
||||
|
||||
XCFLAGS=
|
||||
XCFLAGS+= -DLUAJIT_DISABLE_FFI
|
||||
#XCFLAGS+= -DLUAJIT_ENABLE_LUA52COMPAT
|
||||
#XCFLAGS+= -DLUAJIT_DISABLE_JIT
|
||||
#XCFLAGS+= -DLUAJIT_USE_SYSMALLOC
|
||||
#XCFLAGS+= -DLUAJIT_USE_VALGRIND
|
||||
#XCFLAGS+= -DLUAJIT_USE_GDBJIT
|
||||
#XCFLAGS+= -DLUA_USE_APICHECK
|
||||
#XCFLAGS+= -DLUA_USE_ASSERT
|
||||
XCFLAGS+= -DLUAJIT_DISABLE_BYTECODE
|
||||
|
||||
# load standard libraries in debug mode, so jit.dump etc works
|
||||
ifndef DEBUGMODE
|
||||
XCFLAGS+= -DLUAJIT_SRB2LIB -DLUAJIT_DISABLE_BUFFER
|
||||
endif
|
||||
# additional functions
|
||||
#XCFLAGS+= -DLUAJIT_SRB2LIB_OS
|
||||
XCFLAGS+= -DLUAJIT_SRB2LIB_DEBUG
|
||||
XCFLAGS+= -DLUAJIT_SRB2LIB_IO
|
||||
|
||||
# don't touch these unless you wanna have a bad time
|
||||
XCFLAGS+= -DLUAJIT_NUMMODE=2
|
||||
XCFLAGS+= -DLUAJIT_INTONLY
|
||||
# needed for the headers
|
||||
OPTS+=-DLUAJIT_INTONLY
|
||||
|
||||
ifdef MINGW
|
||||
TARGET_SYS= Windows
|
||||
HOST_MSYS= mingw
|
||||
endif
|
||||
|
||||
ifeq (Windows,$(findstring Windows,$(OS))$(MSYSTEM)$(TERM))
|
||||
HOST_SYS= Windows
|
||||
else
|
||||
HOST_SYS:= $(shell uname -s)
|
||||
ifneq (,$(findstring MINGW,$(HOST_SYS)))
|
||||
HOST_SYS= Windows
|
||||
HOST_MSYS= mingw
|
||||
endif
|
||||
ifneq (,$(findstring MSYS,$(HOST_SYS)))
|
||||
HOST_SYS= Windows
|
||||
HOST_MSYS= mingw
|
||||
endif
|
||||
ifneq (,$(findstring CYGWIN,$(HOST_SYS)))
|
||||
HOST_SYS= Windows
|
||||
HOST_MSYS= cygwin
|
||||
endif
|
||||
endif
|
||||
|
||||
ASOPTIONS= $(CCOPT) $(XCFLAGS) $(CFLAGS)
|
||||
CCOPTIONS= $(ASOPTIONS)
|
||||
|
||||
HOST_CC= $(CC)
|
||||
HOST_RM?= rm -f
|
||||
|
||||
HOST_XCFLAGS= -Ibluajit
|
||||
HOST_XLIBS=
|
||||
HOST_ACFLAGS= $(XCFLAGS) $(HOST_XCFLAGS) $(TARGET_ARCH)
|
||||
|
||||
TARGET_CC= $(CROSS)$(CC)
|
||||
|
||||
TARGET_LFSFLAGS= -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE
|
||||
TARGET_XCFLAGS= $(TARGET_LFSFLAGS) -U_FORTIFY_SOURCE
|
||||
TARGET_XLIBS= -lm
|
||||
TARGET_ACFLAGS= $(CCOPTIONS) $(TARGET_XCFLAGS) $(TARGET_FLAGS)
|
||||
TARGET_ASFLAGS= $(ASOPTIONS) $(TARGET_XCFLAGS) $(TARGET_FLAGS)
|
||||
TARGET_ACFLAGS+= $(LUA_CFLAGS)
|
||||
|
||||
TARGET_TESTARCH:=$(shell $(TARGET_CC) $(TARGET_ACFLAGS) -E bluajit/lj_arch.h -dM)
|
||||
ifneq (,$(findstring LJ_TARGET_X64 ,$(TARGET_TESTARCH)))
|
||||
TARGET_LJARCH= x64
|
||||
else
|
||||
ifneq (,$(findstring LJ_TARGET_X86 ,$(TARGET_TESTARCH)))
|
||||
TARGET_LJARCH= x86
|
||||
else
|
||||
ifneq (,$(findstring LJ_TARGET_ARM ,$(TARGET_TESTARCH)))
|
||||
TARGET_LJARCH= arm
|
||||
else
|
||||
ifneq (,$(findstring LJ_TARGET_ARM64 ,$(TARGET_TESTARCH)))
|
||||
ifneq (,$(findstring __AARCH64EB__ ,$(TARGET_TESTARCH)))
|
||||
TARGET_ARCH= -D__AARCH64EB__=1
|
||||
endif
|
||||
TARGET_LJARCH= arm64
|
||||
else
|
||||
ifneq (,$(findstring LJ_TARGET_PPC ,$(TARGET_TESTARCH)))
|
||||
ifneq (,$(findstring LJ_LE 1,$(TARGET_TESTARCH)))
|
||||
TARGET_ARCH= -DLJ_ARCH_ENDIAN=LUAJIT_LE
|
||||
else
|
||||
TARGET_ARCH= -DLJ_ARCH_ENDIAN=LUAJIT_BE
|
||||
endif
|
||||
TARGET_LJARCH= ppc
|
||||
else
|
||||
ifneq (,$(findstring LJ_TARGET_MIPS ,$(TARGET_TESTARCH)))
|
||||
ifneq (,$(findstring MIPSEL ,$(TARGET_TESTARCH)))
|
||||
TARGET_ARCH= -D__MIPSEL__=1
|
||||
endif
|
||||
ifneq (,$(findstring LJ_TARGET_MIPS64 ,$(TARGET_TESTARCH)))
|
||||
TARGET_LJARCH= mips64
|
||||
else
|
||||
TARGET_LJARCH= mips
|
||||
endif
|
||||
else
|
||||
$(error Unsupported target architecture)
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
ifneq (,$(findstring LJ_TARGET_PS3 1,$(TARGET_TESTARCH)))
|
||||
TARGET_SYS= PS3
|
||||
TARGET_ARCH+= -D__CELLOS_LV2__
|
||||
TARGET_XCFLAGS+= -DLUAJIT_USE_SYSMALLOC
|
||||
TARGET_XLIBS+= -lpthread
|
||||
endif
|
||||
|
||||
TARGET_ARCH+= $(patsubst %,-DLUAJIT_TARGET=LUAJIT_ARCH_%,$(TARGET_LJARCH))
|
||||
|
||||
ifneq (,$(PREFIX))
|
||||
ifneq (/usr/local,$(PREFIX))
|
||||
TARGET_XCFLAGS+= -DLUA_ROOT=\"$(PREFIX)\"
|
||||
endif
|
||||
endif
|
||||
ifneq (,$(MULTILIB))
|
||||
TARGET_XCFLAGS+= -DLUA_MULTILIB=\"$(MULTILIB)\"
|
||||
endif
|
||||
ifneq (,$(LMULTILIB))
|
||||
TARGET_XCFLAGS+= -DLUA_LMULTILIB=\"$(LMULTILIB)\"
|
||||
endif
|
||||
ifneq (,$(INSTALL_LJLIBD))
|
||||
TARGET_XCFLAGS+= -DLUA_LJDIR=\"$(INSTALL_LJLIBD)\"
|
||||
endif
|
||||
|
||||
##############################################################################
|
||||
# Target system detection.
|
||||
##############################################################################
|
||||
|
||||
TARGET_SYS?= $(HOST_SYS)
|
||||
ifeq (,$(shell $(TARGET_CC) -o /dev/null -c -x c /dev/null -fno-stack-protector 2>/dev/null || echo 1))
|
||||
TARGET_XCFLAGS+= -fno-stack-protector
|
||||
endif
|
||||
ifeq (Darwin,$(TARGET_SYS))
|
||||
ifeq (,$(MACOSX_DEPLOYMENT_TARGET))
|
||||
$(error missing: export MACOSX_DEPLOYMENT_TARGET=XX.YY)
|
||||
endif
|
||||
TARGET_XCFLAGS+= -DLUAJIT_UNWIND_EXTERNAL
|
||||
else
|
||||
ifeq (iOS,$(TARGET_SYS))
|
||||
ifeq (arm64,$(TARGET_LJARCH))
|
||||
TARGET_XCFLAGS+= -fno-omit-frame-pointer
|
||||
endif
|
||||
else
|
||||
ifeq (,$(findstring LJ_NO_UNWIND 1,$(TARGET_TESTARCH)))
|
||||
# Find out whether the target toolchain always generates unwind tables.
|
||||
TARGET_TESTUNWIND=$(shell exec 2>/dev/null; echo 'extern void b(void);int a(void){b();return 0;}' | $(TARGET_CC) -c -x c - -o tmpunwind.o && { grep -qa -e eh_frame -e __unwind_info tmpunwind.o || grep -qU -e eh_frame -e __unwind_info tmpunwind.o; } && echo E; rm -f tmpunwind.o)
|
||||
ifneq (,$(findstring E,$(TARGET_TESTUNWIND)))
|
||||
TARGET_XCFLAGS+= -DLUAJIT_UNWIND_EXTERNAL
|
||||
endif
|
||||
endif
|
||||
ifeq (Linux,$(TARGET_SYS))
|
||||
TARGET_XLIBS+= -ldl
|
||||
endif
|
||||
ifeq (GNU/kFreeBSD,$(TARGET_SYS))
|
||||
TARGET_XLIBS+= -ldl
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
ifneq ($(HOST_SYS),$(TARGET_SYS))
|
||||
ifeq (Windows,$(TARGET_SYS))
|
||||
HOST_XCFLAGS+= -malign-double -DLUAJIT_OS=LUAJIT_OS_WINDOWS
|
||||
else
|
||||
ifeq (Linux,$(TARGET_SYS))
|
||||
HOST_XCFLAGS+= -DLUAJIT_OS=LUAJIT_OS_LINUX
|
||||
else
|
||||
ifeq (Darwin,$(TARGET_SYS))
|
||||
HOST_XCFLAGS+= -DLUAJIT_OS=LUAJIT_OS_OSX
|
||||
else
|
||||
ifeq (iOS,$(TARGET_SYS))
|
||||
HOST_XCFLAGS+= -DLUAJIT_OS=LUAJIT_OS_OSX -DTARGET_OS_IPHONE=1
|
||||
else
|
||||
HOST_XCFLAGS+= -DLUAJIT_OS=LUAJIT_OS_OTHER
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
##############################################################################
|
||||
# Files and pathnames.
|
||||
##############################################################################
|
||||
|
||||
MINILUA_O= $(OBJDIR)/minilua.o
|
||||
MINILUA_LIBS= -lm
|
||||
MINILUA_T= $(OBJDIR)/minilua
|
||||
MINILUA_X= $(MINILUA_T)
|
||||
MINILUA_DEP=
|
||||
|
||||
HOST_LUA= $(MINILUA_X)
|
||||
MINILUA_DEP= $(MINILUA_T)
|
||||
|
||||
DASM_DIR= bluajit/dynasm
|
||||
DASM= $(HOST_LUA) $(DASM_DIR)/dynasm.lua
|
||||
DASM_XFLAGS=
|
||||
DASM_AFLAGS=
|
||||
DASM_ARCH= $(TARGET_LJARCH)
|
||||
|
||||
ifneq (,$(findstring LJ_LE 1,$(TARGET_TESTARCH)))
|
||||
DASM_AFLAGS+= -D ENDIAN_LE
|
||||
else
|
||||
DASM_AFLAGS+= -D ENDIAN_BE
|
||||
endif
|
||||
ifneq (,$(findstring LJ_ARCH_BITS 64,$(TARGET_TESTARCH)))
|
||||
DASM_AFLAGS+= -D P64
|
||||
endif
|
||||
ifneq (,$(findstring LJ_HASJIT 1,$(TARGET_TESTARCH)))
|
||||
DASM_AFLAGS+= -D JIT
|
||||
endif
|
||||
ifneq (,$(findstring LJ_HASFFI 1,$(TARGET_TESTARCH)))
|
||||
DASM_AFLAGS+= -D FFI
|
||||
endif
|
||||
ifneq (,$(findstring LJ_DUALNUM 1,$(TARGET_TESTARCH)))
|
||||
DASM_AFLAGS+= -D DUALNUM
|
||||
endif
|
||||
ifneq (,$(findstring LJ_INTONLY 1,$(TARGET_TESTARCH)))
|
||||
DASM_AFLAGS+= -D INTONLY
|
||||
endif
|
||||
ifneq (,$(findstring LJ_ARCH_HASFPU 1,$(TARGET_TESTARCH)))
|
||||
DASM_AFLAGS+= -D FPU
|
||||
TARGET_ARCH+= -DLJ_ARCH_HASFPU=1
|
||||
else
|
||||
TARGET_ARCH+= -DLJ_ARCH_HASFPU=0
|
||||
endif
|
||||
ifeq (,$(findstring LJ_ABI_SOFTFP 1,$(TARGET_TESTARCH)))
|
||||
DASM_AFLAGS+= -D HFABI
|
||||
TARGET_ARCH+= -DLJ_ABI_SOFTFP=0
|
||||
else
|
||||
TARGET_ARCH+= -DLJ_ABI_SOFTFP=1
|
||||
endif
|
||||
ifneq (,$(findstring LJ_NO_UNWIND 1,$(TARGET_TESTARCH)))
|
||||
DASM_AFLAGS+= -D NO_UNWIND
|
||||
TARGET_ARCH+= -DLUAJIT_NO_UNWIND
|
||||
endif
|
||||
ifneq (,$(findstring LJ_ABI_PAUTH 1,$(TARGET_TESTARCH)))
|
||||
DASM_AFLAGS+= -D PAUTH
|
||||
TARGET_ARCH+= -DLJ_ABI_PAUTH=1
|
||||
endif
|
||||
DASM_AFLAGS+= -D VER=$(subst LJ_ARCH_VERSION_,,$(filter LJ_ARCH_VERSION_%,$(subst LJ_ARCH_VERSION ,LJ_ARCH_VERSION_,$(TARGET_TESTARCH))))
|
||||
ifeq (Windows,$(TARGET_SYS))
|
||||
DASM_AFLAGS+= -D WIN
|
||||
endif
|
||||
ifeq (x64,$(TARGET_LJARCH))
|
||||
ifeq (,$(findstring LJ_FR2 1,$(TARGET_TESTARCH)))
|
||||
DASM_ARCH= x86
|
||||
endif
|
||||
else
|
||||
ifeq (arm,$(TARGET_LJARCH))
|
||||
ifeq (iOS,$(TARGET_SYS))
|
||||
DASM_AFLAGS+= -D IOS
|
||||
endif
|
||||
else
|
||||
ifneq (,$(findstring LJ_TARGET_MIPSR6 ,$(TARGET_TESTARCH)))
|
||||
DASM_AFLAGS+= -D MIPSR6
|
||||
endif
|
||||
ifeq (ppc,$(TARGET_LJARCH))
|
||||
ifneq (,$(findstring LJ_ARCH_SQRT 1,$(TARGET_TESTARCH)))
|
||||
DASM_AFLAGS+= -D SQRT
|
||||
endif
|
||||
ifneq (,$(findstring LJ_ARCH_ROUND 1,$(TARGET_TESTARCH)))
|
||||
DASM_AFLAGS+= -D ROUND
|
||||
endif
|
||||
ifneq (,$(findstring LJ_ARCH_PPC32ON64 1,$(TARGET_TESTARCH)))
|
||||
DASM_AFLAGS+= -D GPR64
|
||||
endif
|
||||
ifeq (PS3,$(TARGET_SYS))
|
||||
DASM_AFLAGS+= -D PPE -D TOC
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
DASM_FLAGS= $(DASM_XFLAGS) $(DASM_AFLAGS)
|
||||
DASM_DASC= bluajit/vm_$(DASM_ARCH).dasc
|
||||
|
||||
GIT= git
|
||||
ifeq (Windows,$(HOST_SYS)$(HOST_MSYS))
|
||||
GIT_RELVER= if exist ..\.git ( $(GIT) show -s --format=%%ct >bluajit/luajit_relver.txt ) else ( type ..\.relver >bluajit/luajit_relver.txt )
|
||||
else
|
||||
GIT_RELVER= [ -e ../.git ] && $(GIT) show -s --format=%ct >bluajit/luajit_relver.txt 2>/dev/null || cat ../.relver >bluajit/luajit_relver.txt 2>/dev/null || :
|
||||
endif
|
||||
GIT_DEP= $(wildcard ../.git/HEAD ../.git/refs/heads/*)
|
||||
|
||||
BUILDVM_O= $(OBJDIR)/buildvm.o $(OBJDIR)/buildvm_asm.o $(OBJDIR)/buildvm_peobj.o \
|
||||
$(OBJDIR)/buildvm_lib.o $(OBJDIR)/buildvm_fold.o
|
||||
BUILDVM_T= $(OBJDIR)/buildvm
|
||||
BUILDVM_X= $(BUILDVM_T)
|
||||
|
||||
HOST_O= $(MINILUA_O) $(BUILDVM_O)
|
||||
HOST_T= $(MINILUA_T) $(BUILDVM_T)
|
||||
|
||||
LJVM_S= $(OBJDIR)/lj_vm.S
|
||||
LJVM_O= $(OBJDIR)/lj_vm.o
|
||||
LJVM_BOUT= $(LJVM_S)
|
||||
LJVM_MODE= elfasm
|
||||
|
||||
LJLIB_O= lib_base.o lib_string.o lib_table.o lib_io.o lib_jit.o
|
||||
ifeq (,$(filter -DLUAJIT_SRB2LIB,$(XCFLAGS)))
|
||||
LJLIB_O+= lib_math.o lib_bit.o lib_os.o lib_package.o lib_debug.o lib_ffi.o lib_buffer.o
|
||||
else
|
||||
ifneq (,$(filter -DLUAJIT_SRB2LIB_OS,$(XCFLAGS)))
|
||||
LJLIB_O+= lib_os.o
|
||||
endif
|
||||
ifneq (,$(filter -DLUAJIT_SRB2LIB_DEBUG,$(XCFLAGS)))
|
||||
LJLIB_O+= lib_debug.o
|
||||
endif
|
||||
endif
|
||||
LJLIB_C= $(addprefix bluajit/,$(LJLIB_O:.o=.c))
|
||||
|
||||
LJCORE_O= lj_assert.o lj_gc.o lj_err.o lj_char.o lj_bc.o lj_obj.o lj_buf.o \
|
||||
lj_str.o lj_tab.o lj_func.o lj_udata.o lj_meta.o lj_debug.o \
|
||||
lj_prng.o lj_state.o lj_dispatch.o lj_vmevent.o lj_vmmath.o \
|
||||
lj_strscan.o lj_strfmt.o lj_strfmt_num.o lj_serialize.o \
|
||||
lj_api.o lj_profile.o \
|
||||
lj_lex.o lj_parse.o lj_bcread.o lj_bcwrite.o lj_load.o \
|
||||
lj_ir.o lj_opt_mem.o lj_opt_fold.o lj_opt_narrow.o \
|
||||
lj_opt_dce.o lj_opt_loop.o lj_opt_split.o lj_opt_sink.o \
|
||||
lj_mcode.o lj_snap.o lj_record.o lj_crecord.o lj_ffrecord.o \
|
||||
lj_asm.o lj_trace.o lj_gdbjit.o \
|
||||
lj_ctype.o lj_cdata.o lj_cconv.o lj_ccall.o lj_ccallback.o \
|
||||
lj_carith.o lj_clib.o lj_cparse.o \
|
||||
lj_lib.o lj_alloc.o lib_aux.o \
|
||||
$(LJLIB_O) lib_init.o
|
||||
|
||||
LJCORE_O:= $(addprefix $(OBJDIR)/,$(LJCORE_O))
|
||||
LJVMCORE_O= $(LJVM_O) $(LJCORE_O)
|
||||
|
||||
LIB_VMDEF= bluajit/jit/vmdef.lua
|
||||
LIB_VMDEFP= $(LIB_VMDEF)
|
||||
|
||||
ALL_T= $(HOST_T)
|
||||
ALL_HDRGEN:= lj_bcdef.h lj_ffdef.h lj_libdef.h lj_recdef.h lj_folddef.h \
|
||||
host/buildvm_arch.h luajit.h
|
||||
ALL_HDRGEN:= $(addprefix bluajit/,$(ALL_HDRGEN))
|
||||
ALL_GEN= $(LJVM_S) $(ALL_HDRGEN) bluajit/luajit_relver.txt $(LIB_VMDEFP)
|
||||
|
||||
##############################################################################
|
||||
# Build mode handling.
|
||||
##############################################################################
|
||||
|
||||
ifeq (Windows,$(TARGET_SYS))
|
||||
LJVM_MODE= peobj
|
||||
LJVM_BOUT= $(LJVM_O)
|
||||
endif
|
||||
ifeq (Darwin,$(TARGET_SYS))
|
||||
LJVM_MODE= machasm
|
||||
endif
|
||||
ifeq (iOS,$(TARGET_SYS))
|
||||
LJVM_MODE= machasm
|
||||
endif
|
||||
|
||||
ifeq (Windows,$(TARGET_SYS))
|
||||
MINILUA_T= $(OBJDIR)/minilua.exe
|
||||
BUILDVM_T= $(OBJDIR)/buildvm.exe
|
||||
ifeq (,$(HOST_MSYS))
|
||||
MINILUA_X= $(OBJDIR)\minilua
|
||||
BUILDVM_X= $(OBJDIR)\buildvm
|
||||
HOST_RM= del
|
||||
endif
|
||||
endif
|
||||
|
||||
|
||||
OBJS:=$(OBJS) \
|
||||
$(LJVMCORE_O) \
|
||||
$(OBJDIR)/lua_script.o \
|
||||
$(OBJDIR)/lua_baselib.o \
|
||||
$(OBJDIR)/lua_blockmaplib.o \
|
||||
$(OBJDIR)/lua_mathlib.o \
|
||||
$(OBJDIR)/lua_hooklib.o \
|
||||
$(OBJDIR)/lua_consolelib.o \
|
||||
$(OBJDIR)/lua_infolib.o \
|
||||
$(OBJDIR)/lua_mobjlib.o \
|
||||
$(OBJDIR)/lua_playerlib.o \
|
||||
$(OBJDIR)/lua_skinlib.o \
|
||||
$(OBJDIR)/lua_thinkerlib.o \
|
||||
$(OBJDIR)/lua_maplib.o \
|
||||
$(OBJDIR)/hashtable.o \
|
||||
$(OBJDIR)/lua_hudlib.o \
|
||||
$(OBJDIR)/lua_hudlib_drawlist.o \
|
||||
$(OBJDIR)/lua_udatalib.o \
|
||||
$(OBJDIR)/lua_glib.o
|
||||
|
||||
@@ -1,63 +0,0 @@
|
||||
Q= @
|
||||
E= @true
|
||||
#Q=
|
||||
#E= @:
|
||||
|
||||
$(MINILUA_T): $(MINILUA_O)
|
||||
$(E) "HOSTLINK $@"
|
||||
$(HOST_CC) -o $@ $(MINILUA_O) $(MINILUA_LIBS)
|
||||
|
||||
bluajit/luajit.h: $(MINILUA_DEP) $(GIT_DEP) bluajit/luajit_rolling.h
|
||||
$(E) "VERSION $@"
|
||||
$(Q)$(GIT_RELVER)
|
||||
$(Q)cd bluajit && ../$(HOST_LUA) host/genversion.lua
|
||||
|
||||
bluajit/host/buildvm_arch.h: $(DASM_DASC) $(MINILUA_DEP) bluajit/lj_arch.h bluajit/lua.h bluajit/luaconf.h
|
||||
$(E) "DYNASM $@"
|
||||
$(Q)$(DASM) $(DASM_FLAGS) -o $@ $(DASM_DASC)
|
||||
|
||||
$(OBJDIR)/buildvm.o: $(DASM_DIR)/dasm_*.h
|
||||
|
||||
$(BUILDVM_T): $(BUILDVM_O)
|
||||
$(E) "HOSTLINK $@"
|
||||
$(HOST_CC) -o $@ $(BUILDVM_O)
|
||||
|
||||
$(LJVM_BOUT): $(BUILDVM_T)
|
||||
$(E) "BUILDVM $@"
|
||||
$(Q)$(BUILDVM_X) -m $(LJVM_MODE) -o $@
|
||||
|
||||
bluajit/lj_bcdef.h: $(BUILDVM_T) $(LJLIB_C)
|
||||
$(E) "BUILDVM $@"
|
||||
$(Q)$(BUILDVM_X) -m bcdef -o $@ $(LJLIB_C)
|
||||
|
||||
bluajit/lj_ffdef.h: $(BUILDVM_T) $(LJLIB_C)
|
||||
$(E) "BUILDVM $@"
|
||||
$(Q)$(BUILDVM_X) -m ffdef -o $@ $(LJLIB_C)
|
||||
|
||||
bluajit/lj_libdef.h: $(BUILDVM_T) $(LJLIB_C)
|
||||
$(E) "BUILDVM $@"
|
||||
$(Q)$(BUILDVM_X) -m libdef -o $@ $(LJLIB_C)
|
||||
|
||||
bluajit/lj_recdef.h: $(BUILDVM_T) $(LJLIB_C)
|
||||
$(E) "BUILDVM $@"
|
||||
$(Q)$(BUILDVM_X) -m recdef -o $@ $(LJLIB_C)
|
||||
|
||||
$(LIB_VMDEF): $(BUILDVM_T) $(LJLIB_C)
|
||||
$(E) "BUILDVM $@"
|
||||
$(Q)$(BUILDVM_X) -m vmdef -o $(LIB_VMDEFP) $(LJLIB_C)
|
||||
|
||||
bluajit/lj_folddef.h: $(BUILDVM_T) bluajit/lj_opt_fold.c
|
||||
$(E) "BUILDVM $@"
|
||||
$(Q)$(BUILDVM_X) -m folddef -o $@ bluajit/lj_opt_fold.c
|
||||
|
||||
$(OBJDIR)/%.o: bluajit/%.c
|
||||
$(E) "CC $@"
|
||||
$(TARGET_CC) $(TARGET_ACFLAGS) -c -o $@ $<
|
||||
|
||||
$(OBJDIR)/%.o: $(OBJDIR)/lj_vm.S
|
||||
$(E) "ASM $@"
|
||||
$(TARGET_CC) $(TARGET_ASFLAGS) -c -o $@ $<
|
||||
|
||||
$(HOST_O): $(OBJDIR)/%.o: bluajit/host/%.c
|
||||
$(E) "HOSTCC $@"
|
||||
$(HOST_CC) $(HOST_ACFLAGS) -c -o $@ $<
|
||||
@@ -1,456 +0,0 @@
|
||||
/*
|
||||
** DynASM ARM encoding engine.
|
||||
** Copyright (C) 2005-2023 Mike Pall. All rights reserved.
|
||||
** Released under the MIT license. See dynasm.lua for full copyright notice.
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define DASM_ARCH "arm"
|
||||
|
||||
#ifndef DASM_EXTERN
|
||||
#define DASM_EXTERN(a,b,c,d) 0
|
||||
#endif
|
||||
|
||||
/* Action definitions. */
|
||||
enum {
|
||||
DASM_STOP, DASM_SECTION, DASM_ESC, DASM_REL_EXT,
|
||||
/* The following actions need a buffer position. */
|
||||
DASM_ALIGN, DASM_REL_LG, DASM_LABEL_LG,
|
||||
/* The following actions also have an argument. */
|
||||
DASM_REL_PC, DASM_LABEL_PC,
|
||||
DASM_IMM, DASM_IMM12, DASM_IMM16, DASM_IMML8, DASM_IMML12, DASM_IMMV8,
|
||||
DASM__MAX
|
||||
};
|
||||
|
||||
/* Maximum number of section buffer positions for a single dasm_put() call. */
|
||||
#define DASM_MAXSECPOS 25
|
||||
|
||||
/* DynASM encoder status codes. Action list offset or number are or'ed in. */
|
||||
#define DASM_S_OK 0x00000000
|
||||
#define DASM_S_NOMEM 0x01000000
|
||||
#define DASM_S_PHASE 0x02000000
|
||||
#define DASM_S_MATCH_SEC 0x03000000
|
||||
#define DASM_S_RANGE_I 0x11000000
|
||||
#define DASM_S_RANGE_SEC 0x12000000
|
||||
#define DASM_S_RANGE_LG 0x13000000
|
||||
#define DASM_S_RANGE_PC 0x14000000
|
||||
#define DASM_S_RANGE_REL 0x15000000
|
||||
#define DASM_S_UNDEF_LG 0x21000000
|
||||
#define DASM_S_UNDEF_PC 0x22000000
|
||||
|
||||
/* Macros to convert positions (8 bit section + 24 bit index). */
|
||||
#define DASM_POS2IDX(pos) ((pos)&0x00ffffff)
|
||||
#define DASM_POS2BIAS(pos) ((pos)&0xff000000)
|
||||
#define DASM_SEC2POS(sec) ((sec)<<24)
|
||||
#define DASM_POS2SEC(pos) ((pos)>>24)
|
||||
#define DASM_POS2PTR(D, pos) (D->sections[DASM_POS2SEC(pos)].rbuf + (pos))
|
||||
|
||||
/* Action list type. */
|
||||
typedef const unsigned int *dasm_ActList;
|
||||
|
||||
/* Per-section structure. */
|
||||
typedef struct dasm_Section {
|
||||
int *rbuf; /* Biased buffer pointer (negative section bias). */
|
||||
int *buf; /* True buffer pointer. */
|
||||
size_t bsize; /* Buffer size in bytes. */
|
||||
int pos; /* Biased buffer position. */
|
||||
int epos; /* End of biased buffer position - max single put. */
|
||||
int ofs; /* Byte offset into section. */
|
||||
} dasm_Section;
|
||||
|
||||
/* Core structure holding the DynASM encoding state. */
|
||||
struct dasm_State {
|
||||
size_t psize; /* Allocated size of this structure. */
|
||||
dasm_ActList actionlist; /* Current actionlist pointer. */
|
||||
int *lglabels; /* Local/global chain/pos ptrs. */
|
||||
size_t lgsize;
|
||||
int *pclabels; /* PC label chains/pos ptrs. */
|
||||
size_t pcsize;
|
||||
void **globals; /* Array of globals. */
|
||||
dasm_Section *section; /* Pointer to active section. */
|
||||
size_t codesize; /* Total size of all code sections. */
|
||||
int maxsection; /* 0 <= sectionidx < maxsection. */
|
||||
int status; /* Status code. */
|
||||
dasm_Section sections[1]; /* All sections. Alloc-extended. */
|
||||
};
|
||||
|
||||
/* The size of the core structure depends on the max. number of sections. */
|
||||
#define DASM_PSZ(ms) (sizeof(dasm_State)+(ms-1)*sizeof(dasm_Section))
|
||||
|
||||
|
||||
/* Initialize DynASM state. */
|
||||
void dasm_init(Dst_DECL, int maxsection)
|
||||
{
|
||||
dasm_State *D;
|
||||
size_t psz = 0;
|
||||
Dst_REF = NULL;
|
||||
DASM_M_GROW(Dst, struct dasm_State, Dst_REF, psz, DASM_PSZ(maxsection));
|
||||
D = Dst_REF;
|
||||
D->psize = psz;
|
||||
D->lglabels = NULL;
|
||||
D->lgsize = 0;
|
||||
D->pclabels = NULL;
|
||||
D->pcsize = 0;
|
||||
D->globals = NULL;
|
||||
D->maxsection = maxsection;
|
||||
memset((void *)D->sections, 0, maxsection * sizeof(dasm_Section));
|
||||
}
|
||||
|
||||
/* Free DynASM state. */
|
||||
void dasm_free(Dst_DECL)
|
||||
{
|
||||
dasm_State *D = Dst_REF;
|
||||
int i;
|
||||
for (i = 0; i < D->maxsection; i++)
|
||||
if (D->sections[i].buf)
|
||||
DASM_M_FREE(Dst, D->sections[i].buf, D->sections[i].bsize);
|
||||
if (D->pclabels) DASM_M_FREE(Dst, D->pclabels, D->pcsize);
|
||||
if (D->lglabels) DASM_M_FREE(Dst, D->lglabels, D->lgsize);
|
||||
DASM_M_FREE(Dst, D, D->psize);
|
||||
}
|
||||
|
||||
/* Setup global label array. Must be called before dasm_setup(). */
|
||||
void dasm_setupglobal(Dst_DECL, void **gl, unsigned int maxgl)
|
||||
{
|
||||
dasm_State *D = Dst_REF;
|
||||
D->globals = gl;
|
||||
DASM_M_GROW(Dst, int, D->lglabels, D->lgsize, (10+maxgl)*sizeof(int));
|
||||
}
|
||||
|
||||
/* Grow PC label array. Can be called after dasm_setup(), too. */
|
||||
void dasm_growpc(Dst_DECL, unsigned int maxpc)
|
||||
{
|
||||
dasm_State *D = Dst_REF;
|
||||
size_t osz = D->pcsize;
|
||||
DASM_M_GROW(Dst, int, D->pclabels, D->pcsize, maxpc*sizeof(int));
|
||||
memset((void *)(((unsigned char *)D->pclabels)+osz), 0, D->pcsize-osz);
|
||||
}
|
||||
|
||||
/* Setup encoder. */
|
||||
void dasm_setup(Dst_DECL, const void *actionlist)
|
||||
{
|
||||
dasm_State *D = Dst_REF;
|
||||
int i;
|
||||
D->actionlist = (dasm_ActList)actionlist;
|
||||
D->status = DASM_S_OK;
|
||||
D->section = &D->sections[0];
|
||||
memset((void *)D->lglabels, 0, D->lgsize);
|
||||
if (D->pclabels) memset((void *)D->pclabels, 0, D->pcsize);
|
||||
for (i = 0; i < D->maxsection; i++) {
|
||||
D->sections[i].pos = DASM_SEC2POS(i);
|
||||
D->sections[i].rbuf = D->sections[i].buf - D->sections[i].pos;
|
||||
D->sections[i].ofs = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifdef DASM_CHECKS
|
||||
#define CK(x, st) \
|
||||
do { if (!(x)) { \
|
||||
D->status = DASM_S_##st|(p-D->actionlist-1); return; } } while (0)
|
||||
#define CKPL(kind, st) \
|
||||
do { if ((size_t)((char *)pl-(char *)D->kind##labels) >= D->kind##size) { \
|
||||
D->status = DASM_S_RANGE_##st|(p-D->actionlist-1); return; } } while (0)
|
||||
#else
|
||||
#define CK(x, st) ((void)0)
|
||||
#define CKPL(kind, st) ((void)0)
|
||||
#endif
|
||||
|
||||
static int dasm_imm12(unsigned int n)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < 16; i++, n = (n << 2) | (n >> 30))
|
||||
if (n <= 255) return (int)(n + (i << 8));
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Pass 1: Store actions and args, link branches/labels, estimate offsets. */
|
||||
void dasm_put(Dst_DECL, int start, ...)
|
||||
{
|
||||
va_list ap;
|
||||
dasm_State *D = Dst_REF;
|
||||
dasm_ActList p = D->actionlist + start;
|
||||
dasm_Section *sec = D->section;
|
||||
int pos = sec->pos, ofs = sec->ofs;
|
||||
int *b;
|
||||
|
||||
if (pos >= sec->epos) {
|
||||
DASM_M_GROW(Dst, int, sec->buf, sec->bsize,
|
||||
sec->bsize + 2*DASM_MAXSECPOS*sizeof(int));
|
||||
sec->rbuf = sec->buf - DASM_POS2BIAS(pos);
|
||||
sec->epos = (int)sec->bsize/sizeof(int) - DASM_MAXSECPOS+DASM_POS2BIAS(pos);
|
||||
}
|
||||
|
||||
b = sec->rbuf;
|
||||
b[pos++] = start;
|
||||
|
||||
va_start(ap, start);
|
||||
while (1) {
|
||||
unsigned int ins = *p++;
|
||||
unsigned int action = (ins >> 16);
|
||||
if (action >= DASM__MAX) {
|
||||
ofs += 4;
|
||||
} else {
|
||||
int *pl, n = action >= DASM_REL_PC ? va_arg(ap, int) : 0;
|
||||
switch (action) {
|
||||
case DASM_STOP: goto stop;
|
||||
case DASM_SECTION:
|
||||
n = (ins & 255); CK(n < D->maxsection, RANGE_SEC);
|
||||
D->section = &D->sections[n]; goto stop;
|
||||
case DASM_ESC: p++; ofs += 4; break;
|
||||
case DASM_REL_EXT: break;
|
||||
case DASM_ALIGN: ofs += (ins & 255); b[pos++] = ofs; break;
|
||||
case DASM_REL_LG:
|
||||
n = (ins & 2047) - 10; pl = D->lglabels + n;
|
||||
/* Bkwd rel or global. */
|
||||
if (n >= 0) { CK(n>=10||*pl<0, RANGE_LG); CKPL(lg, LG); goto putrel; }
|
||||
pl += 10; n = *pl;
|
||||
if (n < 0) n = 0; /* Start new chain for fwd rel if label exists. */
|
||||
goto linkrel;
|
||||
case DASM_REL_PC:
|
||||
pl = D->pclabels + n; CKPL(pc, PC);
|
||||
putrel:
|
||||
n = *pl;
|
||||
if (n < 0) { /* Label exists. Get label pos and store it. */
|
||||
b[pos] = -n;
|
||||
} else {
|
||||
linkrel:
|
||||
b[pos] = n; /* Else link to rel chain, anchored at label. */
|
||||
*pl = pos;
|
||||
}
|
||||
pos++;
|
||||
break;
|
||||
case DASM_LABEL_LG:
|
||||
pl = D->lglabels + (ins & 2047) - 10; CKPL(lg, LG); goto putlabel;
|
||||
case DASM_LABEL_PC:
|
||||
pl = D->pclabels + n; CKPL(pc, PC);
|
||||
putlabel:
|
||||
n = *pl; /* n > 0: Collapse rel chain and replace with label pos. */
|
||||
while (n > 0) { int *pb = DASM_POS2PTR(D, n); n = *pb; *pb = pos;
|
||||
}
|
||||
*pl = -pos; /* Label exists now. */
|
||||
b[pos++] = ofs; /* Store pass1 offset estimate. */
|
||||
break;
|
||||
case DASM_IMM:
|
||||
case DASM_IMM16:
|
||||
#ifdef DASM_CHECKS
|
||||
CK((n & ((1<<((ins>>10)&31))-1)) == 0, RANGE_I);
|
||||
if ((ins & 0x8000))
|
||||
CK(((n + (1<<(((ins>>5)&31)-1)))>>((ins>>5)&31)) == 0, RANGE_I);
|
||||
else
|
||||
CK((n>>((ins>>5)&31)) == 0, RANGE_I);
|
||||
#endif
|
||||
b[pos++] = n;
|
||||
break;
|
||||
case DASM_IMMV8:
|
||||
CK((n & 3) == 0, RANGE_I);
|
||||
n >>= 2;
|
||||
/* fallthrough */
|
||||
case DASM_IMML8:
|
||||
case DASM_IMML12:
|
||||
CK(n >= 0 ? ((n>>((ins>>5)&31)) == 0) :
|
||||
(((-n)>>((ins>>5)&31)) == 0), RANGE_I);
|
||||
b[pos++] = n;
|
||||
break;
|
||||
case DASM_IMM12:
|
||||
CK(dasm_imm12((unsigned int)n) != -1, RANGE_I);
|
||||
b[pos++] = n;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
stop:
|
||||
va_end(ap);
|
||||
sec->pos = pos;
|
||||
sec->ofs = ofs;
|
||||
}
|
||||
#undef CK
|
||||
|
||||
/* Pass 2: Link sections, shrink aligns, fix label offsets. */
|
||||
int dasm_link(Dst_DECL, size_t *szp)
|
||||
{
|
||||
dasm_State *D = Dst_REF;
|
||||
int secnum;
|
||||
int ofs = 0;
|
||||
|
||||
#ifdef DASM_CHECKS
|
||||
*szp = 0;
|
||||
if (D->status != DASM_S_OK) return D->status;
|
||||
{
|
||||
int pc;
|
||||
for (pc = 0; pc*sizeof(int) < D->pcsize; pc++)
|
||||
if (D->pclabels[pc] > 0) return DASM_S_UNDEF_PC|pc;
|
||||
}
|
||||
#endif
|
||||
|
||||
{ /* Handle globals not defined in this translation unit. */
|
||||
int idx;
|
||||
for (idx = 10; idx*sizeof(int) < D->lgsize; idx++) {
|
||||
int n = D->lglabels[idx];
|
||||
/* Undefined label: Collapse rel chain and replace with marker (< 0). */
|
||||
while (n > 0) { int *pb = DASM_POS2PTR(D, n); n = *pb; *pb = -idx; }
|
||||
}
|
||||
}
|
||||
|
||||
/* Combine all code sections. No support for data sections (yet). */
|
||||
for (secnum = 0; secnum < D->maxsection; secnum++) {
|
||||
dasm_Section *sec = D->sections + secnum;
|
||||
int *b = sec->rbuf;
|
||||
int pos = DASM_SEC2POS(secnum);
|
||||
int lastpos = sec->pos;
|
||||
|
||||
while (pos != lastpos) {
|
||||
dasm_ActList p = D->actionlist + b[pos++];
|
||||
while (1) {
|
||||
unsigned int ins = *p++;
|
||||
unsigned int action = (ins >> 16);
|
||||
switch (action) {
|
||||
case DASM_STOP: case DASM_SECTION: goto stop;
|
||||
case DASM_ESC: p++; break;
|
||||
case DASM_REL_EXT: break;
|
||||
case DASM_ALIGN: ofs -= (b[pos++] + ofs) & (ins & 255); break;
|
||||
case DASM_REL_LG: case DASM_REL_PC: pos++; break;
|
||||
case DASM_LABEL_LG: case DASM_LABEL_PC: b[pos++] += ofs; break;
|
||||
case DASM_IMM: case DASM_IMM12: case DASM_IMM16:
|
||||
case DASM_IMML8: case DASM_IMML12: case DASM_IMMV8: pos++; break;
|
||||
}
|
||||
}
|
||||
stop: (void)0;
|
||||
}
|
||||
ofs += sec->ofs; /* Next section starts right after current section. */
|
||||
}
|
||||
|
||||
D->codesize = ofs; /* Total size of all code sections */
|
||||
*szp = ofs;
|
||||
return DASM_S_OK;
|
||||
}
|
||||
|
||||
#ifdef DASM_CHECKS
|
||||
#define CK(x, st) \
|
||||
do { if (!(x)) return DASM_S_##st|(p-D->actionlist-1); } while (0)
|
||||
#else
|
||||
#define CK(x, st) ((void)0)
|
||||
#endif
|
||||
|
||||
/* Pass 3: Encode sections. */
|
||||
int dasm_encode(Dst_DECL, void *buffer)
|
||||
{
|
||||
dasm_State *D = Dst_REF;
|
||||
char *base = (char *)buffer;
|
||||
unsigned int *cp = (unsigned int *)buffer;
|
||||
int secnum;
|
||||
|
||||
/* Encode all code sections. No support for data sections (yet). */
|
||||
for (secnum = 0; secnum < D->maxsection; secnum++) {
|
||||
dasm_Section *sec = D->sections + secnum;
|
||||
int *b = sec->buf;
|
||||
int *endb = sec->rbuf + sec->pos;
|
||||
|
||||
while (b != endb) {
|
||||
dasm_ActList p = D->actionlist + *b++;
|
||||
while (1) {
|
||||
unsigned int ins = *p++;
|
||||
unsigned int action = (ins >> 16);
|
||||
int n = (action >= DASM_ALIGN && action < DASM__MAX) ? *b++ : 0;
|
||||
switch (action) {
|
||||
case DASM_STOP: case DASM_SECTION: goto stop;
|
||||
case DASM_ESC: *cp++ = *p++; break;
|
||||
case DASM_REL_EXT:
|
||||
n = DASM_EXTERN(Dst, (unsigned char *)cp, (ins&2047), !(ins&2048));
|
||||
goto patchrel;
|
||||
case DASM_ALIGN:
|
||||
ins &= 255; while ((((char *)cp - base) & ins)) *cp++ = 0xe1a00000;
|
||||
break;
|
||||
case DASM_REL_LG:
|
||||
if (n < 0) {
|
||||
n = (int)((ptrdiff_t)D->globals[-n-10] - (ptrdiff_t)cp - 4);
|
||||
goto patchrel;
|
||||
}
|
||||
/* fallthrough */
|
||||
case DASM_REL_PC:
|
||||
CK(n >= 0, UNDEF_PC);
|
||||
n = *DASM_POS2PTR(D, n) - (int)((char *)cp - base) - 4;
|
||||
patchrel:
|
||||
if ((ins & 0x800) == 0) {
|
||||
CK((n & 3) == 0 && ((n+0x02000000) >> 26) == 0, RANGE_REL);
|
||||
cp[-1] |= ((n >> 2) & 0x00ffffff);
|
||||
} else if ((ins & 0x1000)) {
|
||||
CK((n & 3) == 0 && -256 <= n && n <= 256, RANGE_REL);
|
||||
goto patchimml8;
|
||||
} else if ((ins & 0x2000) == 0) {
|
||||
CK((n & 3) == 0 && -4096 <= n && n <= 4096, RANGE_REL);
|
||||
goto patchimml;
|
||||
} else {
|
||||
CK((n & 3) == 0 && -1020 <= n && n <= 1020, RANGE_REL);
|
||||
n >>= 2;
|
||||
goto patchimml;
|
||||
}
|
||||
break;
|
||||
case DASM_LABEL_LG:
|
||||
ins &= 2047; if (ins >= 20) D->globals[ins-20] = (void *)(base + n);
|
||||
break;
|
||||
case DASM_LABEL_PC: break;
|
||||
case DASM_IMM:
|
||||
cp[-1] |= ((n>>((ins>>10)&31)) & ((1<<((ins>>5)&31))-1)) << (ins&31);
|
||||
break;
|
||||
case DASM_IMM12:
|
||||
cp[-1] |= dasm_imm12((unsigned int)n);
|
||||
break;
|
||||
case DASM_IMM16:
|
||||
cp[-1] |= ((n & 0xf000) << 4) | (n & 0x0fff);
|
||||
break;
|
||||
case DASM_IMML8: patchimml8:
|
||||
cp[-1] |= n >= 0 ? (0x00800000 | (n & 0x0f) | ((n & 0xf0) << 4)) :
|
||||
((-n & 0x0f) | ((-n & 0xf0) << 4));
|
||||
break;
|
||||
case DASM_IMML12: case DASM_IMMV8: patchimml:
|
||||
cp[-1] |= n >= 0 ? (0x00800000 | n) : (-n);
|
||||
break;
|
||||
default: *cp++ = ins; break;
|
||||
}
|
||||
}
|
||||
stop: (void)0;
|
||||
}
|
||||
}
|
||||
|
||||
if (base + D->codesize != (char *)cp) /* Check for phase errors. */
|
||||
return DASM_S_PHASE;
|
||||
return DASM_S_OK;
|
||||
}
|
||||
#undef CK
|
||||
|
||||
/* Get PC label offset. */
|
||||
int dasm_getpclabel(Dst_DECL, unsigned int pc)
|
||||
{
|
||||
dasm_State *D = Dst_REF;
|
||||
if (pc*sizeof(int) < D->pcsize) {
|
||||
int pos = D->pclabels[pc];
|
||||
if (pos < 0) return *DASM_POS2PTR(D, -pos);
|
||||
if (pos > 0) return -1; /* Undefined. */
|
||||
}
|
||||
return -2; /* Unused or out of range. */
|
||||
}
|
||||
|
||||
#ifdef DASM_CHECKS
|
||||
/* Optional sanity checker to call between isolated encoding steps. */
|
||||
int dasm_checkstep(Dst_DECL, int secmatch)
|
||||
{
|
||||
dasm_State *D = Dst_REF;
|
||||
if (D->status == DASM_S_OK) {
|
||||
int i;
|
||||
for (i = 1; i <= 9; i++) {
|
||||
if (D->lglabels[i] > 0) { D->status = DASM_S_UNDEF_LG|i; break; }
|
||||
D->lglabels[i] = 0;
|
||||
}
|
||||
}
|
||||
if (D->status == DASM_S_OK && secmatch >= 0 &&
|
||||
D->section != &D->sections[secmatch])
|
||||
D->status = DASM_S_MATCH_SEC|(D->section-D->sections);
|
||||
return D->status;
|
||||
}
|
||||
#endif
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -1,558 +0,0 @@
|
||||
/*
|
||||
** DynASM ARM64 encoding engine.
|
||||
** Copyright (C) 2005-2023 Mike Pall. All rights reserved.
|
||||
** Released under the MIT license. See dynasm.lua for full copyright notice.
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define DASM_ARCH "arm64"
|
||||
|
||||
#ifndef DASM_EXTERN
|
||||
#define DASM_EXTERN(a,b,c,d) 0
|
||||
#endif
|
||||
|
||||
/* Action definitions. */
|
||||
enum {
|
||||
DASM_STOP, DASM_SECTION, DASM_ESC, DASM_REL_EXT,
|
||||
/* The following actions need a buffer position. */
|
||||
DASM_ALIGN, DASM_REL_LG, DASM_LABEL_LG,
|
||||
/* The following actions also have an argument. */
|
||||
DASM_REL_PC, DASM_LABEL_PC, DASM_REL_A,
|
||||
DASM_IMM, DASM_IMM6, DASM_IMM12, DASM_IMM13W, DASM_IMM13X, DASM_IMML,
|
||||
DASM_IMMV, DASM_VREG,
|
||||
DASM__MAX
|
||||
};
|
||||
|
||||
/* Maximum number of section buffer positions for a single dasm_put() call. */
|
||||
#define DASM_MAXSECPOS 25
|
||||
|
||||
/* DynASM encoder status codes. Action list offset or number are or'ed in. */
|
||||
#define DASM_S_OK 0x00000000
|
||||
#define DASM_S_NOMEM 0x01000000
|
||||
#define DASM_S_PHASE 0x02000000
|
||||
#define DASM_S_MATCH_SEC 0x03000000
|
||||
#define DASM_S_RANGE_I 0x11000000
|
||||
#define DASM_S_RANGE_SEC 0x12000000
|
||||
#define DASM_S_RANGE_LG 0x13000000
|
||||
#define DASM_S_RANGE_PC 0x14000000
|
||||
#define DASM_S_RANGE_REL 0x15000000
|
||||
#define DASM_S_RANGE_VREG 0x16000000
|
||||
#define DASM_S_UNDEF_LG 0x21000000
|
||||
#define DASM_S_UNDEF_PC 0x22000000
|
||||
|
||||
/* Macros to convert positions (8 bit section + 24 bit index). */
|
||||
#define DASM_POS2IDX(pos) ((pos)&0x00ffffff)
|
||||
#define DASM_POS2BIAS(pos) ((pos)&0xff000000)
|
||||
#define DASM_SEC2POS(sec) ((sec)<<24)
|
||||
#define DASM_POS2SEC(pos) ((pos)>>24)
|
||||
#define DASM_POS2PTR(D, pos) (D->sections[DASM_POS2SEC(pos)].rbuf + (pos))
|
||||
|
||||
/* Action list type. */
|
||||
typedef const unsigned int *dasm_ActList;
|
||||
|
||||
/* Per-section structure. */
|
||||
typedef struct dasm_Section {
|
||||
int *rbuf; /* Biased buffer pointer (negative section bias). */
|
||||
int *buf; /* True buffer pointer. */
|
||||
size_t bsize; /* Buffer size in bytes. */
|
||||
int pos; /* Biased buffer position. */
|
||||
int epos; /* End of biased buffer position - max single put. */
|
||||
int ofs; /* Byte offset into section. */
|
||||
} dasm_Section;
|
||||
|
||||
/* Core structure holding the DynASM encoding state. */
|
||||
struct dasm_State {
|
||||
size_t psize; /* Allocated size of this structure. */
|
||||
dasm_ActList actionlist; /* Current actionlist pointer. */
|
||||
int *lglabels; /* Local/global chain/pos ptrs. */
|
||||
size_t lgsize;
|
||||
int *pclabels; /* PC label chains/pos ptrs. */
|
||||
size_t pcsize;
|
||||
void **globals; /* Array of globals. */
|
||||
dasm_Section *section; /* Pointer to active section. */
|
||||
size_t codesize; /* Total size of all code sections. */
|
||||
int maxsection; /* 0 <= sectionidx < maxsection. */
|
||||
int status; /* Status code. */
|
||||
dasm_Section sections[1]; /* All sections. Alloc-extended. */
|
||||
};
|
||||
|
||||
/* The size of the core structure depends on the max. number of sections. */
|
||||
#define DASM_PSZ(ms) (sizeof(dasm_State)+(ms-1)*sizeof(dasm_Section))
|
||||
|
||||
|
||||
/* Initialize DynASM state. */
|
||||
void dasm_init(Dst_DECL, int maxsection)
|
||||
{
|
||||
dasm_State *D;
|
||||
size_t psz = 0;
|
||||
Dst_REF = NULL;
|
||||
DASM_M_GROW(Dst, struct dasm_State, Dst_REF, psz, DASM_PSZ(maxsection));
|
||||
D = Dst_REF;
|
||||
D->psize = psz;
|
||||
D->lglabels = NULL;
|
||||
D->lgsize = 0;
|
||||
D->pclabels = NULL;
|
||||
D->pcsize = 0;
|
||||
D->globals = NULL;
|
||||
D->maxsection = maxsection;
|
||||
memset((void *)D->sections, 0, maxsection * sizeof(dasm_Section));
|
||||
}
|
||||
|
||||
/* Free DynASM state. */
|
||||
void dasm_free(Dst_DECL)
|
||||
{
|
||||
dasm_State *D = Dst_REF;
|
||||
int i;
|
||||
for (i = 0; i < D->maxsection; i++)
|
||||
if (D->sections[i].buf)
|
||||
DASM_M_FREE(Dst, D->sections[i].buf, D->sections[i].bsize);
|
||||
if (D->pclabels) DASM_M_FREE(Dst, D->pclabels, D->pcsize);
|
||||
if (D->lglabels) DASM_M_FREE(Dst, D->lglabels, D->lgsize);
|
||||
DASM_M_FREE(Dst, D, D->psize);
|
||||
}
|
||||
|
||||
/* Setup global label array. Must be called before dasm_setup(). */
|
||||
void dasm_setupglobal(Dst_DECL, void **gl, unsigned int maxgl)
|
||||
{
|
||||
dasm_State *D = Dst_REF;
|
||||
D->globals = gl;
|
||||
DASM_M_GROW(Dst, int, D->lglabels, D->lgsize, (10+maxgl)*sizeof(int));
|
||||
}
|
||||
|
||||
/* Grow PC label array. Can be called after dasm_setup(), too. */
|
||||
void dasm_growpc(Dst_DECL, unsigned int maxpc)
|
||||
{
|
||||
dasm_State *D = Dst_REF;
|
||||
size_t osz = D->pcsize;
|
||||
DASM_M_GROW(Dst, int, D->pclabels, D->pcsize, maxpc*sizeof(int));
|
||||
memset((void *)(((unsigned char *)D->pclabels)+osz), 0, D->pcsize-osz);
|
||||
}
|
||||
|
||||
/* Setup encoder. */
|
||||
void dasm_setup(Dst_DECL, const void *actionlist)
|
||||
{
|
||||
dasm_State *D = Dst_REF;
|
||||
int i;
|
||||
D->actionlist = (dasm_ActList)actionlist;
|
||||
D->status = DASM_S_OK;
|
||||
D->section = &D->sections[0];
|
||||
memset((void *)D->lglabels, 0, D->lgsize);
|
||||
if (D->pclabels) memset((void *)D->pclabels, 0, D->pcsize);
|
||||
for (i = 0; i < D->maxsection; i++) {
|
||||
D->sections[i].pos = DASM_SEC2POS(i);
|
||||
D->sections[i].rbuf = D->sections[i].buf - D->sections[i].pos;
|
||||
D->sections[i].ofs = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifdef DASM_CHECKS
|
||||
#define CK(x, st) \
|
||||
do { if (!(x)) { \
|
||||
D->status = DASM_S_##st|(int)(p-D->actionlist-1); return; } } while (0)
|
||||
#define CKPL(kind, st) \
|
||||
do { if ((size_t)((char *)pl-(char *)D->kind##labels) >= D->kind##size) { \
|
||||
D->status = DASM_S_RANGE_##st|(int)(p-D->actionlist-1); return; } } while (0)
|
||||
#else
|
||||
#define CK(x, st) ((void)0)
|
||||
#define CKPL(kind, st) ((void)0)
|
||||
#endif
|
||||
|
||||
static int dasm_imm12(unsigned int n)
|
||||
{
|
||||
if ((n >> 12) == 0)
|
||||
return n;
|
||||
else if ((n & 0xff000fff) == 0)
|
||||
return (n >> 12) | 0x1000;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int dasm_ffs(unsigned long long x)
|
||||
{
|
||||
int n = -1;
|
||||
while (x) { x >>= 1; n++; }
|
||||
return n;
|
||||
}
|
||||
|
||||
static int dasm_imm13(int lo, int hi)
|
||||
{
|
||||
int inv = 0, w = 64, s = 0xfff, xa, xb;
|
||||
unsigned long long n = (((unsigned long long)hi) << 32) | (unsigned int)lo;
|
||||
unsigned long long m = 1ULL, a, b, c;
|
||||
if (n & 1) { n = ~n; inv = 1; }
|
||||
a = n & (unsigned long long)-(long long)n;
|
||||
b = (n+a)&(unsigned long long)-(long long)(n+a);
|
||||
c = (n+a-b)&(unsigned long long)-(long long)(n+a-b);
|
||||
xa = dasm_ffs(a); xb = dasm_ffs(b);
|
||||
if (c) {
|
||||
w = dasm_ffs(c) - xa;
|
||||
if (w == 32) m = 0x0000000100000001UL;
|
||||
else if (w == 16) m = 0x0001000100010001UL;
|
||||
else if (w == 8) m = 0x0101010101010101UL;
|
||||
else if (w == 4) m = 0x1111111111111111UL;
|
||||
else if (w == 2) m = 0x5555555555555555UL;
|
||||
else return -1;
|
||||
s = (-2*w & 0x3f) - 1;
|
||||
} else if (!a) {
|
||||
return -1;
|
||||
} else if (xb == -1) {
|
||||
xb = 64;
|
||||
}
|
||||
if ((b-a) * m != n) return -1;
|
||||
if (inv) {
|
||||
return ((w - xb) << 6) | (s+w+xa-xb);
|
||||
} else {
|
||||
return ((w - xa) << 6) | (s+xb-xa);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Pass 1: Store actions and args, link branches/labels, estimate offsets. */
|
||||
void dasm_put(Dst_DECL, int start, ...)
|
||||
{
|
||||
va_list ap;
|
||||
dasm_State *D = Dst_REF;
|
||||
dasm_ActList p = D->actionlist + start;
|
||||
dasm_Section *sec = D->section;
|
||||
int pos = sec->pos, ofs = sec->ofs;
|
||||
int *b;
|
||||
|
||||
if (pos >= sec->epos) {
|
||||
DASM_M_GROW(Dst, int, sec->buf, sec->bsize,
|
||||
sec->bsize + 2*DASM_MAXSECPOS*sizeof(int));
|
||||
sec->rbuf = sec->buf - DASM_POS2BIAS(pos);
|
||||
sec->epos = (int)sec->bsize/sizeof(int) - DASM_MAXSECPOS+DASM_POS2BIAS(pos);
|
||||
}
|
||||
|
||||
b = sec->rbuf;
|
||||
b[pos++] = start;
|
||||
|
||||
va_start(ap, start);
|
||||
while (1) {
|
||||
unsigned int ins = *p++;
|
||||
unsigned int action = (ins >> 16);
|
||||
if (action >= DASM__MAX) {
|
||||
ofs += 4;
|
||||
} else {
|
||||
int *pl, n = action >= DASM_REL_PC ? va_arg(ap, int) : 0;
|
||||
switch (action) {
|
||||
case DASM_STOP: goto stop;
|
||||
case DASM_SECTION:
|
||||
n = (ins & 255); CK(n < D->maxsection, RANGE_SEC);
|
||||
D->section = &D->sections[n]; goto stop;
|
||||
case DASM_ESC: p++; ofs += 4; break;
|
||||
case DASM_REL_EXT: if ((ins & 0x8000)) ofs += 8; break;
|
||||
case DASM_ALIGN: ofs += (ins & 255); b[pos++] = ofs; break;
|
||||
case DASM_REL_LG:
|
||||
n = (ins & 2047) - 10; pl = D->lglabels + n;
|
||||
/* Bkwd rel or global. */
|
||||
if (n >= 0) { CK(n>=10||*pl<0, RANGE_LG); CKPL(lg, LG); goto putrel; }
|
||||
pl += 10; n = *pl;
|
||||
if (n < 0) n = 0; /* Start new chain for fwd rel if label exists. */
|
||||
goto linkrel;
|
||||
case DASM_REL_PC:
|
||||
pl = D->pclabels + n; CKPL(pc, PC);
|
||||
putrel:
|
||||
n = *pl;
|
||||
if (n < 0) { /* Label exists. Get label pos and store it. */
|
||||
b[pos] = -n;
|
||||
} else {
|
||||
linkrel:
|
||||
b[pos] = n; /* Else link to rel chain, anchored at label. */
|
||||
*pl = pos;
|
||||
}
|
||||
pos++;
|
||||
if ((ins & 0x8000)) ofs += 8;
|
||||
break;
|
||||
case DASM_REL_A:
|
||||
b[pos++] = n;
|
||||
b[pos++] = va_arg(ap, int);
|
||||
break;
|
||||
case DASM_LABEL_LG:
|
||||
pl = D->lglabels + (ins & 2047) - 10; CKPL(lg, LG); goto putlabel;
|
||||
case DASM_LABEL_PC:
|
||||
pl = D->pclabels + n; CKPL(pc, PC);
|
||||
putlabel:
|
||||
n = *pl; /* n > 0: Collapse rel chain and replace with label pos. */
|
||||
while (n > 0) { int *pb = DASM_POS2PTR(D, n); n = *pb; *pb = pos;
|
||||
}
|
||||
*pl = -pos; /* Label exists now. */
|
||||
b[pos++] = ofs; /* Store pass1 offset estimate. */
|
||||
break;
|
||||
case DASM_IMM:
|
||||
CK((n & ((1<<((ins>>10)&31))-1)) == 0, RANGE_I);
|
||||
n >>= ((ins>>10)&31);
|
||||
#ifdef DASM_CHECKS
|
||||
if ((ins & 0x8000))
|
||||
CK(((n + (1<<(((ins>>5)&31)-1)))>>((ins>>5)&31)) == 0, RANGE_I);
|
||||
else
|
||||
CK((n>>((ins>>5)&31)) == 0, RANGE_I);
|
||||
#endif
|
||||
b[pos++] = n;
|
||||
break;
|
||||
case DASM_IMM6:
|
||||
CK((n >> 6) == 0, RANGE_I);
|
||||
b[pos++] = n;
|
||||
break;
|
||||
case DASM_IMM12:
|
||||
CK(dasm_imm12((unsigned int)n) != -1, RANGE_I);
|
||||
b[pos++] = n;
|
||||
break;
|
||||
case DASM_IMM13W:
|
||||
CK(dasm_imm13(n, n) != -1, RANGE_I);
|
||||
b[pos++] = n;
|
||||
break;
|
||||
case DASM_IMM13X: {
|
||||
int m = va_arg(ap, int);
|
||||
CK(dasm_imm13(n, m) != -1, RANGE_I);
|
||||
b[pos++] = n;
|
||||
b[pos++] = m;
|
||||
break;
|
||||
}
|
||||
case DASM_IMML: {
|
||||
#ifdef DASM_CHECKS
|
||||
int scale = (ins & 3);
|
||||
CK((!(n & ((1<<scale)-1)) && (unsigned int)(n>>scale) < 4096) ||
|
||||
(unsigned int)(n+256) < 512, RANGE_I);
|
||||
#endif
|
||||
b[pos++] = n;
|
||||
break;
|
||||
}
|
||||
case DASM_IMMV:
|
||||
ofs += 4;
|
||||
b[pos++] = n;
|
||||
break;
|
||||
case DASM_VREG:
|
||||
CK(n < 32, RANGE_VREG);
|
||||
b[pos++] = n;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
stop:
|
||||
va_end(ap);
|
||||
sec->pos = pos;
|
||||
sec->ofs = ofs;
|
||||
}
|
||||
#undef CK
|
||||
|
||||
/* Pass 2: Link sections, shrink aligns, fix label offsets. */
|
||||
int dasm_link(Dst_DECL, size_t *szp)
|
||||
{
|
||||
dasm_State *D = Dst_REF;
|
||||
int secnum;
|
||||
int ofs = 0;
|
||||
|
||||
#ifdef DASM_CHECKS
|
||||
*szp = 0;
|
||||
if (D->status != DASM_S_OK) return D->status;
|
||||
{
|
||||
int pc;
|
||||
for (pc = 0; pc*sizeof(int) < D->pcsize; pc++)
|
||||
if (D->pclabels[pc] > 0) return DASM_S_UNDEF_PC|pc;
|
||||
}
|
||||
#endif
|
||||
|
||||
{ /* Handle globals not defined in this translation unit. */
|
||||
int idx;
|
||||
for (idx = 10; idx*sizeof(int) < D->lgsize; idx++) {
|
||||
int n = D->lglabels[idx];
|
||||
/* Undefined label: Collapse rel chain and replace with marker (< 0). */
|
||||
while (n > 0) { int *pb = DASM_POS2PTR(D, n); n = *pb; *pb = -idx; }
|
||||
}
|
||||
}
|
||||
|
||||
/* Combine all code sections. No support for data sections (yet). */
|
||||
for (secnum = 0; secnum < D->maxsection; secnum++) {
|
||||
dasm_Section *sec = D->sections + secnum;
|
||||
int *b = sec->rbuf;
|
||||
int pos = DASM_SEC2POS(secnum);
|
||||
int lastpos = sec->pos;
|
||||
|
||||
while (pos != lastpos) {
|
||||
dasm_ActList p = D->actionlist + b[pos++];
|
||||
while (1) {
|
||||
unsigned int ins = *p++;
|
||||
unsigned int action = (ins >> 16);
|
||||
switch (action) {
|
||||
case DASM_STOP: case DASM_SECTION: goto stop;
|
||||
case DASM_ESC: p++; break;
|
||||
case DASM_REL_EXT: break;
|
||||
case DASM_ALIGN: ofs -= (b[pos++] + ofs) & (ins & 255); break;
|
||||
case DASM_REL_LG: case DASM_REL_PC: pos++; break;
|
||||
case DASM_LABEL_LG: case DASM_LABEL_PC: b[pos++] += ofs; break;
|
||||
case DASM_IMM: case DASM_IMM6: case DASM_IMM12: case DASM_IMM13W:
|
||||
case DASM_IMML: case DASM_IMMV: case DASM_VREG: pos++; break;
|
||||
case DASM_IMM13X: case DASM_REL_A: pos += 2; break;
|
||||
}
|
||||
}
|
||||
stop: (void)0;
|
||||
}
|
||||
ofs += sec->ofs; /* Next section starts right after current section. */
|
||||
}
|
||||
|
||||
D->codesize = ofs; /* Total size of all code sections */
|
||||
*szp = ofs;
|
||||
return DASM_S_OK;
|
||||
}
|
||||
|
||||
#ifdef DASM_CHECKS
|
||||
#define CK(x, st) \
|
||||
do { if (!(x)) return DASM_S_##st|(int)(p-D->actionlist-1); } while (0)
|
||||
#else
|
||||
#define CK(x, st) ((void)0)
|
||||
#endif
|
||||
|
||||
/* Pass 3: Encode sections. */
|
||||
int dasm_encode(Dst_DECL, void *buffer)
|
||||
{
|
||||
dasm_State *D = Dst_REF;
|
||||
char *base = (char *)buffer;
|
||||
unsigned int *cp = (unsigned int *)buffer;
|
||||
int secnum;
|
||||
|
||||
/* Encode all code sections. No support for data sections (yet). */
|
||||
for (secnum = 0; secnum < D->maxsection; secnum++) {
|
||||
dasm_Section *sec = D->sections + secnum;
|
||||
int *b = sec->buf;
|
||||
int *endb = sec->rbuf + sec->pos;
|
||||
|
||||
while (b != endb) {
|
||||
dasm_ActList p = D->actionlist + *b++;
|
||||
while (1) {
|
||||
unsigned int ins = *p++;
|
||||
unsigned int action = (ins >> 16);
|
||||
int n = (action >= DASM_ALIGN && action < DASM__MAX) ? *b++ : 0;
|
||||
switch (action) {
|
||||
case DASM_STOP: case DASM_SECTION: goto stop;
|
||||
case DASM_ESC: *cp++ = *p++; break;
|
||||
case DASM_REL_EXT:
|
||||
n = DASM_EXTERN(Dst, (unsigned char *)cp, (ins&2047), !(ins&2048));
|
||||
goto patchrel;
|
||||
case DASM_ALIGN:
|
||||
ins &= 255; while ((((char *)cp - base) & ins)) *cp++ = 0xd503201f;
|
||||
break;
|
||||
case DASM_REL_LG:
|
||||
if (n < 0) {
|
||||
ptrdiff_t na = (ptrdiff_t)D->globals[-n-10] - (ptrdiff_t)cp + 4;
|
||||
n = (int)na;
|
||||
CK((ptrdiff_t)n == na, RANGE_REL);
|
||||
goto patchrel;
|
||||
}
|
||||
/* fallthrough */
|
||||
case DASM_REL_PC:
|
||||
CK(n >= 0, UNDEF_PC);
|
||||
n = *DASM_POS2PTR(D, n) - (int)((char *)cp - base) + 4;
|
||||
patchrel:
|
||||
if (!(ins & 0xf800)) { /* B, BL */
|
||||
CK((n & 3) == 0 && ((n+0x08000000) >> 28) == 0, RANGE_REL);
|
||||
cp[-1] |= ((n >> 2) & 0x03ffffff);
|
||||
} else if ((ins & 0x800)) { /* B.cond, CBZ, CBNZ, LDR* literal */
|
||||
CK((n & 3) == 0 && ((n+0x00100000) >> 21) == 0, RANGE_REL);
|
||||
cp[-1] |= ((n << 3) & 0x00ffffe0);
|
||||
} else if ((ins & 0x3000) == 0x2000) { /* ADR */
|
||||
CK(((n+0x00100000) >> 21) == 0, RANGE_REL);
|
||||
cp[-1] |= ((n << 3) & 0x00ffffe0) | ((n & 3) << 29);
|
||||
} else if ((ins & 0x3000) == 0x3000) { /* ADRP */
|
||||
cp[-1] |= ((n >> 9) & 0x00ffffe0) | (((n >> 12) & 3) << 29);
|
||||
} else if ((ins & 0x1000)) { /* TBZ, TBNZ */
|
||||
CK((n & 3) == 0 && ((n+0x00008000) >> 16) == 0, RANGE_REL);
|
||||
cp[-1] |= ((n << 3) & 0x0007ffe0);
|
||||
} else if ((ins & 0x8000)) { /* absolute */
|
||||
cp[0] = (unsigned int)((ptrdiff_t)cp - 4 + n);
|
||||
cp[1] = (unsigned int)(((ptrdiff_t)cp - 4 + n) >> 32);
|
||||
cp += 2;
|
||||
}
|
||||
break;
|
||||
case DASM_REL_A: {
|
||||
ptrdiff_t na = (((ptrdiff_t)(*b++) << 32) | (unsigned int)n);
|
||||
if ((ins & 0x3000) == 0x3000) { /* ADRP */
|
||||
ins &= ~0x1000;
|
||||
na = (na >> 12) - (((ptrdiff_t)cp - 4) >> 12);
|
||||
} else {
|
||||
na = na - (ptrdiff_t)cp + 4;
|
||||
}
|
||||
n = (int)na;
|
||||
CK((ptrdiff_t)n == na, RANGE_REL);
|
||||
goto patchrel;
|
||||
}
|
||||
case DASM_LABEL_LG:
|
||||
ins &= 2047; if (ins >= 20) D->globals[ins-20] = (void *)(base + n);
|
||||
break;
|
||||
case DASM_LABEL_PC: break;
|
||||
case DASM_IMM:
|
||||
cp[-1] |= (n & ((1<<((ins>>5)&31))-1)) << (ins&31);
|
||||
break;
|
||||
case DASM_IMM6:
|
||||
cp[-1] |= ((n&31) << 19) | ((n&32) << 26);
|
||||
break;
|
||||
case DASM_IMM12:
|
||||
cp[-1] |= (dasm_imm12((unsigned int)n) << 10);
|
||||
break;
|
||||
case DASM_IMM13W:
|
||||
cp[-1] |= (dasm_imm13(n, n) << 10);
|
||||
break;
|
||||
case DASM_IMM13X:
|
||||
cp[-1] |= (dasm_imm13(n, *b++) << 10);
|
||||
break;
|
||||
case DASM_IMML: {
|
||||
int scale = (ins & 3);
|
||||
cp[-1] |= (!(n & ((1<<scale)-1)) && (unsigned int)(n>>scale) < 4096) ?
|
||||
((n << (10-scale)) | 0x01000000) : ((n & 511) << 12);
|
||||
break;
|
||||
}
|
||||
case DASM_IMMV:
|
||||
*cp++ = n;
|
||||
break;
|
||||
case DASM_VREG:
|
||||
cp[-1] |= (n & 0x1f) << (ins & 0x1f);
|
||||
break;
|
||||
default: *cp++ = ins; break;
|
||||
}
|
||||
}
|
||||
stop: (void)0;
|
||||
}
|
||||
}
|
||||
|
||||
if (base + D->codesize != (char *)cp) /* Check for phase errors. */
|
||||
return DASM_S_PHASE;
|
||||
return DASM_S_OK;
|
||||
}
|
||||
#undef CK
|
||||
|
||||
/* Get PC label offset. */
|
||||
int dasm_getpclabel(Dst_DECL, unsigned int pc)
|
||||
{
|
||||
dasm_State *D = Dst_REF;
|
||||
if (pc*sizeof(int) < D->pcsize) {
|
||||
int pos = D->pclabels[pc];
|
||||
if (pos < 0) return *DASM_POS2PTR(D, -pos);
|
||||
if (pos > 0) return -1; /* Undefined. */
|
||||
}
|
||||
return -2; /* Unused or out of range. */
|
||||
}
|
||||
|
||||
#ifdef DASM_CHECKS
|
||||
/* Optional sanity checker to call between isolated encoding steps. */
|
||||
int dasm_checkstep(Dst_DECL, int secmatch)
|
||||
{
|
||||
dasm_State *D = Dst_REF;
|
||||
if (D->status == DASM_S_OK) {
|
||||
int i;
|
||||
for (i = 1; i <= 9; i++) {
|
||||
if (D->lglabels[i] > 0) { D->status = DASM_S_UNDEF_LG|i; break; }
|
||||
D->lglabels[i] = 0;
|
||||
}
|
||||
}
|
||||
if (D->status == DASM_S_OK && secmatch >= 0 &&
|
||||
D->section != &D->sections[secmatch])
|
||||
D->status = DASM_S_MATCH_SEC|(int)(D->section-D->sections);
|
||||
return D->status;
|
||||
}
|
||||
#endif
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -1,419 +0,0 @@
|
||||
/*
|
||||
** DynASM MIPS encoding engine.
|
||||
** Copyright (C) 2005-2023 Mike Pall. All rights reserved.
|
||||
** Released under the MIT license. See dynasm.lua for full copyright notice.
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define DASM_ARCH "mips"
|
||||
|
||||
#ifndef DASM_EXTERN
|
||||
#define DASM_EXTERN(a,b,c,d) 0
|
||||
#endif
|
||||
|
||||
/* Action definitions. */
|
||||
enum {
|
||||
DASM_STOP, DASM_SECTION, DASM_ESC, DASM_REL_EXT,
|
||||
/* The following actions need a buffer position. */
|
||||
DASM_ALIGN, DASM_REL_LG, DASM_LABEL_LG,
|
||||
/* The following actions also have an argument. */
|
||||
DASM_REL_PC, DASM_LABEL_PC, DASM_IMM, DASM_IMMS,
|
||||
DASM__MAX
|
||||
};
|
||||
|
||||
/* Maximum number of section buffer positions for a single dasm_put() call. */
|
||||
#define DASM_MAXSECPOS 25
|
||||
|
||||
/* DynASM encoder status codes. Action list offset or number are or'ed in. */
|
||||
#define DASM_S_OK 0x00000000
|
||||
#define DASM_S_NOMEM 0x01000000
|
||||
#define DASM_S_PHASE 0x02000000
|
||||
#define DASM_S_MATCH_SEC 0x03000000
|
||||
#define DASM_S_RANGE_I 0x11000000
|
||||
#define DASM_S_RANGE_SEC 0x12000000
|
||||
#define DASM_S_RANGE_LG 0x13000000
|
||||
#define DASM_S_RANGE_PC 0x14000000
|
||||
#define DASM_S_RANGE_REL 0x15000000
|
||||
#define DASM_S_UNDEF_LG 0x21000000
|
||||
#define DASM_S_UNDEF_PC 0x22000000
|
||||
|
||||
/* Macros to convert positions (8 bit section + 24 bit index). */
|
||||
#define DASM_POS2IDX(pos) ((pos)&0x00ffffff)
|
||||
#define DASM_POS2BIAS(pos) ((pos)&0xff000000)
|
||||
#define DASM_SEC2POS(sec) ((sec)<<24)
|
||||
#define DASM_POS2SEC(pos) ((pos)>>24)
|
||||
#define DASM_POS2PTR(D, pos) (D->sections[DASM_POS2SEC(pos)].rbuf + (pos))
|
||||
|
||||
/* Action list type. */
|
||||
typedef const unsigned int *dasm_ActList;
|
||||
|
||||
/* Per-section structure. */
|
||||
typedef struct dasm_Section {
|
||||
int *rbuf; /* Biased buffer pointer (negative section bias). */
|
||||
int *buf; /* True buffer pointer. */
|
||||
size_t bsize; /* Buffer size in bytes. */
|
||||
int pos; /* Biased buffer position. */
|
||||
int epos; /* End of biased buffer position - max single put. */
|
||||
int ofs; /* Byte offset into section. */
|
||||
} dasm_Section;
|
||||
|
||||
/* Core structure holding the DynASM encoding state. */
|
||||
struct dasm_State {
|
||||
size_t psize; /* Allocated size of this structure. */
|
||||
dasm_ActList actionlist; /* Current actionlist pointer. */
|
||||
int *lglabels; /* Local/global chain/pos ptrs. */
|
||||
size_t lgsize;
|
||||
int *pclabels; /* PC label chains/pos ptrs. */
|
||||
size_t pcsize;
|
||||
void **globals; /* Array of globals. */
|
||||
dasm_Section *section; /* Pointer to active section. */
|
||||
size_t codesize; /* Total size of all code sections. */
|
||||
int maxsection; /* 0 <= sectionidx < maxsection. */
|
||||
int status; /* Status code. */
|
||||
dasm_Section sections[1]; /* All sections. Alloc-extended. */
|
||||
};
|
||||
|
||||
/* The size of the core structure depends on the max. number of sections. */
|
||||
#define DASM_PSZ(ms) (sizeof(dasm_State)+(ms-1)*sizeof(dasm_Section))
|
||||
|
||||
|
||||
/* Initialize DynASM state. */
|
||||
void dasm_init(Dst_DECL, int maxsection)
|
||||
{
|
||||
dasm_State *D;
|
||||
size_t psz = 0;
|
||||
Dst_REF = NULL;
|
||||
DASM_M_GROW(Dst, struct dasm_State, Dst_REF, psz, DASM_PSZ(maxsection));
|
||||
D = Dst_REF;
|
||||
D->psize = psz;
|
||||
D->lglabels = NULL;
|
||||
D->lgsize = 0;
|
||||
D->pclabels = NULL;
|
||||
D->pcsize = 0;
|
||||
D->globals = NULL;
|
||||
D->maxsection = maxsection;
|
||||
memset((void *)D->sections, 0, maxsection * sizeof(dasm_Section));
|
||||
}
|
||||
|
||||
/* Free DynASM state. */
|
||||
void dasm_free(Dst_DECL)
|
||||
{
|
||||
dasm_State *D = Dst_REF;
|
||||
int i;
|
||||
for (i = 0; i < D->maxsection; i++)
|
||||
if (D->sections[i].buf)
|
||||
DASM_M_FREE(Dst, D->sections[i].buf, D->sections[i].bsize);
|
||||
if (D->pclabels) DASM_M_FREE(Dst, D->pclabels, D->pcsize);
|
||||
if (D->lglabels) DASM_M_FREE(Dst, D->lglabels, D->lgsize);
|
||||
DASM_M_FREE(Dst, D, D->psize);
|
||||
}
|
||||
|
||||
/* Setup global label array. Must be called before dasm_setup(). */
|
||||
void dasm_setupglobal(Dst_DECL, void **gl, unsigned int maxgl)
|
||||
{
|
||||
dasm_State *D = Dst_REF;
|
||||
D->globals = gl;
|
||||
DASM_M_GROW(Dst, int, D->lglabels, D->lgsize, (10+maxgl)*sizeof(int));
|
||||
}
|
||||
|
||||
/* Grow PC label array. Can be called after dasm_setup(), too. */
|
||||
void dasm_growpc(Dst_DECL, unsigned int maxpc)
|
||||
{
|
||||
dasm_State *D = Dst_REF;
|
||||
size_t osz = D->pcsize;
|
||||
DASM_M_GROW(Dst, int, D->pclabels, D->pcsize, maxpc*sizeof(int));
|
||||
memset((void *)(((unsigned char *)D->pclabels)+osz), 0, D->pcsize-osz);
|
||||
}
|
||||
|
||||
/* Setup encoder. */
|
||||
void dasm_setup(Dst_DECL, const void *actionlist)
|
||||
{
|
||||
dasm_State *D = Dst_REF;
|
||||
int i;
|
||||
D->actionlist = (dasm_ActList)actionlist;
|
||||
D->status = DASM_S_OK;
|
||||
D->section = &D->sections[0];
|
||||
memset((void *)D->lglabels, 0, D->lgsize);
|
||||
if (D->pclabels) memset((void *)D->pclabels, 0, D->pcsize);
|
||||
for (i = 0; i < D->maxsection; i++) {
|
||||
D->sections[i].pos = DASM_SEC2POS(i);
|
||||
D->sections[i].rbuf = D->sections[i].buf - D->sections[i].pos;
|
||||
D->sections[i].ofs = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifdef DASM_CHECKS
|
||||
#define CK(x, st) \
|
||||
do { if (!(x)) { \
|
||||
D->status = DASM_S_##st|(int)(p-D->actionlist-1); return; } } while (0)
|
||||
#define CKPL(kind, st) \
|
||||
do { if ((size_t)((char *)pl-(char *)D->kind##labels) >= D->kind##size) { \
|
||||
D->status = DASM_S_RANGE_##st|(int)(p-D->actionlist-1); return; } } while (0)
|
||||
#else
|
||||
#define CK(x, st) ((void)0)
|
||||
#define CKPL(kind, st) ((void)0)
|
||||
#endif
|
||||
|
||||
/* Pass 1: Store actions and args, link branches/labels, estimate offsets. */
|
||||
void dasm_put(Dst_DECL, int start, ...)
|
||||
{
|
||||
va_list ap;
|
||||
dasm_State *D = Dst_REF;
|
||||
dasm_ActList p = D->actionlist + start;
|
||||
dasm_Section *sec = D->section;
|
||||
int pos = sec->pos, ofs = sec->ofs;
|
||||
int *b;
|
||||
|
||||
if (pos >= sec->epos) {
|
||||
DASM_M_GROW(Dst, int, sec->buf, sec->bsize,
|
||||
sec->bsize + 2*DASM_MAXSECPOS*sizeof(int));
|
||||
sec->rbuf = sec->buf - DASM_POS2BIAS(pos);
|
||||
sec->epos = (int)sec->bsize/sizeof(int) - DASM_MAXSECPOS+DASM_POS2BIAS(pos);
|
||||
}
|
||||
|
||||
b = sec->rbuf;
|
||||
b[pos++] = start;
|
||||
|
||||
va_start(ap, start);
|
||||
while (1) {
|
||||
unsigned int ins = *p++;
|
||||
unsigned int action = (ins >> 16) - 0xff00;
|
||||
if (action >= DASM__MAX) {
|
||||
ofs += 4;
|
||||
} else {
|
||||
int *pl, n = action >= DASM_REL_PC ? va_arg(ap, int) : 0;
|
||||
switch (action) {
|
||||
case DASM_STOP: goto stop;
|
||||
case DASM_SECTION:
|
||||
n = (ins & 255); CK(n < D->maxsection, RANGE_SEC);
|
||||
D->section = &D->sections[n]; goto stop;
|
||||
case DASM_ESC: p++; ofs += 4; break;
|
||||
case DASM_REL_EXT: break;
|
||||
case DASM_ALIGN: ofs += (ins & 255); b[pos++] = ofs; break;
|
||||
case DASM_REL_LG:
|
||||
n = (ins & 2047) - 10; pl = D->lglabels + n;
|
||||
/* Bkwd rel or global. */
|
||||
if (n >= 0) { CK(n>=10||*pl<0, RANGE_LG); CKPL(lg, LG); goto putrel; }
|
||||
pl += 10; n = *pl;
|
||||
if (n < 0) n = 0; /* Start new chain for fwd rel if label exists. */
|
||||
goto linkrel;
|
||||
case DASM_REL_PC:
|
||||
pl = D->pclabels + n; CKPL(pc, PC);
|
||||
putrel:
|
||||
n = *pl;
|
||||
if (n < 0) { /* Label exists. Get label pos and store it. */
|
||||
b[pos] = -n;
|
||||
} else {
|
||||
linkrel:
|
||||
b[pos] = n; /* Else link to rel chain, anchored at label. */
|
||||
*pl = pos;
|
||||
}
|
||||
pos++;
|
||||
break;
|
||||
case DASM_LABEL_LG:
|
||||
pl = D->lglabels + (ins & 2047) - 10; CKPL(lg, LG); goto putlabel;
|
||||
case DASM_LABEL_PC:
|
||||
pl = D->pclabels + n; CKPL(pc, PC);
|
||||
putlabel:
|
||||
n = *pl; /* n > 0: Collapse rel chain and replace with label pos. */
|
||||
while (n > 0) { int *pb = DASM_POS2PTR(D, n); n = *pb; *pb = pos;
|
||||
}
|
||||
*pl = -pos; /* Label exists now. */
|
||||
b[pos++] = ofs; /* Store pass1 offset estimate. */
|
||||
break;
|
||||
case DASM_IMM: case DASM_IMMS:
|
||||
#ifdef DASM_CHECKS
|
||||
CK((n & ((1<<((ins>>10)&31))-1)) == 0, RANGE_I);
|
||||
#endif
|
||||
n >>= ((ins>>10)&31);
|
||||
#ifdef DASM_CHECKS
|
||||
if (ins & 0x8000)
|
||||
CK(((n + (1<<(((ins>>5)&31)-1)))>>((ins>>5)&31)) == 0, RANGE_I);
|
||||
else
|
||||
CK((n>>((ins>>5)&31)) == 0, RANGE_I);
|
||||
#endif
|
||||
b[pos++] = n;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
stop:
|
||||
va_end(ap);
|
||||
sec->pos = pos;
|
||||
sec->ofs = ofs;
|
||||
}
|
||||
#undef CK
|
||||
|
||||
/* Pass 2: Link sections, shrink aligns, fix label offsets. */
|
||||
int dasm_link(Dst_DECL, size_t *szp)
|
||||
{
|
||||
dasm_State *D = Dst_REF;
|
||||
int secnum;
|
||||
int ofs = 0;
|
||||
|
||||
#ifdef DASM_CHECKS
|
||||
*szp = 0;
|
||||
if (D->status != DASM_S_OK) return D->status;
|
||||
{
|
||||
int pc;
|
||||
for (pc = 0; pc*sizeof(int) < D->pcsize; pc++)
|
||||
if (D->pclabels[pc] > 0) return DASM_S_UNDEF_PC|pc;
|
||||
}
|
||||
#endif
|
||||
|
||||
{ /* Handle globals not defined in this translation unit. */
|
||||
int idx;
|
||||
for (idx = 10; idx*sizeof(int) < D->lgsize; idx++) {
|
||||
int n = D->lglabels[idx];
|
||||
/* Undefined label: Collapse rel chain and replace with marker (< 0). */
|
||||
while (n > 0) { int *pb = DASM_POS2PTR(D, n); n = *pb; *pb = -idx; }
|
||||
}
|
||||
}
|
||||
|
||||
/* Combine all code sections. No support for data sections (yet). */
|
||||
for (secnum = 0; secnum < D->maxsection; secnum++) {
|
||||
dasm_Section *sec = D->sections + secnum;
|
||||
int *b = sec->rbuf;
|
||||
int pos = DASM_SEC2POS(secnum);
|
||||
int lastpos = sec->pos;
|
||||
|
||||
while (pos != lastpos) {
|
||||
dasm_ActList p = D->actionlist + b[pos++];
|
||||
while (1) {
|
||||
unsigned int ins = *p++;
|
||||
unsigned int action = (ins >> 16) - 0xff00;
|
||||
switch (action) {
|
||||
case DASM_STOP: case DASM_SECTION: goto stop;
|
||||
case DASM_ESC: p++; break;
|
||||
case DASM_REL_EXT: break;
|
||||
case DASM_ALIGN: ofs -= (b[pos++] + ofs) & (ins & 255); break;
|
||||
case DASM_REL_LG: case DASM_REL_PC: pos++; break;
|
||||
case DASM_LABEL_LG: case DASM_LABEL_PC: b[pos++] += ofs; break;
|
||||
case DASM_IMM: case DASM_IMMS: pos++; break;
|
||||
}
|
||||
}
|
||||
stop: (void)0;
|
||||
}
|
||||
ofs += sec->ofs; /* Next section starts right after current section. */
|
||||
}
|
||||
|
||||
D->codesize = ofs; /* Total size of all code sections */
|
||||
*szp = ofs;
|
||||
return DASM_S_OK;
|
||||
}
|
||||
|
||||
#ifdef DASM_CHECKS
|
||||
#define CK(x, st) \
|
||||
do { if (!(x)) return DASM_S_##st|(int)(p-D->actionlist-1); } while (0)
|
||||
#else
|
||||
#define CK(x, st) ((void)0)
|
||||
#endif
|
||||
|
||||
/* Pass 3: Encode sections. */
|
||||
int dasm_encode(Dst_DECL, void *buffer)
|
||||
{
|
||||
dasm_State *D = Dst_REF;
|
||||
char *base = (char *)buffer;
|
||||
unsigned int *cp = (unsigned int *)buffer;
|
||||
int secnum;
|
||||
|
||||
/* Encode all code sections. No support for data sections (yet). */
|
||||
for (secnum = 0; secnum < D->maxsection; secnum++) {
|
||||
dasm_Section *sec = D->sections + secnum;
|
||||
int *b = sec->buf;
|
||||
int *endb = sec->rbuf + sec->pos;
|
||||
|
||||
while (b != endb) {
|
||||
dasm_ActList p = D->actionlist + *b++;
|
||||
while (1) {
|
||||
unsigned int ins = *p++;
|
||||
unsigned int action = (ins >> 16) - 0xff00;
|
||||
int n = (action >= DASM_ALIGN && action < DASM__MAX) ? *b++ : 0;
|
||||
switch (action) {
|
||||
case DASM_STOP: case DASM_SECTION: goto stop;
|
||||
case DASM_ESC: *cp++ = *p++; break;
|
||||
case DASM_REL_EXT:
|
||||
n = DASM_EXTERN(Dst, (unsigned char *)cp, (ins & 2047), 1);
|
||||
goto patchrel;
|
||||
case DASM_ALIGN:
|
||||
ins &= 255; while ((((char *)cp - base) & ins)) *cp++ = 0x60000000;
|
||||
break;
|
||||
case DASM_REL_LG:
|
||||
if (n < 0) {
|
||||
n = (int)((ptrdiff_t)D->globals[-n-10] - (ptrdiff_t)cp);
|
||||
goto patchrel;
|
||||
}
|
||||
/* fallthrough */
|
||||
case DASM_REL_PC:
|
||||
CK(n >= 0, UNDEF_PC);
|
||||
n = *DASM_POS2PTR(D, n);
|
||||
if (ins & 2048)
|
||||
n = (n + (int)(size_t)base) & 0x0fffffff;
|
||||
else
|
||||
n = n - (int)((char *)cp - base);
|
||||
patchrel: {
|
||||
unsigned int e = 16 + ((ins >> 12) & 15);
|
||||
CK((n & 3) == 0 &&
|
||||
((n + ((ins & 2048) ? 0 : (1<<(e+1)))) >> (e+2)) == 0, RANGE_REL);
|
||||
cp[-1] |= ((n>>2) & ((1<<e)-1));
|
||||
}
|
||||
break;
|
||||
case DASM_LABEL_LG:
|
||||
ins &= 2047; if (ins >= 20) D->globals[ins-20] = (void *)(base + n);
|
||||
break;
|
||||
case DASM_LABEL_PC: break;
|
||||
case DASM_IMMS:
|
||||
cp[-1] |= ((n>>3) & 4); n &= 0x1f;
|
||||
/* fallthrough */
|
||||
case DASM_IMM:
|
||||
cp[-1] |= (n & ((1<<((ins>>5)&31))-1)) << (ins&31);
|
||||
break;
|
||||
default: *cp++ = ins; break;
|
||||
}
|
||||
}
|
||||
stop: (void)0;
|
||||
}
|
||||
}
|
||||
|
||||
if (base + D->codesize != (char *)cp) /* Check for phase errors. */
|
||||
return DASM_S_PHASE;
|
||||
return DASM_S_OK;
|
||||
}
|
||||
#undef CK
|
||||
|
||||
/* Get PC label offset. */
|
||||
int dasm_getpclabel(Dst_DECL, unsigned int pc)
|
||||
{
|
||||
dasm_State *D = Dst_REF;
|
||||
if (pc*sizeof(int) < D->pcsize) {
|
||||
int pos = D->pclabels[pc];
|
||||
if (pos < 0) return *DASM_POS2PTR(D, -pos);
|
||||
if (pos > 0) return -1; /* Undefined. */
|
||||
}
|
||||
return -2; /* Unused or out of range. */
|
||||
}
|
||||
|
||||
#ifdef DASM_CHECKS
|
||||
/* Optional sanity checker to call between isolated encoding steps. */
|
||||
int dasm_checkstep(Dst_DECL, int secmatch)
|
||||
{
|
||||
dasm_State *D = Dst_REF;
|
||||
if (D->status == DASM_S_OK) {
|
||||
int i;
|
||||
for (i = 1; i <= 9; i++) {
|
||||
if (D->lglabels[i] > 0) { D->status = DASM_S_UNDEF_LG|i; break; }
|
||||
D->lglabels[i] = 0;
|
||||
}
|
||||
}
|
||||
if (D->status == DASM_S_OK && secmatch >= 0 &&
|
||||
D->section != &D->sections[secmatch])
|
||||
D->status = DASM_S_MATCH_SEC|(int)(D->section-D->sections);
|
||||
return D->status;
|
||||
}
|
||||
#endif
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -1,12 +0,0 @@
|
||||
------------------------------------------------------------------------------
|
||||
-- DynASM MIPS64 module.
|
||||
--
|
||||
-- Copyright (C) 2005-2023 Mike Pall. All rights reserved.
|
||||
-- See dynasm.lua for full copyright notice.
|
||||
------------------------------------------------------------------------------
|
||||
-- This module just sets 64 bit mode for the combined MIPS/MIPS64 module.
|
||||
-- All the interesting stuff is there.
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
mips64 = true -- Using a global is an ugly, but effective solution.
|
||||
return require("dasm_mips")
|
||||
@@ -1,418 +0,0 @@
|
||||
/*
|
||||
** DynASM PPC/PPC64 encoding engine.
|
||||
** Copyright (C) 2005-2023 Mike Pall. All rights reserved.
|
||||
** Released under the MIT license. See dynasm.lua for full copyright notice.
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define DASM_ARCH "ppc"
|
||||
|
||||
#ifndef DASM_EXTERN
|
||||
#define DASM_EXTERN(a,b,c,d) 0
|
||||
#endif
|
||||
|
||||
/* Action definitions. */
|
||||
enum {
|
||||
DASM_STOP, DASM_SECTION, DASM_ESC, DASM_REL_EXT,
|
||||
/* The following actions need a buffer position. */
|
||||
DASM_ALIGN, DASM_REL_LG, DASM_LABEL_LG,
|
||||
/* The following actions also have an argument. */
|
||||
DASM_REL_PC, DASM_LABEL_PC, DASM_IMM, DASM_IMMSH,
|
||||
DASM__MAX
|
||||
};
|
||||
|
||||
/* Maximum number of section buffer positions for a single dasm_put() call. */
|
||||
#define DASM_MAXSECPOS 25
|
||||
|
||||
/* DynASM encoder status codes. Action list offset or number are or'ed in. */
|
||||
#define DASM_S_OK 0x00000000
|
||||
#define DASM_S_NOMEM 0x01000000
|
||||
#define DASM_S_PHASE 0x02000000
|
||||
#define DASM_S_MATCH_SEC 0x03000000
|
||||
#define DASM_S_RANGE_I 0x11000000
|
||||
#define DASM_S_RANGE_SEC 0x12000000
|
||||
#define DASM_S_RANGE_LG 0x13000000
|
||||
#define DASM_S_RANGE_PC 0x14000000
|
||||
#define DASM_S_RANGE_REL 0x15000000
|
||||
#define DASM_S_UNDEF_LG 0x21000000
|
||||
#define DASM_S_UNDEF_PC 0x22000000
|
||||
|
||||
/* Macros to convert positions (8 bit section + 24 bit index). */
|
||||
#define DASM_POS2IDX(pos) ((pos)&0x00ffffff)
|
||||
#define DASM_POS2BIAS(pos) ((pos)&0xff000000)
|
||||
#define DASM_SEC2POS(sec) ((sec)<<24)
|
||||
#define DASM_POS2SEC(pos) ((pos)>>24)
|
||||
#define DASM_POS2PTR(D, pos) (D->sections[DASM_POS2SEC(pos)].rbuf + (pos))
|
||||
|
||||
/* Action list type. */
|
||||
typedef const unsigned int *dasm_ActList;
|
||||
|
||||
/* Per-section structure. */
|
||||
typedef struct dasm_Section {
|
||||
int *rbuf; /* Biased buffer pointer (negative section bias). */
|
||||
int *buf; /* True buffer pointer. */
|
||||
size_t bsize; /* Buffer size in bytes. */
|
||||
int pos; /* Biased buffer position. */
|
||||
int epos; /* End of biased buffer position - max single put. */
|
||||
int ofs; /* Byte offset into section. */
|
||||
} dasm_Section;
|
||||
|
||||
/* Core structure holding the DynASM encoding state. */
|
||||
struct dasm_State {
|
||||
size_t psize; /* Allocated size of this structure. */
|
||||
dasm_ActList actionlist; /* Current actionlist pointer. */
|
||||
int *lglabels; /* Local/global chain/pos ptrs. */
|
||||
size_t lgsize;
|
||||
int *pclabels; /* PC label chains/pos ptrs. */
|
||||
size_t pcsize;
|
||||
void **globals; /* Array of globals. */
|
||||
dasm_Section *section; /* Pointer to active section. */
|
||||
size_t codesize; /* Total size of all code sections. */
|
||||
int maxsection; /* 0 <= sectionidx < maxsection. */
|
||||
int status; /* Status code. */
|
||||
dasm_Section sections[1]; /* All sections. Alloc-extended. */
|
||||
};
|
||||
|
||||
/* The size of the core structure depends on the max. number of sections. */
|
||||
#define DASM_PSZ(ms) (sizeof(dasm_State)+(ms-1)*sizeof(dasm_Section))
|
||||
|
||||
|
||||
/* Initialize DynASM state. */
|
||||
void dasm_init(Dst_DECL, int maxsection)
|
||||
{
|
||||
dasm_State *D;
|
||||
size_t psz = 0;
|
||||
Dst_REF = NULL;
|
||||
DASM_M_GROW(Dst, struct dasm_State, Dst_REF, psz, DASM_PSZ(maxsection));
|
||||
D = Dst_REF;
|
||||
D->psize = psz;
|
||||
D->lglabels = NULL;
|
||||
D->lgsize = 0;
|
||||
D->pclabels = NULL;
|
||||
D->pcsize = 0;
|
||||
D->globals = NULL;
|
||||
D->maxsection = maxsection;
|
||||
memset((void *)D->sections, 0, maxsection * sizeof(dasm_Section));
|
||||
}
|
||||
|
||||
/* Free DynASM state. */
|
||||
void dasm_free(Dst_DECL)
|
||||
{
|
||||
dasm_State *D = Dst_REF;
|
||||
int i;
|
||||
for (i = 0; i < D->maxsection; i++)
|
||||
if (D->sections[i].buf)
|
||||
DASM_M_FREE(Dst, D->sections[i].buf, D->sections[i].bsize);
|
||||
if (D->pclabels) DASM_M_FREE(Dst, D->pclabels, D->pcsize);
|
||||
if (D->lglabels) DASM_M_FREE(Dst, D->lglabels, D->lgsize);
|
||||
DASM_M_FREE(Dst, D, D->psize);
|
||||
}
|
||||
|
||||
/* Setup global label array. Must be called before dasm_setup(). */
|
||||
void dasm_setupglobal(Dst_DECL, void **gl, unsigned int maxgl)
|
||||
{
|
||||
dasm_State *D = Dst_REF;
|
||||
D->globals = gl;
|
||||
DASM_M_GROW(Dst, int, D->lglabels, D->lgsize, (10+maxgl)*sizeof(int));
|
||||
}
|
||||
|
||||
/* Grow PC label array. Can be called after dasm_setup(), too. */
|
||||
void dasm_growpc(Dst_DECL, unsigned int maxpc)
|
||||
{
|
||||
dasm_State *D = Dst_REF;
|
||||
size_t osz = D->pcsize;
|
||||
DASM_M_GROW(Dst, int, D->pclabels, D->pcsize, maxpc*sizeof(int));
|
||||
memset((void *)(((unsigned char *)D->pclabels)+osz), 0, D->pcsize-osz);
|
||||
}
|
||||
|
||||
/* Setup encoder. */
|
||||
void dasm_setup(Dst_DECL, const void *actionlist)
|
||||
{
|
||||
dasm_State *D = Dst_REF;
|
||||
int i;
|
||||
D->actionlist = (dasm_ActList)actionlist;
|
||||
D->status = DASM_S_OK;
|
||||
D->section = &D->sections[0];
|
||||
memset((void *)D->lglabels, 0, D->lgsize);
|
||||
if (D->pclabels) memset((void *)D->pclabels, 0, D->pcsize);
|
||||
for (i = 0; i < D->maxsection; i++) {
|
||||
D->sections[i].pos = DASM_SEC2POS(i);
|
||||
D->sections[i].rbuf = D->sections[i].buf - D->sections[i].pos;
|
||||
D->sections[i].ofs = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifdef DASM_CHECKS
|
||||
#define CK(x, st) \
|
||||
do { if (!(x)) { \
|
||||
D->status = DASM_S_##st|(p-D->actionlist-1); return; } } while (0)
|
||||
#define CKPL(kind, st) \
|
||||
do { if ((size_t)((char *)pl-(char *)D->kind##labels) >= D->kind##size) { \
|
||||
D->status = DASM_S_RANGE_##st|(p-D->actionlist-1); return; } } while (0)
|
||||
#else
|
||||
#define CK(x, st) ((void)0)
|
||||
#define CKPL(kind, st) ((void)0)
|
||||
#endif
|
||||
|
||||
/* Pass 1: Store actions and args, link branches/labels, estimate offsets. */
|
||||
void dasm_put(Dst_DECL, int start, ...)
|
||||
{
|
||||
va_list ap;
|
||||
dasm_State *D = Dst_REF;
|
||||
dasm_ActList p = D->actionlist + start;
|
||||
dasm_Section *sec = D->section;
|
||||
int pos = sec->pos, ofs = sec->ofs;
|
||||
int *b;
|
||||
|
||||
if (pos >= sec->epos) {
|
||||
DASM_M_GROW(Dst, int, sec->buf, sec->bsize,
|
||||
sec->bsize + 2*DASM_MAXSECPOS*sizeof(int));
|
||||
sec->rbuf = sec->buf - DASM_POS2BIAS(pos);
|
||||
sec->epos = (int)sec->bsize/sizeof(int) - DASM_MAXSECPOS+DASM_POS2BIAS(pos);
|
||||
}
|
||||
|
||||
b = sec->rbuf;
|
||||
b[pos++] = start;
|
||||
|
||||
va_start(ap, start);
|
||||
while (1) {
|
||||
unsigned int ins = *p++;
|
||||
unsigned int action = (ins >> 16);
|
||||
if (action >= DASM__MAX) {
|
||||
ofs += 4;
|
||||
} else {
|
||||
int *pl, n = action >= DASM_REL_PC ? va_arg(ap, int) : 0;
|
||||
switch (action) {
|
||||
case DASM_STOP: goto stop;
|
||||
case DASM_SECTION:
|
||||
n = (ins & 255); CK(n < D->maxsection, RANGE_SEC);
|
||||
D->section = &D->sections[n]; goto stop;
|
||||
case DASM_ESC: p++; ofs += 4; break;
|
||||
case DASM_REL_EXT: break;
|
||||
case DASM_ALIGN: ofs += (ins & 255); b[pos++] = ofs; break;
|
||||
case DASM_REL_LG:
|
||||
n = (ins & 2047) - 10; pl = D->lglabels + n;
|
||||
/* Bkwd rel or global. */
|
||||
if (n >= 0) { CK(n>=10||*pl<0, RANGE_LG); CKPL(lg, LG); goto putrel; }
|
||||
pl += 10; n = *pl;
|
||||
if (n < 0) n = 0; /* Start new chain for fwd rel if label exists. */
|
||||
goto linkrel;
|
||||
case DASM_REL_PC:
|
||||
pl = D->pclabels + n; CKPL(pc, PC);
|
||||
putrel:
|
||||
n = *pl;
|
||||
if (n < 0) { /* Label exists. Get label pos and store it. */
|
||||
b[pos] = -n;
|
||||
} else {
|
||||
linkrel:
|
||||
b[pos] = n; /* Else link to rel chain, anchored at label. */
|
||||
*pl = pos;
|
||||
}
|
||||
pos++;
|
||||
break;
|
||||
case DASM_LABEL_LG:
|
||||
pl = D->lglabels + (ins & 2047) - 10; CKPL(lg, LG); goto putlabel;
|
||||
case DASM_LABEL_PC:
|
||||
pl = D->pclabels + n; CKPL(pc, PC);
|
||||
putlabel:
|
||||
n = *pl; /* n > 0: Collapse rel chain and replace with label pos. */
|
||||
while (n > 0) { int *pb = DASM_POS2PTR(D, n); n = *pb; *pb = pos;
|
||||
}
|
||||
*pl = -pos; /* Label exists now. */
|
||||
b[pos++] = ofs; /* Store pass1 offset estimate. */
|
||||
break;
|
||||
case DASM_IMM:
|
||||
#ifdef DASM_CHECKS
|
||||
CK((n & ((1<<((ins>>10)&31))-1)) == 0, RANGE_I);
|
||||
#endif
|
||||
n >>= ((ins>>10)&31);
|
||||
#ifdef DASM_CHECKS
|
||||
if (ins & 0x8000)
|
||||
CK(((n + (1<<(((ins>>5)&31)-1)))>>((ins>>5)&31)) == 0, RANGE_I);
|
||||
else
|
||||
CK((n>>((ins>>5)&31)) == 0, RANGE_I);
|
||||
#endif
|
||||
b[pos++] = n;
|
||||
break;
|
||||
case DASM_IMMSH:
|
||||
CK((n >> 6) == 0, RANGE_I);
|
||||
b[pos++] = n;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
stop:
|
||||
va_end(ap);
|
||||
sec->pos = pos;
|
||||
sec->ofs = ofs;
|
||||
}
|
||||
#undef CK
|
||||
|
||||
/* Pass 2: Link sections, shrink aligns, fix label offsets. */
|
||||
int dasm_link(Dst_DECL, size_t *szp)
|
||||
{
|
||||
dasm_State *D = Dst_REF;
|
||||
int secnum;
|
||||
int ofs = 0;
|
||||
|
||||
#ifdef DASM_CHECKS
|
||||
*szp = 0;
|
||||
if (D->status != DASM_S_OK) return D->status;
|
||||
{
|
||||
int pc;
|
||||
for (pc = 0; pc*sizeof(int) < D->pcsize; pc++)
|
||||
if (D->pclabels[pc] > 0) return DASM_S_UNDEF_PC|pc;
|
||||
}
|
||||
#endif
|
||||
|
||||
{ /* Handle globals not defined in this translation unit. */
|
||||
int idx;
|
||||
for (idx = 10; idx*sizeof(int) < D->lgsize; idx++) {
|
||||
int n = D->lglabels[idx];
|
||||
/* Undefined label: Collapse rel chain and replace with marker (< 0). */
|
||||
while (n > 0) { int *pb = DASM_POS2PTR(D, n); n = *pb; *pb = -idx; }
|
||||
}
|
||||
}
|
||||
|
||||
/* Combine all code sections. No support for data sections (yet). */
|
||||
for (secnum = 0; secnum < D->maxsection; secnum++) {
|
||||
dasm_Section *sec = D->sections + secnum;
|
||||
int *b = sec->rbuf;
|
||||
int pos = DASM_SEC2POS(secnum);
|
||||
int lastpos = sec->pos;
|
||||
|
||||
while (pos != lastpos) {
|
||||
dasm_ActList p = D->actionlist + b[pos++];
|
||||
while (1) {
|
||||
unsigned int ins = *p++;
|
||||
unsigned int action = (ins >> 16);
|
||||
switch (action) {
|
||||
case DASM_STOP: case DASM_SECTION: goto stop;
|
||||
case DASM_ESC: p++; break;
|
||||
case DASM_REL_EXT: break;
|
||||
case DASM_ALIGN: ofs -= (b[pos++] + ofs) & (ins & 255); break;
|
||||
case DASM_REL_LG: case DASM_REL_PC: pos++; break;
|
||||
case DASM_LABEL_LG: case DASM_LABEL_PC: b[pos++] += ofs; break;
|
||||
case DASM_IMM: case DASM_IMMSH: pos++; break;
|
||||
}
|
||||
}
|
||||
stop: (void)0;
|
||||
}
|
||||
ofs += sec->ofs; /* Next section starts right after current section. */
|
||||
}
|
||||
|
||||
D->codesize = ofs; /* Total size of all code sections */
|
||||
*szp = ofs;
|
||||
return DASM_S_OK;
|
||||
}
|
||||
|
||||
#ifdef DASM_CHECKS
|
||||
#define CK(x, st) \
|
||||
do { if (!(x)) return DASM_S_##st|(p-D->actionlist-1); } while (0)
|
||||
#else
|
||||
#define CK(x, st) ((void)0)
|
||||
#endif
|
||||
|
||||
/* Pass 3: Encode sections. */
|
||||
int dasm_encode(Dst_DECL, void *buffer)
|
||||
{
|
||||
dasm_State *D = Dst_REF;
|
||||
char *base = (char *)buffer;
|
||||
unsigned int *cp = (unsigned int *)buffer;
|
||||
int secnum;
|
||||
|
||||
/* Encode all code sections. No support for data sections (yet). */
|
||||
for (secnum = 0; secnum < D->maxsection; secnum++) {
|
||||
dasm_Section *sec = D->sections + secnum;
|
||||
int *b = sec->buf;
|
||||
int *endb = sec->rbuf + sec->pos;
|
||||
|
||||
while (b != endb) {
|
||||
dasm_ActList p = D->actionlist + *b++;
|
||||
while (1) {
|
||||
unsigned int ins = *p++;
|
||||
unsigned int action = (ins >> 16);
|
||||
int n = (action >= DASM_ALIGN && action < DASM__MAX) ? *b++ : 0;
|
||||
switch (action) {
|
||||
case DASM_STOP: case DASM_SECTION: goto stop;
|
||||
case DASM_ESC: *cp++ = *p++; break;
|
||||
case DASM_REL_EXT:
|
||||
n = DASM_EXTERN(Dst, (unsigned char *)cp, (ins & 2047), 1) - 4;
|
||||
goto patchrel;
|
||||
case DASM_ALIGN:
|
||||
ins &= 255; while ((((char *)cp - base) & ins)) *cp++ = 0x60000000;
|
||||
break;
|
||||
case DASM_REL_LG:
|
||||
if (n < 0) {
|
||||
n = (int)((ptrdiff_t)D->globals[-n-10] - (ptrdiff_t)cp);
|
||||
goto patchrel;
|
||||
}
|
||||
/* fallthrough */
|
||||
case DASM_REL_PC:
|
||||
CK(n >= 0, UNDEF_PC);
|
||||
n = *DASM_POS2PTR(D, n) - (int)((char *)cp - base);
|
||||
patchrel:
|
||||
CK((n & 3) == 0 &&
|
||||
(((n+4) + ((ins & 2048) ? 0x00008000 : 0x02000000)) >>
|
||||
((ins & 2048) ? 16 : 26)) == 0, RANGE_REL);
|
||||
cp[-1] |= ((n+4) & ((ins & 2048) ? 0x0000fffc: 0x03fffffc));
|
||||
break;
|
||||
case DASM_LABEL_LG:
|
||||
ins &= 2047; if (ins >= 20) D->globals[ins-20] = (void *)(base + n);
|
||||
break;
|
||||
case DASM_LABEL_PC: break;
|
||||
case DASM_IMM:
|
||||
cp[-1] |= (n & ((1<<((ins>>5)&31))-1)) << (ins&31);
|
||||
break;
|
||||
case DASM_IMMSH:
|
||||
cp[-1] |= (ins & 1) ? ((n&31)<<11)|((n&32)>>4) : ((n&31)<<6)|(n&32);
|
||||
break;
|
||||
default: *cp++ = ins; break;
|
||||
}
|
||||
}
|
||||
stop: (void)0;
|
||||
}
|
||||
}
|
||||
|
||||
if (base + D->codesize != (char *)cp) /* Check for phase errors. */
|
||||
return DASM_S_PHASE;
|
||||
return DASM_S_OK;
|
||||
}
|
||||
#undef CK
|
||||
|
||||
/* Get PC label offset. */
|
||||
int dasm_getpclabel(Dst_DECL, unsigned int pc)
|
||||
{
|
||||
dasm_State *D = Dst_REF;
|
||||
if (pc*sizeof(int) < D->pcsize) {
|
||||
int pos = D->pclabels[pc];
|
||||
if (pos < 0) return *DASM_POS2PTR(D, -pos);
|
||||
if (pos > 0) return -1; /* Undefined. */
|
||||
}
|
||||
return -2; /* Unused or out of range. */
|
||||
}
|
||||
|
||||
#ifdef DASM_CHECKS
|
||||
/* Optional sanity checker to call between isolated encoding steps. */
|
||||
int dasm_checkstep(Dst_DECL, int secmatch)
|
||||
{
|
||||
dasm_State *D = Dst_REF;
|
||||
if (D->status == DASM_S_OK) {
|
||||
int i;
|
||||
for (i = 1; i <= 9; i++) {
|
||||
if (D->lglabels[i] > 0) { D->status = DASM_S_UNDEF_LG|i; break; }
|
||||
D->lglabels[i] = 0;
|
||||
}
|
||||
}
|
||||
if (D->status == DASM_S_OK && secmatch >= 0 &&
|
||||
D->section != &D->sections[secmatch])
|
||||
D->status = DASM_S_MATCH_SEC|(D->section-D->sections);
|
||||
return D->status;
|
||||
}
|
||||
#endif
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -1,83 +0,0 @@
|
||||
/*
|
||||
** DynASM encoding engine prototypes.
|
||||
** Copyright (C) 2005-2023 Mike Pall. All rights reserved.
|
||||
** Released under the MIT license. See dynasm.lua for full copyright notice.
|
||||
*/
|
||||
|
||||
#ifndef _DASM_PROTO_H
|
||||
#define _DASM_PROTO_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#define DASM_IDENT "DynASM 1.5.0"
|
||||
#define DASM_VERSION 10500 /* 1.5.0 */
|
||||
|
||||
#ifndef Dst_DECL
|
||||
#define Dst_DECL dasm_State **Dst
|
||||
#endif
|
||||
|
||||
#ifndef Dst_REF
|
||||
#define Dst_REF (*Dst)
|
||||
#endif
|
||||
|
||||
#ifndef DASM_FDEF
|
||||
#define DASM_FDEF extern
|
||||
#endif
|
||||
|
||||
#ifndef DASM_M_GROW
|
||||
#define DASM_M_GROW(ctx, t, p, sz, need) \
|
||||
do { \
|
||||
size_t _sz = (sz), _need = (need); \
|
||||
if (_sz < _need) { \
|
||||
if (_sz < 16) _sz = 16; \
|
||||
while (_sz < _need) _sz += _sz; \
|
||||
(p) = (t *)realloc((p), _sz); \
|
||||
if ((p) == NULL) exit(1); \
|
||||
(sz) = _sz; \
|
||||
} \
|
||||
} while(0)
|
||||
#endif
|
||||
|
||||
#ifndef DASM_M_FREE
|
||||
#define DASM_M_FREE(ctx, p, sz) free(p)
|
||||
#endif
|
||||
|
||||
/* Internal DynASM encoder state. */
|
||||
typedef struct dasm_State dasm_State;
|
||||
|
||||
|
||||
/* Initialize and free DynASM state. */
|
||||
DASM_FDEF void dasm_init(Dst_DECL, int maxsection);
|
||||
DASM_FDEF void dasm_free(Dst_DECL);
|
||||
|
||||
/* Setup global array. Must be called before dasm_setup(). */
|
||||
DASM_FDEF void dasm_setupglobal(Dst_DECL, void **gl, unsigned int maxgl);
|
||||
|
||||
/* Grow PC label array. Can be called after dasm_setup(), too. */
|
||||
DASM_FDEF void dasm_growpc(Dst_DECL, unsigned int maxpc);
|
||||
|
||||
/* Setup encoder. */
|
||||
DASM_FDEF void dasm_setup(Dst_DECL, const void *actionlist);
|
||||
|
||||
/* Feed encoder with actions. Calls are generated by pre-processor. */
|
||||
DASM_FDEF void dasm_put(Dst_DECL, int start, ...);
|
||||
|
||||
/* Link sections and return the resulting size. */
|
||||
DASM_FDEF int dasm_link(Dst_DECL, size_t *szp);
|
||||
|
||||
/* Encode sections into buffer. */
|
||||
DASM_FDEF int dasm_encode(Dst_DECL, void *buffer);
|
||||
|
||||
/* Get PC label offset. */
|
||||
DASM_FDEF int dasm_getpclabel(Dst_DECL, unsigned int pc);
|
||||
|
||||
#ifdef DASM_CHECKS
|
||||
/* Optional sanity checker to call between isolated encoding steps. */
|
||||
DASM_FDEF int dasm_checkstep(Dst_DECL, int secmatch);
|
||||
#else
|
||||
#define dasm_checkstep(a, b) 0
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* _DASM_PROTO_H */
|
||||
@@ -1,12 +0,0 @@
|
||||
------------------------------------------------------------------------------
|
||||
-- DynASM x64 module.
|
||||
--
|
||||
-- Copyright (C) 2005-2023 Mike Pall. All rights reserved.
|
||||
-- See dynasm.lua for full copyright notice.
|
||||
------------------------------------------------------------------------------
|
||||
-- This module just sets 64 bit mode for the combined x86/x64 module.
|
||||
-- All the interesting stuff is there.
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
x64 = true -- Using a global is an ugly, but effective solution.
|
||||
return require("dasm_x86")
|
||||
@@ -1,523 +0,0 @@
|
||||
/*
|
||||
** DynASM x86 encoding engine.
|
||||
** Copyright (C) 2005-2023 Mike Pall. All rights reserved.
|
||||
** Released under the MIT license. See dynasm.lua for full copyright notice.
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define DASM_ARCH "x86"
|
||||
|
||||
#ifndef DASM_EXTERN
|
||||
#define DASM_EXTERN(a,b,c,d) 0
|
||||
#endif
|
||||
|
||||
/* Action definitions. DASM_STOP must be 255. */
|
||||
enum {
|
||||
DASM_DISP = 233,
|
||||
DASM_IMM_S, DASM_IMM_B, DASM_IMM_W, DASM_IMM_D, DASM_IMM_WB, DASM_IMM_DB,
|
||||
DASM_VREG, DASM_SPACE, DASM_SETLABEL, DASM_REL_A, DASM_REL_LG, DASM_REL_PC,
|
||||
DASM_IMM_LG, DASM_IMM_PC, DASM_LABEL_LG, DASM_LABEL_PC, DASM_ALIGN,
|
||||
DASM_EXTERN, DASM_ESC, DASM_MARK, DASM_SECTION, DASM_STOP
|
||||
};
|
||||
|
||||
/* Maximum number of section buffer positions for a single dasm_put() call. */
|
||||
#define DASM_MAXSECPOS 25
|
||||
|
||||
/* DynASM encoder status codes. Action list offset or number are or'ed in. */
|
||||
#define DASM_S_OK 0x00000000
|
||||
#define DASM_S_NOMEM 0x01000000
|
||||
#define DASM_S_PHASE 0x02000000
|
||||
#define DASM_S_MATCH_SEC 0x03000000
|
||||
#define DASM_S_RANGE_I 0x11000000
|
||||
#define DASM_S_RANGE_SEC 0x12000000
|
||||
#define DASM_S_RANGE_LG 0x13000000
|
||||
#define DASM_S_RANGE_PC 0x14000000
|
||||
#define DASM_S_RANGE_VREG 0x15000000
|
||||
#define DASM_S_UNDEF_L 0x21000000
|
||||
#define DASM_S_UNDEF_PC 0x22000000
|
||||
|
||||
/* Macros to convert positions (8 bit section + 24 bit index). */
|
||||
#define DASM_POS2IDX(pos) ((pos)&0x00ffffff)
|
||||
#define DASM_POS2BIAS(pos) ((pos)&0xff000000)
|
||||
#define DASM_SEC2POS(sec) ((sec)<<24)
|
||||
#define DASM_POS2SEC(pos) ((pos)>>24)
|
||||
#define DASM_POS2PTR(D, pos) (D->sections[DASM_POS2SEC(pos)].rbuf + (pos))
|
||||
|
||||
/* Action list type. */
|
||||
typedef const unsigned char *dasm_ActList;
|
||||
|
||||
/* Per-section structure. */
|
||||
typedef struct dasm_Section {
|
||||
int *rbuf; /* Biased buffer pointer (negative section bias). */
|
||||
int *buf; /* True buffer pointer. */
|
||||
size_t bsize; /* Buffer size in bytes. */
|
||||
int pos; /* Biased buffer position. */
|
||||
int epos; /* End of biased buffer position - max single put. */
|
||||
int ofs; /* Byte offset into section. */
|
||||
} dasm_Section;
|
||||
|
||||
/* Core structure holding the DynASM encoding state. */
|
||||
struct dasm_State {
|
||||
size_t psize; /* Allocated size of this structure. */
|
||||
dasm_ActList actionlist; /* Current actionlist pointer. */
|
||||
int *lglabels; /* Local/global chain/pos ptrs. */
|
||||
size_t lgsize;
|
||||
int *pclabels; /* PC label chains/pos ptrs. */
|
||||
size_t pcsize;
|
||||
void **globals; /* Array of globals. */
|
||||
dasm_Section *section; /* Pointer to active section. */
|
||||
size_t codesize; /* Total size of all code sections. */
|
||||
int maxsection; /* 0 <= sectionidx < maxsection. */
|
||||
int status; /* Status code. */
|
||||
dasm_Section sections[1]; /* All sections. Alloc-extended. */
|
||||
};
|
||||
|
||||
/* The size of the core structure depends on the max. number of sections. */
|
||||
#define DASM_PSZ(ms) (sizeof(dasm_State)+(ms-1)*sizeof(dasm_Section))
|
||||
|
||||
|
||||
/* Initialize DynASM state. */
|
||||
void dasm_init(Dst_DECL, int maxsection)
|
||||
{
|
||||
dasm_State *D;
|
||||
size_t psz = 0;
|
||||
Dst_REF = NULL;
|
||||
DASM_M_GROW(Dst, struct dasm_State, Dst_REF, psz, DASM_PSZ(maxsection));
|
||||
D = Dst_REF;
|
||||
D->psize = psz;
|
||||
D->lglabels = NULL;
|
||||
D->lgsize = 0;
|
||||
D->pclabels = NULL;
|
||||
D->pcsize = 0;
|
||||
D->globals = NULL;
|
||||
D->maxsection = maxsection;
|
||||
memset((void *)D->sections, 0, maxsection * sizeof(dasm_Section));
|
||||
}
|
||||
|
||||
/* Free DynASM state. */
|
||||
void dasm_free(Dst_DECL)
|
||||
{
|
||||
dasm_State *D = Dst_REF;
|
||||
int i;
|
||||
for (i = 0; i < D->maxsection; i++)
|
||||
if (D->sections[i].buf)
|
||||
DASM_M_FREE(Dst, D->sections[i].buf, D->sections[i].bsize);
|
||||
if (D->pclabels) DASM_M_FREE(Dst, D->pclabels, D->pcsize);
|
||||
if (D->lglabels) DASM_M_FREE(Dst, D->lglabels, D->lgsize);
|
||||
DASM_M_FREE(Dst, D, D->psize);
|
||||
}
|
||||
|
||||
/* Setup global label array. Must be called before dasm_setup(). */
|
||||
void dasm_setupglobal(Dst_DECL, void **gl, unsigned int maxgl)
|
||||
{
|
||||
dasm_State *D = Dst_REF;
|
||||
D->globals = gl;
|
||||
DASM_M_GROW(Dst, int, D->lglabels, D->lgsize, (10+maxgl)*sizeof(int));
|
||||
}
|
||||
|
||||
/* Grow PC label array. Can be called after dasm_setup(), too. */
|
||||
void dasm_growpc(Dst_DECL, unsigned int maxpc)
|
||||
{
|
||||
dasm_State *D = Dst_REF;
|
||||
size_t osz = D->pcsize;
|
||||
DASM_M_GROW(Dst, int, D->pclabels, D->pcsize, maxpc*sizeof(int));
|
||||
memset((void *)(((unsigned char *)D->pclabels)+osz), 0, D->pcsize-osz);
|
||||
}
|
||||
|
||||
/* Setup encoder. */
|
||||
void dasm_setup(Dst_DECL, const void *actionlist)
|
||||
{
|
||||
dasm_State *D = Dst_REF;
|
||||
int i;
|
||||
D->actionlist = (dasm_ActList)actionlist;
|
||||
D->status = DASM_S_OK;
|
||||
D->section = &D->sections[0];
|
||||
memset((void *)D->lglabels, 0, D->lgsize);
|
||||
if (D->pclabels) memset((void *)D->pclabels, 0, D->pcsize);
|
||||
for (i = 0; i < D->maxsection; i++) {
|
||||
D->sections[i].pos = DASM_SEC2POS(i);
|
||||
D->sections[i].rbuf = D->sections[i].buf - D->sections[i].pos;
|
||||
D->sections[i].ofs = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifdef DASM_CHECKS
|
||||
#define CK(x, st) \
|
||||
do { if (!(x)) { \
|
||||
D->status = DASM_S_##st|(int)(p-D->actionlist-1); return; } } while (0)
|
||||
#define CKPL(kind, st) \
|
||||
do { if ((size_t)((char *)pl-(char *)D->kind##labels) >= D->kind##size) { \
|
||||
D->status=DASM_S_RANGE_##st|(int)(p-D->actionlist-1); return; } } while (0)
|
||||
#else
|
||||
#define CK(x, st) ((void)0)
|
||||
#define CKPL(kind, st) ((void)0)
|
||||
#endif
|
||||
|
||||
/* Pass 1: Store actions and args, link branches/labels, estimate offsets. */
|
||||
void dasm_put(Dst_DECL, int start, ...)
|
||||
{
|
||||
va_list ap;
|
||||
dasm_State *D = Dst_REF;
|
||||
dasm_ActList p = D->actionlist + start;
|
||||
dasm_Section *sec = D->section;
|
||||
int pos = sec->pos, ofs = sec->ofs, mrm = -1;
|
||||
int *b;
|
||||
|
||||
if (pos >= sec->epos) {
|
||||
DASM_M_GROW(Dst, int, sec->buf, sec->bsize,
|
||||
sec->bsize + 2*DASM_MAXSECPOS*sizeof(int));
|
||||
sec->rbuf = sec->buf - DASM_POS2BIAS(pos);
|
||||
sec->epos = (int)sec->bsize/sizeof(int) - DASM_MAXSECPOS+DASM_POS2BIAS(pos);
|
||||
}
|
||||
|
||||
b = sec->rbuf;
|
||||
b[pos++] = start;
|
||||
|
||||
va_start(ap, start);
|
||||
while (1) {
|
||||
int action = *p++;
|
||||
if (action < DASM_DISP) {
|
||||
ofs++;
|
||||
} else if (action <= DASM_REL_A) {
|
||||
int n = va_arg(ap, int);
|
||||
b[pos++] = n;
|
||||
switch (action) {
|
||||
case DASM_DISP:
|
||||
if (n == 0) { if (mrm < 0) mrm = p[-2]; if ((mrm&7) != 5) break; }
|
||||
/* fallthrough */
|
||||
case DASM_IMM_DB: if (((n+128)&-256) == 0) goto ob; /* fallthrough */
|
||||
case DASM_REL_A: /* Assumes ptrdiff_t is int. !x64 */
|
||||
case DASM_IMM_D: ofs += 4; break;
|
||||
case DASM_IMM_S: CK(((n+128)&-256) == 0, RANGE_I); goto ob;
|
||||
case DASM_IMM_B: CK((n&-256) == 0, RANGE_I); ob: ofs++; break;
|
||||
case DASM_IMM_WB: if (((n+128)&-256) == 0) goto ob; /* fallthrough */
|
||||
case DASM_IMM_W: CK((n&-65536) == 0, RANGE_I); ofs += 2; break;
|
||||
case DASM_SPACE: p++; ofs += n; break;
|
||||
case DASM_SETLABEL: b[pos-2] = -0x40000000; break; /* Neg. label ofs. */
|
||||
case DASM_VREG: CK((n&-16) == 0 && (n != 4 || (*p>>5) != 2), RANGE_VREG);
|
||||
if (*p < 0x40 && p[1] == DASM_DISP) mrm = n;
|
||||
if (*p < 0x20 && (n&7) == 4) ofs++;
|
||||
switch ((*p++ >> 3) & 3) {
|
||||
case 3: n |= b[pos-3]; /* fallthrough */
|
||||
case 2: n |= b[pos-2]; /* fallthrough */
|
||||
case 1: if (n <= 7) { b[pos-1] |= 0x10; ofs--; }
|
||||
}
|
||||
continue;
|
||||
}
|
||||
mrm = -1;
|
||||
} else {
|
||||
int *pl, n;
|
||||
switch (action) {
|
||||
case DASM_REL_LG:
|
||||
case DASM_IMM_LG:
|
||||
n = *p++; pl = D->lglabels + n;
|
||||
/* Bkwd rel or global. */
|
||||
if (n <= 246) { CK(n>=10||*pl<0, RANGE_LG); CKPL(lg, LG); goto putrel; }
|
||||
pl -= 246; n = *pl;
|
||||
if (n < 0) n = 0; /* Start new chain for fwd rel if label exists. */
|
||||
goto linkrel;
|
||||
case DASM_REL_PC:
|
||||
case DASM_IMM_PC: pl = D->pclabels + va_arg(ap, int); CKPL(pc, PC);
|
||||
putrel:
|
||||
n = *pl;
|
||||
if (n < 0) { /* Label exists. Get label pos and store it. */
|
||||
b[pos] = -n;
|
||||
} else {
|
||||
linkrel:
|
||||
b[pos] = n; /* Else link to rel chain, anchored at label. */
|
||||
*pl = pos;
|
||||
}
|
||||
pos++;
|
||||
ofs += 4; /* Maximum offset needed. */
|
||||
if (action == DASM_REL_LG || action == DASM_REL_PC) {
|
||||
b[pos++] = ofs; /* Store pass1 offset estimate. */
|
||||
} else if (sizeof(ptrdiff_t) == 8) {
|
||||
ofs += 4;
|
||||
}
|
||||
break;
|
||||
case DASM_LABEL_LG: pl = D->lglabels + *p++; CKPL(lg, LG); goto putlabel;
|
||||
case DASM_LABEL_PC: pl = D->pclabels + va_arg(ap, int); CKPL(pc, PC);
|
||||
putlabel:
|
||||
n = *pl; /* n > 0: Collapse rel chain and replace with label pos. */
|
||||
while (n > 0) { int *pb = DASM_POS2PTR(D, n); n = *pb; *pb = pos; }
|
||||
*pl = -pos; /* Label exists now. */
|
||||
b[pos++] = ofs; /* Store pass1 offset estimate. */
|
||||
break;
|
||||
case DASM_ALIGN:
|
||||
ofs += *p++; /* Maximum alignment needed (arg is 2**n-1). */
|
||||
b[pos++] = ofs; /* Store pass1 offset estimate. */
|
||||
break;
|
||||
case DASM_EXTERN: p += 2; ofs += 4; break;
|
||||
case DASM_ESC: p++; ofs++; break;
|
||||
case DASM_MARK: mrm = p[-2]; break;
|
||||
case DASM_SECTION:
|
||||
n = *p; CK(n < D->maxsection, RANGE_SEC); D->section = &D->sections[n];
|
||||
case DASM_STOP: goto stop;
|
||||
}
|
||||
}
|
||||
}
|
||||
stop:
|
||||
va_end(ap);
|
||||
sec->pos = pos;
|
||||
sec->ofs = ofs;
|
||||
}
|
||||
#undef CK
|
||||
|
||||
/* Pass 2: Link sections, shrink branches/aligns, fix label offsets. */
|
||||
int dasm_link(Dst_DECL, size_t *szp)
|
||||
{
|
||||
dasm_State *D = Dst_REF;
|
||||
int secnum;
|
||||
int ofs = 0;
|
||||
|
||||
#ifdef DASM_CHECKS
|
||||
*szp = 0;
|
||||
if (D->status != DASM_S_OK) return D->status;
|
||||
{
|
||||
int pc;
|
||||
for (pc = 0; pc*sizeof(int) < D->pcsize; pc++)
|
||||
if (D->pclabels[pc] > 0) return DASM_S_UNDEF_PC|pc;
|
||||
}
|
||||
#endif
|
||||
|
||||
{ /* Handle globals not defined in this translation unit. */
|
||||
int idx;
|
||||
for (idx = 10; idx*sizeof(int) < D->lgsize; idx++) {
|
||||
int n = D->lglabels[idx];
|
||||
/* Undefined label: Collapse rel chain and replace with marker (< 0). */
|
||||
while (n > 0) { int *pb = DASM_POS2PTR(D, n); n = *pb; *pb = -idx; }
|
||||
}
|
||||
}
|
||||
|
||||
/* Combine all code sections. No support for data sections (yet). */
|
||||
for (secnum = 0; secnum < D->maxsection; secnum++) {
|
||||
dasm_Section *sec = D->sections + secnum;
|
||||
int *b = sec->rbuf;
|
||||
int pos = DASM_SEC2POS(secnum);
|
||||
int lastpos = sec->pos;
|
||||
|
||||
while (pos != lastpos) {
|
||||
dasm_ActList p = D->actionlist + b[pos++];
|
||||
int op = 0;
|
||||
while (1) {
|
||||
int action = *p++;
|
||||
switch (action) {
|
||||
case DASM_REL_LG: p++;
|
||||
/* fallthrough */
|
||||
case DASM_REL_PC: {
|
||||
int shrink = op == 0xe9 ? 3 : ((op&0xf0) == 0x80 ? 4 : 0);
|
||||
if (shrink) { /* Shrinkable branch opcode? */
|
||||
int lofs, lpos = b[pos];
|
||||
if (lpos < 0) goto noshrink; /* Ext global? */
|
||||
lofs = *DASM_POS2PTR(D, lpos);
|
||||
if (lpos > pos) { /* Fwd label: add cumulative section offsets. */
|
||||
int i;
|
||||
for (i = secnum; i < DASM_POS2SEC(lpos); i++)
|
||||
lofs += D->sections[i].ofs;
|
||||
} else {
|
||||
lofs -= ofs; /* Bkwd label: unfix offset. */
|
||||
}
|
||||
lofs -= b[pos+1]; /* Short branch ok? */
|
||||
if (lofs >= -128-shrink && lofs <= 127) ofs -= shrink; /* Yes. */
|
||||
else { noshrink: shrink = 0; } /* No, cannot shrink op. */
|
||||
}
|
||||
b[pos+1] = shrink;
|
||||
pos += 2;
|
||||
break;
|
||||
}
|
||||
/* fallthrough */
|
||||
case DASM_SPACE: case DASM_IMM_LG: case DASM_VREG: p++;
|
||||
/* fallthrough */
|
||||
case DASM_DISP: case DASM_IMM_S: case DASM_IMM_B: case DASM_IMM_W:
|
||||
case DASM_IMM_D: case DASM_IMM_WB: case DASM_IMM_DB:
|
||||
case DASM_SETLABEL: case DASM_REL_A: case DASM_IMM_PC: pos++; break;
|
||||
case DASM_LABEL_LG: p++;
|
||||
/* fallthrough */
|
||||
case DASM_LABEL_PC: b[pos++] += ofs; break; /* Fix label offset. */
|
||||
case DASM_ALIGN: ofs -= (b[pos++]+ofs)&*p++; break; /* Adjust ofs. */
|
||||
case DASM_EXTERN: p += 2; break;
|
||||
case DASM_ESC: op = *p++; break;
|
||||
case DASM_MARK: break;
|
||||
case DASM_SECTION: case DASM_STOP: goto stop;
|
||||
default: op = action; break;
|
||||
}
|
||||
}
|
||||
stop: (void)0;
|
||||
}
|
||||
ofs += sec->ofs; /* Next section starts right after current section. */
|
||||
}
|
||||
|
||||
D->codesize = ofs; /* Total size of all code sections */
|
||||
*szp = ofs;
|
||||
return DASM_S_OK;
|
||||
}
|
||||
|
||||
#define dasmb(x) *cp++ = (unsigned char)(x)
|
||||
#ifndef DASM_ALIGNED_WRITES
|
||||
#define dasmw(x) \
|
||||
do { *((unsigned short *)cp) = (unsigned short)(x); cp+=2; } while (0)
|
||||
#define dasmd(x) \
|
||||
do { *((unsigned int *)cp) = (unsigned int)(x); cp+=4; } while (0)
|
||||
#define dasmq(x) \
|
||||
do { *((unsigned long long *)cp) = (unsigned long long)(x); cp+=8; } while (0)
|
||||
#else
|
||||
#define dasmw(x) do { dasmb(x); dasmb((x)>>8); } while (0)
|
||||
#define dasmd(x) do { dasmw(x); dasmw((x)>>16); } while (0)
|
||||
#define dasmq(x) do { dasmd(x); dasmd((x)>>32); } while (0)
|
||||
#endif
|
||||
static unsigned char *dasma_(unsigned char *cp, ptrdiff_t x)
|
||||
{
|
||||
if (sizeof(ptrdiff_t) == 8)
|
||||
dasmq((unsigned long long)x);
|
||||
else
|
||||
dasmd((unsigned int)x);
|
||||
return cp;
|
||||
}
|
||||
#define dasma(x) (cp = dasma_(cp, (x)))
|
||||
|
||||
/* Pass 3: Encode sections. */
|
||||
int dasm_encode(Dst_DECL, void *buffer)
|
||||
{
|
||||
dasm_State *D = Dst_REF;
|
||||
unsigned char *base = (unsigned char *)buffer;
|
||||
unsigned char *cp = base;
|
||||
int secnum;
|
||||
|
||||
/* Encode all code sections. No support for data sections (yet). */
|
||||
for (secnum = 0; secnum < D->maxsection; secnum++) {
|
||||
dasm_Section *sec = D->sections + secnum;
|
||||
int *b = sec->buf;
|
||||
int *endb = sec->rbuf + sec->pos;
|
||||
|
||||
while (b != endb) {
|
||||
dasm_ActList p = D->actionlist + *b++;
|
||||
unsigned char *mark = NULL;
|
||||
while (1) {
|
||||
int action = *p++;
|
||||
int n = (action >= DASM_DISP && action <= DASM_ALIGN) ? *b++ : 0;
|
||||
switch (action) {
|
||||
case DASM_DISP: if (!mark) mark = cp; {
|
||||
unsigned char *mm = mark;
|
||||
if (*p != DASM_IMM_DB && *p != DASM_IMM_WB) mark = NULL;
|
||||
if (n == 0) { int mrm = mm[-1]&7; if (mrm == 4) mrm = mm[0]&7;
|
||||
if (mrm != 5) { mm[-1] -= 0x80; break; } }
|
||||
if (((n+128) & -256) != 0) goto wd; else mm[-1] -= 0x40;
|
||||
}
|
||||
/* fallthrough */
|
||||
case DASM_IMM_S: case DASM_IMM_B: wb: dasmb(n); break;
|
||||
case DASM_IMM_DB: if (((n+128)&-256) == 0) {
|
||||
db: if (!mark) mark = cp; mark[-2] += 2; mark = NULL; goto wb;
|
||||
} else mark = NULL;
|
||||
/* fallthrough */
|
||||
case DASM_IMM_D: wd: dasmd(n); break;
|
||||
case DASM_IMM_WB: if (((n+128)&-256) == 0) goto db; else mark = NULL;
|
||||
/* fallthrough */
|
||||
case DASM_IMM_W: dasmw(n); break;
|
||||
case DASM_VREG: {
|
||||
int t = *p++;
|
||||
unsigned char *ex = cp - (t&7);
|
||||
if ((n & 8) && t < 0xa0) {
|
||||
if (*ex & 0x80) ex[1] ^= 0x20 << (t>>6); else *ex ^= 1 << (t>>6);
|
||||
n &= 7;
|
||||
} else if (n & 0x10) {
|
||||
if (*ex & 0x80) {
|
||||
*ex = 0xc5; ex[1] = (ex[1] & 0x80) | ex[2]; ex += 2;
|
||||
}
|
||||
while (++ex < cp) ex[-1] = *ex;
|
||||
if (mark) mark--;
|
||||
cp--;
|
||||
n &= 7;
|
||||
}
|
||||
if (t >= 0xc0) n <<= 4;
|
||||
else if (t >= 0x40) n <<= 3;
|
||||
else if (n == 4 && t < 0x20) { cp[-1] ^= n; *cp++ = 0x20; }
|
||||
cp[-1] ^= n;
|
||||
break;
|
||||
}
|
||||
case DASM_REL_LG: p++; if (n >= 0) goto rel_pc;
|
||||
b++; n = (int)(ptrdiff_t)D->globals[-n-10];
|
||||
/* fallthrough */
|
||||
case DASM_REL_A: rel_a:
|
||||
n -= (unsigned int)(ptrdiff_t)(cp+4); goto wd; /* !x64 */
|
||||
case DASM_REL_PC: rel_pc: {
|
||||
int shrink = *b++;
|
||||
int *pb = DASM_POS2PTR(D, n); if (*pb < 0) { n = pb[1]; goto rel_a; }
|
||||
n = *pb - ((int)(cp-base) + 4-shrink);
|
||||
if (shrink == 0) goto wd;
|
||||
if (shrink == 4) { cp--; cp[-1] = *cp-0x10; } else cp[-1] = 0xeb;
|
||||
goto wb;
|
||||
}
|
||||
case DASM_IMM_LG:
|
||||
p++;
|
||||
if (n < 0) { dasma((ptrdiff_t)D->globals[-n-10]); break; }
|
||||
/* fallthrough */
|
||||
case DASM_IMM_PC: {
|
||||
int *pb = DASM_POS2PTR(D, n);
|
||||
dasma(*pb < 0 ? (ptrdiff_t)pb[1] : (*pb + (ptrdiff_t)base));
|
||||
break;
|
||||
}
|
||||
case DASM_LABEL_LG: {
|
||||
int idx = *p++;
|
||||
if (idx >= 10)
|
||||
D->globals[idx-10] = (void *)(base + (*p == DASM_SETLABEL ? *b : n));
|
||||
break;
|
||||
}
|
||||
case DASM_LABEL_PC: case DASM_SETLABEL: break;
|
||||
case DASM_SPACE: { int fill = *p++; while (n--) *cp++ = fill; break; }
|
||||
case DASM_ALIGN:
|
||||
n = *p++;
|
||||
while (((cp-base) & n)) *cp++ = 0x90; /* nop */
|
||||
break;
|
||||
case DASM_EXTERN: n = DASM_EXTERN(Dst, cp, p[1], *p); p += 2; goto wd;
|
||||
case DASM_MARK: mark = cp; break;
|
||||
case DASM_ESC: action = *p++;
|
||||
/* fallthrough */
|
||||
default: *cp++ = action; break;
|
||||
case DASM_SECTION: case DASM_STOP: goto stop;
|
||||
}
|
||||
}
|
||||
stop: (void)0;
|
||||
}
|
||||
}
|
||||
|
||||
if (base + D->codesize != cp) /* Check for phase errors. */
|
||||
return DASM_S_PHASE;
|
||||
return DASM_S_OK;
|
||||
}
|
||||
|
||||
/* Get PC label offset. */
|
||||
int dasm_getpclabel(Dst_DECL, unsigned int pc)
|
||||
{
|
||||
dasm_State *D = Dst_REF;
|
||||
if (pc*sizeof(int) < D->pcsize) {
|
||||
int pos = D->pclabels[pc];
|
||||
if (pos < 0) return *DASM_POS2PTR(D, -pos);
|
||||
if (pos > 0) return -1; /* Undefined. */
|
||||
}
|
||||
return -2; /* Unused or out of range. */
|
||||
}
|
||||
|
||||
#ifdef DASM_CHECKS
|
||||
/* Optional sanity checker to call between isolated encoding steps. */
|
||||
int dasm_checkstep(Dst_DECL, int secmatch)
|
||||
{
|
||||
dasm_State *D = Dst_REF;
|
||||
if (D->status == DASM_S_OK) {
|
||||
int i;
|
||||
for (i = 1; i <= 9; i++) {
|
||||
if (D->lglabels[i] > 0) { D->status = DASM_S_UNDEF_L|i; break; }
|
||||
D->lglabels[i] = 0;
|
||||
}
|
||||
}
|
||||
if (D->status == DASM_S_OK && secmatch >= 0 &&
|
||||
D->section != &D->sections[secmatch])
|
||||
D->status = DASM_S_MATCH_SEC|(int)(D->section-D->sections);
|
||||
return D->status;
|
||||
}
|
||||
#endif
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
@@ -1,3 +0,0 @@
|
||||
minilua
|
||||
buildvm
|
||||
buildvm_arch.h
|
||||
@@ -1,4 +0,0 @@
|
||||
The files in this directory are only used during the build process of LuaJIT.
|
||||
For cross-compilation, they must be executed on the host, not on the target.
|
||||
|
||||
These files should NOT be installed!
|
||||
@@ -1,529 +0,0 @@
|
||||
/*
|
||||
** LuaJIT VM builder.
|
||||
** Copyright (C) 2005-2023 Mike Pall. See Copyright Notice in luajit.h
|
||||
**
|
||||
** This is a tool to build the hand-tuned assembler code required for
|
||||
** LuaJIT's bytecode interpreter. It supports a variety of output formats
|
||||
** to feed different toolchains (see usage() below).
|
||||
**
|
||||
** This tool is not particularly optimized because it's only used while
|
||||
** _building_ LuaJIT. There's no point in distributing or installing it.
|
||||
** Only the object code generated by this tool is linked into LuaJIT.
|
||||
**
|
||||
** Caveat: some memory is not free'd, error handling is lazy.
|
||||
** It's a one-shot tool -- any effort fixing this would be wasted.
|
||||
*/
|
||||
|
||||
#include "buildvm.h"
|
||||
#include "lj_obj.h"
|
||||
#include "lj_gc.h"
|
||||
#include "lj_bc.h"
|
||||
#if LJ_HASJIT
|
||||
#include "lj_ir.h"
|
||||
#include "lj_ircall.h"
|
||||
#endif
|
||||
#include "lj_frame.h"
|
||||
#include "lj_dispatch.h"
|
||||
#if LJ_HASFFI
|
||||
#include "lj_ctype.h"
|
||||
#include "lj_ccall.h"
|
||||
#endif
|
||||
#include "luajit.h"
|
||||
|
||||
#if defined(_WIN32)
|
||||
#include <fcntl.h>
|
||||
#include <io.h>
|
||||
#endif
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
/* DynASM glue definitions. */
|
||||
#define Dst ctx
|
||||
#define Dst_DECL BuildCtx *ctx
|
||||
#define Dst_REF (ctx->D)
|
||||
#define DASM_CHECKS 1
|
||||
|
||||
#include "../dynasm/dasm_proto.h"
|
||||
|
||||
/* Glue macros for DynASM. */
|
||||
static int collect_reloc(BuildCtx *ctx, uint8_t *addr, int idx, int type);
|
||||
|
||||
#define DASM_EXTERN(ctx, addr, idx, type) \
|
||||
collect_reloc(ctx, addr, idx, type)
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
/* Avoid trouble if cross-compiling for an x86 target. Speed doesn't matter. */
|
||||
#define DASM_ALIGNED_WRITES 1
|
||||
|
||||
/* Embed architecture-specific DynASM encoder. */
|
||||
#if LJ_TARGET_X86ORX64
|
||||
#include "../dynasm/dasm_x86.h"
|
||||
#elif LJ_TARGET_ARM
|
||||
#include "../dynasm/dasm_arm.h"
|
||||
#elif LJ_TARGET_ARM64
|
||||
#include "../dynasm/dasm_arm64.h"
|
||||
#elif LJ_TARGET_PPC
|
||||
#include "../dynasm/dasm_ppc.h"
|
||||
#elif LJ_TARGET_MIPS
|
||||
#include "../dynasm/dasm_mips.h"
|
||||
#else
|
||||
#error "No support for this architecture (yet)"
|
||||
#endif
|
||||
|
||||
/* Embed generated architecture-specific backend. */
|
||||
#include "buildvm_arch.h"
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
void owrite(BuildCtx *ctx, const void *ptr, size_t sz)
|
||||
{
|
||||
if (fwrite(ptr, 1, sz, ctx->fp) != sz) {
|
||||
fprintf(stderr, "Error: cannot write to output file: %s\n",
|
||||
strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
/* Emit code as raw bytes. Only used for DynASM debugging. */
|
||||
static void emit_raw(BuildCtx *ctx)
|
||||
{
|
||||
owrite(ctx, ctx->code, ctx->codesz);
|
||||
}
|
||||
|
||||
/* -- Build machine code -------------------------------------------------- */
|
||||
|
||||
static const char *sym_decorate(BuildCtx *ctx,
|
||||
const char *prefix, const char *suffix)
|
||||
{
|
||||
char name[256];
|
||||
char *p;
|
||||
#if LJ_64
|
||||
const char *symprefix = ctx->mode == BUILD_machasm ? "_" : "";
|
||||
#elif LJ_TARGET_XBOX360
|
||||
const char *symprefix = "";
|
||||
#else
|
||||
const char *symprefix = ctx->mode != BUILD_elfasm ? "_" : "";
|
||||
#endif
|
||||
sprintf(name, "%s%s%s", symprefix, prefix, suffix);
|
||||
p = strchr(name, '@');
|
||||
if (p) {
|
||||
#if LJ_TARGET_X86ORX64
|
||||
if (!LJ_64 && (ctx->mode == BUILD_coffasm || ctx->mode == BUILD_peobj))
|
||||
name[0] = name[1] == 'R' ? '_' : '@'; /* Just for _RtlUnwind@16. */
|
||||
else
|
||||
*p = '\0';
|
||||
#elif LJ_TARGET_PPC && !LJ_TARGET_CONSOLE
|
||||
/* Keep @plt etc. */
|
||||
#else
|
||||
*p = '\0';
|
||||
#endif
|
||||
}
|
||||
p = (char *)malloc(strlen(name)+1); /* MSVC doesn't like strdup. */
|
||||
strcpy(p, name);
|
||||
return p;
|
||||
}
|
||||
|
||||
#define NRELOCSYM (sizeof(extnames)/sizeof(extnames[0])-1)
|
||||
|
||||
static int relocmap[NRELOCSYM];
|
||||
|
||||
/* Collect external relocations. */
|
||||
static int collect_reloc(BuildCtx *ctx, uint8_t *addr, int idx, int type)
|
||||
{
|
||||
if (ctx->nreloc >= BUILD_MAX_RELOC) {
|
||||
fprintf(stderr, "Error: too many relocations, increase BUILD_MAX_RELOC.\n");
|
||||
exit(1);
|
||||
}
|
||||
if (relocmap[idx] < 0) {
|
||||
relocmap[idx] = ctx->nrelocsym;
|
||||
ctx->relocsym[ctx->nrelocsym] = sym_decorate(ctx, "", extnames[idx]);
|
||||
ctx->nrelocsym++;
|
||||
}
|
||||
ctx->reloc[ctx->nreloc].ofs = (int32_t)(addr - ctx->code);
|
||||
ctx->reloc[ctx->nreloc].sym = relocmap[idx];
|
||||
ctx->reloc[ctx->nreloc].type = type;
|
||||
ctx->nreloc++;
|
||||
#if LJ_TARGET_XBOX360
|
||||
return (int)(ctx->code - addr) + 4; /* Encode symbol offset of .text. */
|
||||
#else
|
||||
return 0; /* Encode symbol offset of 0. */
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Naive insertion sort. Performance doesn't matter here. */
|
||||
static void sym_insert(BuildCtx *ctx, int32_t ofs,
|
||||
const char *prefix, const char *suffix)
|
||||
{
|
||||
ptrdiff_t i = ctx->nsym++;
|
||||
while (i > 0) {
|
||||
if (ctx->sym[i-1].ofs <= ofs)
|
||||
break;
|
||||
ctx->sym[i] = ctx->sym[i-1];
|
||||
i--;
|
||||
}
|
||||
ctx->sym[i].ofs = ofs;
|
||||
ctx->sym[i].name = sym_decorate(ctx, prefix, suffix);
|
||||
}
|
||||
|
||||
/* Build the machine code. */
|
||||
static int build_code(BuildCtx *ctx)
|
||||
{
|
||||
int status;
|
||||
int i;
|
||||
|
||||
/* Initialize DynASM structures. */
|
||||
ctx->nglob = GLOB__MAX;
|
||||
ctx->glob = (void **)malloc(ctx->nglob*sizeof(void *));
|
||||
memset(ctx->glob, 0, ctx->nglob*sizeof(void *));
|
||||
ctx->nreloc = 0;
|
||||
|
||||
ctx->globnames = globnames;
|
||||
ctx->extnames = extnames;
|
||||
ctx->relocsym = (const char **)malloc(NRELOCSYM*sizeof(const char *));
|
||||
ctx->nrelocsym = 0;
|
||||
for (i = 0; i < (int)NRELOCSYM; i++) relocmap[i] = -1;
|
||||
|
||||
ctx->dasm_ident = DASM_IDENT;
|
||||
ctx->dasm_arch = DASM_ARCH;
|
||||
|
||||
dasm_init(Dst, DASM_MAXSECTION);
|
||||
dasm_setupglobal(Dst, ctx->glob, ctx->nglob);
|
||||
dasm_setup(Dst, build_actionlist);
|
||||
|
||||
/* Call arch-specific backend to emit the code. */
|
||||
ctx->npc = build_backend(ctx);
|
||||
|
||||
/* Finalize the code. */
|
||||
(void)dasm_checkstep(Dst, -1);
|
||||
if ((status = dasm_link(Dst, &ctx->codesz))) return status;
|
||||
ctx->code = (uint8_t *)malloc(ctx->codesz);
|
||||
if ((status = dasm_encode(Dst, (void *)ctx->code))) return status;
|
||||
|
||||
/* Allocate symbol table and bytecode offsets. */
|
||||
ctx->beginsym = sym_decorate(ctx, "", LABEL_PREFIX "vm_asm_begin");
|
||||
ctx->sym = (BuildSym *)malloc((ctx->npc+ctx->nglob+1)*sizeof(BuildSym));
|
||||
ctx->nsym = 0;
|
||||
ctx->bc_ofs = (int32_t *)malloc(ctx->npc*sizeof(int32_t));
|
||||
|
||||
/* Collect the opcodes (PC labels). */
|
||||
for (i = 0; i < ctx->npc; i++) {
|
||||
int32_t ofs = dasm_getpclabel(Dst, i);
|
||||
if (ofs < 0) return 0x22000000|i;
|
||||
ctx->bc_ofs[i] = ofs;
|
||||
if ((LJ_HASJIT ||
|
||||
!(i == BC_JFORI || i == BC_JFORL || i == BC_JITERL || i == BC_JLOOP ||
|
||||
i == BC_IFORL || i == BC_IITERL || i == BC_ILOOP)) &&
|
||||
(LJ_HASFFI || i != BC_KCDATA))
|
||||
sym_insert(ctx, ofs, LABEL_PREFIX_BC, bc_names[i]);
|
||||
}
|
||||
|
||||
/* Collect the globals (named labels). */
|
||||
for (i = 0; i < ctx->nglob; i++) {
|
||||
const char *gl = globnames[i];
|
||||
int len = (int)strlen(gl);
|
||||
if (!ctx->glob[i]) {
|
||||
fprintf(stderr, "Error: undefined global %s\n", gl);
|
||||
exit(2);
|
||||
}
|
||||
/* Skip the _Z symbols. */
|
||||
if (!(len >= 2 && gl[len-2] == '_' && gl[len-1] == 'Z'))
|
||||
sym_insert(ctx, (int32_t)((uint8_t *)(ctx->glob[i]) - ctx->code),
|
||||
LABEL_PREFIX, globnames[i]);
|
||||
}
|
||||
|
||||
/* Close the address range. */
|
||||
sym_insert(ctx, (int32_t)ctx->codesz, "", "");
|
||||
ctx->nsym--;
|
||||
|
||||
dasm_free(Dst);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* -- Generate VM enums --------------------------------------------------- */
|
||||
|
||||
const char *const bc_names[] = {
|
||||
#define BCNAME(name, ma, mb, mc, mt) #name,
|
||||
BCDEF(BCNAME)
|
||||
#undef BCNAME
|
||||
NULL
|
||||
};
|
||||
|
||||
#if LJ_HASJIT
|
||||
const char *const ir_names[] = {
|
||||
#define IRNAME(name, m, m1, m2) #name,
|
||||
IRDEF(IRNAME)
|
||||
#undef IRNAME
|
||||
NULL
|
||||
};
|
||||
|
||||
const char *const irt_names[] = {
|
||||
#define IRTNAME(name, size) #name,
|
||||
IRTDEF(IRTNAME)
|
||||
#undef IRTNAME
|
||||
NULL
|
||||
};
|
||||
|
||||
const char *const irfpm_names[] = {
|
||||
#define FPMNAME(name) #name,
|
||||
IRFPMDEF(FPMNAME)
|
||||
#undef FPMNAME
|
||||
NULL
|
||||
};
|
||||
|
||||
const char *const irfield_names[] = {
|
||||
#define FLNAME(name, ofs) #name,
|
||||
IRFLDEF(FLNAME)
|
||||
#undef FLNAME
|
||||
NULL
|
||||
};
|
||||
|
||||
const char *const ircall_names[] = {
|
||||
#define IRCALLNAME(cond, name, nargs, kind, type, flags) #name,
|
||||
IRCALLDEF(IRCALLNAME)
|
||||
#undef IRCALLNAME
|
||||
NULL
|
||||
};
|
||||
|
||||
static const char *const trace_errors[] = {
|
||||
#define TREDEF(name, msg) msg,
|
||||
#include "lj_traceerr.h"
|
||||
NULL
|
||||
};
|
||||
#endif
|
||||
|
||||
#if LJ_HASJIT
|
||||
static const char *lower(char *buf, const char *s)
|
||||
{
|
||||
char *p = buf;
|
||||
while (*s) {
|
||||
*p++ = (*s >= 'A' && *s <= 'Z') ? *s+0x20 : *s;
|
||||
s++;
|
||||
}
|
||||
*p = '\0';
|
||||
return buf;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Emit C source code for bytecode-related definitions. */
|
||||
static void emit_bcdef(BuildCtx *ctx)
|
||||
{
|
||||
int i;
|
||||
fprintf(ctx->fp, "/* This is a generated file. DO NOT EDIT! */\n\n");
|
||||
fprintf(ctx->fp, "LJ_DATADEF const uint16_t lj_bc_ofs[] = {\n");
|
||||
for (i = 0; i < ctx->npc; i++) {
|
||||
if (i != 0)
|
||||
fprintf(ctx->fp, ",\n");
|
||||
fprintf(ctx->fp, "%d", ctx->bc_ofs[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/* Emit VM definitions as Lua code for debug modules. */
|
||||
static void emit_vmdef(BuildCtx *ctx)
|
||||
{
|
||||
#if LJ_HASJIT
|
||||
char buf[80];
|
||||
#endif
|
||||
int i;
|
||||
fprintf(ctx->fp, "-- This is a generated file. DO NOT EDIT!\n\n");
|
||||
fprintf(ctx->fp, "assert(require(\"jit\").version == \"%s\", \"LuaJIT core/library version mismatch\")\n\n", LUAJIT_VERSION);
|
||||
fprintf(ctx->fp, "return {\n\n");
|
||||
|
||||
fprintf(ctx->fp, "bcnames = \"");
|
||||
for (i = 0; bc_names[i]; i++) fprintf(ctx->fp, "%-6s", bc_names[i]);
|
||||
fprintf(ctx->fp, "\",\n\n");
|
||||
|
||||
#if LJ_HASJIT
|
||||
fprintf(ctx->fp, "irnames = \"");
|
||||
for (i = 0; ir_names[i]; i++) fprintf(ctx->fp, "%-6s", ir_names[i]);
|
||||
fprintf(ctx->fp, "\",\n\n");
|
||||
|
||||
fprintf(ctx->fp, "irfpm = { [0]=");
|
||||
for (i = 0; irfpm_names[i]; i++)
|
||||
fprintf(ctx->fp, "\"%s\", ", lower(buf, irfpm_names[i]));
|
||||
fprintf(ctx->fp, "},\n\n");
|
||||
|
||||
fprintf(ctx->fp, "irfield = { [0]=");
|
||||
for (i = 0; irfield_names[i]; i++) {
|
||||
char *p;
|
||||
lower(buf, irfield_names[i]);
|
||||
p = strchr(buf, '_');
|
||||
if (p) *p = '.';
|
||||
fprintf(ctx->fp, "\"%s\", ", buf);
|
||||
}
|
||||
fprintf(ctx->fp, "},\n\n");
|
||||
|
||||
fprintf(ctx->fp, "ircall = {\n[0]=");
|
||||
for (i = 0; ircall_names[i]; i++)
|
||||
fprintf(ctx->fp, "\"%s\",\n", ircall_names[i]);
|
||||
fprintf(ctx->fp, "},\n\n");
|
||||
|
||||
fprintf(ctx->fp, "traceerr = {\n[0]=");
|
||||
for (i = 0; trace_errors[i]; i++)
|
||||
fprintf(ctx->fp, "\"%s\",\n", trace_errors[i]);
|
||||
fprintf(ctx->fp, "},\n\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
/* -- Argument parsing ---------------------------------------------------- */
|
||||
|
||||
/* Build mode names. */
|
||||
static const char *const modenames[] = {
|
||||
#define BUILDNAME(name) #name,
|
||||
BUILDDEF(BUILDNAME)
|
||||
#undef BUILDNAME
|
||||
NULL
|
||||
};
|
||||
|
||||
/* Print usage information and exit. */
|
||||
static void usage(void)
|
||||
{
|
||||
int i;
|
||||
fprintf(stderr, LUAJIT_VERSION " VM builder.\n");
|
||||
fprintf(stderr, LUAJIT_COPYRIGHT ", " LUAJIT_URL "\n");
|
||||
fprintf(stderr, "Target architecture: " LJ_ARCH_NAME "\n\n");
|
||||
fprintf(stderr, "Usage: buildvm -m mode [-o outfile] [infiles...]\n\n");
|
||||
fprintf(stderr, "Available modes:\n");
|
||||
for (i = 0; i < BUILD__MAX; i++)
|
||||
fprintf(stderr, " %s\n", modenames[i]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Parse the output mode name. */
|
||||
static BuildMode parsemode(const char *mode)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; modenames[i]; i++)
|
||||
if (!strcmp(mode, modenames[i]))
|
||||
return (BuildMode)i;
|
||||
usage();
|
||||
return (BuildMode)-1;
|
||||
}
|
||||
|
||||
/* Parse arguments. */
|
||||
static void parseargs(BuildCtx *ctx, char **argv)
|
||||
{
|
||||
const char *a;
|
||||
int i;
|
||||
ctx->mode = (BuildMode)-1;
|
||||
ctx->outname = "-";
|
||||
for (i = 1; (a = argv[i]) != NULL; i++) {
|
||||
if (a[0] != '-')
|
||||
break;
|
||||
switch (a[1]) {
|
||||
case '-':
|
||||
if (a[2]) goto err;
|
||||
i++;
|
||||
goto ok;
|
||||
case '\0':
|
||||
goto ok;
|
||||
case 'm':
|
||||
i++;
|
||||
if (a[2] || argv[i] == NULL) goto err;
|
||||
ctx->mode = parsemode(argv[i]);
|
||||
break;
|
||||
case 'o':
|
||||
i++;
|
||||
if (a[2] || argv[i] == NULL) goto err;
|
||||
ctx->outname = argv[i];
|
||||
break;
|
||||
default: err:
|
||||
usage();
|
||||
break;
|
||||
}
|
||||
}
|
||||
ok:
|
||||
ctx->args = argv+i;
|
||||
if (ctx->mode == (BuildMode)-1) goto err;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
BuildCtx ctx_;
|
||||
BuildCtx *ctx = &ctx_;
|
||||
int status, binmode;
|
||||
|
||||
if (sizeof(void *) != 4*LJ_32+8*LJ_64) {
|
||||
fprintf(stderr,"Error: pointer size mismatch in cross-build.\n");
|
||||
fprintf(stderr,"Try: make HOST_CC=\"gcc -m32\" CROSS=...\n\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
UNUSED(argc);
|
||||
parseargs(ctx, argv);
|
||||
|
||||
if ((status = build_code(ctx))) {
|
||||
fprintf(stderr,"Error: DASM error %08x\n", status);
|
||||
return 1;
|
||||
}
|
||||
|
||||
switch (ctx->mode) {
|
||||
case BUILD_peobj:
|
||||
case BUILD_raw:
|
||||
binmode = 1;
|
||||
break;
|
||||
default:
|
||||
binmode = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (ctx->outname[0] == '-' && ctx->outname[1] == '\0') {
|
||||
ctx->fp = stdout;
|
||||
#if defined(_WIN32)
|
||||
if (binmode)
|
||||
_setmode(_fileno(stdout), _O_BINARY); /* Yuck. */
|
||||
#endif
|
||||
} else if (!(ctx->fp = fopen(ctx->outname, binmode ? "wb" : "w"))) {
|
||||
fprintf(stderr, "Error: cannot open output file '%s': %s\n",
|
||||
ctx->outname, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
switch (ctx->mode) {
|
||||
case BUILD_elfasm:
|
||||
case BUILD_coffasm:
|
||||
case BUILD_machasm:
|
||||
emit_asm(ctx);
|
||||
emit_asm_debug(ctx);
|
||||
break;
|
||||
case BUILD_peobj:
|
||||
emit_peobj(ctx);
|
||||
break;
|
||||
case BUILD_raw:
|
||||
emit_raw(ctx);
|
||||
break;
|
||||
case BUILD_bcdef:
|
||||
emit_bcdef(ctx);
|
||||
emit_lib(ctx);
|
||||
break;
|
||||
case BUILD_vmdef:
|
||||
emit_vmdef(ctx);
|
||||
emit_lib(ctx);
|
||||
fprintf(ctx->fp, "}\n\n");
|
||||
break;
|
||||
case BUILD_ffdef:
|
||||
case BUILD_libdef:
|
||||
case BUILD_recdef:
|
||||
emit_lib(ctx);
|
||||
break;
|
||||
case BUILD_folddef:
|
||||
emit_fold(ctx);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
fflush(ctx->fp);
|
||||
if (ferror(ctx->fp)) {
|
||||
fprintf(stderr, "Error: cannot write to output file: %s\n",
|
||||
strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
fclose(ctx->fp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Loaded 100 of 465 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user