6 files changed, 11 insertions(+), 703 deletions(-)
D devices/apu.c
D devices/apu.h
D devices/ppu.c
D devices/ppu.h
D main.c
M src/main.c
D devices/apu.c => devices/apu.c +0 -95
@@ 1,95 0,0 @@
-/*
-Copyright (c) 2021 Devine Lu Linvega
-Copyright (c) 2021 Andrew Alderwick
-
-Permission to use, copy, modify, and distribute this software for any
-purpose with or without fee is hereby granted, provided that the above
-copyright notice and this permission notice appear in all copies.
-
-THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-WITH REGARD TO THIS SOFTWARE.
-*/
-
-#include "apu.h"
-
-#define NOTE_PERIOD (SAMPLE_FREQUENCY * 0x4000 / 11025)
-#define ADSR_STEP (SAMPLE_FREQUENCY / 0xf)
-
-/* clang-format off */
-
-static uint32_t advances[12] = {
- 0x80000, 0x879c8, 0x8facd, 0x9837f, 0xa1451, 0xaadc1,
- 0xb504f, 0xbfc88, 0xcb2ff, 0xd7450, 0xe411f, 0xf1a1c
-};
-
-/* clang-format on */
-
-static int32_t
-envelope(Apu *c, uint32_t age)
-{
- if(!c->r) return 0x0888;
- if(age < c->a) return 0x0888 * age / c->a;
- if(age < c->d) return 0x0444 * (2 * c->d - c->a - age) / (c->d - c->a);
- if(age < c->s) return 0x0444;
- if(age < c->r) return 0x0444 * (c->r - age) / (c->r - c->s);
- c->advance = 0;
- return 0x0000;
-}
-
-int
-apu_render(Apu *c, uint8_t *dat, int16_t *left, int16_t *right, int len)
-{
- int32_t s;
- if(!c->advance || !c->period) return 0;
- while(len--) {
- c->count += c->advance;
- c->i += c->count / c->period;
- c->count %= c->period;
- if(c->i >= c->len) {
- if(!c->repeat) {
- c->advance = 0;
- break;
- }
- c->i %= c->len;
- }
- s = (int8_t)(dat[c->addr + c->i] + 0x80) * envelope(c, c->age++);
- *left++ = s * c->volume[0] / 0x180;
- *right++ = s * c->volume[1] / 0x180;
- }
- return 1;
-}
-
-void
-apu_start(Apu *c, uint16_t adsr, uint8_t pitch)
-{
- if(pitch < 108 && c->len)
- c->advance = advances[pitch % 12] >> (8 - pitch / 12);
- else {
- c->advance = 0;
- return;
- }
- c->a = ADSR_STEP * (adsr >> 12);
- c->d = ADSR_STEP * (adsr >> 8 & 0xf) + c->a;
- c->s = ADSR_STEP * (adsr >> 4 & 0xf) + c->d;
- c->r = ADSR_STEP * (adsr >> 0 & 0xf) + c->s;
- c->age = 0;
- c->i = 0;
- if(c->len <= 0x100) /* single cycle mode */
- c->period = NOTE_PERIOD * 337 / 2 / c->len;
- else /* sample repeat mode */
- c->period = NOTE_PERIOD;
-}
-
-uint8_t
-apu_get_vu(Apu *c)
-{
- int i;
- int32_t sum[2] = {0, 0};
- if(!c->advance || !c->period) return 0;
- for(i = 0; i < 2; ++i) {
- if(!c->volume[i]) continue;
- sum[i] = 1 + envelope(c, c->age) * c->volume[i] / 0x800;
- if(sum[i] > 0xf) sum[i] = 0xf;
- }
- return (sum[0] << 4) | sum[1];
-}
D devices/apu.h => devices/apu.h +0 -27
@@ 1,27 0,0 @@
-/*
-Copyright (c) 2021 Devine Lu Linvega
-Copyright (c) 2021 Andrew Alderwick
-
-Permission to use, copy, modify, and distribute this software for any
-purpose with or without fee is hereby granted, provided that the above
-copyright notice and this permission notice appear in all copies.
-
-THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-WITH REGARD TO THIS SOFTWARE.
-*/
-
-#include <stdint.h>
-
-#define SAMPLE_FREQUENCY 44100
-
-typedef struct {
- uint32_t count, advance, period, age, a, d, s, r;
- uint16_t addr, i, len;
- int8_t volume[2];
- uint8_t pitch, repeat;
-} Apu;
-
-int apu_render(Apu *c, uint8_t *dat, int16_t *left, int16_t *right, int len);
-void apu_start(Apu *c, uint16_t adsr, uint8_t pitch);
-uint8_t apu_get_vu(Apu *c);
-void apu_finished_handler(Apu *c);
D devices/ppu.c => devices/ppu.c +0 -109
@@ 1,109 0,0 @@
-/*
-Copyright (c) 2021 Devine Lu Linvega
-Copyright (c) 2021 Andrew Alderwick
-
-Permission to use, copy, modify, and distribute this software for any
-purpose with or without fee is hereby granted, provided that the above
-copyright notice and this permission notice appear in all copies.
-
-THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-WITH REGARD TO THIS SOFTWARE.
-*/
-
-#include "ppu.h"
-
-int
-ppu_init(Ppu *p, uint32_t *framebuffer)
-{
- p->framebuffer = framebuffer;
- return 1;
-}
-
-static inline void
-render(Ppu *p, int offset, int count)
-{
- uint32_t *in = &p->pixels[offset * 3];
- uint32_t *out = &p->framebuffer[offset];
- while(count--) {
- *(out++) = in[0] ^ (in[2] & (in[0] ^ in[1]));
- in += 3;
- }
-}
-
-void
-render_all(Ppu *p)
-{
- render(p, 0, STRIDE_WORDS * HEIGHT);
-}
-
-void
-ppu_pixel(Ppu *p, uint8_t layer, uint16_t x, uint16_t y, uint8_t color)
-{
- if(x >= WIDTH_PIXELS || y >= HEIGHT) return;
- int offset = y * STRIDE_WORDS + x / 32;
- uint32_t *px = &p->pixels[offset * 3 + layer];
- uint32_t mask = 1 << ((x & 0x18) + (7 - (x & 0x7)));
- if(p->color_is_white[color])
- p->pixels[offset * 3 + layer] |= mask;
- else
- p->pixels[offset * 3 + layer] &= ~mask;
- if(layer) {
- if(color)
- p->pixels[offset * 3 + 2] |= mask;
- else
- p->pixels[offset * 3 + 2] &= ~mask;
- }
- render(p, offset, 1);
-}
-
-void
-ppu_clear(Ppu *p)
-{
- uint32_t background = p->color_is_white[0] ? 0xffffffff : 0;
- int i;
- for(i = 0; i < HEIGHT * STRIDE_WORDS * 3; i += 3) {
- p->pixels[i] = background;
- p->pixels[i + 2] = 0;
- }
-}
-
-static uint8_t blending[5][16] = {
- {0, 0, 0, 0, 1, 0, 1, 1, 2, 2, 0, 2, 3, 3, 3, 0},
- {0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3},
- {1, 2, 3, 1, 1, 2, 3, 1, 1, 2, 3, 1, 1, 2, 3, 1},
- {2, 3, 1, 2, 2, 3, 1, 2, 2, 3, 1, 2, 2, 3, 1, 2},
- {1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0}};
-
-void
-ppu_1bpp(Ppu *p, uint8_t layer, uint16_t x, uint16_t y, uint8_t *sprite, uint8_t color, uint8_t flipx, uint8_t flipy)
-{
- uint16_t v, h;
- for(v = 0; v < 8; v++)
- for(h = 0; h < 8; h++) {
- uint8_t ch1 = (sprite[v] >> (7 - h)) & 0x1;
- if(ch1 || blending[4][color])
- ppu_pixel(p,
- layer,
- x + (flipx ? 7 - h : h),
- y + (flipy ? 7 - v : v),
- blending[ch1][color]);
- }
-}
-
-void
-ppu_2bpp(Ppu *p, uint8_t layer, uint16_t x, uint16_t y, uint8_t *sprite, uint8_t color, uint8_t flipx, uint8_t flipy)
-{
- uint16_t v, h;
- for(v = 0; v < 8; v++)
- for(h = 0; h < 8; h++) {
- uint8_t ch1 = ((sprite[v] >> (7 - h)) & 0x1);
- uint8_t ch2 = ((sprite[v + 8] >> (7 - h)) & 0x1);
- uint8_t ch = ch1 + ch2 * 2;
- if(ch || blending[4][color])
- ppu_pixel(p,
- layer,
- x + (flipx ? 7 - h : h),
- y + (flipy ? 7 - v : v),
- blending[ch][color]);
- }
-}
D devices/ppu.h => devices/ppu.h +0 -46
@@ 1,46 0,0 @@
-/*
-Copyright (c) 2021 Devine Lu Linvega
-Copyright (c) 2021 Andrew Alderwick
-
-Permission to use, copy, modify, and distribute this software for any
-purpose with or without fee is hereby granted, provided that the above
-copyright notice and this permission notice appear in all copies.
-
-THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-WITH REGARD TO THIS SOFTWARE.
-*/
-
-#include <stdint.h>
-
-#define WIDTH_PIXELS 400
-#define STRIDE_PIXELS (52 * 8)
-#define STRIDE_WORDS (STRIDE_PIXELS / 32)
-#define HEIGHT 240
-
-/*
- * framebuffer is the Playdate's raw framebuffer.
- *
- * pixels is the buffer for Varvara's two graphics layers and are grouped in
- * three sets of 32 bits.
- *
- * pixels[0] carries the background color of the first 32 pixels,
- * pixels[1] carries the foreground color, and
- * pixels[2] carries the mask that switches between the two.
- *
- * Zero color bits are white, ones are black.
- * Zero mask bits mean that the background color is shown, one is for the
- * foreground color.
- */
-
-typedef struct Ppu {
- uint32_t pixels[HEIGHT * STRIDE_WORDS * 3];
- uint32_t *framebuffer;
- int color_is_white[4];
-} Ppu;
-
-int ppu_init(Ppu *p, uint32_t *framebuffer);
-void ppu_pixel(Ppu *p, uint8_t layer, uint16_t x, uint16_t y, uint8_t color);
-void ppu_1bpp(Ppu *p, uint8_t layer, uint16_t x, uint16_t y, uint8_t *sprite, uint8_t color, uint8_t flipx, uint8_t flipy);
-void ppu_2bpp(Ppu *p, uint8_t layer, uint16_t x, uint16_t y, uint8_t *sprite, uint8_t color, uint8_t flipx, uint8_t flipy);
-void ppu_clear(Ppu *p);
-void render_all(Ppu *p);
D main.c => main.c +0 -412
@@ 1,412 0,0 @@
-/*
-Copyright (c) 2021 Devine Lu Linvega
-Copyright (c) 2021 Andrew Alderwick
-
-Permission to use, copy, modify, and distribute this software for any
-purpose with or without fee is hereby granted, provided that the above
-copyright notice and this permission notice appear in all copies.
-
-THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-WITH REGARD TO THIS SOFTWARE.
-*/
-
-#include "pd_api.h"
-#include "uxn/src/uxn.h"
-#include "devices/apu.h"
-#include "devices/ppu.h"
-
-#define POLYPHONY 4
-#define BOOT_ROM_FILENAME "boot.rom"
-#define SNAPSHOT_FILENAME "uxn.sna"
-#define SNAPSHOT_VERSION 1
-
-static PlaydateAPI *pd = NULL;
-static SoundSource *apu_sources[POLYPHONY];
-static Uxn u;
-static Device *devctrl, *devconsole, *devscreen, *devmouse, *devdatetime, *devaudio0;
-static Ppu ppu;
-static Apu apu[POLYPHONY];
-
-static const char *errors[] = {"underflow", "overflow", "division by zero"};
-
-int
-uxn_halt(Uxn *u, Uint8 error, char *name, int id)
-{
- pd->system->error("Halted: %s %s#%04x, at 0x%04x\n", name, errors[error - 1], id, u->ram.ptr);
- u->ram.ptr = 0;
- return 0;
-}
-
-static void
-docolors(Device *d)
-{
- int i, sum;
- for(i = 0; i < 4; ++i) {
- sum = ((d->dat[0x8 + i / 2] >> (!(i % 2) << 2)) & 0x0f);
- sum += ((d->dat[0xa + i / 2] >> (!(i % 2) << 2)) & 0x0f);
- sum += ((d->dat[0xc + i / 2] >> (!(i % 2) << 2)) & 0x0f);
- ppu.color_is_white[i] = sum > 0x17;
- }
- ppu_clear(&ppu);
- render_all(&ppu);
-}
-
-static uint8_t
-getcolors(int i)
-{
- return (ppu.color_is_white[i] ? 0xf0 : 0) + (ppu.color_is_white[i + 1] ? 0x0f : 0);
-}
-
-static int
-system_talk(Device *d, Uint8 b0, Uint8 w)
-{
- if(!w) { /* read */
- switch(b0) {
- case 0x2: d->dat[0x2] = d->u->wst.ptr; break;
- case 0x3: d->dat[0x3] = d->u->rst.ptr; break;
- case 0x8 ... 0xd: d->dat[b0] = getcolors((b0 & 1) << 1); break;
- }
- } else { /* write */
- switch(b0) {
- case 0x2: d->u->wst.ptr = d->dat[0x2]; break;
- case 0x3: d->u->rst.ptr = d->dat[0x3]; break;
- case 0x8 ... 0xd: docolors(d); break;
- case 0xf: d->u->ram.ptr = 0x0000; break;
- }
- }
- return 1;
-}
-
-static int
-console_talk(Device *d, Uint8 b0, Uint8 w)
-{
- if(w && b0 > 0x7)
- pd->system->logToConsole("%c", d->dat[b0]);
- return 1;
-}
-
-static int
-screen_talk(Device *d, Uint8 b0, Uint8 w)
-{
-
- if(w && b0 == 0xe) {
- Uint16 x = peek16(d->dat, 0x8);
- Uint16 y = peek16(d->dat, 0xa);
- Uint8 layer = d->dat[0xe] & 0x40;
- ppu_pixel(&ppu, !!layer, x, y, d->dat[0xe] & 0x3);
- if(d->dat[0x6] & 0x01) poke16(d->dat, 0x8, x + 1); /* auto x+1 */
- if(d->dat[0x6] & 0x02) poke16(d->dat, 0xa, y + 1); /* auto y+1 */
- pd->graphics->markUpdatedRows(y, y);
- } else if(w && b0 == 0xf) {
- Uint16 x = peek16(d->dat, 0x8);
- Uint16 y = peek16(d->dat, 0xa);
- Uint8 layer = d->dat[0xf] & 0x40;
- Uint8 *addr = &d->mem[peek16(d->dat, 0xc)];
- if(d->dat[0xf] & 0x80) {
- ppu_2bpp(&ppu, !!layer, x, y, addr, d->dat[0xf] & 0xf, d->dat[0xf] & 0x10, d->dat[0xf] & 0x20);
- if(d->dat[0x6] & 0x04) poke16(d->dat, 0xc, peek16(d->dat, 0xc) + 16); /* auto addr+16 */
- } else {
- ppu_1bpp(&ppu, !!layer, x, y, addr, d->dat[0xf] & 0xf, d->dat[0xf] & 0x10, d->dat[0xf] & 0x20);
- if(d->dat[0x6] & 0x04) poke16(d->dat, 0xc, peek16(d->dat, 0xc) + 8); /* auto addr+8 */
- }
- if(d->dat[0x6] & 0x01) poke16(d->dat, 0x8, x + 8); /* auto x+8 */
- if(d->dat[0x6] & 0x02) poke16(d->dat, 0xa, y + 8); /* auto y+8 */
- pd->graphics->markUpdatedRows(y, y + 7);
- }
- return 1;
-}
-
-static int
-file_talk(Device *d, Uint8 b0, Uint8 w)
-{
- Uint8 read = b0 == 0xd;
- if(w && (read || b0 == 0xf)) {
- char *name = (char *)&d->mem[peek16(d->dat, 0x8)];
- Uint16 result = 0, length = peek16(d->dat, 0xa);
- Uint16 offset = peek16(d->dat, 0x4);
- Uint16 addr = peek16(d->dat, b0 - 1);
- SDFile *f = pd->file->open(name, read ? (kFileRead | kFileReadData) : (offset ? kFileAppend : kFileWrite));
- if(f) {
- pd->system->logToConsole("%s %s %s #%04x, ", read ? "Loading" : "Saving", name, read ? "to" : "from", addr);
- if(pd->file->seek(f, offset, SEEK_SET) != -1)
- result = read ? pd->file->read(f, &d->mem[addr], length) : pd->file->write(f, &d->mem[addr], length);
- pd->system->logToConsole("%04x bytes\n", result);
- pd->file->close(f);
- } else {
- pd->system->logToConsole("unable to open %s", name);
- }
- poke16(d->dat, 0x2, result);
- }
- return 1;
-}
-
-static int
-audio_talk(Device *d, Uint8 b0, Uint8 w)
-{
- Apu *c = &apu[d - devaudio0];
- if(!w) {
- if(b0 == 0x2)
- poke16(d->dat, 0x2, c->i);
- else if(b0 == 0x4)
- d->dat[0x4] = apu_get_vu(c);
- } else if(b0 == 0xf) {
- c->len = peek16(d->dat, 0xa);
- c->addr = peek16(d->dat, 0xc);
- c->volume[0] = d->dat[0xe] >> 4;
- c->volume[1] = d->dat[0xe] & 0xf;
- c->repeat = !(d->dat[0xf] & 0x80);
- apu_start(c, peek16(d->dat, 0x8), d->dat[0xf] & 0x7f);
- }
- return 1;
-}
-
-static int
-nil_talk(Device *d, Uint8 b0, Uint8 w)
-{
- (void)d;
- (void)b0;
- (void)w;
- return 1;
-}
-
-static int
-update_datetime(lua_State *L)
-{
- // DateTime
- int i;
- for(i = 0; i < 11; ++i)
- devdatetime->dat[i] = pd->lua->getArgInt(i + 1);
- return 0;
-}
-
-static int
-update_controller(lua_State *L)
-{
- // Buttons
- PDButtons state, pushed, released;
- pd->system->getButtonState(&state, &pushed, &released);
- if(pushed || released) {
- devctrl->dat[2] = 0x00;
- if(state & kButtonA)
- devctrl->dat[2] |= 0x01;
- if(state & kButtonB)
- devctrl->dat[2] |= 0x02;
- if(state & kButtonUp)
- devctrl->dat[2] |= 0x10;
- if(state & kButtonDown)
- devctrl->dat[2] |= 0x20;
- if(state & kButtonLeft)
- devctrl->dat[2] |= 0x40;
- if(state & kButtonRight)
- devctrl->dat[2] |= 0x80;
- uxn_eval(&u, peek16(devctrl->dat, 0));
- }
-
- // Crank
- unsigned char crank = pd->system->getCrankChange();
- if(crank) {
- devmouse->dat[7] = crank;
- uxn_eval(&u, peek16(devmouse->dat, 0));
- devmouse->dat[7] = 0x00;
- }
-
- return 0;
-}
-
-static int
-update_mouse(lua_State *L)
-{
- int i;
- for(i = 0; i < 5; ++i) {
- devmouse->dat[i + 2] = pd->lua->getArgInt(i + 1);
- }
- uxn_eval(&u, peek16(devmouse->dat, 0));
- return 0;
-}
-
-static int
-update_screen(lua_State *L)
-{
- uxn_eval(&u, peek16(devscreen->dat, 0));
- return 0;
-}
-
-static int
-audio_callback(void *context, int16_t *left, int16_t *right, int len)
-{
- return apu_render((Apu *)context, u.ram.dat, left, right, len);
-}
-
-static int
-varvara_init_once(void)
-{
- int i;
- SoundChannel *ch = pd->sound->getDefaultChannel();
- for(i = 0; i < POLYPHONY; ++i) {
- apu_sources[i] = pd->sound->channel->addCallbackSource(ch, audio_callback, &apu[i], 1);
- }
- pd->sound->channel->setVolume(ch, 1.0);
- pd->sound->channel->setPan(ch, 0.0);
- return 1;
-}
-
-static int
-post_load_init(void)
-{
- if(!ppu_init(&ppu, (uint32_t *)pd->graphics->getFrame()))
- return 0;
- render_all(&ppu);
-
- uxn_port(&u, 0x0, system_talk);
- devconsole = uxn_port(&u, 0x1, console_talk);
- devscreen = uxn_port(&u, 0x2, screen_talk);
- devaudio0 = uxn_port(&u, 0x3, audio_talk);
- uxn_port(&u, 0x4, audio_talk);
- uxn_port(&u, 0x5, audio_talk);
- uxn_port(&u, 0x6, audio_talk);
- uxn_port(&u, 0x7, nil_talk);
- devctrl = uxn_port(&u, 0x8, nil_talk);
- devmouse = uxn_port(&u, 0x9, nil_talk);
- uxn_port(&u, 0xa, file_talk);
- devdatetime = uxn_port(&u, 0xb, nil_talk);
- uxn_port(&u, 0xc, nil_talk);
- uxn_port(&u, 0xd, nil_talk);
- uxn_port(&u, 0xe, nil_talk);
- uxn_port(&u, 0xf, nil_talk);
-
- return 1;
-}
-
-static int
-load(Uxn *u, char *filepath)
-{
- SDFile *f = pd->file->open(filepath, kFileRead | kFileReadData);
- if(f == NULL) {
- pd->system->error("Failed to open rom.");
- return 0;
- }
- pd->file->read(f, u->ram.dat + PAGE_PROGRAM, sizeof(u->ram.dat) - PAGE_PROGRAM);
- pd->system->logToConsole("Loaded %s\n", filepath);
- return post_load_init();
-}
-
-static int
-reset(Uxn *u, char *filepath)
-{
- if(!uxn_boot(u)) {
- pd->system->error("Failed to start uxn.");
- return 0;
- }
- memset(&ppu, 0, sizeof(ppu));
- memset(&apu, 0, sizeof(apu));
- if(!load(u, filepath))
- return 0;
-
- poke16(devscreen->dat, 2, WIDTH_PIXELS);
- poke16(devscreen->dat, 4, HEIGHT);
-
- uxn_eval(u, PAGE_PROGRAM);
- return 1;
-}
-
-static int
-menu_reset(lua_State *L)
-{
- if(!reset(&u, BOOT_ROM_FILENAME))
- pd->system->error("Failed to reset Uxn.");
- return 0;
-}
-
-static int
-freeze(void)
-{
- SDFile *f = pd->file->open(SNAPSHOT_FILENAME, kFileWrite);
- if(f == NULL) {
- pd->system->error("Failed to open snapshot for writing.");
- return 0;
- }
- int version = SNAPSHOT_VERSION;
- /* clang-format off */
- if(pd->file->write(f, &version, sizeof(version)) != sizeof(version)
- || pd->file->write(f, &u, sizeof(u)) != sizeof(u)
- || pd->file->write(f, &ppu, sizeof(ppu)) != sizeof(ppu)
- || pd->file->write(f, &apu, sizeof(apu)) != sizeof(apu)) {
- pd->system->error("Failed to write snapshot data.");
- pd->file->close(f);
- return 0;
- }
- pd->file->close(f);
- /* clang-format on */
- return 1;
-}
-
-static int
-thaw(void)
-{
- SDFile *f = pd->file->open(SNAPSHOT_FILENAME, kFileRead | kFileReadData);
- if(f == NULL)
- return 0;
- int version;
- /* clang-format off */
- if(pd->file->read(f, &version, sizeof(version)) != sizeof(version)
- || pd->file->read(f, &u, sizeof(u)) != sizeof(u)
- || pd->file->read(f, &ppu, sizeof(ppu)) != sizeof(ppu)
- || pd->file->read(f, &apu, sizeof(apu)) != sizeof(apu)) {
- pd->file->close(f);
- return 0;
- }
- pd->file->close(f);
- /* clang-format on */
- if(version != SNAPSHOT_VERSION)
- return 0;
- return post_load_init();
-}
-
-struct lua_function_pair {
- lua_CFunction f;
- const char *name;
-};
-
-static struct lua_function_pair fns[] = {
- {update_datetime, "varvaraDateTime"},
- {update_controller, "varvaraController"},
- {update_mouse, "varvaraMouse"},
- {update_screen, "varvaraScreen"},
- {menu_reset, "varvaraReset"}};
-
-int
-eventHandler(PlaydateAPI *playdate, PDSystemEvent event, uint32_t arg)
-{
- switch(event) {
- case kEventInit:
- pd = playdate;
- pd->display->setRefreshRate(60);
-
- if(!varvara_init_once())
- pd->system->error("Failed to initialize Varvara.");
-
- if(!thaw() && !reset(&u, BOOT_ROM_FILENAME))
- pd->system->error("Failed to reset Uxn.");
-
- break;
-
- case kEventInitLua: {
- const char *err;
- int i;
- for(i = 0; i < sizeof(fns) / sizeof(struct lua_function_pair); ++i) {
- if(!pd->lua->addFunction(fns[i].f, fns[i].name, &err))
- pd->system->error("Failed to create function: %s", err);
- }
- break;
- }
-
- case kEventTerminate:
- case kEventLowPower:
- freeze();
- break;
-
- default:
- break;
- }
- return 0;
-}
M src/main.c => src/main.c +11 -14
@@ 8,19 8,6 @@ static PlaydateAPI *pd = NULL;
Uxn u;
Ppu ppu;
-/*
-static unsigned char rom[] = {
- 0xa0, 0x01, 0x39, 0x94, 0x80, 0x18, 0x17, 0x21, 0x94, 0x80, 0xf7, 0x0d, 0x22, 0x80, 0x22, 0x36,
- 0x80, 0x01, 0x3f, 0xa0, 0x00, 0x08, 0x39, 0x80, 0x28, 0x37, 0x80, 0x24, 0x36, 0x80, 0x01, 0x3f,
- 0xa0, 0x00, 0x08, 0x39, 0x80, 0x2a, 0x37, 0x80, 0x16, 0x80, 0x26, 0x17, 0xa0, 0x01, 0x47, 0x80,
- 0x2c, 0x37, 0x80, 0x01, 0x80, 0x2f, 0x97, 0x17, 0x00, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x57,
- 0x6f, 0x72, 0x6c, 0x64, 0x21, 0x0a, 0x00, 0x00, 0x07, 0x18, 0x20, 0x20, 0x40, 0x48, 0x48, 0x00,
- 0xe0, 0x18, 0x04, 0x04, 0x02, 0x12, 0x12, 0x40, 0x40, 0x44, 0x23, 0x20, 0x18, 0x07, 0x00, 0x02,
- 0x02, 0x22, 0xc4, 0x04, 0x18, 0xe0, 0x00
-};
-
-*/
-
unsigned char rom[] = {
0xa0, 0x4c, 0xfd, 0x80, 0x08, 0x37, 0xa0, 0x4c, 0xf3, 0x80, 0x0a, 0x37, 0xa0, 0xdc, 0xf2, 0x80,
0x0c, 0x37, 0xa0, 0x01, 0x4b, 0x80, 0x20, 0x37, 0x80, 0x22, 0x36, 0x80, 0x01, 0x3f, 0x80, 0x00,
@@ 41,7 28,6 @@ unsigned char rom[] = {
0x00, 0xf0, 0x00, 0x00, 0xe0, 0xfc, 0xfc, 0x80, 0x00,
};
-
/* Varvara */
static const char *errors[] = {
@@ 64,6 50,17 @@ emu_error(char *msg, const char *err)
}
static int
+load(Uxn *u, char *filepath)
+{
+ SDFile *f = pd->file->open(filepath, kFileRead | kFileReadData);
+ if(f == NULL)
+ return emu_error("Missing file", filepath);
+ pd->file->read(f, u->ram + PAGE_PROGRAM, sizeof(u->ram) - PAGE_PROGRAM);
+ pd->system->logToConsole("Loaded %s\n", filepath);
+ return 1;
+}
+
+static int
emu_load(unsigned char *r)
{
int i, len = sizeof(rom);