Take libakgl 0.5.0 and rename every symbol it namespaced
0.5.0 gives every exported symbol the akgl_ prefix, which is the first libakgl release to break this project's source rather than only its ABI. The soname goes to libakgl.so.0.5 and include/akbasic/akgl.h asserts the floor. What moved here: akgl_render_bind2d is akgl_render_2d_bind, akgl_sprite_sheet_coords_for_frame is akgl_spritesheet_coords_for_frame, the renderer, camera and window globals carry the prefix, and _akgl_renderer and _akgl_camera are akgl_default_renderer and akgl_default_camera. The renames were applied by site rather than by pattern, because renderer is also a parameter name in src/sprite_akgl.c and a struct member throughout src/frontend_akgl.c -- a substitution would have rewritten both without a word. That is the same trap upstream describes hitting, and it is worth knowing that the defect behind the rename was not cosmetic: an exported global called renderer collided with a test's own variable, the executable's definition preempted the library's, and every texture load in that suite failed while the suite passed. 0.5.0 also fixes libakgl defect 26, which was one of the two reasons src/sprite_akgl.c installs its own renderfunc: akgl_actor_render took its destination height from the sprite's width, drawing a 24x21 Commodore sprite as a 24x24 square. The renderfunc stays, because the other reason has not moved -- an actor carries one scalar scale and SPRITE has separate x- and y-expand bits -- but the comments and TODO.md deviation 40 no longer claim a defect that is fixed. Every documentation figure re-renders byte-identical under the new library, which is what says the sprite and drawing paths did not move underneath them. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -166,7 +166,7 @@ a mixed build leaks pool slots or frees one twice rather than failing to link.
|
|||||||
|---|---|---|---|---|
|
|---|---|---|---|---|
|
||||||
| `deps/libakerror` | 2.0.1 | `libakerror.so.2` | major only | **none** — no version macro; `include/akbasic/error.h` feature-tests `AKERR_THREAD_SAFE` and `AKERR_EXIT_STATUS_UNREPRESENTABLE` instead |
|
| `deps/libakerror` | 2.0.1 | `libakerror.so.2` | major only | **none** — no version macro; `include/akbasic/error.h` feature-tests `AKERR_THREAD_SAFE` and `AKERR_EXIT_STATUS_UNREPRESENTABLE` instead |
|
||||||
| `deps/libakstdlib` | 0.2.0 | `libakstdlib.so.0.2` | **`MAJOR.MINOR` while major is 0** | `AKSL_VERSION_*`, `aksl_version()`, `AKSL_VERSION_CHECK()` |
|
| `deps/libakstdlib` | 0.2.0 | `libakstdlib.so.0.2` | **`MAJOR.MINOR` while major is 0** | `AKSL_VERSION_*`, `aksl_version()`, `AKSL_VERSION_CHECK()` |
|
||||||
| `deps/libakgl` | 0.4.0 | `libakgl.so.0.4` | **`MAJOR.MINOR` while major is 0** | `AKGL_VERSION*`, `akgl_version()`, `AKGL_VERSION_AT_LEAST()` |
|
| `deps/libakgl` | 0.5.0 | `libakgl.so.0.5` | **`MAJOR.MINOR` while major is 0** | `AKGL_VERSION*`, `akgl_version()`, `AKGL_VERSION_AT_LEAST()` |
|
||||||
|
|
||||||
For both 0.x libraries the soname carries `MAJOR.MINOR` deliberately: 0.1 and 0.2 are
|
For both 0.x libraries the soname carries `MAJOR.MINOR` deliberately: 0.1 and 0.2 are
|
||||||
*different* ABIs, and both become major-only at 1.0. Do not read `0.1 → 0.2` as a compatible
|
*different* ABIs, and both become major-only at 1.0. Do not read `0.1 → 0.2` as a compatible
|
||||||
|
|||||||
@@ -144,7 +144,7 @@ nothing to install first.
|
|||||||
* [libakstdlib](https://source.starfort.tech/andrew/libakstdlib) 0.2.0 — libc wrappers that
|
* [libakstdlib](https://source.starfort.tech/andrew/libakstdlib) 0.2.0 — libc wrappers that
|
||||||
report through `libakerror`. String-to-number conversion goes straight to it, which is why
|
report through `libakerror`. String-to-number conversion goes straight to it, which is why
|
||||||
`VAL("garbage")` is an error rather than a silent `0`.
|
`VAL("garbage")` is an error rather than a silent `0`.
|
||||||
* [libakgl](https://source.starfort.tech/andrew/libakgl) 0.4.0 — **optional**, only for
|
* [libakgl](https://source.starfort.tech/andrew/libakgl) 0.5.0 — **optional**, only for
|
||||||
`-DAKBASIC_WITH_AKGL=ON`. Pulls in SDL3. Its soname carries `MAJOR.MINOR` while the major is 0,
|
`-DAKBASIC_WITH_AKGL=ON`. Pulls in SDL3. Its soname carries `MAJOR.MINOR` while the major is 0,
|
||||||
so rebuild rather than relink.
|
so rebuild rather than relink.
|
||||||
* [basicinterpret](https://source.starfort.tech/andrew/basicinterpret) — the Go original.
|
* [basicinterpret](https://source.starfort.tech/andrew/basicinterpret) — the Go original.
|
||||||
|
|||||||
24
TODO.md
24
TODO.md
@@ -1291,11 +1291,23 @@ deviations from the reference's *program*: `main.go` and the SDL half of
|
|||||||
40. **A sprite is a real `libakgl` actor, and it is drawn by a renderfunc of ours.** Each of the
|
40. **A sprite is a real `libakgl` actor, and it is drawn by a renderfunc of ours.** Each of the
|
||||||
eight becomes a `SpriteSheet` + `Sprite` + `Character` + `Actor` registered in
|
eight becomes a `SpriteSheet` + `Sprite` + `Character` + `Actor` registered in
|
||||||
`AKGL_REGISTRY_ACTOR`, so an embedding game sees BASIC's sprites alongside its own (goal 3).
|
`AKGL_REGISTRY_ACTOR`, so an embedding game sees BASIC's sprites alongside its own (goal 3).
|
||||||
But `akgl_actor_render()` is not what draws them: it computes its destination *height* from
|
But `akgl_actor_render()` is not what draws them. There were two reasons and **libakgl
|
||||||
the sprite's **width**, which would draw a 24×21 Commodore sprite as a 24×24 square, and an
|
0.5.0 fixed one**: the default used to compute its destination *height* from the sprite's
|
||||||
actor carries a single scalar `scale` that cannot express `SPRITE`'s separate x- and
|
**width**, drawing a 24×21 Commodore sprite as a 24×24 square, and it now uses the height
|
||||||
y-expand bits. `src/sprite_akgl.c` installs its own `renderfunc`, which is libakgl's own
|
— libakgl defect 26, filed from here and closed there.
|
||||||
extension point for exactly this. Both defects are filed upstream.
|
|
||||||
|
**The reason that remains is the one that keeps this file.** An actor carries a single
|
||||||
|
scalar `scale` applied to both axes, which cannot express `SPRITE`'s separate x- and
|
||||||
|
y-expand bits, so `MOVSPR`'s twice-as-wide-same-height is unrepresentable. libakgl records
|
||||||
|
it as open and names this interpreter as the caller that needs it; the fix is a design
|
||||||
|
choice over there — `scale_x`/`scale_y` beside `scale`, or replacing `scale` and taking
|
||||||
|
the ABI break while the major is still 0 — rather than a patch. Until then
|
||||||
|
`src/sprite_akgl.c` installs its own `renderfunc`, which is libakgl's own extension point
|
||||||
|
for exactly this.
|
||||||
|
|
||||||
|
Worth keeping as a pattern: both defects were found by *using* the library for something
|
||||||
|
it had not been used for, and both were filed rather than worked around silently. One came
|
||||||
|
back fixed.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -1708,7 +1720,7 @@ Dependency baseline:
|
|||||||
|---|---|---|
|
|---|---|---|
|
||||||
| `deps/libakerror` | 2.0.1 | Private ownership-enforced status registry. akbasic reserves 512–767 in `akbasic_error_register()`. Does not namespace its `coverage` target when embedded — worked around in our `CMakeLists.txt`. **2.0.0 is thread safe and an ABI break** (`libakerror.so.2`): `__akerr_last_ignored` is thread-local and `akerr_next_error()` returns an owned reference, neither of which fails to link when mismatched. **2.0.1 fixes an exit status that mattered more to this band than to any other** — see below. |
|
| `deps/libakerror` | 2.0.1 | Private ownership-enforced status registry. akbasic reserves 512–767 in `akbasic_error_register()`. Does not namespace its `coverage` target when embedded — worked around in our `CMakeLists.txt`. **2.0.0 is thread safe and an ABI break** (`libakerror.so.2`): `__akerr_last_ignored` is thread-local and `akerr_next_error()` returns an owned reference, neither of which fails to link when mismatched. **2.0.1 fixes an exit status that mattered more to this band than to any other** — see below. |
|
||||||
| `deps/libakstdlib` | 0.2.0 | soname `libakstdlib.so.0.2`. `AKSL_VERSION_CHECK()` asserted in `tests/version_check.c`. This release fixed all six confirmed defects the port was working around — see §1.9, where the bans are now lifted. |
|
| `deps/libakstdlib` | 0.2.0 | soname `libakstdlib.so.0.2`. `AKSL_VERSION_CHECK()` asserted in `tests/version_check.c`. This release fixed all six confirmed defects the port was working around — see §1.9, where the bans are now lifted. |
|
||||||
| `deps/libakgl` | 0.4.0 | soname `libakgl.so.0.4`. Owns status codes 256–260. Linked and tested under `-DAKBASIC_WITH_AKGL=ON`, which still defaults OFF so the core library and its whole suite build on a machine with no SDL. **0.3.0 closed every API gap this port had filed** — see §7 — so the four workarounds §3 used to list are gone. 0.4.0 is a leak-and-overread release that changed no public struct, but the soname carries `MAJOR.MINOR` while the major is 0, so rebuild rather than relink. |
|
| `deps/libakgl` | 0.5.0 | soname `libakgl.so.0.5`. Owns status codes 256–260. Linked and tested under `-DAKBASIC_WITH_AKGL=ON`, which still defaults OFF so the core library and its whole suite build on a machine with no SDL. **0.3.0 closed every API gap this port had filed** — see §7 — so the four workarounds §3 used to list are gone. 0.4.0 was a leak-and-overread release that changed no public struct. **0.5.0 is the first that broke our source as well as our ABI**: it namespaced every exported symbol, so `akgl_render_bind2d` is `akgl_render_2d_bind`, `akgl_sprite_sheet_coords_for_frame` is `akgl_spritesheet_coords_for_frame`, the `renderer`/`camera`/`window` globals carry the prefix, and `_akgl_renderer`/`_akgl_camera` are `akgl_default_renderer`/`akgl_default_camera`. `include/akbasic/akgl.h` asserts the 0.5.0 floor. |
|
||||||
|
|
||||||
**An unhandled error in this band used to exit zero, and 512 is the worst possible base for
|
**An unhandled error in this band used to exit zero, and 512 is the worst possible base for
|
||||||
that.** `libakerror`'s default unhandled-error handler ended in `exit(errctx->status)`, and a
|
that.** `libakerror`'s default unhandled-error handler ended in `exit(errctx->status)`, and a
|
||||||
|
|||||||
2
deps/libakgl
vendored
2
deps/libakgl
vendored
Submodule deps/libakgl updated: 93e8e4afa4...b899f09fc8
@@ -36,26 +36,34 @@
|
|||||||
#include <akgl/version.h>
|
#include <akgl/version.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The API floor is 0.3.0: akgl_render_bind2d(), akgl_audio_sweep(), and
|
* **0.5.0 is a hard floor, API as well as ABI**, which is new: every release
|
||||||
* akgl_Keystroke with akgl_controller_poll_keystroke() all arrived there, and
|
* before it moved this line for ABI reasons alone. 0.5.0 namespaced every
|
||||||
* nothing in this target uses anything newer. The floor asserted below is
|
* exported symbol, so the spellings this target compiles against do not exist in
|
||||||
* 0.4.0 anyway, and the difference is ABI rather than API.
|
* 0.4.0 and the ones 0.4.0 had do not exist here. `akgl_render_bind2d` is
|
||||||
|
* `akgl_render_2d_bind`, `akgl_sprite_sheet_coords_for_frame` is
|
||||||
|
* `akgl_spritesheet_coords_for_frame`, and the `renderer`, `camera` and `window`
|
||||||
|
* globals carry the prefix -- with `_akgl_renderer` and `_akgl_camera` now
|
||||||
|
* `akgl_default_renderer` and `akgl_default_camera`.
|
||||||
*
|
*
|
||||||
* The soname carries MAJOR.MINOR while the major is 0, so 0.3 and 0.4 are
|
* That rename was not cosmetic and libakgl's TODO.md says why at length: an
|
||||||
* different ABIs *by declaration* -- libakgl's versioning policy says a 0.x
|
* exported global called `renderer` collided with a test's own variable of the
|
||||||
* minor bump may break, and the soname is built to match. 0.4.0 in fact changed
|
* same name, the executable's definition preempted the library's, and every
|
||||||
* no public struct: it is leak and overread fixes inside src/. The floor moves
|
* texture load in that suite failed while the suite reported success.
|
||||||
* anyway, because the alternative is deciding for ourselves which of libakgl's
|
|
||||||
* minor releases were really compatible, and that is exactly the judgement the
|
|
||||||
* soname exists to take away from us.
|
|
||||||
*
|
*
|
||||||
* What it catches is the case the soname cannot: a build against 0.3 headers
|
* The soname carries MAJOR.MINOR while the major is 0, so 0.4 and 0.5 are
|
||||||
* that happens to find a 0.4 library, or the reverse. Refused here rather than
|
* different ABIs *by declaration* -- libakgl's versioning policy says a 0.x minor
|
||||||
|
* bump may break, and the soname is built to match. The floor moves with every
|
||||||
|
* one of them, because the alternative is deciding for ourselves which of
|
||||||
|
* libakgl's minor releases were really compatible, and that is exactly the
|
||||||
|
* judgement the soname exists to take away from us.
|
||||||
|
*
|
||||||
|
* What it catches is the case the soname cannot: a build against 0.4 headers
|
||||||
|
* that happens to find a 0.5 library, or the reverse. Refused here rather than
|
||||||
* at link time, because a missing symbol names a function and this names the
|
* at link time, because a missing symbol names a function and this names the
|
||||||
* release.
|
* release.
|
||||||
*/
|
*/
|
||||||
#if !AKGL_VERSION_AT_LEAST(0, 4, 0)
|
#if !AKGL_VERSION_AT_LEAST(0, 5, 0)
|
||||||
#error "akbasic's libakgl adaptors require libakgl 0.4.0 or later"
|
#error "akbasic's libakgl adaptors require libakgl 0.5.0 or later"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <akbasic/audio.h>
|
#include <akbasic/audio.h>
|
||||||
|
|||||||
@@ -30,7 +30,8 @@
|
|||||||
#include <akgl/controller.h>
|
#include <akgl/controller.h>
|
||||||
#include <akgl/error.h>
|
#include <akgl/error.h>
|
||||||
/*
|
/*
|
||||||
* game.h purely for the `renderer` global and its `_akgl_renderer` storage.
|
* game.h purely for the `akgl_renderer` global and its `akgl_default_renderer`
|
||||||
|
* storage.
|
||||||
* akgl_text_rendertextat() takes no renderer argument and reads that global, so
|
* akgl_text_rendertextat() takes no renderer argument and reads that global, so
|
||||||
* a host that never calls akgl_game_init() -- which is every host embedding this
|
* a host that never calls akgl_game_init() -- which is every host embedding this
|
||||||
* interpreter, since owning the game loop is exactly what goal 3 forbids -- has
|
* interpreter, since owning the game loop is exactly what goal 3 forbids -- has
|
||||||
@@ -72,13 +73,13 @@ akerr_ErrorContext *akbasic_frontend_akgl_init(akbasic_AkglFrontend *obj, const
|
|||||||
FAIL_ZERO_RETURN(errctx, TTF_Init(), AKGL_ERR_SDL,
|
FAIL_ZERO_RETURN(errctx, TTF_Init(), AKGL_ERR_SDL,
|
||||||
"Couldn't initialize SDL_ttf: %s", SDL_GetError());
|
"Couldn't initialize SDL_ttf: %s", SDL_GetError());
|
||||||
|
|
||||||
obj->renderer = &_akgl_renderer;
|
obj->renderer = &akgl_default_renderer;
|
||||||
renderer = obj->renderer;
|
akgl_renderer = obj->renderer;
|
||||||
FAIL_ZERO_RETURN(errctx,
|
FAIL_ZERO_RETURN(errctx,
|
||||||
SDL_CreateWindowAndRenderer(title, w, h, 0,
|
SDL_CreateWindowAndRenderer(title, w, h, 0,
|
||||||
&obj->window, &obj->renderer->sdl_renderer),
|
&obj->window, &obj->renderer->sdl_renderer),
|
||||||
AKGL_ERR_SDL, "Couldn't create the window: %s", SDL_GetError());
|
AKGL_ERR_SDL, "Couldn't create the window: %s", SDL_GetError());
|
||||||
window = obj->window;
|
akgl_window = obj->window;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Without this SDL sends no SDL_EVENT_TEXT_INPUT at all, every keystroke
|
* Without this SDL sends no SDL_EVENT_TEXT_INPUT at all, every keystroke
|
||||||
@@ -95,14 +96,14 @@ akerr_ErrorContext *akbasic_frontend_akgl_init(akbasic_AkglFrontend *obj, const
|
|||||||
SDL_GetError());
|
SDL_GetError());
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* Bind the 2D methods onto the renderer we just made. akgl_render_init2d()
|
* Bind the 2D methods onto the renderer we just made. akgl_render_2d_init()
|
||||||
* would do this too, but it creates its own window from the game properties
|
* would do this too, but it creates its own window from the game properties
|
||||||
* first, which is the akgl_game_init() path a host with its own window is
|
* first, which is the akgl_game_init() path a host with its own window is
|
||||||
* not on. libakgl 0.3.0 split the vtable half out for exactly this caller --
|
* not on. libakgl 0.3.0 split the vtable half out for exactly this caller --
|
||||||
* it was API-gap item 7, and until it landed these six pointers were
|
* it was API-gap item 7, and until it landed these six pointers were
|
||||||
* assigned by hand here and in tests/akgl_backends.c.
|
* assigned by hand here and in tests/akgl_backends.c.
|
||||||
*/
|
*/
|
||||||
PASS(errctx, akgl_render_bind2d(obj->renderer));
|
PASS(errctx, akgl_render_2d_bind(obj->renderer));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The object pools and the name registries. Every akgl_*_initialize ends in
|
* The object pools and the name registries. Every akgl_*_initialize ends in
|
||||||
@@ -133,11 +134,11 @@ akerr_ErrorContext *akbasic_frontend_akgl_init(akbasic_AkglFrontend *obj, const
|
|||||||
* anybody could act on. One screen's worth at the origin: BASIC has no verb
|
* anybody could act on. One screen's worth at the origin: BASIC has no verb
|
||||||
* that scrolls a view, so the world and the screen are the same thing here.
|
* that scrolls a view, so the world and the screen are the same thing here.
|
||||||
*/
|
*/
|
||||||
camera = &_akgl_camera;
|
akgl_camera = &akgl_default_camera;
|
||||||
camera->x = 0.0f;
|
akgl_camera->x = 0.0f;
|
||||||
camera->y = 0.0f;
|
akgl_camera->y = 0.0f;
|
||||||
camera->w = (float)w;
|
akgl_camera->w = (float)w;
|
||||||
camera->h = (float)h;
|
akgl_camera->h = (float)h;
|
||||||
|
|
||||||
obj->font = TTF_OpenFont(fontpath, (float)fontsize);
|
obj->font = TTF_OpenFont(fontpath, (float)fontsize);
|
||||||
FAIL_ZERO_RETURN(errctx, (obj->font != NULL), AKGL_ERR_SDL,
|
FAIL_ZERO_RETURN(errctx, (obj->font != NULL), AKGL_ERR_SDL,
|
||||||
@@ -331,7 +332,7 @@ void akbasic_frontend_akgl_shutdown(akbasic_AkglFrontend *obj)
|
|||||||
SDL_StopTextInput(obj->window);
|
SDL_StopTextInput(obj->window);
|
||||||
SDL_DestroyWindow(obj->window);
|
SDL_DestroyWindow(obj->window);
|
||||||
obj->window = NULL;
|
obj->window = NULL;
|
||||||
window = NULL;
|
akgl_window = NULL;
|
||||||
}
|
}
|
||||||
TTF_Quit();
|
TTF_Quit();
|
||||||
if ( obj->ownssdl ) {
|
if ( obj->ownssdl ) {
|
||||||
|
|||||||
@@ -17,12 +17,20 @@
|
|||||||
* loads through akgl_spritesheet_initialize(), the same two calls
|
* loads through akgl_spritesheet_initialize(), the same two calls
|
||||||
* akgl_sprite_load_json_spritesheet() makes.
|
* akgl_sprite_load_json_spritesheet() makes.
|
||||||
*
|
*
|
||||||
* Every actor gets a renderfunc of its own rather than akgl_actor_render(). Two
|
* Every actor gets a renderfunc of its own rather than akgl_actor_render(). It
|
||||||
* reasons, both defects filed upstream: the default computes its destination
|
* was two reasons, both filed upstream, and **libakgl 0.5.0 fixed one of them**:
|
||||||
* height from the sprite's *width*, which draws a 24x21 Commodore sprite as a
|
* the default used to compute its destination height from the sprite's *width*,
|
||||||
* 24x24 square; and an actor carries one scalar `scale`, which cannot express
|
* drawing a 24x21 Commodore sprite as a 24x24 square, and it now uses the
|
||||||
* SPRITE's separate x- and y-expand bits. Installing a function pointer is
|
* height. That was libakgl defect 26.
|
||||||
* libakgl's own extension point for exactly this, so nothing is forked.
|
*
|
||||||
|
* The remaining reason is the one that still requires this file: an akgl_Actor
|
||||||
|
* carries a single scalar `scale` applied to both axes, which cannot express
|
||||||
|
* SPRITE's separate x- and y-expand bits. libakgl records that as an open item
|
||||||
|
* and names this interpreter as the caller that needs it; the shape it takes --
|
||||||
|
* scale_x/scale_y beside scale, or replacing scale outright -- is a design
|
||||||
|
* decision over there rather than a patch. Until it lands, installing a function
|
||||||
|
* pointer is libakgl's own extension point for exactly this, so nothing is
|
||||||
|
* forked.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
@@ -82,9 +90,11 @@ static akerr_ErrorContext *slot_of(akbasic_SpriteBackend *self, int n, akbasic_A
|
|||||||
/**
|
/**
|
||||||
* @brief Draw one BASIC sprite, in place of akgl_actor_render().
|
* @brief Draw one BASIC sprite, in place of akgl_actor_render().
|
||||||
*
|
*
|
||||||
* Differs from the default in exactly two ways, both noted at the top of this
|
* Differs from the default in exactly one way now, noted at the top of this file:
|
||||||
* file: the destination height comes from the sprite's height rather than its
|
* the two expansion bits scale the axes independently, where an actor's single
|
||||||
* width, and the two expansion bits scale the axes independently.
|
* `scale` cannot. Taking the destination height from the sprite's height used to
|
||||||
|
* be the second difference and is the default's behaviour as of libakgl 0.5.0 --
|
||||||
|
* the line below is no longer a correction, only agreement.
|
||||||
*
|
*
|
||||||
* Like the default, it skips rather than reports: an actor with no image, one
|
* Like the default, it skips rather than reports: an actor with no image, one
|
||||||
* that is hidden, one whose slot has been reused. A frame is not the place to
|
* that is hidden, one whose slot has been reused. A frame is not the place to
|
||||||
@@ -121,9 +131,9 @@ static akerr_ErrorContext *spr_render_actor(akgl_Actor *obj)
|
|||||||
SUCCEED_RETURN(errctx);
|
SUCCEED_RETURN(errctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
PASS(errctx, akgl_sprite_sheet_coords_for_frame(sprite, &src, 0));
|
PASS(errctx, akgl_spritesheet_coords_for_frame(sprite, &src, 0));
|
||||||
dest.x = obj->x - (camera != NULL ? camera->x : 0.0f);
|
dest.x = obj->x - (akgl_camera != NULL ? akgl_camera->x : 0.0f);
|
||||||
dest.y = obj->y - (camera != NULL ? camera->y : 0.0f);
|
dest.y = obj->y - (akgl_camera != NULL ? akgl_camera->y : 0.0f);
|
||||||
dest.w = (float32_t)sprite->width * (state->xexpand[found] ? 2.0f : 1.0f);
|
dest.w = (float32_t)sprite->width * (state->xexpand[found] ? 2.0f : 1.0f);
|
||||||
dest.h = (float32_t)sprite->height * (state->yexpand[found] ? 2.0f : 1.0f);
|
dest.h = (float32_t)sprite->height * (state->yexpand[found] ? 2.0f : 1.0f);
|
||||||
|
|
||||||
|
|||||||
@@ -25,7 +25,7 @@
|
|||||||
#include <akgl/controller.h>
|
#include <akgl/controller.h>
|
||||||
#include <akgl/error.h>
|
#include <akgl/error.h>
|
||||||
/*
|
/*
|
||||||
* game.h purely for the `renderer` global and its `_akgl_renderer` storage. The
|
* game.h purely for the `akgl_renderer` global and its `akgl_default_renderer` storage. The
|
||||||
* interpreter never calls akgl_game_init() -- it drives subsystems directly, and
|
* interpreter never calls akgl_game_init() -- it drives subsystems directly, and
|
||||||
* owning the game loop is exactly what goal 3 forbids -- but the draw calls read
|
* owning the game loop is exactly what goal 3 forbids -- but the draw calls read
|
||||||
* that global, so a test standing in for a host has to populate it the same way
|
* that global, so a test standing in for a host has to populate it the same way
|
||||||
@@ -85,9 +85,9 @@ static akerr_ErrorContext AKERR_NOIGNORE *clear_target(void)
|
|||||||
{
|
{
|
||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
|
|
||||||
FAIL_ZERO_RETURN(errctx, SDL_SetRenderDrawColor(renderer->sdl_renderer, 0, 0, 0, 0xff),
|
FAIL_ZERO_RETURN(errctx, SDL_SetRenderDrawColor(akgl_renderer->sdl_renderer, 0, 0, 0, 0xff),
|
||||||
AKGL_ERR_SDL, "%s", SDL_GetError());
|
AKGL_ERR_SDL, "%s", SDL_GetError());
|
||||||
FAIL_ZERO_RETURN(errctx, SDL_RenderClear(renderer->sdl_renderer),
|
FAIL_ZERO_RETURN(errctx, SDL_RenderClear(akgl_renderer->sdl_renderer),
|
||||||
AKGL_ERR_SDL, "%s", SDL_GetError());
|
AKGL_ERR_SDL, "%s", SDL_GetError());
|
||||||
SUCCEED_RETURN(errctx);
|
SUCCEED_RETURN(errctx);
|
||||||
}
|
}
|
||||||
@@ -104,8 +104,8 @@ static akerr_ErrorContext AKERR_NOIGNORE *start_runtime(const char *source)
|
|||||||
|
|
||||||
PASS(errctx, akbasic_sink_init_stdio(&SINK, &SINKSTATE, OUT, NULL));
|
PASS(errctx, akbasic_sink_init_stdio(&SINK, &SINKSTATE, OUT, NULL));
|
||||||
PASS(errctx, akbasic_runtime_init(&RUNTIME, &SINK));
|
PASS(errctx, akbasic_runtime_init(&RUNTIME, &SINK));
|
||||||
PASS(errctx, akbasic_graphics_init_akgl(&GRAPHICS, &GRAPHICSSTATE, renderer));
|
PASS(errctx, akbasic_graphics_init_akgl(&GRAPHICS, &GRAPHICSSTATE, akgl_renderer));
|
||||||
PASS(errctx, akbasic_sprite_init_akgl(&SPRITES, &SPRITESSTATE, renderer, &GRAPHICSSTATE));
|
PASS(errctx, akbasic_sprite_init_akgl(&SPRITES, &SPRITESSTATE, akgl_renderer, &GRAPHICSSTATE));
|
||||||
PASS(errctx, akbasic_runtime_set_devices(&RUNTIME, &GRAPHICS, NULL, NULL, &SPRITES));
|
PASS(errctx, akbasic_runtime_set_devices(&RUNTIME, &GRAPHICS, NULL, NULL, &SPRITES));
|
||||||
PASS(errctx, akbasic_runtime_load(&RUNTIME, source));
|
PASS(errctx, akbasic_runtime_load(&RUNTIME, source));
|
||||||
PASS(errctx, akbasic_runtime_start(&RUNTIME, AKBASIC_MODE_RUN));
|
PASS(errctx, akbasic_runtime_start(&RUNTIME, AKBASIC_MODE_RUN));
|
||||||
@@ -136,7 +136,7 @@ static akerr_ErrorContext AKERR_NOIGNORE *test_draw_reaches_pixels(void)
|
|||||||
PASS(errctx, start_runtime("10 COLOR 1, 3\n20 DRAW 1, 10, 20\n"));
|
PASS(errctx, start_runtime("10 COLOR 1, 3\n20 DRAW 1, 10, 20\n"));
|
||||||
TEST_REQUIRE_STR(OUTPUT, "");
|
TEST_REQUIRE_STR(OUTPUT, "");
|
||||||
|
|
||||||
shot = SDL_RenderReadPixels(renderer->sdl_renderer, NULL);
|
shot = SDL_RenderReadPixels(akgl_renderer->sdl_renderer, NULL);
|
||||||
TEST_REQUIRE(shot != NULL, "could not read the render target back");
|
TEST_REQUIRE(shot != NULL, "could not read the render target back");
|
||||||
/* Palette index 3 is red: 0x88, 0x39, 0x32 in src/graphics_tables.c. */
|
/* Palette index 3 is red: 0x88, 0x39, 0x32 in src/graphics_tables.c. */
|
||||||
TEST_REQUIRE(pixel_is(shot, 10, 20, 0x88, 0x39, 0x32),
|
TEST_REQUIRE(pixel_is(shot, 10, 20, 0x88, 0x39, 0x32),
|
||||||
@@ -171,7 +171,7 @@ static akerr_ErrorContext AKERR_NOIGNORE *test_size_is_the_renderer(void)
|
|||||||
"20 DRAW 1, 1000, 1000\n"));
|
"20 DRAW 1, 1000, 1000\n"));
|
||||||
TEST_REQUIRE_STR(OUTPUT, "");
|
TEST_REQUIRE_STR(OUTPUT, "");
|
||||||
|
|
||||||
shot = SDL_RenderReadPixels(renderer->sdl_renderer, NULL);
|
shot = SDL_RenderReadPixels(akgl_renderer->sdl_renderer, NULL);
|
||||||
TEST_REQUIRE(shot != NULL, "could not read the render target back");
|
TEST_REQUIRE(shot != NULL, "could not read the render target back");
|
||||||
/*
|
/*
|
||||||
* The far corner of the user space lands on the far corner of the target.
|
* The far corner of the user space lands on the far corner of the target.
|
||||||
@@ -195,7 +195,7 @@ static akerr_ErrorContext AKERR_NOIGNORE *test_box_outlines(void)
|
|||||||
PASS(errctx, start_runtime("10 BOX 1, 10, 10, 40, 40\n"));
|
PASS(errctx, start_runtime("10 BOX 1, 10, 10, 40, 40\n"));
|
||||||
TEST_REQUIRE_STR(OUTPUT, "");
|
TEST_REQUIRE_STR(OUTPUT, "");
|
||||||
|
|
||||||
shot = SDL_RenderReadPixels(renderer->sdl_renderer, NULL);
|
shot = SDL_RenderReadPixels(akgl_renderer->sdl_renderer, NULL);
|
||||||
TEST_REQUIRE(shot != NULL, "could not read the render target back");
|
TEST_REQUIRE(shot != NULL, "could not read the render target back");
|
||||||
TEST_REQUIRE(pixel_is(shot, 10, 10, 0xff, 0xff, 0xff), "the box's corner should be lit");
|
TEST_REQUIRE(pixel_is(shot, 10, 10, 0xff, 0xff, 0xff), "the box's corner should be lit");
|
||||||
TEST_REQUIRE(pixel_is(shot, 25, 10, 0xff, 0xff, 0xff), "the box's top edge should be lit");
|
TEST_REQUIRE(pixel_is(shot, 25, 10, 0xff, 0xff, 0xff), "the box's top edge should be lit");
|
||||||
@@ -223,7 +223,7 @@ static akerr_ErrorContext AKERR_NOIGNORE *test_paint_fills_region(void)
|
|||||||
"30 PAINT 2, 25, 25\n"));
|
"30 PAINT 2, 25, 25\n"));
|
||||||
TEST_REQUIRE_STR(OUTPUT, "");
|
TEST_REQUIRE_STR(OUTPUT, "");
|
||||||
|
|
||||||
shot = SDL_RenderReadPixels(renderer->sdl_renderer, NULL);
|
shot = SDL_RenderReadPixels(akgl_renderer->sdl_renderer, NULL);
|
||||||
TEST_REQUIRE(shot != NULL, "could not read the render target back");
|
TEST_REQUIRE(shot != NULL, "could not read the render target back");
|
||||||
/* Palette index 6 is green: 0x55, 0xa0, 0x49. */
|
/* Palette index 6 is green: 0x55, 0xa0, 0x49. */
|
||||||
TEST_REQUIRE(pixel_is(shot, 25, 25, 0x55, 0xa0, 0x49),
|
TEST_REQUIRE(pixel_is(shot, 25, 25, 0x55, 0xa0, 0x49),
|
||||||
@@ -247,7 +247,7 @@ static akerr_ErrorContext AKERR_NOIGNORE *test_shape_roundtrip(void)
|
|||||||
"30 GSHAPE A$, 64, 64\n"));
|
"30 GSHAPE A$, 64, 64\n"));
|
||||||
TEST_REQUIRE_STR(OUTPUT, "");
|
TEST_REQUIRE_STR(OUTPUT, "");
|
||||||
|
|
||||||
shot = SDL_RenderReadPixels(renderer->sdl_renderer, NULL);
|
shot = SDL_RenderReadPixels(akgl_renderer->sdl_renderer, NULL);
|
||||||
TEST_REQUIRE(shot != NULL, "could not read the render target back");
|
TEST_REQUIRE(shot != NULL, "could not read the render target back");
|
||||||
/* The saved corner was at (4,4); pasted at (64,64) it lands at (68,68). */
|
/* The saved corner was at (4,4); pasted at (64,64) it lands at (68,68). */
|
||||||
TEST_REQUIRE(pixel_is(shot, 68, 68, 0xff, 0xff, 0xff),
|
TEST_REQUIRE(pixel_is(shot, 68, 68, 0xff, 0xff, 0xff),
|
||||||
@@ -273,7 +273,7 @@ static akerr_ErrorContext AKERR_NOIGNORE *test_sink_grid_and_wrap(void)
|
|||||||
PASS(errctx, akgl_text_measure(font, "A", &cellw, &cellh));
|
PASS(errctx, akgl_text_measure(font, "A", &cellw, &cellh));
|
||||||
TEST_REQUIRE(cellw > 0 && cellh > 0, "the fixture font should measure a real cell");
|
TEST_REQUIRE(cellw > 0 && cellh > 0, "the fixture font should measure a real cell");
|
||||||
|
|
||||||
PASS(errctx, akbasic_sink_init_akgl(&AKGLSINK, &AKGLSINKSTATE, renderer, font,
|
PASS(errctx, akbasic_sink_init_akgl(&AKGLSINK, &AKGLSINKSTATE, akgl_renderer, font,
|
||||||
TARGET_SIZE, TARGET_SIZE));
|
TARGET_SIZE, TARGET_SIZE));
|
||||||
TEST_REQUIRE_INT(AKGLSINKSTATE.cellw, cellw);
|
TEST_REQUIRE_INT(AKGLSINKSTATE.cellw, cellw);
|
||||||
TEST_REQUIRE_INT(AKGLSINKSTATE.columns, TARGET_SIZE / cellw);
|
TEST_REQUIRE_INT(AKGLSINKSTATE.columns, TARGET_SIZE / cellw);
|
||||||
@@ -297,7 +297,7 @@ static akerr_ErrorContext AKERR_NOIGNORE *test_sink_grid_and_wrap(void)
|
|||||||
* producing a zero-column grid, which would divide by zero on the first
|
* producing a zero-column grid, which would divide by zero on the first
|
||||||
* wrap.
|
* wrap.
|
||||||
*/
|
*/
|
||||||
TEST_REQUIRE_STATUS(akbasic_sink_init_akgl(&AKGLSINK, &AKGLSINKSTATE, renderer, font, 1, 1),
|
TEST_REQUIRE_STATUS(akbasic_sink_init_akgl(&AKGLSINK, &AKGLSINKSTATE, akgl_renderer, font, 1, 1),
|
||||||
AKBASIC_ERR_BOUNDS);
|
AKBASIC_ERR_BOUNDS);
|
||||||
TEST_REQUIRE_STATUS(akbasic_sink_init_akgl(&AKGLSINK, &AKGLSINKSTATE, NULL, font,
|
TEST_REQUIRE_STATUS(akbasic_sink_init_akgl(&AKGLSINK, &AKGLSINKSTATE, NULL, font,
|
||||||
TARGET_SIZE, TARGET_SIZE),
|
TARGET_SIZE, TARGET_SIZE),
|
||||||
@@ -315,7 +315,7 @@ static akerr_ErrorContext AKERR_NOIGNORE *test_sink_renders(void)
|
|||||||
bool lit = false;
|
bool lit = false;
|
||||||
|
|
||||||
PASS(errctx, clear_target());
|
PASS(errctx, clear_target());
|
||||||
PASS(errctx, akbasic_sink_init_akgl(&AKGLSINK, &AKGLSINKSTATE, renderer, font,
|
PASS(errctx, akbasic_sink_init_akgl(&AKGLSINK, &AKGLSINKSTATE, akgl_renderer, font,
|
||||||
TARGET_SIZE, TARGET_SIZE));
|
TARGET_SIZE, TARGET_SIZE));
|
||||||
PASS(errctx, AKGLSINK.write(&AKGLSINK, "X"));
|
PASS(errctx, AKGLSINK.write(&AKGLSINK, "X"));
|
||||||
PASS(errctx, akbasic_sink_akgl_render(&AKGLSINK));
|
PASS(errctx, akbasic_sink_akgl_render(&AKGLSINK));
|
||||||
@@ -326,7 +326,7 @@ static akerr_ErrorContext AKERR_NOIGNORE *test_sink_renders(void)
|
|||||||
* is free to hint them differently. The seam being tested is that the text
|
* is free to hint them differently. The seam being tested is that the text
|
||||||
* reached the renderer at the cursor's cell at all.
|
* reached the renderer at the cursor's cell at all.
|
||||||
*/
|
*/
|
||||||
shot = SDL_RenderReadPixels(renderer->sdl_renderer, NULL);
|
shot = SDL_RenderReadPixels(akgl_renderer->sdl_renderer, NULL);
|
||||||
TEST_REQUIRE(shot != NULL, "could not read the render target back");
|
TEST_REQUIRE(shot != NULL, "could not read the render target back");
|
||||||
for ( y = 0; y < AKGLSINKSTATE.cellh && !lit; y++ ) {
|
for ( y = 0; y < AKGLSINKSTATE.cellh && !lit; y++ ) {
|
||||||
for ( x = 0; x < AKGLSINKSTATE.cellw && !lit; x++ ) {
|
for ( x = 0; x < AKGLSINKSTATE.cellw && !lit; x++ ) {
|
||||||
@@ -402,7 +402,7 @@ static akerr_ErrorContext AKERR_NOIGNORE *test_sprite_from_file(void)
|
|||||||
TEST_REQUIRE_STR(OUTPUT, "");
|
TEST_REQUIRE_STR(OUTPUT, "");
|
||||||
PASS(errctx, akbasic_sprite_akgl_render(&SPRITES));
|
PASS(errctx, akbasic_sprite_akgl_render(&SPRITES));
|
||||||
|
|
||||||
shot = SDL_RenderReadPixels(renderer->sdl_renderer, NULL);
|
shot = SDL_RenderReadPixels(akgl_renderer->sdl_renderer, NULL);
|
||||||
TEST_REQUIRE(shot != NULL, "could not read the render target back");
|
TEST_REQUIRE(shot != NULL, "could not read the render target back");
|
||||||
/*
|
/*
|
||||||
* Magenta, not white: SPRITE's colour argument modulates the texture and
|
* Magenta, not white: SPRITE's colour argument modulates the texture and
|
||||||
@@ -448,7 +448,7 @@ static akerr_ErrorContext AKERR_NOIGNORE *test_sprite_from_pattern(void)
|
|||||||
TEST_REQUIRE_STR(OUTPUT, "");
|
TEST_REQUIRE_STR(OUTPUT, "");
|
||||||
PASS(errctx, akbasic_sprite_akgl_render(&SPRITES));
|
PASS(errctx, akbasic_sprite_akgl_render(&SPRITES));
|
||||||
|
|
||||||
shot = SDL_RenderReadPixels(renderer->sdl_renderer, NULL);
|
shot = SDL_RenderReadPixels(akgl_renderer->sdl_renderer, NULL);
|
||||||
TEST_REQUIRE(shot != NULL, "could not read the render target back");
|
TEST_REQUIRE(shot != NULL, "could not read the render target back");
|
||||||
/* Palette index 6 is green: 0x55, 0xa0, 0x49. */
|
/* Palette index 6 is green: 0x55, 0xa0, 0x49. */
|
||||||
TEST_REQUIRE(pixel_is(shot, 20, 20, 0x55, 0xa0, 0x49),
|
TEST_REQUIRE(pixel_is(shot, 20, 20, 0x55, 0xa0, 0x49),
|
||||||
@@ -485,7 +485,7 @@ static akerr_ErrorContext AKERR_NOIGNORE *test_sprite_from_shape(void)
|
|||||||
TEST_REQUIRE_STR(OUTPUT, "");
|
TEST_REQUIRE_STR(OUTPUT, "");
|
||||||
PASS(errctx, akbasic_sprite_akgl_render(&SPRITES));
|
PASS(errctx, akbasic_sprite_akgl_render(&SPRITES));
|
||||||
|
|
||||||
shot = SDL_RenderReadPixels(renderer->sdl_renderer, NULL);
|
shot = SDL_RenderReadPixels(akgl_renderer->sdl_renderer, NULL);
|
||||||
TEST_REQUIRE(shot != NULL, "could not read the render target back");
|
TEST_REQUIRE(shot != NULL, "could not read the render target back");
|
||||||
/*
|
/*
|
||||||
* Palette index 3 is red, which is what the BOX was outlined in. The corner
|
* Palette index 3 is red, which is what the BOX was outlined in. The corner
|
||||||
@@ -512,7 +512,7 @@ int main(void)
|
|||||||
|
|
||||||
ATTEMPT {
|
ATTEMPT {
|
||||||
CATCH(errctx, akgl_error_init());
|
CATCH(errctx, akgl_error_init());
|
||||||
renderer = &_akgl_renderer;
|
akgl_renderer = &akgl_default_renderer;
|
||||||
|
|
||||||
FAIL_ZERO_BREAK(errctx, SDL_Init(SDL_INIT_VIDEO), AKGL_ERR_SDL,
|
FAIL_ZERO_BREAK(errctx, SDL_Init(SDL_INIT_VIDEO), AKGL_ERR_SDL,
|
||||||
"Couldn't initialize SDL: %s", SDL_GetError());
|
"Couldn't initialize SDL: %s", SDL_GetError());
|
||||||
@@ -521,17 +521,18 @@ int main(void)
|
|||||||
FAIL_ZERO_BREAK(errctx,
|
FAIL_ZERO_BREAK(errctx,
|
||||||
SDL_CreateWindowAndRenderer("net/aklabs/akbasic/test_akgl_backends",
|
SDL_CreateWindowAndRenderer("net/aklabs/akbasic/test_akgl_backends",
|
||||||
TARGET_SIZE, TARGET_SIZE, 0,
|
TARGET_SIZE, TARGET_SIZE, 0,
|
||||||
&window, &renderer->sdl_renderer),
|
&akgl_window, &akgl_renderer->sdl_renderer),
|
||||||
AKGL_ERR_SDL, "Couldn't create window/renderer: %s", SDL_GetError());
|
AKGL_ERR_SDL, "Couldn't create window/renderer: %s", SDL_GetError());
|
||||||
/*
|
/*
|
||||||
* Bind the 2D methods. akgl_text_rendertextat() reaches through
|
* Bind the 2D methods. akgl_text_rendertextat() reaches through
|
||||||
* renderer->draw_texture and an SDL_Renderer alone does not fill that in;
|
* akgl_renderer->draw_texture and an SDL_Renderer alone does not fill that in;
|
||||||
* deps/libakgl/tests/draw.c gets away without it because the draw
|
* deps/libakgl/tests/draw.c gets away without it because the draw
|
||||||
* primitives take the SDL_Renderer directly. These six pointers were
|
* primitives take the SDL_Renderer directly. These six pointers were
|
||||||
* assigned by hand here until libakgl 0.3.0 split akgl_render_bind2d out
|
* assigned by hand here until libakgl 0.3.0 split the bind half out of the
|
||||||
* of akgl_render_init2d -- API-gap item 7, filed from this file.
|
* init half -- API-gap item 7, filed from this file. Both were renamed in
|
||||||
|
* 0.5.0, from akgl_render_bind2d and akgl_render_init2d.
|
||||||
*/
|
*/
|
||||||
CATCH(errctx, akgl_render_bind2d(renderer));
|
CATCH(errctx, akgl_render_2d_bind(akgl_renderer));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The three things akgl_game_init() would have done and this file, being
|
* The three things akgl_game_init() would have done and this file, being
|
||||||
@@ -541,11 +542,11 @@ int main(void)
|
|||||||
*/
|
*/
|
||||||
CATCH(errctx, akgl_heap_init());
|
CATCH(errctx, akgl_heap_init());
|
||||||
CATCH(errctx, akgl_registry_init());
|
CATCH(errctx, akgl_registry_init());
|
||||||
camera = &_akgl_camera;
|
akgl_camera = &akgl_default_camera;
|
||||||
camera->x = 0.0f;
|
akgl_camera->x = 0.0f;
|
||||||
camera->y = 0.0f;
|
akgl_camera->y = 0.0f;
|
||||||
camera->w = (float)TARGET_SIZE;
|
akgl_camera->w = (float)TARGET_SIZE;
|
||||||
camera->h = (float)TARGET_SIZE;
|
akgl_camera->h = (float)TARGET_SIZE;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* libakgl's own monospaced fixture, borrowed rather than copied. Being
|
* libakgl's own monospaced fixture, borrowed rather than copied. Being
|
||||||
|
|||||||
@@ -33,7 +33,7 @@
|
|||||||
#include <akgl/controller.h>
|
#include <akgl/controller.h>
|
||||||
#include <akgl/draw.h>
|
#include <akgl/draw.h>
|
||||||
#include <akgl/error.h>
|
#include <akgl/error.h>
|
||||||
/* game.h for the `camera` global, which akgl_actor_render() reads. */
|
/* game.h for the `akgl_camera` global, which akgl_actor_render() reads. */
|
||||||
#include <akgl/game.h>
|
#include <akgl/game.h>
|
||||||
#include <akgl/heap.h>
|
#include <akgl/heap.h>
|
||||||
#include <akgl/registry.h>
|
#include <akgl/registry.h>
|
||||||
@@ -875,9 +875,9 @@ static akerr_ErrorContext AKERR_NOIGNORE *test_host_can_draw_an_actor(void)
|
|||||||
|
|
||||||
PASS(errctx, start_frontend(NULL));
|
PASS(errctx, start_frontend(NULL));
|
||||||
|
|
||||||
TEST_REQUIRE(camera != NULL, "the frontend should have pointed the camera somewhere");
|
TEST_REQUIRE(akgl_camera != NULL, "the frontend should have pointed the camera somewhere");
|
||||||
TEST_REQUIRE_INT((int)camera->w, WINDOW_W);
|
TEST_REQUIRE_INT((int)akgl_camera->w, WINDOW_W);
|
||||||
TEST_REQUIRE_INT((int)camera->h, WINDOW_H);
|
TEST_REQUIRE_INT((int)akgl_camera->h, WINDOW_H);
|
||||||
TEST_REQUIRE(AKGL_REGISTRY_ACTOR != 0, "the frontend should have created the registries");
|
TEST_REQUIRE(AKGL_REGISTRY_ACTOR != 0, "the frontend should have created the registries");
|
||||||
|
|
||||||
memset(sheetname, 0, sizeof(sheetname));
|
memset(sheetname, 0, sizeof(sheetname));
|
||||||
|
|||||||
@@ -104,22 +104,22 @@ static akerr_ErrorContext AKERR_NOIGNORE *draw_program(const char *outpath, int
|
|||||||
SDL_Surface *shot = NULL;
|
SDL_Surface *shot = NULL;
|
||||||
|
|
||||||
PASS(errctx, akgl_error_init());
|
PASS(errctx, akgl_error_init());
|
||||||
renderer = &_akgl_renderer;
|
akgl_renderer = &akgl_default_renderer;
|
||||||
|
|
||||||
FAIL_ZERO_RETURN(errctx, SDL_Init(SDL_INIT_VIDEO), AKGL_ERR_SDL,
|
FAIL_ZERO_RETURN(errctx, SDL_Init(SDL_INIT_VIDEO), AKGL_ERR_SDL,
|
||||||
"Couldn't initialize SDL: %s", SDL_GetError());
|
"Couldn't initialize SDL: %s", SDL_GetError());
|
||||||
FAIL_ZERO_RETURN(errctx,
|
FAIL_ZERO_RETURN(errctx,
|
||||||
SDL_CreateWindowAndRenderer("net/aklabs/akbasic/screenshot", w, h, 0,
|
SDL_CreateWindowAndRenderer("net/aklabs/akbasic/screenshot", w, h, 0,
|
||||||
&window, &renderer->sdl_renderer),
|
&akgl_window, &akgl_renderer->sdl_renderer),
|
||||||
AKGL_ERR_SDL, "Couldn't create window/renderer: %s", SDL_GetError());
|
AKGL_ERR_SDL, "Couldn't create window/renderer: %s", SDL_GetError());
|
||||||
PASS(errctx, akgl_render_bind2d(renderer));
|
PASS(errctx, akgl_render_2d_bind(akgl_renderer));
|
||||||
PASS(errctx, akgl_heap_init());
|
PASS(errctx, akgl_heap_init());
|
||||||
PASS(errctx, akgl_registry_init());
|
PASS(errctx, akgl_registry_init());
|
||||||
camera = &_akgl_camera;
|
akgl_camera = &akgl_default_camera;
|
||||||
camera->x = 0.0f;
|
akgl_camera->x = 0.0f;
|
||||||
camera->y = 0.0f;
|
akgl_camera->y = 0.0f;
|
||||||
camera->w = (float32_t)w;
|
akgl_camera->w = (float32_t)w;
|
||||||
camera->h = (float32_t)h;
|
akgl_camera->h = (float32_t)h;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Opaque black, so a figure has a defined background rather than whatever
|
* Opaque black, so a figure has a defined background rather than whatever
|
||||||
@@ -127,17 +127,17 @@ static akerr_ErrorContext AKERR_NOIGNORE *draw_program(const char *outpath, int
|
|||||||
* over the output for a reason src/graphics_akgl.c explains -- clearing is
|
* over the output for a reason src/graphics_akgl.c explains -- clearing is
|
||||||
* the host's prerogative -- and this is the host doing it.
|
* the host's prerogative -- and this is the host doing it.
|
||||||
*/
|
*/
|
||||||
FAIL_ZERO_RETURN(errctx, SDL_SetRenderDrawColor(renderer->sdl_renderer, 0, 0, 0, 0xff),
|
FAIL_ZERO_RETURN(errctx, SDL_SetRenderDrawColor(akgl_renderer->sdl_renderer, 0, 0, 0, 0xff),
|
||||||
AKGL_ERR_SDL, "%s", SDL_GetError());
|
AKGL_ERR_SDL, "%s", SDL_GetError());
|
||||||
FAIL_ZERO_RETURN(errctx, SDL_RenderClear(renderer->sdl_renderer),
|
FAIL_ZERO_RETURN(errctx, SDL_RenderClear(akgl_renderer->sdl_renderer),
|
||||||
AKGL_ERR_SDL, "%s", SDL_GetError());
|
AKGL_ERR_SDL, "%s", SDL_GetError());
|
||||||
|
|
||||||
/* stdout: a program that errors puts its "? line : CLASS message" there,
|
/* stdout: a program that errors puts its "? line : CLASS message" there,
|
||||||
which is what the caller shows when a figure comes out wrong. */
|
which is what the caller shows when a figure comes out wrong. */
|
||||||
PASS(errctx, akbasic_sink_init_stdio(&SINK, &SINKSTATE, stdout, NULL));
|
PASS(errctx, akbasic_sink_init_stdio(&SINK, &SINKSTATE, stdout, NULL));
|
||||||
PASS(errctx, akbasic_runtime_init(&RUNTIME, &SINK));
|
PASS(errctx, akbasic_runtime_init(&RUNTIME, &SINK));
|
||||||
PASS(errctx, akbasic_graphics_init_akgl(&GRAPHICS, &GRAPHICSSTATE, renderer));
|
PASS(errctx, akbasic_graphics_init_akgl(&GRAPHICS, &GRAPHICSSTATE, akgl_renderer));
|
||||||
PASS(errctx, akbasic_sprite_init_akgl(&SPRITES, &SPRITESSTATE, renderer, &GRAPHICSSTATE));
|
PASS(errctx, akbasic_sprite_init_akgl(&SPRITES, &SPRITESSTATE, akgl_renderer, &GRAPHICSSTATE));
|
||||||
PASS(errctx, akbasic_runtime_set_devices(&RUNTIME, &GRAPHICS, NULL, NULL, &SPRITES));
|
PASS(errctx, akbasic_runtime_set_devices(&RUNTIME, &GRAPHICS, NULL, NULL, &SPRITES));
|
||||||
PASS(errctx, akbasic_runtime_load(&RUNTIME, SOURCE));
|
PASS(errctx, akbasic_runtime_load(&RUNTIME, SOURCE));
|
||||||
PASS(errctx, akbasic_runtime_start(&RUNTIME, AKBASIC_MODE_RUN));
|
PASS(errctx, akbasic_runtime_start(&RUNTIME, AKBASIC_MODE_RUN));
|
||||||
@@ -151,7 +151,7 @@ static akerr_ErrorContext AKERR_NOIGNORE *draw_program(const char *outpath, int
|
|||||||
*/
|
*/
|
||||||
PASS(errctx, akbasic_sprite_akgl_render(&SPRITES));
|
PASS(errctx, akbasic_sprite_akgl_render(&SPRITES));
|
||||||
|
|
||||||
shot = SDL_RenderReadPixels(renderer->sdl_renderer, NULL);
|
shot = SDL_RenderReadPixels(akgl_renderer->sdl_renderer, NULL);
|
||||||
FAIL_ZERO_RETURN(errctx, (shot != NULL), AKGL_ERR_SDL,
|
FAIL_ZERO_RETURN(errctx, (shot != NULL), AKGL_ERR_SDL,
|
||||||
"Couldn't read the target back: %s", SDL_GetError());
|
"Couldn't read the target back: %s", SDL_GetError());
|
||||||
if ( !IMG_SavePNG(shot, outpath) ) {
|
if ( !IMG_SavePNG(shot, outpath) ) {
|
||||||
@@ -196,9 +196,9 @@ int main(int argc, char **argv)
|
|||||||
CATCH(errctx, read_program(argv[1]));
|
CATCH(errctx, read_program(argv[1]));
|
||||||
CATCH(errctx, draw_program(argv[2], w, h));
|
CATCH(errctx, draw_program(argv[2], w, h));
|
||||||
} CLEANUP {
|
} CLEANUP {
|
||||||
if ( window != NULL ) {
|
if ( akgl_window != NULL ) {
|
||||||
SDL_DestroyWindow(window);
|
SDL_DestroyWindow(akgl_window);
|
||||||
window = NULL;
|
akgl_window = NULL;
|
||||||
}
|
}
|
||||||
SDL_Quit();
|
SDL_Quit();
|
||||||
} PROCESS(errctx) {
|
} PROCESS(errctx) {
|
||||||
|
|||||||
Reference in New Issue
Block a user