# Matias Salles — Full Blog Content > Software engineer, Ruby/Crystal developer, and author. Born in Buenos Aires, raised in Montevideo, now doing a master's in AI back in Buenos Aires. This is the full content of my blog at https://matiassalles99.codes for use by LLMs and AI assistants. --- ## Crystal: The Language I Didn't Know I Needed URL: https://matiassalles99.codes/posts/crystal-programming-language/ Date: 2026-03-01 Topics: Crystal, Ruby, programming languages, emulation, performance I was searching "Mario Bros NES online" at 2 AM out of nostalgia. After playing for 15 minutes I started wondering how hard it would be to code an emulator. I went down a rabbit hole of YouTube tutorials and the NES Wiki, and started coding the CPU in Ruby since that's the language I know best. After a few days I had a working CPU and PPU. I ran Mario and got 0.5 FPS — half a frame per second. Mario was a slideshow. I looked at alternatives (Go, Rust, C) but wanted something familiar. After some research I found Crystal, a compiled language with Ruby-like syntax made in Argentina. The syntax was basically identical to Ruby. I rewrote everything in Crystal and got 120 FPS — a 240x speedup with nearly the same code. Crystal is a compiled, statically typed language that compiles to native code through LLVM. It has type inference (you can add annotations but it infers most types), compiles to a single binary, has C interop out of the box, and uses compile-time macros instead of Ruby's runtime metaprogramming. What's great: zero learning curve for Ruby devs, genuinely fast (60 FPS NES emulation), helpful compiler error messages. What could be better: slow compile times for larger projects, smaller ecosystem than Ruby, Windows support still catching up. --- ## I Wrote a Book About Building a NES Emulator URL: https://matiassalles99.codes/posts/i-wrote-a-book/ Date: 2026-03-22 Topics: Crystal, NES emulation, book, 6502 CPU, PPU, APU After building the emulator I spent a few months writing a 280-page book about building one from scratch. The book starts with a CPU that can't do anything and builds up to playing Super Mario Bros. The book covers: NES architecture overview + Crystal setup (chapters 1-2), the entire 6502 CPU with all 151 opcodes (chapter 3), cartridge parsing and iNES format (chapter 4), PPU rendering with SDL2 GUI, backgrounds, sprites and scroll (chapter 5), running real games (chapter 6), APU audio with square, triangle and noise waves (chapter 7), and Mapper 1 (MMC1) for games like Zelda (appendix). The CPU works by fetching an opcode and matching it against all 151 instructions in a case statement. Each instruction is a few lines — for example, LDA (Load Accumulator) reads a byte and puts it in register A, then updates the flags. The same base operation is reused across all 8 addressing modes. The core emulation loop is three lines: the CPU executes one instruction and returns the cycle count, the PPU runs 3x as fast (matching real hardware), and the APU keeps pace. The emulator is compiled to WebAssembly and playable at https://emulator.matiassalles99.codes The book is available on Leanpub in English ("Building Your First Emulator") and Spanish ("Construi tu Primer Emulador"), both with free sample chapters. --- ## How to Create a DSL (Domain-Specific Language) in Ruby URL: https://matiassalles99.codes/posts/dsl-with-ruby/ Date: 2024-04-20 Topics: Ruby, metaprogramming, DSL, define_method, class_eval, ActiveSupport::Concern While building an API client gem for dlocalGo (a payment processor for South American markets), I used Ruby metaprogramming to create a mini-DSL that generates endpoint methods dynamically. The initial approach had a separate method for each API endpoint, leading to repetitive code. The solution was an `endpoint` class method that uses `define_method` to generate instance methods based on URI, HTTP verb, and response class. Key concepts covered: - How ActiveSupport::Concern's `class_methods` works behind the scenes (it creates a ClassMethods module and uses `append_features` to extend the base class) - The plain Ruby equivalent using `self.included(base)` and `base.extend(ClassMethods)` - Using `class_eval` with strings vs blocks for method definitions - ActiveSupport's `class_attribute` for storing metadata (like attribute lists and associations) - Building a response parser DSL with `has_attributes` and `has_association` methods similar to ActiveRecord's API --- ## Active Record's Magic: How Rails Defines Getters and Setters from Your Schema URL: https://matiassalles99.codes/posts/active-record-magic/ Date: 2024-05-10 Topics: Ruby on Rails, ActiveRecord, metaprogramming, ORM internals A deep dive into how ActiveRecord automatically creates getter and setter methods based on your database schema. ActiveRecord::Base includes dozens of modules. The getter/setter definitions happen through ModelSchema and AttributeMethods modules. The AttributeMethods module: - Uses `initialize_generated_modules` to create an empty GeneratedAttributeMethods module where methods will be defined - Includes sub-modules for Read, Write, BeforeTypeCast, Query, PrimaryKey, etc. - Relies heavily on ActiveModel::AttributeMethods which provides the pattern-matching system The process works through AttributeMethodPattern objects. The default pattern (no prefix/suffix) triggers `define_method_attribute` which is answered by the Read module to create getters. The Write module adds a pattern with suffix "=" which triggers `define_method_attribute=` for setters. The schema loading happens through ModelSchema's `load_schema!` method, which queries the actual database (not db/schema.rb) to discover columns. For MySQL, it runs `SHOW FULL FIELDS FROM table_name`. The whole process is kicked off by Railties during application initialization, which calls `define_attribute_methods` on every model descendant. --- ## Building a 4-bit CPU with Integrated Circuits and Breadboards URL: https://matiassalles99.codes/posts/4bit-cpu/ Date: 2024-06-18 Topics: electronics, CPU architecture, digital logic, breadboard, Ben Eater During my first year of college, my friend and I built a 4-bit CPU from scratch with integrated circuits and breadboards for our Computer System Architecture class. We were inspired by Ben Eater's YouTube series on building an 8-bit CPU. We ordered chips from Texas Instruments but they turned out to be five times smaller than needed. We eventually found the right ones at a small electronics shop in Uruguay, though they were different models, which forced us to read datasheets instead of blindly following tutorials. Components built: - Clock: provides regular energy pulses to the rest of the CPU - ALU (Arithmetic Logic Unit): performs addition and subtraction, controlled by pin voltage - Registers: store data, loading controlled by voltage on a control pin - BUS: connects all components, acts as the CPU's data highway - RAM: several 4-bit RAM chips loaded manually with DIP switches We set it up so the ALU could output to the BUS and Register A could read from it, allowing us to run multiplication tables. The Control Unit (CU) is where instructions, machine code, and assembly become practical. It connects to every control pin and manages the CPU's instruction set — each binary code (like "0001") maps to a specific operation. The instruction set is encoded in an EEPROM. We didn't finish the CU before our deadline. This is why different CPUs have different Assembly languages — the instruction sets are defined based on each CPU's architecture. --- ## Save Money on Heroku: Share One Database Across Multiple Apps URL: https://matiassalles99.codes/posts/save-money-on-heroku-share-one-database-across-multiple-apps/ Date: 2025-08-07 Topics: Ruby on Rails, Heroku, PostgreSQL, deployment, cost optimization A practical trick for running multiple Heroku apps cheaply by sharing a single Postgres database using PostgreSQL schemas. The problem: Heroku's cheapest Postgres plan is $5/month per app. With 10 staging apps, that's $57/month ($50 for databases + $7 eco dyno). The solution: use `schema_search_path` in Rails' database.yml to point each app at a different PostgreSQL schema within the same database. Steps: 1. Set `schema_search_path: <%= ENV["DATABASE_SCHEMA"] || "public" %>` in database.yml 2. Copy the DATABASE_URL from your main app to your other apps 3. Set a DATABASE_SCHEMA environment variable in each app 4. Manually create the schema in the shared database using a tool like TablePlus 5. Deploy Total cost: $12/month for unlimited apps (one $5 database + $7 eco dyno plan). Gotcha: if Heroku rotates the DATABASE_URL during maintenance, you need to update it in the other apps manually. Alternative mentioned: Kamal for self-hosting on VMs, with a future post planned about deploying multiple apps on the same server. --- ## About the Author Matias Salles is a software engineer from Uruguay, currently based in Buenos Aires doing a master's in AI. He works primarily with Ruby on Rails and has been writing code professionally for several years. His interests span software engineering, electronics, physics, aerodynamics, and philosophy. He built a NES emulator in Crystal and wrote a 280-page book about it. He also built a 4-bit CPU from breadboards during college. The emulator is playable in the browser at https://emulator.matiassalles99.codes - Blog: https://matiassalles99.codes - GitHub: https://github.com/matiassalles99 - Book (English): https://leanpub.com/nes-emulator-en - Book (Spanish): https://leanpub.com/nes-emulator-sp