]> git.0x19.co - doomgeneric-snom360/commitdiff
port: snom360 master
author0x19 <hex25@0x19.co>
Sun, 22 Feb 2026 18:17:43 +0000 (19:17 +0100)
committer0x19 <25@0x19.co>
Mon, 13 Jul 2026 18:43:17 +0000 (20:43 +0200)
Add snom360 port, including some small fixes for the endianness check,
as well as the platform driver.

doomgeneric/Makefile.snom360 [new file with mode: 0644]
doomgeneric/doomgeneric_snom360.c [new file with mode: 0644]
doomgeneric/i_swap.h
doomgeneric/snom360.c [new file with mode: 0644]
doomgeneric/snom360.h [new file with mode: 0644]

diff --git a/doomgeneric/Makefile.snom360 b/doomgeneric/Makefile.snom360
new file mode 100644 (file)
index 0000000..7dc3b50
--- /dev/null
@@ -0,0 +1,58 @@
+################################################################
+#
+# $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)
diff --git a/doomgeneric/doomgeneric_snom360.c b/doomgeneric/doomgeneric_snom360.c
new file mode 100644 (file)
index 0000000..5d962ee
--- /dev/null
@@ -0,0 +1,199 @@
+#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;
+}
+
index fa45d4c91102ae13c0c4c1b73aa4951f493379c6..405ce6e9ec09660ed65cad6dbb2f4fce59aeafae 100644 (file)
 
 #else  // __DJGPP__
 
 
 #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
 
 #if ( __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ )
 #define SYS_LITTLE_ENDIAN
@@ -65,6 +81,7 @@ static inline unsigned long swapLE32(unsigned long val) {
 #define doom_wtohs(x) (short int)(x)
 #endif
 
 #define doom_wtohs(x) (short int)(x)
 #endif
 
+#endif  // SNOM360
 
 #endif  // __DJGPP__
 
 
 #endif  // __DJGPP__
 
diff --git a/doomgeneric/snom360.c b/doomgeneric/snom360.c
new file mode 100644 (file)
index 0000000..601d9ba
--- /dev/null
@@ -0,0 +1,249 @@
+#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);
+}
diff --git a/doomgeneric/snom360.h b/doomgeneric/snom360.h
new file mode 100644 (file)
index 0000000..c93ce80
--- /dev/null
@@ -0,0 +1,87 @@
+#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();