commit 8ee9b6f53a75c3b79409347d2a584363590f7728
parent 65dcc262b854e3dad76cfcce9d8a9c041b43f888
Author: noone <vazkats@gmail.com>
Date: Sat, 11 Oct 2025 19:45:41 +0300
Tidying up. Fixed compiler warnings. Following ansi c philosophy.
Still compiling with c99 though.
Gonna see if integrating lua will help me through my debugging journey
Diffstat:
22 files changed, 1132 insertions(+), 1458 deletions(-)
diff --git a/lib/include/MiniFB.h b/lib/include/MiniFB.h
@@ -1,107 +0,0 @@
-#ifndef _MINIFB_H_
-#define _MINIFB_H_
-
-#include "MiniFB_enums.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-#ifndef __ANDROID__
-#define MFB_RGB(r, g, b) (((uint32_t) r) << 16) | (((uint32_t) g) << 8) | ((uint32_t) b)
-#define MFB_ARGB(a, r, g, b) (((uint32_t) a) << 24) | (((uint32_t) r) << 16) | (((uint32_t) g) << 8) | ((uint32_t) b)
-#else
- #ifdef HOST_WORDS_BIGENDIAN
- #define MFB_RGB(r, g, b) (((uint32_t) r) << 16) | (((uint32_t) g) << 8) | ((uint32_t) b)
- #define MFB_ARGB(a, r, g, b) (((uint32_t) a) << 24) | (((uint32_t) r) << 16) | (((uint32_t) g) << 8) | ((uint32_t) b)
- #else
- #define MFB_ARGB(r, g, b) (((uint32_t) a) << 24) | (((uint32_t) b) << 16) | (((uint32_t) g) << 8) | ((uint32_t) r)
- #define MFB_RGB(r, g, b) (((uint32_t) b) << 16) | (((uint32_t) g) << 8) | ((uint32_t) r)
- #endif
-#endif
-
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-// Create a window that is used to display the buffer sent into the mfb_update function, returns 0 if fails
-struct mfb_window * mfb_open(const char *title, unsigned width, unsigned height);
-struct mfb_window * mfb_open_ex(const char *title, unsigned width, unsigned height, unsigned flags);
-
-// Update the display
-// Input buffer is assumed to be a 32-bit buffer of the size given in the open call
-// Will return a negative status if something went wrong or the user want to exit
-// Also updates the window events
-mfb_update_state mfb_update(struct mfb_window *window, void *buffer);
-
-mfb_update_state mfb_update_ex(struct mfb_window *window, void *buffer, unsigned width, unsigned height);
-
-// Only updates the window events
-mfb_update_state mfb_update_events(struct mfb_window *window);
-
-// Close the window
-void mfb_close(struct mfb_window *window);
-
-// Set user data
-void mfb_set_user_data(struct mfb_window *window, void *user_data);
-void * mfb_get_user_data(struct mfb_window *window);
-
-// Set viewport (useful when resize)
-bool mfb_set_viewport(struct mfb_window *window, unsigned offset_x, unsigned offset_y, unsigned width, unsigned height);
-// Let mfb to calculate the best fit from your framebuffer original size
-bool mfb_set_viewport_best_fit(struct mfb_window *window, unsigned old_width, unsigned old_height);
-
-// DPI
-// [Deprecated]: Probably a better name will be mfb_get_monitor_scale
-void mfb_get_monitor_dpi(struct mfb_window *window, float *dpi_x, float *dpi_y);
-// Use this instead
-void mfb_get_monitor_scale(struct mfb_window *window, float *scale_x, float *scale_y);
-
-// Callbacks
-void mfb_set_active_callback(struct mfb_window *window, mfb_active_func callback);
-void mfb_set_resize_callback(struct mfb_window *window, mfb_resize_func callback);
-void mfb_set_close_callback(struct mfb_window* window, mfb_close_func callback);
-void mfb_set_keyboard_callback(struct mfb_window *window, mfb_keyboard_func callback);
-void mfb_set_char_input_callback(struct mfb_window *window, mfb_char_input_func callback);
-void mfb_set_mouse_button_callback(struct mfb_window *window, mfb_mouse_button_func callback);
-void mfb_set_mouse_move_callback(struct mfb_window *window, mfb_mouse_move_func callback);
-void mfb_set_mouse_scroll_callback(struct mfb_window *window, mfb_mouse_scroll_func callback);
-
-// Getters
-const char * mfb_get_key_name(mfb_key key);
-
-bool mfb_is_window_active(struct mfb_window *window);
-unsigned mfb_get_window_width(struct mfb_window *window);
-unsigned mfb_get_window_height(struct mfb_window *window);
-int mfb_get_mouse_x(struct mfb_window *window); // Last mouse pos X
-int mfb_get_mouse_y(struct mfb_window *window); // Last mouse pos Y
-float mfb_get_mouse_scroll_x(struct mfb_window *window); // Mouse wheel X as a sum. When you call this function it resets.
-float mfb_get_mouse_scroll_y(struct mfb_window *window); // Mouse wheel Y as a sum. When you call this function it resets.
-const uint8_t * mfb_get_mouse_button_buffer(struct mfb_window *window); // One byte for every button. Press (1), Release 0. (up to 8 buttons)
-const uint8_t * mfb_get_key_buffer(struct mfb_window *window); // One byte for every key. Press (1), Release 0.
-
-// FPS
-void mfb_set_target_fps(uint32_t fps);
-unsigned mfb_get_target_fps(void);
-bool mfb_wait_sync(struct mfb_window *window);
-
-// Timer
-struct mfb_timer * mfb_timer_create(void);
-void mfb_timer_destroy(struct mfb_timer *tmr);
-void mfb_timer_reset(struct mfb_timer *tmr);
-double mfb_timer_now(struct mfb_timer *tmr);
-double mfb_timer_delta(struct mfb_timer *tmr);
-double mfb_timer_get_frequency(void);
-double mfb_timer_get_resolution(void);
-
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-#ifdef __cplusplus
-}
-
-#if !defined(MINIFB_AVOID_CPP_HEADERS)
- #include "MiniFB_cpp.h"
-#endif
-
-#endif
-
-#endif
diff --git a/lib/include/MiniFB_cpp.h b/lib/include/MiniFB_cpp.h
@@ -1,186 +0,0 @@
-#pragma once
-
-#if defined(__cplusplus)
-
-#include <functional>
-#include "MiniFB.h"
-
-//-------------------------------------
-// To be able to distinguish these C++ functions, using std::function, from C functions, using raw function pointers, we need to reverse params order.
-//
-// Note that FROM the compiler point of view
-// mfb_set_XXX_callback(window, &my_c_func)
-// and
-// mfb_set_XXX_callback(window, [](...) {})
-// have the same parameters.
-//-------------------------------------
-void mfb_set_active_callback (std::function<void(struct mfb_window *, bool)> func, struct mfb_window *window);
-void mfb_set_resize_callback (std::function<void(struct mfb_window *, int, int)> func, struct mfb_window *window);
-void mfb_set_close_callback (std::function<bool(struct mfb_window *)> func, struct mfb_window *window);
-void mfb_set_keyboard_callback (std::function<void(struct mfb_window *, mfb_key, mfb_key_mod, bool)> func, struct mfb_window *window);
-void mfb_set_char_input_callback (std::function<void(struct mfb_window *, unsigned int)> func, struct mfb_window *window);
-void mfb_set_mouse_button_callback(std::function<void(struct mfb_window *, mfb_mouse_button, mfb_key_mod, bool)> func, struct mfb_window *window);
-void mfb_set_mouse_move_callback (std::function<void(struct mfb_window *, int, int)> func, struct mfb_window *window);
-void mfb_set_mouse_scroll_callback(std::function<void(struct mfb_window *, mfb_key_mod, float, float)> func, struct mfb_window *window);
-//-------------------------------------
-
-//-------------------------------------
-template <class T>
-void mfb_set_active_callback(struct mfb_window *window, T *obj, void (T::*method)(struct mfb_window *, bool));
-
-template <class T>
-void mfb_set_resize_callback(struct mfb_window *window, T *obj, void (T::*method)(struct mfb_window *, int, int));
-
-template <class T>
-void mfb_set_keyboard_callback(struct mfb_window *window, T *obj, void (T::*method)(struct mfb_window *, mfb_key, mfb_key_mod, bool));
-
-template <class T>
-void mfb_set_char_input_callback(struct mfb_window *window, T *obj, void (T::*method)(struct mfb_window *, unsigned int));
-
-template <class T>
-void mfb_set_mouse_button_callback(struct mfb_window *window, T *obj, void (T::*method)(struct mfb_window *, mfb_mouse_button, mfb_key_mod, bool));
-
-template <class T>
-void mfb_set_mouse_move_callback(struct mfb_window *window, T *obj, void (T::*method)(struct mfb_window *, int, int));
-
-template <class T>
-void mfb_set_mouse_scroll_callback(struct mfb_window *window, T *obj, void (T::*method)(struct mfb_window *, mfb_key_mod, float, float));
-//-------------------------------------
-
-//-------------------------------------
-// To avoid clumsy hands
-//-------------------------------------
-class mfb_stub {
- mfb_stub() : m_window(0x0) {}
-
- friend void mfb_set_active_callback (std::function<void(struct mfb_window *window, bool)> func, struct mfb_window *window);
- friend void mfb_set_resize_callback (std::function<void(struct mfb_window *, int, int)> func, struct mfb_window *window);
- friend void mfb_set_close_callback (std::function<bool(struct mfb_window *)> func, struct mfb_window *window);
- friend void mfb_set_keyboard_callback (std::function<void(struct mfb_window *, mfb_key, mfb_key_mod, bool)> func, struct mfb_window *window);
- friend void mfb_set_char_input_callback (std::function<void(struct mfb_window *, unsigned int)> func, struct mfb_window *window);
- friend void mfb_set_mouse_button_callback(std::function<void(struct mfb_window *, mfb_mouse_button, mfb_key_mod, bool)> func, struct mfb_window *window);
- friend void mfb_set_mouse_move_callback (std::function<void(struct mfb_window *, int, int)> func, struct mfb_window *window);
- friend void mfb_set_mouse_scroll_callback(std::function<void(struct mfb_window *, mfb_key_mod, float, float)> func, struct mfb_window *window);
-
- template <class T>
- friend void mfb_set_active_callback(struct mfb_window *window, T *obj, void (T::*method)(struct mfb_window *, bool));
- template <class T>
- friend void mfb_set_resize_callback(struct mfb_window *window, T *obj, void (T::*method)(struct mfb_window *, int, int));
- template <class T>
- friend void mfb_set_close_callback(struct mfb_window *window, T *obj, bool (T::*method)(struct mfb_window *));
- template <class T>
- friend void mfb_set_mouse_button_callback(struct mfb_window *window, T *obj, void (T::*method)(struct mfb_window *, mfb_mouse_button, mfb_key_mod, bool));
- template <class T>
- friend void mfb_set_keyboard_callback(struct mfb_window *window, T *obj, void (T::*method)(struct mfb_window *, mfb_key, mfb_key_mod, bool));
- template <class T>
- friend void mfb_set_char_input_callback(struct mfb_window *window, T *obj, void (T::*method)(struct mfb_window *, unsigned int));
- template <class T>
- friend void mfb_set_mouse_button_callback(struct mfb_window *window, T *obj, void (T::*method)(struct mfb_window *, mfb_mouse_button, mfb_key_mod, bool));
- template <class T>
- friend void mfb_set_mouse_move_callback(struct mfb_window *window, T *obj, void (T::*method)(struct mfb_window *, int, int));
- template <class T>
- friend void mfb_set_mouse_scroll_callback(struct mfb_window *window, T *obj, void (T::*method)(struct mfb_window *, mfb_key_mod, float, float));
-
- static mfb_stub *GetInstance(struct mfb_window *window);
-
- static void active_stub(struct mfb_window *window, bool isActive);
- static void resize_stub(struct mfb_window *window, int width, int height);
- static bool close_stub(struct mfb_window *window);
- static void keyboard_stub(struct mfb_window *window, mfb_key key, mfb_key_mod mod, bool isPressed);
- static void char_input_stub(struct mfb_window *window, unsigned int);
- static void mouse_btn_stub(struct mfb_window *window, mfb_mouse_button button, mfb_key_mod mod, bool isPressed);
- static void mouse_move_stub(struct mfb_window *window, int x, int y);
- static void scroll_stub(struct mfb_window *window, mfb_key_mod mod, float deltaX, float deltaY);
-
- struct mfb_window *m_window;
- std::function<void(struct mfb_window *window, bool)> m_active;
- std::function<void(struct mfb_window *window, int, int)> m_resize;
- std::function<bool(struct mfb_window *window)> m_close;
- std::function<void(struct mfb_window *window, mfb_key, mfb_key_mod, bool)> m_keyboard;
- std::function<void(struct mfb_window *window, unsigned int)> m_char_input;
- std::function<void(struct mfb_window *window, mfb_mouse_button, mfb_key_mod, bool)> m_mouse_btn;
- std::function<void(struct mfb_window *window, int, int)> m_mouse_move;
- std::function<void(struct mfb_window *window, mfb_key_mod, float, float)> m_scroll;
-};
-
-//-------------------------------------
-template <class T>
-inline void mfb_set_active_callback(struct mfb_window *window, T *obj, void (T::*method)(struct mfb_window *window, bool)) {
- using namespace std::placeholders;
-
- mfb_stub *stub = mfb_stub::GetInstance(window);
- stub->m_active = std::bind(method, obj, _1, _2);
- mfb_set_active_callback(window, mfb_stub::active_stub);
-}
-
-//-------------------------------------
-template <class T>
-inline void mfb_set_resize_callback(struct mfb_window *window, T *obj, void (T::*method)(struct mfb_window *window, int, int)) {
- using namespace std::placeholders;
-
- mfb_stub *stub = mfb_stub::GetInstance(window);
- stub->m_resize = std::bind(method, obj, _1, _2, _3);
- mfb_set_resize_callback(window, mfb_stub::resize_stub);
-}
-
-//-------------------------------------
-template <class T>
-inline void mfb_set_close_callback(struct mfb_window *window, T *obj, bool (T::*method)(struct mfb_window *window)) {
- using namespace std::placeholders;
-
- mfb_stub *stub = mfb_stub::GetInstance(window);
- stub->m_close = std::bind(method, obj, _1);
- mfb_set_close_callback(window, mfb_stub::close_stub);
-}
-
-//-------------------------------------
-template <class T>
-inline void mfb_set_keyboard_callback(struct mfb_window *window, T *obj, void (T::*method)(struct mfb_window *window, mfb_key, mfb_key_mod, bool)) {
- using namespace std::placeholders;
-
- mfb_stub *stub = mfb_stub::GetInstance(window);
- stub->m_keyboard = std::bind(method, obj, _1, _2, _3, _4);
- mfb_set_keyboard_callback(window, mfb_stub::keyboard_stub);
-}
-
-//-------------------------------------
-template <class T>
-inline void mfb_set_char_input_callback(struct mfb_window *window, T *obj, void (T::*method)(struct mfb_window *window, unsigned int)) {
- using namespace std::placeholders;
-
- mfb_stub *stub = mfb_stub::GetInstance(window);
- stub->m_char_input = std::bind(method, obj, _1, _2);
- mfb_set_char_input_callback(window, mfb_stub::char_input_stub);
-}
-
-//-------------------------------------
-template <class T>
-inline void mfb_set_mouse_button_callback(struct mfb_window *window, T *obj, void (T::*method)(struct mfb_window *window, mfb_mouse_button, mfb_key_mod, bool)) {
- using namespace std::placeholders;
-
- mfb_stub *stub = mfb_stub::GetInstance(window);
- stub->m_mouse_btn = std::bind(method, obj, _1, _2, _3, _4);
- mfb_set_mouse_button_callback(window, mfb_stub::mouse_btn_stub);
-}
-
-//-------------------------------------
-template <class T>
-inline void mfb_set_mouse_move_callback(struct mfb_window *window, T *obj, void (T::*method)(struct mfb_window *window, int, int)) {
- using namespace std::placeholders;
-
- mfb_stub *stub = mfb_stub::GetInstance(window);
- stub->m_mouse_move = std::bind(method, obj, _1, _2, _3);
- mfb_set_mouse_move_callback(window, mfb_stub::mouse_move_stub);
-}
-
-//-------------------------------------
-template <class T>
-inline void mfb_set_mouse_scroll_callback(struct mfb_window *window, T *obj, void (T::*method)(struct mfb_window *window, mfb_key_mod, float, float)) {
- using namespace std::placeholders;
-
- mfb_stub *stub = mfb_stub::GetInstance(window);
- stub->m_scroll = std::bind(method, obj, _1, _2, _3, _4);
- mfb_set_mouse_scroll_callback(window, mfb_stub::scroll_stub);
-}
-
-#endif
diff --git a/lib/include/MiniFB_enums.h b/lib/include/MiniFB_enums.h
@@ -1,186 +0,0 @@
-#pragma once
-
-#include <stdint.h>
-#include <stdbool.h>
-
-// Enums
-typedef enum {
- STATE_OK = 0,
- STATE_EXIT = -1,
- STATE_INVALID_WINDOW = -2,
- STATE_INVALID_BUFFER = -3,
- STATE_INTERNAL_ERROR = -4,
-} mfb_update_state;
-
-typedef enum {
- MOUSE_BTN_0, // No mouse button
- MOUSE_BTN_1,
- MOUSE_BTN_2,
- MOUSE_BTN_3,
- MOUSE_BTN_4,
- MOUSE_BTN_5,
- MOUSE_BTN_6,
- MOUSE_BTN_7,
-} mfb_mouse_button;
-#define MOUSE_LEFT MOUSE_BTN_1
-#define MOUSE_RIGHT MOUSE_BTN_2
-#define MOUSE_MIDDLE MOUSE_BTN_3
-
-typedef enum {
- KB_KEY_UNKNOWN = -1,
-
- KB_KEY_SPACE = 32,
- KB_KEY_APOSTROPHE = 39,
- KB_KEY_COMMA = 44,
- KB_KEY_MINUS = 45,
- KB_KEY_PERIOD = 46,
- KB_KEY_SLASH = 47,
- KB_KEY_0 = 48,
- KB_KEY_1 = 49,
- KB_KEY_2 = 50,
- KB_KEY_3 = 51,
- KB_KEY_4 = 52,
- KB_KEY_5 = 53,
- KB_KEY_6 = 54,
- KB_KEY_7 = 55,
- KB_KEY_8 = 56,
- KB_KEY_9 = 57,
- KB_KEY_SEMICOLON = 59,
- KB_KEY_EQUAL = 61,
- KB_KEY_A = 65,
- KB_KEY_B = 66,
- KB_KEY_C = 67,
- KB_KEY_D = 68,
- KB_KEY_E = 69,
- KB_KEY_F = 70,
- KB_KEY_G = 71,
- KB_KEY_H = 72,
- KB_KEY_I = 73,
- KB_KEY_J = 74,
- KB_KEY_K = 75,
- KB_KEY_L = 76,
- KB_KEY_M = 77,
- KB_KEY_N = 78,
- KB_KEY_O = 79,
- KB_KEY_P = 80,
- KB_KEY_Q = 81,
- KB_KEY_R = 82,
- KB_KEY_S = 83,
- KB_KEY_T = 84,
- KB_KEY_U = 85,
- KB_KEY_V = 86,
- KB_KEY_W = 87,
- KB_KEY_X = 88,
- KB_KEY_Y = 89,
- KB_KEY_Z = 90,
- KB_KEY_LEFT_BRACKET = 91,
- KB_KEY_BACKSLASH = 92,
- KB_KEY_RIGHT_BRACKET = 93,
- KB_KEY_GRAVE_ACCENT = 96,
- KB_KEY_WORLD_1 = 161,
- KB_KEY_WORLD_2 = 162,
-
- KB_KEY_ESCAPE = 256,
- KB_KEY_ENTER = 257,
- KB_KEY_TAB = 258,
- KB_KEY_BACKSPACE = 259,
- KB_KEY_INSERT = 260,
- KB_KEY_DELETE = 261,
- KB_KEY_RIGHT = 262,
- KB_KEY_LEFT = 263,
- KB_KEY_DOWN = 264,
- KB_KEY_UP = 265,
- KB_KEY_PAGE_UP = 266,
- KB_KEY_PAGE_DOWN = 267,
- KB_KEY_HOME = 268,
- KB_KEY_END = 269,
- KB_KEY_CAPS_LOCK = 280,
- KB_KEY_SCROLL_LOCK = 281,
- KB_KEY_NUM_LOCK = 282,
- KB_KEY_PRINT_SCREEN = 283,
- KB_KEY_PAUSE = 284,
- KB_KEY_F1 = 290,
- KB_KEY_F2 = 291,
- KB_KEY_F3 = 292,
- KB_KEY_F4 = 293,
- KB_KEY_F5 = 294,
- KB_KEY_F6 = 295,
- KB_KEY_F7 = 296,
- KB_KEY_F8 = 297,
- KB_KEY_F9 = 298,
- KB_KEY_F10 = 299,
- KB_KEY_F11 = 300,
- KB_KEY_F12 = 301,
- KB_KEY_F13 = 302,
- KB_KEY_F14 = 303,
- KB_KEY_F15 = 304,
- KB_KEY_F16 = 305,
- KB_KEY_F17 = 306,
- KB_KEY_F18 = 307,
- KB_KEY_F19 = 308,
- KB_KEY_F20 = 309,
- KB_KEY_F21 = 310,
- KB_KEY_F22 = 311,
- KB_KEY_F23 = 312,
- KB_KEY_F24 = 313,
- KB_KEY_F25 = 314,
- KB_KEY_KP_0 = 320,
- KB_KEY_KP_1 = 321,
- KB_KEY_KP_2 = 322,
- KB_KEY_KP_3 = 323,
- KB_KEY_KP_4 = 324,
- KB_KEY_KP_5 = 325,
- KB_KEY_KP_6 = 326,
- KB_KEY_KP_7 = 327,
- KB_KEY_KP_8 = 328,
- KB_KEY_KP_9 = 329,
- KB_KEY_KP_DECIMAL = 330,
- KB_KEY_KP_DIVIDE = 331,
- KB_KEY_KP_MULTIPLY = 332,
- KB_KEY_KP_SUBTRACT = 333,
- KB_KEY_KP_ADD = 334,
- KB_KEY_KP_ENTER = 335,
- KB_KEY_KP_EQUAL = 336,
- KB_KEY_LEFT_SHIFT = 340,
- KB_KEY_LEFT_CONTROL = 341,
- KB_KEY_LEFT_ALT = 342,
- KB_KEY_LEFT_SUPER = 343,
- KB_KEY_RIGHT_SHIFT = 344,
- KB_KEY_RIGHT_CONTROL = 345,
- KB_KEY_RIGHT_ALT = 346,
- KB_KEY_RIGHT_SUPER = 347,
- KB_KEY_MENU = 348
-} mfb_key;
-#define KB_KEY_LAST KB_KEY_MENU
-
-typedef enum {
- KB_MOD_SHIFT = 0x0001,
- KB_MOD_CONTROL = 0x0002,
- KB_MOD_ALT = 0x0004,
- KB_MOD_SUPER = 0x0008,
- KB_MOD_CAPS_LOCK = 0x0010,
- KB_MOD_NUM_LOCK = 0x0020
-} mfb_key_mod;
-
-typedef enum {
- WF_RESIZABLE = 0x01,
- WF_FULLSCREEN = 0x02,
- WF_FULLSCREEN_DESKTOP = 0x04,
- WF_BORDERLESS = 0x08,
- WF_ALWAYS_ON_TOP = 0x10,
-} mfb_window_flags;
-
-// Opaque pointer
-struct mfb_window;
-struct mfb_timer;
-
-// Event callbacks
-typedef void(*mfb_active_func)(struct mfb_window *window, bool isActive);
-typedef void(*mfb_resize_func)(struct mfb_window *window, int width, int height);
-typedef bool(*mfb_close_func)(struct mfb_window* window);
-typedef void(*mfb_keyboard_func)(struct mfb_window *window, mfb_key key, mfb_key_mod mod, bool isPressed);
-typedef void(*mfb_char_input_func)(struct mfb_window *window, unsigned int code);
-typedef void(*mfb_mouse_button_func)(struct mfb_window *window, mfb_mouse_button button, mfb_key_mod mod, bool isPressed);
-typedef void(*mfb_mouse_move_func)(struct mfb_window *window, int x, int y);
-typedef void(*mfb_mouse_scroll_func)(struct mfb_window *window, mfb_key_mod mod, float deltaX, float deltaY);
-
diff --git a/lib/include/MiniFB_ios.h b/lib/include/MiniFB_ios.h
@@ -1,7 +0,0 @@
-#pragma once
-
-#include "MiniFB_enums.h"
-
-void user_implemented_init(struct mfb_window *window);
-
-void user_implemented_update(struct mfb_window *window);
diff --git a/lib/libminifb.a b/lib/libminifb.a
Binary files differ.
diff --git a/makefile b/makefile
@@ -1,9 +1,9 @@
# Ultimecia PSX Emulator Makefile
CC := clang
-CFLAGS := -Wall -Wpedantic -g -Ilib/include $(shell /opt/homebrew/bin/pkg-config --cflags sdl2 lua)
-LDFLAGS := $(shell /opt/homebrew/bin/pkg-config --libs sdl2 lua) -framework Cocoa -framework Metal -framework MetalKit
-LIBS := lib/libminifb.a
+CFLAGS := -std=c99 -g -Wall -Wextra -Werror -pedantic -Icommon $(shell /opt/homebrew/bin/pkg-config --cflags sdl2 lua) -DLOG_USE_COLOR
+LDFLAGS := $(shell /opt/homebrew/bin/pkg-config --libs sdl2 lua) -framework Cocoa -framework Metal -framework MetalKit -lcurses
+#LIBS := lib/libminifb.a
SRC := $(wildcard src/*.c)
OBJ := $(SRC:.c=.o)
@@ -13,7 +13,7 @@ all: $(BIN)
$(BIN): $(OBJ)
@mkdir -p bin
- $(CC) $(OBJ) -o $@ $(LDFLAGS) $(LIBS)
+ $(CC) $(OBJ) -o $@ $(LDFLAGS) #$(LIBS)
# Compile .c to .o
%.o: %.c
diff --git a/ntani.txt b/ntani.txt
@@ -1,4 +0,0 @@
-ηθελα να σου πω οτι οτι ειπα δεν ηταν αληθεια και δεν το εννουσα
-αλιμονο αν κατι τετοιο δεν το λαχταρουσα
-συγγνωμη μονο μπορω να πω και σε παρακαλω πιστεψε με μετανοω
-σε περιμενω την παρασκευη σαν τρελος να σε ειδω
diff --git a/test.cc b/playground/test.cc
diff --git a/src/cdrom.c b/src/cdrom.c
@@ -29,11 +29,12 @@ cdrom_fifo_full(fifo fifo)
return fifo.write_idx == (fifo.read_idx ^ 0x10);
}
-void
+/*void
cdrom_store8(cdrom* cd, u32 off, u8 val)
{
off &= 0x3;
-}
+
+}*/
void
cdrom_write(cdrom* cd, u32 offset, u8 val)
@@ -102,6 +103,7 @@ cdrom_exec_cmd(cdrom* cd, u8 cmd)
switch ((cdrom_cmd)cmd)
{
case CDROM_CMD_GETSTAT:
+ fprintf(stderr, "Not implemented TEST COMMAND");
cd->status = cdrom_status(cd);
break;
case CDROM_CMD_TEST:
diff --git a/src/cdrom.h b/src/cdrom.h
@@ -8,23 +8,20 @@ enum {
cdrom_sector_header_size = 4,
cdrom_mode1_header_size = 4,
cdrom_mode2_header_size = 12,
- cdrom_mode2_data_sector_size = 2336, // header + edc
- cdrom_frames_per_second = 75, // "sectors", or "timecode frames" (not "channel frames")
+ cdrom_mode2_data_sector_size = 2336,
+ cdrom_frames_per_second = 75,
cdrom_seconds_per_minute = 60,
cdrom_frames_per_minute = cdrom_frames_per_second * cdrom_seconds_per_minute,
cdrom_subchannel_bytes_per_frame = 12,
cdrom_lead_out_sector_count = 6750,
cdrom_all_subcode_size = 96,
cdrom_audio_sample_rate = 44100,
- cdrom_audio_channels = 2,
+ cdrom_audio_channels = 2
};
typedef struct {
- // Data buffer
u8 buffer[16];
- // Write pointer (4bits + carry)
u8 write_idx;
- // Read pointer (4bits + carry)
u8 read_idx;
} fifo;
@@ -33,7 +30,7 @@ typedef enum {
CDROM_CMD_GETSTAT = 0x01,
CDROM_CMD_SETLOC = 0x02,
CDROM_CMD_TEST = 0x19,
- CDROM_CMD_INIT = 0xA,
+ CDROM_CMD_INIT = 0xA
} cdrom_cmd;
#define STATUS_INDEX_MASK 0x03
diff --git a/src/cpu.c b/src/cpu.c
@@ -4,8 +4,8 @@
#include "interconnect.h"
#include "cpu.h"
#include "types.h"
-#include "defs.h"
#include "util.h"
+#include "log.h"
CPU*
new_cpu(Interconnect* inter) {
@@ -124,9 +124,7 @@ op_sw(CPU* cpu, instruction* i)
if ((cpu->sr & 0x10000) != 0)
{
-#ifndef DEBUG
- printf("ignoring store while cache is isolated!\n");
-#endif
+ log_debug("ignoring store while cache is isolated!");
return;
}
@@ -162,7 +160,7 @@ op_swl(CPU* cpu, instruction* i)
case 1: mem = (cur_mem & 0xffff0000) | (v >> 16); break;
case 2: mem = (cur_mem & 0xff000000) | (v >> 8); break;
case 3: mem = (cur_mem & 0x00000000) | (v >> 0); break;
- default: fprintf(stderr, "* STORE WORD LEFT.. WHAT ARE YOU DOING *\n"); exit(EXIT_FAILURE);
+ default: log_fatal("* STORE WORD LEFT.. WHAT ARE YOU DOING *"); exit(EXIT_FAILURE);
}
CPU_store32(cpu, addr, mem);
@@ -184,7 +182,7 @@ op_swr(CPU* cpu, instruction* i)
case 1: mem = (cur_mem & 0x000000ff) | (v << 8); break;
case 2: mem = (cur_mem & 0x0000ffff) | (v << 16); break;
case 3: mem = (cur_mem & 0x00ffffff) | (v << 24); break;
- default: fprintf(stderr, "* STORE WORD RIGHT.. WHAT ARE YOU DOING *\n"); exit(EXIT_FAILURE);
+ default: log_fatal("* STORE WORD RIGHT.. WHAT ARE YOU DOING *"); exit(EXIT_FAILURE);
}
CPU_store32(cpu, addr, mem);
@@ -197,9 +195,7 @@ op_sh(CPU* cpu, instruction* i)
if ((cpu->sr & 0x10000) != 0)
{
-#ifndef DEBUG
- printf("ignoring store while cache is isolated!\n");
-#endif
+ log_info("ignoring store while cache is isolated!");
return;
}
@@ -227,9 +223,7 @@ op_sb(CPU* cpu, instruction* i)
if ((cpu->sr & 0x10000) != 0)
{
-#ifndef DEBUG
- printf("ignoring store while cache is isolated!\n");
-#endif
+ log_info("ignoring store while cache is isolated!");
return;
}
@@ -338,7 +332,7 @@ op_mtc0(CPU* cpu, instruction* i)
case 3: case 5: case 6: case 7: case 9: case 11:
if (v != 0)
{
- fprintf(stderr, "Unhandled cop0r%d", cop_r);
+ log_fatal("Unhandled cop0r%d", cop_r);
exit(EXIT_FAILURE);
}
break;
@@ -348,12 +342,12 @@ op_mtc0(CPU* cpu, instruction* i)
case 13:
if (v != 0)
{
- fprintf(stderr, "Unhandled write to CAUSE register\n");
+ log_fatal("Unhandled write to CAUSE register");
exit(EXIT_FAILURE);
}
break;
default:
- fprintf(stderr, "Unhandled cop0 register %d\n", cop_r);
+ log_fatal("Unhandled cop0 register %d", cop_r);
exit(EXIT_FAILURE);
}
}
@@ -379,7 +373,7 @@ op_mfc0(CPU* cpu, instruction* i)
cpu->load._1 = cpu->epc;
break;
default:
- fprintf(stderr, "Unhandled read from cop0r%d\n", cop_r);
+ log_fatal("Unhandled read from cop0r%d", cop_r);
exit(EXIT_FAILURE);
}
}
@@ -391,7 +385,7 @@ op_rfe(CPU* cpu, instruction* i)
if ((i->_0 & 0x3f) != 0x10)
{
- fprintf(stderr, "Invalid cop0 instruction %08X\n", i->_0);
+ log_fatal("Invalid cop0 instruction %08X", i->_0);
exit(EXIT_FAILURE);
}
@@ -407,13 +401,14 @@ op_cop0(CPU* cpu, instruction* i)
case 0x00: op_mfc0(cpu, i); break;
case 0x04: op_mtc0(cpu, i); break;
case 0x10: op_rfe(cpu, i); break;
- default: printf("Unhandled cop0 instruction %08X\n", i->_0); exit(EXIT_FAILURE);
+ default: log_fatal("Unhandled cop0 instruction %08X", i->_0); exit(EXIT_FAILURE);
}
}
void
op_cop1(CPU* cpu, instruction* i)
{
+ (void)i;
exception(cpu, E_COPROCESSOR_ERROR);
}
@@ -421,7 +416,8 @@ op_cop1(CPU* cpu, instruction* i)
void
op_cop2(CPU* cpu, instruction* i)
{
- fprintf(stderr, "Unhandle GTE Instruction: %08X\n", i->_0);
+ (void)i;(void)cpu;
+ log_fatal("Unhandle GTE Instruction: %08X", i->_0);
exit(EXIT_FAILURE);
/* exception(cpu, E_COPROCESSOR_ERROR); */
}
@@ -429,6 +425,7 @@ op_cop2(CPU* cpu, instruction* i)
void
op_cop3(CPU* cpu, instruction* i)
{
+ (void)i;
exception(cpu, E_COPROCESSOR_ERROR);
}
@@ -536,7 +533,7 @@ op_lwl(CPU* cpu, instruction* i)
case 1: v = (cur_v & 0x0000ffff) | (aligned_word << 16); break;
case 2: v = (cur_v & 0x000000ff) | (aligned_word << 8); break;
case 3: v = (cur_v & 0x00000000) | (aligned_word << 0); break;
- default: fprintf(stderr, "* LOAD WORD LEFT.. WHAT ARE YOU DOING *\n"); exit(EXIT_FAILURE);
+ default: log_fatal("* LOAD WORD LEFT.. WHAT ARE YOU DOING *"); exit(EXIT_FAILURE);
}
cpu->load._0 = i->t;
@@ -561,7 +558,7 @@ op_lwr(CPU* cpu, instruction* i)
case 1: v = (cur_v & 0xff000000) | (aligned_word >> 8); break;
case 2: v = (cur_v & 0xffff0000) | (aligned_word >> 16); break;
case 3: v = (cur_v & 0xffffff00) | (aligned_word >> 24); break;
- default: fprintf(stderr, "* LOAD WORD RIGHT.. WHAT ARE YOU DOING *\n"); exit(EXIT_FAILURE);
+ default: log_fatal("* LOAD WORD RIGHT.. WHAT ARE YOU DOING *"); exit(EXIT_FAILURE);
}
cpu->load._0 = i->t;
@@ -856,29 +853,32 @@ op_mthi(CPU* cpu, instruction* i)
void op_syscall(CPU* cpu, instruction* i)
{
+ (void)i;
exception(cpu, E_SYSCALL);
}
void
op_break(CPU* cpu, instruction* i)
{
+ (void)i;
exception(cpu, E_BREAK);
}
-void op_lwc0(CPU* cpu, instruction* i) { exception(cpu, E_COPROCESSOR_ERROR); }
-void op_lwc1(CPU* cpu, instruction* i) { exception(cpu, E_COPROCESSOR_ERROR); }
-void op_lwc2(CPU* cpu, instruction* i) { fprintf(stderr, "Unhandled GTE LWC: %08X\n", i->_0); exit(EXIT_FAILURE); }
-void op_lwc3(CPU* cpu, instruction* i) { exception(cpu, E_COPROCESSOR_ERROR); }
+void op_lwc0(CPU* cpu, instruction* i) { (void)i; exception(cpu, E_COPROCESSOR_ERROR); }
+void op_lwc1(CPU* cpu, instruction* i) { (void)i; exception(cpu, E_COPROCESSOR_ERROR); }
+void op_lwc2(CPU* cpu, instruction* i) { (void)i; (void)cpu; log_fatal("Unhandled GTE LWC: %08X", i->_0); exit(EXIT_FAILURE); }
+void op_lwc3(CPU* cpu, instruction* i) { (void)i; exception(cpu, E_COPROCESSOR_ERROR); }
-void op_swc0(CPU* cpu, instruction* i) { exception(cpu, E_COPROCESSOR_ERROR); }
-void op_swc1(CPU* cpu, instruction* i) { exception(cpu, E_COPROCESSOR_ERROR); }
-void op_swc2(CPU* cpu, instruction* i) { fprintf(stderr, "Unhandled GTE SWC: %08X\n", i->_0); exit(EXIT_FAILURE); }
-void op_swc3(CPU* cpu, instruction* i) { exception(cpu, E_COPROCESSOR_ERROR); }
+void op_swc0(CPU* cpu, instruction* i) { (void)i; exception(cpu, E_COPROCESSOR_ERROR); }
+void op_swc1(CPU* cpu, instruction* i) { (void)i; exception(cpu, E_COPROCESSOR_ERROR); }
+void op_swc2(CPU* cpu, instruction* i) { (void)i; (void)cpu; log_fatal("Unhandled GTE SWC: %08X", i->_0); exit(EXIT_FAILURE); }
+void op_swc3(CPU* cpu, instruction* i) { (void)i; exception(cpu, E_COPROCESSOR_ERROR); }
void
op_illegal(CPU* cpu, instruction* i)
{
- printf("Illegal instruction %08X\n", i->_0);
+ (void)i;
+ log_warn("Illegal instruction %08X", i->_0);
exception(cpu, E_ILLEGAL_INSTRUCTION);
}
@@ -893,7 +893,7 @@ CPU_decode_and_execute(CPU* cpu, instruction* i)
case 0x0: op_sll(cpu, i); break;
case 0x02: op_srl(cpu, i); break;
case 0x03: op_sra(cpu, i); break;
- case 0x0d: op_break(cpu, i); break;
+ case 0x0d: op_break(cpu, i); break;
case 0x07: op_srav(cpu, i); break;
case 0x04: op_sllv(cpu, i); break;
case 0x06: op_srlv(cpu, i); break;
@@ -917,7 +917,7 @@ CPU_decode_and_execute(CPU* cpu, instruction* i)
case 0x13: op_mtlo(cpu, i); break;
case 0x18: op_mult(cpu, i); break;
case 0x19: op_multu(cpu, i); break;
- case 0x0C: op_syscall(cpu, i); break;
+ case 0x0C: op_syscall(cpu, i); break;
default: op_illegal(cpu, i); break;
}
break;
diff --git a/src/defs.h b/src/defs.h
@@ -1,26 +0,0 @@
-#pragma once
-
-static const int debug = 0; // Set to 0 to disable debug prints
-
-#include <assert.h>
-
-#define LOG_ERR(x) fprintf(stderr, (x))
-
-/* #define PANIC(...) do { fprintf(stderr, __VA_ARGS__); exit(EXIT_FAILURE); } while(0) */
-
-/* We should get rid of this */
-#define DEBUG 0;
-
-#define LOG_NONE 0
-#define LOG_DEBUG 1
-#define LOG_INFO 2
-#define LOG_WARN 3
-#define LOG_ERROR 4
-
-// Set the current log level
-#define CURRENT_LOG_LEVEL LOG_ERROR
-
-#define LOG(level, fmt, ...) \
- do { if (level >= CURRENT_LOG_LEVEL) fprintf(stderr, fmt, __VA_ARGS__); } while (0)
-#define GPU_LOG(fmt, ...) \
- do { fprintf(stderr, fmt, __VA_ARGS__); } while (0)
diff --git a/src/gpu.c b/src/gpu.c
@@ -3,8 +3,8 @@
#include <string.h>
#include "gpu.h"
#include "types.h"
-#include "defs.h"
#include "sr.h"
+#include "log.h"
u8 HOR_RES_from_fields(u8 hr1, u8 hr2) { return (hr2 & 1) | ((hr1 & 3) << 1); }
u32 HOR_RES_into_status(u8 hr) {return ((u32)hr) << 16; }
@@ -12,452 +12,458 @@ u32 HOR_RES_into_status(u8 hr) {return ((u32)hr) << 16; }
GPU*
GPU_new(void)
{
- GPU* gpu;
+ GPU* gpu;
- gpu = (GPU*)malloc(sizeof(GPU));
- memset(gpu, 0, sizeof(GPU));
- gpu->display_disabled = 1;
- gpu->ren = REN_new();
+ gpu = (GPU*)malloc(sizeof(GPU));
+ memset(gpu, 0, sizeof(GPU));
+ gpu->display_disabled = 1;
+ gpu->ren = REN_new();
- return gpu;
+ return gpu;
}
u32
GPU_read(GPU* gpu)
{
- return 0;
+ (void)gpu;
+ return 0;
}
u32
GPU_status(GPU* gpu)
{
- u32 r;
- u32 dma_req;
-
- dma_req = 0;
- r = 0;
-
- r |= ((u32)gpu->page_base_x) << 0;
- r |= ((u32)gpu->page_base_y) << 4;
- r |= ((u32)gpu->semi_transparency) << 5;
- r |= ((u32)gpu->texture_depth) << 7;
- r |= ((u32)gpu->dithering) << 9;
- r |= ((u32)gpu->draw_to_display) << 10;
- r |= ((u32)gpu->force_set_mask_bit) << 11;
- r |= ((u32)gpu->preserve_masked_pixels) << 12;
- r |= ((u32)gpu->field) << 13;
- /* Bit 14 not supported */
- r |= ((u32)gpu->texture_disable) << 15;
- r |= HOR_RES_into_status(gpu->hres);
- /* If we don't emulate bit 31 correctly setting vres to 1
- locks the BIOS. 4.17 on the guide.
- */
- //r |= ((u32)gpu->vres) << 19;
- r |= ((u32)gpu->vmode) << 20;
- r |= ((u32)gpu->display_depth) << 21;
- r |= ((u32)gpu->interlaced) << 22;
- r |= ((u32)gpu->display_disabled) << 23;
- r |= ((u32)gpu->interrupt) << 24;
-
- /* Always GPU is ready */
- r |= 1 << 26;
- r |= 1 << 27;
- r |= 1 << 28;
-
- r |= ((u32) gpu->dma_direction) << 29;
-
- /* Ignore odd lines for now */
- r |= 0 << 31;
-
- switch(gpu->dma_direction)
- {
- case DMA_DIR_OFF: dma_req = 0; break;
- case DMA_DIR_FIFO: dma_req = 1; break;
- case DMA_DIR_CPUTOGP0: dma_req = (r >> 28) & 1; break;
- case DMA_DIR_VRAMTOCPU: dma_req = (r >> 27) & 1; break;
- default: fprintf(stderr, "UNREACHABLE"); exit(1);
- }
-
- r |= dma_req << 25;
-
- return r;
+ u32 r;
+ u32 dma_req;
+
+ dma_req = 0;
+ r = 0;
+
+ r |= ((u32)gpu->page_base_x) << 0;
+ r |= ((u32)gpu->page_base_y) << 4;
+ r |= ((u32)gpu->semi_transparency) << 5;
+ r |= ((u32)gpu->texture_depth) << 7;
+ r |= ((u32)gpu->dithering) << 9;
+ r |= ((u32)gpu->draw_to_display) << 10;
+ r |= ((u32)gpu->force_set_mask_bit) << 11;
+ r |= ((u32)gpu->preserve_masked_pixels) << 12;
+ r |= ((u32)gpu->field) << 13;
+ /* Bit 14 not supported */
+ r |= ((u32)gpu->texture_disable) << 15;
+ r |= HOR_RES_into_status(gpu->hres);
+ /* If we don't emulate bit 31 correctly setting vres to 1
+ locks the BIOS. 4.17 on the guide.
+ */
+ /*r |= ((u32)gpu->vres) << 19;*/
+ r |= ((u32)gpu->vmode) << 20;
+ r |= ((u32)gpu->display_depth) << 21;
+ r |= ((u32)gpu->interlaced) << 22;
+ r |= ((u32)gpu->display_disabled) << 23;
+ r |= ((u32)gpu->interrupt) << 24;
+
+ /* Always GPU is ready */
+ r |= 1 << 26;
+ r |= 1 << 27;
+ r |= 1 << 28;
+
+ r |= ((u32) gpu->dma_direction) << 29;
+
+ /* Ignore odd lines for now */
+ r |= 0 << 31;
+
+ switch(gpu->dma_direction)
+ {
+ case DMA_DIR_OFF: dma_req = 0; break;
+ case DMA_DIR_FIFO: dma_req = 1; break;
+ case DMA_DIR_CPUTOGP0: dma_req = (r >> 28) & 1; break;
+ case DMA_DIR_VRAMTOCPU: dma_req = (r >> 27) & 1; break;
+ default: log_fatal("UNREACHABLE"); exit(1);
+ }
+
+ r |= dma_req << 25;
+
+ return r;
}
void
GPU_gp1(GPU* gpu, u32 val)
{
- u32 opcode;
+ u32 opcode;
- opcode = (val >> 24) & 0xff;
+ opcode = (val >> 24) & 0xff;
- switch (opcode)
- {
- case 0x00: GPU_gp1_reset(gpu, val); break;
- case 0x01: GPU_gp1_reset_command_buffer(gpu, val); break;
- case 0x02: GPU_gp1_acknowledge_irq(gpu, val); break;
- case 0x03: GPU_gp1_display_enable(gpu, val); break;
- case 0x04: GPU_gp1_dma_direction(gpu, val); break;
- case 0x05: GPU_gp1_display_vram_start(gpu, val); break;
- case 0x06: GPU_gp1_display_horizontal_range(gpu, val); break;
- case 0x07: GPU_gp1_display_vertical_range(gpu, val); break;
- case 0x08: GPU_gp1_display_mode(gpu, val); break;
- default: fprintf(stderr, "OP: %08X: Unhandled GP1 command %08X\n", opcode, val); exit(1);
- }
+ switch (opcode)
+ {
+ case 0x00: GPU_gp1_reset(gpu, val); break;
+ case 0x01: GPU_gp1_reset_command_buffer(gpu, val); break;
+ case 0x02: GPU_gp1_acknowledge_irq(gpu, val); break;
+ case 0x03: GPU_gp1_display_enable(gpu, val); break;
+ case 0x04: GPU_gp1_dma_direction(gpu, val); break;
+ case 0x05: GPU_gp1_display_vram_start(gpu, val); break;
+ case 0x06: GPU_gp1_display_horizontal_range(gpu, val); break;
+ case 0x07: GPU_gp1_display_vertical_range(gpu, val); break;
+ case 0x08: GPU_gp1_display_mode(gpu, val); break;
+ default: log_fatal("OP: %08X: Unhandled GP1 command %08X", opcode, val); exit(1);
+ }
}
void
GPU_gp1_reset(GPU* gpu, u32 val)
{
- REN* tmp = gpu->ren;
- memset(gpu, 0, sizeof(GPU));
- /* Fill out the rest of the fields with no$cash spec reset values*/
- gpu->display_disabled = 1;
- gpu->interlaced = 1;
- gpu->display_horiz_start = 0x200;
- gpu->display_horiz_end = 0xc00;
- gpu->display_line_start = 0x10;
- gpu->display_line_end = 0x100;
- gpu->ren = tmp;
+ (void)val;
+ REN* tmp = gpu->ren;
+ memset(gpu, 0, sizeof(GPU));
+ /* Fill out the rest of the fields with no$cash spec reset values*/
+ gpu->display_disabled = 1;
+ gpu->interlaced = 1;
+ gpu->display_horiz_start = 0x200;
+ gpu->display_horiz_end = 0xc00;
+ gpu->display_line_start = 0x10;
+ gpu->display_line_end = 0x100;
+ gpu->ren = tmp;
}
void
GPU_gp1_display_enable(GPU* gpu, u32 val)
{
- gpu->display_disabled = (val & 1) != 0;
+ gpu->display_disabled = (val & 1) != 0;
}
void
GPU_gp1_acknowledge_irq(GPU* gpu, u32 val)
{
- gpu->interrupt = 0;
+ (void)val;
+ gpu->interrupt = 0;
}
void
GPU_gp1_reset_command_buffer(GPU* gpu, u32 val)
{
- GPU_CMD_BUFFER_clear(&gpu->gp0_command);
- gpu->gp0_words_remaining = 0;
- gpu->gp0_mode = GP0_MODE_COMMAND;
+ (void)val;
+ GPU_CMD_BUFFER_clear(&gpu->gp0_command);
+ gpu->gp0_words_remaining = 0;
+ gpu->gp0_mode = GP0_MODE_COMMAND;
- // XXX Should also clear the command FIFO when we implement it
+ /* XXX Should also clear the command FIFO when we implement it*/
}
-void
+ void
GPU_gp1_display_horizontal_range(GPU* gpu, u32 val)
{
- gpu->display_horiz_start = (u16)(val & 0xfff);
- gpu->display_horiz_end = (u16)((val >> 12) & 0xfff);
+ gpu->display_horiz_start = (u16)(val & 0xfff);
+ gpu->display_horiz_end = (u16)((val >> 12) & 0xfff);
}
-void
+ void
GPU_gp1_display_vertical_range(GPU* gpu, u32 val)
{
- gpu->display_line_start = (u16)(val & 0x3ff);
- gpu->display_line_end = (u16)((val >> 10) & 0x3ff);
+ gpu->display_line_start = (u16)(val & 0x3ff);
+ gpu->display_line_end = (u16)((val >> 10) & 0x3ff);
}
-void
+ void
GPU_gp1_display_vram_start(GPU* gpu, u32 val)
{
- gpu->display_vram_x_start = (u16)(val & 0x3fe);
- gpu->display_vram_y_start = (u16)((val >> 10) & 0x1ff);
+ gpu->display_vram_x_start = (u16)(val & 0x3fe);
+ gpu->display_vram_y_start = (u16)((val >> 10) & 0x1ff);
}
-void
+ void
GPU_gp1_dma_direction(GPU* gpu, u32 val)
{
- switch (val & 3) {
- case 0: gpu->dma_direction = DMA_DIR_OFF; break;
- case 1: gpu->dma_direction = DMA_DIR_FIFO; break;
- case 2: gpu->dma_direction = DMA_DIR_CPUTOGP0; break;
- case 3: gpu->dma_direction = DMA_DIR_VRAMTOCPU; break;
- default: fprintf(stderr, "UNREACHABLE"); exit(EXIT_FAILURE);
- }
+ switch (val & 3) {
+ case 0: gpu->dma_direction = DMA_DIR_OFF; break;
+ case 1: gpu->dma_direction = DMA_DIR_FIFO; break;
+ case 2: gpu->dma_direction = DMA_DIR_CPUTOGP0; break;
+ case 3: gpu->dma_direction = DMA_DIR_VRAMTOCPU; break;
+ default: log_fatal("UNREACHABLE"); exit(EXIT_FAILURE);
+ }
}
-void
+ void
GPU_gp1_display_mode(GPU* gpu, u32 val)
{
- u8 hr1, hr2;
+ u8 hr1, hr2;
- hr1 = (u8)(val & 3);
- hr2 = (u8)((val >> 6) & 1);
+ hr1 = (u8)(val & 3);
+ hr2 = (u8)((val >> 6) & 1);
- gpu->hres = HOR_RES_from_fields(hr1, hr2);
- gpu->vres = (val & 0x4) != 0;
- gpu->vmode = (val & 0x8) != 0 ? VMODE_NTSC : VMODE_PAL;
- gpu->display_depth = (val & 0x10) != 0 ? DISP_DEPTH_D24BITS : DISP_DEPTH_D15BITS;
- gpu->interlaced = (val & 0x20) != 0;
+ gpu->hres = HOR_RES_from_fields(hr1, hr2);
+ gpu->vres = (val & 0x4) != 0;
+ gpu->vmode = (val & 0x8) != 0 ? VMODE_NTSC : VMODE_PAL;
+ gpu->display_depth = (val & 0x10) != 0 ? DISP_DEPTH_D24BITS : DISP_DEPTH_D15BITS;
+ gpu->interlaced = (val & 0x20) != 0;
- if (val & 0x80)
- fprintf(stderr, "Unsupported display mode %08X\n", val), exit(EXIT_FAILURE);
+ if (val & 0x80)
+ log_fatal("Unsupported display mode %08X", val), exit(EXIT_FAILURE);
}
-void
+ void
GPU_gp0(GPU* gpu, u32 val)
{
- if (gpu->gp0_words_remaining == 0) {
- u32 opcode, len;
- void (*method)(GPU*);
-
- opcode = (val >> 24) & 0xff;
-
- switch (opcode) {
- case 0x00: len = 1; method = GPU_gp0_nop; break;
- case 0x01: len = 1; method = GPU_gp0_clear_cache; break;
- case 0xa0: len = 3; method = GPU_gp0_image_load; break;
- case 0xe1: len = 1; method = GPU_gp0_draw_mode; break;
- case 0xe2: len = 1; method = GPU_gp0_texture_window; break;
- case 0xe3: len = 1; method = GPU_gp0_drawing_area_top_left; break;
- case 0xe4: len = 1; method = GPU_gp0_drawing_area_bottom_right; break;
- case 0xe5: len = 1; method = GPU_gp0_drawing_offset; break;
- case 0xe6: len = 1; method = GPU_gp0_mask_bit_setting; break;
- case 0x28: len = 5; method = GPU_gp0_quad_mono_opaque; break;
- case 0x2c: len = 9; method = GPU_gp0_quad_texture_blend_opaque; break;
- case 0x30: len = 6; method = GPU_gp0_triangle_shaded_opaque; break;
- case 0x38: len = 8; method = GPU_gp0_quad_shaded_opaque; break;
- case 0xc0: len = 3; method = GPU_gp0_image_store; break;
- default: fprintf(stderr, "OP: %08X: Unhandled GP0 command %08X\n", opcode, val); exit(1);
+ if (gpu->gp0_words_remaining == 0) {
+ u32 opcode, len;
+ void (*method)(GPU*);
+
+ opcode = (val >> 24) & 0xff;
+
+ switch (opcode) {
+ case 0x00: len = 1; method = GPU_gp0_nop; break;
+ case 0x01: len = 1; method = GPU_gp0_clear_cache; break;
+ case 0xa0: len = 3; method = GPU_gp0_image_load; break;
+ case 0xe1: len = 1; method = GPU_gp0_draw_mode; break;
+ case 0xe2: len = 1; method = GPU_gp0_texture_window; break;
+ case 0xe3: len = 1; method = GPU_gp0_drawing_area_top_left; break;
+ case 0xe4: len = 1; method = GPU_gp0_drawing_area_bottom_right; break;
+ case 0xe5: len = 1; method = GPU_gp0_drawing_offset; break;
+ case 0xe6: len = 1; method = GPU_gp0_mask_bit_setting; break;
+ case 0x28: len = 5; method = GPU_gp0_quad_mono_opaque; break;
+ case 0x2c: len = 9; method = GPU_gp0_quad_texture_blend_opaque; break;
+ case 0x30: len = 6; method = GPU_gp0_triangle_shaded_opaque; break;
+ case 0x38: len = 8; method = GPU_gp0_quad_shaded_opaque; break;
+ case 0xc0: len = 3; method = GPU_gp0_image_store; break;
+ default: log_fatal("OP: %08X: Unhandled GP0 command %08X", opcode, val); exit(1);
+ }
+
+ gpu->gp0_words_remaining = len;
+ gpu->gp0_command_method = method;
+ GPU_CMD_BUFFER_clear(&gpu->gp0_command);
}
- gpu->gp0_words_remaining = len;
- gpu->gp0_command_method = method;
- GPU_CMD_BUFFER_clear(&gpu->gp0_command);
- }
-
- gpu->gp0_words_remaining -= 1;
-
- switch (gpu->gp0_mode) {
- case GP0_MODE_COMMAND:
- GPU_CMD_BUFFER_push_word(&gpu->gp0_command, val);
- if (gpu->gp0_words_remaining == 0)
- gpu->gp0_command_method(gpu);
- break;
- case GP0_MODE_IMAGE_LOAD:
- if (gpu->gp0_words_remaining == 0)
- gpu->gp0_mode = GP0_MODE_COMMAND;
- break;
- }
+ gpu->gp0_words_remaining -= 1;
+
+ switch (gpu->gp0_mode) {
+ case GP0_MODE_COMMAND:
+ GPU_CMD_BUFFER_push_word(&gpu->gp0_command, val);
+ if (gpu->gp0_words_remaining == 0)
+ gpu->gp0_command_method(gpu);
+ break;
+ case GP0_MODE_IMAGE_LOAD:
+ if (gpu->gp0_words_remaining == 0)
+ gpu->gp0_mode = GP0_MODE_COMMAND;
+ break;
+ }
}
-void GPU_gp0_nop(GPU* gpu) {}
+void GPU_gp0_nop(GPU* gpu) {(void)gpu;}
-void GPU_gp0_clear_cache(GPU* gpu) { /* Not implemented */}
+void GPU_gp0_clear_cache(GPU* gpu) {(void)gpu;}
-void
+ void
GPU_gp0_image_load(GPU* gpu)
{
- u32 res, width, height, imgsize;
-
- res = gpu->gp0_command.buffer[2];
- width = res & 0xffff;
- height = res >> 16;
- imgsize = width * height;
- imgsize = (imgsize + 1) & ~1;
- gpu->gp0_words_remaining = imgsize / 2;
- gpu->gp0_mode = GP0_MODE_IMAGE_LOAD;
+ u32 res, width, height, imgsize;
+
+ res = gpu->gp0_command.buffer[2];
+ width = res & 0xffff;
+ height = res >> 16;
+ imgsize = width * height;
+ imgsize = (imgsize + 1) & ~1;
+ gpu->gp0_words_remaining = imgsize / 2;
+ gpu->gp0_mode = GP0_MODE_IMAGE_LOAD;
}
-void
+ void
GPU_gp0_draw_mode(GPU* gpu)
{
- u32 val;
- val = gpu->gp0_command.buffer[0];
-
- gpu->page_base_x = (u8)(val & 0xf);
- gpu->page_base_y = (u8)((val >> 4) & 1);
- gpu->semi_transparency = (u8)((val >> 5) & 3);
-
- switch ((val >> 7) & 3)
- {
- case 0: gpu->texture_depth = TD_T4BIT; break;
- case 1: gpu->texture_depth = TD_T8BIT; break;
- case 2: gpu->texture_depth = TD_T15BIT; break;
- default: fprintf(stderr, "Unhandled texture depth %d\n", (val >> 7) & 3); exit(1);
- }
-
- gpu->dithering = ((val >> 9) & 1);
- gpu->draw_to_display = ((val >> 10) & 1);
- gpu->texture_disable = ((val >> 11) & 1);
- gpu->rectangle_texture_x_flip = ((val >> 12) & 1);
- gpu->rectangle_texture_y_flip = ((val >> 13) & 1);
+ u32 val;
+ val = gpu->gp0_command.buffer[0];
+
+ gpu->page_base_x = (u8)(val & 0xf);
+ gpu->page_base_y = (u8)((val >> 4) & 1);
+ gpu->semi_transparency = (u8)((val >> 5) & 3);
+
+ switch ((val >> 7) & 3)
+ {
+ case 0: gpu->texture_depth = TD_T4BIT; break;
+ case 1: gpu->texture_depth = TD_T8BIT; break;
+ case 2: gpu->texture_depth = TD_T15BIT; break;
+ default: log_fatal("Unhandled texture depth %d", (val >> 7) & 3); exit(1);
+ }
+
+ gpu->dithering = ((val >> 9) & 1);
+ gpu->draw_to_display = ((val >> 10) & 1);
+ gpu->texture_disable = ((val >> 11) & 1);
+ gpu->rectangle_texture_x_flip = ((val >> 12) & 1);
+ gpu->rectangle_texture_y_flip = ((val >> 13) & 1);
}
-void
+ void
GPU_gp0_drawing_area_top_left(GPU* gpu)
{
- u32 val;
- val = gpu->gp0_command.buffer[0];
- gpu->drawing_area_top = (u16)((val >> 10) & 0x3ff);
- gpu->drawing_area_left = (u16)(val & 0x3ff);
+ u32 val;
+ val = gpu->gp0_command.buffer[0];
+ gpu->drawing_area_top = (u16)((val >> 10) & 0x3ff);
+ gpu->drawing_area_left = (u16)(val & 0x3ff);
}
-void
+ void
GPU_gp0_drawing_area_bottom_right(GPU* gpu)
{
- u32 val;
- val = gpu->gp0_command.buffer[0];
+ u32 val;
+ val = gpu->gp0_command.buffer[0];
- gpu->drawing_area_bottom = (u16)((val >> 10) & 0x3ff);
- gpu->drawing_area_right = (u16)(val & 0x3ff);
+ gpu->drawing_area_bottom = (u16)((val >> 10) & 0x3ff);
+ gpu->drawing_area_right = (u16)(val & 0x3ff);
}
-void
+ void
GPU_gp0_drawing_offset(GPU* gpu)
{
- u16 x, y;
- u32 val;
-
- val = gpu->gp0_command.buffer[0];
- x = (u16)(val & 0x7ff);
- y = (u16)((val >> 11) & 0x7ff);
-
- /* Values here are 11bit 2s complement signed values, we need to force sign extension */
- gpu->drawing_x_offset = ((i16)(x << 5)) >> 5;
- gpu->drawing_y_offset = ((i16)(y << 5)) >> 5;
-
- /*
- This is a hack because I haven't implemented gpu timings yet.
- But gp0_drawing_offset is called every frame apparently.
- */
- REN_display(gpu->ren);
-
+ u16 x, y;
+ u32 val;
+
+ val = gpu->gp0_command.buffer[0];
+ x = (u16)(val & 0x7ff);
+ y = (u16)((val >> 11) & 0x7ff);
+
+ /* Values here are 11bit 2s complement signed values, we need to force sign extension */
+ gpu->drawing_x_offset = ((i16)(x << 5)) >> 5;
+ gpu->drawing_y_offset = ((i16)(y << 5)) >> 5;
+
+ /*
+ This is a hack because I haven't implemented gpu timings yet.
+ But gp0_drawing_offset is called every frame apparently.
+ */
+ REN_display(gpu->ren);
+
}
-void
+ void
GPU_gp0_texture_window(GPU* gpu)
{
- u32 val;
- val = gpu->gp0_command.buffer[0];
+ u32 val;
+ val = gpu->gp0_command.buffer[0];
- gpu->texture_window_x_mask = (u8)(val & 0x1f);
- gpu->texture_window_y_mask = (u8)((val >> 5) & 0x1f);
- gpu->texture_window_x_offset = (u8)((val >> 10) & 0x1f);
- gpu->texture_window_y_offset = (u8)((val >> 15) & 0x1f);
+ gpu->texture_window_x_mask = (u8)(val & 0x1f);
+ gpu->texture_window_y_mask = (u8)((val >> 5) & 0x1f);
+ gpu->texture_window_x_offset = (u8)((val >> 10) & 0x1f);
+ gpu->texture_window_y_offset = (u8)((val >> 15) & 0x1f);
}
-void
+ void
GPU_gp0_mask_bit_setting(GPU* gpu)
{
- u32 val;
- val = gpu->gp0_command.buffer[0];
+ u32 val;
+ val = gpu->gp0_command.buffer[0];
- gpu->force_set_mask_bit = (val & 1) != 0;
- gpu->preserve_masked_pixels = (val & 2) != 0;
+ gpu->force_set_mask_bit = (val & 1) != 0;
+ gpu->preserve_masked_pixels = (val & 2) != 0;
}
-void
+ void
GPU_gp0_quad_mono_opaque(GPU* gpu)
{
- ivec2 positions[4];
- C colors[4];
+ ivec2 positions[4];
+ C colors[4];
- positions[0] = POSITION_from_gp0(gpu->gp0_command.buffer[1]);
- positions[1] = POSITION_from_gp0(gpu->gp0_command.buffer[2]);
- positions[2] = POSITION_from_gp0(gpu->gp0_command.buffer[3]);
- positions[3] = POSITION_from_gp0(gpu->gp0_command.buffer[4]);
+ positions[0] = POSITION_from_gp0(gpu->gp0_command.buffer[1]);
+ positions[1] = POSITION_from_gp0(gpu->gp0_command.buffer[2]);
+ positions[2] = POSITION_from_gp0(gpu->gp0_command.buffer[3]);
+ positions[3] = POSITION_from_gp0(gpu->gp0_command.buffer[4]);
- colors[0] = colors[1] = colors[2] = colors[3] = COLOR_from_gp0(gpu->gp0_command.buffer[0]);
+ colors[0] = colors[1] = colors[2] = colors[3] = COLOR_from_gp0(gpu->gp0_command.buffer[0]);
- //GPU_LOG("Draw quad mono opaque at x: %d, y: %d\n", positions[0].x, positions[0].y, NULL);
- //GPU_LOG("Draw quad mono opaque with R: %d, G: %d, B: %d\n", colors[0].r, colors[0].g, colors[0].b, NULL);
+ /*GPU_LOG("Draw quad mono opaque at x: %d, y: %d\n", positions[0].x, positions[0].y, NULL);*/
+ /*GPU_LOG("Draw quad mono opaque with R: %d, G: %d, B: %d\n", colors[0].r, colors[0].g, colors[0].b, NULL);*/
- REN_push_quad(gpu->ren, positions, colors);
+ REN_push_quad(gpu->ren, positions, colors);
}
-void
+ void
GPU_gp0_triangle_shaded_opaque(GPU* gpu)
{
- ivec2 positions[3];
- C colors[3];
+ ivec2 positions[3];
+ C colors[3];
- positions[0] = POSITION_from_gp0(gpu->gp0_command.buffer[1]);
- positions[1] = POSITION_from_gp0(gpu->gp0_command.buffer[3]);
- positions[2] = POSITION_from_gp0(gpu->gp0_command.buffer[5]);
+ positions[0] = POSITION_from_gp0(gpu->gp0_command.buffer[1]);
+ positions[1] = POSITION_from_gp0(gpu->gp0_command.buffer[3]);
+ positions[2] = POSITION_from_gp0(gpu->gp0_command.buffer[5]);
- colors[0] = COLOR_from_gp0(gpu->gp0_command.buffer[0]);
- colors[1] = COLOR_from_gp0(gpu->gp0_command.buffer[2]);
- colors[2] = COLOR_from_gp0(gpu->gp0_command.buffer[4]);
+ colors[0] = COLOR_from_gp0(gpu->gp0_command.buffer[0]);
+ colors[1] = COLOR_from_gp0(gpu->gp0_command.buffer[2]);
+ colors[2] = COLOR_from_gp0(gpu->gp0_command.buffer[4]);
- REN_push_triangle(gpu->ren, positions, colors);
+ REN_push_triangle(gpu->ren, positions, colors);
- //GPU_LOG("Draw triangle shaded at x: %d, y: %d\n", positions[0].x, positions[0].y, NULL);
+ /*GPU_LOG("Draw triangle shaded at x: %d, y: %d\n", positions[0].x, positions[0].y, NULL);*/
}
-void
+ void
GPU_gp0_quad_texture_blend_opaque(GPU* gpu)
{
- ivec2 positions[4];
- C colors[4];
+ ivec2 positions[4];
+ C colors[4];
+ C tmp = {0x80, 0x00, 0x00};
+
- positions[0] = POSITION_from_gp0(gpu->gp0_command.buffer[1]);
- positions[1] = POSITION_from_gp0(gpu->gp0_command.buffer[3]);
- positions[2] = POSITION_from_gp0(gpu->gp0_command.buffer[5]);
- positions[3] = POSITION_from_gp0(gpu->gp0_command.buffer[7]);
+ positions[0] = POSITION_from_gp0(gpu->gp0_command.buffer[1]);
+ positions[1] = POSITION_from_gp0(gpu->gp0_command.buffer[3]);
+ positions[2] = POSITION_from_gp0(gpu->gp0_command.buffer[5]);
+ positions[3] = POSITION_from_gp0(gpu->gp0_command.buffer[7]);
- colors[0] = colors[1] = colors[2] = colors[3] = (C){0x80, 0x00, 0x00};
+ colors[0] = colors[1] = colors[2] = colors[3] = tmp;
- REN_push_quad(gpu->ren, positions, colors);
+ REN_push_quad(gpu->ren, positions, colors);
}
-void
+ void
GPU_gp0_quad_shaded_opaque(GPU* gpu)
{
- ivec2 positions[4];
- C colors[4];
+ ivec2 positions[4];
+ C colors[4];
- positions[0] = POSITION_from_gp0(gpu->gp0_command.buffer[1]);
- positions[1] = POSITION_from_gp0(gpu->gp0_command.buffer[3]);
- positions[2] = POSITION_from_gp0(gpu->gp0_command.buffer[5]);
- positions[3] = POSITION_from_gp0(gpu->gp0_command.buffer[7]);
+ positions[0] = POSITION_from_gp0(gpu->gp0_command.buffer[1]);
+ positions[1] = POSITION_from_gp0(gpu->gp0_command.buffer[3]);
+ positions[2] = POSITION_from_gp0(gpu->gp0_command.buffer[5]);
+ positions[3] = POSITION_from_gp0(gpu->gp0_command.buffer[7]);
- colors[0] = COLOR_from_gp0(gpu->gp0_command.buffer[0]);
- colors[1] = COLOR_from_gp0(gpu->gp0_command.buffer[2]);
- colors[2] = COLOR_from_gp0(gpu->gp0_command.buffer[4]);
- colors[3] = COLOR_from_gp0(gpu->gp0_command.buffer[6]);
+ colors[0] = COLOR_from_gp0(gpu->gp0_command.buffer[0]);
+ colors[1] = COLOR_from_gp0(gpu->gp0_command.buffer[2]);
+ colors[2] = COLOR_from_gp0(gpu->gp0_command.buffer[4]);
+ colors[3] = COLOR_from_gp0(gpu->gp0_command.buffer[6]);
- //GPU_LOG("I GOT CALLED\n", NULL);
- REN_push_quad(gpu->ren, positions, colors);
+ /*GPU_LOG("I GOT CALLED\n", NULL);*/
+ REN_push_quad(gpu->ren, positions, colors);
}
-void
+ void
GPU_gp0_image_store(GPU* gpu)
{
- u32 res, width, height;
+ u32 res, width, height;
- res = gpu->gp0_command.buffer[2];
- width = res & 0xffff;
- height = res >> 16;
+ res = gpu->gp0_command.buffer[2];
+ width = res & 0xffff;
+ height = res >> 16;
- fprintf(stdout, "Unhandled image store: %dx%d\n", width, height);
+ log_debug("Unhandled image store: %dx%d", width, height);
}
-GPU_CMD_BUFFER*
+ GPU_CMD_BUFFER*
GPU_CMD_BUFFER_new(void)
{
- GPU_CMD_BUFFER* buffer;
+ GPU_CMD_BUFFER* buffer;
- buffer = (GPU_CMD_BUFFER*)malloc(sizeof(GPU_CMD_BUFFER));
- memset(buffer, 0, sizeof(GPU_CMD_BUFFER));
+ buffer = (GPU_CMD_BUFFER*)malloc(sizeof(GPU_CMD_BUFFER));
+ memset(buffer, 0, sizeof(GPU_CMD_BUFFER));
- return buffer;
+ return buffer;
}
-void
+ void
GPU_CMD_BUFFER_clear(GPU_CMD_BUFFER* cmd_buffer)
{
- cmd_buffer->len = 0;
- memset(cmd_buffer->buffer, 413, 12 * sizeof(u32));
+ cmd_buffer->len = 0;
+ memset(cmd_buffer->buffer, 413, 12 * sizeof(u32));
}
-void
+ void
GPU_CMD_BUFFER_push_word(GPU_CMD_BUFFER* cmd_buffer, u32 word)
{
- if (cmd_buffer->len > 12)
- fprintf(stderr, "OUT OF BOUNDS GPU_CMD_BUFFER"), exit(EXIT_FAILURE);
+ if (cmd_buffer->len > 12)
+ log_fatal("OUT OF BOUNDS GPU_CMD_BUFFER"), exit(EXIT_FAILURE);
- cmd_buffer->buffer[cmd_buffer->len] = word;
- cmd_buffer->len++;
+ cmd_buffer->buffer[cmd_buffer->len] = word;
+ cmd_buffer->len++;
}
diff --git a/src/interconnect.c b/src/interconnect.c
@@ -6,580 +6,542 @@
#include "mem.h"
#include "util.h"
#include "types.h"
-#include "defs.h"
#include "gpu.h"
#include "cdrom.h"
+#include "log.h"
Interconnect*
new_interconnect(void) {
- Interconnect* inter = (Interconnect*)malloc(sizeof(Interconnect));
- inter->bios = BIOS_new("roms/scph1001.bin");
- inter->ram = RAM_new();
- inter->dma = DMA_new();
- inter->gpu = GPU_new();
- inter->cdrom = cdrom_new();
- inter->irq = irq_new();
- return inter;
+ Interconnect* inter = (Interconnect*)malloc(sizeof(Interconnect));
+ inter->bios = BIOS_new("roms/scph1001.bin");
+ inter->ram = RAM_new();
+ inter->dma = DMA_new();
+ inter->gpu = GPU_new();
+ inter->cdrom = cdrom_new();
+ inter->irq = irq_new();
+ return inter;
}
u8
INTER_load8(Interconnect* inter, u32 addr)
{
- u32 offset;
- u32 abs_addr;
- u32 contains;
-
- offset = 0;
- contains = 0;
- abs_addr = mask_region(addr);
-
- /* Assert abs_address Mappings */
- contains = UTIL_contains(BIOS_START, BIOS_SIZE, abs_addr, &offset);
- if (contains)
- return BIOS_load8(inter->bios, offset);
-
- contains = UTIL_contains(EXPANSION1_START, EXPANSION1_SIZE, abs_addr, &offset);
- if (contains)
- return 0xff;
-
- contains = UTIL_contains(RAM_START, RAM_SIZE, abs_addr, &offset);
- if (contains)
- return RAM_load8(inter->ram, offset);
-
- contains = UTIL_contains(IRQ_CONTROL_START, IRQ_CONTROL_SIZE, abs_addr, &offset);
- if (contains)
- {
-#ifndef DEBUG
- printf("IRQ CONTROL read %08X\n", offset);
-#endif
- return 0;
- }
-
- contains = UTIL_contains(CDROM_START, CDROM_SIZE, abs_addr, &offset);
- if (contains)
- {
- return cdrom_load(inter->cdrom, offset);
- }
-
- fprintf(stderr, "Unhandled Load8 At Address %08X\n", addr);
- exit(EXIT_FAILURE);
+ u32 offset;
+ u32 abs_addr;
+ u32 contains;
+
+ offset = 0;
+ contains = 0;
+ abs_addr = mask_region(addr);
+
+ /* Assert abs_address Mappings */
+ contains = UTIL_contains(BIOS_START, BIOS_SIZE, abs_addr, &offset);
+ if (contains)
+ return BIOS_load8(inter->bios, offset);
+
+ contains = UTIL_contains(EXPANSION1_START, EXPANSION1_SIZE, abs_addr, &offset);
+ if (contains)
+ return 0xff;
+
+ contains = UTIL_contains(RAM_START, RAM_SIZE, abs_addr, &offset);
+ if (contains)
+ return RAM_load8(inter->ram, offset);
+
+ contains = UTIL_contains(IRQ_CONTROL_START, IRQ_CONTROL_SIZE, abs_addr, &offset);
+ if (contains)
+ {
+ log_debug("IRQ CONTROL read %08X", offset);
+ return 0;
+ }
+
+ contains = UTIL_contains(CDROM_START, CDROM_SIZE, abs_addr, &offset);
+ if (contains)
+ {
+ return cdrom_load(inter->cdrom, offset);
+ }
+
+ log_fatal("Unhandled Load8 At Address %08X", addr);
+ exit(EXIT_FAILURE);
}
u16
INTER_load16(Interconnect* inter, u32 addr)
{
- u32 offset;
- u32 abs_addr;
- u32 contains;
+ u32 offset;
+ u32 abs_addr;
+ u32 contains;
+
+ offset = 0;
+ contains = 0;
+ abs_addr = mask_region(addr);
+
+ if (addr % 2 != 0)
+ {
+ log_fatal("Unaligned_load16_abs_address: %08X", abs_addr);
+ exit(EXIT_FAILURE);
+ }
+
+ /* Assert abs_address Mappings */
+ contains = UTIL_contains(SPU_START, SPU_SIZE, abs_addr, &offset);
+ if (contains)
+ {
+ log_warn("Unhandled read from SPU register: %08X", offset);
+ return 0;
+ }
- offset = 0;
- contains = 0;
- abs_addr = mask_region(addr);
+ contains = UTIL_contains(RAM_START, RAM_SIZE, abs_addr, &offset);
+ if (contains)
+ return RAM_load16(inter->ram, offset);
- if (addr % 2 != 0)
- {
- fprintf(stderr, "Unaligned_load16_abs_address: %08X\n", abs_addr);
+ contains = UTIL_contains(IRQ_CONTROL_START, IRQ_CONTROL_SIZE, abs_addr, &offset);
+ if (contains)
+ {
+ log_debug("IRQ CONTROL read %08X", offset);
+ return 0;
+ }
+
+ log_fatal("Unhandled Load16 At Address %08X", abs_addr);
exit(EXIT_FAILURE);
- }
-
- /* Assert abs_address Mappings */
- contains = UTIL_contains(SPU_START, SPU_SIZE, abs_addr, &offset);
- if (contains)
- {
-#ifndef DEBUG
- fprintf(stderr, "Unhandled read from SPU register: %08X\n", offset);
-#endif
- return 0;
- }
-
- contains = UTIL_contains(RAM_START, RAM_SIZE, abs_addr, &offset);
- if (contains)
- return RAM_load16(inter->ram, offset);
-
- contains = UTIL_contains(IRQ_CONTROL_START, IRQ_CONTROL_SIZE, abs_addr, &offset);
- if (contains)
- {
-#ifndef DEBUG
- printf("IRQ CONTROL read %08X\n", offset);
-#endif
- return 0;
- }
-
- fprintf(stderr, "Unhandled Load16 At Address %08X\n", abs_addr);
- exit(EXIT_FAILURE);
}
- u32
+u32
INTER_load32(Interconnect* inter, u32 addr)
{
- u32 offset;
- u32 abs_addr;
- u32 contains;
+ u32 offset;
+ u32 abs_addr;
+ u32 contains;
- offset = 0;
- contains = 0;
- abs_addr = mask_region(addr);
+ offset = 0;
+ contains = 0;
+ abs_addr = mask_region(addr);
- if (addr % 4 != 0)
- {
- fprintf(stderr, "Unaligned_load32_abs_address: %08X\n", abs_addr);
- exit(EXIT_FAILURE);
- }
-
- /* Assert abs_address Mappings */
- contains = UTIL_contains(BIOS_START, BIOS_SIZE, abs_addr, &offset);
- if (contains)
- return BIOS_load32(inter->bios, offset);
-
- contains = UTIL_contains(RAM_START, RAM_SIZE, abs_addr, &offset);
- if (contains)
- return RAM_load32(inter->ram, offset);
-
- contains = UTIL_contains(IRQ_CONTROL_START, IRQ_CONTROL_SIZE, abs_addr, &offset);
- if (contains)
- {
-#ifndef DEBUG
- printf("IRQ CONTROL read %08X\n", offset);
-#endif
- return 0;
- }
-
- contains = UTIL_contains(TIMERS_START, TIMERS_SIZE, abs_addr, &offset);
- if (contains)
- {
-#ifndef DEBUG
- printf("TIMERS read %08X\n", offset);
-#endif
- return 0;
- }
-
- contains = UTIL_contains(DMA_START, DMA_SIZE, abs_addr, &offset);
- if (contains)
- {
- return INTER_dma_reg(inter, offset);
- }
-
- contains = UTIL_contains(GPU_START, GPU_SIZE, abs_addr, &offset);
- if (contains)
- {
-
- LOG(LOG_DEBUG, "GPU read %08X\n", abs_addr);
-
- switch(offset)
+ if (addr % 4 != 0)
+ {
+ log_fatal("Unaligned_load32_abs_address: %08X", abs_addr);
+ exit(EXIT_FAILURE);
+ }
+
+ /* Assert abs_address Mappings */
+ contains = UTIL_contains(BIOS_START, BIOS_SIZE, abs_addr, &offset);
+ if (contains)
+ return BIOS_load32(inter->bios, offset);
+
+ contains = UTIL_contains(RAM_START, RAM_SIZE, abs_addr, &offset);
+ if (contains)
+ return RAM_load32(inter->ram, offset);
+
+ contains = UTIL_contains(IRQ_CONTROL_START, IRQ_CONTROL_SIZE, abs_addr, &offset);
+ if (contains)
+ {
+ log_debug("IRQ CONTROL read %08X", offset);
+ return 0;
+ }
+
+ contains = UTIL_contains(TIMERS_START, TIMERS_SIZE, abs_addr, &offset);
+ if (contains)
+ {
+ log_debug("TIMERS read %08X", offset);
+ return 0;
+ }
+
+ contains = UTIL_contains(DMA_START, DMA_SIZE, abs_addr, &offset);
+ if (contains)
+ {
+ return INTER_dma_reg(inter, offset);
+ }
+
+ contains = UTIL_contains(GPU_START, GPU_SIZE, abs_addr, &offset);
+ if (contains)
{
- case 0: return GPU_read(inter->gpu); /* NOT COMPLETE */
- case 4: return GPU_status(inter->gpu);
- default: return 0;
+
+ log_debug("GPU read %08X", abs_addr);
+ switch(offset)
+ {
+ case 0: return GPU_read(inter->gpu); /* NOT COMPLETE */
+ case 4: return GPU_status(inter->gpu);
+ default: return 0;
+ }
}
- }
- fprintf(stderr, "Unhandled Load32 At Address %08X\n", addr);
- exit(EXIT_FAILURE);
+ log_fatal("Unhandled Load32 At Address %08X", addr);
+ exit(EXIT_FAILURE);
}
void
INTER_store8(Interconnect* inter, u32 addr, u8 val)
{
- u32 offset;
- u32 contains;
- u32 abs_addr;
-
- offset = 0;
- contains = 0;
- abs_addr = mask_region(addr);
-
- contains = UTIL_contains(EXPANSION2_START, EXPANSION2_SIZE, abs_addr, &offset);
- if (contains)
- {
-#ifndef DEBUG
- fprintf(stdout, "Ignoring write to EXPANSION2 register at: %08X\n", abs_addr);
-#endif
- return;
- }
-
- contains = UTIL_contains(RAM_START, RAM_SIZE, abs_addr, &offset);
- if (contains)
- {
- RAM_store8(inter->ram, offset, val);
- return;
- }
-
- contains = UTIL_contains(CDROM_START, CDROM_SIZE, abs_addr, &offset);
- if (contains)
- {
- cdrom_write(inter->cdrom, offset, val);
- return;
- }
-
- fprintf(stderr, "Unhandled Store8 At Address %08X\n", abs_addr);
- exit(EXIT_FAILURE);
+ u32 offset;
+ u32 contains;
+ u32 abs_addr;
+
+ offset = 0;
+ contains = 0;
+ abs_addr = mask_region(addr);
+
+ contains = UTIL_contains(EXPANSION2_START, EXPANSION2_SIZE, abs_addr, &offset);
+ if (contains)
+ {
+ log_debug("Ignoring write to EXPANSION2 register at: %08X", abs_addr);
+ return;
+ }
+
+ contains = UTIL_contains(RAM_START, RAM_SIZE, abs_addr, &offset);
+ if (contains)
+ {
+ RAM_store8(inter->ram, offset, val);
+ return;
+ }
+
+ contains = UTIL_contains(CDROM_START, CDROM_SIZE, abs_addr, &offset);
+ if (contains)
+ {
+ cdrom_write(inter->cdrom, offset, val);
+ return;
+ }
+
+ log_fatal("Unhandled Store8 At Address %08X", abs_addr);
+ exit(EXIT_FAILURE);
}
- void
+void
INTER_store16(Interconnect* inter, u32 addr, u16 val)
{
- u32 offset;
- u32 contains;
- u32 abs_addr;
+ u32 offset;
+ u32 contains;
+ u32 abs_addr;
+
+ offset = 0;
+ contains = 0;
+ abs_addr = mask_region(addr);
+
+ if (addr % 2 != 0)
+ {
+ log_fatal("Unaligned_store16_address: %08X", addr);
+ exit(EXIT_FAILURE);
+ }
+
+ contains = UTIL_contains(SPU_START, SPU_SIZE, abs_addr, &offset);
+ if (contains)
+ {
+ log_debug("Ignoring SPU register write: %X", abs_addr);
+ return;
+ }
- offset = 0;
- contains = 0;
- abs_addr = mask_region(addr);
+ contains = UTIL_contains(TIMERS_START, TIMERS_SIZE, abs_addr, &offset);
+ if (contains)
+ {
+ log_debug("Ignoring TIMER register write to offset: %X", offset);
+ return;
+ }
+
+ contains = UTIL_contains(RAM_START, RAM_SIZE, abs_addr, &offset);
+ if (contains)
+ {
+ RAM_store16(inter->ram, offset, val);
+ return;
+ }
- if (addr % 2 != 0)
- {
- fprintf(stderr, "Unaligned_store16_address: %08X", addr);
+ contains = UTIL_contains(IRQ_CONTROL_START, IRQ_CONTROL_SIZE, abs_addr, &offset);
+ if (contains)
+ {
+ log_debug("IRQ control write %08X at address %08X", val, offset);
+ return;
+ }
+
+ log_fatal("Unhandled Store16 At Address %08X", abs_addr);
exit(EXIT_FAILURE);
- }
-
- contains = UTIL_contains(SPU_START, SPU_SIZE, abs_addr, &offset);
- if (contains)
- {
-#ifndef DEBUG
- fprintf(stdout, "Ignoring SPU register write: %X\n", abs_addr);
-#endif
- return;
- }
-
- contains = UTIL_contains(TIMERS_START, TIMERS_SIZE, abs_addr, &offset);
- if (contains)
- {
-#ifndef DEBUG
- fprintf(stdout, "Ignoring TIMER register write to offset: %X\n", offset);
-#endif
- return;
- }
-
- contains = UTIL_contains(RAM_START, RAM_SIZE, abs_addr, &offset);
- if (contains)
- {
- RAM_store16(inter->ram, offset, val);
- return;
- }
-
- contains = UTIL_contains(IRQ_CONTROL_START, IRQ_CONTROL_SIZE, abs_addr, &offset);
- if (contains)
- {
-#ifndef DEBUG
- printf("IRQ control write %08X at address %08X\n", val, offset);
-#endif
- return;
- }
-
- fprintf(stderr, "Unhandled Store16 At Address %08X\n", abs_addr);
- exit(EXIT_FAILURE);
}
void
INTER_store32(Interconnect* inter, u32 addr, u32 val)
{
- u32 offset;
- u32 contains;
- u32 abs_addr;
-
- offset = 0;
- contains = 0;
- abs_addr = mask_region(addr);
-
- if (addr % 4 != 0) {
-#ifndef DEBUG
- fprintf(stderr, "Unaligned_store32_address: %08X", addr);
-#endif
- }
-
- contains = UTIL_contains(RAM_START, RAM_SIZE, abs_addr, &offset);
- if (contains)
- {
- RAM_store32(inter->ram, offset, val);
- return;
- }
-
- contains = UTIL_contains(RAM_SIZE_START, RAM_SIZE_SIZE, abs_addr, &offset);
- if (contains)
- {
-#ifndef DEBUG
- fprintf(stdout, "Ignoring RAM_SIZE register write %X\n", abs_addr);
-#endif
- return;
- }
-
- contains = UTIL_contains(CACHECONTROL_START, CACHECONTROL_SIZE, abs_addr, &offset);
- if (contains)
- {
-#ifndef DEBUG
- fprintf(stdout, "Ignoring CACHECONTROL abs_address write: %X\n", abs_addr);
-#endif
- return;
- }
-
- contains = UTIL_contains(IRQ_CONTROL_START, IRQ_CONTROL_SIZE, abs_addr, &offset);
- if (contains)
- {
-#ifndef DEBUG
- fprintf(stdout, "Ignoring IRQ CONTROL write %08X to address %08X\n", val, offset);
-#endif
- return;
- }
-
- contains = UTIL_contains(DMA_START, DMA_SIZE, abs_addr, &offset);
- if (contains)
- {
- INTER_set_dma_reg(inter, offset, val);
- return;
- }
-
- contains = UTIL_contains(TIMERS_START, TIMERS_SIZE, abs_addr, &offset);
- if (contains)
- {
-#ifndef DEBUG
- fprintf(stdout, "TIMER register write %08X to offset: %08X\n", val, offset);
-#endif
- return;
- }
-
- contains = UTIL_contains(GPU_START, GPU_SIZE, abs_addr, &offset);
- if (contains)
- {
- LOG(LOG_DEBUG, "GPU write %08X to address %08X\n", val, offset);
- switch (offset) {
- case 0: GPU_gp0(inter->gpu, val); break;
- case 4: GPU_gp1(inter->gpu, val); break;
- default: fprintf(stderr, "GPU write %08X: %08X", offset, val); exit(EXIT_FAILURE);
- }
-
- return;
- }
-
- contains = UTIL_contains(SYSCONTROL_START, SYSCONTROL_SIZE, abs_addr, &offset);
- if (contains)
- {
- switch(offset) {
- case 0:
- if (val != 0x1F000000) {
- fprintf(stderr, "Bad Expansion 1 base abs_address: %08X", val);
- exit(EXIT_FAILURE);
+ u32 offset;
+ u32 contains;
+ u32 abs_addr;
+
+ offset = 0;
+ contains = 0;
+ abs_addr = mask_region(addr);
+
+ if (addr % 4 != 0)
+ log_warn("Unaligned_store32_address: %08X", addr);
+
+ contains = UTIL_contains(RAM_START, RAM_SIZE, abs_addr, &offset);
+ if (contains) {
+ RAM_store32(inter->ram, offset, val);
+ return;
+ }
+
+ contains = UTIL_contains(RAM_SIZE_START, RAM_SIZE_SIZE, abs_addr, &offset);
+ if (contains)
+ {
+ log_debug("Ignoring RAM_SIZE register write %X", abs_addr);
+ return;
+ }
+
+ contains = UTIL_contains(CACHECONTROL_START, CACHECONTROL_SIZE, abs_addr, &offset);
+ if (contains)
+ {
+ log_debug("Ignoring CACHECONTROL abs_address write: %X", abs_addr);
+ return;
+ }
+
+ contains = UTIL_contains(IRQ_CONTROL_START, IRQ_CONTROL_SIZE, abs_addr, &offset);
+ if (contains)
+ {
+ log_debug("Ignoring IRQ CONTROL write %08X to address %08X", val, offset);
+ return;
+ }
+
+ contains = UTIL_contains(DMA_START, DMA_SIZE, abs_addr, &offset);
+ if (contains)
+ {
+ INTER_set_dma_reg(inter, offset, val);
+ return;
+ }
+
+ contains = UTIL_contains(TIMERS_START, TIMERS_SIZE, abs_addr, &offset);
+ if (contains)
+ {
+ log_debug("TIMER register write %08X to offset: %08X", val, offset);
+ return;
+ }
+
+ contains = UTIL_contains(GPU_START, GPU_SIZE, abs_addr, &offset);
+ if (contains)
+ {
+ log_debug("GPU write %08X to address %08X", val, offset);
+ switch (offset) {
+ case 0: GPU_gp0(inter->gpu, val); break;
+ case 4: GPU_gp1(inter->gpu, val); break;
+ default: log_fatal("GPU write %08X: %08X", offset, val); exit(EXIT_FAILURE);
}
- break;
- case 4:
- if (val != 0x1F802000) {
- fprintf(stderr, "Bad expansion 2 base abs_address: %08X", val);
- exit(EXIT_FAILURE);
+
+ return;
+ }
+
+ contains = UTIL_contains(SYSCONTROL_START, SYSCONTROL_SIZE, abs_addr, &offset);
+ if (contains)
+ {
+ switch(offset) {
+ case 0:
+ if (val != 0x1F000000) {
+ log_fatal("Bad Expansion 1 base abs_address: %08X", val);
+ exit(EXIT_FAILURE);
+ }
+ break;
+ case 4:
+ if (val != 0x1F802000) {
+ log_fatal("Bad expansion 2 base abs_address: %08X", val);
+ exit(EXIT_FAILURE);
+ }
+ break;
+ default:
+ log_warn("Unhandled write to SYSCONTROL register");
+ return;
}
- break;
- default:
-#ifndef DEBUG
- fprintf(stderr, "Unhandled write to SYSCONTROL register\n");
-#endif
return;
}
- return;
- }
- fprintf(stderr, "Unhandled Store32 At Address %08X\n", addr);
- exit(EXIT_FAILURE);
+ log_fatal("Unhandled Store32 At Address %08X", addr);
+ exit(EXIT_FAILURE);
}
u32
INTER_dma_reg(Interconnect* inter, u32 offset)
{
- u32 major, minor, val;
- Channel* channel;
- major = (offset & 0x70) >> 4;
- minor = offset & 0xf;
-
- switch (major) {
- case 0: case 1: case 2: case 3: case 4: case 5: case 6:
-
- channel = &inter->dma->channels[(Port)major];
- switch (minor) {
- case 0: val = CHANNEL_base(channel); break;
- case 4: val = CHANNEL_block_control(channel); break;
- case 8: val = CHANNEL_control(channel); break;
- default: fprintf(stderr, "Unhandled DMA read at %08X\n", offset); exit(EXIT_FAILURE);
- }
- break;
- case 7:
- switch (minor) {
- case 0: val = DMA_control(inter->dma); break;
- case 4: val = DMA_interrupt(inter->dma); break;
- default: fprintf(stderr, "unhandled DMA access %08X\n", offset); exit(EXIT_FAILURE);
- }
- break;
- default: fprintf(stderr, "unhandled DMA access %08X\n", offset); exit(EXIT_FAILURE);
- }
-
- return val;
+ u32 major, minor, val;
+ Channel* channel;
+ major = (offset & 0x70) >> 4;
+ minor = offset & 0xf;
+
+ switch (major) {
+ case 0: case 1: case 2: case 3: case 4: case 5: case 6:
+
+ channel = &inter->dma->channels[(Port)major];
+ switch (minor) {
+ case 0: val = CHANNEL_base(channel); break;
+ case 4: val = CHANNEL_block_control(channel); break;
+ case 8: val = CHANNEL_control(channel); break;
+ default: log_fatal("Unhandled DMA read at %08X", offset); exit(EXIT_FAILURE);
+ }
+ break;
+ case 7:
+ switch (minor) {
+ case 0: val = DMA_control(inter->dma); break;
+ case 4: val = DMA_interrupt(inter->dma); break;
+ default: log_fatal("Unhandled DMA access %08X", offset); exit(EXIT_FAILURE);
+ }
+ break;
+ default: log_fatal("Unhandled DMA access %08X", offset); exit(EXIT_FAILURE);
+ }
+
+ return val;
}
- void
+void
INTER_set_dma_reg(Interconnect* inter, u32 offset, u32 val)
{
- u32 major, minor;
- Channel* channel;
- Port port, active_port;
- major = (offset & 0x70) >> 4;
- minor = offset & 0xf;
- active_port = PORT_INVALID;
-
- switch (major) {
- case 0: case 1: case 2: case 3: case 4: case 5: case 6:
-
- port = (Port)major;
- channel = &inter->dma->channels[port];
-
- switch (minor) {
- case 0: CHANNEL_set_base(channel, val); break;
- case 4: CHANNEL_set_block_control(channel, val); break;
- case 8: CHANNEL_set_control(channel, val); break;
- default: fprintf(stderr, "Unhandled DMA write at %08X\n", offset); exit(EXIT_FAILURE);
- }
- if (CHANNEL_active(channel)) {
- active_port = port;
- } else {
- active_port = PORT_INVALID;
- }
- break;
- case 7:
- switch (minor) {
- case 0: DMA_set_control(inter->dma, val); break;
- case 4: DMA_set_interrupt(inter->dma, val); break;
- default: active_port = PORT_INVALID; break;/* fprintf(stderr, "unhandled DMA write %08X\n", offset); exit(EXIT_FAILURE); */
- }
- break;
- default: fprintf(stderr, "unhandled DMA write %08X\n", offset); exit(EXIT_FAILURE);
- }
-
- if (active_port != PORT_INVALID)
- INTER_do_dma(inter, (Port)active_port);
+ u32 major, minor;
+ Channel* channel;
+ Port port, active_port;
+ major = (offset & 0x70) >> 4;
+ minor = offset & 0xf;
+ active_port = PORT_INVALID;
+
+ switch (major) {
+ case 0: case 1: case 2: case 3: case 4: case 5: case 6:
+
+ port = (Port)major;
+ channel = &inter->dma->channels[port];
+
+ switch (minor) {
+ case 0: CHANNEL_set_base(channel, val); break;
+ case 4: CHANNEL_set_block_control(channel, val); break;
+ case 8: CHANNEL_set_control(channel, val); break;
+ default: log_fatal("Unhandled DMA write at %08X", offset); exit(EXIT_FAILURE);
+ }
+ if (CHANNEL_active(channel)) {
+ active_port = port;
+ } else {
+ active_port = PORT_INVALID;
+ }
+ break;
+ case 7:
+ switch (minor) {
+ case 0: DMA_set_control(inter->dma, val); break;
+ case 4: DMA_set_interrupt(inter->dma, val); break;
+ default: active_port = PORT_INVALID; break;/* fprintf(stderr, "unhandled DMA write %08X\n", offset); exit(EXIT_FAILURE); */
+ }
+ break;
+ default: log_fatal("unhandled DMA write %08X", offset); exit(EXIT_FAILURE);
+ }
+
+ if (active_port != PORT_INVALID)
+ INTER_do_dma(inter, (Port)active_port);
}
- void
+void
INTER_do_dma(Interconnect* inter, Port port)
{
- Channel* ch;
- if (port == PORT_INVALID) {
- printf("%d\n", port);
- fprintf(stderr, "Invalid port doing dma\n");
- exit(EXIT_FAILURE);
- }
+ Channel* ch;
+ if (port == PORT_INVALID) {
+ log_fatal("Invalid port doing dma");
+ exit(EXIT_FAILURE);
+ }
- ch = &inter->dma->channels[(Port)port];
+ ch = &inter->dma->channels[(Port)port];
- switch (ch->sync) {
- case SYNC_LINKED_LIST: INTER_do_dma_linked_list(inter, port); break;
- default: INTER_do_dma_block(inter, port); break;
- }
+ switch (ch->sync) {
+ case SYNC_LINKED_LIST: INTER_do_dma_linked_list(inter, port); break;
+ default: INTER_do_dma_block(inter, port); break;
+ }
}
-void
+ void
INTER_do_dma_block(Interconnect* inter, Port port)
{
- Channel *ch;
- u32 addr;
- u32 increment;
- u32 src_word;
- u32 remsz;
-
- ch = &inter->dma->channels[port];
- remsz = 0;
+ Channel *ch;
+ u32 addr;
+ u32 increment;
+ u32 src_word;
+ u32 remsz;
+
+ ch = &inter->dma->channels[port];
+ remsz = 0;
+
+ switch (ch->step) {
+ case STEP_INCREMENT: increment = 4; break;
+ case STEP_DECREMENT: increment = -4; break;
+ default: log_fatal("Unreachable!"); exit(EXIT_FAILURE);
+ }
- switch (ch->step) {
- case STEP_INCREMENT: increment = 4; break;
- case STEP_DECREMENT: increment = -4; break;
- default: fprintf(stderr, "Unreachable!\n"); exit(EXIT_FAILURE);
- }
+ addr = ch->base;
- addr = ch->base;
+ /* printf("%d\n", port);
+ / printf("%08X %08X %d\n", ch->block_size, ch->block_count, (Port)ch->step); */
- /* printf("%d\n", port);
- / printf("%08X %08X %d\n", ch->block_size, ch->block_count, (Port)ch->step); */
+ if (!CHANNEL_transfer_size(ch, &remsz)) {
+ log_fatal("Couldn't figure out DMA block transfer size");
+ exit(EXIT_FAILURE);
+ }
- if (!CHANNEL_transfer_size(ch, &remsz)) {
- fprintf(stderr, "Couldn't figure out DMA block transfer size\n");
- exit(EXIT_FAILURE);
- }
-
- while (remsz > 0) {
- u32 cur_addr;
- cur_addr = addr & 0x1ffffc;
-
- switch (ch->direction) {
- case DIR_FROM_RAM:
- src_word = RAM_load32(inter->ram, cur_addr);
- switch(port) {
- case PORT_GPU:
- GPU_gp0(inter->gpu, src_word);
-#ifndef DEBUG
- printf("GPU data %08X\n", src_word);
-#endif
- break;
- default:
- fprintf(stderr, "Unhandled DMA destination port: %d", (u8)port);
- exit(EXIT_FAILURE);
- }
- break;
- case DIR_TO_RAM:
- switch(port) {
- case PORT_OTC:
- if (remsz == 1) {
- src_word = 0xffffff;
- } else {
- src_word = (addr - 4) & 0x1fffff;
- }
- break;
- default:
- fprintf(stderr, "Unhandled DMA source port: %d", (u8)port);
- exit(EXIT_FAILURE);
+ while (remsz > 0) {
+ u32 cur_addr;
+ cur_addr = addr & 0x1ffffc;
+
+ switch (ch->direction) {
+ case DIR_FROM_RAM:
+ src_word = RAM_load32(inter->ram, cur_addr);
+ switch(port) {
+ case PORT_GPU:
+ GPU_gp0(inter->gpu, src_word);
+ log_debug("GPU data %08X", src_word);
+ break;
+ default:
+ log_fatal("Unhandled DMA destination port: %d", (u8)port);
+ exit(EXIT_FAILURE);
+ }
+ break;
+ case DIR_TO_RAM:
+ switch(port) {
+ case PORT_OTC:
+ if (remsz == 1) {
+ src_word = 0xffffff;
+ } else {
+ src_word = (addr - 4) & 0x1fffff;
+ }
+ break;
+ default:
+ log_fatal("Unhandled DMA source port: %d", (u8)port);
+ exit(EXIT_FAILURE);
+ }
+ RAM_store32(inter->ram, cur_addr, src_word);
+ break;
+ default: break;
}
- RAM_store32(inter->ram, cur_addr, src_word);
- break;
- default: break;
- }
- addr += increment;
- remsz--;
- }
- CHANNEL_done(ch);
+ addr += increment;
+ remsz--;
+ }
+ CHANNEL_done(ch);
}
-void
+ void
INTER_do_dma_linked_list(Interconnect* inter, Port port)
{
- Channel *ch;
- u32 addr, header, remsz, command;
+ Channel *ch;
+ u32 addr, header, remsz, command;
- ch = &inter->dma->channels[port];
- addr = ch->base & 0x1ffffc;
+ ch = &inter->dma->channels[port];
+ addr = ch->base & 0x1ffffc;
- if (ch->direction == DIR_TO_RAM) {
- fprintf(stderr, "Invalid DMA direction for linked list mode\n");
- exit(EXIT_FAILURE);
- }
+ if (ch->direction == DIR_TO_RAM) {
+ log_fatal("Invalid DMA direction for linked list mode");
+ exit(EXIT_FAILURE);
+ }
- if (port != PORT_GPU) {
- fprintf(stderr, "Attempted linked list DMA on port %d\n", (u8)port);
- exit(EXIT_FAILURE);
- }
+ if (port != PORT_GPU) {
+ log_fatal("Attempted linked list DMA on port %d", (u8)port);
+ exit(EXIT_FAILURE);
+ }
- while (1) {
- header = RAM_load32(inter->ram, addr);
- remsz = header >> 24;
+ while (1) {
+ header = RAM_load32(inter->ram, addr);
+ remsz = header >> 24;
- while (remsz > 0) {
- addr = (addr + 4) & 0x1ffffc;
- command = RAM_load32(inter->ram, addr);
- GPU_gp0(inter->gpu, command);
-#ifndef DEBUG
- printf("GPU command %08X\n", command);
-#endif
- remsz--;
- }
+ while (remsz > 0) {
+ addr = (addr + 4) & 0x1ffffc;
+ command = RAM_load32(inter->ram, addr);
+ GPU_gp0(inter->gpu, command);
+ log_debug("GPU command %08X", command);
+ remsz--;
+ }
- if ((header & 0x800000) != 0)
- break;
+ if ((header & 0x800000) != 0)
+ break;
- addr = header & 0x1ffffc;
+ addr = header & 0x1ffffc;
- }
- CHANNEL_done(ch);
+ }
+ CHANNEL_done(ch);
}
diff --git a/src/irq.h b/src/irq.h
@@ -18,7 +18,7 @@ enum {
IRQ_TIMER_2 = 6,
IRQ_SIO = 7,
IRQ_SPU = 9,
- IRQ_PIO = 10,
+ IRQ_PIO = 10
};
enum
diff --git a/src/log.c b/src/log.c
@@ -0,0 +1,168 @@
+/*
+ * Copyright (c) 2020 rxi
+ *
+ * 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.
+ */
+
+#include "log.h"
+
+#define MAX_CALLBACKS 32
+
+typedef struct {
+ log_LogFn fn;
+ void *udata;
+ int level;
+} Callback;
+
+static struct {
+ void *udata;
+ log_LockFn lock;
+ int level;
+ bool quiet;
+ Callback callbacks[MAX_CALLBACKS];
+} L;
+
+
+static const char *level_strings[] = {
+ "TRACE", "DEBUG", "INFO", "WARN", "ERROR", "FATAL"
+};
+
+#ifdef LOG_USE_COLOR
+static const char *level_colors[] = {
+ "\x1b[94m", "\x1b[36m", "\x1b[32m", "\x1b[33m", "\x1b[31m", "\x1b[35m"
+};
+#endif
+
+
+static void stdout_callback(log_Event *ev) {
+ char buf[16];
+ buf[strftime(buf, sizeof(buf), "%H:%M:%S", ev->time)] = '\0';
+#ifdef LOG_USE_COLOR
+ fprintf(
+ ev->udata, "%s %s%-5s\x1b[0m \x1b[90m%s:%d:\x1b[0m ",
+ buf, level_colors[ev->level], level_strings[ev->level],
+ ev->file, ev->line);
+#else
+ fprintf(
+ ev->udata, "%s %-5s %s:%d: ",
+ buf, level_strings[ev->level], ev->file, ev->line);
+#endif
+ vfprintf(ev->udata, ev->fmt, ev->ap);
+ fprintf(ev->udata, "\n");
+ fflush(ev->udata);
+}
+
+
+static void file_callback(log_Event *ev) {
+ char buf[64];
+ buf[strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", ev->time)] = '\0';
+ fprintf(
+ ev->udata, "%s %-5s %s:%d: ",
+ buf, level_strings[ev->level], ev->file, ev->line);
+ vfprintf(ev->udata, ev->fmt, ev->ap);
+ fprintf(ev->udata, "\n");
+ fflush(ev->udata);
+}
+
+
+static void lock(void) {
+ if (L.lock) { L.lock(true, L.udata); }
+}
+
+
+static void unlock(void) {
+ if (L.lock) { L.lock(false, L.udata); }
+}
+
+
+const char* log_level_string(int level) {
+ return level_strings[level];
+}
+
+
+void log_set_lock(log_LockFn fn, void *udata) {
+ L.lock = fn;
+ L.udata = udata;
+}
+
+
+void log_set_level(int level) {
+ L.level = level;
+}
+
+
+void log_set_quiet(bool enable) {
+ L.quiet = enable;
+}
+
+
+int log_add_callback(log_LogFn fn, void *udata, int level) {
+ for (int i = 0; i < MAX_CALLBACKS; i++) {
+ if (!L.callbacks[i].fn) {
+ L.callbacks[i] = (Callback) { fn, udata, level };
+ return 0;
+ }
+ }
+ return -1;
+}
+
+
+int log_add_fp(FILE *fp, int level) {
+ return log_add_callback(file_callback, fp, level);
+}
+
+
+static void init_event(log_Event *ev, void *udata) {
+ if (!ev->time) {
+ time_t t = time(NULL);
+ ev->time = localtime(&t);
+ }
+ ev->udata = udata;
+}
+
+
+void log_log(int level, const char *file, int line, const char *fmt, ...) {
+ log_Event ev = {
+ .fmt = fmt,
+ .file = file,
+ .line = line,
+ .level = level,
+ };
+
+ lock();
+
+ if (!L.quiet && level >= L.level) {
+ init_event(&ev, stderr);
+ va_start(ev.ap, fmt);
+ stdout_callback(&ev);
+ va_end(ev.ap);
+ }
+
+ for (int i = 0; i < MAX_CALLBACKS && L.callbacks[i].fn; i++) {
+ Callback *cb = &L.callbacks[i];
+ if (level >= cb->level) {
+ init_event(&ev, cb->udata);
+ va_start(ev.ap, fmt);
+ cb->fn(&ev);
+ va_end(ev.ap);
+ }
+ }
+
+ unlock();
+}
diff --git a/src/log.h b/src/log.h
@@ -0,0 +1,49 @@
+/**
+ * Copyright (c) 2020 rxi
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MIT license. See `log.c` for details.
+ */
+
+#ifndef LOG_H
+#define LOG_H
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdbool.h>
+#include <time.h>
+
+#define LOG_VERSION "0.1.0"
+
+typedef struct {
+ va_list ap;
+ const char *fmt;
+ const char *file;
+ struct tm *time;
+ void *udata;
+ int line;
+ int level;
+} log_Event;
+
+typedef void (*log_LogFn)(log_Event *ev);
+typedef void (*log_LockFn)(bool lock, void *udata);
+
+enum { LOG_TRACE, LOG_DEBUG, LOG_INFO, LOG_WARN, LOG_ERROR, LOG_FATAL };
+
+#define log_trace(...) log_log(LOG_TRACE, __FILE__, __LINE__, __VA_ARGS__)
+#define log_debug(...) log_log(LOG_DEBUG, __FILE__, __LINE__, __VA_ARGS__)
+#define log_info(...) log_log(LOG_INFO, __FILE__, __LINE__, __VA_ARGS__)
+#define log_warn(...) log_log(LOG_WARN, __FILE__, __LINE__, __VA_ARGS__)
+#define log_error(...) log_log(LOG_ERROR, __FILE__, __LINE__, __VA_ARGS__)
+#define log_fatal(...) log_log(LOG_FATAL, __FILE__, __LINE__, __VA_ARGS__)
+
+const char* log_level_string(int level);
+void log_set_lock(log_LockFn fn, void *udata);
+void log_set_level(int level);
+void log_set_quiet(bool enable);
+int log_add_callback(log_LogFn fn, void *udata, int level);
+int log_add_fp(FILE *fp, int level);
+
+void log_log(int level, const char *file, int line, const char *fmt, ...);
+
+#endif
diff --git a/src/main.c b/src/main.c
@@ -1,5 +1,6 @@
#include <stdlib.h>
-#include <SDL2/SDL.h>
+#include <unistd.h>
+#include <ncurses.h>
#include "cpu.h"
#include "interconnect.h"
@@ -7,65 +8,61 @@
#include "mem.h"
#include "gpu.h"
#include "sr.h"
-#include "MiniFB.h"
+#include "log.h"
+
+#include <SDL2/SDL.h>
SDL_Event ev;
Interconnect *inter;
+CPU *cpu;
+FILE *fp_debug;
-int WINDOW_STATE;
-
-void
-keyboard(struct mfb_window *window, mfb_key key, mfb_key_mod mod, bool isPressed)
+static void
+frame(void)
{
- if (key == KB_KEY_ESCAPE)
- exit(EXIT_FAILURE);
- if (key == KB_KEY_A)
- fprintf(stderr, "The value of OFFSET is: %08X", inter->cdrom->status & 3);
+ int c;
+
+ for (c = 0; c < 1e5; c++) CPU_run_next_instruction(cpu);
+
+ while(SDL_PollEvent(&ev) != 0) {
+ switch(ev.type) {
+ case SDL_QUIT:
+ SDL_Quit();
+ exit(1);
+ case SDL_KEYDOWN:
+ if (ev.key.keysym.sym == SDLK_q) {
+ SDL_Quit();
+ exit(1);
+ }
+ }
+ }
}
-int
-main(int argc, char **argv)
+void
+init(void)
{
- int c;
REN *ren;
- CPU *cpu;
- //lua_State *L = luaL_newstate();
- //luaL_openlibs(L);
+ SDL_Init(SDL_INIT_VIDEO);
- //SDL_Init(SDL_INIT_VIDEO);
- //SDL_SetRenderDrawColor(ren->renderer, 0xff, 0xff, 0xff, 0xff);
- //SDL_RenderClear(ren->renderer);
- //SDL_RenderPresent(ren->renderer);
+ /* Logging */
+ log_set_quiet(1);
+ fp_debug = fopen("log_debug.txt", "w+");
+ log_add_fp(fp_debug, LOG_DEBUG);
inter = new_interconnect();
cpu = new_cpu(inter);
ren = inter->gpu->ren;
- mfb_set_keyboard_callback(inter->gpu->ren->window, keyboard);
+ SDL_SetRenderDrawColor(ren->renderer, 0xff, 0xff, 0xff, 0xff);
+ SDL_RenderClear(ren->renderer);
+ SDL_RenderPresent(ren->renderer);
- while(1) {
- //while(mfb_wait_sync(inter->gpu->ren->window)) {
- /* Because it's too slow to run events every instr */
- for (c = 0; c < 1e5; c++) CPU_run_next_instruction(cpu);
-
- if (WINDOW_STATE < 0)
- break;
-
-
- //while(SDL_PollEvent(&ev) != 0) {
- // switch(ev.type) {
- // case SDL_QUIT:
- // SDL_Quit();
- // exit(1);
- // case SDL_KEYDOWN:
- // if (ev.key.keysym.sym == SDLK_q) {
- // SDL_Quit();
- // exit(1);
- // }
- // }
- //}
- }
+}
+
+void
+kill(void)
+{
free(inter->bios->data);
free(inter->bios);
@@ -76,10 +73,22 @@ main(int argc, char **argv)
free(inter->cdrom);
free(inter);
free(cpu);
+ fclose(fp_debug);
+
+ SDL_Quit();
+}
+
+int
+main(void)
+{
+
+ init();
- //lua_close(L);
+ while(1) {
+ frame();
+ }
- //SDL_Quit();
+ kill();
return 0;
}
diff --git a/src/mem.c b/src/mem.c
@@ -4,6 +4,7 @@
#include "mem.h"
#include "types.h"
#include "util.h"
+#include "log.h"
Channel*
CHANNEL_new(void)
@@ -111,7 +112,7 @@ CHANNEL_transfer_size(Channel* ch, u32 *res)
*res = (u32)((u32)ch->block_size * (u32)(ch->block_count));
return 1;
case SYNC_LINKED_LIST: return 0;
- default: fprintf(stderr, "UNREACHABLE"); exit(EXIT_FAILURE);
+ default: log_fatal("UNREACHABLE"); exit(EXIT_FAILURE);
}
}
diff --git a/src/sr.c b/src/sr.c
@@ -7,9 +7,7 @@
#include "types.h"
#include "sr.h"
-#include "defs.h"
#include "util.h"
-#include "MiniFB.h"
ivec2
POSITION_from_gp0(u32 val)
@@ -67,68 +65,64 @@ REN_FB_set(REN* ren, i32 x, i32 y, u8 r, u8 g, u8 b) {
if (!ren->fb || x < 0 || y < 0 || x >= W || y >= H) return;
- // Clamp color values
r = r > 255 ? 255 : r;
g = g > 255 ? 255 : g;
b = b > 255 ? 255 : b;
- // Direct write instead of memcpy
fb = ren->fb + (x + y * W);
*fb = r | (g << 8) | (b << 16);
}
-//C*
-//FB_get(i32 x, i32 y)
-//{
-// void* c = (!fb.data || x<0 || y<0 || x>=W || y>=H) ? (void*)0 : (void*)(C_new(fb.data[(x+y*W)]));
-// return (C*)c;
-//}
-
REN*
REN_new(void)
{
REN* ren;
ren = (REN*)malloc(sizeof(REN));
- ren->window = mfb_open_ex("my display", 800, 600, WF_RESIZABLE | WF_ALWAYS_ON_TOP);
- //ren->window = SDL_CreateWindow("Ultimecia", 400 , 300, WIN_W, WIN_H, SDL_WINDOW_HIDDEN);
- //ren->renderer = SDL_CreateRenderer(ren->window, -1, 0);
- //ren->tex = SDL_CreateTexture(ren->renderer, SDL_PIXELFORMAT_RGB888, SDL_TEXTUREACCESS_STREAMING, W, H);
- ren->verts = (ivec2*)malloc(sizeof(ivec2) * 10000); // Single allocation with larger size
- ren->colors = (C*)malloc(sizeof(C) * 10000); // Single allocation with larger size
+ ren->window = SDL_CreateWindow("Ultimecia", 400 , 300, WIN_W, WIN_H, SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE);
+ ren->renderer = SDL_CreateRenderer(ren->window, -1, 0);
+ ren->tex = SDL_CreateTexture(ren->renderer, SDL_PIXELFORMAT_RGB888, SDL_TEXTUREACCESS_STREAMING, W, H);
+ ren->verts = (ivec2*)malloc(sizeof(ivec2) * 10000);
+ ren->colors = (C*)malloc(sizeof(C) * 10000);
ren->fb = (u32*)malloc(W*H*sizeof(u32));
memset(ren->fb, 0, (u32)(W*H)*sizeof(u32));
ren->nvertices = 0;
+
return ren;
}
-// Draw a scanline with color interpolation
void
draw_scanline(REN* ren, int y, int x1, C c1, int x2, C c2)
{
+ int dx, x;
+ float r, g, b, dr, dg, db;
if (x1 > x2) {
swap_int(&x1, &x2);
swap_color(&c1, &c2);
}
- int dx = x2 - x1;
+ dx = x2 - x1;
if (dx == 0) return;
- float dr = (c2.r - c1.r) / (float)dx;
- float dg = (c2.g - c1.g) / (float)dx;
- float db = (c2.b - c1.b) / (float)dx;
+ dr = (c2.r - c1.r) / (float)dx;
+ dg = (c2.g - c1.g) / (float)dx;
+ db = (c2.b - c1.b) / (float)dx;
- float r = c1.r, g = c1.g, b = c1.b;
- for (int x = x1; x <= x2; x++) {
+ r = c1.r, g = c1.g, b = c1.b;
+ for (x = x1; x <= x2; x++) {
REN_FB_set(ren, x, y, (u8)r,(u8)g,(u8)b);
r += dr; g += dg; b += db;
}
}
-// Rasterize triangle with color interpolation
void
REN_triangle(REN* ren, ivec2 verts[3], C colors[3])
{
- // Check for degenerate triangles
+
+ i32 y, dx01, dx02, dx12, dr01, dr02, dg02, db02, dg01, db01, dr12, dg12, db12, xL, xR;
+ u32 rL, rR, gL, bL, gR, bR;
+
+
+ /* Check for degenerate triangles */
if (verts[0].x == verts[1].x && verts[0].y == verts[1].y) return;
if (verts[1].x == verts[2].x && verts[1].y == verts[2].y) return;
if (verts[2].x == verts[0].x && verts[2].y == verts[0].y) return;
@@ -138,40 +132,40 @@ REN_triangle(REN* ren, ivec2 verts[3], C colors[3])
if (verts[0].y > verts[2].y) { swap_vec2(&verts[0], &verts[2]); swap_color(&colors[0], &colors[2]); }
if (verts[1].y > verts[2].y) { swap_vec2(&verts[1], &verts[2]); swap_color(&colors[1], &colors[2]); }
- // Calculate edge slopes using fixed-point arithmetic
- i32 dx01 = ((verts[1].x - verts[0].x) << 16) / (verts[1].y - verts[0].y + 1);
- i32 dx02 = ((verts[2].x - verts[0].x) << 16) / (verts[2].y - verts[0].y + 1);
- i32 dx12 = ((verts[2].x - verts[1].x) << 16) / (verts[2].y - verts[1].y + 1);
-
- // Calculate color slopes using fixed-point arithmetic
- i32 dr01 = ((colors[1].r - colors[0].r) << 16) / (verts[1].y - verts[0].y + 1);
- i32 dg01 = ((colors[1].g - colors[0].g) << 16) / (verts[1].y - verts[0].y + 1);
- i32 db01 = ((colors[1].b - colors[0].b) << 16) / (verts[1].y - verts[0].y + 1);
-
- i32 dr02 = ((colors[2].r - colors[0].r) << 16) / (verts[2].y - verts[0].y + 1);
- i32 dg02 = ((colors[2].g - colors[0].g) << 16) / (verts[2].y - verts[0].y + 1);
- i32 db02 = ((colors[2].b - colors[0].b) << 16) / (verts[2].y - verts[0].y + 1);
-
- i32 dr12 = ((colors[2].r - colors[1].r) << 16) / (verts[2].y - verts[1].y + 1);
- i32 dg12 = ((colors[2].g - colors[1].g) << 16) / (verts[2].y - verts[1].y + 1);
- i32 db12 = ((colors[2].b - colors[1].b) << 16) / (verts[2].y - verts[1].y + 1);
-
- // Rasterize top part
- i32 xL = verts[0].x << 16;
- u32 rL = colors[0].r << 16, gL = colors[0].g << 16, bL = colors[0].b << 16;
- i32 xR = verts[0].x << 16;
- u32 rR = colors[0].r << 16, gR = colors[0].g << 16, bR = colors[0].b << 16;
-
- for (i32 y = verts[0].y; y < verts[1].y; y++) {
- draw_scanline(ren, y, xL >> 16, (C){(u8)(rL >> 16), (u8)(gL >> 16), (u8)(bL >> 16)},
- xR >> 16, (C){(u8)(rR >> 16), (u8)(gR >> 16), (u8)(bR >> 16)});
+ /* Calculate edge slopes using fixed-point arithmetic */
+ dx01 = ((verts[1].x - verts[0].x) << 16) / (verts[1].y - verts[0].y + 1);
+ dx02 = ((verts[2].x - verts[0].x) << 16) / (verts[2].y - verts[0].y + 1);
+ dx12 = ((verts[2].x - verts[1].x) << 16) / (verts[2].y - verts[1].y + 1);
+
+ /* Calculate color slopes using fixed-point arithmetic */
+ dr01 = ((colors[1].r - colors[0].r) << 16) / (verts[1].y - verts[0].y + 1);
+ dg01 = ((colors[1].g - colors[0].g) << 16) / (verts[1].y - verts[0].y + 1);
+ db01 = ((colors[1].b - colors[0].b) << 16) / (verts[1].y - verts[0].y + 1);
+
+ dr02 = ((colors[2].r - colors[0].r) << 16) / (verts[2].y - verts[0].y + 1);
+ dg02 = ((colors[2].g - colors[0].g) << 16) / (verts[2].y - verts[0].y + 1);
+ db02 = ((colors[2].b - colors[0].b) << 16) / (verts[2].y - verts[0].y + 1);
+
+ dr12 = ((colors[2].r - colors[1].r) << 16) / (verts[2].y - verts[1].y + 1);
+ dg12 = ((colors[2].g - colors[1].g) << 16) / (verts[2].y - verts[1].y + 1);
+ db12 = ((colors[2].b - colors[1].b) << 16) / (verts[2].y - verts[1].y + 1);
+
+ /* Rasterize top part */
+ xL = verts[0].x << 16;
+ rL = colors[0].r << 16, gL = colors[0].g << 16, bL = colors[0].b << 16;
+ xR = verts[0].x << 16;
+ rR = colors[0].r << 16, gR = colors[0].g << 16, bR = colors[0].b << 16;
+
+ for (y = verts[0].y; y < verts[1].y; y++) {
+ draw_scanline(ren, y, xL >> 16, (C){(rL >> 16), (gL >> 16), (bL >> 16)},
+ xR >> 16, (C){(rR >> 16), (gR >> 16), (bR >> 16)});
xL += dx01; rL += dr01; gL += dg01; bL += db01;
xR += dx02; rR += dr02; gR += dg02; bR += db02;
}
- // Rasterize bottom part
+ /* Rasterize bottom part */
xL = verts[1].x << 16, rL = colors[1].r << 16, gL = colors[1].g << 16, bL = colors[1].b << 16;
- for (i32 y = verts[1].y; y < verts[2].y; y++) {
+ for (y = verts[1].y; y < verts[2].y; y++) {
draw_scanline(ren, y, xL >> 16, (C){(u8)(rL >> 16), (u8)(gL >> 16), (u8)(bL >> 16)},
xR >> 16, (C){(u8)(rR >> 16), (u8)(gR >> 16), (u8)(bR >> 16)});
xL += dx12; rL += dr12; gL += dg12; bL += db12;
@@ -200,7 +194,7 @@ REN_push_quad(REN* ren, ivec2 verts[4], C colors[4])
REN_flush(ren);
- // First triangle: vertices 0,1,2
+ /* First triangle: vertices 0,1,2 */
for (i = 0; i < 3; i++) {
ren->verts[ren->nvertices] = verts[i];
ren->colors[ren->nvertices] = colors[i];
@@ -218,25 +212,22 @@ REN_flush(REN* ren) {
u32 i;
for (i = 0; i < ren->nvertices; i += 3)
REN_triangle(ren, ren->verts + i, ren->colors + i);
- ren->nvertices = 0; // Reset buffer for next frame
+ ren->nvertices = 0;
}
void
REN_draw(REN* ren)
{
- //SDL_UpdateTexture(ren->tex, NULL, ren->fb, W * sizeof(u32));
- //SDL_RenderCopy(ren->renderer, ren->tex, NULL, NULL);
- mfb_update_ex(ren->window, ren->fb, W , H);
+ SDL_UpdateTexture(ren->tex, NULL, ren->fb, W * sizeof(u32));
+ SDL_RenderCopy(ren->renderer, ren->tex, NULL, NULL);
}
void
REN_display(REN* ren)
{
- // Flush any remaining vertices before displaying
- if (ren->nvertices > 0) {
+ if (ren->nvertices > 0)
REN_flush(ren);
- }
REN_draw(ren);
- //SDL_RenderPresent(ren->renderer);
+ SDL_RenderPresent(ren->renderer);
}
diff --git a/src/sr.h b/src/sr.h
@@ -21,8 +21,7 @@ typedef struct { double x, y, z; } vec3f;
enum mop {ADD, SUB, MUL, DIV};
typedef struct _RENDERER {
- struct mfb_window* window;
- //SDL_Window* window;
+ SDL_Window* window;
SDL_Texture* tex;
SDL_Renderer* renderer;
ivec2* verts;
diff --git a/src/time.c b/src/time.c
@@ -0,0 +1,6 @@
+/* Time is endless */
+
+#include "types.h"
+typedef struct {
+ u32 time;
+} time_t;