> compile NEMU
ysyx_22040000 李心杨 Linux calcite 6.6.19 #1-NixOS SMP PREEMPT_DYNAMIC Fri Mar 1 12:35:11 UTC 2024 x86_64 GNU/Linux 16:26:21 up 4 days 3:32, 2 users, load average: 0.85, 0.91, 0.95
This commit is contained in:
parent
a210694e82
commit
d08c2860da
415 changed files with 44314 additions and 11 deletions
23
am-kernels/kernels/bad-apple/Makefile
Normal file
23
am-kernels/kernels/bad-apple/Makefile
Normal file
|
@ -0,0 +1,23 @@
|
|||
VIDEO_ROW = 25
|
||||
VIDEO_COL = 80
|
||||
AUDIO_FREQ = 44100
|
||||
AUDIO_CHANNEL = 1
|
||||
|
||||
VIDEO_SRC = bad-apple.mp4
|
||||
VIDEO = build/video.frame
|
||||
AUDIO = build/audio.pcm
|
||||
|
||||
NAME = bad-apple
|
||||
SRCS = bad-apple.c resources.S
|
||||
include $(AM_HOME)/Makefile
|
||||
|
||||
CFLAGS += -DVIDEO_ROW=$(VIDEO_ROW) -DVIDEO_COL=$(VIDEO_COL) \
|
||||
-DAUDIO_FREQ=$(AUDIO_FREQ) -DAUDIO_CHANNEL=$(AUDIO_CHANNEL)
|
||||
ASFLAGS += -DVIDEO_FILE=\"$(abspath $(VIDEO))\" -DAUDIO_FILE=\"$(abspath $(AUDIO))\"
|
||||
$(VIDEO):
|
||||
ffmpeg -i $(VIDEO_SRC) -f image2pipe -s $(VIDEO_COL)x$(VIDEO_ROW) -vcodec rawvideo -pix_fmt monow $@
|
||||
|
||||
$(AUDIO):
|
||||
ffmpeg -i $(VIDEO_SRC) -vn -acodec pcm_s16le -f s16le -ac $(AUDIO_CHANNEL) -ar $(AUDIO_FREQ) $@
|
||||
|
||||
resources.S: $(VIDEO) $(AUDIO)
|
74
am-kernels/kernels/bad-apple/bad-apple.c
Normal file
74
am-kernels/kernels/bad-apple/bad-apple.c
Normal file
|
@ -0,0 +1,74 @@
|
|||
#include <am.h>
|
||||
#include <stdio.h>
|
||||
#include <klib-macros.h>
|
||||
|
||||
#define FPS 30
|
||||
#define CHAR_WHITE '.'
|
||||
#define CHAR_BLACK 'X'
|
||||
|
||||
typedef struct {
|
||||
uint8_t pixel[VIDEO_ROW * VIDEO_COL / 8];
|
||||
} frame_t;
|
||||
|
||||
static void sleep_until(uint64_t next) {
|
||||
while (io_read(AM_TIMER_UPTIME).us < next) ;
|
||||
}
|
||||
|
||||
static uint8_t getbit(uint8_t *p, int idx) {
|
||||
int byte_idx = idx / 8;
|
||||
int bit_idx = idx % 8;
|
||||
bit_idx = 7 - bit_idx;
|
||||
uint8_t byte = p[byte_idx];
|
||||
uint8_t bit = (byte >> bit_idx) & 1;
|
||||
return bit;
|
||||
}
|
||||
|
||||
int main() {
|
||||
extern uint8_t video_payload, video_payload_end;
|
||||
extern uint8_t audio_payload, audio_payload_end;
|
||||
int audio_len = 0, audio_left = 0;
|
||||
Area sbuf;
|
||||
|
||||
ioe_init();
|
||||
|
||||
frame_t *f = (void *)&video_payload;
|
||||
frame_t *fend = (void *)&video_payload_end;
|
||||
printf("\033[H\033[J"); // screan_clear
|
||||
|
||||
bool has_audio = io_read(AM_AUDIO_CONFIG).present;
|
||||
if (has_audio) {
|
||||
io_write(AM_AUDIO_CTRL, AUDIO_FREQ, AUDIO_CHANNEL, 1024);
|
||||
audio_left = audio_len = &audio_payload_end - &audio_payload;
|
||||
sbuf.start = &audio_payload;
|
||||
}
|
||||
|
||||
uint64_t now = io_read(AM_TIMER_UPTIME).us;
|
||||
for (; f < fend; f ++) {
|
||||
printf("\033[0;0H"); // reset cursor
|
||||
for (int y = 0; y < VIDEO_ROW; y++) {
|
||||
for (int x = 0; x < VIDEO_COL; x++) {
|
||||
uint8_t p = getbit(f->pixel, y * VIDEO_COL + x);
|
||||
putch(p ? CHAR_BLACK : CHAR_WHITE);
|
||||
}
|
||||
putch('\n');
|
||||
}
|
||||
|
||||
if (has_audio) {
|
||||
int should_play = (AUDIO_FREQ / FPS) * sizeof(int16_t);
|
||||
if (should_play > audio_left) should_play = audio_left;
|
||||
while (should_play > 0) {
|
||||
int len = (should_play > 4096 ? 4096 : should_play);
|
||||
sbuf.end = sbuf.start + len;
|
||||
io_write(AM_AUDIO_PLAY, sbuf);
|
||||
sbuf.start += len;
|
||||
should_play -= len;
|
||||
}
|
||||
audio_left -= should_play;
|
||||
}
|
||||
|
||||
uint64_t next = now + (1000 * 1000 / FPS);
|
||||
sleep_until(next);
|
||||
now = next;
|
||||
}
|
||||
return 0;
|
||||
}
|
BIN
am-kernels/kernels/bad-apple/bad-apple.mp4
Normal file
BIN
am-kernels/kernels/bad-apple/bad-apple.mp4
Normal file
Binary file not shown.
12
am-kernels/kernels/bad-apple/resources.S
Normal file
12
am-kernels/kernels/bad-apple/resources.S
Normal file
|
@ -0,0 +1,12 @@
|
|||
.section .data
|
||||
.global video_payload, video_payload_end
|
||||
.p2align 3
|
||||
video_payload:
|
||||
.incbin VIDEO_FILE
|
||||
video_payload_end:
|
||||
|
||||
.global audio_payload, audio_payload_end
|
||||
.p2align 3
|
||||
audio_payload:
|
||||
.incbin AUDIO_FILE
|
||||
audio_payload_end:
|
3
am-kernels/kernels/demo/Makefile
Normal file
3
am-kernels/kernels/demo/Makefile
Normal file
|
@ -0,0 +1,3 @@
|
|||
NAME = demo
|
||||
SRCS = $(shell find src -name "*.c")
|
||||
include $(AM_HOME)/Makefile
|
97
am-kernels/kernels/demo/include/io.h
Normal file
97
am-kernels/kernels/demo/include/io.h
Normal file
|
@ -0,0 +1,97 @@
|
|||
#ifndef __DRAW_H__
|
||||
|
||||
#define HAS_GUI
|
||||
|
||||
#include <stdio.h>
|
||||
#include <am.h>
|
||||
#include <amdev.h>
|
||||
#include <klib-macros.h>
|
||||
|
||||
#define ANSI_COLOR_RED 31
|
||||
#define ANSI_COLOR_GREEN 32
|
||||
#define ANSI_COLOR_WHITE 37
|
||||
#define ANSI_COLOR_RESET 0
|
||||
|
||||
#ifdef HAS_GUI
|
||||
#define TILE_W 4
|
||||
#define SCREEN_W 320
|
||||
#define SCREEN_H 200
|
||||
static inline void set_color(int c) {
|
||||
}
|
||||
|
||||
static inline void print_char(char c, int y, int x) {
|
||||
static char last_c = 0xff;
|
||||
static uint32_t buf[TILE_W * TILE_W];
|
||||
if (last_c != c) {
|
||||
last_c = c;
|
||||
uint32_t color = 0x0;
|
||||
if (c != ' ') { // convert different character to different color
|
||||
uint8_t r = c / 25;
|
||||
c -= r * 25;
|
||||
uint8_t g = c / 5;
|
||||
c -= g * 5;
|
||||
uint8_t b = c;
|
||||
r = r * 0x100 / 5;
|
||||
g = g * 0x100 / 5;
|
||||
b = b * 0x100 / 5;
|
||||
color = (r << 16) | (g << 8) | b;
|
||||
}
|
||||
int i;
|
||||
for (i = 0; i < TILE_W * TILE_W; i ++) {
|
||||
buf[i] = color;
|
||||
}
|
||||
}
|
||||
io_write(AM_GPU_FBDRAW, x * TILE_W, y * TILE_W, buf, TILE_W, TILE_W, false);
|
||||
}
|
||||
|
||||
static inline void screen_clear() {
|
||||
static uint32_t buf[SCREEN_W];
|
||||
int i;
|
||||
for (i = 0; i < SCREEN_H; i ++) {
|
||||
io_write(AM_GPU_FBDRAW, 0, i, buf, SCREEN_W, 1, false);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void screen_refresh() {
|
||||
io_write(AM_GPU_FBDRAW, 0, 0, NULL, 0, 0, true);
|
||||
}
|
||||
|
||||
static inline int screen_tile_height() {
|
||||
return io_read(AM_GPU_CONFIG).height / TILE_W;
|
||||
}
|
||||
|
||||
static inline int screen_tile_width() {
|
||||
return io_read(AM_GPU_CONFIG).width / TILE_W;
|
||||
}
|
||||
#else
|
||||
static inline void set_color(int c) {
|
||||
printf("\033[%dm", c);
|
||||
}
|
||||
|
||||
static inline void print_char(char c, int y, int x) {
|
||||
printf("\033[%d;%dH%c", y + 1, x + 1, c);
|
||||
}
|
||||
|
||||
static inline void screen_clear() {
|
||||
printf("\033[H\033[J");
|
||||
}
|
||||
|
||||
static inline void screen_refresh() {
|
||||
}
|
||||
|
||||
static inline int screen_tile_height() {
|
||||
return 24;
|
||||
}
|
||||
|
||||
static inline int screen_tile_width() {
|
||||
return 80;
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline void usleep(int us) {
|
||||
uint64_t now = io_read(AM_TIMER_UPTIME).us;
|
||||
uint64_t next = now + us;
|
||||
while (io_read(AM_TIMER_UPTIME).us < next) ;
|
||||
}
|
||||
|
||||
#endif
|
219
am-kernels/kernels/demo/src/aclock/aclock.c
Normal file
219
am-kernels/kernels/demo/src/aclock/aclock.c
Normal file
|
@ -0,0 +1,219 @@
|
|||
/*
|
||||
* aclock - ascii clock for vt100 terminals
|
||||
* failsafe mode:
|
||||
* > no curses / termcap required
|
||||
* > no floating point required
|
||||
* > no ANSI C compiler required
|
||||
*
|
||||
* Copyright (c) 2002 Antoni Sawicki <tenox@tenox.tc>
|
||||
* Version 1.8 (knr-nofloat-vt100); Dublin, June 2002
|
||||
*
|
||||
* Compilation: cc aclock-vt100.c -o aclock
|
||||
*
|
||||
* https://github.com/tenox7/aclock/blob/master/sources/aclock-vt100.c
|
||||
*
|
||||
* 2021-03-26 Meco Man port to RT-Thread
|
||||
*
|
||||
*/
|
||||
|
||||
#include <am.h>
|
||||
#include <amdev.h>
|
||||
#include <klib-macros.h>
|
||||
#include <io.h>
|
||||
|
||||
static const int minute[60][8][2] = {
|
||||
{ { 39,11 },{ 39,10 },{ 39,9 },{ 39,8 },{ 39,7 },{ 39,6 },{ 39,5 },{ 39,4 } },
|
||||
{ { 40,11 },{ 40,10 },{ 40,9 },{ 40,8 },{ 41,7 },{ 41,6 },{ 41,5 },{ 41,4 } },
|
||||
{ { 40,11 },{ 40,10 },{ 41,9 },{ 41,8 },{ 42,7 },{ 42,6 },{ 42,5 },{ 43,4 } },
|
||||
{ { 40,11 },{ 41,10 },{ 41,9 },{ 42,8 },{ 43,7 },{ 43,6 },{ 44,5 },{ 44,4 } },
|
||||
{ { 40,11 },{ 41,10 },{ 42,9 },{ 43,8 },{ 44,7 },{ 44,6 },{ 45,5 },{ 46,4 } },
|
||||
{ { 40,11 },{ 41,10 },{ 42,9 },{ 43,8 },{ 44,7 },{ 45,6 },{ 46,5 },{ 47,5 } },
|
||||
{ { 41,11 },{ 42,10 },{ 43,9 },{ 44,8 },{ 45,7 },{ 47,7 },{ 48,6 },{ 49,5 } },
|
||||
{ { 41,11 },{ 42,10 },{ 44,9 },{ 45,9 },{ 46,8 },{ 48,7 },{ 49,6 },{ 50,6 } },
|
||||
{ { 41,11 },{ 42,10 },{ 44,9 },{ 45,9 },{ 47,8 },{ 48,7 },{ 50,7 },{ 51,6 } },
|
||||
{ { 41,11 },{ 43,10 },{ 44,10 },{ 46,9 },{ 48,9 },{ 49,8 },{ 51,7 },{ 52,7 } },
|
||||
{ { 41,11 },{ 43,10 },{ 45,10 },{ 46,9 },{ 48,9 },{ 50,8 },{ 52,8 },{ 53,7 } },
|
||||
{ { 41,11 },{ 43,11 },{ 45,10 },{ 47,10 },{ 49,9 },{ 50,9 },{ 52,9 },{ 54,8 } },
|
||||
{ { 41,11 },{ 43,11 },{ 45,11 },{ 47,10 },{ 49,10 },{ 51,10 },{ 53,9 },{ 55,9 } },
|
||||
{ { 41,11 },{ 43,11 },{ 45,11 },{ 47,11 },{ 49,10 },{ 51,10 },{ 53,10 },{ 55,10 } },
|
||||
{ { 41,11 },{ 43,11 },{ 45,11 },{ 47,11 },{ 49,11 },{ 51,11 },{ 53,11 },{ 55,11 } },
|
||||
{ { 42,12 },{ 44,12 },{ 46,12 },{ 48,12 },{ 50,12 },{ 52,12 },{ 54,12 },{ 56,12 } },
|
||||
{ { 41,12 },{ 43,12 },{ 45,12 },{ 47,12 },{ 49,12 },{ 51,12 },{ 53,12 },{ 55,12 } },
|
||||
{ { 41,12 },{ 43,12 },{ 45,12 },{ 47,12 },{ 49,13 },{ 51,13 },{ 53,13 },{ 55,13 } },
|
||||
{ { 41,12 },{ 43,12 },{ 45,12 },{ 47,13 },{ 49,13 },{ 51,13 },{ 53,14 },{ 55,14 } },
|
||||
{ { 41,12 },{ 43,12 },{ 45,13 },{ 47,13 },{ 49,14 },{ 50,14 },{ 52,14 },{ 54,15 } },
|
||||
{ { 41,12 },{ 43,13 },{ 45,13 },{ 46,14 },{ 48,14 },{ 50,15 },{ 52,15 },{ 53,16 } },
|
||||
{ { 41,12 },{ 43,13 },{ 44,13 },{ 46,14 },{ 48,14 },{ 49,15 },{ 51,16 },{ 52,16 } },
|
||||
{ { 41,12 },{ 42,13 },{ 44,14 },{ 45,14 },{ 47,15 },{ 48,16 },{ 50,16 },{ 51,17 } },
|
||||
{ { 41,12 },{ 42,13 },{ 44,14 },{ 45,14 },{ 46,15 },{ 48,16 },{ 49,17 },{ 50,17 } },
|
||||
{ { 41,12 },{ 42,13 },{ 43,14 },{ 44,15 },{ 45,16 },{ 47,16 },{ 48,17 },{ 49,18 } },
|
||||
{ { 40,12 },{ 41,13 },{ 42,14 },{ 43,15 },{ 44,16 },{ 45,17 },{ 46,18 },{ 47,18 } },
|
||||
{ { 40,12 },{ 41,13 },{ 42,14 },{ 43,15 },{ 44,16 },{ 44,17 },{ 45,18 },{ 46,19 } },
|
||||
{ { 40,12 },{ 41,13 },{ 41,14 },{ 42,15 },{ 43,16 },{ 43,17 },{ 44,18 },{ 44,19 } },
|
||||
{ { 40,12 },{ 40,13 },{ 41,14 },{ 41,15 },{ 42,16 },{ 42,17 },{ 42,18 },{ 43,19 } },
|
||||
{ { 40,12 },{ 40,13 },{ 40,14 },{ 40,15 },{ 41,16 },{ 41,17 },{ 41,18 },{ 41,19 } },
|
||||
{ { 39,12 },{ 39,13 },{ 39,14 },{ 39,15 },{ 39,16 },{ 39,17 },{ 39,18 },{ 39,19 } },
|
||||
{ { 39,12 },{ 39,13 },{ 39,14 },{ 39,15 },{ 38,16 },{ 38,17 },{ 38,18 },{ 38,19 } },
|
||||
{ { 39,12 },{ 39,13 },{ 38,14 },{ 38,15 },{ 37,16 },{ 37,17 },{ 37,18 },{ 36,19 } },
|
||||
{ { 39,12 },{ 38,13 },{ 38,14 },{ 37,15 },{ 36,16 },{ 36,17 },{ 35,18 },{ 35,19 } },
|
||||
{ { 39,12 },{ 38,13 },{ 37,14 },{ 36,15 },{ 35,16 },{ 35,17 },{ 34,18 },{ 33,19 } },
|
||||
{ { 38,12 },{ 37,13 },{ 36,14 },{ 35,15 },{ 34,16 },{ 33,17 },{ 32,18 },{ 31,18 } },
|
||||
{ { 38,12 },{ 37,13 },{ 36,14 },{ 35,15 },{ 34,16 },{ 32,16 },{ 31,17 },{ 30,18 } },
|
||||
{ { 38,12 },{ 37,13 },{ 35,14 },{ 34,14 },{ 33,15 },{ 31,16 },{ 30,17 },{ 29,17 } },
|
||||
{ { 38,12 },{ 37,13 },{ 35,14 },{ 34,14 },{ 32,15 },{ 31,16 },{ 29,16 },{ 28,17 } },
|
||||
{ { 38,12 },{ 36,13 },{ 35,13 },{ 33,14 },{ 31,14 },{ 30,15 },{ 28,16 },{ 27,16 } },
|
||||
{ { 38,12 },{ 36,13 },{ 34,13 },{ 33,14 },{ 31,14 },{ 29,15 },{ 27,15 },{ 26,16 } },
|
||||
{ { 38,12 },{ 36,12 },{ 34,13 },{ 32,13 },{ 30,14 },{ 29,14 },{ 27,14 },{ 25,15 } },
|
||||
{ { 38,12 },{ 36,12 },{ 34,12 },{ 32,13 },{ 30,13 },{ 28,13 },{ 26,14 },{ 24,14 } },
|
||||
{ { 38,12 },{ 36,12 },{ 34,12 },{ 32,12 },{ 30,13 },{ 28,13 },{ 26,13 },{ 24,13 } },
|
||||
{ { 38,12 },{ 36,12 },{ 34,12 },{ 32,12 },{ 30,12 },{ 28,12 },{ 26,12 },{ 24,12 } },
|
||||
{ { 38,11 },{ 36,11 },{ 34,11 },{ 32,11 },{ 30,11 },{ 28,11 },{ 26,11 },{ 24,11 } },
|
||||
{ { 38,11 },{ 36,11 },{ 34,11 },{ 32,11 },{ 30,11 },{ 28,11 },{ 26,11 },{ 24,11 } },
|
||||
{ { 38,11 },{ 36,11 },{ 34,11 },{ 32,11 },{ 30,10 },{ 28,10 },{ 26,10 },{ 24,10 } },
|
||||
{ { 38,11 },{ 36,11 },{ 34,11 },{ 32,10 },{ 30,10 },{ 28,10 },{ 26,9 },{ 24,9 } },
|
||||
{ { 38,11 },{ 36,11 },{ 34,10 },{ 32,10 },{ 30,9 },{ 29,9 },{ 27,9 },{ 25,8 } },
|
||||
{ { 38,11 },{ 36,11 },{ 34,10 },{ 33,10 },{ 31,9 },{ 29,9 },{ 27,8 },{ 26,8 } },
|
||||
{ { 38,11 },{ 36,10 },{ 35,10 },{ 33,9 },{ 31,9 },{ 30,8 },{ 28,7 },{ 27,7 } },
|
||||
{ { 38,11 },{ 37,10 },{ 35,9 },{ 34,9 },{ 32,8 },{ 31,7 },{ 29,7 },{ 28,6 } },
|
||||
{ { 38,11 },{ 37,10 },{ 35,9 },{ 34,9 },{ 33,8 },{ 31,7 },{ 30,6 },{ 29,6 } },
|
||||
{ { 38,11 },{ 37,10 },{ 36,9 },{ 35,8 },{ 34,7 },{ 32,7 },{ 31,6 },{ 30,5 } },
|
||||
{ { 39,11 },{ 38,10 },{ 37,9 },{ 36,8 },{ 35,7 },{ 34,6 },{ 33,5 },{ 32,5 } },
|
||||
{ { 39,11 },{ 38,10 },{ 37,9 },{ 36,8 },{ 35,7 },{ 35,6 },{ 34,5 },{ 33,4 } },
|
||||
{ { 39,11 },{ 38,10 },{ 38,9 },{ 37,8 },{ 36,7 },{ 36,6 },{ 35,5 },{ 35,4 } },
|
||||
{ { 39,11 },{ 39,10 },{ 38,9 },{ 38,8 },{ 37,7 },{ 37,6 },{ 37,5 },{ 36,4 } },
|
||||
{ { 39,11 },{ 39,10 },{ 39,9 },{ 39,8 },{ 38,7 },{ 38,6 },{ 38,5 },{ 38,4 } }
|
||||
};
|
||||
|
||||
static const int hour[60][6][2] = {
|
||||
{ { 39,11 },{ 39,10 },{ 39,9 },{ 39,8 },{ 39,7 },{ 39,6 } },
|
||||
{ { 40,11 },{ 40,10 },{ 40,9 },{ 40,8 },{ 41,7 },{ 41,6 } },
|
||||
{ { 40,11 },{ 40,10 },{ 41,9 },{ 41,8 },{ 42,7 },{ 42,6 } },
|
||||
{ { 40,11 },{ 41,10 },{ 41,9 },{ 42,8 },{ 43,7 },{ 43,6 } },
|
||||
{ { 40,11 },{ 41,10 },{ 42,9 },{ 43,8 },{ 44,7 },{ 44,6 } },
|
||||
{ { 40,11 },{ 41,10 },{ 42,9 },{ 43,8 },{ 44,7 },{ 45,6 } },
|
||||
{ { 41,11 },{ 42,10 },{ 43,9 },{ 44,8 },{ 45,7 },{ 47,7 } },
|
||||
{ { 41,11 },{ 42,10 },{ 44,9 },{ 45,9 },{ 46,8 },{ 48,7 } },
|
||||
{ { 41,11 },{ 42,10 },{ 44,9 },{ 45,9 },{ 47,8 },{ 48,7 } },
|
||||
{ { 41,11 },{ 43,10 },{ 44,10 },{ 46,9 },{ 48,9 },{ 49,8 } },
|
||||
{ { 41,11 },{ 43,10 },{ 45,10 },{ 46,9 },{ 48,9 },{ 50,8 } },
|
||||
{ { 41,11 },{ 43,11 },{ 45,10 },{ 47,10 },{ 49,9 },{ 50,9 } },
|
||||
{ { 41,11 },{ 43,11 },{ 45,11 },{ 47,10 },{ 49,10 },{ 51,10 } },
|
||||
{ { 41,11 },{ 43,11 },{ 45,11 },{ 47,11 },{ 49,10 },{ 51,10 } },
|
||||
{ { 41,11 },{ 43,11 },{ 45,11 },{ 47,11 },{ 49,11 },{ 51,11 } },
|
||||
{ { 42,12 },{ 44,12 },{ 46,12 },{ 48,12 },{ 50,12 },{ 52,12 } },
|
||||
{ { 41,12 },{ 43,12 },{ 45,12 },{ 47,12 },{ 49,12 },{ 51,12 } },
|
||||
{ { 41,12 },{ 43,12 },{ 45,12 },{ 47,12 },{ 49,13 },{ 51,13 } },
|
||||
{ { 41,12 },{ 43,12 },{ 45,12 },{ 47,13 },{ 49,13 },{ 51,13 } },
|
||||
{ { 41,12 },{ 43,12 },{ 45,13 },{ 47,13 },{ 49,14 },{ 50,14 } },
|
||||
{ { 41,12 },{ 43,13 },{ 45,13 },{ 46,14 },{ 48,14 },{ 50,15 } },
|
||||
{ { 41,12 },{ 43,13 },{ 44,13 },{ 46,14 },{ 48,14 },{ 49,15 } },
|
||||
{ { 41,12 },{ 42,13 },{ 44,14 },{ 45,14 },{ 47,15 },{ 48,16 } },
|
||||
{ { 41,12 },{ 42,13 },{ 44,14 },{ 45,14 },{ 46,15 },{ 48,16 } },
|
||||
{ { 41,12 },{ 42,13 },{ 43,14 },{ 44,15 },{ 45,16 },{ 47,16 } },
|
||||
{ { 40,12 },{ 41,13 },{ 42,14 },{ 43,15 },{ 44,16 },{ 45,17 } },
|
||||
{ { 40,12 },{ 41,13 },{ 42,14 },{ 43,15 },{ 44,16 },{ 44,17 } },
|
||||
{ { 40,12 },{ 41,13 },{ 41,14 },{ 42,15 },{ 43,16 },{ 43,17 } },
|
||||
{ { 40,12 },{ 40,13 },{ 41,14 },{ 41,15 },{ 42,16 },{ 42,17 } },
|
||||
{ { 40,12 },{ 40,13 },{ 40,14 },{ 40,15 },{ 41,16 },{ 41,17 } },
|
||||
{ { 39,12 },{ 39,13 },{ 39,14 },{ 39,15 },{ 39,16 },{ 39,17 } },
|
||||
{ { 39,12 },{ 39,13 },{ 39,14 },{ 39,15 },{ 38,16 },{ 38,17 } },
|
||||
{ { 39,12 },{ 39,13 },{ 38,14 },{ 38,15 },{ 37,16 },{ 37,17 } },
|
||||
{ { 39,12 },{ 38,13 },{ 38,14 },{ 37,15 },{ 36,16 },{ 36,17 } },
|
||||
{ { 39,12 },{ 38,13 },{ 37,14 },{ 36,15 },{ 35,16 },{ 35,17 } },
|
||||
{ { 38,12 },{ 37,13 },{ 36,14 },{ 35,15 },{ 34,16 },{ 33,17 } },
|
||||
{ { 38,12 },{ 37,13 },{ 36,14 },{ 35,15 },{ 34,16 },{ 32,16 } },
|
||||
{ { 38,12 },{ 37,13 },{ 35,14 },{ 34,14 },{ 33,15 },{ 31,16 } },
|
||||
{ { 38,12 },{ 37,13 },{ 35,14 },{ 34,14 },{ 32,15 },{ 31,16 } },
|
||||
{ { 38,12 },{ 36,13 },{ 35,13 },{ 33,14 },{ 31,14 },{ 30,15 } },
|
||||
{ { 38,12 },{ 36,13 },{ 34,13 },{ 33,14 },{ 31,14 },{ 29,15 } },
|
||||
{ { 38,12 },{ 36,12 },{ 34,13 },{ 32,13 },{ 30,14 },{ 29,14 } },
|
||||
{ { 38,12 },{ 36,12 },{ 34,12 },{ 32,13 },{ 30,13 },{ 28,13 } },
|
||||
{ { 38,12 },{ 36,12 },{ 34,12 },{ 32,12 },{ 30,13 },{ 28,13 } },
|
||||
{ { 38,12 },{ 36,12 },{ 34,12 },{ 32,12 },{ 30,12 },{ 28,12 } },
|
||||
{ { 38,11 },{ 36,11 },{ 34,11 },{ 32,11 },{ 30,11 },{ 28,11 } },
|
||||
{ { 38,11 },{ 36,11 },{ 34,11 },{ 32,11 },{ 30,11 },{ 28,11 } },
|
||||
{ { 38,11 },{ 36,11 },{ 34,11 },{ 32,11 },{ 30,10 },{ 28,10 } },
|
||||
{ { 38,11 },{ 36,11 },{ 34,11 },{ 32,10 },{ 30,10 },{ 28,10 } },
|
||||
{ { 38,11 },{ 36,11 },{ 34,10 },{ 32,10 },{ 30,9 },{ 29,9 } },
|
||||
{ { 38,11 },{ 36,11 },{ 34,10 },{ 33,10 },{ 31,9 },{ 29,9 } },
|
||||
{ { 38,11 },{ 36,10 },{ 35,10 },{ 33,9 },{ 31,9 },{ 30,8 } },
|
||||
{ { 38,11 },{ 37,10 },{ 35,9 },{ 34,9 },{ 32,8 },{ 31,7 } },
|
||||
{ { 38,11 },{ 37,10 },{ 35,9 },{ 34,9 },{ 33,8 },{ 31,7 } },
|
||||
{ { 38,11 },{ 37,10 },{ 36,9 },{ 35,8 },{ 34,7 },{ 32,7 } },
|
||||
{ { 39,11 },{ 38,10 },{ 37,9 },{ 36,8 },{ 35,7 },{ 34,6 } },
|
||||
{ { 39,11 },{ 38,10 },{ 37,9 },{ 36,8 },{ 35,7 },{ 35,6 } },
|
||||
{ { 39,11 },{ 38,10 },{ 38,9 },{ 37,8 },{ 36,7 },{ 36,6 } },
|
||||
{ { 39,11 },{ 39,10 },{ 38,9 },{ 38,8 },{ 37,7 },{ 37,6 } },
|
||||
{ { 39,11 },{ 39,10 },{ 39,9 },{ 39,8 },{ 38,7 },{ 38,6 } }
|
||||
};
|
||||
|
||||
static const int circle[60][3] = {
|
||||
{ 62,12,111 }, { 61,13,46 }, { 61,14,46 }, { 60,15,46 },
|
||||
{ 60,16,46 }, { 59,17,111 }, { 57,18,46 }, { 56,19,46 },
|
||||
{ 54,20,46 }, { 52,20,46 }, { 51,21,111 }, { 48,22,46 },
|
||||
{ 46,22,46 }, { 44,22,46 }, { 42,22,46 }, { 40,23,111 },
|
||||
{ 37,22,46 }, { 35,22,46 }, { 33,22,46 }, { 31,22,46 },
|
||||
{ 29,21,111 }, { 27,20,46 }, { 25,20,46 }, { 23,19,46 },
|
||||
{ 22,18,46 }, { 20,17,111 }, { 19,16,46 }, { 19,15,46 },
|
||||
{ 18,14,46 }, { 18,13,46 }, { 18,12,111 }, { 18,10,46 },
|
||||
{ 18,9,46 }, { 19,8,46 }, { 19,7,46 }, { 20,6,111 },
|
||||
{ 22,5,46 }, { 23,4,46 }, { 25,3,46 }, { 27,3,46 },
|
||||
{ 28,2,111 }, { 31,1,46 }, { 33,1,46 }, { 35,1,46 },
|
||||
{ 37,1,46 }, { 39,1,111 }, { 42,1,46 }, { 44,1,46 },
|
||||
{ 46,1,46 }, { 48,1,46 }, { 51,2,111 }, { 52,3,46 },
|
||||
{ 54,3,46 }, { 56,4,46 }, { 57,5,46 }, { 59,6,111 },
|
||||
{ 60,7,46 }, { 60,8,46 }, { 61,9,46 }, { 61,10,46 }
|
||||
};
|
||||
|
||||
|
||||
static void draw_point(int x, int y, int c) {
|
||||
int xx = x - 16;
|
||||
#ifdef HAS_GUI
|
||||
xx /= 2;
|
||||
#endif
|
||||
print_char(c, y, xx);
|
||||
}
|
||||
|
||||
//void draw_text(int x, int y, char *string) {
|
||||
// rt_kprintf("\033[%d;%dH%s", y, x, string);
|
||||
//}
|
||||
|
||||
static void draw_circle(void) {
|
||||
int n;
|
||||
for(n=0;n<60;n++)
|
||||
draw_point(circle[n][0], circle[n][1], circle[n][2]);
|
||||
}
|
||||
|
||||
static void draw_hour(int n) {
|
||||
int m;
|
||||
for(m=0;m<6;m++)
|
||||
draw_point(hour[n][m][0], hour[n][m][1], 'h');
|
||||
}
|
||||
|
||||
static void draw_minute(int n) {
|
||||
int m;
|
||||
for(m=0;m<8;m++)
|
||||
draw_point(minute[n][m][0], minute[n][m][1], 'M');
|
||||
}
|
||||
|
||||
static void draw_seconds(int n) {
|
||||
int m;
|
||||
for(m=0;m<8;m++)
|
||||
draw_point(minute[n][m][0], minute[n][m][1], '.');
|
||||
}
|
||||
|
||||
void aclock(void) {
|
||||
while(1) {
|
||||
AM_TIMER_RTC_T rtc = io_read(AM_TIMER_RTC);
|
||||
screen_clear();
|
||||
draw_circle();
|
||||
draw_hour(((rtc.hour > 12 ? rtc.hour - 12 : rtc.hour) * 5) + (rtc.minute / 10));
|
||||
draw_minute(rtc.minute);
|
||||
draw_seconds(rtc.second);
|
||||
screen_refresh();
|
||||
//draw_text(35, 6, ".:ACLOCK:.");
|
||||
//rt_sprintf(digital_time, "[%02d:%02d:%02d]", ltime->tm_hour, ltime->tm_min, ltime->tm_sec);
|
||||
//draw_text(35, 19, digital_time);
|
||||
usleep(1000000);
|
||||
}
|
||||
}
|
70
am-kernels/kernels/demo/src/ant/ant.c
Normal file
70
am-kernels/kernels/demo/src/ant/ant.c
Normal file
|
@ -0,0 +1,70 @@
|
|||
/* from http://rosettacode.org/wiki/Langton%27s_ant#C */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <io.h>
|
||||
|
||||
static int w = 40, h = 25;
|
||||
|
||||
static unsigned char *pix = NULL;
|
||||
|
||||
static void refresh(int x, int y) {
|
||||
int i, j, k;
|
||||
screen_clear();
|
||||
for (i = k = 0; i < h; i++)
|
||||
for (j = 0; j < w; j++, k++)
|
||||
print_char(pix[k] ? '#' : ' ', i, j);
|
||||
}
|
||||
|
||||
void ant() {
|
||||
w = screen_tile_width();
|
||||
h = screen_tile_height();
|
||||
|
||||
int dx = 0, dy = 1, i, k;
|
||||
int x = w / 2, y = h / 2;
|
||||
|
||||
pix = malloc(w * h);
|
||||
memset(pix, 0, w * h);
|
||||
screen_clear();
|
||||
|
||||
while (1) {
|
||||
i = (y * w + x);
|
||||
if (pix[i]) k = dx, dx = -dy, dy = k;
|
||||
else k = dy, dy = -dx, dx = k;
|
||||
|
||||
pix[i] = !pix[i];
|
||||
print_char(pix[i] ? 'o' : ' ', y + 1, x + 1);
|
||||
|
||||
x += dx, y += dy;
|
||||
|
||||
k = 0;
|
||||
if (x < 0) {
|
||||
memmove(pix + 1, pix, w * h - 1);
|
||||
for (i = 0; i < w * h; i += w) pix[i] = 0;
|
||||
x++, k = 1;
|
||||
}
|
||||
else if (x >= w) {
|
||||
memmove(pix, pix + 1, w * h - 1);
|
||||
for (i = w-1; i < w * h; i += w) pix[i] = 0;
|
||||
x--, k = 1;
|
||||
}
|
||||
|
||||
if (y >= h) {
|
||||
memmove(pix, pix + w, w * (h - 1));
|
||||
memset(pix + w * (h - 1), 0, w);
|
||||
y--, k = 1;
|
||||
}
|
||||
else if (y < 0) {
|
||||
memmove(pix + w, pix, w * (h - 1));
|
||||
memset(pix, 0, w);
|
||||
y++, k = 1;
|
||||
}
|
||||
if (k) refresh(x, y);
|
||||
set_color(ANSI_COLOR_RED);
|
||||
print_char('+', y + 1, x + 1);
|
||||
set_color(ANSI_COLOR_RESET);
|
||||
screen_refresh();
|
||||
|
||||
usleep(10000);
|
||||
}
|
||||
}
|
98
am-kernels/kernels/demo/src/bf/bf.c
Normal file
98
am-kernels/kernels/demo/src/bf/bf.c
Normal file
|
@ -0,0 +1,98 @@
|
|||
/* from http://rosettacode.org/wiki/Execute_Brain****#C */
|
||||
/* This is the Neutron brainfuck interpreter.
|
||||
* It's rather small and dense, but still readable, more or less.
|
||||
*
|
||||
* Robert de Bath -- 2013.
|
||||
*/
|
||||
#include <am.h>
|
||||
#include <klib.h>
|
||||
#include <io.h>
|
||||
|
||||
static const char *prog =
|
||||
#include "mandelbrot.h"
|
||||
;
|
||||
|
||||
struct bfi { char cmd; struct bfi *next, *jmp; };
|
||||
struct mem { char val; struct mem *next, *prev; };
|
||||
|
||||
static inline void putch2(char c) {
|
||||
static int x = 0, y = 0;
|
||||
if (c == '\n') {
|
||||
y ++;
|
||||
x = 0;
|
||||
} else {
|
||||
if (x % 2 == 0) {
|
||||
print_char(c, y, x / 2);
|
||||
screen_refresh();
|
||||
}
|
||||
x ++;
|
||||
}
|
||||
}
|
||||
|
||||
void bf() {
|
||||
int ch;
|
||||
struct bfi *p=0, *n=0, *j=0, *pgm = 0;
|
||||
struct mem *m = malloc(sizeof(*m));
|
||||
memset(m, 0, sizeof(*m));
|
||||
screen_clear();
|
||||
|
||||
/*
|
||||
* For each character, if it's a valid BF command add it onto the
|
||||
* end of the program. If the input is stdin use the '!' character
|
||||
* to mark the end of the program and the start of the data, but
|
||||
* only if we have a complete program. The 'j' variable points
|
||||
* at the list of currently open '[' commands, one is matched off
|
||||
* by each ']'. A ']' without a matching '[' is not a legal BF
|
||||
* command and so is ignored. If there are any '[' commands left
|
||||
* over at the end they are not valid BF commands and so are ignored.
|
||||
*/
|
||||
const char *s = prog;
|
||||
while((ch = *(s ++)) != '\0') {
|
||||
if (ch == '<' || ch == '>' || ch == '+' || ch == '-' ||
|
||||
ch == ',' || ch == '.' || ch == '[' || (ch == ']' && j)) {
|
||||
if ((n = malloc(sizeof(*n))) == NULL) {
|
||||
printf("malloc failed! exiting...\n");
|
||||
halt(1);
|
||||
}
|
||||
memset(n, 0, sizeof(*n));
|
||||
if (p) p->next = n; else pgm = n;
|
||||
n->cmd = ch; p = n;
|
||||
if (n->cmd == '[') { n->jmp=j; j = n; }
|
||||
else if (n->cmd == ']') {
|
||||
n->jmp = j; j = j->jmp; n->jmp->jmp = n;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Ignore any left over '[' commands */
|
||||
while(j) { p = j; j = j->jmp; p->jmp = 0; p->cmd = ' '; }
|
||||
|
||||
/* Execute the loaded BF program */
|
||||
for(n=pgm; n; n=n->next) {
|
||||
switch(n->cmd) {
|
||||
case '+': m->val++; break;
|
||||
case '-': m->val--; break;
|
||||
case '.': putch2(m->val); break;
|
||||
case ',': if((ch=*(s ++))!='\0') m->val=ch; break;
|
||||
case '[': if (m->val == 0) n=n->jmp; break;
|
||||
case ']': if (m->val != 0) n=n->jmp; break;
|
||||
case '<':
|
||||
if (!(m=m->prev)) {
|
||||
printf("Hit start of tape\n");
|
||||
halt(1);
|
||||
}
|
||||
break;
|
||||
case '>':
|
||||
if (m->next == 0) {
|
||||
if ((m->next = malloc(sizeof(*m))) == NULL) {
|
||||
printf("malloc failed! exiting...\n");
|
||||
halt(1);
|
||||
}
|
||||
memset(m->next, 0, sizeof(*m));
|
||||
m->next->prev = m;
|
||||
}
|
||||
m=m->next;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
146
am-kernels/kernels/demo/src/bf/mandelbrot.h
Normal file
146
am-kernels/kernels/demo/src/bf/mandelbrot.h
Normal file
|
@ -0,0 +1,146 @@
|
|||
"\
|
||||
A mandelbrot set fractal viewer in brainf*** written by Erik Bosman \
|
||||
+++++++++++++[->++>>>+++++>++>+<<<<<<]>>>>>++++++>--->>>>>>>>>>+++++++++++++++[[ \
|
||||
>>>>>>>>>]+[<<<<<<<<<]>>>>>>>>>-]+[>>>>>>>>[-]>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>[-]+ \
|
||||
<<<<<<<+++++[-[->>>>>>>>>+<<<<<<<<<]>>>>>>>>>]>>>>>>>+>>>>>>>>>>>>>>>>>>>>>>>>>> \
|
||||
>+<<<<<<<<<<<<<<<<<[<<<<<<<<<]>>>[-]+[>>>>>>[>>>>>>>[-]>>]<<<<<<<<<[<<<<<<<<<]>> \
|
||||
>>>>>[-]+<<<<<<++++[-[->>>>>>>>>+<<<<<<<<<]>>>>>>>>>]>>>>>>+<<<<<<+++++++[-[->>> \
|
||||
>>>>>>+<<<<<<<<<]>>>>>>>>>]>>>>>>+<<<<<<<<<<<<<<<<[<<<<<<<<<]>>>[[-]>>>>>>[>>>>> \
|
||||
>>[-<<<<<<+>>>>>>]<<<<<<[->>>>>>+<<+<<<+<]>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>> \
|
||||
[>>>>>>>>[-<<<<<<<+>>>>>>>]<<<<<<<[->>>>>>>+<<+<<<+<<]>>>>>>>>]<<<<<<<<<[<<<<<<< \
|
||||
<<]>>>>>>>[-<<<<<<<+>>>>>>>]<<<<<<<[->>>>>>>+<<+<<<<<]>>>>>>>>>+++++++++++++++[[ \
|
||||
>>>>>>>>>]+>[-]>[-]>[-]>[-]>[-]>[-]>[-]>[-]>[-]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>-]+[ \
|
||||
>+>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>->>>>[-<<<<+>>>>]<<<<[->>>>+<<<<<[->>[ \
|
||||
-<<+>>]<<[->>+>>+<<<<]+>>>>>>>>>]<<<<<<<<[<<<<<<<<<]]>>>>>>>>>[>>>>>>>>>]<<<<<<< \
|
||||
<<[>[->>>>>>>>>+<<<<<<<<<]<<<<<<<<<<]>[->>>>>>>>>+<<<<<<<<<]<+>>>>>>>>]<<<<<<<<< \
|
||||
[>[-]<->>>>[-<<<<+>[<->-<<<<<<+>>>>>>]<[->+<]>>>>]<<<[->>>+<<<]<+<<<<<<<<<]>>>>> \
|
||||
>>>>[>+>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>->>>>>[-<<<<<+>>>>>]<<<<<[->>>>>+ \
|
||||
<<<<<<[->>>[-<<<+>>>]<<<[->>>+>+<<<<]+>>>>>>>>>]<<<<<<<<[<<<<<<<<<]]>>>>>>>>>[>> \
|
||||
>>>>>>>]<<<<<<<<<[>>[->>>>>>>>>+<<<<<<<<<]<<<<<<<<<<<]>>[->>>>>>>>>+<<<<<<<<<]<< \
|
||||
+>>>>>>>>]<<<<<<<<<[>[-]<->>>>[-<<<<+>[<->-<<<<<<+>>>>>>]<[->+<]>>>>]<<<[->>>+<< \
|
||||
<]<+<<<<<<<<<]>>>>>>>>>[>>>>[-<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>> \
|
||||
>>>>>>>>>>>>>>>>>>>>>>>]>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>+++++++++++++++[[>>>> \
|
||||
>>>>>]<<<<<<<<<-<<<<<<<<<[<<<<<<<<<]>>>>>>>>>-]+>>>>>>>>>>>>>>>>>>>>>+<<<[<<<<<< \
|
||||
<<<]>>>>>>>>>[>>>[-<<<->>>]+<<<[->>>->[-<<<<+>>>>]<<<<[->>>>+<<<<<<<<<<<<<[<<<<< \
|
||||
<<<<]>>>>[-]+>>>>>[>>>>>>>>>]>+<]]+>>>>[-<<<<->>>>]+<<<<[->>>>-<[-<<<+>>>]<<<[-> \
|
||||
>>+<<<<<<<<<<<<[<<<<<<<<<]>>>[-]+>>>>>>[>>>>>>>>>]>[-]+<]]+>[-<[>>>>>>>>>]<<<<<< \
|
||||
<<]>>>>>>>>]<<<<<<<<<[<<<<<<<<<]<<<<<<<[->+>>>-<<<<]>>>>>>>>>+++++++++++++++++++ \
|
||||
+++++++>>[-<<<<+>>>>]<<<<[->>>>+<<[-]<<]>>[<<<<<<<+<[-<+>>>>+<<[-]]>[-<<[->+>>>- \
|
||||
<<<<]>>>]>>>>>>>>>>>>>[>>[-]>[-]>[-]>>>>>]<<<<<<<<<[<<<<<<<<<]>>>[-]>>>>>>[>>>>> \
|
||||
[-<<<<+>>>>]<<<<[->>>>+<<<+<]>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>>[-<<<<<<<< \
|
||||
<+>>>>>>>>>]>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>+++++++++++++++[[>>>>>>>>>]+>[- \
|
||||
]>[-]>[-]>[-]>[-]>[-]>[-]>[-]>[-]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>-]+[>+>>>>>>>>]<<< \
|
||||
<<<<<<[<<<<<<<<<]>>>>>>>>>[>->>>>>[-<<<<<+>>>>>]<<<<<[->>>>>+<<<<<<[->>[-<<+>>]< \
|
||||
<[->>+>+<<<]+>>>>>>>>>]<<<<<<<<[<<<<<<<<<]]>>>>>>>>>[>>>>>>>>>]<<<<<<<<<[>[->>>> \
|
||||
>>>>>+<<<<<<<<<]<<<<<<<<<<]>[->>>>>>>>>+<<<<<<<<<]<+>>>>>>>>]<<<<<<<<<[>[-]<->>> \
|
||||
[-<<<+>[<->-<<<<<<<+>>>>>>>]<[->+<]>>>]<<[->>+<<]<+<<<<<<<<<]>>>>>>>>>[>>>>>>[-< \
|
||||
<<<<+>>>>>]<<<<<[->>>>>+<<<<+<]>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>+>>>>>>>> \
|
||||
]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>->>>>>[-<<<<<+>>>>>]<<<<<[->>>>>+<<<<<<[->>[-<<+ \
|
||||
>>]<<[->>+>>+<<<<]+>>>>>>>>>]<<<<<<<<[<<<<<<<<<]]>>>>>>>>>[>>>>>>>>>]<<<<<<<<<[> \
|
||||
[->>>>>>>>>+<<<<<<<<<]<<<<<<<<<<]>[->>>>>>>>>+<<<<<<<<<]<+>>>>>>>>]<<<<<<<<<[>[- \
|
||||
]<->>>>[-<<<<+>[<->-<<<<<<+>>>>>>]<[->+<]>>>>]<<<[->>>+<<<]<+<<<<<<<<<]>>>>>>>>> \
|
||||
[>>>>[-<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> \
|
||||
]>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>>>[-<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+> \
|
||||
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>]>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>++++++++ \
|
||||
+++++++[[>>>>>>>>>]<<<<<<<<<-<<<<<<<<<[<<<<<<<<<]>>>>>>>>>-]+[>>>>>>>>[-<<<<<<<+ \
|
||||
>>>>>>>]<<<<<<<[->>>>>>>+<<<<<<+<]>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>>>>>>[ \
|
||||
-]>>>]<<<<<<<<<[<<<<<<<<<]>>>>+>[-<-<<<<+>>>>>]>[-<<<<<<[->>>>>+<++<<<<]>>>>>[-< \
|
||||
<<<<+>>>>>]<->+>]<[->+<]<<<<<[->>>>>+<<<<<]>>>>>>[-]<<<<<<+>>>>[-<<<<->>>>]+<<<< \
|
||||
[->>>>->>>>>[>>[-<<->>]+<<[->>->[-<<<+>>>]<<<[->>>+<<<<<<<<<<<<[<<<<<<<<<]>>>[-] \
|
||||
+>>>>>>[>>>>>>>>>]>+<]]+>>>[-<<<->>>]+<<<[->>>-<[-<<+>>]<<[->>+<<<<<<<<<<<[<<<<< \
|
||||
<<<<]>>>>[-]+>>>>>[>>>>>>>>>]>[-]+<]]+>[-<[>>>>>>>>>]<<<<<<<<]>>>>>>>>]<<<<<<<<< \
|
||||
[<<<<<<<<<]>>>>[-<<<<+>>>>]<<<<[->>>>+>>>>>[>+>>[-<<->>]<<[->>+<<]>>>>>>>>]<<<<< \
|
||||
<<<+<[>[->>>>>+<<<<[->>>>-<<<<<<<<<<<<<<+>>>>>>>>>>>[->>>+<<<]<]>[->>>-<<<<<<<<< \
|
||||
<<<<<+>>>>>>>>>>>]<<]>[->>>>+<<<[->>>-<<<<<<<<<<<<<<+>>>>>>>>>>>]<]>[->>>+<<<]<< \
|
||||
<<<<<<<<<<]>>>>[-]<<<<]>>>[-<<<+>>>]<<<[->>>+>>>>>>[>+>[-<->]<[->+<]>>>>>>>>]<<< \
|
||||
<<<<<+<[>[->>>>>+<<<[->>>-<<<<<<<<<<<<<<+>>>>>>>>>>[->>>>+<<<<]>]<[->>>>-<<<<<<< \
|
||||
<<<<<<<+>>>>>>>>>>]<]>>[->>>+<<<<[->>>>-<<<<<<<<<<<<<<+>>>>>>>>>>]>]<[->>>>+<<<< \
|
||||
]<<<<<<<<<<<]>>>>>>+<<<<<<]]>>>>[-<<<<+>>>>]<<<<[->>>>+>>>>>[>>>>>>>>>]<<<<<<<<< \
|
||||
[>[->>>>>+<<<<[->>>>-<<<<<<<<<<<<<<+>>>>>>>>>>>[->>>+<<<]<]>[->>>-<<<<<<<<<<<<<< \
|
||||
+>>>>>>>>>>>]<<]>[->>>>+<<<[->>>-<<<<<<<<<<<<<<+>>>>>>>>>>>]<]>[->>>+<<<]<<<<<<< \
|
||||
<<<<<]]>[-]>>[-]>[-]>>>>>[>>[-]>[-]>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>>>>>[-< \
|
||||
<<<+>>>>]<<<<[->>>>+<<<+<]>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>+++++++++++++++[ \
|
||||
[>>>>>>>>>]+>[-]>[-]>[-]>[-]>[-]>[-]>[-]>[-]>[-]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>-]+ \
|
||||
[>+>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>->>>>[-<<<<+>>>>]<<<<[->>>>+<<<<<[->> \
|
||||
[-<<+>>]<<[->>+>+<<<]+>>>>>>>>>]<<<<<<<<[<<<<<<<<<]]>>>>>>>>>[>>>>>>>>>]<<<<<<<< \
|
||||
<[>[->>>>>>>>>+<<<<<<<<<]<<<<<<<<<<]>[->>>>>>>>>+<<<<<<<<<]<+>>>>>>>>]<<<<<<<<<[ \
|
||||
>[-]<->>>[-<<<+>[<->-<<<<<<<+>>>>>>>]<[->+<]>>>]<<[->>+<<]<+<<<<<<<<<]>>>>>>>>>[ \
|
||||
>>>[-<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>]> \
|
||||
>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>[-]>>>>+++++++++++++++[[>>>>>>>>>]<<<<<<<<<-<<<<< \
|
||||
<<<<[<<<<<<<<<]>>>>>>>>>-]+[>>>[-<<<->>>]+<<<[->>>->[-<<<<+>>>>]<<<<[->>>>+<<<<< \
|
||||
<<<<<<<<[<<<<<<<<<]>>>>[-]+>>>>>[>>>>>>>>>]>+<]]+>>>>[-<<<<->>>>]+<<<<[->>>>-<[- \
|
||||
<<<+>>>]<<<[->>>+<<<<<<<<<<<<[<<<<<<<<<]>>>[-]+>>>>>>[>>>>>>>>>]>[-]+<]]+>[-<[>> \
|
||||
>>>>>>>]<<<<<<<<]>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>[-<<<+>>>]<<<[->>>+>>>>>>[>+>>> \
|
||||
[-<<<->>>]<<<[->>>+<<<]>>>>>>>>]<<<<<<<<+<[>[->+>[-<-<<<<<<<<<<+>>>>>>>>>>>>[-<< \
|
||||
+>>]<]>[-<<-<<<<<<<<<<+>>>>>>>>>>>>]<<<]>>[-<+>>[-<<-<<<<<<<<<<+>>>>>>>>>>>>]<]> \
|
||||
[-<<+>>]<<<<<<<<<<<<<]]>>>>[-<<<<+>>>>]<<<<[->>>>+>>>>>[>+>>[-<<->>]<<[->>+<<]>> \
|
||||
>>>>>>]<<<<<<<<+<[>[->+>>[-<<-<<<<<<<<<<+>>>>>>>>>>>[-<+>]>]<[-<-<<<<<<<<<<+>>>> \
|
||||
>>>>>>>]<<]>>>[-<<+>[-<-<<<<<<<<<<+>>>>>>>>>>>]>]<[-<+>]<<<<<<<<<<<<]>>>>>+<<<<< \
|
||||
]>>>>>>>>>[>>>[-]>[-]>[-]>>>>]<<<<<<<<<[<<<<<<<<<]>>>[-]>[-]>>>>>[>>>>>>>[-<<<<< \
|
||||
<+>>>>>>]<<<<<<[->>>>>>+<<<<+<<]>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>+>[-<-<<<<+>>>> \
|
||||
>]>>[-<<<<<<<[->>>>>+<++<<<<]>>>>>[-<<<<<+>>>>>]<->+>>]<<[->>+<<]<<<<<[->>>>>+<< \
|
||||
<<<]+>>>>[-<<<<->>>>]+<<<<[->>>>->>>>>[>>>[-<<<->>>]+<<<[->>>-<[-<<+>>]<<[->>+<< \
|
||||
<<<<<<<<<[<<<<<<<<<]>>>>[-]+>>>>>[>>>>>>>>>]>+<]]+>>[-<<->>]+<<[->>->[-<<<+>>>]< \
|
||||
<<[->>>+<<<<<<<<<<<<[<<<<<<<<<]>>>[-]+>>>>>>[>>>>>>>>>]>[-]+<]]+>[-<[>>>>>>>>>]< \
|
||||
<<<<<<<]>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>[-<<<+>>>]<<<[->>>+>>>>>>[>+>[-<->]<[->+ \
|
||||
<]>>>>>>>>]<<<<<<<<+<[>[->>>>+<<[->>-<<<<<<<<<<<<<+>>>>>>>>>>[->>>+<<<]>]<[->>>- \
|
||||
<<<<<<<<<<<<<+>>>>>>>>>>]<]>>[->>+<<<[->>>-<<<<<<<<<<<<<+>>>>>>>>>>]>]<[->>>+<<< \
|
||||
]<<<<<<<<<<<]>>>>>[-]>>[-<<<<<<<+>>>>>>>]<<<<<<<[->>>>>>>+<<+<<<<<]]>>>>[-<<<<+> \
|
||||
>>>]<<<<[->>>>+>>>>>[>+>>[-<<->>]<<[->>+<<]>>>>>>>>]<<<<<<<<+<[>[->>>>+<<<[->>>- \
|
||||
<<<<<<<<<<<<<+>>>>>>>>>>>[->>+<<]<]>[->>-<<<<<<<<<<<<<+>>>>>>>>>>>]<<]>[->>>+<<[ \
|
||||
->>-<<<<<<<<<<<<<+>>>>>>>>>>>]<]>[->>+<<]<<<<<<<<<<<<]]>>>>[-]<<<<]>>>>[-<<<<+>> \
|
||||
>>]<<<<[->>>>+>[-]>>[-<<<<<<<+>>>>>>>]<<<<<<<[->>>>>>>+<<+<<<<<]>>>>>>>>>[>>>>>> \
|
||||
>>>]<<<<<<<<<[>[->>>>+<<<[->>>-<<<<<<<<<<<<<+>>>>>>>>>>>[->>+<<]<]>[->>-<<<<<<<< \
|
||||
<<<<<+>>>>>>>>>>>]<<]>[->>>+<<[->>-<<<<<<<<<<<<<+>>>>>>>>>>>]<]>[->>+<<]<<<<<<<< \
|
||||
<<<<]]>>>>>>>>>[>>[-]>[-]>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>[-]>[-]>>>>>[>>>>>[-<<<<+ \
|
||||
>>>>]<<<<[->>>>+<<<+<]>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>>>>>>[-<<<<<+>>>>> \
|
||||
]<<<<<[->>>>>+<<<+<<]>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>+++++++++++++++[[>>>> \
|
||||
>>>>>]+>[-]>[-]>[-]>[-]>[-]>[-]>[-]>[-]>[-]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>-]+[>+>> \
|
||||
>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>->>>>[-<<<<+>>>>]<<<<[->>>>+<<<<<[->>[-<<+ \
|
||||
>>]<<[->>+>>+<<<<]+>>>>>>>>>]<<<<<<<<[<<<<<<<<<]]>>>>>>>>>[>>>>>>>>>]<<<<<<<<<[> \
|
||||
[->>>>>>>>>+<<<<<<<<<]<<<<<<<<<<]>[->>>>>>>>>+<<<<<<<<<]<+>>>>>>>>]<<<<<<<<<[>[- \
|
||||
]<->>>>[-<<<<+>[<->-<<<<<<+>>>>>>]<[->+<]>>>>]<<<[->>>+<<<]<+<<<<<<<<<]>>>>>>>>> \
|
||||
[>+>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>->>>>>[-<<<<<+>>>>>]<<<<<[->>>>>+<<<< \
|
||||
<<[->>>[-<<<+>>>]<<<[->>>+>+<<<<]+>>>>>>>>>]<<<<<<<<[<<<<<<<<<]]>>>>>>>>>[>>>>>> \
|
||||
>>>]<<<<<<<<<[>>[->>>>>>>>>+<<<<<<<<<]<<<<<<<<<<<]>>[->>>>>>>>>+<<<<<<<<<]<<+>>> \
|
||||
>>>>>]<<<<<<<<<[>[-]<->>>>[-<<<<+>[<->-<<<<<<+>>>>>>]<[->+<]>>>>]<<<[->>>+<<<]<+ \
|
||||
<<<<<<<<<]>>>>>>>>>[>>>>[-<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>> \
|
||||
>>>>>>>>>>>>>>>>>>>]>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>+++++++++++++++[[>>>>>>>> \
|
||||
>]<<<<<<<<<-<<<<<<<<<[<<<<<<<<<]>>>>>>>>>-]+>>>>>>>>>>>>>>>>>>>>>+<<<[<<<<<<<<<] \
|
||||
>>>>>>>>>[>>>[-<<<->>>]+<<<[->>>->[-<<<<+>>>>]<<<<[->>>>+<<<<<<<<<<<<<[<<<<<<<<< \
|
||||
]>>>>[-]+>>>>>[>>>>>>>>>]>+<]]+>>>>[-<<<<->>>>]+<<<<[->>>>-<[-<<<+>>>]<<<[->>>+< \
|
||||
<<<<<<<<<<<[<<<<<<<<<]>>>[-]+>>>>>>[>>>>>>>>>]>[-]+<]]+>[-<[>>>>>>>>>]<<<<<<<<]> \
|
||||
>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>->>[-<<<<+>>>>]<<<<[->>>>+<<[-]<<]>>]<<+>>>>[-<<<< \
|
||||
->>>>]+<<<<[->>>>-<<<<<<.>>]>>>>[-<<<<<<<.>>>>>>>]<<<[-]>[-]>[-]>[-]>[-]>[-]>>>[ \
|
||||
>[-]>[-]>[-]>[-]>[-]>[-]>>>]<<<<<<<<<[<<<<<<<<<]>>>>>>>>>[>>>>>[-]>>>>]<<<<<<<<< \
|
||||
[<<<<<<<<<]>+++++++++++[-[->>>>>>>>>+<<<<<<<<<]>>>>>>>>>]>>>>+>>>>>>>>>+<<<<<<<< \
|
||||
<<<<<<[<<<<<<<<<]>>>>>>>[-<<<<<<<+>>>>>>>]<<<<<<<[->>>>>>>+[-]>>[>>>>>>>>>]<<<<< \
|
||||
<<<<[>>>>>>>[-<<<<<<+>>>>>>]<<<<<<[->>>>>>+<<<<<<<[<<<<<<<<<]>>>>>>>[-]+>>>]<<<< \
|
||||
<<<<<<]]>>>>>>>[-<<<<<<<+>>>>>>>]<<<<<<<[->>>>>>>+>>[>+>>>>[-<<<<->>>>]<<<<[->>> \
|
||||
>+<<<<]>>>>>>>>]<<+<<<<<<<[>>>>>[->>+<<]<<<<<<<<<<<<<<]>>>>>>>>>[>>>>>>>>>]<<<<< \
|
||||
<<<<[>[-]<->>>>>>>[-<<<<<<<+>[<->-<<<+>>>]<[->+<]>>>>>>>]<<<<<<[->>>>>>+<<<<<<]< \
|
||||
+<<<<<<<<<]>>>>>>>-<<<<[-]+<<<]+>>>>>>>[-<<<<<<<->>>>>>>]+<<<<<<<[->>>>>>>->>[>> \
|
||||
>>>[->>+<<]>>>>]<<<<<<<<<[>[-]<->>>>>>>[-<<<<<<<+>[<->-<<<+>>>]<[->+<]>>>>>>>]<< \
|
||||
<<<<[->>>>>>+<<<<<<]<+<<<<<<<<<]>+++++[-[->>>>>>>>>+<<<<<<<<<]>>>>>>>>>]>>>>+<<< \
|
||||
<<[<<<<<<<<<]>>>>>>>>>[>>>>>[-<<<<<->>>>>]+<<<<<[->>>>>->>[-<<<<<<<+>>>>>>>]<<<< \
|
||||
<<<[->>>>>>>+<<<<<<<<<<<<<<<<[<<<<<<<<<]>>>>[-]+>>>>>[>>>>>>>>>]>+<]]+>>>>>>>[-< \
|
||||
<<<<<<->>>>>>>]+<<<<<<<[->>>>>>>-<<[-<<<<<+>>>>>]<<<<<[->>>>>+<<<<<<<<<<<<<<[<<< \
|
||||
<<<<<<]>>>[-]+>>>>>>[>>>>>>>>>]>[-]+<]]+>[-<[>>>>>>>>>]<<<<<<<<]>>>>>>>>]<<<<<<< \
|
||||
<<[<<<<<<<<<]>>>>[-]<<<+++++[-[->>>>>>>>>+<<<<<<<<<]>>>>>>>>>]>>>>-<<<<<[<<<<<<< \
|
||||
<<]]>>>]<<<<.>>>>>>>>>>[>>>>>>[-]>>>]<<<<<<<<<[<<<<<<<<<]>++++++++++[-[->>>>>>>> \
|
||||
>+<<<<<<<<<]>>>>>>>>>]>>>>>+>>>>>>>>>+<<<<<<<<<<<<<<<[<<<<<<<<<]>>>>>>>>[-<<<<<< \
|
||||
<<+>>>>>>>>]<<<<<<<<[->>>>>>>>+[-]>[>>>>>>>>>]<<<<<<<<<[>>>>>>>>[-<<<<<<<+>>>>>> \
|
||||
>]<<<<<<<[->>>>>>>+<<<<<<<<[<<<<<<<<<]>>>>>>>>[-]+>>]<<<<<<<<<<]]>>>>>>>>[-<<<<< \
|
||||
<<<+>>>>>>>>]<<<<<<<<[->>>>>>>>+>[>+>>>>>[-<<<<<->>>>>]<<<<<[->>>>>+<<<<<]>>>>>> \
|
||||
>>]<+<<<<<<<<[>>>>>>[->>+<<]<<<<<<<<<<<<<<<]>>>>>>>>>[>>>>>>>>>]<<<<<<<<<[>[-]<- \
|
||||
>>>>>>>>[-<<<<<<<<+>[<->-<<+>>]<[->+<]>>>>>>>>]<<<<<<<[->>>>>>>+<<<<<<<]<+<<<<<< \
|
||||
<<<]>>>>>>>>-<<<<<[-]+<<<]+>>>>>>>>[-<<<<<<<<->>>>>>>>]+<<<<<<<<[->>>>>>>>->[>>> \
|
||||
>>>[->>+<<]>>>]<<<<<<<<<[>[-]<->>>>>>>>[-<<<<<<<<+>[<->-<<+>>]<[->+<]>>>>>>>>]<< \
|
||||
<<<<<[->>>>>>>+<<<<<<<]<+<<<<<<<<<]>+++++[-[->>>>>>>>>+<<<<<<<<<]>>>>>>>>>]>>>>> \
|
||||
+>>>>>>>>>>>>>>>>>>>>>>>>>>>+<<<<<<[<<<<<<<<<]>>>>>>>>>[>>>>>>[-<<<<<<->>>>>>]+< \
|
||||
<<<<<[->>>>>>->>[-<<<<<<<<+>>>>>>>>]<<<<<<<<[->>>>>>>>+<<<<<<<<<<<<<<<<<[<<<<<<< \
|
||||
<<]>>>>[-]+>>>>>[>>>>>>>>>]>+<]]+>>>>>>>>[-<<<<<<<<->>>>>>>>]+<<<<<<<<[->>>>>>>> \
|
||||
-<<[-<<<<<<+>>>>>>]<<<<<<[->>>>>>+<<<<<<<<<<<<<<<[<<<<<<<<<]>>>[-]+>>>>>>[>>>>>> \
|
||||
>>>]>[-]+<]]+>[-<[>>>>>>>>>]<<<<<<<<]>>>>>>>>]<<<<<<<<<[<<<<<<<<<]>>>>[-]<<<++++ \
|
||||
+[-[->>>>>>>>>+<<<<<<<<<]>>>>>>>>>]>>>>>->>>>>>>>>>>>>>>>>>>>>>>>>>>-<<<<<<[<<<< \
|
||||
<<<<<]]>>>]"
|
21
am-kernels/kernels/demo/src/cmatrix/LICENSE
Normal file
21
am-kernels/kernels/demo/src/cmatrix/LICENSE
Normal file
|
@ -0,0 +1,21 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2018 Fontaine Hugo a.k.a "Usiten"
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
72
am-kernels/kernels/demo/src/cmatrix/cmatrix.c
Normal file
72
am-kernels/kernels/demo/src/cmatrix/cmatrix.c
Normal file
|
@ -0,0 +1,72 @@
|
|||
/************************************************************************
|
||||
|
||||
The Matrix Rain Screen Saver
|
||||
|
||||
This code is converted from QBASIC to C.
|
||||
|
||||
QBasic Code from
|
||||
http://codegolf.stackexchange.com/questions/17285/make-the-matrix-digital-rain-using-the-shortest-amount-of-code
|
||||
|
||||
************************************************************************/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <am.h>
|
||||
#include <io.h>
|
||||
|
||||
#define W 80
|
||||
#define H 24
|
||||
|
||||
static int t[W];
|
||||
|
||||
static void sub_d(int p, int s, int x, int y) {
|
||||
uint8_t r = (p % 16) * 16;
|
||||
uint8_t g = 180 - p;
|
||||
if (r < 10) {
|
||||
// set_color(ANSI_COLOR_RESET);
|
||||
}
|
||||
else {
|
||||
if (g > 170) {
|
||||
set_color(ANSI_COLOR_WHITE);
|
||||
}
|
||||
else if (g < 170) {
|
||||
set_color(ANSI_COLOR_GREEN);
|
||||
}
|
||||
}
|
||||
|
||||
if ((y >= 0) && (y < H) && (x < W)) {
|
||||
char c = (r < 10 ? ' ' : 33 + (x * y) % 94);
|
||||
print_char(c, y, x);
|
||||
//)vt_draw_char_at(y, x, c);
|
||||
}
|
||||
}
|
||||
|
||||
void cmatrix() {
|
||||
int i, x, y, k;
|
||||
screen_clear();
|
||||
|
||||
x = rand();
|
||||
for (i = 0; i < W; i++) {
|
||||
t[i] = - rand() % 50;
|
||||
}
|
||||
|
||||
sub_d(1,1,10,10);
|
||||
|
||||
while (1) {
|
||||
for (k = 1; k < W; k++) {
|
||||
i = rand() % (W-1);
|
||||
if (t[i] > 28)t[i] = 0;
|
||||
t[i] = t[i] + 1;
|
||||
y = t[i];
|
||||
sub_d( 0 , 0, i, y - 6);
|
||||
sub_d( 2 + x, 0, i, y - 5);
|
||||
sub_d( 2 + x, 0, i, y - 4);
|
||||
sub_d( 10 + x, 0, i, y - 3);
|
||||
sub_d( 10 + x, 0, i, y - 2);
|
||||
sub_d( 11 + x, 0, i, y - 1);
|
||||
sub_d( 0 , 2 + x, i, y);
|
||||
}
|
||||
|
||||
screen_refresh();
|
||||
usleep(100000);
|
||||
}
|
||||
}
|
82
am-kernels/kernels/demo/src/donut/donut.c
Normal file
82
am-kernels/kernels/demo/src/donut/donut.c
Normal file
|
@ -0,0 +1,82 @@
|
|||
/**
|
||||
* Original author:
|
||||
* https://twitter.com/a1k0n
|
||||
* https://www.a1k0n.net/2021/01/13/optimizing-donut.html
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2006-09-15 Andy Sloane First version
|
||||
* 2011-07-20 Andy Sloane Second version
|
||||
* 2021-01-13 Andy Sloane Third version
|
||||
* 2021-03-25 Meco Man Port to RT-Thread RTOS
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <io.h>
|
||||
|
||||
#define R(mul,shift,x,y) \
|
||||
_=x; \
|
||||
x -= mul*y>>shift; \
|
||||
y += mul*_>>shift; \
|
||||
_ = (3145728-x*x-y*y)>>11; \
|
||||
x = x*_>>10; \
|
||||
y = y*_>>10;
|
||||
|
||||
static char b[1760];
|
||||
static signed char z[1760];
|
||||
|
||||
void donut(void) {
|
||||
int sA = 1024, cA = 0, sB = 1024, cB = 0, _;
|
||||
|
||||
while(1) {
|
||||
memset(b, 32, 1760); // text buffer
|
||||
memset(z, 127, 1760); // z buffer
|
||||
int sj = 0, cj = 1024;
|
||||
for (int j = 0; j < 90; j++) {
|
||||
int si = 0, ci = 1024; // sine and cosine of angle i
|
||||
for (int i = 0; i < 324; i++) {
|
||||
int R1 = 1, R2 = 2048, K2 = 5120*1024;
|
||||
|
||||
int x0 = R1*cj + R2,
|
||||
x1 = ci*x0 >> 10,
|
||||
x2 = cA*sj >> 10,
|
||||
x3 = si*x0 >> 10,
|
||||
x4 = R1*x2 - (sA*x3 >> 10),
|
||||
x5 = sA*sj >> 10,
|
||||
x6 = K2 + R1*1024*x5 + cA*x3,
|
||||
x7 = cj*si >> 10,
|
||||
x = 25 + 30*(cB*x1 - sB*x4)/x6,
|
||||
y = 12 + 15*(cB*x4 + sB*x1)/x6,
|
||||
N = (((-cA*x7 - cB*((-sA*x7>>10) + x2) - ci*(cj*sB >> 10)) >> 10) - x5) >> 7;
|
||||
|
||||
int o = x + 80 * y;
|
||||
signed char zz = (x6-K2)>>15;
|
||||
if (22 > y && y > 0 && x > 0 && 80 > x && zz < z[o]) {
|
||||
z[o] = zz;
|
||||
b[o] = ".,-~:;=!*#$@"[N > 0 ? N : 0];
|
||||
}
|
||||
R(5, 8, ci, si) // rotate i
|
||||
}
|
||||
R(9, 7, cj, sj) // rotate j
|
||||
}
|
||||
R(5, 7, cA, sA);
|
||||
R(5, 8, cB, sB);
|
||||
|
||||
screen_clear();
|
||||
int y = 0, x = 0;
|
||||
for (int k = 0; 1761 > k; k++) {
|
||||
if (k % 80) {
|
||||
if (x < 50) print_char(b[k], y, x);
|
||||
x ++;
|
||||
} else {
|
||||
y ++;
|
||||
x = 1;
|
||||
}
|
||||
}
|
||||
|
||||
screen_refresh();
|
||||
usleep(100000);
|
||||
}
|
||||
}
|
96
am-kernels/kernels/demo/src/galton/galton.c
Normal file
96
am-kernels/kernels/demo/src/galton/galton.c
Normal file
|
@ -0,0 +1,96 @@
|
|||
/* from http://rosettacode.org/wiki/Galton_box_animation#C */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <io.h>
|
||||
|
||||
#define BALLS 1024
|
||||
#define N 8
|
||||
#define W (N * 2 + 1)
|
||||
#define H_MAX 50
|
||||
#define H_MIN 30
|
||||
static int h = 0;
|
||||
static int *x = NULL, *y = NULL, cnt = 0;
|
||||
static char *b = NULL;
|
||||
|
||||
#define B(y, x) b[(y)*W + x]
|
||||
#define C(y, x) ' ' == b[(y)*W + x]
|
||||
#define V(i) B(y[i], x[i])
|
||||
static int rnd(int a) { return rand() % a; }
|
||||
|
||||
static void show_board() {
|
||||
int i, j;
|
||||
for (i = 0; i < h; i++)
|
||||
for (j = 0; j < W; j++) {
|
||||
if (B(i, j) == '*') {
|
||||
set_color(C(i - 1, j) ? ANSI_COLOR_GREEN : ANSI_COLOR_RED);
|
||||
print_char(B(i, j), i, 2 * j);
|
||||
set_color(ANSI_COLOR_RESET);
|
||||
} else {
|
||||
print_char(B(i, j), i, 2 * j);
|
||||
}
|
||||
print_char(' ', i, 2 * j + 1);
|
||||
}
|
||||
screen_refresh();
|
||||
}
|
||||
|
||||
static void init() {
|
||||
int i, j;
|
||||
screen_clear();
|
||||
b = malloc(W * h);
|
||||
memset(b, ' ', W * h);
|
||||
|
||||
x = malloc(sizeof(int) * BALLS * 2);
|
||||
y = x + BALLS;
|
||||
|
||||
for (i = 0; i < N; i++)
|
||||
for (j = -i; j <= i; j += 2)
|
||||
B(2 * i+2, j + W/2) = '*';
|
||||
}
|
||||
|
||||
static void move(int idx) {
|
||||
int xx = x[idx], yy = y[idx], c, kill = 0, sl = 3, o = 0;
|
||||
|
||||
if (yy < 0) return;
|
||||
if (yy == h - 1) { y[idx] = -1; return; }
|
||||
|
||||
switch(c = B(yy + 1, xx)) {
|
||||
case ' ': yy++; break;
|
||||
case '*': sl = 1;
|
||||
default: if (xx < W - 1 && C(yy, xx + 1) && C(yy + 1, xx + 1))
|
||||
if (!rnd(sl++)) o = 1;
|
||||
if (xx && C(yy, xx - 1) && C(yy + 1, xx - 1))
|
||||
if (!rnd(sl++)) o = -1;
|
||||
if (!o) kill = 1;
|
||||
xx += o;
|
||||
}
|
||||
|
||||
c = V(idx); V(idx) = ' ';
|
||||
idx[y] = yy, idx[x] = xx;
|
||||
B(yy, xx) = c;
|
||||
if (kill) idx[y] = -1;
|
||||
}
|
||||
|
||||
static int run(void) {
|
||||
static int step = 0;
|
||||
int i;
|
||||
for (i = 0; i < cnt; i++) move(i);
|
||||
if (2 == ++step && cnt < BALLS) {
|
||||
step = 0;
|
||||
x[cnt] = W/2;
|
||||
y[cnt] = 0;
|
||||
if (V(cnt) != ' ') return 0;
|
||||
V(cnt) = rnd(80) + 43;
|
||||
cnt++;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void galton() {
|
||||
h = screen_tile_height() - 2;
|
||||
if (h > H_MAX) h = H_MAX;
|
||||
if (h < H_MIN) h = H_MIN;
|
||||
init();
|
||||
do { show_board(), usleep(6000); } while (run());
|
||||
}
|
60
am-kernels/kernels/demo/src/hanoi/hanoi.c
Normal file
60
am-kernels/kernels/demo/src/hanoi/hanoi.c
Normal file
|
@ -0,0 +1,60 @@
|
|||
/* from http://rosettacode.org/wiki/Towers_of_Hanoi#C */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <io.h>
|
||||
|
||||
#define H 7
|
||||
|
||||
typedef struct { int *x, n; } tower;
|
||||
static tower *new_tower(int cap) {
|
||||
int size = sizeof(tower) + sizeof(int) * cap;
|
||||
tower *t = malloc(size);
|
||||
memset(t, 0, size);
|
||||
t->x = (int*)(t + 1);
|
||||
return t;
|
||||
}
|
||||
|
||||
static tower *t[3];
|
||||
|
||||
static void text(int y, int i, int d, const char *s) {
|
||||
int yy = H - y + 1;
|
||||
int xx = (H + 1) * (2 * i + 1) - d;
|
||||
while (d--) {
|
||||
for (const char *p = s; *p; p ++) {
|
||||
print_char(*p, yy, xx ++);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void add_disk(int i, int d) {
|
||||
t[i]->x[t[i]->n++] = d;
|
||||
text(t[i]->n, i, d, "==");
|
||||
screen_refresh();
|
||||
usleep(100000);
|
||||
}
|
||||
|
||||
int remove_disk(int i) {
|
||||
int d = t[i]->x[--t[i]->n];
|
||||
text(t[i]->n + 1, i, d, " ");
|
||||
return d;
|
||||
}
|
||||
|
||||
void move(int n, int from, int to, int via) {
|
||||
if (!n) return;
|
||||
|
||||
move(n - 1, from, via, to);
|
||||
add_disk(to, remove_disk(from));
|
||||
move(n - 1, via, to, from);
|
||||
}
|
||||
|
||||
void hanoi() {
|
||||
screen_clear();
|
||||
|
||||
int c;
|
||||
for (c = 0; c < 3; c++) t[c] = new_tower(H);
|
||||
for (c = H; c; c--) add_disk(0, c);
|
||||
|
||||
move(H, 0, 2, 1);
|
||||
}
|
56
am-kernels/kernels/demo/src/life/life.c
Normal file
56
am-kernels/kernels/demo/src/life/life.c
Normal file
|
@ -0,0 +1,56 @@
|
|||
/* adapted from http://rosettacode.org/wiki/Conway%27s_Game_of_Life */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <io.h>
|
||||
|
||||
static int w = 40, h = 25;
|
||||
static unsigned *new_array = NULL;
|
||||
static unsigned *univ_array = NULL;
|
||||
|
||||
void show(void *u) {
|
||||
int x,y;
|
||||
int (*univ)[w] = u;
|
||||
screen_clear();
|
||||
for (y=0;y<h;y++) {
|
||||
for (x=0;x<w;x++)
|
||||
print_char(univ[y][x] ? 'o' : ' ', y, x);
|
||||
}
|
||||
screen_refresh();
|
||||
}
|
||||
|
||||
void evolve(void *u) {
|
||||
int x,y,x1,y1;
|
||||
unsigned (*univ)[w] = u;
|
||||
unsigned (*new)[w] = (void *)new_array;
|
||||
|
||||
for (y=0;y<h;y++) for (x=0;x<w;x++) {
|
||||
int n = 0;
|
||||
for (y1 = y - 1; y1 <= y + 1; y1++)
|
||||
for (x1 = x - 1; x1 <= x + 1; x1++)
|
||||
if (univ[(y1 + h) % h][(x1 + w) % w])
|
||||
n++;
|
||||
|
||||
if (univ[y][x]) n--;
|
||||
new[y][x] = (n == 3 || (n == 2 && univ[y][x]));
|
||||
}
|
||||
for (y=0;y<h;y++) for (x=0;x<w;x++) univ[y][x] = new[y][x];
|
||||
}
|
||||
|
||||
void game_of_life(void) {
|
||||
w = screen_tile_width();
|
||||
h = screen_tile_height();
|
||||
univ_array = malloc(h * w * sizeof(unsigned));
|
||||
new_array = malloc(h * w * sizeof(unsigned));
|
||||
unsigned (*univ)[w] = (void *)univ_array;
|
||||
|
||||
int x,y;
|
||||
for (x=0;x<w;x++)
|
||||
for (y=0;y<h;y++)
|
||||
univ[y][x] = rand() % 2;
|
||||
while (1) {
|
||||
show(univ);
|
||||
evolve(univ);
|
||||
usleep(200000);
|
||||
}
|
||||
}
|
44
am-kernels/kernels/demo/src/main.c
Normal file
44
am-kernels/kernels/demo/src/main.c
Normal file
|
@ -0,0 +1,44 @@
|
|||
#include <am.h>
|
||||
#include <klib.h>
|
||||
#include <klib-macros.h>
|
||||
|
||||
void ant();
|
||||
void galton();
|
||||
void hanoi();
|
||||
void game_of_life();
|
||||
void aclock();
|
||||
void cmatrix();
|
||||
void donut();
|
||||
void bf();
|
||||
|
||||
int main(const char *args) {
|
||||
ioe_init();
|
||||
|
||||
switch (args[0]) {
|
||||
case '1': ant(); break;
|
||||
case '2': galton(); break;
|
||||
case '3': hanoi(); break;
|
||||
case '4': game_of_life(); break;
|
||||
case '5': aclock(); break;
|
||||
case '6': cmatrix(); break;
|
||||
case '7': donut(); break;
|
||||
case '8': bf(); break;
|
||||
default:
|
||||
printf("Usage: make run mainargs=*\n");
|
||||
printf(" 1: ant\n");
|
||||
printf(" 2: galton\n");
|
||||
printf(" 3: hanoi\n");
|
||||
printf(" 4: game of life\n");
|
||||
printf(" 5: aclock\n");
|
||||
printf(" 6: cmatrix\n");
|
||||
printf(" 7: donut\n");
|
||||
printf(" 8: bf\n");
|
||||
}
|
||||
|
||||
printf("Press Q to Exit\n");
|
||||
while (1) {
|
||||
AM_INPUT_KEYBRD_T ev = io_read(AM_INPUT_KEYBRD);
|
||||
if (ev.keydown && ev.keycode == AM_KEY_Q) break;
|
||||
}
|
||||
return 0;
|
||||
}
|
3
am-kernels/kernels/hello/Makefile
Normal file
3
am-kernels/kernels/hello/Makefile
Normal file
|
@ -0,0 +1,3 @@
|
|||
NAME = hello
|
||||
SRCS = hello.c
|
||||
include $(AM_HOME)/Makefile
|
13
am-kernels/kernels/hello/hello.c
Normal file
13
am-kernels/kernels/hello/hello.c
Normal file
|
@ -0,0 +1,13 @@
|
|||
#include <am.h>
|
||||
#include <klib-macros.h>
|
||||
|
||||
int main(const char *args) {
|
||||
const char *fmt =
|
||||
"Hello, AbstractMachine!\n"
|
||||
"mainargs = '%'.\n";
|
||||
|
||||
for (const char *p = fmt; *p; p++) {
|
||||
(*p == '%') ? putstr(args) : putch(*p);
|
||||
}
|
||||
return 0;
|
||||
}
|
3
am-kernels/kernels/litenes/Makefile
Normal file
3
am-kernels/kernels/litenes/Makefile
Normal file
|
@ -0,0 +1,3 @@
|
|||
NAME = litenes
|
||||
SRCS = $(shell find src/ -name "*.c")
|
||||
include $(AM_HOME)/Makefile
|
2
am-kernels/kernels/litenes/README
Normal file
2
am-kernels/kernels/litenes/README
Normal file
|
@ -0,0 +1,2 @@
|
|||
This is the AbstractMachine port of mynes (https://github.com/yaglo/mynes).
|
||||
Emulates "Super Mario Bros" on NES (CPU, PPU, and peripherals).
|
16
am-kernels/kernels/litenes/src/common.c
Normal file
16
am-kernels/kernels/litenes/src/common.c
Normal file
|
@ -0,0 +1,16 @@
|
|||
#include "common.h"
|
||||
|
||||
bool common_bit_set(long long value, byte position) { return value & (1L << position); }
|
||||
|
||||
// I could do this through non-void methods with returns in one copy,
|
||||
// but this variant is slightly faster, and needs less typing in client code
|
||||
#define M_common(SUFFIX, TYPE) \
|
||||
void common_set_bit##SUFFIX(TYPE *variable, byte position) { *variable |= 1L << position; } \
|
||||
void common_unset_bit##SUFFIX(TYPE *variable, byte position) { *variable &= ~(1L << position); } \
|
||||
void common_toggle_bit##SUFFIX(TYPE *variable, byte position) { *variable ^= 1L << position; } \
|
||||
void common_modify_bit##SUFFIX(TYPE *variable, byte position, bool set) \
|
||||
{ set ? common_set_bit##SUFFIX(variable, position) : common_unset_bit##SUFFIX(variable, position); }
|
||||
|
||||
M_common(b, byte)
|
||||
M_common(w, word)
|
||||
M_common(d, dword)
|
33
am-kernels/kernels/litenes/src/common.h
Normal file
33
am-kernels/kernels/litenes/src/common.h
Normal file
|
@ -0,0 +1,33 @@
|
|||
#ifndef COMMON_H
|
||||
#define COMMON_H
|
||||
|
||||
#include <am.h>
|
||||
#include <klib.h>
|
||||
#include <klib-macros.h>
|
||||
|
||||
typedef uint8_t byte;
|
||||
typedef uint16_t word;
|
||||
typedef uint32_t dword;
|
||||
|
||||
// Binary Operations
|
||||
bool common_bit_set(long long value, byte position);
|
||||
|
||||
// Byte Bit Operations
|
||||
void common_set_bitb(byte *variable, byte position);
|
||||
void common_unset_bitb(byte *variable, byte position);
|
||||
void common_toggle_bitb(byte *variable, byte position);
|
||||
void common_modify_bitb(byte *variable, byte position, bool set);
|
||||
|
||||
// Word Bit Operations
|
||||
void common_set_bitw(word *variable, byte position);
|
||||
void common_unset_bitw(word *variable, byte position);
|
||||
void common_toggle_bitw(word *variable, byte position);
|
||||
void common_modify_bitw(word *variable, byte position, bool set);
|
||||
|
||||
// Double Word Bit Operations
|
||||
void common_set_bitd(dword *variable, byte position);
|
||||
void common_unset_bitd(dword *variable, byte position);
|
||||
void common_toggle_bitd(dword *variable, byte position);
|
||||
void common_modify_bitd(dword *variable, byte position, bool set);
|
||||
|
||||
#endif
|
101
am-kernels/kernels/litenes/src/cpu-addressing.c
Normal file
101
am-kernels/kernels/litenes/src/cpu-addressing.c
Normal file
|
@ -0,0 +1,101 @@
|
|||
#include "cpu.h"
|
||||
#include "cpu-internal.h"
|
||||
#include "memory.h"
|
||||
|
||||
// CPU Addressing Modes
|
||||
|
||||
void cpu_address_implied() { }
|
||||
|
||||
void cpu_address_immediate() {
|
||||
op_value = memory_readb(cpu.PC);
|
||||
cpu.PC++;
|
||||
}
|
||||
|
||||
void cpu_address_zero_page() {
|
||||
op_address = memory_readb(cpu.PC);
|
||||
op_value = CPU_RAM[op_address];
|
||||
cpu.PC++;
|
||||
}
|
||||
|
||||
void cpu_address_zero_page_x() {
|
||||
op_address = (memory_readb(cpu.PC) + cpu.X) & 0xFF;
|
||||
op_value = CPU_RAM[op_address];
|
||||
cpu.PC++;
|
||||
}
|
||||
|
||||
void cpu_address_zero_page_y() {
|
||||
op_address = (memory_readb(cpu.PC) + cpu.Y) & 0xFF;
|
||||
op_value = CPU_RAM[op_address];
|
||||
cpu.PC++;
|
||||
}
|
||||
|
||||
void cpu_address_absolute() {
|
||||
op_address = memory_readw(cpu.PC);
|
||||
op_value = memory_readb(op_address);
|
||||
cpu.PC += 2;
|
||||
}
|
||||
|
||||
void cpu_address_absolute_x() {
|
||||
op_address = memory_readw(cpu.PC) + cpu.X;
|
||||
op_value = memory_readb(op_address);
|
||||
cpu.PC += 2;
|
||||
|
||||
if ((op_address >> 8) != (cpu.PC >> 8)) {
|
||||
op_cycles++;
|
||||
}
|
||||
}
|
||||
|
||||
void cpu_address_absolute_y() {
|
||||
op_address = (memory_readw(cpu.PC) + cpu.Y) & 0xFFFF;
|
||||
op_value = memory_readb(op_address);
|
||||
cpu.PC += 2;
|
||||
|
||||
if ((op_address >> 8) != (cpu.PC >> 8)) {
|
||||
op_cycles++;
|
||||
}
|
||||
}
|
||||
|
||||
void cpu_address_relative() {
|
||||
op_address = memory_readb(cpu.PC);
|
||||
cpu.PC++;
|
||||
if (op_address & 0x80)
|
||||
op_address -= 0x100;
|
||||
op_address += cpu.PC;
|
||||
|
||||
if ((op_address >> 8) != (cpu.PC >> 8)) {
|
||||
op_cycles++;
|
||||
}
|
||||
}
|
||||
|
||||
void cpu_address_indirect() {
|
||||
word arg_addr = memory_readw(cpu.PC);
|
||||
|
||||
// The famous 6502 bug when instead of reading from $C0FF/$C100 it reads from $C0FF/$C000
|
||||
if ((arg_addr & 0xFF) == 0xFF) {
|
||||
// Buggy code
|
||||
op_address = (memory_readb(arg_addr & 0xFF00) << 8) + memory_readb(arg_addr);
|
||||
}
|
||||
else {
|
||||
// Normal code
|
||||
op_address = memory_readw(arg_addr);
|
||||
}
|
||||
cpu.PC += 2;
|
||||
}
|
||||
|
||||
void cpu_address_indirect_x() {
|
||||
byte arg_addr = memory_readb(cpu.PC);
|
||||
op_address = (memory_readb((arg_addr + cpu.X + 1) & 0xFF) << 8) | memory_readb((arg_addr + cpu.X) & 0xFF);
|
||||
op_value = memory_readb(op_address);
|
||||
cpu.PC++;
|
||||
}
|
||||
|
||||
void cpu_address_indirect_y() {
|
||||
byte arg_addr = memory_readb(cpu.PC);
|
||||
op_address = (((memory_readb((arg_addr + 1) & 0xFF) << 8) | memory_readb(arg_addr)) + cpu.Y) & 0xFFFF;
|
||||
op_value = memory_readb(op_address);
|
||||
cpu.PC++;
|
||||
|
||||
if ((op_address >> 8) != (cpu.PC >> 8)) {
|
||||
op_cycles++;
|
||||
}
|
||||
}
|
63
am-kernels/kernels/litenes/src/cpu-internal.h
Normal file
63
am-kernels/kernels/litenes/src/cpu-internal.h
Normal file
|
@ -0,0 +1,63 @@
|
|||
#ifndef CPU_INTERNAL_H
|
||||
#define CPU_INTERNAL_H
|
||||
|
||||
#include "common.h"
|
||||
|
||||
typedef enum {
|
||||
carry_flag = 0x01,
|
||||
zero_flag = 0x02,
|
||||
interrupt_flag = 0x04,
|
||||
decimal_flag = 0x08,
|
||||
break_flag = 0x10,
|
||||
unused_flag = 0x20,
|
||||
overflow_flag = 0x40,
|
||||
negative_flag = 0x80
|
||||
} cpu_p_flag;
|
||||
|
||||
typedef enum {
|
||||
carry_bp = 0,
|
||||
zero_bp = 1,
|
||||
interrupt_bp = 2,
|
||||
decimal_bp = 3,
|
||||
break_bp = 4,
|
||||
unused_bp = 5,
|
||||
overflow_bp = 6,
|
||||
negative_bp = 7
|
||||
} cpu_p_bp;
|
||||
|
||||
typedef struct {
|
||||
word PC; // Program Counter,
|
||||
byte SP; // Stack Pointer,
|
||||
byte A, X, Y; // Registers
|
||||
byte P; // Flag Register
|
||||
} CPU_STATE;
|
||||
|
||||
extern CPU_STATE cpu;
|
||||
|
||||
extern byte CPU_RAM[0x8000];
|
||||
extern int op_value, op_address; // Arguments for current instruction
|
||||
extern int op_cycles; // Additional instruction cycles used (e.g. when paging occurs)
|
||||
|
||||
byte cpu_ram_read(word address);
|
||||
void cpu_ram_write(word address, byte data);
|
||||
|
||||
// Interrupt Addresses
|
||||
word cpu_nmi_interrupt_address();
|
||||
word cpu_reset_interrupt_address();
|
||||
word cpu_irq_interrupt_address();
|
||||
|
||||
// CPU Adressing Modes
|
||||
void cpu_address_implied();
|
||||
void cpu_address_immediate();
|
||||
void cpu_address_zero_page();
|
||||
void cpu_address_zero_page_x();
|
||||
void cpu_address_zero_page_y();
|
||||
void cpu_address_absolute();
|
||||
void cpu_address_absolute_x();
|
||||
void cpu_address_absolute_y();
|
||||
void cpu_address_relative();
|
||||
void cpu_address_indirect();
|
||||
void cpu_address_indirect_x();
|
||||
void cpu_address_indirect_y();
|
||||
|
||||
#endif
|
606
am-kernels/kernels/litenes/src/cpu.c
Normal file
606
am-kernels/kernels/litenes/src/cpu.c
Normal file
|
@ -0,0 +1,606 @@
|
|||
#include "cpu.h"
|
||||
#include "cpu-internal.h"
|
||||
#include "memory.h"
|
||||
#include "ppu.h"
|
||||
#include "common.h"
|
||||
|
||||
CPU_STATE cpu;
|
||||
|
||||
// CPU Memory
|
||||
|
||||
byte CPU_RAM[0x8000];
|
||||
|
||||
byte cpu_ram_read(word address) {
|
||||
return CPU_RAM[address & 0x7FF];
|
||||
}
|
||||
|
||||
void cpu_ram_write(word address, byte data) {
|
||||
CPU_RAM[address & 0x7FF] = data;
|
||||
}
|
||||
|
||||
static byte op_code; // Current instruction code
|
||||
int op_value, op_address; // Arguments for current instruction
|
||||
int op_cycles; // Additional instruction cycles used (e.g. when paging occurs)
|
||||
static unsigned long long cpu_cycles; // Total CPU Cycles Since Power Up (wraps)
|
||||
|
||||
static void (*cpu_op_address_mode[256])(); // Array of address modes
|
||||
static void (*cpu_op_handler[256])(); // Array of instruction function pointers
|
||||
static bool cpu_op_in_base_instruction_set[256]; // true if instruction is in base 6502 instruction set
|
||||
static char *cpu_op_name[256]; // Instruction names
|
||||
static int cpu_op_cycles[256]; // CPU cycles used by instructions
|
||||
|
||||
static const byte cpu_zn_flag_table[256] = {
|
||||
zero_flag,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
negative_flag,negative_flag,negative_flag,negative_flag,negative_flag,negative_flag,negative_flag,negative_flag,
|
||||
negative_flag,negative_flag,negative_flag,negative_flag,negative_flag,negative_flag,negative_flag,negative_flag,
|
||||
negative_flag,negative_flag,negative_flag,negative_flag,negative_flag,negative_flag,negative_flag,negative_flag,
|
||||
negative_flag,negative_flag,negative_flag,negative_flag,negative_flag,negative_flag,negative_flag,negative_flag,
|
||||
negative_flag,negative_flag,negative_flag,negative_flag,negative_flag,negative_flag,negative_flag,negative_flag,
|
||||
negative_flag,negative_flag,negative_flag,negative_flag,negative_flag,negative_flag,negative_flag,negative_flag,
|
||||
negative_flag,negative_flag,negative_flag,negative_flag,negative_flag,negative_flag,negative_flag,negative_flag,
|
||||
negative_flag,negative_flag,negative_flag,negative_flag,negative_flag,negative_flag,negative_flag,negative_flag,
|
||||
negative_flag,negative_flag,negative_flag,negative_flag,negative_flag,negative_flag,negative_flag,negative_flag,
|
||||
negative_flag,negative_flag,negative_flag,negative_flag,negative_flag,negative_flag,negative_flag,negative_flag,
|
||||
negative_flag,negative_flag,negative_flag,negative_flag,negative_flag,negative_flag,negative_flag,negative_flag,
|
||||
negative_flag,negative_flag,negative_flag,negative_flag,negative_flag,negative_flag,negative_flag,negative_flag,
|
||||
negative_flag,negative_flag,negative_flag,negative_flag,negative_flag,negative_flag,negative_flag,negative_flag,
|
||||
negative_flag,negative_flag,negative_flag,negative_flag,negative_flag,negative_flag,negative_flag,negative_flag,
|
||||
negative_flag,negative_flag,negative_flag,negative_flag,negative_flag,negative_flag,negative_flag,negative_flag,
|
||||
negative_flag,negative_flag,negative_flag,negative_flag,negative_flag,negative_flag,negative_flag,negative_flag,
|
||||
};
|
||||
|
||||
// Interrupt Addresses
|
||||
|
||||
word cpu_nmi_interrupt_address() { return memory_readw(0xFFFA); }
|
||||
word cpu_reset_interrupt_address() { return memory_readw(0xFFFC); }
|
||||
word cpu_irq_interrupt_address() { return memory_readw(0xFFFE); }
|
||||
|
||||
// Stack Routines
|
||||
|
||||
void cpu_stack_pushb(byte data) { memory_writeb(0x100 + cpu.SP--, data); }
|
||||
void cpu_stack_pushw(word data) { memory_writew(0xFF + cpu.SP, data); cpu.SP -= 2; }
|
||||
byte cpu_stack_popb() { return memory_readb(0x100 + ++cpu.SP); }
|
||||
word cpu_stack_popw() { cpu.SP += 2; return memory_readw(0xFF + cpu.SP); }
|
||||
|
||||
// CPU Instructions
|
||||
|
||||
void ____FE____() { /* Instruction for future Extension */ }
|
||||
|
||||
#define cpu_flag_set(flag) common_bit_set(cpu.P, flag)
|
||||
#define cpu_modify_flag(flag, value) common_modify_bitb(&cpu.P, flag, value)
|
||||
#define cpu_set_flag(flag) common_set_bitb(&cpu.P, flag)
|
||||
#define cpu_unset_flag(flag) common_unset_bitb(&cpu.P, flag)
|
||||
|
||||
#define cpu_update_zn_flags(value) cpu.P = (cpu.P & ~(zero_flag | negative_flag)) | cpu_zn_flag_table[value]
|
||||
|
||||
#define cpu_branch(flag) if (flag) cpu.PC = op_address;
|
||||
#define cpu_compare(reg) \
|
||||
int result = reg - op_value; \
|
||||
cpu_modify_flag(carry_bp, result >= 0); \
|
||||
cpu_modify_flag(zero_bp, result == 0); \
|
||||
cpu_modify_flag(negative_bp, (result >> 7) & 1);
|
||||
|
||||
|
||||
// CPU Instructions
|
||||
|
||||
// NOP
|
||||
|
||||
void cpu_op_nop() {}
|
||||
|
||||
// Addition
|
||||
|
||||
void cpu_op_adc() {
|
||||
int result = cpu.A + op_value + (cpu_flag_set(carry_bp) ? 1 : 0);
|
||||
cpu_modify_flag(carry_bp, !!(result & 0x100));
|
||||
cpu_modify_flag(overflow_bp, !!(~(cpu.A ^ op_value) & (cpu.A ^ result) & 0x80));
|
||||
cpu.A = result & 0xFF;
|
||||
cpu_update_zn_flags(cpu.A);
|
||||
}
|
||||
|
||||
// Subtraction
|
||||
|
||||
void cpu_op_sbc() {
|
||||
int result = cpu.A - op_value - (cpu_flag_set(carry_bp) ? 0 : 1);
|
||||
cpu_modify_flag(carry_bp, !(result & 0x100));
|
||||
cpu_modify_flag(overflow_bp, !!((cpu.A ^ op_value) & (cpu.A ^ result) & 0x80));
|
||||
cpu.A = result & 0xFF;
|
||||
cpu_update_zn_flags(cpu.A);
|
||||
}
|
||||
|
||||
// Bit Manipulation Operations
|
||||
|
||||
void cpu_op_and() { cpu_update_zn_flags(cpu.A &= op_value); }
|
||||
void cpu_op_bit() {
|
||||
cpu_modify_flag(zero_bp, !(cpu.A & op_value));
|
||||
cpu.P = (cpu.P & 0x3F) | (0xC0 & op_value);
|
||||
}
|
||||
void cpu_op_eor() { cpu_update_zn_flags(cpu.A ^= op_value); }
|
||||
void cpu_op_ora() { cpu_update_zn_flags(cpu.A |= op_value); }
|
||||
void cpu_op_asla() {
|
||||
cpu_modify_flag(carry_bp, cpu.A & 0x80);
|
||||
cpu.A <<= 1;
|
||||
cpu_update_zn_flags(cpu.A);
|
||||
}
|
||||
void cpu_op_asl() {
|
||||
cpu_modify_flag(carry_bp, op_value & 0x80);
|
||||
op_value <<= 1;
|
||||
op_value &= 0xFF;
|
||||
cpu_update_zn_flags(op_value);
|
||||
memory_writeb(op_address, op_value);
|
||||
}
|
||||
void cpu_op_lsra() {
|
||||
int value = cpu.A >> 1;
|
||||
cpu_modify_flag(carry_bp, cpu.A & 0x01);
|
||||
cpu.A = value & 0xFF;
|
||||
cpu_update_zn_flags(value);
|
||||
}
|
||||
void cpu_op_lsr() {
|
||||
cpu_modify_flag(carry_bp, op_value & 0x01);
|
||||
op_value >>= 1;
|
||||
op_value &= 0xFF;
|
||||
memory_writeb(op_address, op_value);
|
||||
cpu_update_zn_flags(op_value);
|
||||
}
|
||||
|
||||
void cpu_op_rola() {
|
||||
int value = cpu.A << 1;
|
||||
value |= cpu_flag_set(carry_bp) ? 1 : 0;
|
||||
cpu_modify_flag(carry_bp, value > 0xFF);
|
||||
cpu.A = value & 0xFF;
|
||||
cpu_update_zn_flags(cpu.A);
|
||||
}
|
||||
void cpu_op_rol() {
|
||||
op_value <<= 1;
|
||||
op_value |= cpu_flag_set(carry_bp) ? 1 : 0;
|
||||
cpu_modify_flag(carry_bp, op_value > 0xFF);
|
||||
op_value &= 0xFF;
|
||||
memory_writeb(op_address, op_value);
|
||||
cpu_update_zn_flags(op_value);
|
||||
}
|
||||
void cpu_op_rora() {
|
||||
unsigned char carry = cpu_flag_set(carry_bp);
|
||||
cpu_modify_flag(carry_bp, cpu.A & 0x01);
|
||||
cpu.A = (cpu.A >> 1) | (carry << 7);
|
||||
cpu_modify_flag(zero_bp, cpu.A == 0);
|
||||
cpu_modify_flag(negative_bp, !!carry);
|
||||
}
|
||||
void cpu_op_ror() {
|
||||
unsigned char carry = cpu_flag_set(carry_bp);
|
||||
cpu_modify_flag(carry_bp, op_value & 0x01);
|
||||
op_value = ((op_value >> 1) | (carry << 7)) & 0xFF;
|
||||
cpu_modify_flag(zero_bp, op_value == 0);
|
||||
cpu_modify_flag(negative_bp, !!carry);
|
||||
memory_writeb(op_address, op_value);
|
||||
}
|
||||
|
||||
// Loading
|
||||
|
||||
void cpu_op_lda() { cpu_update_zn_flags(cpu.A = op_value); }
|
||||
void cpu_op_ldx() { cpu_update_zn_flags(cpu.X = op_value); }
|
||||
void cpu_op_ldy() { cpu_update_zn_flags(cpu.Y = op_value); }
|
||||
|
||||
// Storing
|
||||
|
||||
void cpu_op_sta() { memory_writeb(op_address, cpu.A); }
|
||||
void cpu_op_stx() { memory_writeb(op_address, cpu.X); }
|
||||
void cpu_op_sty() { memory_writeb(op_address, cpu.Y); }
|
||||
|
||||
// Transfering
|
||||
|
||||
void cpu_op_tax() { cpu_update_zn_flags(cpu.X = cpu.A); }
|
||||
void cpu_op_txa() { cpu_update_zn_flags(cpu.A = cpu.X); }
|
||||
void cpu_op_tay() { cpu_update_zn_flags(cpu.Y = cpu.A); }
|
||||
void cpu_op_tya() { cpu_update_zn_flags(cpu.A = cpu.Y); }
|
||||
void cpu_op_tsx() { cpu_update_zn_flags(cpu.X = cpu.SP); }
|
||||
void cpu_op_txs() { cpu.SP = cpu.X; }
|
||||
|
||||
// Branching Positive
|
||||
|
||||
void cpu_op_bcs() { cpu_branch(cpu_flag_set(carry_bp)); }
|
||||
void cpu_op_beq() { cpu_branch(cpu_flag_set(zero_bp)); }
|
||||
void cpu_op_bmi() { cpu_branch(cpu_flag_set(negative_bp)); }
|
||||
void cpu_op_bvs() { cpu_branch(cpu_flag_set(overflow_bp)); }
|
||||
|
||||
// Branching Negative
|
||||
|
||||
void cpu_op_bne() { cpu_branch(!cpu_flag_set(zero_bp)); }
|
||||
void cpu_op_bcc() { cpu_branch(!cpu_flag_set(carry_bp)); }
|
||||
void cpu_op_bpl() { cpu_branch(!cpu_flag_set(negative_bp)); }
|
||||
void cpu_op_bvc() { cpu_branch(!cpu_flag_set(overflow_bp)); }
|
||||
|
||||
// Jumping
|
||||
|
||||
void cpu_op_jmp() { cpu.PC = op_address; }
|
||||
|
||||
// Subroutines
|
||||
|
||||
void cpu_op_jsr() { cpu_stack_pushw(cpu.PC - 1); cpu.PC = op_address; }
|
||||
void cpu_op_rts() { cpu.PC = cpu_stack_popw() + 1; }
|
||||
|
||||
// Interruptions
|
||||
|
||||
void cpu_op_brk() {
|
||||
cpu_stack_pushw(cpu.PC - 1);
|
||||
cpu_stack_pushb(cpu.P);
|
||||
cpu.P |= unused_flag | break_flag;
|
||||
cpu.PC = cpu_nmi_interrupt_address();
|
||||
}
|
||||
void cpu_op_rti() { cpu.P = cpu_stack_popb() | unused_flag; cpu.PC = cpu_stack_popw(); }
|
||||
|
||||
// Flags
|
||||
|
||||
void cpu_op_clc() { cpu_unset_flag(carry_bp); }
|
||||
void cpu_op_cld() { cpu_unset_flag(decimal_bp); }
|
||||
void cpu_op_cli() { cpu_unset_flag(interrupt_bp); }
|
||||
void cpu_op_clv() { cpu_unset_flag(overflow_bp); }
|
||||
void cpu_op_sec() { cpu_set_flag(carry_bp); }
|
||||
void cpu_op_sed() { cpu_set_flag(decimal_bp); }
|
||||
void cpu_op_sei() { cpu_set_flag(interrupt_bp); }
|
||||
|
||||
// Comparison
|
||||
|
||||
void cpu_op_cmp() { cpu_compare(cpu.A); }
|
||||
void cpu_op_cpx() { cpu_compare(cpu.X); }
|
||||
void cpu_op_cpy() { cpu_compare(cpu.Y); }
|
||||
|
||||
// Increment
|
||||
|
||||
void cpu_op_inc() {
|
||||
byte result = op_value + 1;
|
||||
memory_writeb(op_address, result);
|
||||
cpu_update_zn_flags(result);
|
||||
}
|
||||
void cpu_op_inx() { cpu_update_zn_flags(++cpu.X); }
|
||||
void cpu_op_iny() { cpu_update_zn_flags(++cpu.Y); }
|
||||
|
||||
// Decrement
|
||||
|
||||
void cpu_op_dec() {
|
||||
byte result = op_value - 1;
|
||||
memory_writeb(op_address, result);
|
||||
cpu_update_zn_flags(result);
|
||||
}
|
||||
void cpu_op_dex() { cpu_update_zn_flags(--cpu.X); }
|
||||
void cpu_op_dey() { cpu_update_zn_flags(--cpu.Y); }
|
||||
|
||||
// Stack
|
||||
|
||||
void cpu_op_php() { cpu_stack_pushb(cpu.P | 0x30); }
|
||||
void cpu_op_pha() { cpu_stack_pushb(cpu.A); }
|
||||
void cpu_op_pla() { cpu.A = cpu_stack_popb(); cpu_update_zn_flags(cpu.A); }
|
||||
void cpu_op_plp() { cpu.P = (cpu_stack_popb() & 0xEF) | 0x20; }
|
||||
|
||||
|
||||
// Extended Instruction Set
|
||||
|
||||
void cpu_op_aso() { cpu_op_asl(); cpu_op_ora(); }
|
||||
void cpu_op_axa() { memory_writeb(op_address, cpu.A & cpu.X & (op_address >> 8)); }
|
||||
void cpu_op_axs() { memory_writeb(op_address, cpu.A & cpu.X); }
|
||||
void cpu_op_dcm()
|
||||
{
|
||||
op_value--;
|
||||
op_value &= 0xFF;
|
||||
memory_writeb(op_address, op_value);
|
||||
cpu_op_cmp();
|
||||
}
|
||||
void cpu_op_ins()
|
||||
{
|
||||
op_value = (op_value + 1) & 0xFF;
|
||||
memory_writeb(op_address, op_value);
|
||||
cpu_op_sbc();
|
||||
}
|
||||
void cpu_op_lax() { cpu_update_zn_flags(cpu.A = cpu.X = op_value); }
|
||||
void cpu_op_lse() { cpu_op_lsr(); cpu_op_eor(); }
|
||||
void cpu_op_rla() { cpu_op_rol(); cpu_op_and(); }
|
||||
void cpu_op_rra() { cpu_op_ror(); cpu_op_adc(); }
|
||||
|
||||
|
||||
// Base 6502 instruction set
|
||||
|
||||
#define CPU_OP_BIS(o, c, f, n, a) \
|
||||
cpu_op_cycles[0x##o] = c; \
|
||||
cpu_op_handler[0x##o] = cpu_op_##f; \
|
||||
cpu_op_name[0x##o] = n; \
|
||||
cpu_op_address_mode[0x##o] = cpu_address_##a; \
|
||||
cpu_op_in_base_instruction_set[0x##o] = true;
|
||||
|
||||
// Not implemented instructions
|
||||
|
||||
#define CPU_OP_NII(o, a) \
|
||||
cpu_op_cycles[0x##o] = 1; \
|
||||
cpu_op_handler[0x##o] = ____FE____; \
|
||||
cpu_op_name[0x##o] = "NOP"; \
|
||||
cpu_op_address_mode[0x##o] = cpu_address_##a; \
|
||||
cpu_op_in_base_instruction_set[0x##o] = false;
|
||||
|
||||
// Extended instruction set found in other CPUs and implemented for compatibility
|
||||
|
||||
#define CPU_OP_EIS(o, c, f, n, a) \
|
||||
cpu_op_cycles[0x##o] = c; \
|
||||
cpu_op_handler[0x##o] = cpu_op_##f; \
|
||||
cpu_op_name[0x##o] = n; \
|
||||
cpu_op_address_mode[0x##o] = cpu_address_##a; \
|
||||
cpu_op_in_base_instruction_set[0x##o] = false;
|
||||
|
||||
// CPU Lifecycle
|
||||
|
||||
void cpu_init() {
|
||||
CPU_OP_BIS(00, 7, brk, "BRK", implied)
|
||||
CPU_OP_BIS(01, 6, ora, "ORA", indirect_x)
|
||||
CPU_OP_BIS(05, 3, ora, "ORA", zero_page)
|
||||
CPU_OP_BIS(06, 5, asl, "ASL", zero_page)
|
||||
CPU_OP_BIS(08, 3, php, "PHP", implied)
|
||||
CPU_OP_BIS(09, 2, ora, "ORA", immediate)
|
||||
CPU_OP_BIS(0A, 2, asla,"ASL", implied)
|
||||
CPU_OP_BIS(0D, 4, ora, "ORA", absolute)
|
||||
CPU_OP_BIS(0E, 6, asl, "ASL", absolute)
|
||||
CPU_OP_BIS(10, 2, bpl, "BPL", relative)
|
||||
CPU_OP_BIS(11, 5, ora, "ORA", indirect_y)
|
||||
CPU_OP_BIS(15, 4, ora, "ORA", zero_page_x)
|
||||
CPU_OP_BIS(16, 6, asl, "ASL", zero_page_x)
|
||||
CPU_OP_BIS(18, 2, clc, "CLC", implied)
|
||||
CPU_OP_BIS(19, 4, ora, "ORA", absolute_y)
|
||||
CPU_OP_BIS(1D, 4, ora, "ORA", absolute_x)
|
||||
CPU_OP_BIS(1E, 7, asl, "ASL", absolute_x)
|
||||
CPU_OP_BIS(20, 6, jsr, "JSR", absolute)
|
||||
CPU_OP_BIS(21, 6, and, "AND", indirect_x)
|
||||
CPU_OP_BIS(24, 3, bit, "BIT", zero_page)
|
||||
CPU_OP_BIS(25, 3, and, "AND", zero_page)
|
||||
CPU_OP_BIS(26, 5, rol, "ROL", zero_page)
|
||||
CPU_OP_BIS(28, 4, plp, "PLP", implied)
|
||||
CPU_OP_BIS(29, 2, and, "AND", immediate)
|
||||
CPU_OP_BIS(2A, 2, rola,"ROL", implied)
|
||||
CPU_OP_BIS(2C, 4, bit, "BIT", absolute)
|
||||
CPU_OP_BIS(2D, 2, and, "AND", absolute)
|
||||
CPU_OP_BIS(2E, 6, rol, "ROL", absolute)
|
||||
CPU_OP_BIS(30, 2, bmi, "BMI", relative)
|
||||
CPU_OP_BIS(31, 5, and, "AND", indirect_y)
|
||||
CPU_OP_BIS(35, 4, and, "AND", zero_page_x)
|
||||
CPU_OP_BIS(36, 6, rol, "ROL", zero_page_x)
|
||||
CPU_OP_BIS(38, 2, sec, "SEC", implied)
|
||||
CPU_OP_BIS(39, 4, and, "AND", absolute_y)
|
||||
CPU_OP_BIS(3D, 4, and, "AND", absolute_x)
|
||||
CPU_OP_BIS(3E, 7, rol, "ROL", absolute_x)
|
||||
CPU_OP_BIS(40, 6, rti, "RTI", implied)
|
||||
CPU_OP_BIS(41, 6, eor, "EOR", indirect_x)
|
||||
CPU_OP_BIS(45, 3, eor, "EOR", zero_page)
|
||||
CPU_OP_BIS(46, 5, lsr, "LSR", zero_page)
|
||||
CPU_OP_BIS(48, 3, pha, "PHA", implied)
|
||||
CPU_OP_BIS(49, 2, eor, "EOR", immediate)
|
||||
CPU_OP_BIS(4A, 2, lsra,"LSR", implied)
|
||||
CPU_OP_BIS(4C, 3, jmp, "JMP", absolute)
|
||||
CPU_OP_BIS(4D, 4, eor, "EOR", absolute)
|
||||
CPU_OP_BIS(4E, 6, lsr, "LSR", absolute)
|
||||
CPU_OP_BIS(50, 2, bvc, "BVC", relative)
|
||||
CPU_OP_BIS(51, 5, eor, "EOR", indirect_y)
|
||||
CPU_OP_BIS(55, 4, eor, "EOR", zero_page_x)
|
||||
CPU_OP_BIS(56, 6, lsr, "LSR", zero_page_x)
|
||||
CPU_OP_BIS(58, 2, cli, "CLI", implied)
|
||||
CPU_OP_BIS(59, 4, eor, "EOR", absolute_y)
|
||||
CPU_OP_BIS(5D, 4, eor, "EOR", absolute_x)
|
||||
CPU_OP_BIS(5E, 7, lsr, "LSR", absolute_x)
|
||||
CPU_OP_BIS(60, 6, rts, "RTS", implied)
|
||||
CPU_OP_BIS(61, 6, adc, "ADC", indirect_x)
|
||||
CPU_OP_BIS(65, 3, adc, "ADC", zero_page)
|
||||
CPU_OP_BIS(66, 5, ror, "ROR", zero_page)
|
||||
CPU_OP_BIS(68, 4, pla, "PLA", implied)
|
||||
CPU_OP_BIS(69, 2, adc, "ADC", immediate)
|
||||
CPU_OP_BIS(6A, 2, rora,"ROR", implied)
|
||||
CPU_OP_BIS(6C, 5, jmp, "JMP", indirect)
|
||||
CPU_OP_BIS(6D, 4, adc, "ADC", absolute)
|
||||
CPU_OP_BIS(6E, 6, ror, "ROR", absolute)
|
||||
CPU_OP_BIS(70, 2, bvs, "BVS", relative)
|
||||
CPU_OP_BIS(71, 5, adc, "ADC", indirect_y)
|
||||
CPU_OP_BIS(75, 4, adc, "ADC", zero_page_x)
|
||||
CPU_OP_BIS(76, 6, ror, "ROR", zero_page_x)
|
||||
CPU_OP_BIS(78, 2, sei, "SEI", implied)
|
||||
CPU_OP_BIS(79, 4, adc, "ADC", absolute_y)
|
||||
CPU_OP_BIS(7D, 4, adc, "ADC", absolute_x)
|
||||
CPU_OP_BIS(7E, 7, ror, "ROR", absolute_x)
|
||||
CPU_OP_BIS(81, 6, sta, "STA", indirect_x)
|
||||
CPU_OP_BIS(84, 3, sty, "STY", zero_page)
|
||||
CPU_OP_BIS(85, 3, sta, "STA", zero_page)
|
||||
CPU_OP_BIS(86, 3, stx, "STX", zero_page)
|
||||
CPU_OP_BIS(88, 2, dey, "DEY", implied)
|
||||
CPU_OP_BIS(8A, 2, txa, "TXA", implied)
|
||||
CPU_OP_BIS(8C, 4, sty, "STY", absolute)
|
||||
CPU_OP_BIS(8D, 4, sta, "STA", absolute)
|
||||
CPU_OP_BIS(8E, 4, stx, "STX", absolute)
|
||||
CPU_OP_BIS(90, 2, bcc, "BCC", relative)
|
||||
CPU_OP_BIS(91, 6, sta, "STA", indirect_y)
|
||||
CPU_OP_BIS(94, 4, sty, "STY", zero_page_x)
|
||||
CPU_OP_BIS(95, 4, sta, "STA", zero_page_x)
|
||||
CPU_OP_BIS(96, 4, stx, "STX", zero_page_y)
|
||||
CPU_OP_BIS(98, 2, tya, "TYA", implied)
|
||||
CPU_OP_BIS(99, 5, sta, "STA", absolute_y)
|
||||
CPU_OP_BIS(9A, 2, txs, "TXS", implied)
|
||||
CPU_OP_BIS(9D, 5, sta, "STA", absolute_x)
|
||||
CPU_OP_BIS(A0, 2, ldy, "LDY", immediate)
|
||||
CPU_OP_BIS(A1, 6, lda, "LDA", indirect_x)
|
||||
CPU_OP_BIS(A2, 2, ldx, "LDX", immediate)
|
||||
CPU_OP_BIS(A4, 3, ldy, "LDY", zero_page)
|
||||
CPU_OP_BIS(A5, 3, lda, "LDA", zero_page)
|
||||
CPU_OP_BIS(A6, 3, ldx, "LDX", zero_page)
|
||||
CPU_OP_BIS(A8, 2, tay, "TAY", implied)
|
||||
CPU_OP_BIS(A9, 2, lda, "LDA", immediate)
|
||||
CPU_OP_BIS(AA, 2, tax, "TAX", implied)
|
||||
CPU_OP_BIS(AC, 4, ldy, "LDY", absolute)
|
||||
CPU_OP_BIS(AD, 4, lda, "LDA", absolute)
|
||||
CPU_OP_BIS(AE, 4, ldx, "LDX", absolute)
|
||||
CPU_OP_BIS(B0, 2, bcs, "BCS", relative)
|
||||
CPU_OP_BIS(B1, 5, lda, "LDA", indirect_y)
|
||||
CPU_OP_BIS(B4, 4, ldy, "LDY", zero_page_x)
|
||||
CPU_OP_BIS(B5, 4, lda, "LDA", zero_page_x)
|
||||
CPU_OP_BIS(B6, 4, ldx, "LDX", zero_page_y)
|
||||
CPU_OP_BIS(B8, 2, clv, "CLV", implied)
|
||||
CPU_OP_BIS(B9, 4, lda, "LDA", absolute_y)
|
||||
CPU_OP_BIS(BA, 2, tsx, "TSX", implied)
|
||||
CPU_OP_BIS(BC, 4, ldy, "LDY", absolute_x)
|
||||
CPU_OP_BIS(BD, 4, lda, "LDA", absolute_x)
|
||||
CPU_OP_BIS(BE, 4, ldx, "LDX", absolute_y)
|
||||
CPU_OP_BIS(C0, 2, cpy, "CPY", immediate)
|
||||
CPU_OP_BIS(C1, 6, cmp, "CMP", indirect_x)
|
||||
CPU_OP_BIS(C4, 3, cpy, "CPY", zero_page)
|
||||
CPU_OP_BIS(C5, 3, cmp, "CMP", zero_page)
|
||||
CPU_OP_BIS(C6, 5, dec, "DEC", zero_page)
|
||||
CPU_OP_BIS(C8, 2, iny, "INY", implied)
|
||||
CPU_OP_BIS(C9, 2, cmp, "CMP", immediate)
|
||||
CPU_OP_BIS(CA, 2, dex, "DEX", implied)
|
||||
CPU_OP_BIS(CC, 4, cpy, "CPY", absolute)
|
||||
CPU_OP_BIS(CD, 4, cmp, "CMP", absolute)
|
||||
CPU_OP_BIS(CE, 6, dec, "DEC", absolute)
|
||||
CPU_OP_BIS(D0, 2, bne, "BNE", relative)
|
||||
CPU_OP_BIS(D1, 5, cmp, "CMP", indirect_y)
|
||||
CPU_OP_BIS(D5, 4, cmp, "CMP", zero_page_x)
|
||||
CPU_OP_BIS(D6, 6, dec, "DEC", zero_page_x)
|
||||
CPU_OP_BIS(D8, 2, cld, "CLD", implied)
|
||||
CPU_OP_BIS(D9, 4, cmp, "CMP", absolute_y)
|
||||
CPU_OP_BIS(DD, 4, cmp, "CMP", absolute_x)
|
||||
CPU_OP_BIS(DE, 7, dec, "DEC", absolute_x)
|
||||
CPU_OP_BIS(E0, 2, cpx, "CPX", immediate)
|
||||
CPU_OP_BIS(E1, 6, sbc, "SBC", indirect_x)
|
||||
CPU_OP_BIS(E4, 3, cpx, "CPX", zero_page)
|
||||
CPU_OP_BIS(E5, 3, sbc, "SBC", zero_page)
|
||||
CPU_OP_BIS(E6, 5, inc, "INC", zero_page)
|
||||
CPU_OP_BIS(E8, 2, inx, "INX", implied)
|
||||
CPU_OP_BIS(E9, 2, sbc, "SBC", immediate)
|
||||
CPU_OP_BIS(EA, 2, nop, "NOP", implied)
|
||||
CPU_OP_BIS(EC, 4, cpx, "CPX", absolute)
|
||||
CPU_OP_BIS(ED, 4, sbc, "SBC", absolute)
|
||||
CPU_OP_BIS(EE, 6, inc, "INC", absolute)
|
||||
CPU_OP_BIS(F0, 2, beq, "BEQ", relative)
|
||||
CPU_OP_BIS(F1, 5, sbc, "SBC", indirect_y)
|
||||
CPU_OP_BIS(F5, 4, sbc, "SBC", zero_page_x)
|
||||
CPU_OP_BIS(F6, 6, inc, "INC", zero_page_x)
|
||||
CPU_OP_BIS(F8, 2, sed, "SED", implied)
|
||||
CPU_OP_BIS(F9, 4, sbc, "SBC", absolute_y)
|
||||
CPU_OP_BIS(FD, 4, sbc, "SBC", absolute_x)
|
||||
CPU_OP_BIS(FE, 7, inc, "INC", absolute_x)
|
||||
|
||||
CPU_OP_EIS(03, 8, aso, "SLO", indirect_x)
|
||||
CPU_OP_EIS(07, 5, aso, "SLO", zero_page)
|
||||
CPU_OP_EIS(0F, 6, aso, "SLO", absolute)
|
||||
CPU_OP_EIS(13, 8, aso, "SLO", indirect_y)
|
||||
CPU_OP_EIS(17, 6, aso, "SLO", zero_page_x)
|
||||
CPU_OP_EIS(1B, 7, aso, "SLO", absolute_y)
|
||||
CPU_OP_EIS(1F, 7, aso, "SLO", absolute_x)
|
||||
CPU_OP_EIS(23, 8, rla, "RLA", indirect_x)
|
||||
CPU_OP_EIS(27, 5, rla, "RLA", zero_page)
|
||||
CPU_OP_EIS(2F, 6, rla, "RLA", absolute)
|
||||
CPU_OP_EIS(33, 8, rla, "RLA", indirect_y)
|
||||
CPU_OP_EIS(37, 6, rla, "RLA", zero_page_x)
|
||||
CPU_OP_EIS(3B, 7, rla, "RLA", absolute_y)
|
||||
CPU_OP_EIS(3F, 7, rla, "RLA", absolute_x)
|
||||
CPU_OP_EIS(43, 8, lse, "SRE", indirect_x)
|
||||
CPU_OP_EIS(47, 5, lse, "SRE", zero_page)
|
||||
CPU_OP_EIS(4F, 6, lse, "SRE", absolute)
|
||||
CPU_OP_EIS(53, 8, lse, "SRE", indirect_y)
|
||||
CPU_OP_EIS(57, 6, lse, "SRE", zero_page_x)
|
||||
CPU_OP_EIS(5B, 7, lse, "SRE", absolute_y)
|
||||
CPU_OP_EIS(5F, 7, lse, "SRE", absolute_x)
|
||||
CPU_OP_EIS(63, 8, rra, "RRA", indirect_x)
|
||||
CPU_OP_EIS(67, 5, rra, "RRA", zero_page)
|
||||
CPU_OP_EIS(6F, 6, rra, "RRA", absolute)
|
||||
CPU_OP_EIS(73, 8, rra, "RRA", indirect_y)
|
||||
CPU_OP_EIS(77, 6, rra, "RRA", zero_page_x)
|
||||
CPU_OP_EIS(7B, 7, rra, "RRA", absolute_y)
|
||||
CPU_OP_EIS(7F, 7, rra, "RRA", absolute_x)
|
||||
CPU_OP_EIS(83, 6, axs, "SAX", indirect_x)
|
||||
CPU_OP_EIS(87, 3, axs, "SAX", zero_page)
|
||||
CPU_OP_EIS(8F, 4, axs, "SAX", absolute)
|
||||
CPU_OP_EIS(93, 6, axa, "SAX", indirect_y)
|
||||
CPU_OP_EIS(97, 4, axs, "SAX", zero_page_y)
|
||||
CPU_OP_EIS(9F, 5, axa, "SAX", absolute_y)
|
||||
CPU_OP_EIS(A3, 6, lax, "LAX", indirect_x)
|
||||
CPU_OP_EIS(A7, 3, lax, "LAX", zero_page)
|
||||
CPU_OP_EIS(AF, 4, lax, "LAX", absolute)
|
||||
CPU_OP_EIS(B3, 5, lax, "LAX", indirect_y)
|
||||
CPU_OP_EIS(B7, 4, lax, "LAX", zero_page_y)
|
||||
CPU_OP_EIS(BF, 4, lax, "LAX", absolute_y)
|
||||
CPU_OP_EIS(C3, 8, dcm, "DCP", indirect_x)
|
||||
CPU_OP_EIS(C7, 5, dcm, "DCP", zero_page)
|
||||
CPU_OP_EIS(CF, 6, dcm, "DCP", absolute)
|
||||
CPU_OP_EIS(D3, 8, dcm, "DCP", indirect_y)
|
||||
CPU_OP_EIS(D7, 6, dcm, "DCP", zero_page_x)
|
||||
CPU_OP_EIS(DB, 7, dcm, "DCP", absolute_y)
|
||||
CPU_OP_EIS(DF, 7, dcm, "DCP", absolute_x)
|
||||
CPU_OP_EIS(E3, 8, ins, "ISB", indirect_x)
|
||||
CPU_OP_EIS(E7, 5, ins, "ISB", zero_page)
|
||||
CPU_OP_EIS(EB, 2, sbc, "SBC", immediate)
|
||||
CPU_OP_EIS(EF, 6, ins, "ISB", absolute)
|
||||
CPU_OP_EIS(F3, 8, ins, "ISB", indirect_y)
|
||||
CPU_OP_EIS(F7, 6, ins, "ISB", zero_page_x)
|
||||
CPU_OP_EIS(FB, 7, ins, "ISB", absolute_y)
|
||||
CPU_OP_EIS(FF, 7, ins, "ISB", absolute_x)
|
||||
|
||||
CPU_OP_NII(04, zero_page)
|
||||
CPU_OP_NII(0C, absolute)
|
||||
CPU_OP_NII(14, zero_page_x)
|
||||
CPU_OP_NII(1A, implied)
|
||||
CPU_OP_NII(1C, absolute_x)
|
||||
CPU_OP_NII(34, zero_page_x)
|
||||
CPU_OP_NII(3A, implied)
|
||||
CPU_OP_NII(3C, absolute_x)
|
||||
CPU_OP_NII(44, zero_page)
|
||||
CPU_OP_NII(54, zero_page_x)
|
||||
CPU_OP_NII(5A, implied)
|
||||
CPU_OP_NII(5C, absolute_x)
|
||||
CPU_OP_NII(64, zero_page)
|
||||
CPU_OP_NII(74, zero_page_x)
|
||||
CPU_OP_NII(7A, implied)
|
||||
CPU_OP_NII(7C, absolute_x)
|
||||
CPU_OP_NII(80, immediate)
|
||||
CPU_OP_NII(D4, zero_page_x)
|
||||
CPU_OP_NII(DA, implied)
|
||||
CPU_OP_NII(DC, absolute_x)
|
||||
CPU_OP_NII(F4, zero_page_x)
|
||||
CPU_OP_NII(FA, implied)
|
||||
CPU_OP_NII(FC, absolute_x)
|
||||
|
||||
cpu.P = 0x24;
|
||||
cpu.SP = 0x00;
|
||||
cpu.A = cpu.X = cpu.Y = 0;
|
||||
}
|
||||
|
||||
void cpu_reset() {
|
||||
cpu.PC = cpu_reset_interrupt_address();
|
||||
cpu.SP -= 3;
|
||||
cpu.P |= interrupt_flag;
|
||||
}
|
||||
|
||||
void cpu_interrupt() {
|
||||
if (ppu_generates_nmi()) {
|
||||
cpu.P |= interrupt_flag;
|
||||
cpu_unset_flag(unused_bp);
|
||||
cpu_stack_pushw(cpu.PC);
|
||||
cpu_stack_pushb(cpu.P);
|
||||
cpu.PC = cpu_nmi_interrupt_address();
|
||||
}
|
||||
}
|
||||
|
||||
unsigned long long cpu_clock() {
|
||||
return cpu_cycles;
|
||||
}
|
||||
|
||||
void cpu_run(long cycles) {
|
||||
cycles /= 3;
|
||||
while (cycles > 0) {
|
||||
op_code = memory_readb(cpu.PC++);
|
||||
if (cpu_op_address_mode[op_code] == NULL) {
|
||||
}
|
||||
else {
|
||||
cpu_op_address_mode[op_code]();
|
||||
cpu_op_handler[op_code]();
|
||||
}
|
||||
cycles -= cpu_op_cycles[op_code] + op_cycles;
|
||||
cpu_cycles -= cpu_op_cycles[op_code] + op_cycles;
|
||||
op_cycles = 0;
|
||||
}
|
||||
}
|
17
am-kernels/kernels/litenes/src/cpu.h
Normal file
17
am-kernels/kernels/litenes/src/cpu.h
Normal file
|
@ -0,0 +1,17 @@
|
|||
#include "common.h"
|
||||
|
||||
#ifndef CPU_H
|
||||
#define CPU_H
|
||||
|
||||
byte cpu_ram_read(word address);
|
||||
void cpu_ram_write(word address, byte data);
|
||||
|
||||
void cpu_init();
|
||||
void cpu_reset();
|
||||
void cpu_interrupt();
|
||||
void cpu_run(long cycles);
|
||||
|
||||
// CPU cycles that passed since power up
|
||||
unsigned long long cpu_clock();
|
||||
|
||||
#endif
|
140
am-kernels/kernels/litenes/src/fce.c
Normal file
140
am-kernels/kernels/litenes/src/fce.c
Normal file
|
@ -0,0 +1,140 @@
|
|||
#include "fce.h"
|
||||
#include "cpu.h"
|
||||
#include "memory.h"
|
||||
#include "ppu.h"
|
||||
#include "psg.h"
|
||||
#include <klib.h>
|
||||
|
||||
static int frame_cnt;
|
||||
static inline bool candraw() { return frame_cnt % (1 + FRAME_SKIP) == 0; }
|
||||
|
||||
static uint32_t canvas[SCR_W * SCR_H];
|
||||
|
||||
void draw(int x, int y, int idx) {
|
||||
if (x >= 0 && x < SCR_W && y >= 0 && y < SCR_H && candraw()) {
|
||||
canvas[y * SCR_W + x] = palette[idx];
|
||||
}
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
char signature[4];
|
||||
byte prg_block_count;
|
||||
byte chr_block_count;
|
||||
word rom_type;
|
||||
byte reserved[8];
|
||||
} ines_header;
|
||||
|
||||
static byte *buf;
|
||||
static ines_header *fce_rom_header;
|
||||
|
||||
byte *romread(int size) {
|
||||
byte *ret = buf;
|
||||
buf += size;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int fce_load_rom(char *rom) {
|
||||
buf = (byte*)rom;
|
||||
fce_rom_header = (ines_header*)romread(sizeof(ines_header));
|
||||
|
||||
if (memcmp(fce_rom_header->signature, "NES\x1A", 4)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
mmc_id = ((fce_rom_header->rom_type & 0xF0) >> 4);
|
||||
|
||||
int prg_size = fce_rom_header->prg_block_count * 0x4000;
|
||||
|
||||
byte *blk = romread(prg_size);
|
||||
|
||||
if (mmc_id == 0 || mmc_id == 3) {
|
||||
// if there is only one PRG block, we must repeat it twice
|
||||
if (fce_rom_header->prg_block_count == 1) {
|
||||
mmc_copy(0x8000, blk, 0x4000);
|
||||
mmc_copy(0xC000, blk, 0x4000);
|
||||
}
|
||||
else {
|
||||
mmc_copy(0x8000, blk, 0x8000);
|
||||
}
|
||||
}
|
||||
else {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Copying CHR pages into MMC and PPU
|
||||
int i;
|
||||
for (i = 0; i < fce_rom_header->chr_block_count; i++) {
|
||||
byte *blk = romread(0x2000);
|
||||
mmc_append_chr_rom_page(blk);
|
||||
|
||||
if (i == 0) {
|
||||
ppu_copy(0x0000, blk, 0x2000);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void fce_init() {
|
||||
cpu_init();
|
||||
ppu_init();
|
||||
ppu_set_mirroring(fce_rom_header->rom_type & 1);
|
||||
cpu_reset();
|
||||
}
|
||||
|
||||
static int gtime;
|
||||
|
||||
static inline int uptime_ms() {
|
||||
return io_read(AM_TIMER_UPTIME).us / 1000;
|
||||
}
|
||||
|
||||
void wait_for_frame() {
|
||||
int cur = uptime_ms();
|
||||
while (cur - gtime < 1000 / FPS) {
|
||||
cur = uptime_ms();
|
||||
}
|
||||
gtime = cur;
|
||||
}
|
||||
|
||||
// FCE Lifecycle
|
||||
|
||||
void fce_run() {
|
||||
gtime = uptime_ms();
|
||||
int nr_draw = 0;
|
||||
uint32_t last = gtime;
|
||||
while(1) {
|
||||
wait_for_frame();
|
||||
int scanlines = 262;
|
||||
|
||||
while (scanlines-- > 0) {
|
||||
ppu_cycle();
|
||||
psg_detect_key();
|
||||
}
|
||||
|
||||
nr_draw ++;
|
||||
int upt = uptime_ms();
|
||||
if (upt - last > 1000) {
|
||||
last = upt;
|
||||
for (int i = 0; i < 80; i++) putch('\b');
|
||||
printf("(System time: %ds) FPS = %d", upt / 1000, nr_draw);
|
||||
nr_draw = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void fce_update_screen() {
|
||||
frame_cnt++;
|
||||
if (!candraw()) return;
|
||||
|
||||
int idx = ppu_ram_read(0x3F00);
|
||||
uint32_t bgc = palette[idx];
|
||||
|
||||
AM_GPU_CONFIG_T cfg = io_read(AM_GPU_CONFIG);
|
||||
int xpad = (cfg.width - SCR_W) / 2;
|
||||
int ypad = (cfg.height - SCR_H) / 2;
|
||||
panic_on(xpad < 0 || ypad < 0, "screen too small");
|
||||
|
||||
io_write(AM_GPU_FBDRAW, xpad, ypad, canvas, SCR_W, SCR_H, true);
|
||||
|
||||
for (int i = 0; i < SCR_W * SCR_H; i ++) canvas[i] = bgc;
|
||||
}
|
28
am-kernels/kernels/litenes/src/fce.h
Normal file
28
am-kernels/kernels/litenes/src/fce.h
Normal file
|
@ -0,0 +1,28 @@
|
|||
#ifndef FCE_H
|
||||
#define FCE_H
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#define FPS 60
|
||||
#define SCR_W 256
|
||||
#define SCR_H 240
|
||||
#define FRAME_SKIP 1
|
||||
|
||||
void fce_update_screen();
|
||||
int fce_load_rom(char *rom);
|
||||
void fce_init();
|
||||
void fce_run();
|
||||
void draw(int x, int y, int idx);
|
||||
|
||||
static const uint32_t palette[64] = {
|
||||
0x808080, 0x0000BB, 0x3700BF, 0x8400A6, 0xBB006A, 0xB7001E, 0xB30000, 0x912600,
|
||||
0x7B2B00, 0x003E00, 0x00480D, 0x003C22, 0x002F66, 0x000000, 0x050505, 0x050505,
|
||||
0xC8C8C8, 0x0059FF, 0x443CFF, 0xB733CC, 0xFF33AA, 0xFF375E, 0xFF371A, 0xD54B00,
|
||||
0xC46200, 0x3C7B00, 0x1E8415, 0x009566, 0x0084C4, 0x111111, 0x090909, 0x090909,
|
||||
0xFFFFFF, 0x0095FF, 0x6F84FF, 0xD56FFF, 0xFF77CC, 0xFF6F99, 0xFF7B59, 0xFF915F,
|
||||
0xFFA233, 0xA6BF00, 0x51D96A, 0x4DD5AE, 0x00D9FF, 0x666666, 0x0D0D0D, 0x0D0D0D,
|
||||
0xFFFFFF, 0x84BFFF, 0xBBBBFF, 0xD0BBFF, 0xFFBFEA, 0xFFBFCC, 0xFFC4B7, 0xFFCCAE,
|
||||
0xFFD9A2, 0xCCE199, 0xAEEEB7, 0xAAF7EE, 0xB3EEFF, 0xDDDDDD, 0x111111, 0x111111
|
||||
};
|
||||
|
||||
#endif
|
22
am-kernels/kernels/litenes/src/main.c
Normal file
22
am-kernels/kernels/litenes/src/main.c
Normal file
|
@ -0,0 +1,22 @@
|
|||
#include "common.h"
|
||||
#include "fce.h"
|
||||
#include "psg.h"
|
||||
|
||||
extern char rom_mario_nes[];
|
||||
|
||||
int main() {
|
||||
ioe_init();
|
||||
|
||||
printf("==================== LiteNES Emulator ====================\n\n");
|
||||
printf("Control: [%s] SELECT [%s] START [%s]\n"
|
||||
" [%s] [%s] [%s] A [%s] B [%s]\n\n",
|
||||
TOSTRING(KEY_UP), TOSTRING(KEY_SELECT), TOSTRING(KEY_START),
|
||||
TOSTRING(KEY_LEFT), TOSTRING(KEY_DOWN), TOSTRING(KEY_RIGHT),
|
||||
TOSTRING(KEY_A), TOSTRING(KEY_B));
|
||||
printf("==========================================================\n");
|
||||
|
||||
fce_load_rom((void *)rom_mario_nes);
|
||||
fce_init();
|
||||
fce_run();
|
||||
return 1;
|
||||
}
|
3418
am-kernels/kernels/litenes/src/mario-rom.c
Normal file
3418
am-kernels/kernels/litenes/src/mario-rom.c
Normal file
File diff suppressed because it is too large
Load diff
41
am-kernels/kernels/litenes/src/memory.c
Normal file
41
am-kernels/kernels/litenes/src/memory.c
Normal file
|
@ -0,0 +1,41 @@
|
|||
#include "memory.h"
|
||||
#include "cpu.h"
|
||||
#include "ppu.h"
|
||||
#include "psg.h"
|
||||
|
||||
byte memory_readb(word address) {
|
||||
switch (address >> 13) {
|
||||
case 0: return cpu_ram_read(address & 0x07FF);
|
||||
case 1: return ppuio_read(address);
|
||||
case 2: return psgio_read(address);
|
||||
case 3: return cpu_ram_read(address & 0x1FFF);
|
||||
default: return mmc_read(address);
|
||||
}
|
||||
}
|
||||
|
||||
void memory_writeb(word address, byte data) {
|
||||
// DMA transfer
|
||||
int i;
|
||||
if (address == 0x4014) {
|
||||
for (i = 0; i < 256; i++) {
|
||||
ppu_sprram_write(cpu_ram_read((0x100 * data) + i));
|
||||
}
|
||||
return;
|
||||
}
|
||||
switch (address >> 13) {
|
||||
case 0: return cpu_ram_write(address & 0x07FF, data);
|
||||
case 1: return ppuio_write(address, data);
|
||||
case 2: return psgio_write(address, data);
|
||||
case 3: return cpu_ram_write(address & 0x1FFF, data);
|
||||
default: return mmc_write(address, data);
|
||||
}
|
||||
}
|
||||
|
||||
word memory_readw(word address) {
|
||||
return memory_readb(address) + (memory_readb(address + 1) << 8);
|
||||
}
|
||||
|
||||
void memory_writew(word address, word data) {
|
||||
memory_writeb(address, data & 0xFF);
|
||||
memory_writeb(address + 1, data >> 8);
|
||||
}
|
15
am-kernels/kernels/litenes/src/memory.h
Normal file
15
am-kernels/kernels/litenes/src/memory.h
Normal file
|
@ -0,0 +1,15 @@
|
|||
#ifndef MEM_H
|
||||
#define MEM_H
|
||||
|
||||
#include "common.h"
|
||||
#include "mmc.h"
|
||||
|
||||
// Single byte
|
||||
byte memory_readb(word address);
|
||||
void memory_writeb(word address, byte data);
|
||||
|
||||
// Two bytes (word), LSB first
|
||||
word memory_readw(word address);
|
||||
void memory_writew(word address, word data);
|
||||
|
||||
#endif
|
31
am-kernels/kernels/litenes/src/mmc.c
Normal file
31
am-kernels/kernels/litenes/src/mmc.c
Normal file
|
@ -0,0 +1,31 @@
|
|||
#include "mmc.h"
|
||||
#include "ppu.h"
|
||||
#include <klib.h>
|
||||
|
||||
byte mmc_id;
|
||||
#define MMC_MAX_PAGE_COUNT 1
|
||||
|
||||
static byte mmc_chr_pages[MMC_MAX_PAGE_COUNT][0x2000];
|
||||
static int mmc_chr_pages_number;
|
||||
|
||||
byte memory[0x10000];
|
||||
|
||||
byte mmc_read(word address) {
|
||||
return memory[address];
|
||||
}
|
||||
|
||||
void mmc_write(word address, byte data) {
|
||||
switch (mmc_id) {
|
||||
case 0x3: ppu_copy(0x0000, &mmc_chr_pages[data & 3][0], 0x2000); break;
|
||||
}
|
||||
memory[address] = data;
|
||||
}
|
||||
|
||||
void mmc_copy(word address, byte *source, int length) {
|
||||
memcpy(&memory[address], source, length);
|
||||
}
|
||||
|
||||
void mmc_append_chr_rom_page(byte *source) {
|
||||
assert(mmc_chr_pages_number < MMC_MAX_PAGE_COUNT);
|
||||
memcpy(&mmc_chr_pages[mmc_chr_pages_number++][0], source, 0x2000);
|
||||
}
|
8
am-kernels/kernels/litenes/src/mmc.h
Normal file
8
am-kernels/kernels/litenes/src/mmc.h
Normal file
|
@ -0,0 +1,8 @@
|
|||
#include "common.h"
|
||||
|
||||
extern byte mmc_id;
|
||||
|
||||
byte mmc_read(word address);
|
||||
void mmc_write(word address, byte data);
|
||||
void mmc_copy(word address, byte *source, int length);
|
||||
void mmc_append_chr_rom_page(byte *source);
|
432
am-kernels/kernels/litenes/src/ppu.c
Normal file
432
am-kernels/kernels/litenes/src/ppu.c
Normal file
|
@ -0,0 +1,432 @@
|
|||
#include "ppu.h"
|
||||
#include "cpu.h"
|
||||
#include "fce.h"
|
||||
#include "memory.h"
|
||||
#include <klib.h>
|
||||
|
||||
//#define PROFILE
|
||||
//#define HAS_US_TIMER
|
||||
|
||||
PPU_STATE ppu;
|
||||
|
||||
static bool ppu_2007_first_read;
|
||||
static byte ppu_addr_latch;
|
||||
static byte PPU_SPRRAM[0x100];
|
||||
static byte PPU_RAM[0x4000];
|
||||
static bool ppu_sprite_hit_occured = false;
|
||||
static byte ppu_latch;
|
||||
|
||||
// PPU Constants
|
||||
static const word ppu_base_nametable_addresses[4] = { 0x2000, 0x2400, 0x2800, 0x2C00 };
|
||||
|
||||
// For sprite-0-hit checks
|
||||
static byte ppu_screen_background[264][248];
|
||||
|
||||
// Precalculated tile high and low bytes addition for pattern tables
|
||||
static byte ppu_l_h_addition_table[256][256][8];
|
||||
static byte ppu_l_h_addition_flip_table[256][256][8];
|
||||
|
||||
|
||||
// PPUCTRL Functions
|
||||
|
||||
word ppu_base_nametable_address() { return ppu_base_nametable_addresses[ppu.PPUCTRL & 0x3]; }
|
||||
byte ppu_vram_address_increment() { return common_bit_set(ppu.PPUCTRL, 2) ? 32 : 1; }
|
||||
word ppu_sprite_pattern_table_address() { return common_bit_set(ppu.PPUCTRL, 3) ? 0x1000 : 0x0000; }
|
||||
word ppu_background_pattern_table_address() { return common_bit_set(ppu.PPUCTRL, 4) ? 0x1000 : 0x0000; }
|
||||
byte ppu_sprite_height() { return common_bit_set(ppu.PPUCTRL, 5) ? 16 : 8; }
|
||||
bool ppu_generates_nmi() { return common_bit_set(ppu.PPUCTRL, 7); }
|
||||
|
||||
// PPUMASK Functions
|
||||
|
||||
bool ppu_renders_grayscale() { return common_bit_set(ppu.PPUMASK, 0); }
|
||||
bool ppu_shows_background_in_leftmost_8px() { return common_bit_set(ppu.PPUMASK, 1); }
|
||||
bool ppu_shows_sprites_in_leftmost_8px() { return common_bit_set(ppu.PPUMASK, 2); }
|
||||
bool ppu_shows_background() { return common_bit_set(ppu.PPUMASK, 3); }
|
||||
bool ppu_shows_sprites() { return common_bit_set(ppu.PPUMASK, 4); }
|
||||
bool ppu_intensifies_reds() { return common_bit_set(ppu.PPUMASK, 5); }
|
||||
bool ppu_intensifies_greens() { return common_bit_set(ppu.PPUMASK, 6); }
|
||||
bool ppu_intensifies_blues() { return common_bit_set(ppu.PPUMASK, 7); }
|
||||
|
||||
void ppu_set_renders_grayscale(bool yesno) { common_modify_bitb(&ppu.PPUMASK, 0, yesno); }
|
||||
void ppu_set_shows_background_in_leftmost_8px(bool yesno) { common_modify_bitb(&ppu.PPUMASK, 1, yesno); }
|
||||
void ppu_set_shows_sprites_in_leftmost_8px(bool yesno) { common_modify_bitb(&ppu.PPUMASK, 2, yesno); }
|
||||
void ppu_set_shows_background(bool yesno) { common_modify_bitb(&ppu.PPUMASK, 3, yesno); }
|
||||
void ppu_set_shows_sprites(bool yesno) { common_modify_bitb(&ppu.PPUMASK, 4, yesno); }
|
||||
void ppu_set_intensifies_reds(bool yesno) { common_modify_bitb(&ppu.PPUMASK, 5, yesno); }
|
||||
void ppu_set_intensifies_greens(bool yesno) { common_modify_bitb(&ppu.PPUMASK, 6, yesno); }
|
||||
void ppu_set_intensifies_blues(bool yesno) { common_modify_bitb(&ppu.PPUMASK, 7, yesno); }
|
||||
|
||||
// PPUSTATUS Functions
|
||||
|
||||
bool ppu_sprite_overflow() { return common_bit_set(ppu.PPUSTATUS, 5); }
|
||||
bool ppu_sprite_0_hit() { return common_bit_set(ppu.PPUSTATUS, 6); }
|
||||
bool ppu_in_vblank() { return common_bit_set(ppu.PPUSTATUS, 7); }
|
||||
|
||||
void ppu_set_sprite_overflow(bool yesno) { common_modify_bitb(&ppu.PPUSTATUS, 5, yesno); }
|
||||
void ppu_set_sprite_0_hit(bool yesno) { common_modify_bitb(&ppu.PPUSTATUS, 6, yesno); }
|
||||
void ppu_set_in_vblank(bool yesno) { common_modify_bitb(&ppu.PPUSTATUS, 7, yesno); }
|
||||
|
||||
|
||||
// RAM
|
||||
|
||||
word ppu_get_real_ram_address(word address) {
|
||||
if (address < 0x2000) { return address; }
|
||||
else if (address < 0x3F00) {
|
||||
if (address < 0x3000) { return address; }
|
||||
else { return address; }
|
||||
}
|
||||
else if (address < 0x4000) {
|
||||
address = 0x3F00 | (address & 0x1F);
|
||||
if (address == 0x3F10 || address == 0x3F14 || address == 0x3F18 || address == 0x3F1C)
|
||||
address -= 0x10;
|
||||
return address;
|
||||
}
|
||||
return 0xFFFF;
|
||||
}
|
||||
|
||||
byte ppu_ram_read(word address) {
|
||||
return PPU_RAM[ppu_get_real_ram_address(address)];
|
||||
}
|
||||
|
||||
void ppu_ram_write(word address, byte data) {
|
||||
PPU_RAM[ppu_get_real_ram_address(address)] = data;
|
||||
}
|
||||
|
||||
// 3F01 = 0F (00001111)
|
||||
// 3F02 = 2A (00101010)
|
||||
// 3F03 = 09 (00001001)
|
||||
// 3F04 = 07 (00000111)
|
||||
// 3F05 = 0F (00001111)
|
||||
// 3F06 = 30 (00110000)
|
||||
// 3F07 = 27 (00100111)
|
||||
// 3F08 = 15 (00010101)
|
||||
// 3F09 = 0F (00001111)
|
||||
// 3F0A = 30 (00110000)
|
||||
// 3F0B = 02 (00000010)
|
||||
// 3F0C = 21 (00100001)
|
||||
// 3F0D = 0F (00001111)
|
||||
// 3F0E = 30 (00110000)
|
||||
// 3F0F = 00 (00000000)
|
||||
// 3F11 = 0F (00001111)
|
||||
// 3F12 = 16 (00010110)
|
||||
// 3F13 = 12 (00010010)
|
||||
// 3F14 = 37 (00110111)
|
||||
// 3F15 = 0F (00001111)
|
||||
// 3F16 = 12 (00010010)
|
||||
// 3F17 = 16 (00010110)
|
||||
// 3F18 = 37 (00110111)
|
||||
// 3F19 = 0F (00001111)
|
||||
// 3F1A = 17 (00010111)
|
||||
// 3F1B = 11 (00010001)
|
||||
// 3F1C = 35 (00110101)
|
||||
// 3F1D = 0F (00001111)
|
||||
// 3F1E = 17 (00010111)
|
||||
// 3F1F = 11 (00010001)
|
||||
// 3F20 = 2B (00101011)
|
||||
|
||||
|
||||
// Rendering
|
||||
|
||||
void ppu_draw_background_scanline(bool mirror) {
|
||||
int tile_x;
|
||||
for (tile_x = ppu_shows_background_in_leftmost_8px() ? 0 : 1; tile_x < 32; tile_x ++) {
|
||||
// Skipping off-screen pixels
|
||||
if (((tile_x << 3) - ppu.PPUSCROLL_X + (mirror ? 256 : 0)) > 256)
|
||||
continue;
|
||||
|
||||
int tile_y = ppu.scanline >> 3;
|
||||
int tile_index = ppu_ram_read(ppu_base_nametable_address() + tile_x + (tile_y << 5) + (mirror ? 0x400 : 0));
|
||||
word tile_address = ppu_background_pattern_table_address() + 16 * tile_index;
|
||||
|
||||
int y_in_tile = ppu.scanline & 0x7;
|
||||
byte l = ppu_ram_read(tile_address + y_in_tile);
|
||||
byte h = ppu_ram_read(tile_address + y_in_tile + 8);
|
||||
|
||||
int x;
|
||||
for (x = 0; x < 8; x ++) {
|
||||
byte color = ppu_l_h_addition_table[l][h][x];
|
||||
|
||||
// Color 0 is transparent
|
||||
if (color != 0) {
|
||||
word attribute_address = (ppu_base_nametable_address() + (mirror ? 0x400 : 0) + 0x3C0 + (tile_x >> 2) + (ppu.scanline >> 5) * 8);
|
||||
bool top = (ppu.scanline % 32) < 16;
|
||||
bool left = (tile_x % 4 < 2);
|
||||
|
||||
byte palette_attribute = ppu_ram_read(attribute_address);
|
||||
|
||||
if (!top) { palette_attribute >>= 4; }
|
||||
if (!left) { palette_attribute >>= 2; }
|
||||
palette_attribute &= 3;
|
||||
|
||||
word palette_address = 0x3F00 + (palette_attribute << 2);
|
||||
int idx = ppu_ram_read(palette_address + color);
|
||||
|
||||
ppu_screen_background[(tile_x << 3) + x][ppu.scanline] = color;
|
||||
|
||||
draw((tile_x << 3) + x - ppu.PPUSCROLL_X + (mirror ? 256 : 0), ppu.scanline + 1, idx); // bg
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ppu_draw_sprite_scanline() {
|
||||
int scanline_sprite_count = 0;
|
||||
int n;
|
||||
for (n = 0; n < 0x100; n += 4) {
|
||||
byte sprite_x = PPU_SPRRAM[n + 3];
|
||||
byte sprite_y = PPU_SPRRAM[n];
|
||||
|
||||
// Skip if sprite not on scanline
|
||||
if (sprite_y > ppu.scanline || sprite_y + ppu_sprite_height() < ppu.scanline)
|
||||
continue;
|
||||
|
||||
scanline_sprite_count++;
|
||||
|
||||
// PPU can't render > 8 sprites
|
||||
if (scanline_sprite_count > 8) {
|
||||
ppu_set_sprite_overflow(true);
|
||||
// break;
|
||||
}
|
||||
|
||||
bool vflip = PPU_SPRRAM[n + 2] & 0x80;
|
||||
bool hflip = PPU_SPRRAM[n + 2] & 0x40;
|
||||
|
||||
word tile_address = ppu_sprite_pattern_table_address() + 16 * PPU_SPRRAM[n + 1];
|
||||
int y_in_tile = ppu.scanline & 0x7;
|
||||
byte l = ppu_ram_read(tile_address + (vflip ? (7 - y_in_tile) : y_in_tile));
|
||||
byte h = ppu_ram_read(tile_address + (vflip ? (7 - y_in_tile) : y_in_tile) + 8);
|
||||
|
||||
byte palette_attribute = PPU_SPRRAM[n + 2] & 0x3;
|
||||
word palette_address = 0x3F10 + (palette_attribute << 2);
|
||||
int x;
|
||||
for (x = 0; x < 8; x ++) {
|
||||
int color = hflip ? ppu_l_h_addition_flip_table[l][h][x] : ppu_l_h_addition_table[l][h][x];
|
||||
|
||||
// Color 0 is transparent
|
||||
if (color != 0) {
|
||||
int screen_x = sprite_x + x;
|
||||
int idx = ppu_ram_read(palette_address + color);
|
||||
|
||||
// FIXME: we do not distinguish bbg and fg here to improve performance
|
||||
if (PPU_SPRRAM[n + 2] & 0x20) {
|
||||
draw(screen_x, sprite_y + y_in_tile + 1, idx); // bbg
|
||||
}
|
||||
else {
|
||||
draw(screen_x, sprite_y + y_in_tile + 1, idx); // fg
|
||||
}
|
||||
|
||||
// Checking sprite 0 hit
|
||||
if (ppu_shows_background() && !ppu_sprite_hit_occured && n == 0 && ppu_screen_background[screen_x][sprite_y + y_in_tile] == color) {
|
||||
ppu_set_sprite_0_hit(true);
|
||||
ppu_sprite_hit_occured = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// PPU Lifecycle
|
||||
|
||||
void ppu_run(int cycles) {
|
||||
while (cycles-- > 0) { ppu_cycle(); }
|
||||
}
|
||||
|
||||
static uint32_t background_time, sprite_time, cpu_time;
|
||||
#ifdef PROFILE
|
||||
#ifdef HAS_US_TIMER
|
||||
# define TIMER_UNIT "us"
|
||||
# define time_read(x) read_us(&x)
|
||||
# define time_diff(t1, t0) us_timediff(&t1, &t0)
|
||||
# define TIME_TYPE amtime
|
||||
#else
|
||||
# define TIMER_UNIT "ms"
|
||||
# define time_read(x) x = uptime()
|
||||
# define time_diff(t1, t0) (t1 - t0)
|
||||
# define TIME_TYPE uint32_t
|
||||
#endif
|
||||
#else
|
||||
# define time_read(x)
|
||||
# define time_diff(t1, t0) 0
|
||||
#endif
|
||||
|
||||
void ppu_cycle() {
|
||||
#ifdef PROFILE
|
||||
TIME_TYPE t0, t1, t2, t3, t4, t5;
|
||||
#endif
|
||||
|
||||
if (!ppu.ready && cpu_clock() > 29658)
|
||||
ppu.ready = true;
|
||||
|
||||
time_read(t0);
|
||||
cpu_run(256);
|
||||
time_read(t1);
|
||||
|
||||
ppu.scanline++;
|
||||
|
||||
if (ppu.scanline < SCR_H && ppu_shows_background()) {
|
||||
ppu_draw_background_scanline(false);
|
||||
ppu_draw_background_scanline(true);
|
||||
}
|
||||
|
||||
time_read(t2);
|
||||
cpu_run(85 - 16);
|
||||
time_read(t3);
|
||||
|
||||
if (ppu.scanline < SCR_H && ppu_shows_sprites()) {
|
||||
ppu_draw_sprite_scanline();
|
||||
}
|
||||
|
||||
time_read(t4);
|
||||
cpu_run(16);
|
||||
time_read(t5);
|
||||
|
||||
cpu_time += time_diff(t1, t0) + time_diff(t3, t2) + time_diff(t5, t4);
|
||||
background_time += time_diff(t2, t1);
|
||||
sprite_time += time_diff(t4, t3);
|
||||
|
||||
if (ppu.scanline == 241) {
|
||||
ppu_set_in_vblank(true);
|
||||
ppu_set_sprite_0_hit(false);
|
||||
cpu_interrupt();
|
||||
}
|
||||
else if (ppu.scanline == 262) {
|
||||
ppu.scanline = -1;
|
||||
ppu_sprite_hit_occured = false;
|
||||
ppu_set_in_vblank(false);
|
||||
|
||||
time_read(t0);
|
||||
fce_update_screen();
|
||||
time_read(t1);
|
||||
|
||||
#ifdef PROFILE
|
||||
uint32_t total = cpu_time + background_time + sprite_time + time_diff(t1, t0);
|
||||
printf("Time: cpu + bg + spr + scr = (%d + %d + %d + %d)\t= %d %s\n",
|
||||
cpu_time, background_time, sprite_time, time_diff(t1, t0), total, TIMER_UNIT);
|
||||
#endif
|
||||
cpu_time = 0;
|
||||
background_time = 0;
|
||||
sprite_time = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void ppu_copy(word address, byte *source, int length) {
|
||||
memcpy(&PPU_RAM[address], source, length);
|
||||
}
|
||||
|
||||
byte ppuio_read(word address) {
|
||||
ppu.PPUADDR &= 0x3FFF;
|
||||
switch (address & 7) {
|
||||
case 2:
|
||||
{
|
||||
byte value = ppu.PPUSTATUS;
|
||||
ppu_set_in_vblank(false);
|
||||
ppu_set_sprite_0_hit(false);
|
||||
ppu.scroll_received_x = 0;
|
||||
ppu.PPUSCROLL = 0;
|
||||
ppu.addr_received_high_byte = 0;
|
||||
ppu_latch = value;
|
||||
ppu_addr_latch = 0;
|
||||
ppu_2007_first_read = true;
|
||||
return value;
|
||||
}
|
||||
case 4: return ppu_latch = PPU_SPRRAM[ppu.OAMADDR];
|
||||
case 7:
|
||||
{
|
||||
byte data;
|
||||
|
||||
if (ppu.PPUADDR < 0x3F00) {
|
||||
data = ppu_latch = ppu_ram_read(ppu.PPUADDR);
|
||||
}
|
||||
else {
|
||||
data = ppu_ram_read(ppu.PPUADDR);
|
||||
ppu_latch = 0;
|
||||
}
|
||||
|
||||
if (ppu_2007_first_read) {
|
||||
ppu_2007_first_read = false;
|
||||
}
|
||||
else {
|
||||
ppu.PPUADDR += ppu_vram_address_increment();
|
||||
}
|
||||
return data;
|
||||
}
|
||||
default: return 0xFF;
|
||||
}
|
||||
}
|
||||
|
||||
void ppuio_write(word address, byte data) {
|
||||
address &= 7;
|
||||
ppu_latch = data;
|
||||
ppu.PPUADDR &= 0x3FFF;
|
||||
switch(address) {
|
||||
case 0: if (ppu.ready) ppu.PPUCTRL = data; break;
|
||||
case 1: if (ppu.ready) ppu.PPUMASK = data; break;
|
||||
case 3: ppu.OAMADDR = data; break;
|
||||
case 4: PPU_SPRRAM[ppu.OAMADDR++] = data; break;
|
||||
case 5:
|
||||
{
|
||||
if (ppu.scroll_received_x)
|
||||
ppu.PPUSCROLL_Y = data;
|
||||
else
|
||||
ppu.PPUSCROLL_X = data;
|
||||
|
||||
ppu.scroll_received_x ^= 1;
|
||||
break;
|
||||
}
|
||||
case 6:
|
||||
{
|
||||
if (!ppu.ready)
|
||||
return;
|
||||
|
||||
if (ppu.addr_received_high_byte)
|
||||
ppu.PPUADDR = (ppu_addr_latch << 8) + data;
|
||||
else
|
||||
ppu_addr_latch = data;
|
||||
|
||||
ppu.addr_received_high_byte ^= 1;
|
||||
ppu_2007_first_read = true;
|
||||
break;
|
||||
}
|
||||
case 7:
|
||||
{
|
||||
if (ppu.PPUADDR > 0x1FFF || ppu.PPUADDR < 0x4000) {
|
||||
ppu_ram_write(ppu.PPUADDR ^ ppu.mirroring_xor, data);
|
||||
ppu_ram_write(ppu.PPUADDR, data);
|
||||
}
|
||||
else {
|
||||
ppu_ram_write(ppu.PPUADDR, data);
|
||||
}
|
||||
}
|
||||
}
|
||||
ppu_latch = data;
|
||||
}
|
||||
|
||||
void ppu_init() {
|
||||
ppu.PPUCTRL = ppu.PPUMASK = ppu.PPUSTATUS = ppu.OAMADDR = ppu.PPUSCROLL_X = ppu.PPUSCROLL_Y = ppu.PPUADDR = 0;
|
||||
ppu.PPUSTATUS |= 0xA0;
|
||||
ppu.PPUDATA = 0;
|
||||
ppu_2007_first_read = true;
|
||||
|
||||
// Initializing low-high byte-pairs for pattern tables
|
||||
int h, l, x;
|
||||
for (h = 0; h < 0x100; h ++) {
|
||||
for (l = 0; l < 0x100; l ++) {
|
||||
for (x = 0; x < 8; x ++) {
|
||||
ppu_l_h_addition_table[l][h][x] = (((h >> (7 - x)) & 1) << 1) | ((l >> (7 - x)) & 1);
|
||||
ppu_l_h_addition_flip_table[l][h][x] = (((h >> x) & 1) << 1) | ((l >> x) & 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ppu_sprram_write(byte data) {
|
||||
PPU_SPRRAM[ppu.OAMADDR++] = data;
|
||||
}
|
||||
|
||||
void ppu_set_background_color(byte color) {
|
||||
}
|
||||
|
||||
void ppu_set_mirroring(byte mirroring) {
|
||||
ppu.mirroring = mirroring;
|
||||
ppu.mirroring_xor = 0x400 << mirroring;
|
||||
}
|
41
am-kernels/kernels/litenes/src/ppu.h
Normal file
41
am-kernels/kernels/litenes/src/ppu.h
Normal file
|
@ -0,0 +1,41 @@
|
|||
#ifndef PPU_H
|
||||
#define PPU_H
|
||||
|
||||
#include "common.h"
|
||||
|
||||
typedef struct {
|
||||
byte PPUCTRL; // $2000 write only
|
||||
byte PPUMASK; // $2001 write only
|
||||
byte PPUSTATUS; // $2002 read only
|
||||
byte OAMADDR; // $2003 write only
|
||||
byte OAMDATA; // $2004
|
||||
word PPUSCROLL;
|
||||
byte PPUSCROLL_X, PPUSCROLL_Y; // $2005 write only x2
|
||||
word PPUADDR; // $2006 write only x2
|
||||
word PPUDATA; // $2007
|
||||
|
||||
bool scroll_received_x;
|
||||
bool addr_received_high_byte;
|
||||
bool ready;
|
||||
|
||||
int mirroring, mirroring_xor;
|
||||
|
||||
int x, scanline;
|
||||
} PPU_STATE;
|
||||
|
||||
void ppu_init();
|
||||
|
||||
byte ppu_ram_read(word address);
|
||||
void ppu_ram_write(word address, byte data);
|
||||
byte ppuio_read(word address);
|
||||
void ppuio_write(word address, byte data);
|
||||
|
||||
bool ppu_generates_nmi();
|
||||
|
||||
void ppu_set_mirroring(byte mirroring);
|
||||
|
||||
void ppu_cycle();
|
||||
void ppu_copy(word address, byte *source, int length);
|
||||
void ppu_sprram_write(byte data);
|
||||
|
||||
#endif
|
54
am-kernels/kernels/litenes/src/psg.c
Normal file
54
am-kernels/kernels/litenes/src/psg.c
Normal file
|
@ -0,0 +1,54 @@
|
|||
#include "psg.h"
|
||||
#include <klib.h>
|
||||
|
||||
static int p = 10;
|
||||
static int key_state[256];
|
||||
|
||||
#define KEYS \
|
||||
CONCAT(AM_KEY_, KEY_A), \
|
||||
CONCAT(AM_KEY_, KEY_B), \
|
||||
CONCAT(AM_KEY_, KEY_SELECT), \
|
||||
CONCAT(AM_KEY_, KEY_START), \
|
||||
CONCAT(AM_KEY_, KEY_UP), \
|
||||
CONCAT(AM_KEY_, KEY_DOWN), \
|
||||
CONCAT(AM_KEY_, KEY_LEFT), \
|
||||
CONCAT(AM_KEY_, KEY_RIGHT),
|
||||
|
||||
static int MAP[256] = {
|
||||
0, // On/Off
|
||||
KEYS
|
||||
255,
|
||||
};
|
||||
|
||||
byte psgio_read(word address) {
|
||||
// Joystick 1
|
||||
if (address == 0x4016) {
|
||||
if (p++ < 9) {
|
||||
return key_state[MAP[p]];
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void psgio_write(word address, byte data) {
|
||||
static byte prev_write;
|
||||
if (address == 0x4016) {
|
||||
if ((data & 1) == 0 && prev_write == 1) {
|
||||
// strobe
|
||||
p = 0;
|
||||
}
|
||||
}
|
||||
prev_write = data & 1;
|
||||
}
|
||||
|
||||
void psg_detect_key() {
|
||||
while (1) {
|
||||
AM_INPUT_KEYBRD_T ev = io_read(AM_INPUT_KEYBRD);
|
||||
if (ev.keycode == AM_KEY_NONE) break;
|
||||
key_state[ev.keycode] = ev.keydown;
|
||||
}
|
||||
}
|
||||
|
||||
void psg_init() {
|
||||
key_state[0] = 1;
|
||||
}
|
20
am-kernels/kernels/litenes/src/psg.h
Normal file
20
am-kernels/kernels/litenes/src/psg.h
Normal file
|
@ -0,0 +1,20 @@
|
|||
#ifndef PSG_H
|
||||
#define PSG_H
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#define KEY_A J
|
||||
#define KEY_B K
|
||||
#define KEY_SELECT U
|
||||
#define KEY_START I
|
||||
#define KEY_UP W
|
||||
#define KEY_DOWN S
|
||||
#define KEY_LEFT A
|
||||
#define KEY_RIGHT D
|
||||
|
||||
byte psgio_read(word address);
|
||||
void psgio_write(word address, byte data);
|
||||
void psg_init();
|
||||
void psg_detect_key();
|
||||
|
||||
#endif
|
31
am-kernels/kernels/nemu/Makefile
Normal file
31
am-kernels/kernels/nemu/Makefile
Normal file
|
@ -0,0 +1,31 @@
|
|||
ARCH_SPLIT = $(subst -, ,$(ARCH))
|
||||
ISA = $(word 1,$(ARCH_SPLIT))
|
||||
PLATFORM = $(word 2,$(ARCH_SPLIT))
|
||||
|
||||
ifneq ($(PLATFORM), nemu)
|
||||
$(error Only support with NEMU)
|
||||
endif
|
||||
|
||||
TMPDEFCONFIG = tmp_defconfig
|
||||
TMPDEFCONFIG_FILE = $(NEMU_HOME)/configs/$(TMPDEFCONFIG)
|
||||
|
||||
all:
|
||||
$(MAKE) save_config
|
||||
$(MAKE) build_am
|
||||
$(MAKE) restore_config
|
||||
$(MAKE) -C $(NEMU_HOME) run IMG=$(NEMU_HOME)/build/$(ISA)-nemu-interpreter-$(ARCH).bin
|
||||
|
||||
save_config:
|
||||
$(MAKE) -C $(NEMU_HOME) savedefconfig
|
||||
mv $(NEMU_HOME)/configs/defconfig $(TMPDEFCONFIG_FILE)
|
||||
|
||||
build_am:
|
||||
$(MAKE) -C $(NEMU_HOME) $(ISA)-am_defconfig
|
||||
$(MAKE) -C $(NEMU_HOME) ARCH=$(ARCH) mainargs=$(mainargs) || \
|
||||
($(MAKE) restore_config; false)
|
||||
|
||||
restore_config:
|
||||
$(MAKE) -C $(NEMU_HOME) ARCH=$(ARCH) $(TMPDEFCONFIG)
|
||||
rm $(TMPDEFCONFIG_FILE)
|
||||
|
||||
.PHONY: all save_config build_am restore_config
|
3
am-kernels/kernels/slider/Makefile
Normal file
3
am-kernels/kernels/slider/Makefile
Normal file
|
@ -0,0 +1,3 @@
|
|||
NAME = slider
|
||||
SRCS = main.c image.S
|
||||
include $(AM_HOME)/Makefile
|
7
am-kernels/kernels/slider/image.S
Normal file
7
am-kernels/kernels/slider/image.S
Normal file
|
@ -0,0 +1,7 @@
|
|||
.section .data
|
||||
.global image, image_end
|
||||
.p2align 3
|
||||
image:
|
||||
.incbin "images/projectn.bin"
|
||||
.incbin "images/litenes.bin"
|
||||
image_end:
|
1
am-kernels/kernels/slider/images/.gitignore
vendored
Normal file
1
am-kernels/kernels/slider/images/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
!*.bin
|
1583
am-kernels/kernels/slider/images/litenes.bin
Normal file
1583
am-kernels/kernels/slider/images/litenes.bin
Normal file
File diff suppressed because one or more lines are too long
219
am-kernels/kernels/slider/images/projectn.bin
Normal file
219
am-kernels/kernels/slider/images/projectn.bin
Normal file
File diff suppressed because one or more lines are too long
32
am-kernels/kernels/slider/main.c
Normal file
32
am-kernels/kernels/slider/main.c
Normal file
|
@ -0,0 +1,32 @@
|
|||
#include <am.h>
|
||||
#include <klib.h>
|
||||
#include <klib-macros.h>
|
||||
|
||||
extern uint32_t image[][400][300];
|
||||
extern uint32_t image_end[][400][300];
|
||||
#define NR_IMG (image_end - image)
|
||||
|
||||
void display_image(int i) {
|
||||
io_write(AM_GPU_FBDRAW, 0, 0, &image[i][0][0], 400, 300, true);
|
||||
}
|
||||
|
||||
int main() {
|
||||
ioe_init();
|
||||
|
||||
int i = 0;
|
||||
unsigned long last = 0;
|
||||
unsigned long current;
|
||||
|
||||
display_image(i);
|
||||
|
||||
while (1) {
|
||||
current = io_read(AM_TIMER_UPTIME).us / 1000;
|
||||
if (current - last > 5000) {
|
||||
// change image every 5s
|
||||
i = (i + 1) % NR_IMG;
|
||||
display_image(i);
|
||||
last = current;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
42
am-kernels/kernels/snake/LICENSE
Normal file
42
am-kernels/kernels/snake/LICENSE
Normal file
|
@ -0,0 +1,42 @@
|
|||
This software is licensed under a BSD Style License
|
||||
|
||||
Copyright (c) 2015 Battelle Memorial Institute. All Rights Reserved.
|
||||
http://www.battelle.org/
|
||||
|
||||
Redistribution and use of this software and associated documentation
|
||||
("Software"), with or without modification, are permitted provided that the
|
||||
following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain copyright statements and
|
||||
notices. Redistributions must also contain a copy of this document.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. The names "M/o/Vfuscator" and "Battelle" must not be used to endorse or
|
||||
promote products derived from this Software without prior written
|
||||
permission of Battelle Memorial Institute. For written permission,
|
||||
please contact solutions@battelle.org
|
||||
|
||||
4. Products derived from this Software may not be called "M/o/Vfuscator" or
|
||||
"Battelle", nor may "M/o/Vfuscator" or "Battelle" appear in their names
|
||||
without prior written permission of Battelle Memorial Institute.
|
||||
Battelle is a registered trademark of Battelle Memorial Institute.
|
||||
|
||||
5. Due credit should be given to the Battelle Memorial Institute.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY BATTELLE MEMORIAL INSTITUTE "AS IS" AND ANY
|
||||
EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL BATTELLE MEMORIAL INSTITUTE OR ITS
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
The original author of this software is Christopher P. Domas, an employee of
|
||||
the Battelle Memorial Institute.
|
3
am-kernels/kernels/snake/Makefile
Normal file
3
am-kernels/kernels/snake/Makefile
Normal file
|
@ -0,0 +1,3 @@
|
|||
NAME = snake
|
||||
SRCS = snake.c
|
||||
include $(AM_HOME)/Makefile
|
188
am-kernels/kernels/snake/snake.c
Normal file
188
am-kernels/kernels/snake/snake.c
Normal file
|
@ -0,0 +1,188 @@
|
|||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <am.h>
|
||||
#include <amdev.h>
|
||||
#include <klib-macros.h>
|
||||
|
||||
#define MAX_LENGTH 100
|
||||
#define TILE_W 8
|
||||
|
||||
typedef enum { NONE, UP, DOWN, LEFT, RIGHT } dir_t;
|
||||
|
||||
typedef struct {
|
||||
int x, y;
|
||||
} point_t;
|
||||
|
||||
typedef struct {
|
||||
int width, height;
|
||||
} dim_t;
|
||||
|
||||
typedef struct {
|
||||
int top, bottom, left, right;
|
||||
} rect_t;
|
||||
|
||||
typedef struct {
|
||||
point_t body[MAX_LENGTH];
|
||||
int length;
|
||||
int index;
|
||||
int dead;
|
||||
} snake_t;
|
||||
|
||||
static void refresh() {
|
||||
io_write(AM_GPU_FBDRAW, 0, 0, NULL, 0, 0, true);
|
||||
}
|
||||
|
||||
static void draw_tile(int y, int x, uint32_t color) {
|
||||
static uint32_t buf[TILE_W * TILE_W];
|
||||
uint32_t last_color = 0xffffffff;
|
||||
if (last_color != color) {
|
||||
for (int i = 0; i < LENGTH(buf); i ++) { buf[i] = color; }
|
||||
}
|
||||
io_write(AM_GPU_FBDRAW, x * TILE_W, y * TILE_W, buf, TILE_W, TILE_W, false);
|
||||
}
|
||||
|
||||
static int read_key() {
|
||||
while (1) {
|
||||
AM_INPUT_KEYBRD_T ev = io_read(AM_INPUT_KEYBRD);
|
||||
if (ev.keydown || ev.keycode == AM_KEY_NONE) return ev.keycode;
|
||||
}
|
||||
}
|
||||
|
||||
static point_t create_food(dim_t game_size) {
|
||||
point_t f;
|
||||
f.x = rand() % game_size.width;
|
||||
f.y = rand() % game_size.height;
|
||||
return f;
|
||||
}
|
||||
|
||||
static void print_board(rect_t board) {
|
||||
uint32_t color = 0x0000ff00;
|
||||
for (int i = board.left; i <= board.right; i++) {
|
||||
draw_tile(board.top, i, color);
|
||||
draw_tile(board.bottom, i, color);
|
||||
}
|
||||
for (int i = board.top; i <= board.bottom; i++) {
|
||||
draw_tile(i, board.left, color);
|
||||
draw_tile(i, board.right, color);
|
||||
}
|
||||
}
|
||||
|
||||
static void print_food(point_t food, rect_t board) {
|
||||
draw_tile(food.y + board.top + 1, food.x + board.left + 1, 0x000000ff);
|
||||
}
|
||||
|
||||
static void print_head(snake_t* snake, rect_t board) {
|
||||
point_t *p = &snake->body[snake->index];
|
||||
draw_tile(p->y + board.top + 1, p->x + board.left + 1, 0x00ff0000);
|
||||
}
|
||||
|
||||
static void clear_tail(snake_t* snake, rect_t board) {
|
||||
int t = snake->index-snake->length;
|
||||
if (t < 0) { t += MAX_LENGTH; }
|
||||
draw_tile(snake->body[t].y + board.top + 1, snake->body[t].x + board.left + 1, 0);
|
||||
}
|
||||
|
||||
static dir_t get_dir(int c) {
|
||||
switch (c) {
|
||||
case AM_KEY_LEFT: return LEFT;
|
||||
case AM_KEY_UP: return UP;
|
||||
case AM_KEY_RIGHT: return RIGHT;
|
||||
case AM_KEY_DOWN: return DOWN;
|
||||
default: return NONE;
|
||||
}
|
||||
}
|
||||
|
||||
static void move_snake(snake_t* snake, dir_t dir) {
|
||||
point_t p = snake->body[snake->index];
|
||||
switch (dir) {
|
||||
case LEFT: p.x --; break;
|
||||
case DOWN: p.y ++; break;
|
||||
case RIGHT: p.x ++; break;
|
||||
case UP: p.y --; break;
|
||||
default: break;
|
||||
}
|
||||
snake->index ++;
|
||||
if (snake->index == MAX_LENGTH) { snake->index = 0; }
|
||||
snake->body[snake->index] = p;
|
||||
}
|
||||
|
||||
static int is_dead(snake_t* snake, dim_t game_size) {
|
||||
point_t head = snake->body[snake->index];
|
||||
if (head.x == -1) return 1;
|
||||
if (head.x == game_size.width) return 1;
|
||||
if (head.y == -1) return 1;
|
||||
if (head.y == game_size.height) return 1;
|
||||
|
||||
for (int i = 1; i != snake->length; i ++) {
|
||||
int j = snake->index-i;
|
||||
if (j < 0) { j += MAX_LENGTH; }
|
||||
if (head.x == snake->body[j].x && head.y == snake->body[j].y) { return 1; }
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int has_food(snake_t* snake, point_t food) {
|
||||
return snake->body[snake->index].x == food.x && snake->body[snake->index].y == food.y;
|
||||
}
|
||||
|
||||
int main() {
|
||||
snake_t snake = {0};
|
||||
rect_t board;
|
||||
dim_t screen;
|
||||
dim_t game_size;
|
||||
dir_t dir = RIGHT;
|
||||
|
||||
ioe_init();
|
||||
screen.height = io_read(AM_GPU_CONFIG).height / TILE_W;
|
||||
screen.width = io_read(AM_GPU_CONFIG).width / TILE_W;
|
||||
|
||||
game_size.width = screen.width - 2;
|
||||
game_size.height = screen.height - 2;
|
||||
|
||||
snake.body[0].x = game_size.width / 2;
|
||||
snake.body[0].y = game_size.height / 2;
|
||||
snake.body[1].x = game_size.width / 2;
|
||||
snake.body[1].y = game_size.height / 2 + 1;
|
||||
snake.length = 2;
|
||||
snake.index = 1;
|
||||
|
||||
board.left = screen.width / 2 - game_size.width / 2 - 1;
|
||||
board.right = board.left + game_size.width + 1;
|
||||
board.top = screen.height / 2 - game_size.height / 2 - 1;
|
||||
board.bottom = board.top + game_size.height + 1;
|
||||
print_board(board);
|
||||
|
||||
point_t food = create_food(game_size);
|
||||
print_food(food, board);
|
||||
do {
|
||||
print_head(&snake, board);
|
||||
clear_tail(&snake, board);
|
||||
|
||||
dir_t move_dir = get_dir(read_key());
|
||||
switch (move_dir) {
|
||||
case UP: if (dir != DOWN) dir = move_dir; break;
|
||||
case DOWN: if (dir != UP) dir = move_dir; break;
|
||||
case LEFT: if (dir != RIGHT) dir = move_dir; break;
|
||||
case RIGHT: if (dir != LEFT) dir = move_dir; break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
move_snake(&snake, dir);
|
||||
snake.dead = is_dead(&snake, game_size);
|
||||
|
||||
if (has_food(&snake, food)) {
|
||||
snake.length ++;
|
||||
food = create_food(game_size);
|
||||
print_food(food, board);
|
||||
}
|
||||
refresh();
|
||||
|
||||
uint64_t sleep = 100000 - snake.length * 5000 < 5000 ? 5000 : 100000 - snake.length * 5000;
|
||||
uint64_t next_us = io_read(AM_TIMER_UPTIME).us + sleep;
|
||||
while (io_read(AM_TIMER_UPTIME).us < next_us) ;
|
||||
} while (!snake.dead);
|
||||
|
||||
printf("GAME OVER\nPress Q to Exit\n");
|
||||
while (read_key() != AM_KEY_Q);
|
||||
return 0;
|
||||
}
|
3
am-kernels/kernels/thread-os/Makefile
Normal file
3
am-kernels/kernels/thread-os/Makefile
Normal file
|
@ -0,0 +1,3 @@
|
|||
NAME = thread-os
|
||||
SRCS = thread-os.c
|
||||
include $(AM_HOME)/Makefile
|
70
am-kernels/kernels/thread-os/thread-os.c
Normal file
70
am-kernels/kernels/thread-os/thread-os.c
Normal file
|
@ -0,0 +1,70 @@
|
|||
#include <am.h>
|
||||
#include <klib.h>
|
||||
#include <klib-macros.h>
|
||||
|
||||
#define MAX_CPU 8
|
||||
|
||||
typedef union task {
|
||||
struct {
|
||||
const char *name;
|
||||
union task *next;
|
||||
void (*entry)(void *);
|
||||
Context *context;
|
||||
};
|
||||
uint8_t stack[4096 * 3];
|
||||
} Task;
|
||||
|
||||
Task *currents[MAX_CPU];
|
||||
#define current currents[cpu_current()]
|
||||
|
||||
// user-defined tasks
|
||||
|
||||
int locked = 0;
|
||||
void lock() { while (atomic_xchg(&locked, 1)); }
|
||||
void unlock() { atomic_xchg(&locked, 0); }
|
||||
|
||||
void func(void *arg) {
|
||||
while (1) {
|
||||
lock();
|
||||
printf("Thread-%s on CPU #%d\n", arg, cpu_current());
|
||||
unlock();
|
||||
for (int volatile i = 0; i < 100000; i++) ;
|
||||
}
|
||||
}
|
||||
|
||||
Task tasks[] = {
|
||||
{ .name = "A", .entry = func },
|
||||
{ .name = "B", .entry = func },
|
||||
{ .name = "C", .entry = func },
|
||||
{ .name = "D", .entry = func },
|
||||
{ .name = "E", .entry = func },
|
||||
};
|
||||
|
||||
// ------------------
|
||||
|
||||
Context *on_interrupt(Event ev, Context *ctx) {
|
||||
extern Task tasks[];
|
||||
if (!current) current = &tasks[0];
|
||||
else current->context = ctx;
|
||||
do {
|
||||
current = current->next;
|
||||
} while ((current - tasks) % cpu_count() != cpu_current());
|
||||
return current->context;
|
||||
}
|
||||
|
||||
void mp_entry() {
|
||||
iset(true);
|
||||
yield();
|
||||
}
|
||||
|
||||
int main() {
|
||||
cte_init(on_interrupt);
|
||||
|
||||
for (int i = 0; i < LENGTH(tasks); i++) {
|
||||
Task *task = &tasks[i];
|
||||
Area stack = (Area) { &task->context + 1, task + 1 };
|
||||
task->context = kcontext(stack, task->entry, (void *)task->name);
|
||||
task->next = &tasks[(i + 1) % LENGTH(tasks)];
|
||||
}
|
||||
mpe_init(mp_entry);
|
||||
}
|
3
am-kernels/kernels/typing-game/Makefile
Normal file
3
am-kernels/kernels/typing-game/Makefile
Normal file
|
@ -0,0 +1,3 @@
|
|||
NAME = typing-game
|
||||
SRCS = game.c font.c
|
||||
include $(AM_HOME)/Makefile
|
28
am-kernels/kernels/typing-game/font.c
Normal file
28
am-kernels/kernels/typing-game/font.c
Normal file
|
@ -0,0 +1,28 @@
|
|||
char font[] = {
|
||||
0x00, 0x00, 0x1c, 0x36, 0x63, 0x63, 0x63, 0x7f, 0x63, 0x63, 0x63, 0x63, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x7e, 0x63, 0x63, 0x63, 0x7e, 0x63, 0x63, 0x63, 0x63, 0x7e, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x1e, 0x33, 0x61, 0x60, 0x60, 0x60, 0x60, 0x61, 0x33, 0x1e, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x7c, 0x66, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x66, 0x7c, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x7f, 0x60, 0x60, 0x60, 0x7e, 0x60, 0x60, 0x60, 0x60, 0x7f, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x7f, 0x60, 0x60, 0x60, 0x7c, 0x60, 0x60, 0x60, 0x60, 0x60, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x1e, 0x33, 0x63, 0x60, 0x60, 0x67, 0x63, 0x63, 0x33, 0x1e, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x63, 0x63, 0x63, 0x63, 0x7f, 0x63, 0x63, 0x63, 0x63, 0x63, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x66, 0x66, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x7e, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x63, 0x77, 0x7f, 0x6b, 0x6b, 0x63, 0x63, 0x63, 0x63, 0x63, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x63, 0x63, 0x73, 0x6b, 0x67, 0x63, 0x63, 0x63, 0x63, 0x63, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x3e, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x7e, 0x63, 0x63, 0x63, 0x63, 0x7e, 0x60, 0x60, 0x60, 0x60, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x3e, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x7b, 0x6f, 0x3e, 0x06, 0x03, 0x00, 0x00,
|
||||
0x00, 0x00, 0x7e, 0x63, 0x63, 0x63, 0x7e, 0x6c, 0x66, 0x66, 0x63, 0x63, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x3e, 0x63, 0x63, 0x30, 0x18, 0x0c, 0x06, 0x63, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x36, 0x1c, 0x08, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x63, 0x63, 0x63, 0x63, 0x63, 0x6b, 0x6b, 0x7f, 0x77, 0x63, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x63, 0x63, 0x22, 0x36, 0x1c, 0x1c, 0x36, 0x22, 0x63, 0x63, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x63, 0x63, 0x63, 0x63, 0x3e, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x7f, 0x03, 0x03, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x60, 0x7f, 0x00, 0x00, 0x00, 0x00,
|
||||
};
|
178
am-kernels/kernels/typing-game/game.c
Normal file
178
am-kernels/kernels/typing-game/game.c
Normal file
|
@ -0,0 +1,178 @@
|
|||
#include <am.h>
|
||||
#include <klib.h>
|
||||
#include <klib-macros.h>
|
||||
|
||||
#define FPS 30
|
||||
#define CPS 5
|
||||
#define CHAR_W 8
|
||||
#define CHAR_H 16
|
||||
#define NCHAR 128
|
||||
#define COL_WHITE 0xeeeeee
|
||||
#define COL_RED 0xff0033
|
||||
#define COL_GREEN 0x00cc33
|
||||
#define COL_PURPLE 0x2a0a29
|
||||
|
||||
enum { WHITE = 0, RED, GREEN, PURPLE };
|
||||
struct character {
|
||||
char ch;
|
||||
int x, y, v, t;
|
||||
} chars[NCHAR];
|
||||
|
||||
int screen_w, screen_h, hit, miss, wrong;
|
||||
uint32_t texture[3][26][CHAR_W * CHAR_H], blank[CHAR_W * CHAR_H];
|
||||
|
||||
int min(int a, int b) {
|
||||
return (a < b) ? a : b;
|
||||
}
|
||||
|
||||
int randint(int l, int r) {
|
||||
return l + (rand() & 0x7fffffff) % (r - l + 1);
|
||||
}
|
||||
|
||||
void new_char() {
|
||||
for (int i = 0; i < LENGTH(chars); i++) {
|
||||
struct character *c = &chars[i];
|
||||
if (!c->ch) {
|
||||
c->ch = 'A' + randint(0, 25);
|
||||
c->x = randint(0, screen_w - CHAR_W);
|
||||
c->y = 0;
|
||||
c->v = (screen_h - CHAR_H + 1) / randint(FPS * 3 / 2, FPS * 2);
|
||||
c->t = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void game_logic_update(int frame) {
|
||||
if (frame % (FPS / CPS) == 0) new_char();
|
||||
for (int i = 0; i < LENGTH(chars); i++) {
|
||||
struct character *c = &chars[i];
|
||||
if (c->ch) {
|
||||
if (c->t > 0) {
|
||||
if (--c->t == 0) {
|
||||
c->ch = '\0';
|
||||
}
|
||||
} else {
|
||||
c->y += c->v;
|
||||
if (c->y < 0) {
|
||||
c->ch = '\0';
|
||||
}
|
||||
if (c->y + CHAR_H >= screen_h) {
|
||||
miss++;
|
||||
c->v = 0;
|
||||
c->y = screen_h - CHAR_H;
|
||||
c->t = FPS;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void render() {
|
||||
static int x[NCHAR], y[NCHAR], n = 0;
|
||||
|
||||
for (int i = 0; i < n; i++) {
|
||||
io_write(AM_GPU_FBDRAW, x[i], y[i], blank, CHAR_W, CHAR_H, false);
|
||||
}
|
||||
|
||||
n = 0;
|
||||
for (int i = 0; i < LENGTH(chars); i++) {
|
||||
struct character *c = &chars[i];
|
||||
if (c->ch) {
|
||||
x[n] = c->x; y[n] = c->y; n++;
|
||||
int col = (c->v > 0) ? WHITE : (c->v < 0 ? GREEN : RED);
|
||||
io_write(AM_GPU_FBDRAW, c->x, c->y, texture[col][c->ch - 'A'], CHAR_W, CHAR_H, false);
|
||||
}
|
||||
}
|
||||
io_write(AM_GPU_FBDRAW, 0, 0, NULL, 0, 0, true);
|
||||
for (int i = 0; i < 40; i++) putch('\b');
|
||||
printf("Hit: %d; Miss: %d; Wrong: %d", hit, miss, wrong);
|
||||
}
|
||||
|
||||
void check_hit(char ch) {
|
||||
int m = -1;
|
||||
for (int i = 0; i < LENGTH(chars); i++) {
|
||||
struct character *c = &chars[i];
|
||||
if (ch == c->ch && c->v > 0 && (m < 0 || c->y > chars[m].y)) {
|
||||
m = i;
|
||||
}
|
||||
}
|
||||
if (m == -1) {
|
||||
wrong++;
|
||||
} else {
|
||||
hit++;
|
||||
chars[m].v = -(screen_h - CHAR_H + 1) / (FPS);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void video_init() {
|
||||
screen_w = io_read(AM_GPU_CONFIG).width;
|
||||
screen_h = io_read(AM_GPU_CONFIG).height;
|
||||
|
||||
extern char font[];
|
||||
for (int i = 0; i < CHAR_W * CHAR_H; i++)
|
||||
blank[i] = COL_PURPLE;
|
||||
|
||||
uint32_t blank_line[screen_w];
|
||||
for (int i = 0; i < screen_w; i++)
|
||||
blank_line[i] = COL_PURPLE;
|
||||
|
||||
for (int y = 0; y < screen_h; y ++)
|
||||
io_write(AM_GPU_FBDRAW, 0, y, blank_line, screen_w, 1, false);
|
||||
|
||||
for (int ch = 0; ch < 26; ch++) {
|
||||
char *c = &font[CHAR_H * ch];
|
||||
for (int i = 0, y = 0; y < CHAR_H; y++)
|
||||
for (int x = 0; x < CHAR_W; x++, i++) {
|
||||
int t = (c[y] >> (CHAR_W - x - 1)) & 1;
|
||||
texture[WHITE][ch][i] = t ? COL_WHITE : COL_PURPLE;
|
||||
texture[GREEN][ch][i] = t ? COL_GREEN : COL_PURPLE;
|
||||
texture[RED ][ch][i] = t ? COL_RED : COL_PURPLE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
char lut[256] = {
|
||||
[AM_KEY_A] = 'A', [AM_KEY_B] = 'B', [AM_KEY_C] = 'C', [AM_KEY_D] = 'D',
|
||||
[AM_KEY_E] = 'E', [AM_KEY_F] = 'F', [AM_KEY_G] = 'G', [AM_KEY_H] = 'H',
|
||||
[AM_KEY_I] = 'I', [AM_KEY_J] = 'J', [AM_KEY_K] = 'K', [AM_KEY_L] = 'L',
|
||||
[AM_KEY_M] = 'M', [AM_KEY_N] = 'N', [AM_KEY_O] = 'O', [AM_KEY_P] = 'P',
|
||||
[AM_KEY_Q] = 'Q', [AM_KEY_R] = 'R', [AM_KEY_S] = 'S', [AM_KEY_T] = 'T',
|
||||
[AM_KEY_U] = 'U', [AM_KEY_V] = 'V', [AM_KEY_W] = 'W', [AM_KEY_X] = 'X',
|
||||
[AM_KEY_Y] = 'Y', [AM_KEY_Z] = 'Z',
|
||||
};
|
||||
|
||||
int main() {
|
||||
ioe_init();
|
||||
video_init();
|
||||
|
||||
panic_on(!io_read(AM_TIMER_CONFIG).present, "requires timer");
|
||||
panic_on(!io_read(AM_INPUT_CONFIG).present, "requires keyboard");
|
||||
|
||||
printf("Type 'ESC' to exit\n");
|
||||
|
||||
int current = 0, rendered = 0;
|
||||
uint64_t t0 = io_read(AM_TIMER_UPTIME).us;
|
||||
while (1) {
|
||||
int frames = (io_read(AM_TIMER_UPTIME).us - t0) / (1000000 / FPS);
|
||||
|
||||
for (; current < frames; current++) {
|
||||
game_logic_update(current);
|
||||
}
|
||||
|
||||
while (1) {
|
||||
AM_INPUT_KEYBRD_T ev = io_read(AM_INPUT_KEYBRD);
|
||||
if (ev.keycode == AM_KEY_NONE) break;
|
||||
if (ev.keydown && ev.keycode == AM_KEY_ESCAPE) halt(0);
|
||||
if (ev.keydown && lut[ev.keycode]) {
|
||||
check_hit(lut[ev.keycode]);
|
||||
}
|
||||
};
|
||||
|
||||
if (current > rendered) {
|
||||
render();
|
||||
rendered = current;
|
||||
}
|
||||
}
|
||||
}
|
3
am-kernels/kernels/yield-os/Makefile
Normal file
3
am-kernels/kernels/yield-os/Makefile
Normal file
|
@ -0,0 +1,3 @@
|
|||
NAME = yield-os
|
||||
SRCS = yield-os.c
|
||||
include $(AM_HOME)/Makefile
|
31
am-kernels/kernels/yield-os/yield-os.c
Normal file
31
am-kernels/kernels/yield-os/yield-os.c
Normal file
|
@ -0,0 +1,31 @@
|
|||
#include <am.h>
|
||||
#include <klib-macros.h>
|
||||
|
||||
#define STACK_SIZE (4096 * 8)
|
||||
typedef union {
|
||||
uint8_t stack[STACK_SIZE];
|
||||
struct { Context *cp; };
|
||||
} PCB;
|
||||
static PCB pcb[2], pcb_boot, *current = &pcb_boot;
|
||||
|
||||
static void f(void *arg) {
|
||||
while (1) {
|
||||
putch("?AB"[(uintptr_t)arg > 2 ? 0 : (uintptr_t)arg]);
|
||||
for (int volatile i = 0; i < 100000; i++) ;
|
||||
yield();
|
||||
}
|
||||
}
|
||||
|
||||
static Context *schedule(Event ev, Context *prev) {
|
||||
current->cp = prev;
|
||||
current = (current == &pcb[0] ? &pcb[1] : &pcb[0]);
|
||||
return current->cp;
|
||||
}
|
||||
|
||||
int main() {
|
||||
cte_init(schedule);
|
||||
pcb[0].cp = kcontext((Area) { pcb[0].stack, &pcb[0] + 1 }, f, (void *)1L);
|
||||
pcb[1].cp = kcontext((Area) { pcb[1].stack, &pcb[1] + 1 }, f, (void *)2L);
|
||||
yield();
|
||||
panic("Should not reach here!");
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue