506 lines
14 KiB
C++
506 lines
14 KiB
C++
#include "ascii.h"
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include "lua.h"
|
|
#include "font.c"
|
|
|
|
#define swap(a, b) {auto tmp=a;a=b;b=tmp;}
|
|
|
|
char lua_filename[1024];
|
|
char window_title[256];
|
|
uint8_t mem[2560]; //2400
|
|
uint8_t *char_screen = NULL;
|
|
uint8_t *color_screen = NULL;
|
|
uint8_t screen_width = 40;
|
|
uint8_t screen_height = 30;
|
|
uint8_t current_color = 0x1e;
|
|
uint8_t current_mode = 1;
|
|
uint8_t cursor_x = 0;
|
|
uint8_t cursor_y = 0;
|
|
bool sounding = false;
|
|
int audio_freq = 0;
|
|
uint32_t audio_len = 0;
|
|
|
|
#define CHRSCR(x, y) char_screen[x+y*screen_width]
|
|
#define COLSCR(x, y) color_screen[x+y*screen_width]
|
|
|
|
SDL_Window *mini_win;
|
|
SDL_Renderer *mini_ren;
|
|
SDL_Texture *mini_bak = NULL;
|
|
SDL_AudioDeviceID mini_audio_device;
|
|
Uint32 *pixels;
|
|
int pitch;
|
|
|
|
uint32_t palette[16] = { 0x00000000, 0x000000AA, 0x0000AA00, 0x0000AAAA, 0x00AA0000, 0x00AA00AA, 0x00AA5500, 0x00AAAAAA,
|
|
0x00555555, 0x005555FF, 0x0055FF55, 0x0055FFFF, 0x00FF5555, 0x00FF55FF, 0x00FFFF55, 0x00FFFFFF };
|
|
|
|
#define debug_line_size 80
|
|
#define debug_num_lines 30
|
|
#define debug_total_size 2400 //debug_line_size*debug_num_lines
|
|
char debug_text[debug_total_size];
|
|
int debug_cursor = 0;
|
|
int debug_prompt = 0;
|
|
int debug_cursor_blink = 30;
|
|
bool should_reset = false;
|
|
|
|
//Uint8 keymapping[6] = { SDL_SCANCODE_LEFT, SDL_SCANCODE_RIGHT, SDL_SCANCODE_UP, SDL_SCANCODE_DOWN, SDL_SCANCODE_Z, SDL_SCANCODE_X };
|
|
const Uint8 *keys;
|
|
Uint8 key_just_pressed = 0;
|
|
|
|
int mouse_x, mouse_y, mouse_wheel;
|
|
Uint32 mouse_buttons;
|
|
|
|
void reinit() {
|
|
if (mini_bak != NULL) SDL_DestroyTexture(mini_bak);
|
|
switch (current_mode) {
|
|
case 0:
|
|
screen_width = 80;
|
|
screen_height = 30;
|
|
current_color = 0x07;
|
|
cursor_x = 0;
|
|
cursor_y = 0;
|
|
char_screen = &mem[0];
|
|
color_screen = &mem[1200];
|
|
//SDL_RenderSetLogicalSize(mini_ren, 640, 480);
|
|
mini_bak = SDL_CreateTexture(mini_ren, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, 640, 240);
|
|
break;
|
|
case 1:
|
|
screen_width = 40;
|
|
screen_height = 30;
|
|
current_color = 0x1e;
|
|
cursor_x = 0;
|
|
cursor_y = 0;
|
|
char_screen = &mem[0];
|
|
color_screen = &mem[1200];
|
|
//SDL_RenderSetLogicalSize(mini_ren, 320, 240);
|
|
mini_bak = SDL_CreateTexture(mini_ren, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, 320, 240);
|
|
break;
|
|
case 2:
|
|
screen_width = 20;
|
|
screen_height = 15;
|
|
current_color = 0x1e;
|
|
cursor_x = 0;
|
|
cursor_y = 0;
|
|
char_screen = &mem[0];
|
|
color_screen = &mem[300];
|
|
//SDL_RenderSetLogicalSize(mini_ren, 160, 120);
|
|
mini_bak = SDL_CreateTexture(mini_ren, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, 160, 120);
|
|
break;
|
|
}
|
|
}
|
|
|
|
void audioCallback(void * userdata, uint8_t * stream, int len) {
|
|
//if (audio_len <= 0) nosound();
|
|
static int period=0;
|
|
static int v = 16;
|
|
SDL_memset(stream, 0, len);
|
|
const int flen = min(audio_len, len);
|
|
audio_len -= flen;
|
|
for (int i=0; i<flen; ++i) {
|
|
stream[i] = v;
|
|
period++; if (period>=audio_freq) {period = 0; v=-v;}
|
|
}
|
|
}
|
|
|
|
uint8_t old_mode = 0;
|
|
|
|
int main(int argc,char*argv[]) {
|
|
SDL_strlcpy(lua_filename, "game.lua", 9);
|
|
if (argc > 1) SDL_strlcpy(lua_filename, argv[1], 1023);
|
|
|
|
for (int i=0; i<debug_total_size;++i) debug_text[i] = 32;
|
|
|
|
SDL_Init(49);
|
|
mini_win = SDL_CreateWindow(window_title, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640+80, 480+80, SDL_WINDOW_SHOWN);
|
|
mini_ren = SDL_CreateRenderer(mini_win, -1, SDL_RENDERER_PRESENTVSYNC);
|
|
//SDL_CreateWindowAndRenderer(512,512,0,&mini_win,&mini_ren);
|
|
//SDL_RenderSetLogicalSize(mini_ren, 320, 240);
|
|
//mini_bak = SDL_CreateTexture(mini_ren, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, 320, 240);
|
|
bool exit = false;
|
|
SDL_Event mini_eve;
|
|
|
|
SDL_AudioSpec audioSpec = {44100, AUDIO_S8, 1, 0, 512, 0, 0, audioCallback, NULL};
|
|
mini_audio_device = SDL_OpenAudioDevice(NULL, 0, &audioSpec, NULL, 0);
|
|
SDL_PauseAudioDevice(mini_audio_device, 0);
|
|
|
|
reinit();
|
|
debug("ASCII SYSTEM BOOTING...");
|
|
lua_init(lua_filename);
|
|
lua_call_init();
|
|
|
|
while(!exit) {
|
|
if (should_reset) {
|
|
should_reset = false;
|
|
setmode(1);
|
|
reinit();
|
|
lua_init(lua_filename);
|
|
lua_call_init();
|
|
}
|
|
key_just_pressed = 0;
|
|
mouse_wheel = 0;
|
|
while(SDL_PollEvent(&mini_eve)) {
|
|
if (mini_eve.type == SDL_QUIT) { exit=true; break; }
|
|
if (mini_eve.type == SDL_KEYDOWN) {
|
|
if (mini_eve.key.keysym.scancode == SDL_SCANCODE_ESCAPE) {
|
|
if (lua_is_playing()) {
|
|
lua_pause();
|
|
//lua_quit();
|
|
old_mode = current_mode;
|
|
setmode(0);
|
|
} else {
|
|
setmode(old_mode);
|
|
lua_resume();
|
|
//lua_init();
|
|
//lua_call_init();
|
|
}
|
|
} else if (mini_eve.key.keysym.scancode == SDL_SCANCODE_F5) {
|
|
lua_quit();
|
|
reinit();
|
|
lua_init(lua_filename);
|
|
lua_call_init();
|
|
} else {
|
|
key_just_pressed = mini_eve.key.keysym.scancode;
|
|
}
|
|
}
|
|
if (mini_eve.type == SDL_MOUSEWHEEL) {
|
|
mouse_wheel = mini_eve.wheel.y;
|
|
}
|
|
}
|
|
keys = SDL_GetKeyboardState(NULL);
|
|
mouse_buttons = SDL_GetMouseState(&mouse_x, &mouse_y);
|
|
mouse_x = (mouse_x-40) / (640/screen_width);
|
|
mouse_y = (mouse_y-40) / (480/screen_height);
|
|
|
|
if (lua_is_playing()) {
|
|
lua_call_update();
|
|
} else {
|
|
debug_cursor_blink--;
|
|
if (debug_cursor_blink == 0) {
|
|
debug_cursor_blink = 30;
|
|
debug_text[debug_cursor] = debug_text[debug_cursor]==32 ? 95 : 32;
|
|
}
|
|
loop();
|
|
}
|
|
SDL_LockTexture(mini_bak, NULL, (void**)&pixels, &pitch);
|
|
|
|
switch (current_mode) {
|
|
case 0:
|
|
for (int y=0; y<screen_height; ++y) {
|
|
for (int x=0; x<screen_width; ++x) {
|
|
const uint8_t chr_color = current_color; //COLSCR(x,y);
|
|
const uint32_t ink_color = palette[chr_color & 0x0f];
|
|
const uint32_t paper_color = palette[chr_color >> 4];
|
|
const uint8_t chr = CHRSCR(x,y);
|
|
for (int l=0; l<8; ++l) {
|
|
const uint8_t line = font[chr*8+l];
|
|
for (int b=0; b<8; ++b) {
|
|
if ((line >> (7-b)) & 0x01) {
|
|
pixels[b+(x*8)+((y*8)+l)*(screen_width*8)] = ink_color;
|
|
} else {
|
|
pixels[b+(x*8)+((y*8)+l)*(screen_width*8)] = paper_color;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case 1:
|
|
case 2:
|
|
for (int y=0; y<screen_height; ++y) {
|
|
for (int x=0; x<screen_width; ++x) {
|
|
const uint8_t chr_color = COLSCR(x,y);
|
|
const uint32_t ink_color = palette[chr_color & 0x0f];
|
|
const uint32_t paper_color = palette[chr_color >> 4];
|
|
const uint8_t chr = CHRSCR(x,y);
|
|
for (int l=0; l<8; ++l) {
|
|
const uint8_t line = font[chr*8+l];
|
|
for (int b=0; b<8; ++b) {
|
|
if ((line >> (7-b)) & 0x01) {
|
|
pixels[b+(x*8)+((y*8)+l)*(screen_width*8)] = ink_color;
|
|
} else {
|
|
pixels[b+(x*8)+((y*8)+l)*(screen_width*8)] = paper_color;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
//for (int i=0;i<screen_surface->size;++i) pixels[i] = palette[screen_surface->p[i]];
|
|
|
|
SDL_UnlockTexture(mini_bak);
|
|
SDL_SetRenderDrawColor(mini_ren, (palette[0] >> 16)&0xff, (palette[0] >> 8)&0xff, palette[0]&0xff, 0);
|
|
//SDL_SetRenderDrawColor(mini_ren, 255, 0, 0, 0);
|
|
SDL_RenderClear(mini_ren);
|
|
SDL_Rect rect = {40, 40, 640, 480};
|
|
SDL_RenderCopy(mini_ren, mini_bak, NULL, &rect);
|
|
//SDL_RenderCopy(mini_ren, mini_bak, NULL, NULL);
|
|
SDL_RenderPresent(mini_ren);
|
|
}
|
|
lua_quit();
|
|
SDL_Quit();
|
|
return 0;
|
|
}
|
|
|
|
void cls(uint8_t value) {
|
|
SDL_memset(char_screen, value, screen_width*screen_height);
|
|
if (current_mode != 0) SDL_memset(color_screen, current_color, screen_width*screen_height);
|
|
if (!lua_is_playing()) {
|
|
SDL_memset(debug_text, 32, debug_total_size);
|
|
debug_cursor = 1;
|
|
debug_prompt = 0;
|
|
debug_text[debug_prompt] = '>';
|
|
}
|
|
}
|
|
|
|
void ink(uint8_t value) {
|
|
current_color = (current_color & 0xf0) + (value & 0x0f);
|
|
}
|
|
|
|
void paper(uint8_t value) {
|
|
current_color = (current_color & 0x0f) + (value << 4);
|
|
}
|
|
|
|
void color(uint8_t ink, uint8_t paper) {
|
|
current_color = (ink & 0x0f) + (paper << 4);
|
|
}
|
|
|
|
void locate(uint8_t x, uint8_t y) {
|
|
cursor_x = min(x, screen_width-1);
|
|
cursor_y = min(y, screen_height-1);
|
|
}
|
|
|
|
void print(const char *str, int x, int y) {
|
|
if (x >= 0) cursor_x = min(x, screen_width-1);
|
|
if (y >= 0) cursor_y = min(y, screen_height-1);
|
|
int len = SDL_strlen(str);
|
|
if ((cursor_x+len) > screen_width) len -= ((cursor_x+len) - screen_width);
|
|
//int offset = x+y*screen_width;
|
|
for (int i=0; i < len; ++i) {
|
|
CHRSCR(cursor_x+i, cursor_y) = str[i];
|
|
if (current_mode != 0) COLSCR(cursor_x+i, cursor_y) = current_color;
|
|
//char_screen[offset+i] = str[i];
|
|
//if (current_mode != 0) color_screen[offset+i] = current_color;
|
|
}
|
|
cursor_x += len;
|
|
}
|
|
|
|
bool btn(uint8_t i) {
|
|
return keys[i];
|
|
}
|
|
|
|
bool btnp(uint8_t i) {
|
|
return key_just_pressed == i;
|
|
}
|
|
|
|
uint8_t whichbtn() {
|
|
return key_just_pressed;
|
|
}
|
|
|
|
int mousex() {
|
|
return mouse_x;
|
|
}
|
|
|
|
int mousey() {
|
|
return mouse_y;
|
|
}
|
|
|
|
int mousewheel() {
|
|
return mouse_wheel;
|
|
}
|
|
|
|
bool mousebutton(uint8_t i) {
|
|
return mouse_buttons & SDL_BUTTON(i);
|
|
}
|
|
|
|
int time() {
|
|
return SDL_GetTicks();
|
|
}
|
|
|
|
/*float abs(float x) {
|
|
return SDL_fabsf(x);
|
|
}*/
|
|
|
|
float flr(float x) {
|
|
return SDL_floorf(x);
|
|
}
|
|
|
|
float sgn(float x) {
|
|
return x >= 0 ? 1 : -1;
|
|
}
|
|
|
|
#ifndef __LINUX__
|
|
#ifndef __APPLE__
|
|
|
|
float ceil(float x) {
|
|
return SDL_ceilf(x);
|
|
}
|
|
|
|
float sin(float x) {
|
|
return SDL_sinf(x);
|
|
}
|
|
|
|
float cos(float x) {
|
|
return SDL_cosf(x);
|
|
}
|
|
|
|
float atan2(float dx, float dy) {
|
|
return SDL_atan2f(dx, dy);
|
|
}
|
|
|
|
float sqrt(float x) {
|
|
return SDL_sqrtf(x);
|
|
}
|
|
|
|
#endif
|
|
#endif
|
|
|
|
float max(float x, float y) {
|
|
return SDL_max(x, y);
|
|
}
|
|
|
|
float mid(float x, float y, float z) {
|
|
return max(x, min(y, z));
|
|
}
|
|
|
|
float min(float x, float y) {
|
|
return SDL_min(x, y);
|
|
}
|
|
|
|
int rnd(int x) {
|
|
return rand()%x;
|
|
}
|
|
|
|
/*void srand(int x) {
|
|
srand(x);
|
|
}*/
|
|
|
|
char tostr_tmp[256];
|
|
const char* tostr(float val) {
|
|
return SDL_itoa(val, tostr_tmp, 10);
|
|
}
|
|
|
|
void debug_set_prompt() {
|
|
debug_prompt = debug_cursor++;
|
|
debug_text[debug_prompt] = '>';
|
|
}
|
|
|
|
void debug_one_line_up() {
|
|
for (int i=0; i<debug_total_size-debug_line_size;++i) debug_text[i] = debug_text[i+debug_line_size];
|
|
for (int i=debug_total_size-debug_line_size; i<debug_total_size;++i) debug_text[i] = 32;
|
|
debug_cursor = debug_total_size-debug_line_size;
|
|
debug_set_prompt();
|
|
}
|
|
|
|
void debugchr(const uint8_t chr) {
|
|
if (chr == 8) {
|
|
if (debug_cursor>(debug_prompt+1)) {
|
|
debug_text[debug_cursor--] = 32;
|
|
debug_text[debug_cursor] = 32;
|
|
}
|
|
} else {
|
|
debug_text[debug_cursor++] = chr;
|
|
if (debug_cursor >= debug_total_size) debug_one_line_up();
|
|
}
|
|
}
|
|
|
|
void debug(const char *str) {
|
|
const int len = SDL_strlen(str);
|
|
for (int i=0; i<len;++i) {
|
|
debug_text[debug_cursor++] = str[i];
|
|
if (debug_cursor >= debug_total_size) debug_one_line_up();
|
|
}
|
|
debug_cursor = (int(debug_cursor/debug_line_size)+1)*debug_line_size;
|
|
if (debug_cursor >= debug_total_size) debug_one_line_up();
|
|
debug_set_prompt();
|
|
}
|
|
|
|
void pdebug() {
|
|
int i=0;
|
|
for (int y=0; y<debug_num_lines;++y) {
|
|
for (int x=0; x<debug_line_size;++x) {
|
|
CHRSCR(x, y) = debug_text[i++];
|
|
//COLSCR(x, y) = 0x1e;
|
|
}
|
|
}
|
|
}
|
|
|
|
void debug_get_cmd() {
|
|
debug_text[debug_cursor] = 0;
|
|
lua_call_cmd(&debug_text[debug_prompt+1]);
|
|
}
|
|
|
|
uint8_t ascii(const char *str, uint8_t index) {
|
|
return str[index];
|
|
}
|
|
|
|
char chr_trans[2] = "X";
|
|
const char* chr(uint8_t ascii) {
|
|
uint8_t* peiv = (uint8_t*)chr_trans;
|
|
*peiv = ascii;
|
|
return chr_trans;
|
|
}
|
|
|
|
void setchar(uint8_t index, uint8_t b0, uint8_t b1, uint8_t b2, uint8_t b3, uint8_t b4, uint8_t b5, uint8_t b6, uint8_t b7) {
|
|
font[index*8] = b0;
|
|
font[index*8+1] = b1;
|
|
font[index*8+2] = b2;
|
|
font[index*8+3] = b3;
|
|
font[index*8+4] = b4;
|
|
font[index*8+5] = b5;
|
|
font[index*8+6] = b6;
|
|
font[index*8+7] = b7;
|
|
}
|
|
|
|
uint8_t peek(uint16_t addr) {
|
|
if (addr < 0xA00) {
|
|
return mem[addr];
|
|
} else {
|
|
return font[addr-0xA00];
|
|
}
|
|
}
|
|
|
|
void poke(uint16_t addr, uint8_t val) {
|
|
if (addr < 0xA00) {
|
|
mem[addr] = val;
|
|
} else {
|
|
font[addr-0xA00] = val;
|
|
}
|
|
}
|
|
|
|
void sound(float freq, uint32_t len) {
|
|
// [TODO]
|
|
audio_len = len*44.1f;
|
|
audio_freq = 44100.0f/freq/2.0f;
|
|
sounding = true;
|
|
}
|
|
|
|
void nosound() {
|
|
//SDL_PauseAudioDevice(mini_audio_device, 1);
|
|
audio_len = 0;
|
|
sounding = false;
|
|
}
|
|
|
|
void setmode(const uint8_t mode) {
|
|
current_mode = mode;
|
|
reinit();
|
|
}
|
|
|
|
void load(const char* str) {
|
|
SDL_strlcpy(lua_filename, str, SDL_strlen(str)+1);
|
|
should_reset = true;
|
|
}
|
|
|
|
void fileout(const char* str, uint16_t addr, uint16_t size) {
|
|
FILE* f = fopen(str, "wb");
|
|
fwrite(&mem[addr], size, 1, f);
|
|
fclose(f);
|
|
}
|
|
|
|
void filein(const char* str, uint16_t addr, uint16_t size) {
|
|
FILE* f = fopen(str, "rb");
|
|
fread(&mem[addr], size, 1, f);
|
|
fclose(f);
|
|
}
|