NJU-ProjectN/abstract-machine ics2023 initialized
NJU-ProjectN/abstract-machine 3348db971fd860be5cb28e21c18f9d0e65d0c96a Merge pull request #8 from Jasonyanyusong/master
This commit is contained in:
parent
2824efad33
commit
8e4feb4010
129 changed files with 9017 additions and 0 deletions
72
abstract-machine/am/src/native/ioe/audio.c
Normal file
72
abstract-machine/am/src/native/ioe/audio.c
Normal file
|
@ -0,0 +1,72 @@
|
|||
#define _GNU_SOURCE
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <klib.h>
|
||||
#include <SDL2/SDL.h>
|
||||
|
||||
static int rfd = -1, wfd = -1;
|
||||
static volatile int count = 0;
|
||||
|
||||
void __am_audio_init() {
|
||||
int fds[2];
|
||||
int ret = pipe2(fds, O_NONBLOCK);
|
||||
assert(ret == 0);
|
||||
rfd = fds[0];
|
||||
wfd = fds[1];
|
||||
}
|
||||
|
||||
static void audio_play(void *userdata, uint8_t *stream, int len) {
|
||||
int nread = len;
|
||||
if (count < len) nread = count;
|
||||
int b = 0;
|
||||
while (b < nread) {
|
||||
int n = read(rfd, stream, nread);
|
||||
if (n > 0) b += n;
|
||||
}
|
||||
|
||||
count -= nread;
|
||||
if (len > nread) {
|
||||
memset(stream + nread, 0, len - nread);
|
||||
}
|
||||
}
|
||||
|
||||
static void audio_write(uint8_t *buf, int len) {
|
||||
int nwrite = 0;
|
||||
while (nwrite < len) {
|
||||
int n = write(wfd, buf, len);
|
||||
if (n == -1) n = 0;
|
||||
count += n;
|
||||
nwrite += n;
|
||||
}
|
||||
}
|
||||
|
||||
void __am_audio_ctrl(AM_AUDIO_CTRL_T *ctrl) {
|
||||
SDL_AudioSpec s = {};
|
||||
s.freq = ctrl->freq;
|
||||
s.format = AUDIO_S16SYS;
|
||||
s.channels = ctrl->channels;
|
||||
s.samples = ctrl->samples;
|
||||
s.callback = audio_play;
|
||||
s.userdata = NULL;
|
||||
|
||||
count = 0;
|
||||
int ret = SDL_InitSubSystem(SDL_INIT_AUDIO);
|
||||
if (ret == 0) {
|
||||
SDL_OpenAudio(&s, NULL);
|
||||
SDL_PauseAudio(0);
|
||||
}
|
||||
}
|
||||
|
||||
void __am_audio_status(AM_AUDIO_STATUS_T *stat) {
|
||||
stat->count = count;
|
||||
}
|
||||
|
||||
void __am_audio_play(AM_AUDIO_PLAY_T *ctl) {
|
||||
int len = ctl->buf.end - ctl->buf.start;
|
||||
audio_write(ctl->buf.start, len);
|
||||
}
|
||||
|
||||
void __am_audio_config(AM_AUDIO_CONFIG_T *cfg) {
|
||||
cfg->present = true;
|
||||
cfg->bufsize = fcntl(rfd, F_GETPIPE_SZ);
|
||||
}
|
41
abstract-machine/am/src/native/ioe/disk.c
Normal file
41
abstract-machine/am/src/native/ioe/disk.c
Normal file
|
@ -0,0 +1,41 @@
|
|||
#include <am.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
||||
#define BLKSZ 512
|
||||
|
||||
static int disk_size = 0;
|
||||
static FILE *fp = NULL;
|
||||
|
||||
void __am_disk_init() {
|
||||
const char *diskimg = getenv("diskimg");
|
||||
if (diskimg) {
|
||||
fp = fopen(diskimg, "r+");
|
||||
if (fp) {
|
||||
fseek(fp, 0, SEEK_END);
|
||||
disk_size = (ftell(fp) + 511) / 512;
|
||||
rewind(fp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void __am_disk_config(AM_DISK_CONFIG_T *cfg) {
|
||||
cfg->present = (fp != NULL);
|
||||
cfg->blksz = BLKSZ;
|
||||
cfg->blkcnt = disk_size;
|
||||
}
|
||||
|
||||
void __am_disk_status(AM_DISK_STATUS_T *stat) {
|
||||
stat->ready = 1;
|
||||
}
|
||||
|
||||
void __am_disk_blkio(AM_DISK_BLKIO_T *io) {
|
||||
if (fp) {
|
||||
fseek(fp, io->blkno * BLKSZ, SEEK_SET);
|
||||
int ret;
|
||||
if (io->write) ret = fwrite(io->buf, io->blkcnt * BLKSZ, 1, fp);
|
||||
else ret = fread(io->buf, io->blkcnt * BLKSZ, 1, fp);
|
||||
assert(ret == 1);
|
||||
}
|
||||
}
|
66
abstract-machine/am/src/native/ioe/gpu.c
Normal file
66
abstract-machine/am/src/native/ioe/gpu.c
Normal file
|
@ -0,0 +1,66 @@
|
|||
#include <am.h>
|
||||
#include <SDL2/SDL.h>
|
||||
#include <fenv.h>
|
||||
|
||||
//#define MODE_800x600
|
||||
#ifdef MODE_800x600
|
||||
# define W 800
|
||||
# define H 600
|
||||
#else
|
||||
# define W 400
|
||||
# define H 300
|
||||
#endif
|
||||
|
||||
#define FPS 60
|
||||
|
||||
#define RMASK 0x00ff0000
|
||||
#define GMASK 0x0000ff00
|
||||
#define BMASK 0x000000ff
|
||||
#define AMASK 0x00000000
|
||||
|
||||
static SDL_Window *window = NULL;
|
||||
static SDL_Surface *surface = NULL;
|
||||
|
||||
static Uint32 texture_sync(Uint32 interval, void *param) {
|
||||
SDL_BlitScaled(surface, NULL, SDL_GetWindowSurface(window), NULL);
|
||||
SDL_UpdateWindowSurface(window);
|
||||
return interval;
|
||||
}
|
||||
|
||||
void __am_gpu_init() {
|
||||
SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER);
|
||||
window = SDL_CreateWindow("Native Application",
|
||||
SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
|
||||
#ifdef MODE_800x600
|
||||
W, H,
|
||||
#else
|
||||
W * 2, H * 2,
|
||||
#endif
|
||||
SDL_WINDOW_OPENGL);
|
||||
surface = SDL_CreateRGBSurface(SDL_SWSURFACE, W, H, 32,
|
||||
RMASK, GMASK, BMASK, AMASK);
|
||||
SDL_AddTimer(1000 / FPS, texture_sync, NULL);
|
||||
}
|
||||
|
||||
void __am_gpu_config(AM_GPU_CONFIG_T *cfg) {
|
||||
*cfg = (AM_GPU_CONFIG_T) {
|
||||
.present = true, .has_accel = false,
|
||||
.width = W, .height = H,
|
||||
.vmemsz = 0
|
||||
};
|
||||
}
|
||||
|
||||
void __am_gpu_status(AM_GPU_STATUS_T *stat) {
|
||||
stat->ready = true;
|
||||
}
|
||||
|
||||
void __am_gpu_fbdraw(AM_GPU_FBDRAW_T *ctl) {
|
||||
int x = ctl->x, y = ctl->y, w = ctl->w, h = ctl->h;
|
||||
if (w == 0 || h == 0) return;
|
||||
feclearexcept(-1);
|
||||
SDL_Surface *s = SDL_CreateRGBSurfaceFrom(ctl->pixels, w, h, 32, w * sizeof(uint32_t),
|
||||
RMASK, GMASK, BMASK, AMASK);
|
||||
SDL_Rect rect = { .x = x, .y = y };
|
||||
SDL_BlitSurface(s, NULL, surface, &rect);
|
||||
SDL_FreeSurface(s);
|
||||
}
|
63
abstract-machine/am/src/native/ioe/input.c
Normal file
63
abstract-machine/am/src/native/ioe/input.c
Normal file
|
@ -0,0 +1,63 @@
|
|||
#include <am.h>
|
||||
#include <SDL2/SDL.h>
|
||||
|
||||
#define KEYDOWN_MASK 0x8000
|
||||
|
||||
#define KEY_QUEUE_LEN 1024
|
||||
static int key_queue[KEY_QUEUE_LEN] = {};
|
||||
static int key_f = 0, key_r = 0;
|
||||
static SDL_mutex *key_queue_lock = NULL;
|
||||
|
||||
#define XX(k) [SDL_SCANCODE_##k] = AM_KEY_##k,
|
||||
static int keymap[256] = {
|
||||
AM_KEYS(XX)
|
||||
};
|
||||
|
||||
static int event_thread(void *args) {
|
||||
SDL_Event event;
|
||||
while (1) {
|
||||
SDL_WaitEvent(&event);
|
||||
switch (event.type) {
|
||||
case SDL_QUIT: halt(0);
|
||||
case SDL_KEYDOWN:
|
||||
case SDL_KEYUP: {
|
||||
SDL_Keysym k = event.key.keysym;
|
||||
int keydown = event.key.type == SDL_KEYDOWN;
|
||||
int scancode = k.scancode;
|
||||
if (keymap[scancode] != 0) {
|
||||
int am_code = keymap[scancode] | (keydown ? KEYDOWN_MASK : 0);
|
||||
SDL_LockMutex(key_queue_lock);
|
||||
key_queue[key_r] = am_code;
|
||||
key_r = (key_r + 1) % KEY_QUEUE_LEN;
|
||||
SDL_UnlockMutex(key_queue_lock);
|
||||
void __am_send_kbd_intr();
|
||||
__am_send_kbd_intr();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void __am_input_init() {
|
||||
key_queue_lock = SDL_CreateMutex();
|
||||
SDL_CreateThread(event_thread, "event thread", NULL);
|
||||
}
|
||||
|
||||
void __am_input_config(AM_INPUT_CONFIG_T *cfg) {
|
||||
cfg->present = true;
|
||||
}
|
||||
|
||||
void __am_input_keybrd(AM_INPUT_KEYBRD_T *kbd) {
|
||||
int k = AM_KEY_NONE;
|
||||
|
||||
SDL_LockMutex(key_queue_lock);
|
||||
if (key_f != key_r) {
|
||||
k = key_queue[key_f];
|
||||
key_f = (key_f + 1) % KEY_QUEUE_LEN;
|
||||
}
|
||||
SDL_UnlockMutex(key_queue_lock);
|
||||
|
||||
kbd->keydown = (k & KEYDOWN_MASK ? true : false);
|
||||
kbd->keycode = k & ~KEYDOWN_MASK;
|
||||
}
|
32
abstract-machine/am/src/native/ioe/timer.c
Normal file
32
abstract-machine/am/src/native/ioe/timer.c
Normal file
|
@ -0,0 +1,32 @@
|
|||
#include <am.h>
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
|
||||
static struct timeval boot_time = {};
|
||||
|
||||
void __am_timer_config(AM_TIMER_CONFIG_T *cfg) {
|
||||
cfg->present = cfg->has_rtc = true;
|
||||
}
|
||||
|
||||
void __am_timer_rtc(AM_TIMER_RTC_T *rtc) {
|
||||
time_t t = time(NULL);
|
||||
struct tm *tm = localtime(&t);
|
||||
rtc->second = tm->tm_sec;
|
||||
rtc->minute = tm->tm_min;
|
||||
rtc->hour = tm->tm_hour;
|
||||
rtc->day = tm->tm_mday;
|
||||
rtc->month = tm->tm_mon + 1;
|
||||
rtc->year = tm->tm_year + 1900;
|
||||
}
|
||||
|
||||
void __am_timer_uptime(AM_TIMER_UPTIME_T *uptime) {
|
||||
struct timeval now;
|
||||
gettimeofday(&now, NULL);
|
||||
long seconds = now.tv_sec - boot_time.tv_sec;
|
||||
long useconds = now.tv_usec - boot_time.tv_usec;
|
||||
uptime->us = seconds * 1000000 + (useconds + 500);
|
||||
}
|
||||
|
||||
void __am_timer_init() {
|
||||
gettimeofday(&boot_time, NULL);
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue