--- /dev/null
+################################################################
+#
+# $Id:$
+#
+# $Log:$
+#
+
+ifeq ($(V),1)
+ VB=''
+else
+ VB=@
+endif
+
+UPX=upx
+CC=mips-linux-gcc-3.3.6
+
+CFLAGS+=-ggdb3 -Os -std=c99
+CFLAGS+=-DSNOM360
+LDFLAGS+=-Wl,--gc-sections
+CFLAGS+=-Wall -DNORMALUNIX -DLINUX -DSNDSERV -D_DEFAULT_SOURCE -static # -DUSEASM
+LIBS+=-lm -lc
+
+# subdirectory for objects
+OBJDIR=build
+OUTPUT=doomgeneric
+
+SRC_DOOM = dummy.o am_map.o doomdef.o doomstat.o dstrings.o d_event.o d_items.o d_iwad.o d_loop.o d_main.o d_mode.o d_net.o f_finale.o f_wipe.o g_game.o hu_lib.o hu_stuff.o info.o i_cdmus.o i_endoom.o i_joystick.o i_scale.o i_sound.o i_system.o i_timer.o memio.o m_argv.o m_bbox.o m_cheat.o m_config.o m_controls.o m_fixed.o m_menu.o m_misc.o m_random.o p_ceilng.o p_doors.o p_enemy.o p_floor.o p_inter.o p_lights.o p_map.o p_maputl.o p_mobj.o p_plats.o p_pspr.o p_saveg.o p_setup.o p_sight.o p_spec.o p_switch.o p_telept.o p_tick.o p_user.o r_bsp.o r_data.o r_draw.o r_main.o r_plane.o r_segs.o r_sky.o r_things.o sha1.o sounds.o statdump.o st_lib.o st_stuff.o s_sound.o tables.o v_video.o wi_stuff.o w_checksum.o w_file.o w_main.o w_wad.o z_zone.o w_file_stdc.o i_input.o i_video.o doomgeneric.o doomgeneric_snom360.o snom360.o
+OBJS += $(addprefix $(OBJDIR)/, $(SRC_DOOM))
+
+all: $(OUTPUT)
+
+clean:
+ rm -rf $(OBJDIR)
+ rm -f $(OUTPUT)
+ rm -f $(OUTPUT).gdb
+ rm -f $(OUTPUT).map
+
+$(OUTPUT): $(OBJS)
+ @echo [Linking $@]
+ $(VB)$(CC) $(CFLAGS) $(LDFLAGS) $(OBJS) \
+ -o $(OUTPUT) $(LIBS) -Wl,-Map,$(OUTPUT).map
+ @echo [Size]
+ -$(CROSS_COMPILE)size $(OUTPUT)
+
+$(OBJS): | $(OBJDIR)
+
+$(OBJDIR):
+ mkdir -p $(OBJDIR)
+
+$(OBJDIR)/%.o: %.c
+ @echo [Compiling $<]
+ $(VB)$(CC) $(CFLAGS) -c $< -o $@
+
+print:
+ @echo OBJS: $(OBJS)
+
+compress: $(OUTPUT)
+ $(UPX) -9 $(OUTPUT)
--- /dev/null
+#define _BSD_SOURCE
+
+#include <getopt.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/time.h>
+#include <unistd.h>
+
+#define IMG_WIDTH DISPLAY_COLS
+#define IMG_HEIGHT (DISPLAY_ROWS * 8)
+#define IMG_SIZE (IMG_WIDTH * IMG_HEIGHT)
+
+#define KEYQUEUE_SIZE 16
+
+#include "doomkeys.h"
+#include "doomgeneric.h"
+
+#include "snom360.h"
+
+static struct timeval start;
+static int contrast = 60;
+
+static uint8_t greyscale[IMG_SIZE];
+static uint8_t buf[DISPLAY_SIZE];
+
+static unsigned short s_KeyQueue[KEYQUEUE_SIZE];
+static unsigned int s_KeyQueueWriteIndex = 0;
+static unsigned int s_KeyQueueReadIndex = 0;
+
+const int snom_led_map[] = {
+ [1] = SNOM_LED_ONE,
+ [2] = SNOM_LED_TWO,
+ [3] = SNOM_LED_THREE,
+ [4] = SNOM_LED_FOUR,
+ [5] = SNOM_LED_FIVE,
+ [6] = SNOM_LED_SIX,
+ [7] = SNOM_LED_SEVEN,
+ [8] = SNOM_LED_EIGHT,
+ [9] = SNOM_LED_NINE,
+ [10] = SNOM_LED_TEN,
+ [11] = SNOM_LED_ELEVEN,
+ [12] = SNOM_LED_TWELVE
+};
+
+static unsigned char
+convertToDoomKey(SnomKey key)
+{
+ switch(key) {
+ case SNOM_KEY_QUICK_ONE:
+ return KEY_ENTER;
+ case SNOM_KEY_QUICK_TWO:
+ return KEY_ESCAPE;
+ case SNOM_KEY_LEFT:
+ return KEY_LEFTARROW;
+ case SNOM_KEY_RIGHT:
+ return KEY_RIGHTARROW;
+ case SNOM_KEY_UP:
+ return KEY_UPARROW;
+ case SNOM_KEY_DOWN:
+ return KEY_DOWNARROW;
+ case SNOM_KEY_ACCEPT:
+ return KEY_FIRE;
+ case SNOM_KEY_CANCEL:
+ return KEY_USE;
+ default:
+ break;
+ }
+ return 0;
+}
+
+static void
+addKeyToQueue(SnomKey keyCode)
+{
+ s_KeyQueue[s_KeyQueueWriteIndex] = keyCode;
+ s_KeyQueueWriteIndex++;
+ s_KeyQueueWriteIndex %= KEYQUEUE_SIZE;
+}
+
+void
+DG_Init()
+{
+ snom360_setup();
+ snom360_set_led(SNOM_LED_BACKLIGHT, 1);
+}
+
+void
+DG_DrawFrame()
+{
+ SnomKey keyCode = snom360_keyboard_read();
+ if (keyCode != -1) addKeyToQueue(keyCode);
+
+ for (int y = 0; y < IMG_HEIGHT; y++) {
+ for (int x = 0; x < IMG_WIDTH; x++) {
+ // Sample from source (simple nearest neighbor)
+ int src_x = (x * 640) / IMG_WIDTH;
+ int src_y = (y * 400) / (IMG_HEIGHT);
+
+ uint32_t p1 = DG_ScreenBuffer[src_y * 640 + src_x];
+ uint32_t p2 = DG_ScreenBuffer[src_y * 640 + src_x + 1];
+ uint32_t p3 = DG_ScreenBuffer[(src_y + 1) * 640 + src_x];
+ uint32_t p4 = DG_ScreenBuffer[(src_y + 1) * 640 + src_x + 1];
+
+ // Average the RGB components
+ unsigned char r = (((p1>>16)&0xFF) + ((p2>>16)&0xFF) + ((p3>>16)&0xFF) + ((p4>>16)&0xFF)) >> 2;
+ unsigned char g = (((p1>>8)&0xFF) + ((p2>>8)&0xFF) + ((p3>>8)&0xFF) + ((p4>>8)&0xFF)) >> 2;
+ unsigned char b = ((p1&0xFF) + (p2&0xFF) + (p3&0xFF) + (p4&0xFF)) >> 2;
+
+ // Convert to grayscale
+ unsigned char gray = (r * 76 + g * 150 + b * 29) >> 8;
+
+ greyscale[y * IMG_WIDTH + x] = gray > contrast;
+ }
+ }
+
+ for (int i = 0; i < DISPLAY_ROWS; ++i) {
+ for (int j = 0; j < DISPLAY_COLS; ++j) {
+ int pb = i*DISPLAY_COLS + j;
+ int pr = (DISPLAY_ROWS-1-i)*DISPLAY_COLS*8 + j;
+ int o = DISPLAY_COLS;
+ buf[pb] = greyscale[pr+o*0] << 7
+ | greyscale[pr+o*1] << 6
+ | greyscale[pr+o*2] << 5
+ | greyscale[pr+o*3] << 4
+ | greyscale[pr+o*4] << 3
+ | greyscale[pr+o*5] << 2
+ | greyscale[pr+o*6] << 1
+ | greyscale[pr+o*7] << 0;
+ }
+ }
+
+ snom360_display_draw(buf);
+}
+
+void
+DG_SleepMs(uint32_t ms)
+{
+ usleep(ms * 1000);
+}
+
+uint32_t
+DG_GetTicksMs()
+{
+ struct timeval cur;
+ long seconds, usec;
+
+ gettimeofday(&cur, NULL);
+ seconds = cur.tv_sec - start.tv_sec;
+ usec = cur.tv_usec - start.tv_usec;
+
+ return (seconds * 1000) + (usec / 1000);
+}
+
+int
+DG_GetKey(int* pressed, unsigned char* key)
+{
+ if (s_KeyQueueReadIndex == s_KeyQueueWriteIndex) {
+ //key queue is empty
+
+ return 0;
+ }
+ else {
+ unsigned short keyCode = s_KeyQueue[s_KeyQueueReadIndex];
+ s_KeyQueueReadIndex++;
+ s_KeyQueueReadIndex %= KEYQUEUE_SIZE;
+
+ *pressed = SNOM_KEY_PRESSED(keyCode);
+ *key = convertToDoomKey(SNOM_KEY_CODE(keyCode));
+
+ return 1;
+ }
+}
+
+void
+DG_SetWindowTitle(const char * title)
+{
+}
+
+int main(int argc, char **argv)
+{
+ int opt = getopt(argc, argv, ":c:");
+
+ if (opt == 'c') {
+ contrast = atoi(optarg);
+ }
+
+ gettimeofday(&start, NULL);
+ // invalid arguments for doom are apparently ignored, so we can just pass everythin along unmodified
+ doomgeneric_Create(argc, argv);
+
+ while(true) {
+ doomgeneric_Tick();
+ }
+
+ snom360_close();
+
+ return 0;
+}
+
#else // __DJGPP__
+#ifdef SNOM360
+
+#define SYS_BIG_ENDIAN
+
+static inline unsigned short swapLE16(unsigned short val) {
+ return ((val << 8) | (val >> 8));
+}
+
+static inline unsigned long swapLE32(unsigned long val) {
+ return ((val << 24) | ((val << 8) & 0x00FF0000) | ((val >> 8) & 0x0000FF00) | (val >> 24));
+}
+
+#define SHORT(x) ((signed short) swapLE16(x))
+#define LONG(x) ((signed int) swapLE32(x))
+
+#else // SNOM360
#if ( __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ )
#define SYS_LITTLE_ENDIAN
#define doom_wtohs(x) (short int)(x)
#endif
+#endif // SNOM360
#endif // __DJGPP__
--- /dev/null
+#include "snom360.h"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <getopt.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+
+struct inca_port_ioctl_parm {
+ int port;
+ int pin;
+ int value;
+};
+
+#define INCA_PORT_IOC_MAGIC 0xbf
+#define INCA_PORT_IOCDIR _IOW(INCA_PORT_IOC_MAGIC,4,struct inca_port_ioctl_parm)
+#define INCA_PORT_IOCOUTPUT _IOW(INCA_PORT_IOC_MAGIC,5,struct inca_port_ioctl_parm)
+#define INCA_PORT_IOCINPUT _IOWR(INCA_PORT_IOC_MAGIC,6,struct inca_port_ioctl_parm)
+#define INCA_PORT_DISPCMD _IOWR(INCA_PORT_IOC_MAGIC,7,struct inca_port_ioctl_parm)
+#define INCA_PORT_DISPDATA _IOWR(INCA_PORT_IOC_MAGIC,8,struct inca_port_ioctl_parm)
+
+static int inca_fd = -1;
+static struct inca_port_ioctl_parm parm;
+static int leds[16];
+
+int
+inca_display_write_serial(int cmd, int value)
+{
+ parm.port = 2;
+ parm.pin = 0;
+ parm.value = value;
+
+ int ret;
+
+ if (cmd)
+ ret = ioctl(inca_fd, INCA_PORT_DISPCMD, &parm);
+ else
+ ret = ioctl(inca_fd, INCA_PORT_DISPDATA, &parm);
+
+ for (int i = 0; i < 1000; ++i)
+ __asm("nop");
+
+ return ret;
+}
+
+int
+inca_port_dir(int port, int pin, int value)
+{
+ parm.port = port;
+ parm.pin = pin;
+ parm.value = value;
+
+ return ioctl(inca_fd, INCA_PORT_IOCDIR, &parm);
+}
+
+int
+inca_port_write(int port, int pin, int value)
+{
+ parm.port = port;
+ parm.pin = pin;
+ parm.value = value;
+
+ return ioctl(inca_fd, INCA_PORT_IOCOUTPUT, &parm);
+}
+
+int
+inca_port_read(int port, int pin)
+{
+ parm.port = port;
+ parm.pin = pin;
+ parm.value = 0;
+ int res = ioctl(inca_fd, INCA_PORT_IOCINPUT, &parm);
+
+ if (res == 0)
+ return parm.value;
+ else
+ return -1;
+}
+
+int
+inca_port_read_wait(int port, int pin, int value)
+{
+ for (int i = 0; i < 5000; ++i) {
+ if (inca_port_read(2, 0xb) == value)
+ return 1;
+ }
+ return 0;
+}
+
+int
+inca_port_write_bit(int bit)
+{
+ inca_port_dir(2, 10, 1);
+
+ if (bit) inca_port_write(2, 10, 1);
+ else inca_port_write(2, 10, 0);
+
+ inca_port_write(2, 6, 0);
+ if (inca_port_read_wait(2, 0xb, 0) == 0) goto finish;
+ inca_port_dir(2, 10, 0);
+ inca_port_write(2, 6, 1);
+ if (inca_port_read_wait(2, 0xb, 1) != 0) return 1;
+
+finish:
+ inca_port_dir(2, 10, 0);
+ return 0;
+}
+
+void
+inca_port_setup()
+{
+ inca_port_dir(2, 7, 1);
+ inca_port_dir(2, 6, 1);
+ inca_port_dir(2, 0xb, 0);
+ inca_port_dir(2, 10, 0);
+ inca_port_write(2, 6, 1);
+ inca_port_write(2, 7, 0);
+}
+
+void
+inca_port_finish()
+{
+ inca_port_write(2, 6, 1);
+ inca_port_write(2, 7, 1);
+ inca_port_dir(2, 0xb, 1);
+ inca_port_dir(2, 10, 1);
+}
+
+void
+snom360_display_setup()
+{
+ inca_display_write_serial(1, 0xae);
+ inca_display_write_serial(1, 0xa0);
+ inca_display_write_serial(1, 0xc0);
+ inca_display_write_serial(1, 0x23);
+ inca_display_write_serial(1, 0x81);
+ inca_display_write_serial(1, 0x30);
+ inca_display_write_serial(1, 0xa3);
+ inca_display_write_serial(1, 0x2f);
+ inca_display_write_serial(1, 0xaf);
+ inca_display_write_serial(1, 0xa2);
+}
+
+void
+snom360_display_draw(unsigned char *buf)
+{
+ for (int i = DISPLAY_ROWS - 1; i >= 0; --i) {
+ inca_display_write_serial(1, i | 0xb0);
+ inca_display_write_serial(1, 0);
+ inca_display_write_serial(1, 0x10);
+
+ for (int j = 0; j < DISPLAY_COLS; ++j)
+ inca_display_write_serial(0, buf[i*DISPLAY_COLS + j]);
+ }
+}
+
+void
+snom360_leds_write()
+{
+ inca_port_setup();
+ if (inca_port_write_bit(0) == 0) {
+ goto finish;
+ }
+
+ for (int i = 0; i < 16; ++i) {
+ if (inca_port_write_bit(leds[i]) == 0)
+ goto finish;
+ }
+
+finish:
+ inca_port_finish();
+}
+
+void
+snom360_set_led(SnomLed led, int value)
+{
+ leds[led] = (value != 0);
+ snom360_leds_write();
+}
+
+int
+snom360_keyboard_poll(int *res)
+{
+ inca_port_write(2, 6, 0);
+ if (inca_port_read_wait(2, 0xb, 0) == 0)
+ return 0;
+ *res = inca_port_read(2, 10);
+ inca_port_write(2, 6, 1);
+ if (inca_port_read_wait(2, 0xb, 1) == 0)
+ return 0;
+ return 1;
+}
+
+int
+snom360_keyboard_read()
+{
+ inca_port_setup();
+
+ if (inca_port_write_bit(1) == 0)
+ goto finish;
+
+ int res = 0, code = -1;
+ if (snom360_keyboard_poll(&res) == 0 || res == 0) goto finish;
+
+ code = 0;
+ for (int i = 0; i < 8; ++i) {
+ if (snom360_keyboard_poll(&res) == 0) goto finish;
+ code = code << 1;
+ if (res)
+ code |= 1;
+ }
+
+finish:
+ inca_port_finish();
+ return code;
+}
+
+void
+snom360_setup()
+{
+ if (inca_fd != -1) {
+ fprintf(stderr, "INCA Port already opened!");
+ exit(EXIT_FAILURE);
+ }
+
+ if ((inca_fd = open("/dev/inca-port", O_RDWR)) < 0) {
+ fprintf(stderr, "Couldn't open /dev/inca-port: %s.\n", strerror(errno));
+ exit(1);
+ }
+
+ parm.port = 2;
+ parm.pin = 0;
+ parm.value = 0;
+
+ leds[SNOM_LED_BACKLIGHT] = 0;
+ memset(&leds[1], 1, sizeof(int) * 15);
+ snom360_leds_write();
+ snom360_display_setup();
+}
+
+void
+snom360_close()
+{
+ close(inca_fd);
+}
--- /dev/null
+#pragma once
+
+#define DISPLAY_COLS 132
+#define DISPLAY_ROWS 8
+#define DISPLAY_SIZE (DISPLAY_COLS * DISPLAY_ROWS)
+
+typedef enum {
+ SNOM_KEY_HASH = 35,
+ SNOM_KEY_STAR = 42,
+ SNOM_KEY_ZERO = 48,
+ SNOM_KEY_ONE = 49,
+ SNOM_KEY_TWO = 50,
+ SNOM_KEY_THREE = 51,
+ SNOM_KEY_FOUR = 52,
+ SNOM_KEY_FIVE = 53,
+ SNOM_KEY_SIX = 54,
+ SNOM_KEY_SEVEN = 55,
+ SNOM_KEY_EIGHT = 56,
+ SNOM_KEY_NINE = 57,
+ SNOM_KEY_TRANSFER = 65,
+ SNOM_KEY_HOLD = 66,
+ SNOM_KEY_DND = 67,
+ SNOM_KEY_DIAL_ONE = 74,
+ SNOM_KEY_DIAL_TWO = 68,
+ SNOM_KEY_DIAL_THREE = 75,
+ SNOM_KEY_DIAL_FOUR = 69,
+ SNOM_KEY_DIAL_FIVE = 76,
+ SNOM_KEY_DIAL_SIX = 70,
+ SNOM_KEY_DIAL_SEVEN = 77,
+ SNOM_KEY_DIAL_EIGHT = 71,
+ SNOM_KEY_DIAL_NINE = 78,
+ SNOM_KEY_DIAL_TEN = 72,
+ SNOM_KEY_DIAL_ELEVEN = 79,
+ SNOM_KEY_DIAL_TWELVE = 73,
+ SNOM_KEY_QUICK_ONE = 97,
+ SNOM_KEY_QUICK_TWO = 98,
+ SNOM_KEY_QUICK_THREE = 99,
+ SNOM_KEY_QUICK_FOUR = 100,
+ SNOM_KEY_VOL_DOWN = 101,
+ SNOM_KEY_VOL_UP = 102,
+ SNOM_KEY_CANCEL = 103,
+ SNOM_KEY_ACCEPT = 104,
+ SNOM_KEY_LEFT = 105,
+ SNOM_KEY_RIGHT = 106,
+ SNOM_KEY_UP = 107,
+ SNOM_KEY_DOWN = 108,
+ SNOM_KEY_RECORD = 109,
+ SNOM_KEY_RETRIEVE = 110,
+ SNOM_KEY_MUTE = 111,
+ SNOM_KEY_SPEAKER = 112,
+ SNOM_KEY_HEADSET = 113,
+ SNOM_KEY_REDIAL = 114,
+ SNOM_KEY_SETTINGS = 115,
+ SNOM_KEY_DIRECTORY = 116,
+ SNOM_KEY_HELP = 117,
+ SNOM_KEY_MENU = 118,
+ SNOM_KEY_SNOM = 119,
+ SNOM_KEY_CONFERENCE = 120,
+} SnomKey;
+
+typedef enum {
+ SNOM_LED_BACKLIGHT = 0,
+ SNOM_LED_MESSAGE = 6,
+ SNOM_LED_ONE = 13,
+ SNOM_LED_TWO = 15,
+ SNOM_LED_THREE = 9,
+ SNOM_LED_FOUR = 11,
+ SNOM_LED_FIVE = 5,
+ SNOM_LED_SIX = 7,
+ SNOM_LED_SEVEN = 1,
+ SNOM_LED_EIGHT = 4,
+ SNOM_LED_NINE = 12,
+ SNOM_LED_TEN = 14,
+ SNOM_LED_ELEVEN = 8,
+ SNOM_LED_TWELVE = 10
+} SnomLed;
+
+#define SNOM_KEY_PRESSED(x) (x & 0x80)
+#define SNOM_KEY_RELEASED(x) !(x & 0x80)
+#define SNOM_KEY_CODE(x) (x & 0x7f)
+
+void snom360_setup();
+void snom360_close();
+
+void snom360_display_draw(unsigned char *buf);
+void snom360_set_led(SnomLed led, int value);
+int snom360_keyboard_read();