diff --git a/fonts/MTLc3m.ttf b/fonts/MTLc3m.ttf new file mode 100644 index 0000000..86bdcc7 Binary files /dev/null and b/fonts/MTLc3m.ttf differ diff --git a/fonts/MTLc3m.ttf.license b/fonts/MTLc3m.ttf.license new file mode 100644 index 0000000..c5b1efa --- /dev/null +++ b/fonts/MTLc3m.ttf.license @@ -0,0 +1,190 @@ + + Copyright (c) 2005-2008, The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + diff --git a/fonts/mincho.otf b/fonts/mincho.otf new file mode 100644 index 0000000..d17b2ca Binary files /dev/null and b/fonts/mincho.otf differ diff --git a/fonts/mincho.otf.license b/fonts/mincho.otf.license new file mode 100644 index 0000000..d952d62 --- /dev/null +++ b/fonts/mincho.otf.license @@ -0,0 +1,92 @@ +This Font Software is licensed under the SIL Open Font License, +Version 1.1. + +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font +creation efforts of academic and linguistic communities, and to +provide a free and open framework in which fonts may be shared and +improved in partnership with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply to +any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software +components as distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, +deleting, or substituting -- in part or in whole -- any of the +components of the Original Version, by changing formats or by porting +the Font Software to a new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, +modify, redistribute, and sell modified and unmodified copies of the +Font Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, in +Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the +corresponding Copyright Holder. This restriction only applies to the +primary font name as presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created using +the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/hll/MsgSkip.c b/hll/MsgSkip.c index 8de4800..17f2dac 100644 --- a/hll/MsgSkip.c +++ b/hll/MsgSkip.c @@ -42,7 +42,7 @@ hll_defun(GetEnable, args) } //int GetState(void) -hll_warn_unimplemented(MsgSkip, GetState, 0); +hll_ignore_unimplemented(GetState, 0); //int GetFlag(int nMsgNum) hll_warn_unimplemented(MsgSkip, GetFlag, 0); //int GetNumofMsg(void) diff --git a/hll/SACT2.c b/hll/SACT2.c index 404d502..8e484a9 100644 --- a/hll/SACT2.c +++ b/hll/SACT2.c @@ -84,7 +84,7 @@ hll_defun_inline(SP_Delete, sact_SP_Delete(a[0].i)); hll_defun(SP_SetPos, args) { struct sact_sprite *sp = sact_get_sprite(args[0].i); - if (!sp || !sp->cg) hll_return(1); + if (!sp) hll_return(1); sp->rect.x = args[1].i; sp->rect.y = args[2].i; hll_return(1); @@ -94,7 +94,7 @@ hll_defun(SP_SetPos, args) hll_defun(SP_SetX, args) { struct sact_sprite *sp = sact_get_sprite(args[0].i); - if (!sp || !sp->cg) hll_return(0); + if (!sp) hll_return(0); sp->rect.x = args[1].i; hll_return(1); } @@ -103,22 +103,19 @@ hll_defun(SP_SetX, args) hll_defun(SP_SetY, args) { struct sact_sprite *sp = sact_get_sprite(args[0].i); - if (!sp || !sp->cg) hll_return(0); + if (!sp) hll_return(0); sp->rect.y = args[1].i; hll_return(1); } // int SP_SetZ(int nSP, int nZ) -hll_defun(SP_SetZ, args) -{ - hll_return(sact_SP_SetZ(args[0].i, args[1].i)); -} +hll_defun_inline(SP_SetZ, sact_SP_SetZ(a[0].i, a[1].i)); // int SP_SetBlendRate(int nSP, int nBlendRate) hll_defun(SP_SetBlendRate, args) { struct sact_sprite *sp = sact_get_sprite(args[0].i); - if (!sp || !sp->cg) hll_return(0); + if (!sp) hll_return(0); sp->color.a = args[1].i; hll_return(1); } @@ -127,15 +124,17 @@ hll_defun(SP_SetBlendRate, args) hll_defun(SP_SetShow, args) { struct sact_sprite *sp = sact_get_sprite(args[0].i); - if (!sp || !sp->cg) hll_return(0); + if (!sp) hll_return(0); sp->show = !!args[1].i; hll_return(1); } // int SP_SetDrawMethod(int nSP, int nMethod) hll_unimplemented(SACT2, SP_SetDrawMethod); + // int SP_IsUsing(int nSP) -hll_unimplemented(SACT2, SP_IsUsing); +hll_defun_inline(SP_IsUsing, sact_get_sprite(a[0].i) != NULL); + // int SP_ExistAlpha(int nSP) hll_unimplemented(SACT2, SP_ExistAlpha); @@ -143,7 +142,7 @@ hll_unimplemented(SACT2, SP_ExistAlpha); hll_defun(SP_GetPosX, args) { struct sact_sprite *sp = sact_get_sprite(args[0].i); - if (!sp || !sp->cg) hll_return(0); + if (!sp) hll_return(0); hll_return(sp->rect.x); } @@ -151,7 +150,7 @@ hll_defun(SP_GetPosX, args) hll_defun(SP_GetPosY, args) { struct sact_sprite *sp = sact_get_sprite(args[0].i); - if (!sp || !sp->cg) hll_return(0); + if (!sp) hll_return(0); hll_return(sp->rect.y); } @@ -159,7 +158,7 @@ hll_defun(SP_GetPosY, args) hll_defun(SP_GetWidth, args) { struct sact_sprite *sp = sact_get_sprite(args[0].i); - if (!sp || !sp->cg) hll_return(0); + if (!sp) hll_return(0); hll_return(sp->rect.w); } @@ -167,7 +166,7 @@ hll_defun(SP_GetWidth, args) hll_defun(SP_GetHeight, args) { struct sact_sprite *sp = sact_get_sprite(args[0].i); - if (!sp || !sp->cg) hll_return(0); + if (!sp) hll_return(0); hll_return(sp->rect.h); } @@ -175,7 +174,7 @@ hll_defun(SP_GetHeight, args) hll_defun(SP_GetZ, args) { struct sact_sprite *sp = sact_get_sprite(args[0].i); - if (!sp || !sp->cg) hll_return(0); + if (!sp) hll_return(0); hll_return(sp->z); } @@ -183,7 +182,7 @@ hll_defun(SP_GetZ, args) hll_defun(SP_GetBlendRate, args) { struct sact_sprite *sp = sact_get_sprite(args[0].i); - if (!sp || !sp->cg) hll_return(0); + if (!sp) hll_return(0); hll_return((int)sp->color.a); } @@ -191,44 +190,95 @@ hll_defun(SP_GetBlendRate, args) hll_defun(SP_GetShow, args) { struct sact_sprite *sp = sact_get_sprite(args[0].i); - if (!sp || !sp->cg) hll_return(0); + if (!sp) hll_return(0); hll_return(sp->show); } // int SP_GetDrawMethod(int nSP) hll_warn_unimplemented(SACT2, SP_GetDrawMethod, 0); + // int SP_SetTextHome(int nSP, int nX, int nY) -hll_warn_unimplemented(SACT2, SP_SetTextHome, 0); +hll_defun(SP_SetTextHome, args) +{ + struct sact_sprite *sp = sact_get_sprite(args[0].i); + if (!sp) hll_return(0); + sp->text.home = (Point) { .x = args[1].i, .y = args[2].i }; + hll_return(1); +} + // int SP_SetTextLineSpace(int nSP, int nPx) hll_unimplemented(SACT2, SP_SetTextLineSpace); // int SP_SetTextCharSpace(int nSP, int nPx) hll_unimplemented(SACT2, SP_SetTextCharSpace); + // int SP_SetTextPos(int nSP, int nX, int nY) -hll_warn_unimplemented(SACT2, SP_SetTextPos, 0); +hll_defun(SP_SetTextPos, args) +{ + struct sact_sprite *sp = sact_get_sprite(args[0].i); + if (!sp) hll_return(0); + sp->text.pos = (Point) { .x = args[1].i, .y = args[2].i }; + hll_return(1); +} + // int SP_TextDraw(int nSP, string text, struct tm) -hll_warn_unimplemented(SACT2, SP_TextDraw, 1); +hll_defun_inline(SP_TextDraw, sact_SP_TextDraw(a[0].i, heap[a[1].i].s, heap[a[2].i].page->values)); // int SP_TextClear(int nSP) -hll_warn_unimplemented(SACT2, SP_TextClear, 1); +hll_defun_inline(SP_TextClear, sact_SP_TextClear(a[0].i)); + // int SP_TextHome(int nSP, int nTextSize) -hll_warn_unimplemented(SACT2, SP_TextHome, 1); +hll_defun(SP_TextHome, args) +{ + struct sact_sprite *sp = sact_get_sprite(args[0].i); + if (!sp) hll_return(0); + // FIXME: do something with nTextSize + sp->text.pos = sp->text.home; + hll_return(1); +} + // int SP_TextNewLine(int nSP, int nTextSize) hll_unimplemented(SACT2, SP_TextNewLine); // int SP_TextBackSpace(int nSP) hll_unimplemented(SACT2, SP_TextBackSpace); // int SP_TextCopy(int nDstSP, int nSrcSP) hll_unimplemented(SACT2, SP_TextCopy); + // int SP_GetTextHomeX(int nSP) -hll_unimplemented(SACT2, SP_GetTextHomeX); +hll_defun(SP_GetTextHomeX, args) +{ + struct sact_sprite *sp = sact_get_sprite(args[0].i); + if (!sp) hll_return(0); + hll_return(sp->text.home.x); +} + // int SP_GetTextHomeY(int nSP) -hll_unimplemented(SACT2, SP_GetTextHomeY); +hll_defun(SP_GetTextHomeY, args) +{ + struct sact_sprite *sp = sact_get_sprite(args[0].i); + if (!sp) hll_return(0); + hll_return(sp->text.home.y); +} + // int SP_GetTextCharSpace(int nSP) hll_unimplemented(SACT2, SP_GetTextCharSpace); + // int SP_GetTextPosX(int nSP) -hll_warn_unimplemented(SACT2, SP_GetTextPosX, 0); +hll_defun(SP_GetTextPosX, args) +{ + struct sact_sprite *sp = sact_get_sprite(args[0].i); + if (!sp) hll_return(0); + hll_return(sp->text.pos.x); +} + // int SP_GetTextPosY(int nSP) -hll_warn_unimplemented(SACT2, SP_GetTextPosY, 0); +hll_defun(SP_GetTextPosY, args) +{ + struct sact_sprite *sp = sact_get_sprite(args[0].i); + if (!sp) hll_return(0); + hll_return(sp->text.pos.y); +} + // int SP_GetTextLineSpace(int nSP) -hll_warn_unimplemented(SACT2, SP_GetTextLineSpace, 0); +hll_defun_inline(SP_GetTextLineSpace, 0); // int SP_IsPtIn(int nSP, int nX, int nY) hll_unimplemented(SACT2, SP_IsPtIn); @@ -237,12 +287,12 @@ hll_defun(SP_IsPtInRect, args) { struct sact_sprite *sp = sact_get_sprite(args[0].i); Point p = { .x = args[1].i, .y = args[2].i }; - if (!sp || !sp->cg) hll_return(0); + if (!sp) hll_return(0); hll_return(!!SDL_PointInRect(&p, &sp->rect)); } // int GAME_MSG_GetNumof(void) -hll_unimplemented(SACT2, GAME_MSG_GetNumof); +hll_defun_inline(GAME_MSG_GetNumof, ain->nr_messages); // void GAME_MSG_Get(int nIndex, ref string text) hll_unimplemented(SACT2, GAME_MSG_Get); // void IntToZenkaku(ref string s, int nValue, int nFigures, int nfZeroPadding) @@ -262,7 +312,7 @@ hll_defun(Mouse_GetPos, args) // int Mouse_SetPos(int nX, int nY) hll_warn_unimplemented(SACT2, Mouse_SetPos, 1); // void Mouse_ClearWheel(void) -hll_warn_unimplemented(SACT2, Mouse_ClearWheel, 0); +hll_defun_inline(Mouse_ClearWheel, 0); // void Mouse_GetWheel(ref int pnForward, ref int pnBack) hll_defun(Mouse_GetWheel, args) @@ -309,7 +359,7 @@ hll_defun_inline(Key_IsDown, key_is_down(a[0].i)); // int Timer_Get(void) hll_defun_inline(Timer_Get, vm_time()); // int CG_IsExist(int nCG) -hll_defun_inline(CG_IsExist, cg_exists(a[0].i)); +hll_defun_inline(CG_IsExist, cg_exists(a[0].i - 1)); // int CG_GetMetrics(int nCG, ref struct cm) hll_unimplemented(SACT2, CG_GetMetrics); // int CSV_Load(string pIStringFileName) diff --git a/hll/hll.h b/hll/hll.h index adcfca2..0861040 100644 --- a/hll/hll.h +++ b/hll/hll.h @@ -50,6 +50,8 @@ hll_return(rval); \ } +#define hll_ignore_unimplemented(fname, rval) hll_defun_inline(fname, rval) + #define hll_export(fname) &_hllstruct_ ## fname #define hll_deflib(lname, ...) \ diff --git a/meson.build b/meson.build index ca5825c..b4f4cfa 100644 --- a/meson.build +++ b/meson.build @@ -14,6 +14,7 @@ xsystem4 = ['ald.c', 'page.c', 'sact_graphics.c', 'sdl_draw.c', + 'sdl_text.c', 'sdl_video.c', 'system4.c', 'vm.c', @@ -28,6 +29,7 @@ hll_libs = ['hll/DrawPluginManager.c', zdep = dependency('zlib') mdep = meson.get_compiler('c').find_library('m', required: false) sdl2 = dependency('sdl2') +sdl2ttf = dependency('SDL2_ttf') -executable('system4', xsystem4 + system4 + hll_libs, dependencies: [mdep, zdep, sdl2]) +executable('system4', xsystem4 + system4 + hll_libs, dependencies: [mdep, zdep, sdl2, sdl2ttf]) executable('aindump', ['aindump.c'] + system4, dependencies: [mdep, zdep]) diff --git a/sact.h b/sact.h index 7923486..70c22cc 100644 --- a/sact.h +++ b/sact.h @@ -23,14 +23,23 @@ #include "graphics.h" struct cg; +struct string; +union vm_value; struct sact_sprite { TAILQ_ENTRY(sact_sprite) entry; struct cg *cg; SDL_Color color; Rectangle rect; + struct { + struct string *str; + SDL_Surface *surf; + Point home; + Point pos; + } text; int z; bool show; + int no; }; struct sact_sprite *sact_get_sprite(int sp); @@ -43,5 +52,7 @@ int sact_SP_SetCG(int sp, int cg); int sact_SP_Create(int sp, int width, int height, int r, int g, int b, int a); int sact_SP_Delete(int sp); int sact_SP_SetZ(int sp, int z); +int sact_SP_TextDraw(int sp_no, struct string *text, union vm_value *tm); +int sact_SP_TextClear(int sp_no); #endif /* SYSTEM4_SACT_H */ diff --git a/sact_graphics.c b/sact_graphics.c index 0483aca..5cb73de 100644 --- a/sact_graphics.c +++ b/sact_graphics.c @@ -19,6 +19,9 @@ #include "cg.h" #include "input.h" #include "sdl_core.h" +#include "vm.h" +#include "vm_string.h" +#include "utfsjis.h" static struct sact_sprite **sprites = NULL; static int nr_sprites = 0; @@ -36,6 +39,7 @@ struct sact_sprite *sact_get_sprite(int sp) static struct sact_sprite *alloc_sprite(int sp) { sprites[sp] = xcalloc(1, sizeof(struct sact_sprite)); + sprites[sp]->no = sp; return sprites[sp]; } @@ -59,6 +63,7 @@ static void sprite_unregister(struct sact_sprite *sp) int sact_Init(void) { sdl_initialize(); + sdl_text_init(); return 1; } @@ -71,7 +76,9 @@ int sact_Update(void) continue; if (!p->cg->s) p->cg->s = sdl_make_rectangle(p->rect.w, p->rect.h, &p->color); - sdl_draw_cg(p->cg, &p->rect); + sdl_draw_surface(p->cg->s, &p->rect); + if (p->text.surf) + sdl_draw_surface(p->text.surf, &p->rect); } sdl_update_screen(); return 1; @@ -84,11 +91,11 @@ int sact_SP_GetUnuseNum(int min) return i; } + int old_nr_sprites = nr_sprites; int n = max(min, nr_sprites); nr_sprites = n + 256; sprites = xrealloc(sprites, sizeof(struct sact_sprite*) * nr_sprites); - for (int i = n; i < nr_sprites; i++) - sprites[i] = NULL; + memset(sprites + old_nr_sprites, 0, sizeof(struct sact_sprite*) * (nr_sprites - old_nr_sprites)); return n; } @@ -102,7 +109,13 @@ int sact_SP_GetMaxZ(void) int sact_SP_SetCG(int sp_no, int cg_no) { struct sact_sprite *sp = sact_get_sprite(sp_no); - if (!sp || !cg_load(sp->cg, cg_no - 1)) + if (!sp) + sact_SP_Create(sp_no, 1, 1, 0, 0, 0, 0); + if (!(sp = sact_get_sprite(sp_no))) { + WARNING("Failed to create sprite"); + return 0; + } + if (!cg_load(sp->cg, cg_no - 1)) return 0; sp->rect.w = sp->cg->s->w; sp->rect.h = sp->cg->s->h; @@ -136,14 +149,15 @@ int sact_SP_Delete(int sp_no) if (!sp) return 0; sprite_unregister(sp); cg_free(sp->cg); - sp->cg = NULL; + free(sp); + sprites[sp_no] = NULL; return 1; } int sact_SP_SetZ(int sp_no, int z) { struct sact_sprite *sp = sact_get_sprite(sp_no); - if (!sp || !sp->cg) return 0; + if (!sp) return 0; sprite_unregister(sp); sp->z = z; sprite_register(sp); @@ -151,3 +165,69 @@ int sact_SP_SetZ(int sp_no, int z) } +#define tm_ColorR(tm) (tm[0].i) +#define tm_ColorG(tm) (tm[1].i) +#define tm_ColorB(tm) (tm[2].i) +#define tm_Size(tm) (tm[3].i) +#define tm_Weight(tm) (tm[4].i) +#define tm_Face(tm) (tm[5].i) +#define tm_ShadowPixelL(tm) (tm[6].i) +#define tm_ShadowPixelU(tm) (tm[7].i) +#define tm_ShadowPixelR(tm) (tm[8].i) +#define tm_ShadowPixelD(tm) (tm[9].i) +#define tm_ShadowColorR(tm) (tm[10].i) +#define tm_ShadowColorG(tm) (tm[11].i) +#define tm_ShadowColorB(tm) (tm[12].i) + +static void init_text_metrics(struct text_metrics *tm, union vm_value *_tm) +{ + *tm = (struct text_metrics) { + .color = { + .r = tm_ColorR(_tm), + .g = tm_ColorG(_tm), + .b = tm_ColorB(_tm), + .a = 255 + }, + .outline_color = { + .r = tm_ShadowColorR(_tm), + .g = tm_ShadowColorG(_tm), + .b = tm_ShadowColorB(_tm), + .a = 255 + }, + .size = tm_Size(_tm), + .weight = tm_Weight(_tm), + .face = tm_Face(_tm), + .outline_left = tm_ShadowPixelL(_tm), + .outline_up = tm_ShadowPixelU(_tm), + .outline_right = tm_ShadowPixelR(_tm), + .outline_down = tm_ShadowPixelD(_tm), + }; +} + +int sact_SP_TextDraw(int sp_no, struct string *text, union vm_value *_tm) +{ + struct text_metrics tm; + struct sact_sprite *sp = sact_get_sprite(sp_no); + if (!sp) return 0; + + if (!sp->text.surf) { + SDL_Color c = { 0, 0, 0, 0 }; + sp->text.surf = sdl_make_rectangle(sp->rect.w, sp->rect.h, &c); + } + + init_text_metrics(&tm, _tm); + sp->text.pos.x += sdl_render_text(sp->text.surf, sp->text.pos, text->text, &tm); + return 1; +} + +int sact_SP_TextClear(int sp_no) +{ + struct sact_sprite *sp = sact_get_sprite(sp_no); + if (!sp) return 0; + + if (sp->text.surf) { + SDL_FreeSurface(sp->text.surf); + sp->text.surf = NULL; + } + return 1; +} diff --git a/sdl_core.h b/sdl_core.h index a407eb9..f8e6075 100644 --- a/sdl_core.h +++ b/sdl_core.h @@ -20,6 +20,7 @@ #include #include +#include #include "graphics.h" struct cg; @@ -31,7 +32,33 @@ void sdl_set_window_size(int x, int y, int w, int h); void sdl_fullscreen(bool on); void sdl_update_screen(void); -void sdl_draw_cg(struct cg *cg, Rectangle *dst); +void sdl_draw_surface(SDL_Surface *s, Rectangle *dst); SDL_Surface *sdl_make_rectangle(int w, int h, SDL_Color *color); +enum font_weight { + FW_NORMAL = 400, + FW_BOLD = 700 +}; + +enum font_face { + FONT_GOTHIC = 0, + FONT_MINCHO = 1 +}; + +struct text_metrics { + SDL_Color color; + SDL_Color outline_color; + unsigned int size; + enum font_weight weight; + enum font_face face; + int outline_left; + int outline_up; + int outline_right; + int outline_down; +}; + +void sdl_text_init(void); +bool sdl_set_font(int face, unsigned int size); +int sdl_render_text(SDL_Surface *dst, Point pos, char *msg, struct text_metrics *tm); + #endif /* SYSTEM4_SDL_CORE_H */ diff --git a/sdl_draw.c b/sdl_draw.c index 58989bb..40a10c1 100644 --- a/sdl_draw.c +++ b/sdl_draw.c @@ -69,9 +69,9 @@ void sdl_draw_rectangle(Rectangle *_rect, int pixels, uint8_t r, uint8_t g, uint sdl.dirty = true; } -void sdl_draw_cg(struct cg *cg, Rectangle *dst) +void sdl_draw_surface(SDL_Surface *s, Rectangle *dst) { - Rectangle src = { .x = 0, .y = 0, .w = cg->s->w, .h = cg->s->h }; - SDL_BlitSurface(cg->s, &src, sdl.display, dst); + Rectangle src = { .x = 0, .y = 0, .w = s->w, .h = s->h }; + SDL_BlitSurface(s, &src, sdl.display, dst); sdl.dirty = true; } diff --git a/sdl_text.c b/sdl_text.c new file mode 100644 index 0000000..dc7f87e --- /dev/null +++ b/sdl_text.c @@ -0,0 +1,142 @@ +/* Copyright (C) 2019 Nunuhara Cabbage + * + * 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, see . + */ + +#include +#include +#include "system4.h" +#include "sdl_core.h" +#include "graphics.h" +#include "utfsjis.h" + +#define MAX_FONT_SIZE 128 + +// TODO: install fonts on system, and provide run-time configuration option +const char *font_paths[] = { + [FONT_GOTHIC] = "fonts/mincho.otf", + [FONT_MINCHO] = "fonts/MTLc3m.ttf" +}; + +struct font { + unsigned int size; + enum font_face face; + enum font_weight weight; + TTF_Font *font; +}; + +struct _font { + unsigned int allocated; + struct font *fonts; +}; + +static struct _font font_table[2]; + +static struct font *font; + +bool sdl_set_font(int face, unsigned int size) +{ + struct _font *ff = &font_table[face]; + + if (size > MAX_FONT_SIZE) { + WARNING("Font size too large: %d", size); + return false; + } + + // realloc if needed + if ((size+1) > ff->allocated) { + ff->fonts = xrealloc(ff->fonts, sizeof(struct font) * (size+1)); + memset(ff->fonts + ff->allocated, 0, sizeof(struct font) * ((size+1) - ff->allocated)); + ff->allocated = size+1; + } + + // open font if needed + if (!ff->fonts[size].size) { + if (!(ff->fonts[size].font = TTF_OpenFont(font_paths[face], size))) { + WARNING("Error opening font: %s:%d", font_paths[face], size); + return false; + } + ff->fonts[size].size = size; + ff->fonts[size].face = face; + ff->fonts[size].weight = FW_NORMAL; + } + + // set current font + font = &ff->fonts[size]; + return true; +} + +static void _sdl_render_text(TTF_Font *f, SDL_Surface *dst, Point pos, char *msg, SDL_Color color) +{ + SDL_Surface *s = TTF_RenderUTF8_Blended(f, msg, color); + Rectangle dst_pos = { .x = pos.x, .y = pos.y, .w = s->w, .h = s->h }; + SDL_BlitSurface(s, NULL, dst, &dst_pos); + SDL_FreeSurface(s); +} + +static int sact_to_sdl_fontstyle(int style) +{ + switch (style) { + case FW_NORMAL: return 0; + case FW_BOLD: return TTF_STYLE_BOLD; + default: return 0; + } +} + +int sdl_render_text(SDL_Surface *dst, Point pos, char *msg, struct text_metrics *tm) +{ + if (!font) + return 0; + if (font->size != tm->size || font->face != tm->face) + sdl_set_font(tm->face, tm->size); + if (font->weight != tm->weight) { + TTF_SetFontStyle(font->font, sact_to_sdl_fontstyle(tm->weight)); + font->weight = tm->weight; + } + + int width; + char *conv = sjis2utf(msg, strlen(msg)); + TTF_SizeUTF8(font->font, conv, &width, NULL); + + pos.y -= (TTF_FontAscent(font->font) - font->size * 0.9); + + // XXX: This wont work if the outline size is larger than the stroke size + // of the font itself. + if (tm->outline_left) { + Point p = { pos.x - tm->outline_left, pos.y }; + _sdl_render_text(font->font, dst, p, conv, tm->outline_color); + } + if (tm->outline_up) { + Point p = { pos.x, pos.y - tm->outline_up }; + _sdl_render_text(font->font, dst, p, conv, tm->outline_color); + } + if (tm->outline_right) { + Point p = { pos.x + tm->outline_right, pos.y }; + _sdl_render_text(font->font, dst, p, conv, tm->outline_color); + } + if (tm->outline_down) { + Point p = { pos.x, pos.y + tm->outline_down }; + _sdl_render_text(font->font, dst, p, conv, tm->outline_color); + } + _sdl_render_text(font->font, dst, pos, conv, tm->color); + free(conv); + return width; +} + +void sdl_text_init(void) +{ + if (TTF_Init() == -1) + ERROR("Failed to initialize SDL_ttf: %s", TTF_GetError()); + sdl_set_font(FONT_MINCHO, 16); +}