<commit_before>(in-package :6502)

;;;; REFERENCES:
;; http://www.obelisk.demon.co.uk/6502/registers.html
;; http://www.obelisk.demon.co.uk/6502/addressing.html
;; http://nesdev.parodius.com/6502.txt

(deftype u8 () '(unsigned-byte 8))

(declaim (inline make-cpu))
(defstruct cpu
  "A 6502 CPU with an extra slot for tracking the cycle count/clock ticks."
  (pc #xfffc :type (unsigned-byte 16))  ;; program counter
  (sp #xfd   :type u8)                  ;; stack pointer
  (sr #x24   :type u8)                  ;; status register
  (xr 0      :type u8)                  ;; x register
  (yr 0      :type u8)                  ;; y register
  (ar 0      :type u8)                  ;; accumulator
  (cc 0      :type fixnum))             ;; cycle counter

(defmethod initialize-instance :after ((cpu cpu) &key)
  (setf (cpu-pc cpu) (absolute cpu)))

;;; Tasty Globals

(defparameter *ram* (make-array #x10000 :element-type 'u8)
  "A lovely hunk of bytes.")

(defparameter *cpu* (make-cpu)
  "The 6502 instance used by opcodes in the package.")

(defparameter *opcodes* (make-array #x100 :element-type 'cons :initial-element nil)
  "A mapping of opcodes to instruction mnemonic/metadata conses.")

;;; Helpers

(defmacro defenum (name (&rest keys))
  "Define a function named %NAME, that takes an argument KEY. If KEYS are
scalar values, the corresponding index in KEYS is return. Otherwise, the
associated value is returned."
  `(defun ,(intern (format nil "%~A" (string-upcase name))) (key)
     (let ((enum ',keys))
       (position key enum ,@(when (typep (car keys) 'list) `(:key #'first))))))

(defgeneric reset (obj)
  (:documentation "Reset the OBJ to an initial state.")
  (:method (obj) (initialize-instance obj)))

(defgeneric nmi (obj)
  (:documentation "Generate a non-maskable interrupt. Used for vblanking in NES.")
  (:method (obj)
    (stack-push-word (cpu-pc obj) obj)
    (stack-push (cpu-sr obj) obj)
    (setf (cpu-pc obj) (get-word #xfffa))))

(defun get-instruction (opcode)
  "Get the mnemonic for OPCODE. Returns a symbol to be funcalled or nil."
  (first (aref *opcodes* opcode)))<commit_msg>DEFENUM tweaks.<commit_after>(in-package :6502)

;;;; REFERENCES:
;; http://www.obelisk.demon.co.uk/6502/registers.html
;; http://www.obelisk.demon.co.uk/6502/addressing.html
;; http://nesdev.parodius.com/6502.txt

(deftype u8 () '(unsigned-byte 8))

(declaim (inline make-cpu))
(defstruct cpu
  "A 6502 CPU with an extra slot for tracking the cycle count/clock ticks."
  (pc #xfffc :type (unsigned-byte 16))  ;; program counter
  (sp #xfd   :type u8)                  ;; stack pointer
  (sr #x24   :type u8)                  ;; status register
  (xr 0      :type u8)                  ;; x register
  (yr 0      :type u8)                  ;; y register
  (ar 0      :type u8)                  ;; accumulator
  (cc 0      :type fixnum))             ;; cycle counter

(defmethod initialize-instance :after ((cpu cpu) &key)
  (setf (cpu-pc cpu) (absolute cpu)))

;;; Tasty Globals

(defparameter *ram* (make-array #x10000 :element-type 'u8)
  "A lovely hunk of bytes.")

(defparameter *cpu* (make-cpu)
  "The 6502 instance used by opcodes in the package.")

(defparameter *opcodes* (make-array #x100 :element-type 'cons :initial-element nil)
  "A mapping of opcodes to instruction mnemonic/metadata conses.")

;;; Helpers

(defmacro defenum (name (&rest keys))
  "Define a function named %NAME, that takes an argument KEY. If KEY is a fixnum,
return the value at KEY. Otherwise, return the index of KEY. KEYS may consist of
non-numeric scalar values or lists that start with an EQL-testable scalar value."
  `(defun ,(intern (format nil "%~A" (string-upcase name))) (key &optional next)
     (let ((enum ',keys))
       (if (integerp key)
           (nth key enum)
           (position key enum ,@(when (typep (car keys) 'list) '(:key #'first)))))))

(defgeneric reset (obj)
  (:documentation "Reset the OBJ to an initial state.")
  (:method (obj) (initialize-instance obj)))

(defgeneric nmi (obj)
  (:documentation "Generate a non-maskable interrupt. Used for vblanking in NES.")
  (:method (obj)
    (stack-push-word (cpu-pc obj) obj)
    (stack-push (cpu-sr obj) obj)
    (setf (cpu-pc obj) (get-word #xfffa))))

(defun get-instruction (opcode)
  "Get the mnemonic for OPCODE. Returns a symbol to be funcalled or nil."
  (first (aref *opcodes* opcode)))
{'fraction_non_alphanumeric': 0.1389970231280055, 'fraction_numerical': 0.02198305472864667, 'mean_word_length': 3.059479553903346, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 4, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2072518', 'n_tokens_mistral': 1546, 'n_tokens_neox': 1443, 'n_words': 502}