Add Conway's Game of Life
parent
db33973e0a
commit
dba7552c1e
206
ape/ape.S
206
ape/ape.S
|
@ -364,6 +364,109 @@ pcread: push %ax
|
||||||
jmp 1b
|
jmp 1b
|
||||||
.endfn pcread
|
.endfn pcread
|
||||||
|
|
||||||
|
/ Waits for serial lines to become idle.
|
||||||
|
/
|
||||||
|
/ @param di short array of serial ports (0 means not present)
|
||||||
|
/ @param si number of items in array
|
||||||
|
/ @mode long,legacy,real
|
||||||
|
sflush: mov %si,%cx
|
||||||
|
mov %di,%si
|
||||||
|
xor %dx,%dx
|
||||||
|
0: lodsb
|
||||||
|
mov %al,%dl
|
||||||
|
lodsb
|
||||||
|
mov %al,%dh
|
||||||
|
test %ax,%ax
|
||||||
|
jz 2f
|
||||||
|
add $UART_LSR,%dx
|
||||||
|
mov $UART_TTYIDL,%ah
|
||||||
|
1: in %dx,%al
|
||||||
|
and %ah,%al
|
||||||
|
rep
|
||||||
|
nop
|
||||||
|
jz 1b
|
||||||
|
loop 0b
|
||||||
|
2: ret
|
||||||
|
.endfn sflush,globl
|
||||||
|
|
||||||
|
/ Transmits byte over serial line.
|
||||||
|
/
|
||||||
|
/ This is both blocking and asynchronous.
|
||||||
|
/
|
||||||
|
/ @param di character to send
|
||||||
|
/ @param si serial port
|
||||||
|
/ @mode long,legacy,real
|
||||||
|
/ @see ttytxr
|
||||||
|
sputc: push %ax
|
||||||
|
push %cx
|
||||||
|
push %dx
|
||||||
|
mov %si,%dx
|
||||||
|
add $UART_LSR,%dx
|
||||||
|
mov $UART_TTYTXR,%ah
|
||||||
|
1: in %dx,%al
|
||||||
|
and %ah,%al
|
||||||
|
jnz 2f
|
||||||
|
rep
|
||||||
|
nop
|
||||||
|
jmp 1b
|
||||||
|
2: mov %di,%ax
|
||||||
|
mov %si,%dx
|
||||||
|
out %al,%dx
|
||||||
|
pop %dx
|
||||||
|
pop %cx
|
||||||
|
pop %ax
|
||||||
|
ret
|
||||||
|
.endfn sputc,globl
|
||||||
|
|
||||||
|
/ Shuts down personal computer.
|
||||||
|
/
|
||||||
|
/ @mode real
|
||||||
|
/ @noreturn
|
||||||
|
apmoff: mov $0x5300,%ax # apm installation check
|
||||||
|
xor %bx,%bx # for the apm bios itself
|
||||||
|
int $APM_SERVICE
|
||||||
|
jc 1f
|
||||||
|
cmp $'P<<8|'M,%bx # did apm bios service interrupt?
|
||||||
|
jne 1f
|
||||||
|
mov $0x5301,%ax # real mode interface connect
|
||||||
|
xor %bx,%bx # to apm bios device
|
||||||
|
int $APM_SERVICE # ignore errors e.g. already connected
|
||||||
|
xor %bx,%bx
|
||||||
|
xor %cx,%cx
|
||||||
|
mov $0x5307,%ax # set power state
|
||||||
|
mov $1,%bl # for all devices within my dominion
|
||||||
|
mov $3,%cl # to off
|
||||||
|
int $APM_SERVICE
|
||||||
|
1: call panic
|
||||||
|
.endfn apmoff,globl
|
||||||
|
|
||||||
|
/ Video put char.
|
||||||
|
/
|
||||||
|
/ @param al is the char
|
||||||
|
/ @mode real
|
||||||
|
rvputc: push %bx # don't clobber bp,bx,di,si,cx
|
||||||
|
push %bp # original ibm pc scroll up bug
|
||||||
|
mov $7,%bx # normal mda/cga style page zero
|
||||||
|
mov $0x0e,%ah # teletype output al cp437
|
||||||
|
int $0x10 # vidya service
|
||||||
|
pop %bp # preserves al
|
||||||
|
pop %bx
|
||||||
|
ret
|
||||||
|
.endfn rvputc
|
||||||
|
|
||||||
|
/ Video put string.
|
||||||
|
/
|
||||||
|
/ @param di is the string
|
||||||
|
/ @mode real
|
||||||
|
rvputs: mov %di,%si
|
||||||
|
0: lodsb
|
||||||
|
test %al,%al
|
||||||
|
je 1f
|
||||||
|
call rvputc
|
||||||
|
jmp 0b
|
||||||
|
1: ret
|
||||||
|
.endfn rvputs,globl,hidden
|
||||||
|
|
||||||
/*───────────────────────────────────────────────────────────────────────────│─╗
|
/*───────────────────────────────────────────────────────────────────────────│─╗
|
||||||
│ αcτµαlly pδrταblε εxεcµταblε § partition table ─╬─│┼
|
│ αcτµαlly pδrταblε εxεcµταblε § partition table ─╬─│┼
|
||||||
╚────────────────────────────────────────────────────────────────────────────│*/
|
╚────────────────────────────────────────────────────────────────────────────│*/
|
||||||
|
@ -1143,33 +1246,6 @@ rlput2: push %di
|
||||||
1: ret
|
1: ret
|
||||||
.endfn rlput2,globl,hidden
|
.endfn rlput2,globl,hidden
|
||||||
|
|
||||||
/ Video put string.
|
|
||||||
/
|
|
||||||
/ @param di is the string
|
|
||||||
/ @mode real
|
|
||||||
rvputs: mov %di,%si
|
|
||||||
0: lodsb
|
|
||||||
test %al,%al
|
|
||||||
je 1f
|
|
||||||
call rvputc
|
|
||||||
jmp 0b
|
|
||||||
1: ret
|
|
||||||
.endfn rvputs,globl,hidden
|
|
||||||
|
|
||||||
/ Video put char.
|
|
||||||
/
|
|
||||||
/ @param al is the char
|
|
||||||
/ @mode real
|
|
||||||
rvputc: push %bx # don't clobber bp,bx,di,si,cx
|
|
||||||
push %bp # original ibm pc scroll up bug
|
|
||||||
mov $7,%bx # normal mda/cga style page zero
|
|
||||||
mov $0x0e,%ah # teletype output al cp437
|
|
||||||
int $0x10 # vidya service
|
|
||||||
pop %bp # preserves al
|
|
||||||
pop %bx
|
|
||||||
ret
|
|
||||||
.endfn rvputc
|
|
||||||
|
|
||||||
/ Writes string to serial line.
|
/ Writes string to serial line.
|
||||||
/
|
/
|
||||||
/ @param di NUL-terminated string
|
/ @param di NUL-terminated string
|
||||||
|
@ -1191,82 +1267,6 @@ sputs: push %bx
|
||||||
ret
|
ret
|
||||||
.endfn sputs,globl
|
.endfn sputs,globl
|
||||||
|
|
||||||
/ Waits for serial lines to become idle.
|
|
||||||
/
|
|
||||||
/ @param di short array of serial ports (0 means not present)
|
|
||||||
/ @param si number of items in array
|
|
||||||
/ @mode long,legacy,real
|
|
||||||
sflush: mov %si,%cx
|
|
||||||
mov %di,%si
|
|
||||||
xor %dx,%dx
|
|
||||||
0: lodsb
|
|
||||||
mov %al,%dl
|
|
||||||
lodsb
|
|
||||||
mov %al,%dh
|
|
||||||
test %ax,%ax
|
|
||||||
jz 2f
|
|
||||||
add $UART_LSR,%dx
|
|
||||||
mov $UART_TTYIDL,%ah
|
|
||||||
1: in %dx,%al
|
|
||||||
and %ah,%al
|
|
||||||
rep
|
|
||||||
nop
|
|
||||||
jz 1b
|
|
||||||
loop 0b
|
|
||||||
2: ret
|
|
||||||
.endfn sflush,globl
|
|
||||||
|
|
||||||
/ Transmits byte over serial line.
|
|
||||||
/
|
|
||||||
/ This is both blocking and asynchronous.
|
|
||||||
/
|
|
||||||
/ @param di character to send
|
|
||||||
/ @param si serial port
|
|
||||||
/ @mode long,legacy,real
|
|
||||||
/ @see ttytxr
|
|
||||||
sputc: push %ax
|
|
||||||
push %cx
|
|
||||||
push %dx
|
|
||||||
mov %si,%dx
|
|
||||||
add $UART_LSR,%dx
|
|
||||||
mov $UART_TTYTXR,%ah
|
|
||||||
1: in %dx,%al
|
|
||||||
and %ah,%al
|
|
||||||
jnz 2f
|
|
||||||
rep
|
|
||||||
nop
|
|
||||||
jmp 1b
|
|
||||||
2: mov %di,%ax
|
|
||||||
mov %si,%dx
|
|
||||||
out %al,%dx
|
|
||||||
pop %dx
|
|
||||||
pop %cx
|
|
||||||
pop %ax
|
|
||||||
ret
|
|
||||||
.endfn sputc,globl
|
|
||||||
|
|
||||||
/ Shuts down personal computer.
|
|
||||||
/
|
|
||||||
/ @mode real
|
|
||||||
/ @noreturn
|
|
||||||
apmoff: mov $0x5300,%ax # apm installation check
|
|
||||||
xor %bx,%bx # for the apm bios itself
|
|
||||||
int $APM_SERVICE
|
|
||||||
jc 1f
|
|
||||||
cmp $'P<<8|'M,%bx # did apm bios service interrupt?
|
|
||||||
jne 1f
|
|
||||||
mov $0x5301,%ax # real mode interface connect
|
|
||||||
xor %bx,%bx # to apm bios device
|
|
||||||
int $APM_SERVICE # ignore errors e.g. already connected
|
|
||||||
xor %bx,%bx
|
|
||||||
xor %cx,%cx
|
|
||||||
mov $0x5307,%ax # set power state
|
|
||||||
mov $1,%bl # for all devices within my dominion
|
|
||||||
mov $3,%cl # to off
|
|
||||||
int $APM_SERVICE
|
|
||||||
1: call panic
|
|
||||||
.endfn apmoff,globl
|
|
||||||
|
|
||||||
/* █ █▒
|
/* █ █▒
|
||||||
█ █
|
█ █
|
||||||
█▓▄ █ █
|
█▓▄ █ █
|
||||||
|
|
|
@ -16,10 +16,10 @@ LIBC_CALLS_ARTIFACTS += LIBC_CALLS_A
|
||||||
LIBC_CALLS = $(LIBC_CALLS_A_DEPS) $(LIBC_CALLS_A)
|
LIBC_CALLS = $(LIBC_CALLS_A_DEPS) $(LIBC_CALLS_A)
|
||||||
LIBC_CALLS_A = o/$(MODE)/libc/calls/syscalls.a
|
LIBC_CALLS_A = o/$(MODE)/libc/calls/syscalls.a
|
||||||
LIBC_CALLS_A_FILES := \
|
LIBC_CALLS_A_FILES := \
|
||||||
$(wildcard libc/calls/*) \
|
|
||||||
$(wildcard libc/calls/typedef/*) \
|
$(wildcard libc/calls/typedef/*) \
|
||||||
$(wildcard libc/calls/thunks/*) \
|
$(wildcard libc/calls/thunks/*) \
|
||||||
$(wildcard libc/calls/struct/*)
|
$(wildcard libc/calls/struct/*) \
|
||||||
|
$(wildcard libc/calls/*)
|
||||||
LIBC_CALLS_A_HDRS = $(filter %.h,$(LIBC_CALLS_A_FILES))
|
LIBC_CALLS_A_HDRS = $(filter %.h,$(LIBC_CALLS_A_FILES))
|
||||||
LIBC_CALLS_A_SRCS_S = $(filter %.S,$(LIBC_CALLS_A_FILES))
|
LIBC_CALLS_A_SRCS_S = $(filter %.S,$(LIBC_CALLS_A_FILES))
|
||||||
LIBC_CALLS_A_SRCS_C = $(filter %.c,$(LIBC_CALLS_A_FILES))
|
LIBC_CALLS_A_SRCS_C = $(filter %.c,$(LIBC_CALLS_A_FILES))
|
||||||
|
|
|
@ -43,22 +43,22 @@ static textwindows int64_t ParseInt(char16_t **p) {
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
||||||
static textwindows void WriteAll(int64_t h, void *buf, size_t n) {
|
static noinline textwindows void DoAll(int64_t h, void *buf, size_t n,
|
||||||
|
bool32 (*f)()) {
|
||||||
char *p;
|
char *p;
|
||||||
size_t i;
|
size_t i;
|
||||||
uint32_t wrote;
|
uint32_t x;
|
||||||
for (p = buf, i = 0; i < n; i += wrote) {
|
for (p = buf, i = 0; i < n; i += x) {
|
||||||
WriteFile(h, p + i, n - i, &wrote, NULL);
|
f(h, p + i, n - i, &x, NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static textwindows void ReadAll(int64_t h, void *buf, size_t n) {
|
static noinline textwindows void WriteAll(int64_t h, void *buf, size_t n) {
|
||||||
char *p;
|
DoAll(h, buf, n, WriteFile);
|
||||||
size_t i;
|
}
|
||||||
uint32_t got;
|
|
||||||
for (p = buf, i = 0; i < n; i += got) {
|
static noinline textwindows void ReadAll(int64_t h, void *buf, size_t n) {
|
||||||
ReadFile(h, p + i, n - i, &got, NULL);
|
DoAll(h, buf, n, ReadFile);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
textwindows void WinMainForked(void) {
|
textwindows void WinMainForked(void) {
|
||||||
|
|
|
@ -16,9 +16,6 @@ int ioctl(int, uint64_t, void *);
|
||||||
#include "libc/macros.h"
|
#include "libc/macros.h"
|
||||||
#include "libc/sysv/consts/termios.h"
|
#include "libc/sysv/consts/termios.h"
|
||||||
|
|
||||||
struct termios;
|
|
||||||
struct winsize;
|
|
||||||
|
|
||||||
#define ioctl(FD, REQUEST, MEMORY) ioctl$dispatch(FD, REQUEST, MEMORY)
|
#define ioctl(FD, REQUEST, MEMORY) ioctl$dispatch(FD, REQUEST, MEMORY)
|
||||||
|
|
||||||
#define __IOCTL_DISPATCH(CMP, FD, REQUEST, MEMORY) \
|
#define __IOCTL_DISPATCH(CMP, FD, REQUEST, MEMORY) \
|
||||||
|
|
|
@ -2,13 +2,12 @@
|
||||||
#define COSMOPOLITAN_LIBC_CALLS_TERMIOS_INTERNAL_H_
|
#define COSMOPOLITAN_LIBC_CALLS_TERMIOS_INTERNAL_H_
|
||||||
#ifndef __STRICT_ANSI__
|
#ifndef __STRICT_ANSI__
|
||||||
#include "libc/bits/safemacros.h"
|
#include "libc/bits/safemacros.h"
|
||||||
|
#include "libc/calls/struct/metatermios.h"
|
||||||
|
#include "libc/calls/struct/termios.h"
|
||||||
#include "libc/str/str.h"
|
#include "libc/str/str.h"
|
||||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||||
COSMOPOLITAN_C_START_
|
COSMOPOLITAN_C_START_
|
||||||
|
|
||||||
struct termios;
|
|
||||||
union metatermios;
|
|
||||||
|
|
||||||
#define COPY_TERMIOS(TO, FROM) \
|
#define COPY_TERMIOS(TO, FROM) \
|
||||||
do { \
|
do { \
|
||||||
memset((TO), 0, sizeof(*(TO))); \
|
memset((TO), 0, sizeof(*(TO))); \
|
||||||
|
|
|
@ -33,7 +33,6 @@ relegated noreturn void die(void) {
|
||||||
if (!once) {
|
if (!once) {
|
||||||
once = true;
|
once = true;
|
||||||
if (!IsTiny()) {
|
if (!IsTiny()) {
|
||||||
g_runstate |= RUNSTATE_BROKEN;
|
|
||||||
if (IsDebuggerPresent(false)) DebugBreak();
|
if (IsDebuggerPresent(false)) DebugBreak();
|
||||||
ShowBacktrace(STDERR_FILENO, NULL);
|
ShowBacktrace(STDERR_FILENO, NULL);
|
||||||
}
|
}
|
||||||
|
|
|
@ -203,7 +203,6 @@ relegated void __oncrash(int sig, struct siginfo *si, ucontext_t *ctx) {
|
||||||
int gdbpid, err;
|
int gdbpid, err;
|
||||||
static bool once;
|
static bool once;
|
||||||
err = errno;
|
err = errno;
|
||||||
g_runstate |= RUNSTATE_BROKEN;
|
|
||||||
if (once) abort();
|
if (once) abort();
|
||||||
once = true;
|
once = true;
|
||||||
/* TODO(jart): Needs translation for ucontext_t and possibly siginfo_t. */
|
/* TODO(jart): Needs translation for ucontext_t and possibly siginfo_t. */
|
||||||
|
|
|
@ -53,7 +53,6 @@ void __ubsan_abort(const struct UbsanSourceLocation *loc,
|
||||||
} else {
|
} else {
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
g_runstate |= RUNSTATE_BROKEN;
|
|
||||||
if (IsDebuggerPresent(false)) DebugBreak();
|
if (IsDebuggerPresent(false)) DebugBreak();
|
||||||
__start_fatal(loc->file, loc->line);
|
__start_fatal(loc->file, loc->line);
|
||||||
fprintf(stderr, "%s\r\n", description);
|
fprintf(stderr, "%s\r\n", description);
|
||||||
|
|
|
@ -1,23 +0,0 @@
|
||||||
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
|
||||||
│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│
|
|
||||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
|
||||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
|
||||||
│ │
|
|
||||||
│ This program is free software; you can redistribute it and/or modify │
|
|
||||||
│ it under the terms of the GNU General Public License as published by │
|
|
||||||
│ the Free Software Foundation; version 2 of the License. │
|
|
||||||
│ │
|
|
||||||
│ This program is distributed in the hope that it will be useful, but │
|
|
||||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
|
||||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
|
||||||
│ General Public License for more details. │
|
|
||||||
│ │
|
|
||||||
│ You should have received a copy of the GNU General Public License │
|
|
||||||
│ along with this program; if not, write to the Free Software │
|
|
||||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
|
||||||
│ 02110-1301 USA │
|
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
|
||||||
#include "libc/macros.h"
|
|
||||||
|
|
||||||
.comm g_runstate,4
|
|
||||||
.source __FILE__
|
|
|
@ -1,5 +1,7 @@
|
||||||
#ifndef COSMOPOLITAN_LIBC_NT_IOCP_H_
|
#ifndef COSMOPOLITAN_LIBC_NT_IOCP_H_
|
||||||
#define COSMOPOLITAN_LIBC_NT_IOCP_H_
|
#define COSMOPOLITAN_LIBC_NT_IOCP_H_
|
||||||
|
#include "libc/nt/struct/overlapped.h"
|
||||||
|
#include "libc/nt/struct/overlappedentry.h"
|
||||||
#if 0
|
#if 0
|
||||||
/* ░░░░
|
/* ░░░░
|
||||||
▒▒▒░░░▒▒▒▒▒▒▒▓▓▓░
|
▒▒▒░░░▒▒▒▒▒▒▒▓▓▓░
|
||||||
|
@ -26,8 +28,6 @@
|
||||||
│ cosmopolitan § new technology » i/o completion ports ─╬─│┼
|
│ cosmopolitan § new technology » i/o completion ports ─╬─│┼
|
||||||
╚────────────────────────────────────────────────────────────────────────────│*/
|
╚────────────────────────────────────────────────────────────────────────────│*/
|
||||||
#endif
|
#endif
|
||||||
#include "libc/nt/struct/overlapped.h"
|
|
||||||
#include "libc/nt/struct/overlappedentry.h"
|
|
||||||
|
|
||||||
#define kNtFileSkipCompletionPortOnSuccess 1
|
#define kNtFileSkipCompletionPortOnSuccess 1
|
||||||
#define kNtFileSkipSetEventOnHandle 2
|
#define kNtFileSkipSetEventOnHandle 2
|
||||||
|
|
|
@ -30,7 +30,6 @@
|
||||||
/ @asyncsignalsafe
|
/ @asyncsignalsafe
|
||||||
_Exit: push %rbp
|
_Exit: push %rbp
|
||||||
mov %rsp,%rbp
|
mov %rsp,%rbp
|
||||||
orl $RUNSTATE_TERMINATE,g_runstate(%rip)
|
|
||||||
#if SupportsWindows()
|
#if SupportsWindows()
|
||||||
testb IsWindows()
|
testb IsWindows()
|
||||||
jz 1f
|
jz 1f
|
||||||
|
@ -49,4 +48,3 @@ _Exit: push %rbp
|
||||||
3: .quad 0
|
3: .quad 0
|
||||||
.endfn _Exit,globl,protected
|
.endfn _Exit,globl,protected
|
||||||
.hidden __NR_exit
|
.hidden __NR_exit
|
||||||
.hidden g_runstate
|
|
||||||
|
|
|
@ -39,7 +39,6 @@ abort: push %rbp
|
||||||
mov %rsp,%rbp
|
mov %rsp,%rbp
|
||||||
and $-16,%rsp
|
and $-16,%rsp
|
||||||
sub $16,%rsp
|
sub $16,%rsp
|
||||||
orl $RUNSTATE_BROKEN,g_runstate(%rip)
|
|
||||||
testb IsWindows()
|
testb IsWindows()
|
||||||
jnz 2f
|
jnz 2f
|
||||||
mov SIG_SETMASK,%edi
|
mov SIG_SETMASK,%edi
|
||||||
|
@ -61,4 +60,3 @@ abort: push %rbp
|
||||||
2: mov $134,%edi # exit(128+SIGABRT) [bash-ism]
|
2: mov $134,%edi # exit(128+SIGABRT) [bash-ism]
|
||||||
call _Exit
|
call _Exit
|
||||||
.endfn abort,globl,protected
|
.endfn abort,globl,protected
|
||||||
.hidden g_runstate
|
|
||||||
|
|
|
@ -31,7 +31,6 @@
|
||||||
_construct:
|
_construct:
|
||||||
push %rbp
|
push %rbp
|
||||||
mov %rsp,%rbp
|
mov %rsp,%rbp
|
||||||
orb $RUNSTATE_INITIALIZED,g_runstate(%rip)
|
|
||||||
ezlea __init_array_start,ax # static ctors in forward order
|
ezlea __init_array_start,ax # static ctors in forward order
|
||||||
.weak __init_array_start # could be called multiple times
|
.weak __init_array_start # could be called multiple times
|
||||||
ezlea __init_array_end,cx # idempotency recommended
|
ezlea __init_array_end,cx # idempotency recommended
|
||||||
|
|
|
@ -72,7 +72,7 @@ privileged interruptfn void ftrace_hook(void) {
|
||||||
const char *symbol;
|
const char *symbol;
|
||||||
struct StackFrame *frame;
|
struct StackFrame *frame;
|
||||||
LOAD_DEFAULT_RBX();
|
LOAD_DEFAULT_RBX();
|
||||||
if (g_symbols && !(g_runstate & RUNSTATE_BROKEN)) {
|
if (g_symbols) {
|
||||||
frame = __builtin_frame_address(0);
|
frame = __builtin_frame_address(0);
|
||||||
symbol =
|
symbol =
|
||||||
&g_symbols->name_base[g_symbols
|
&g_symbols->name_base[g_symbols
|
||||||
|
|
|
@ -50,7 +50,6 @@
|
||||||
.section .initprologue,"ax",@progbits
|
.section .initprologue,"ax",@progbits
|
||||||
.type _init,@function
|
.type _init,@function
|
||||||
.globl _init
|
.globl _init
|
||||||
.comm g_runstate,4
|
|
||||||
_init: push %rbp
|
_init: push %rbp
|
||||||
mov %rsp,%rbp
|
mov %rsp,%rbp
|
||||||
.profilable
|
.profilable
|
||||||
|
|
|
@ -4,20 +4,15 @@
|
||||||
#include "libc/dce.h"
|
#include "libc/dce.h"
|
||||||
#include "libc/runtime/runtime.h"
|
#include "libc/runtime/runtime.h"
|
||||||
|
|
||||||
#define RUNSTATE_INITIALIZED (1 << 0)
|
|
||||||
#define RUNSTATE_BROKEN (1 << 1)
|
|
||||||
#define RUNSTATE_TERMINATE (1 << 2)
|
|
||||||
|
|
||||||
#define STACK_CEIL 0x700000000000ul
|
#define STACK_CEIL 0x700000000000ul
|
||||||
#define STACK_SIZE FRAMESIZE
|
#define STACK_SIZE FRAMESIZE
|
||||||
|
|
||||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||||
COSMOPOLITAN_C_START_
|
COSMOPOLITAN_C_START_
|
||||||
|
|
||||||
hidden extern bool _mmap_asan_mode;
|
extern hidden bool _mmap_asan_mode;
|
||||||
hidden extern char **g_freebsdhint;
|
extern hidden char **g_freebsdhint;
|
||||||
hidden extern unsigned g_runstate;
|
extern hidden void *g_stacktop;
|
||||||
hidden extern void *g_stacktop;
|
|
||||||
|
|
||||||
void _init(void) hidden;
|
void _init(void) hidden;
|
||||||
void _piro(int) hidden;
|
void _piro(int) hidden;
|
||||||
|
@ -29,12 +24,6 @@ void _jmpstack(void *, void *, ...) hidden noreturn;
|
||||||
long _setstack(void *, void *, ...) hidden;
|
long _setstack(void *, void *, ...) hidden;
|
||||||
int GetDosArgv(const char16_t *, char *, size_t, char **, size_t) hidden;
|
int GetDosArgv(const char16_t *, char *, size_t, char **, size_t) hidden;
|
||||||
|
|
||||||
forceinline void AssertNeverCalledWhileTerminating(void) {
|
|
||||||
if (!NoDebug() && (g_runstate & RUNSTATE_TERMINATE)) {
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
COSMOPOLITAN_C_END_
|
COSMOPOLITAN_C_END_
|
||||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||||
#endif /* ANSI */
|
#endif /* ANSI */
|
||||||
|
|
|
@ -24,7 +24,10 @@
|
||||||
* without meeting its requirements concerning secrecy or length.
|
* without meeting its requirements concerning secrecy or length.
|
||||||
*/
|
*/
|
||||||
void *memfrob(void *buf, size_t size) {
|
void *memfrob(void *buf, size_t size) {
|
||||||
unsigned char *p = (unsigned char *)buf;
|
size_t i;
|
||||||
for (size_t i = 0; i < size; ++i) p[i] ^= '*';
|
unsigned char *p;
|
||||||
|
for (p = buf, i = 0; i < size; ++i) {
|
||||||
|
p[i] ^= '*';
|
||||||
|
}
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
|
@ -107,16 +107,21 @@ int main(int argc, char *argv[]) {
|
||||||
uint8_t *tablebuf;
|
uint8_t *tablebuf;
|
||||||
struct iovec iov[7];
|
struct iovec iov[7];
|
||||||
const char *symname;
|
const char *symname;
|
||||||
|
const char *outpath;
|
||||||
Elf64_Xword symcount;
|
Elf64_Xword symcount;
|
||||||
struct Ints symnames;
|
struct Ints symnames;
|
||||||
struct String symbols;
|
struct String symbols;
|
||||||
struct String filenames;
|
struct String filenames;
|
||||||
const char *options, *outpath;
|
|
||||||
struct Header *header1, *header2;
|
struct Header *header1, *header2;
|
||||||
size_t wrote, remain, objectargcount;
|
size_t wrote, remain, objectargcount;
|
||||||
int *offsets, *modes, *sizes, *names;
|
int *offsets, *modes, *sizes, *names;
|
||||||
int i, j, fd, err, name, outfd, tablebufsize;
|
int i, j, fd, err, name, outfd, tablebufsize;
|
||||||
|
|
||||||
|
if (!(argc > 2 && strcmp(argv[1], "rcsD") == 0)) {
|
||||||
|
fprintf(stderr, "%s%s%s\n", "Usage: ", argv[0], " rcsD ARCHIVE FILE...");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
st = xmalloc(sizeof(struct stat));
|
st = xmalloc(sizeof(struct stat));
|
||||||
symbols.i = 0;
|
symbols.i = 0;
|
||||||
symbols.n = 4096;
|
symbols.n = 4096;
|
||||||
|
@ -128,12 +133,9 @@ int main(int argc, char *argv[]) {
|
||||||
symnames.n = 1024;
|
symnames.n = 1024;
|
||||||
symnames.p = xmalloc(symnames.n * sizeof(int));
|
symnames.p = xmalloc(symnames.n * sizeof(int));
|
||||||
|
|
||||||
CHECK_GT(argc, 3);
|
|
||||||
options = argv[1];
|
|
||||||
outpath = argv[2];
|
outpath = argv[2];
|
||||||
objectargs = argv + 3;
|
objectargs = argv + 3;
|
||||||
objectargcount = argc - 3;
|
objectargcount = argc - 3;
|
||||||
CHECK_EQ(0, strcmp(options, "rcsD"));
|
|
||||||
modes = xmalloc(sizeof(int) * objectargcount);
|
modes = xmalloc(sizeof(int) * objectargcount);
|
||||||
names = xmalloc(sizeof(int) * objectargcount);
|
names = xmalloc(sizeof(int) * objectargcount);
|
||||||
sizes = xmalloc(sizeof(int) * objectargcount);
|
sizes = xmalloc(sizeof(int) * objectargcount);
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
COSMOPOLITAN_C_START_
|
COSMOPOLITAN_C_START_
|
||||||
|
|
||||||
#define POKE(MEM, VAL) \
|
#define POKE(MEM, VAL) \
|
||||||
asm volatile("mov\t%1,%%es:%0" : "=m"(MEM) : "Qi"((typeof(MEM))(VAL)))
|
asm volatile("mov%z0\t%1,%%es:%0" : "=m"(MEM) : "Qi"((typeof(MEM))(VAL)))
|
||||||
|
|
||||||
COSMOPOLITAN_C_END_
|
COSMOPOLITAN_C_END_
|
||||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||||
|
|
|
@ -43,7 +43,7 @@
|
||||||
|
|
||||||
%token_prefix TK_
|
%token_prefix TK_
|
||||||
%token_type {struct Token}
|
%token_type {struct Token}
|
||||||
%type expr {long double}
|
%default_type {struct Token}
|
||||||
%syntax_error { SyntaxError(); }
|
%syntax_error { SyntaxError(); }
|
||||||
|
|
||||||
%token AUTO BREAK CASE CHAR CONST CONTINUE DEFAULT DO DOUBLE ELSE ENUM EXTERN.
|
%token AUTO BREAK CASE CHAR CONST CONTINUE DEFAULT DO DOUBLE ELSE ENUM EXTERN.
|
||||||
|
|
|
@ -0,0 +1,527 @@
|
||||||
|
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||||
|
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||||
|
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||||
|
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||||
|
│ │
|
||||||
|
│ This program is free software; you can redistribute it and/or modify │
|
||||||
|
│ it under the terms of the GNU General Public License as published by │
|
||||||
|
│ the Free Software Foundation; version 2 of the License. │
|
||||||
|
│ │
|
||||||
|
│ This program is distributed in the hope that it will be useful, but │
|
||||||
|
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||||
|
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||||
|
│ General Public License for more details. │
|
||||||
|
│ │
|
||||||
|
│ You should have received a copy of the GNU General Public License │
|
||||||
|
│ along with this program; if not, write to the Free Software │
|
||||||
|
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||||
|
│ 02110-1301 USA │
|
||||||
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
|
#include "libc/bits/bits.h"
|
||||||
|
#include "libc/bits/safemacros.h"
|
||||||
|
#include "libc/calls/calls.h"
|
||||||
|
#include "libc/calls/ioctl.h"
|
||||||
|
#include "libc/calls/struct/stat.h"
|
||||||
|
#include "libc/calls/struct/termios.h"
|
||||||
|
#include "libc/calls/struct/winsize.h"
|
||||||
|
#include "libc/calls/termios-internal.h"
|
||||||
|
#include "libc/conv/conv.h"
|
||||||
|
#include "libc/dce.h"
|
||||||
|
#include "libc/errno.h"
|
||||||
|
#include "libc/log/log.h"
|
||||||
|
#include "libc/macros.h"
|
||||||
|
#include "libc/mem/mem.h"
|
||||||
|
#include "libc/runtime/runtime.h"
|
||||||
|
#include "libc/stdio/stdio.h"
|
||||||
|
#include "libc/str/str.h"
|
||||||
|
#include "libc/str/tpenc.h"
|
||||||
|
#include "libc/sysv/consts/termios.h"
|
||||||
|
#include "libc/x/x.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @fileoverview Conway's Game of Life
|
||||||
|
*
|
||||||
|
* The Game of Life, also known simply as Life, is a cellular automaton
|
||||||
|
* devised by the British mathematician John Horton Conway in 1970. It
|
||||||
|
* is Turing complete and can simulate a universal constructor or any
|
||||||
|
* other Turing machine.
|
||||||
|
*
|
||||||
|
* This program may be used by dragging the mouse in the terminal. Left
|
||||||
|
* mouse draws or erases cells. Right mouse scrolls or moves the plane.
|
||||||
|
* The space bar may be held down to move time forward.
|
||||||
|
*
|
||||||
|
* This implementation uses bitboards on an n×m wraparound plane. For an
|
||||||
|
* explanation of how this technique works on an 8×8 plane see "Bitboard
|
||||||
|
* Methods for Games" by Cameron Browne.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define INTERRUPTED 1
|
||||||
|
#define RESIZED 2
|
||||||
|
|
||||||
|
#define MOUSE_LEFT_DOWN 0
|
||||||
|
#define MOUSE_MIDDLE_DOWN 1
|
||||||
|
#define MOUSE_RIGHT_DOWN 2
|
||||||
|
#define MOUSE_LEFT_UP 4
|
||||||
|
#define MOUSE_MIDDLE_UP 5
|
||||||
|
#define MOUSE_RIGHT_UP 6
|
||||||
|
#define MOUSE_LEFT_DRAG 32
|
||||||
|
#define MOUSE_MIDDLE_DRAG 33
|
||||||
|
#define MOUSE_RIGHT_DRAG 34
|
||||||
|
#define MOUSE_WHEEL_UP 64
|
||||||
|
#define MOUSE_WHEEL_DOWN 65
|
||||||
|
#define MOUSE_CTRL_WHEEL_UP 80
|
||||||
|
#define MOUSE_CTRL_WHEEL_DOWN 81
|
||||||
|
|
||||||
|
#define LEFT 0x0101010101010101ul
|
||||||
|
#define RIGHT 0x8080808080808080ul
|
||||||
|
#define TOP 0x00000000000000FFul
|
||||||
|
#define BOTTOM 0xFF00000000000000ul
|
||||||
|
|
||||||
|
#define CTRL(C) ((C) ^ 0100)
|
||||||
|
#define GOUP(x) ((x) >> 8)
|
||||||
|
#define GODOWN(x) ((x) << 8)
|
||||||
|
#define GORIGHT(x) (((x) & ~RIGHT) << 1)
|
||||||
|
#define GOLEFT(x) (((x) & ~LEFT) >> 1)
|
||||||
|
#define LEFTMOST(x) ((x)&LEFT)
|
||||||
|
#define RIGHTMOST(x) ((x)&RIGHT)
|
||||||
|
#define TOPMOST(x) ((x)&TOP)
|
||||||
|
#define BOTMOST(x) ((x)&BOTTOM)
|
||||||
|
|
||||||
|
#define ADD(X) \
|
||||||
|
do { \
|
||||||
|
uint64_t c1, c2; \
|
||||||
|
c1 = r[0] & (X); \
|
||||||
|
c2 = r[1] & c1; \
|
||||||
|
r[0] ^= (X); \
|
||||||
|
r[1] ^= c1; \
|
||||||
|
r[2] |= c2; \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define STEP(RES, B00, B01, B02, B10, B11, B12, B20, B21, B22) \
|
||||||
|
do { \
|
||||||
|
uint64_t r[3] = {0}; \
|
||||||
|
ADD(GORIGHT(GODOWN(B11)) | GORIGHT(BOTMOST(B01) >> 56) | \
|
||||||
|
GODOWN(RIGHTMOST(B10) >> 7) | BOTMOST(RIGHTMOST(B00)) >> 7 >> 56); \
|
||||||
|
ADD(GORIGHT(B11) | RIGHTMOST(B10) >> 7); \
|
||||||
|
ADD(GORIGHT(GOUP(B11)) | GORIGHT(TOPMOST(B21) << 56) | \
|
||||||
|
GOUP(RIGHTMOST(B10) >> 7) | TOPMOST(RIGHTMOST(B20)) >> 7 << 56); \
|
||||||
|
ADD(GODOWN(B11) | BOTMOST(B01) >> 56); \
|
||||||
|
ADD(GOUP(B11) | TOPMOST(B21) << 56); \
|
||||||
|
ADD(GOLEFT(GODOWN(B11)) | GOLEFT(BOTMOST(B01) >> 56) | \
|
||||||
|
GODOWN(LEFTMOST(B12) << 7) | BOTMOST(LEFTMOST(B02)) << 7 >> 56); \
|
||||||
|
ADD(GOLEFT(B11) | LEFTMOST(B12) << 7); \
|
||||||
|
ADD(GOLEFT(GOUP(B11)) | GOLEFT(TOPMOST(B21) << 56) | \
|
||||||
|
GOUP(LEFTMOST(B12) << 7) | TOPMOST(LEFTMOST(B22)) << 7 << 56); \
|
||||||
|
RES = (B11 | r[0]) & r[1] & ~r[2]; \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
struct Buffer {
|
||||||
|
unsigned i, n;
|
||||||
|
char *p;
|
||||||
|
};
|
||||||
|
|
||||||
|
static bool erase;
|
||||||
|
static bool natural;
|
||||||
|
static bool mousemode;
|
||||||
|
|
||||||
|
static int out;
|
||||||
|
static int action;
|
||||||
|
|
||||||
|
static long top;
|
||||||
|
static long bottom;
|
||||||
|
static long left;
|
||||||
|
static long right;
|
||||||
|
static long tyn;
|
||||||
|
static long txn;
|
||||||
|
static long byn;
|
||||||
|
static long bxn;
|
||||||
|
static long save_y;
|
||||||
|
static long save_x;
|
||||||
|
static long save_top;
|
||||||
|
static long save_left;
|
||||||
|
|
||||||
|
static uint64_t *board;
|
||||||
|
|
||||||
|
static struct Buffer buffer;
|
||||||
|
static struct termios oldterm;
|
||||||
|
|
||||||
|
static int Write(const char *s) {
|
||||||
|
return write(out, s, strlen(s));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void HideCursor(void) {
|
||||||
|
Write("\e[?25l");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ShowCursor(void) {
|
||||||
|
Write("\e[?25h");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void EnableMouse(void) {
|
||||||
|
mousemode = true;
|
||||||
|
Write("\e[?1000;1002;1015;1006h");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void DisableMouse(void) {
|
||||||
|
mousemode = false;
|
||||||
|
Write("\e[?1000;1002;1015;1006l");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void LeaveScreen(void) {
|
||||||
|
Write("\e[H\e[J");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void GetTtySize(void) {
|
||||||
|
struct winsize wsize;
|
||||||
|
wsize.ws_row = tyn;
|
||||||
|
wsize.ws_col = txn;
|
||||||
|
getttysize(out, &wsize);
|
||||||
|
tyn = wsize.ws_row;
|
||||||
|
txn = wsize.ws_col;
|
||||||
|
right = left + txn;
|
||||||
|
bottom = top + tyn;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void EnableRaw(void) {
|
||||||
|
struct termios term;
|
||||||
|
memcpy(&term, &oldterm, sizeof(term));
|
||||||
|
term.c_cc[VMIN] = 1;
|
||||||
|
term.c_cc[VTIME] = 1;
|
||||||
|
term.c_iflag &= ~(INPCK | ISTRIP | PARMRK | INLCR | IGNCR | ICRNL | IXON);
|
||||||
|
term.c_lflag &= ~(IEXTEN | ICANON | ECHO | ECHONL);
|
||||||
|
term.c_cflag &= ~(CSIZE | PARENB);
|
||||||
|
term.c_cflag |= CS8;
|
||||||
|
term.c_iflag |= IUTF8;
|
||||||
|
ioctl(out, TCSETS, &term);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void OnExit(void) {
|
||||||
|
LeaveScreen();
|
||||||
|
ShowCursor();
|
||||||
|
DisableMouse();
|
||||||
|
ioctl(out, TCSETS, &oldterm);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void OnSigInt(int sig, struct siginfo *sa, struct ucontext *uc) {
|
||||||
|
action |= INTERRUPTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void OnSigWinch(int sig, struct siginfo *sa, struct ucontext *uc) {
|
||||||
|
action |= RESIZED;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool Test(long y, long x) {
|
||||||
|
return (board[(bxn >> 3) * (y >> 3) + (x >> 3)] >>
|
||||||
|
(((y & 7) << 3) + (x & 7))) &
|
||||||
|
1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Set(long y, long x) {
|
||||||
|
board[(bxn >> 3) * (y >> 3) + (x >> 3)] |= 1ul << (((y & 7) << 3) + (x & 7));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Unset(long y, long x) {
|
||||||
|
board[(bxn >> 3) * (y >> 3) + (x >> 3)] &=
|
||||||
|
~(1ul << (((y & 7) << 3) + (x & 7)));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Setup(void) {
|
||||||
|
out = 1;
|
||||||
|
tyn = 80;
|
||||||
|
txn = 24;
|
||||||
|
byn = 64 * 4;
|
||||||
|
bxn = 64 * 8;
|
||||||
|
board = xcalloc((byn * bxn) >> 6, 8);
|
||||||
|
GetTtySize();
|
||||||
|
top = byn / 2 - tyn / 2;
|
||||||
|
left = bxn / 2 - txn / 2;
|
||||||
|
right = left + txn;
|
||||||
|
bottom = top + tyn;
|
||||||
|
ioctl(out, TCGETS, &oldterm);
|
||||||
|
HideCursor();
|
||||||
|
EnableRaw();
|
||||||
|
EnableMouse();
|
||||||
|
atexit(OnExit);
|
||||||
|
sigaction(SIGINT, &(struct sigaction){.sa_sigaction = OnSigInt}, NULL);
|
||||||
|
sigaction(SIGWINCH, &(struct sigaction){.sa_sigaction = OnSigWinch}, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void AppendData(char *data, unsigned len) {
|
||||||
|
char *p;
|
||||||
|
unsigned n;
|
||||||
|
if (buffer.i + len + 1 > buffer.n) {
|
||||||
|
n = MAX(buffer.i + len + 1, MAX(16, buffer.n + (buffer.n >> 1)));
|
||||||
|
if (!(p = realloc(buffer.p, n))) return;
|
||||||
|
buffer.p = p;
|
||||||
|
buffer.n = n;
|
||||||
|
}
|
||||||
|
memcpy(buffer.p + buffer.i, data, len);
|
||||||
|
buffer.p[buffer.i += len] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void AppendChar(char c) {
|
||||||
|
AppendData(&c, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void AppendStr(const char *s) {
|
||||||
|
AppendData(s, strlen(s));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void AppendWide(wint_t wc) {
|
||||||
|
unsigned i;
|
||||||
|
uint64_t wb;
|
||||||
|
char buf[8];
|
||||||
|
i = 0;
|
||||||
|
wb = tpenc(wc);
|
||||||
|
do {
|
||||||
|
buf[i++] = wb & 0xFF;
|
||||||
|
wb >>= 8;
|
||||||
|
} while (wb);
|
||||||
|
AppendData(buf, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Move(long dy, long dx) {
|
||||||
|
top = top + dy;
|
||||||
|
bottom = bottom + dy;
|
||||||
|
left = left + dx;
|
||||||
|
right = right + dx;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void OnUp(void) {
|
||||||
|
Move(-1, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void OnDown(void) {
|
||||||
|
Move(+1, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void OnLeft(void) {
|
||||||
|
Move(0, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void OnRight(void) {
|
||||||
|
Move(0, +1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Generation(void) {
|
||||||
|
uint64_t *board2;
|
||||||
|
long y, x, yn, xn, yp, ym, xp, xm;
|
||||||
|
yn = byn >> 3;
|
||||||
|
xn = bxn >> 3;
|
||||||
|
board2 = xmalloc(yn * xn * 8);
|
||||||
|
for (y = 0; y < yn; ++y) {
|
||||||
|
for (x = 0; x < xn; ++x) {
|
||||||
|
ym = y ? y - 1 : yn - 1;
|
||||||
|
yp = y + 1 < yn ? y + 1 : 0;
|
||||||
|
xm = x ? x - 1 : xn - 1;
|
||||||
|
xp = x + 1 < xn ? x + 1 : 0;
|
||||||
|
STEP(board2[y * xn + x], board[ym * xn + xm], board[ym * xn + x],
|
||||||
|
board[ym * xn + xp], board[y * xn + xm], board[y * xn + x],
|
||||||
|
board[y * xn + xp], board[yp * xn + xm], board[yp * xn + x],
|
||||||
|
board[yp * xn + xp]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(board);
|
||||||
|
board = board2;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void OnMouseLeftDrag(long y, long x) {
|
||||||
|
if (y == save_y && x == save_x) return;
|
||||||
|
save_y = y;
|
||||||
|
save_x = x;
|
||||||
|
y += top;
|
||||||
|
x += left;
|
||||||
|
if (y < 0 || y >= byn) return;
|
||||||
|
if (x < 0 || x >= bxn) return;
|
||||||
|
if (erase) {
|
||||||
|
Unset(y, x);
|
||||||
|
} else {
|
||||||
|
Set(y, x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void OnMouseLeftDown(long y, long x) {
|
||||||
|
save_y = y;
|
||||||
|
save_x = x;
|
||||||
|
y += top;
|
||||||
|
x += left;
|
||||||
|
erase = false;
|
||||||
|
if (y < 0 || y >= byn) return;
|
||||||
|
if (x < 0 || x >= bxn) return;
|
||||||
|
if ((erase = Test(y, x))) {
|
||||||
|
Unset(y, x);
|
||||||
|
} else {
|
||||||
|
Set(y, x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void OnMouseRightDown(long y, long x) {
|
||||||
|
save_y = y;
|
||||||
|
save_x = x;
|
||||||
|
save_top = top;
|
||||||
|
save_left = left;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void OnMouseRightDrag(long y, long x) {
|
||||||
|
long dy, dx, h, w;
|
||||||
|
dy = save_y - y;
|
||||||
|
dx = save_x - x;
|
||||||
|
if (natural) {
|
||||||
|
dy = -dy;
|
||||||
|
dx = -dx;
|
||||||
|
}
|
||||||
|
h = bottom - top;
|
||||||
|
w = right - left;
|
||||||
|
top = save_top + dy;
|
||||||
|
left = save_left + dx;
|
||||||
|
bottom = top + h;
|
||||||
|
right = left + w;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void OnMouse(char *p) {
|
||||||
|
int e, x, y;
|
||||||
|
e = strtol(p, &p, 10);
|
||||||
|
if (*p == ';') ++p;
|
||||||
|
x = min(txn, max(1, strtol(p, &p, 10))) - 1;
|
||||||
|
if (*p == ';') ++p;
|
||||||
|
y = min(tyn, max(1, strtol(p, &p, 10))) - 1;
|
||||||
|
e |= (*p == 'm') << 2;
|
||||||
|
switch (e) {
|
||||||
|
case MOUSE_WHEEL_UP:
|
||||||
|
if (natural) {
|
||||||
|
OnDown();
|
||||||
|
OnDown();
|
||||||
|
OnDown();
|
||||||
|
} else {
|
||||||
|
OnUp();
|
||||||
|
OnUp();
|
||||||
|
OnUp();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case MOUSE_WHEEL_DOWN:
|
||||||
|
if (natural) {
|
||||||
|
OnUp();
|
||||||
|
OnUp();
|
||||||
|
OnUp();
|
||||||
|
} else {
|
||||||
|
OnDown();
|
||||||
|
OnDown();
|
||||||
|
OnDown();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case MOUSE_RIGHT_DOWN:
|
||||||
|
OnMouseRightDown(y, x);
|
||||||
|
break;
|
||||||
|
case MOUSE_RIGHT_DRAG:
|
||||||
|
OnMouseRightDrag(y, x);
|
||||||
|
break;
|
||||||
|
case MOUSE_LEFT_DOWN:
|
||||||
|
OnMouseLeftDown(y, x);
|
||||||
|
break;
|
||||||
|
case MOUSE_LEFT_DRAG:
|
||||||
|
OnMouseLeftDrag(y, x);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ReadKeyboard(void) {
|
||||||
|
char buf[32], *p = buf;
|
||||||
|
memset(buf, 0, sizeof(buf));
|
||||||
|
if (readansi(0, buf, sizeof(buf)) == -1) {
|
||||||
|
if (errno == EINTR) return;
|
||||||
|
exit(errno);
|
||||||
|
}
|
||||||
|
switch (*p++) {
|
||||||
|
case 'q':
|
||||||
|
exit(0);
|
||||||
|
case ' ':
|
||||||
|
case 's':
|
||||||
|
Generation();
|
||||||
|
break;
|
||||||
|
case 'k':
|
||||||
|
case CTRL('P'):
|
||||||
|
OnUp();
|
||||||
|
break;
|
||||||
|
case 'j':
|
||||||
|
case CTRL('N'):
|
||||||
|
OnDown();
|
||||||
|
break;
|
||||||
|
case 'M':
|
||||||
|
if (mousemode) {
|
||||||
|
DisableMouse();
|
||||||
|
} else {
|
||||||
|
EnableMouse();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case '\e':
|
||||||
|
switch (*p++) {
|
||||||
|
case '[':
|
||||||
|
switch (*p++) {
|
||||||
|
case '<':
|
||||||
|
OnMouse(p);
|
||||||
|
break;
|
||||||
|
case 'A':
|
||||||
|
OnUp();
|
||||||
|
break;
|
||||||
|
case 'B':
|
||||||
|
OnDown();
|
||||||
|
break;
|
||||||
|
case 'D':
|
||||||
|
OnLeft();
|
||||||
|
break;
|
||||||
|
case 'C':
|
||||||
|
OnRight();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Draw(void) {
|
||||||
|
long y, x;
|
||||||
|
buffer.i = 0;
|
||||||
|
AppendStr("\e[H");
|
||||||
|
for (y = top; y < bottom; ++y) {
|
||||||
|
if (y > top) AppendStr("\e[K\r\n");
|
||||||
|
for (x = left; x < right; ++x) {
|
||||||
|
if ((0 <= y && y < byn) && (0 <= x && x < bxn)) {
|
||||||
|
if (Test(y, x)) {
|
||||||
|
AppendWide(u'█');
|
||||||
|
} else {
|
||||||
|
AppendChar(' ');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
AppendWide(u'∙');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
write(out, buffer.p, buffer.i);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Life(void) {
|
||||||
|
do {
|
||||||
|
if (action & RESIZED) {
|
||||||
|
GetTtySize();
|
||||||
|
action &= ~RESIZED;
|
||||||
|
}
|
||||||
|
Draw();
|
||||||
|
ReadKeyboard();
|
||||||
|
} while (!(action & INTERRUPTED));
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
if (!NoDebug()) showcrashreports();
|
||||||
|
Setup();
|
||||||
|
Life();
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -446,7 +446,6 @@ static void OnPrevEnd(void) {
|
||||||
|
|
||||||
static void OnMouse(char *p) {
|
static void OnMouse(char *p) {
|
||||||
int e, x, y;
|
int e, x, y;
|
||||||
struct Panel *ep;
|
|
||||||
e = strtol(p, &p, 10);
|
e = strtol(p, &p, 10);
|
||||||
if (*p == ';') ++p;
|
if (*p == ';') ++p;
|
||||||
x = min(txn, max(1, strtol(p, &p, 10))) - 1;
|
x = min(txn, max(1, strtol(p, &p, 10))) - 1;
|
||||||
|
@ -843,13 +842,7 @@ static void RangesZoom(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void MemZoom(void) {
|
static void MemZoom(void) {
|
||||||
char *p;
|
|
||||||
int c, fg2, rc, fg;
|
|
||||||
long i, n, r, w, y, x, got, have;
|
|
||||||
do {
|
do {
|
||||||
if (action & INTERRUPTED) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (action & RESIZED) {
|
if (action & RESIZED) {
|
||||||
GetTtySize();
|
GetTtySize();
|
||||||
SetupCanvas();
|
SetupCanvas();
|
||||||
|
|
Loading…
Reference in New Issue