Advertisement
Tatantyler

UnnamedAPI / Kernel v1

Jan 13th, 2013
2,713
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
DCPU-16 38.94 KB | None | 0 0
  1. JSR program ; kernel code/data begins below
  2.  
  3. kern_version:
  4. DAT 0x0017 ; Current version is 1.7.
  5.  
  6. ; Changelog:
  7. ; 1.7 - Currently, this is a beta-test version, with experimental floating-point support. Also, fixed sub-second clock support AGAIN.
  8. ; 1.6 - Slight optimization in disp_cls.
  9. ; 1.5 - Fixed sub-second clock support
  10. ; 1.4 = ???
  11. ; 1.3 = ???
  12. ; 1.2 = ???
  13. ; 1.1 = Added RNG
  14.  
  15. ; TODO:
  16. ;  o Finish the Math/Floating Point API
  17. ;  o Find a way to test the Floating Point API
  18.  
  19. kern_interrupt_table:
  20. DAT 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000 ; 32 words
  21. DAT 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000 ; 32 words
  22. DAT 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000 ; 32 words
  23. DAT 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000 ; 32 words
  24.  
  25. ; 128 words have been allocated to the interrupt table.
  26. ; To register an interrupt handler, set one of the words in the table to the address of your interrupt handler.
  27. ; Then trigger the interrupt with the offset as the message.
  28. ;
  29. ; For example, to register an interrupt for message 5, set [kern_interrupt_table+5] to the address of the interrupt handler.
  30. ; Custom interrupt handlers should NOT return with RFI. Instead, they should simply return with "SET PC, POP", as you would return from a normal subroutine.
  31. ; In addition, you should NOT change the value of IAS at any point during execution; that will break clock ticks and consequently the system clock/timer.
  32. ;
  33.  
  34. hw_keyboard:
  35. DAT 0xFAC7
  36. hw_monitor:
  37. DAT 0xFAC7
  38. hw_vectordisp:
  39. DAT 0xFAC7
  40. hw_clock:
  41. DAT 0xFAC7
  42. hw_floppydrive:
  43. DAT 0xFAC7
  44. DAT 0xDA7A
  45. sys_clock_humantime: ; Holds # of seconds since system startup
  46. DAT 0, 0, 0, 0, 0 ; 80 bits for time_t. (The 5th word is for the sub-second part)
  47. DAT 0xDA7A
  48. sys_clock_tick:
  49. DAT 0, 0, 0, 0 ; 64 bits for a tick counter
  50. DAT 0xDA7A
  51. sys_timer: ; countdown timer
  52. DAT 0
  53. DAT 0xDA7A
  54. kern_rng_state: ; RNG internal state
  55. DAT 0
  56.  
  57. kern_code_start: ; code start marker, to help with addressing
  58.  
  59. ; -----------------------------------------------------------------------
  60. ; hw_detect - detect and register system peripherals
  61. ; Detects all connected hardware and registers the first found peripherals to the various hw_XXXX data locations.
  62. ; This subroutine should be called before anything else; almost all of the other functions depend on the hw data locations in some way.
  63.  
  64. hw_detect:
  65.     SET PUSH, A
  66.     SET PUSH, B
  67.     SET PUSH, C
  68.     SET PUSH, X
  69.     SET PUSH, Y
  70.     SET PUSH, I
  71.     SET PUSH, J
  72.     HWN I
  73.     find_hw_loop:
  74.         IFE I, 0xFFFF
  75.             SET PC, find_hw_return
  76.         HWQ I
  77.         IFE A, 0xB402 ;
  78.             JSR find_hw_clock_subcond
  79.         IFE A, 0x7406
  80.             JSR find_hw_keyboard_subcond
  81.         IFE A, 0x24C5
  82.             JSR find_hw_floppydrive_subcond
  83.         IFE A, 0xF615
  84.             JSR find_hw_monitor_subcond
  85.         IFE A, 0xBF3C
  86.             JSR find_hw_vectordisp_subcond
  87.         STD PC, find_hw_loop
  88.         find_hw_initkeyboard:
  89.             IFN [hw_keyboard], 0xFAC7
  90.                 SET PC, POP
  91.             SET [hw_keyboard], I
  92.             SET PC, POP
  93.         find_hw_initclock:
  94.             IFN [hw_clock], 0xFAC7
  95.                 SET PC, POP
  96.             SET [hw_clock], I
  97.             SET B, 6 ; 1 "tick": 1/10th of a second
  98.             SET A, 0
  99.             HWI I
  100.             IAS kern_interrupt_handler
  101.             SET B, 0xC10C
  102.             SET A, 2
  103.             HWI I
  104.             SET PC, POP
  105.         find_hw_initfloppydrive:
  106.             IFN [hw_floppydrive], 0xFAC7
  107.                 SET PC, POP
  108.             SET [hw_floppydrive], I
  109.             SET PC, POP
  110.         find_hw_initvectordisp:
  111.             IFN [hw_vectordisp], 0xFAC7
  112.                 SET PC, POP
  113.             SET [hw_vectordisp], I
  114.             SET PC, POP
  115.         find_hw_initmonitor:
  116.             IFN [hw_monitor], 0xFAC7
  117.                 SET PC, POP
  118.             SET [hw_monitor], I
  119.             SET A, 0
  120.             SET B, 0x8000
  121.             HWI I
  122.             SET PC, POP
  123.         find_hw_clock_subcond:
  124.             IFE B, 0x12D0
  125.                 JSR find_hw_initclock
  126.             SET PC, POP
  127.         find_hw_keyboard_subcond:
  128.             IFE B, 0x30CF
  129.                 JSR find_hw_initkeyboard
  130.             SET PC, POP
  131.         find_hw_floppydrive_subcond:
  132.             IFE B, 0x4FD5
  133.                 JSR find_hw_initfloppydrive
  134.             SET PC, POP
  135.         find_hw_monitor_subcond:
  136.             IFE B, 0x7349
  137.                 JSR find_hw_initmonitor
  138.             SET PC, POP
  139.         find_hw_vectordisp_subcond:
  140.             IFE B, 0x42BA
  141.                 JSR find_hw_initvectordisp
  142.             SET PC, POP
  143.         find_hw_return:
  144.             SET J, POP
  145.             SET I, POP
  146.             SET Y, POP
  147.             SET X, POP
  148.             SET C, POP
  149.             SET B, POP
  150.             SET A, POP
  151.             SET PC, POP
  152.  
  153. ; -----------------------------------------------------------------------
  154. ; kern_interrupt_handler - Kernel interrupt handler
  155. ; This function handles clock ticks and any other interrupts.
  156.            
  157. kern_interrupt_handler:
  158.     IFE A, 0xC10C
  159.         JSR clock_tick
  160.     IFL A, 128
  161.         JSR [A+kern_interrupt_table] ; jump to custom interrupt handlers
  162.     RFI 0xC0DE
  163.  
  164. ; -----------------------------------------------------------------------
  165. ; kern_sleep - pause execution
  166. ; This function waits for a variable amount of time, which is stored in register X.
  167. ; The unit of time is deciseconds (i.e setting X to 50 and calling this waits for 5 seconds.)
  168. ; The end-programmer could probably do this on his own, we're just putting it here as a "test".
  169.  
  170. kern_sleep:
  171.     SET [sys_timer], X
  172.     kern_sleep_loop:
  173.     IFG [sys_timer], 0
  174.         SET PC, kern_sleep_loop
  175.     SET PC, POP
  176.  
  177. ; Floating point numbers are assumed to be in the format:
  178. ; (word 1): [significant digits] (word 2): [exponent]
  179. ; Both words are assumed to be signed. If the significant digits are negative, then the whole floating point number is assumed to be negative as well.
  180. ; A floating point number is equivalent to this expression:
  181. ; [significant] * [base]^[exponent].
  182. ; So, .a floating-point number:
  183. ; (w1): [0x0005] (5) (w2): [0xFFF3] (-4) = 5 * 2^-4, or 0.3125
  184. ; In this documentation, a floating point number may be called a "float".
  185.  
  186. ; -----------------------------------------------------------------------
  187. ; floating_greater_than - greater_than for floating point numbers
  188. ; This function sets C to 1 if the float pointed to by A is greater than the one pointed by B, and 0 otherwise.
  189.  
  190. floating_greater_than:
  191.     SET PUSH, X
  192.     SET PUSH, Y
  193.     SET X, [A]
  194.     SET Y, [B]
  195.     AND X, 0x0001
  196.     AND Y, 0x0001
  197.    
  198.     XOR X, Y
  199.     IFG X, 0
  200.         SET PC, floating_greater_than_signs_differ
  201.        
  202.     IFA [A+1], [B+1]
  203.         SET PC, floating_greater_than_true
  204.     IFU [A+1], [B+1]
  205.         SET PC, floating_greater_than_false
  206.     IFA [A], [B]
  207.         SET PC, floating_greater_than_true
  208.     IFU [A], [B]
  209.         SET PC, floating_greater_than_false
  210.     SET PC, floating_greater_than_false
  211.    
  212.     floating_greater_than_true:
  213.     SET C, 1
  214.     SET PC, floating_greater_than_ret
  215.     floating_greater_than_false:
  216.     SET C, 0
  217.     floating_greater_than_ret:
  218.     SET Y, POP
  219.     SET X, POP
  220.     SET PC, POP
  221.     floating_greater_than_signs_differ:
  222.         IFE X, 1 ; If A is positive, then B is negative.
  223.             SET PC, floating_greater_than_true
  224.         SET PC, floating_greater_than_false ; If A is negative, then B is positive.
  225.    
  226. ; -----------------------------------------------------------------------
  227. ; floating_less_than - less_than for floating point numbers
  228. ; This function sets C to 1 if the float pointed to by A is less than the one pointed by B, and 0 otherwise.
  229.  
  230. floating_less_than:
  231.     SET PUSH, X
  232.     SET PUSH, Y
  233.     SET X, [A]
  234.     SET Y, [B]
  235.     AND X, 0x0001
  236.     AND Y, 0x0001
  237.    
  238.     XOR X, Y
  239.     IFG X, 0
  240.         SET PC, floating_less_than_signs_differ
  241.    
  242.     IFU [A+1], [B+1]
  243.         SET PC, floating_less_than_true
  244.     IFA [A+1], [B+1]
  245.         SET PC, floating_less_than_false
  246.     IFU [A], [B]
  247.         SET PC, floating_less_than_true
  248.     IFA [A], [B]
  249.         SET PC, floating_less_than_false
  250.     SET PC, floating_less_than_false
  251.     floating_less_than_true:
  252.     SET C, 1
  253.     SET PC, floating_less_than_ret
  254.     floating_less_than_false:
  255.     SET C, 0
  256.     floating_less_than_ret:
  257.     SET Y, POP
  258.     SET X, POP
  259.     SET PC, POP
  260.  
  261.     floating_less_than_signs_differ:
  262.         IFE X, 1
  263.             SET PC, floating_less_than_false
  264.         SET PC, floating_less_than_true
  265.  
  266. ; -----------------------------------------------------------------------
  267. ; floating_shift - Shift the exponents to prepare for operations
  268. ; This aligns the exponents in the registers.
  269. ; Float A is assumed to be in registers X (exponent) and Y (mantissa).
  270. ; Float B is assumed to be in registers I (exponent) and J (mantissa).
  271.  
  272. floating_shift:
  273.     SET PUSH, Z
  274.     IFG X, I ; We need to shift A's mantissa (which is in Y)
  275.         JSR floating_shift_exponent_A
  276.     IFL X, I ; We need to shift B's mantissa (which is in J)
  277.         JSR floating_shift_exponent_B
  278.     SET Z, POP
  279.     SET PC, POP
  280.     floating_shift_exponent_A:
  281.         SET Z, X
  282.         SUB Z, I
  283.         SHL Y, Z
  284.         SET PC, POP
  285.     floating_shift_exponent_B:
  286.         SET Z, I
  287.         SUB Z, X
  288.         SHL J, Z
  289.         SET PC, POP
  290.  
  291. ; -----------------------------------------------------------------------
  292. ; floating_add - addition for floating point numbers
  293. ; This sets [A] to [A]+[B].
  294.  
  295. ; 1 Stack Overflow question and 4 lecture notes later...
  296. ; If you shift the mantissa (fractional part) to the LEFT, you DECREASE the exponent
  297. ; If you shift it to the RIGHT, you increase it. Someone needs to double-check me on this...
  298. ; We want the bits to fall off the least significant end of the mantissa, se we need to shift LEFT.
  299.  
  300. floating_add:
  301.     SET PUSH, X ; A-exponent
  302.     SET PUSH, Y ; A-mantissa
  303.     SET PUSH, I ; B-exponent
  304.     SET PUSH, J ; B-mantissa
  305.     SET PUSH, Z ; temp. storage
  306.     SET PUSH, C ; temp. storage
  307.    
  308.     SET X, [A+1]
  309.     SET Y, [A]
  310.     SET I, [B+1]
  311.     SET J, [B]
  312.    
  313.     ; Align the exponents (i.e make them the same)
  314.     JSR floating_shift
  315.    
  316.     ; Add
  317.     SET C, Y ; Add the mantissas
  318.     ADD C, J
  319.    
  320.     ; Return
  321.     SET [A], C
  322.     SET [A+1], X
  323.     SET C, POP
  324.     SET J, POP
  325.     SET I, POP
  326.     SET Y, POP
  327.     SET X, POP
  328.     SET PC, POP
  329.  
  330. ; -----------------------------------------------------------------------
  331. ; floating_sub - Subtraction for floating point numbers
  332. ; This function sets [A] to [A]+[B].
  333.  
  334. floating_sub:
  335.     SET PUSH, X ; A-exponent
  336.     SET PUSH, Y ; A-mantissa
  337.     SET PUSH, I ; B-exponent
  338.     SET PUSH, J ; B-mantissa
  339.     SET PUSH, C ; temp. storage
  340.    
  341.     SET X, [A+1]
  342.     SET Y, [A]
  343.     SET I, [B+1]
  344.     SET J, [B]
  345.    
  346.     ; Align the exponents (i.e make them the same)
  347.     JSR floating_shift
  348.    
  349.     ; Subtract
  350.     IFG Y, J
  351.         SET PC, floating_sub_A
  352.     SET PC, floating_sub_B
  353.    
  354.     floating_sub_A:
  355.         SET C, Y
  356.         SUB C, J
  357.         SET PC, floating_sub_ret
  358.     floating_sub_B:
  359.         SET C, J ; Subtract the mantissas
  360.         SUB C, Y
  361.    
  362.     ; Return
  363.     floating_sub_ret:
  364.     SET [A], C
  365.     SET [A+1], X ; just borrow A's exponent
  366.     SET C, POP
  367.     SET J, POP
  368.     SET I, POP
  369.     SET Y, POP
  370.     SET X, POP
  371.     SET PC, POP
  372.  
  373. ; -----------------------------------------------------------------------
  374. ; floating_mul - Multiplication for floats
  375. ; This function sets [A] to [A]*[B]
  376.    
  377. floating_mul:
  378.     SET PUSH, X ; A-exponent
  379.     SET PUSH, Y ; A-mantissa
  380.     SET PUSH, I ; B-exponent
  381.     SET PUSH, J ; B-mantissa
  382.     SET PUSH, C ; temp. storage
  383.     SET PUSH, Z ; temp. storage
  384.    
  385.     SET X, [A+1]
  386.     SET Y, [A]
  387.     SET I, [B+1]
  388.     SET J, [B]
  389.    
  390.     ; Multiply the mantissas:
  391.     SET C, Y
  392.     MLI C, J ; use a signed operator
  393.    
  394.     ; Add the exponents
  395.     SET Z, X
  396.     ADD Z, I
  397.    
  398.     ; Return
  399.     SET [A], C
  400.     SET [A+1], Z ; Use the new exponent
  401.     SET Z, POP
  402.     SET C, POP
  403.     SET J, POP
  404.     SET I, POP
  405.     SET Y, POP
  406.     SET X, POP
  407.     SET PC, POP
  408.  
  409. ; -----------------------------------------------------------------------
  410. ; floating_div - Division for floats
  411. ; This function sets [A] to [A]/[B]
  412.    
  413. floating_div:
  414.     SET PUSH, X ; A-exponent
  415.     SET PUSH, Y ; A-mantissa
  416.     SET PUSH, I ; B-exponent
  417.     SET PUSH, J ; B-mantissa
  418.     SET PUSH, C ; temp. storage
  419.     SET PUSH, Z ; temp. storage
  420.    
  421.     SET X, [A+1]
  422.     SET Y, [A]
  423.     SET I, [B+1]
  424.     SET J, [B]
  425.    
  426.     ; Divide the mantissas:
  427.     SET C, Y
  428.     DIV C, J ; use a signed operator
  429.    
  430.     ; Subtract the exponents
  431.     SET Z, X
  432.     SUB Z, I
  433.    
  434.     ; Return
  435.     SET [A], C
  436.     SET [A+1], Z ; Use the new exponent
  437.     SET Z, POP
  438.     SET C, POP
  439.     SET J, POP
  440.     SET I, POP
  441.     SET Y, POP
  442.     SET X, POP
  443.     SET PC, POP
  444.    
  445. ; -----------------------------------------------------------------------
  446. ; math_abs - Return absolute value
  447. ; This sets register B to the absolute value of the number contained in register B.
  448.  
  449. math_abs:
  450.     IFA B, 0 ; Is B positive?
  451.         SET PC, POP ; If so, then return.
  452.     XOR B, 0xFFFF ; XOR by 0xFFFF is the same as NOT.
  453.     ADD B, 1 ; The number's in one's complement, so add 1 to fix that.
  454.     SET PC, POP
  455.  
  456. ; -----------------------------------------------------------------------
  457. ; math_flipsign - Flip a number's sign ( 5 -> -5 )
  458. ; This flips the sign of the number in register B.
  459.  
  460. math_flipsign:
  461.     XOR B, 0xFFFF
  462.     ADD B, 1
  463.     SET PC, POP
  464.  
  465. ; -----------------------------------------------------------------------
  466. ; math_exponent - Calculate an exponent
  467. ; This calculates A to the power of B, where A and B refer to the registers of the DCPU-16.
  468. ; The result is stored in C.
  469. ;
  470.    
  471. math_exponent:
  472.     SET PUSH, I
  473.     SET PUSH, A
  474.     SET I, B
  475.     exp_loop:
  476.         IFL I, 1
  477.             SET PC, exp_end
  478.         MUL A, B
  479.         STD PC, exp_loop
  480.     exp_end:
  481.     SET C, A
  482.     SET A, POP
  483.     SET I, POP
  484.     SET PC, POP
  485.  
  486. ; -----------------------------------------------------------------------
  487. ; clock_tick - Clock tick handler (human seconds / system ticks)
  488. ; This function increments sys_clock_humantime  and sys_clock_tick by 1.
  489. ; One "tick" is 1/10th of a second.
  490.  
  491. clock_tick:
  492.     SET PUSH, A
  493.    
  494.     SET A, sys_clock_tick
  495.     ADD [A], 1
  496.     ADD [A+1], EX
  497.     ADD [A+2], EX
  498.     ADD [A+3], EX
  499.    
  500.     SET A, sys_clock_humantime
  501.    
  502.     ADD [A], 1
  503.    
  504.     IFG [sys_timer], 0
  505.         SUB [sys_timer], 1
  506.    
  507.     IFL [A], 10
  508.         SET PC, clock_tick_skip
  509.     ; we should not be here unless a second has passed
  510.     SET [A], 0
  511.        
  512.     ADD [A+1], 1
  513.     ADD [A+2], EX
  514.     ADD [A+3], EX
  515.     ADD [A+4], EX
  516.    
  517.     clock_tick_skip:
  518.    
  519.     SET A, POP
  520.     SET PC, POP
  521.  
  522. ; -----------------------------------------------------------------------
  523. ; disp_write_str - write a null-terminated string to screen.
  524. ; Writes data to the screen at the coordinates stored in registers X and Y, starting at Z.
  525. ; Formatting can be set with register C; the data is ORed with the value in C before being written to memory.
  526. ;
  527. ; Dev. Notes:
  528. ; takes (X,Y) coords in X and Y, a pointer to data in Z, and a formatting byte in C
  529.  
  530. disp_write_str:
  531.     SET PUSH, X
  532.     SET PUSH, Y
  533.     SET PUSH, Z
  534.     write_str_to_screen_loop:
  535.         SET PUSH, I
  536.         SET I, Y
  537.         MUL I, 32
  538.         ADD I, X
  539.         ADD I, 0x8000
  540.         SET PUSH, J
  541.         SET J, [Z]
  542.         BOR J, C
  543.         SET [I], J
  544.         SET J, POP
  545.         SET I, POP
  546.        
  547.         ADD Z, 1
  548.         IFE [Z], 0
  549.             SET PC, write_str_to_screen_loopdone
  550.         ADD X, 1
  551.         SET PUSH, I
  552.         SET I, X
  553.         DIV I, 32
  554.         ADD Y, I
  555.         SET I, POP
  556.         MOD X, 32
  557.         SET PC, write_str_to_screen_loop
  558.     write_str_to_screen_loopdone:
  559.     SET Z, POP
  560.     SET Y, POP
  561.     SET X, POP
  562.     SET PC, POP
  563.    
  564. ; -----------------------------------------------------------------------
  565. ; int_to_str - Hex to ASCII.
  566. ; Sets B to the value for a string given a half-byte in A. (A must be 0x0 - 0xF.). All values are in ASCII.
  567. ; There's probably a better way to do this, but I feel that this is "safer" (aka I know it works)
  568.  
  569. int_to_str:
  570.     IFG A, 0xF ; do some basic checking to see if we're in range (I do it now, instead of later, to save time.)
  571.         SET PC, POP ; On a completely unrelated note, why do I keep switching between "I" and "we"? Well, I guess we'll never know.
  572.     IFU A, 0
  573.         SET PC, POP
  574.     IFE A, 0
  575.         SET B, 0x0030
  576.     IFE A, 1
  577.         SET B, 0x0031
  578.     IFE A, 2
  579.         SET B, 0x0032
  580.     IFE A, 3
  581.         SET B, 0x0033
  582.     IFE A, 4
  583.         SET B, 0x0034
  584.     IFE A, 5
  585.         SET B, 0x0035
  586.     IFE A, 6
  587.         SET B, 0x0036
  588.     IFE A, 7
  589.         SET B, 0x0037
  590.     IFE A, 8
  591.         SET B, 0x0038
  592.     IFE A, 9
  593.         SET B, 0x0039
  594.     IFE A, 0xA
  595.         SET B, 0x0041
  596.     IFE A, 0xB
  597.         SET B, 0x0042
  598.     IFE A, 0xC
  599.         SET B, 0x0043
  600.     IFE A, 0xD
  601.         SET B, 0x0044
  602.     IFE A, 0xE
  603.         SET B, 0x0045
  604.     IFE A, 0xF
  605.         SET B, 0x0046
  606.     SET PC, POP
  607.  
  608. ; -----------------------------------------------------------------------
  609. ; disp_write_word - Write a hex word to the screen.
  610. ; Writes a single hex word (e.g 0xFACE) to the screen without a leading "0x".
  611. ; The word will start at the coordinates stored in registers X and Y (like disp_write_str).
  612. ; The word to be written is read from register Z, and formatting is done with register C, similar to disp_write_str.
  613. ;
  614. ; Dev. Notes:
  615. ; target loc in in X,Y (same as write_str), word is in Z
  616.  
  617. disp_write_word:
  618.     ; We can use A/B/C/I/J registers
  619.     SET PUSH, A
  620.     SET PUSH, B
  621.     SET PUSH, C
  622.     SET PUSH, I
  623.     SET PUSH, J
  624.    
  625.     ; split I into 4 hex digits
  626.     SET A, Z
  627.     SET B, Z
  628.     SET C, Z
  629.     SET I, Z
  630.    
  631.     SHR C, 4
  632.     SHR B, 8
  633.     SHR A, 12
  634.    
  635.     AND A, 0x000F
  636.     AND B, 0x000F
  637.     AND C, 0x000F
  638.     AND I, 0x000F
  639.    
  640.     SET J, write_word_tempdata
  641.    
  642.     SET PUSH, B
  643.     JSR int_to_str
  644.     SET [J], B
  645.     SET B, POP
  646.    
  647.     SET PUSH, B
  648.     SET PUSH, A
  649.     SET A, B
  650.     JSR int_to_str
  651.     SET [J+1], B
  652.     SET A, POP
  653.     SET B, POP
  654.    
  655.     SET PUSH, B
  656.     SET PUSH, A
  657.     SET A, C
  658.     JSR int_to_str
  659.     SET [J+2], B
  660.     SET A, POP
  661.     SET B, POP
  662.    
  663.     SET PUSH, B
  664.     SET PUSH, A
  665.     SET A, I
  666.     JSR int_to_str
  667.     SET [J+3], B
  668.     SET A, POP
  669.     SET B, POP
  670.    
  671.     SET J, POP
  672.     SET I, POP
  673.     SET C, POP
  674.     SET B, POP
  675.     SET A, POP
  676.    
  677.     SET PUSH, Z
  678.     SET Z, write_word_tempdata
  679.     JSR disp_write_str
  680.     SET Z, POP
  681.    
  682.     SET PC, POP
  683.     write_word_tempdata:
  684.     DAT 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
  685.  
  686. ; -----------------------------------------------------------------------
  687. ; disp_write_float - write a float to screen (as a decimal)
  688. ; This function writes a floating-point number to screen as a decimal.
  689. ; As with the other functions, an (X,Y) coordinate is taken as a parameter in registers X and Y. The pointer to the float is taken as Z, and the formatting byte is taken as C.
  690.  
  691. ; As of 1.7, this code is nonfunctional. I'll try to get it working soon.
  692.  
  693. ; disp_write_float:
  694. ;   SET PUSH, I
  695. ;   JSR disp_x_y_to_i
  696. ;                   ; Insert drawing code here
  697. ;   disp_write_float_showneg:
  698. ;       SET [I], 0x002D
  699. ;       BOR [I], C
  700. ;       JSR disp_write_float_incpointer
  701. ;       SET PC, POP
  702. ;   disp_write_float_incpointer:
  703. ;       ADD X, 1
  704. ;       SET PUSH, I
  705. ;       SET I, X
  706. ;       DIV I, 32
  707. ;       ADD Y, I
  708. ;       SET I, POP
  709. ;       MOD X, 32
  710. ;       ADD I, 1
  711. ;       SET PC, POP
  712. ;   disp_write_float_ret:
  713. ;       SET I, POP
  714. ;       SET PC, POP
  715.  
  716.  
  717. ; -----------------------------------------------------------------------
  718. ; disp_x_y_to_i - Convert (X,Y) coordinates to an array offset
  719. ; Converts a pair of (X, Y) coordinates stored in X and Y to an array offset stored in I.
  720. ; (0,0) converts to 0x8000, the address of the first character of the screen (the upper-left).
  721.  
  722. disp_x_y_to_i:
  723.     SET I, Y
  724.     MUL I, 32
  725.     ADD I, X
  726.     ADD I, 0x8000
  727.     SET PC, POP
  728.  
  729.  
  730. ; -----------------------------------------------------------------------
  731. ; disp_cls - Clear the screen.
  732. ; This function clears all data between 0x8000 and 0x8182.
  733. ; Thank you to leonardluen (from the 0x10c forums) for some optimization tips that are in use here. To be specific, he made this run 3 cycles faster per loop.
  734.  
  735. disp_cls:
  736.     SET PUSH, I
  737.     SET PUSH, A
  738.     SET PUSH, Z
  739.     SET I, 0x8000 ; The LEM1802's area of memory starts at 0x8000 and spans 0x182 words
  740.     SET A, 0x8182
  741.     SET Z, disp_cls_loop
  742.     disp_cls_loop:
  743.     SET [I], 0
  744.     IFE I, A
  745.         STI PC, Z
  746.     SET Z, POP
  747.     SET A, POP
  748.     SET I, POP
  749.     SET PC, POP
  750.  
  751. ; -----------------------------------------------------------------------
  752. ; ascii_applyshift - simulate pressing Shift and typing
  753. ; This function sets C to the ASCII value it would have if the user had pressed shift.
  754. ; For example, if C had the value "a" then it would then hold the value "A", and "1" would be changed to "!", and so on.
  755. ; This only applys to the printable characters.
  756. ; I need this function because keyboard_read_char doesn't account for shift... (well, it only takes shift into account for the letters.)
  757. ;
  758.  
  759. ascii_applyshift:
  760.     IFE C, 0x31
  761.         SET C, 0x21
  762.     IFE C, 0x32
  763.         SET C, 0x40
  764.     IFE C, 0x33
  765.         SET C, 0x23
  766.     IFE C, 0x34
  767.         SET C, 0x24
  768.     IFE C, 0x35
  769.         SET C, 0x25
  770.     IFE C, 0x36
  771.         SET C, 0x5E
  772.     IFE C, 0x37
  773.         SET C, 0x26
  774.     IFE C, 0x38
  775.         SET C, 0x2A
  776.     IFE C, 0x39
  777.         SET C, 0x28
  778.     IFE C, 0x30
  779.         SET C, 0x29
  780.     SET PC, POP
  781.  
  782. ; -----------------------------------------------------------------------
  783. ; ascii_tocaret - Get a control character from a letter
  784. ; This converts from a letter to a control character based on caret notation.
  785. ; The character to be "converted" is read from, and stored in, C.
  786. ; With caret notation, the decimal code for a character is displayed based with the corresponding letter and a caret (^).
  787. ; For example, the ASCII code for the Start of Header (SOH) character is 1 in decimal (it's also 1 in hex), so we represent it with ^A.
  788. ; Likewise, the ASCII code for the Bell (BEL) character is 7 in decimal, so we represent it with ^G.
  789. ; Since our alphabet has no character 0, we represent the null character (NUL) with ^@. (The ASCII character code for @ comes before the code for A.)
  790. ; However, there is no way to actually type Ctrl-@ on your keyboard, so you cannot type the null character.
  791. ;
  792.  
  793. ascii_tocaret:
  794.     IFG C, 0x60
  795.         SET PC, ascii_tocaret_subcond_2
  796.     IFG C, 0x40
  797.         SET PC, ascii_tocaret_subcond_1
  798.     ascii_tocaret_subcond_1: ; uppercase characters
  799.     IFL C, 0x5B
  800.         SUB C, 0x40
  801.     SET PC, ascii_tocaret_end
  802.     ascii_tocaret_subcond_2: ; lowercase characters
  803.     IFL C, 0x7B
  804.         SUB C, 0x60
  805.     ascii_tocaret_end:
  806.     SET PC, POP
  807.    
  808. ; -----------------------------------------------------------------------
  809. ; keyboard_read_char - read an ASCII value from the keyboard
  810. ; This function sets C to an ASCII value based on what character was pressed on the keyboard.
  811. ; This function DOES NOT ECHO CHARACTERS TO OUTPUT.
  812. ; "Character keys" are:
  813. ; 0x20 - 0x7F - ASCII characters (a, z, A, Z, 1, 2, 3, etc.) (http://en.wikipedia.org/wiki/ASCII)
  814. ; 0x11 - RETURN key, returns ASCII newline ("\n")
  815. ; 0x10 - BACKSPACE key, returns 0x10.
  816.  
  817. keyboard_read_char:
  818.     SET PUSH, A
  819.     keyboard_read_char_loop:
  820.         SET A, 1
  821.         HWI [hw_keyboard]
  822.         IFE C, 0x11
  823.             SET PC, read_char_loop_end
  824.         IFE C, 0x10
  825.             SET PC, read_char_loop_end
  826.         IFE C, 0
  827.             SET PC, keyboard_read_char_loop
  828.         IFG C, 0x7F
  829.             SET PC, keyboard_read_char_loop
  830.         IFL C, 0x20
  831.             SET PC, keyboard_read_char_loop
  832.         read_char_loop_end:
  833.         IFE C, 0x11
  834.             SET C, 0x0A ; 0x0A == '\n'
  835.         SET PUSH, C
  836.         SET A, 2
  837.         SET B, 0x90
  838.         HWI [hw_keyboard]
  839.         SET PUSH, X
  840.         SET X, C
  841.         SET C, [SP+1]
  842.         IFE X, 1
  843.             JSR ascii_applyshift
  844.         SET [SP+1], C
  845.         SET X, POP
  846.         SET C, POP
  847.         SET A, 0
  848.         HWI [hw_keyboard]
  849.         SET A, POP
  850.         SET PC, POP
  851.    
  852. ; -----------------------------------------------------------------------
  853. ; keyboard_read_special - read an special value from the keyboard
  854. ; This function sets C to the keycode for a special key, based on the one pressed.
  855. ; Special keys are:
  856. ;    0x12 - Insert
  857. ;    0x13 - Delete
  858. ;    0x80 - Arrow UP
  859. ;    0x81 - Arrow DOWN
  860. ;    0x82 - Arrow LEFT
  861. ;    0x83 - Arrow RIGHT
  862. ;    0x90 - Shift
  863. ;    0x91 - Control
  864. ;    The RETURN key (0x11) and the BACKSPACE key are ommitted, as keyboard_read_char handles those.
  865.  
  866. keyboard_read_special:
  867.     SET PUSH, A
  868.     SET A, 1
  869.     keyboard_read_special_loop:
  870.         HWI [hw_keyboard]
  871.         IFE C, 0
  872.             SET PC, keyboard_read_special_loop
  873.         IFE C, 0x11
  874.             SET PC, keyboard_read_special_loop
  875.         IFE C, 0x10
  876.             SET PC, keyboard_read_special_loop
  877.         IFL C, 0x20
  878.             SET PC, keyboard_read_special_loop_end
  879.         IFG C, 0x7F
  880.             SET PC, keyboard_read_special_loop_end
  881.         keyboard_read_special_loop_end:
  882.             SET A, 0
  883.             HWI [hw_keyboard]
  884.             SET A, POP
  885.             SET PC, POP
  886.            
  887. ; -----------------------------------------------------------------------
  888. ; keyboard_read_raw - read a key from the keyboard
  889. ; This function sets C to the keycode for any key.
  890. ; This function DOES NOT ECHO CHARACTERS TO OUTPUT.
  891.  
  892. keyboard_read_raw:
  893.     SET PUSH, A
  894.     SET A, 1
  895.     keyboard_read_raw_loop:
  896.         HWI [hw_keyboard]
  897.         IFE C, 0
  898.             SET PC, keyboard_read_raw_loop
  899.         SET A, 0
  900.         HWI [hw_keyboard]
  901.         SET A, POP
  902.         SET PC, POP
  903.  
  904. ; -----------------------------------------------------------------------
  905. ; keyboard_read_str - read a null-terminated string to an address in memory
  906. ; This function writes all characters pressed to Z, echoing each character written.
  907. ; This function echoes characters to the memory address pointed to by I, which should be set to 0x8000 - 0x8182.
  908. ; If I is zero, then characters are not echoed to the terminal.
  909. ; This is, in essence, C's getline or C++'s cin.
  910.  
  911. keyboard_read_str:
  912.     SET PUSH, C
  913.     SET PUSH, Z
  914.     SET PUSH, I
  915.     keyboard_read_str_loop:
  916.         JSR keyboard_read_char
  917.         IFE C, 0x0A
  918.             SET PC, keyboard_read_str_return
  919.         IFE C, 0x10
  920.             SET PC, keyboard_read_str_backspace
  921.         SET [Z], C
  922.         SET [I], C ; actually draw the character
  923.         BOR [I], 0xF000 ; Set [I] to white-on-black
  924.         IFN [Z+2], 0 ; Would we overwrite data during the next iteration? (Z+1 is the next character, but we offset by 2 to take the null terminator into account.)
  925.             SET PC, keyboard_read_str_return ; Z+1 would be set to null.
  926.         ADD Z, 1
  927.         ADD I, 1
  928.         SET PC, keyboard_read_str_loop
  929.     keyboard_read_str_backspace:
  930.         SUB I, 1
  931.         SUB Z, 1
  932.         SET [I], 0
  933.         SET [Z], 0
  934.         IFG [SP+1], Z ; If Old-Z is greater than new-z...
  935.             SET Z, [SP+1]
  936.         IFG [SP], I
  937.             SET I, [SP]
  938.         SET PC, keyboard_read_str_loop
  939.     keyboard_read_str_return:
  940.     SET [Z+1], 0 ; null-terminate the string
  941.     SET I, POP
  942.     SET Z, POP
  943.     SET C, POP
  944.     SET PC, POP
  945.  
  946. ; -----------------------------------------------------------------------
  947. ; floppy_drive_block_read - read a sector to memory from a floppy (blocking)
  948. ; This sector will attempt to read the sector in register X from a floppy to the area of memory pointed to by register Y.
  949. ; This is effectively a wrapper around the interrupts required to read a sector from the disk, and blocks until it is finished.
  950.  
  951. floppy_drive_block_read:
  952.     SET PUSH, A
  953.     SET PUSH, B
  954.     SET PUSH, C
  955.     SET A, 0
  956.     HWI [hw_floppydrive]
  957.     IFE B, 1
  958.         SET PC, floppy_drive_block_read_logic
  959.     IFE B, 2
  960.         SET PC, floppy_drive_block_read_logic
  961.     floppy_drive_block_read_return:
  962.     SET C, POP
  963.     SET B, POP
  964.     SET A, POP
  965.     SET PC, POP
  966.     floppy_drive_block_read_logic:
  967.         SET A, 2
  968.         HWI [hw_floppydrive]
  969.         IFN B, 1
  970.             SET PC, floppy_drive_block_read_return
  971.         SET A, 0
  972.         HWI [hw_floppydrive]
  973.         IFE B, 3
  974.             SUB PC, 3
  975.         SET PC, floppy_drive_block_read_return
  976.        
  977. ; -----------------------------------------------------------------------
  978. ; floppy_drive_block_write - write to a sector on a floppy from memory
  979. ; This sector will attempt to write to the sector in register X on a floppy from the area of memory pointed to by register Y.
  980. ; This is effectively a wrapper around the interrupts required to wrote a sector to the disk, and blocks until it is finished.
  981.  
  982. floppy_drive_block_write:
  983.     SET PUSH, A
  984.     SET PUSH, B
  985.     SET PUSH, C
  986.     SET A, 0
  987.     HWI [hw_floppydrive]
  988.     IFE B, 1
  989.         SET PC, floppy_drive_block_write_logic
  990.     floppy_drive_block_write_return:
  991.     SET C, POP
  992.     SET B, POP
  993.     SET A, POP
  994.     SET PC, POP
  995.     floppy_drive_block_write_logic:
  996.         SET A, 3
  997.         HWI [hw_floppydrive]
  998.         IFN B, 1
  999.             SET PC, floppy_drive_block_write_return
  1000.         SET A, 0
  1001.         HWI [hw_floppydrive]
  1002.         IFE B, 3
  1003.             SUB PC, 3
  1004.         SET PC, floppy_drive_block_write_return
  1005.  
  1006. ; -----------------------------------------------------------------------
  1007. ; ecc_generate_parity - Generate a (simple) checksum for an arbitrary amount of data
  1008. ; This function generates an error-checking code (to be precise, a parity word) for a block of data.
  1009. ; The block is read starting from register I and continues for J bytes.
  1010. ; The ECC is stored in register B.
  1011. ; This function generates an error-CHECKING code, and is one way (i.e cannot be used to get the data back).
  1012. ; To check, simply run this function again with the same parameters. If the result is the same, nothing's changed.
  1013.        
  1014. ecc_generate_parity:
  1015.     SET PUSH, I
  1016.     SET PUSH, J
  1017.     ADD J, I
  1018.     SET B, [I]
  1019.     ecc_generate_parity_loop:
  1020.         IFE I, J
  1021.             SET PC, ecc_generate_parity_loop_end
  1022.         ADD I, 1
  1023.         XOR B, [I]
  1024.     ecc_generate_parity_loop_end:
  1025.     SET J, POP
  1026.     SET I, POP
  1027.     SET PC, POP
  1028.  
  1029. ; -----------------------------------------------------------------------
  1030. ; ecc_generate_crc - Generate a crc for a block of data.
  1031. ; This function calculates an 8-bit CRC for a block of data pointed to by I with a length of J.
  1032. ; This function returns the CRC in B.
  1033. ; The generator polynomial is 0x8408 (CRC-16-CCITT).
  1034.  
  1035. ecc_generate_crc:
  1036.     ; The bitmask for the leftmost divisor bit is 8000 (1000000000000000 in binary)
  1037.     ; input is in I/J
  1038.     ; result goes to B
  1039.     ; loop2 counter goes to Y.
  1040.     ; X is used as a bitmask in the inner loop, and as an "end-word" register (aka it contains the last word to be CRC'd)
  1041.     SET PUSH, A
  1042.     SET PUSH, C
  1043.     SET PUSH, X
  1044.     SET PUSH, Y
  1045.     SET C, 0
  1046.     SET X, I
  1047.     ADD X, J
  1048.     SET B, 0
  1049.     ecc_gen_crc_loop:
  1050.         IFE I, X
  1051.             SET PC, ecc_gen_crc_loop_end
  1052.         XOR B, [I]
  1053.         SET Y, 0
  1054.         ecc_gen_crc_loop_2:
  1055.             IFE Y, 8
  1056.                 SET PC, ecc_gen_crc_loop_2_end
  1057.             SET PUSH, X
  1058.             SET X, B
  1059.             AND X, 0x0001
  1060.             SHR B, 1
  1061.             IFG X, 0
  1062.                 XOR B, 0x8408
  1063.             ADD Y, 1
  1064.             SET X, POP
  1065.             SET PC, ecc_gen_crc_loop_2
  1066.         ecc_gen_crc_loop_2_end:
  1067.             ADD I, 1
  1068.             ADD C, 1
  1069.             SET PC, ecc_gen_crc_loop
  1070.     ecc_gen_crc_loop_end:
  1071.     SET Y, POP
  1072.     SET X, POP
  1073.     SET C, POP
  1074.     SET A, POP
  1075.     SET PC, POP
  1076.  
  1077. ; -----------------------------------------------------------------------
  1078. ; rand_gen_lfsr - generate a pseudorandom number with a Linear Feedback Shift Register
  1079. ; This function sets B to a pseudorandom number generated with a LFSR (polynomial 004B, or x^16+x^14+x^13+x^11+1).
  1080. ; To seed the RNG, set [kern_rng_state] to any value.
  1081.  
  1082. rand_gen_lfsr:
  1083.     SET B, [kern_rng_state] ; B will store the output bit (and later, the resulting state)
  1084.     AND B, 0x8000 ; Get LSB (output bit)
  1085.     SHL [kern_rng_state], 1 ; Shift register
  1086.     BOR [kern_rng_state], EX ; Make sure we get the excess
  1087.     IFG B, 0 ; Is the output bit on?
  1088.         XOR [kern_rng_state], 0x004B ; If so, then XOR the state with the tap-value, or 0x004B.
  1089.     SET B, [kern_rng_state] ; Set B to the output
  1090.     SET PC, POP ; return
  1091.  
  1092. kern_code_end:
  1093. DAT 0xC0DE ; kernel end codeword
  1094.  
  1095. program:
  1096.    
  1097.     ;
  1098.     ; This program simply calculates a parity word for the (assembled) kernel and displays it to the user. This tests disp_write_str, disp_write_word, and ecc_generate_parity.
  1099.     ; This program simply calculates the CRC of the (assembled) kernel and displays it to the user. This tests the above and ecc_generate_crc.
  1100.     ; It then sleeps for a second, testing the clock and sys_timer.
  1101.     ; It then prompts the user to type in anything, and echoes the typed string back to the user. This tests keyboard_read_str and disp_x_y_to_i.
  1102.     ; It then sleeps for 5 seconds.
  1103.     ; Then, it jumps to one of three random loops: "Bitmap", "FuzzyScreen", or "Psychedelic". These write random words (or values derived from such) to the screen. This tests the RNG and its randomness, as well as the clock.
  1104.     ; Note that of these three, "Psychedelic" is the best to use for testing, as it is the only one that uses all 16 bits of the random value. The other loops only test the lowest two bits.
  1105.     ;
  1106.    
  1107.     JSR hw_detect
  1108.    
  1109.     SET X, 0
  1110.     SET Y, 1
  1111.     SET C, 0xF000
  1112.     SET Z, program_str1
  1113.     JSR disp_write_str
  1114.    
  1115.     SET X, 0
  1116.     SET Y, 0
  1117.     SET C, 0xF000
  1118.     SET Z, program_str2
  1119.     JSR disp_write_str
  1120.    
  1121.     SET I, kern_code_start
  1122.     SET J, kern_code_end
  1123.     SUB J, I
  1124.     JSR ecc_generate_parity
  1125.     SET [program_parity1], B
  1126.    
  1127.     SET X, 17
  1128.     SET Y, 0
  1129.     SET C, 0xA000
  1130.     SET Z, [program_parity1]
  1131.     JSR disp_write_word
  1132.    
  1133.     SET X, 22
  1134.     SET Y, 0
  1135.     SET C, 0xF000
  1136.     SET Z, program_period
  1137.     JSR disp_write_str
  1138.    
  1139.     SET I, kern_code_start
  1140.     SET J, kern_code_end
  1141.     SUB J, I
  1142.     JSR ecc_generate_crc
  1143.     SET [program_crc1], B
  1144.    
  1145.     SET X, 14
  1146.     SET Y, 1
  1147.     SET C, 0xA000
  1148.     SET Z, [program_crc1]
  1149.     JSR disp_write_word
  1150.    
  1151.     SET X, 18
  1152.     SET Y, 1
  1153.     SET C, 0xF000
  1154.     SET Z, program_period
  1155.     JSR disp_write_str
  1156.    
  1157.     SET X, 0
  1158.     SET Y, 2
  1159.     SET Z, program_str3
  1160.     SET C, 0xF000
  1161.     JSR disp_write_str
  1162.    
  1163.     SET X, 15
  1164.     SET Y, 2
  1165.     JSR disp_x_y_to_i
  1166.     SET Z, program_dat1
  1167.     JSR keyboard_read_str
  1168.    
  1169.     SET X, 0
  1170.     SET Y, 3
  1171.     JSR disp_write_str
  1172.    
  1173.     SET X, 19
  1174.     SET Y, 0
  1175.     SET C, 0xF000
  1176.     SET Z, program_period
  1177.     JSR disp_write_str
  1178.    
  1179.     SET X, 50
  1180.     JSR kern_sleep
  1181.    
  1182.     SET A, 1
  1183.     HWI [hw_clock]
  1184.     SET X, C
  1185.    
  1186.     ; At this point, we can jump to one of three "random display" loops:
  1187.     ;   * Bitmap: Set characters on the screen to uniform black or white
  1188.     ;   * FuzzyScreen: Produce a "static" effect
  1189.     ;   * Psychedelic: Produce a wide variety of colors/characters
  1190.    
  1191.     ;SET PC, rand_fuzzyscreen
  1192.     SET PC, rand_psychedelic ; Feel free to change the instructions (they both work, in other words)
  1193.    
  1194.     ; Bitmap is the "default"
  1195.    
  1196.     rand_bitmap:
  1197.         SET I, 0x8000
  1198.         rand_bitmap_loop:
  1199.             SET A, 1
  1200.             HWI [hw_clock]
  1201.             IFE C, X ; Has there been a "tick" since we last checked?
  1202.                 SET [kern_rng_state], C
  1203.             IFE C, X
  1204.                 SET X, C
  1205.             IFG I, 0x8182
  1206.                 SET PC, rand_bitmap
  1207.             JSR rand_gen_lfsr
  1208.             SET Y, B
  1209.             AND Y, 0x8000
  1210.             SET A, 0x0020
  1211.             IFG Y, 0
  1212.                 BOR A, 0xF000
  1213.             IFE Y, 0
  1214.                 BOR A, 0x0F00
  1215.             SET [I], A
  1216.             ADD I, 1
  1217.             SET PC, rand_bitmap_loop
  1218.            
  1219.     rand_fuzzyscreen:
  1220.         SET I, 0x8000
  1221.         rand_fuzzyscreen_loop:
  1222.             SET A, 1
  1223.             HWI [hw_clock]
  1224.             IFE C, X ; Has there been a "tick" since we last checked?
  1225.                 SET [kern_rng_state], C
  1226.             IFE C, X
  1227.                 SET X, C
  1228.             IFG I, 0x8182
  1229.                 SET PC, rand_fuzzyscreen
  1230.             JSR rand_gen_lfsr
  1231.             SET Y, B
  1232.             SET A, B
  1233.             AND Y, 0x8000
  1234.             AND A, 0x3000
  1235.             SHR A, 12
  1236.             IFG Y, 0
  1237.                 BOR A, 0xF000
  1238.             IFE Y, 0
  1239.                 BOR A, 0x0F00
  1240.             SET [I], A
  1241.             ADD I, 1
  1242.             SET PC, rand_fuzzyscreen_loop
  1243.            
  1244.     rand_psychedelic:
  1245.         SET I, 0x8000
  1246.         rand_psychedelic_loop:
  1247.             SET A, 1
  1248.             HWI [hw_clock]
  1249.             IFE C, X ; Has there been a "tick" since we last checked?
  1250.                 SET [kern_rng_state], C
  1251.             IFE C, X
  1252.                 SET X, C
  1253.             IFG I, 0x8182
  1254.                 SET PC, rand_psychedelic
  1255.             JSR rand_gen_lfsr
  1256.             SET [I], B
  1257.             ADD I, 1
  1258.             SET PC, rand_psychedelic_loop
  1259.        
  1260.     program_crc1:
  1261.     DAT 0
  1262.     program_parity1:
  1263.     DAT 0
  1264.     program_crc2:
  1265.     DAT 0
  1266.     program_dat1:
  1267.     DAT 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; 32 words for the readbuffer
  1268.     program_period:
  1269.     DAT ".", 0
  1270.     program_str1:
  1271.     DAT "CRC code is 0x", 0 ; length is 14
  1272.     program_str2:
  1273.     DAT "Parity code is 0x", 0 ; length is 20
  1274.     program_str3:
  1275.     DAT "Type anything. ", 0 ;length is 15
  1276.     program_str4:
  1277.     DAT "System clock", 0
  1278.     program_str5:
  1279.     DAT "Test String!", 0 ; 54 65 73 74 20 53 74 72 69 6E 67
  1280.    
  1281. ; In the notes for this kernel, the terms "function" and "subroutine" are to be interpreted as the same thing, despite the slight differences between the terms.
  1282. ; **********************************************************************************************************************************************************************************************************************************************************************
  1283. ;
  1284. ;   -1 Up / KillaVanilla's DCPU-16 Kernel / API
  1285. ;        ( also known as UnnamedAPI )
  1286. ;           Current Version: 1.4
  1287. ;       ----------------------------
  1288. ;   Current Features:
  1289. ;    * System Clock / Countdown Timer:
  1290. ;       The system clock stores the number of seconds since the DCPU-16 booted as a 80-bit little endian unsigned integer. (64 bits for the seconds, 16 bits for the sub-second.)
  1291. ;       Each system tick is 1/10th of a second.
  1292. ;       The countdown timer decreases by one every tick, and is 1 word in length.
  1293. ;    * HW Detection:
  1294. ;       This is pretty much a standard feature on almost every kernel out there.
  1295. ;       The hw_detect function / subroutine saves hardware IDs to special addresses in memory that can be accessed with labels, such as "hw_vectordisp" (SPED-3 Vector Display) and "hw_keyboard" (Generic Keyboard).
  1296. ;    * Multiple Interrupt Handlers:
  1297. ;       This kernel supports a "kernel interrupt table" that allows you to set custom interrupt handlers for interrupts 0-127.
  1298. ;    * "Register-Safe" Code:
  1299. ;       All register values are pushed to the stack before any subroutine begins execution. Therefore, you can rest assured that your registers won't unexpectedly change due to subroutine calls.
  1300. ;    * Keyboard API:
  1301. ;       Has four functions:
  1302. ;           keyboard_read_raw: Blocks until the user presses a key.
  1303. ;           keyboard_read_char: Blocks until the user presses one of the ASCII character keys, RETURN, or BACKSPACE (aka the "text input" keys.) (also accounts for Shift).
  1304. ;           keyboard_read_special: Blocks until the user presses a "special" key (aka any key that is not a letter, RETURN, or BACKSPACE.)
  1305. ;           keyboard_read_str: Writes an entire line of characters to a specified memory address. (Works like C++'s cin and C's getline().)
  1306. ;    * Graphics API:
  1307. ;       Pretty self-explanatory, and has two functions:
  1308. ;           disp_write_str: Writes a null-terminated (C-style) string to the monitor.
  1309. ;           disp_write_word: Writes a hex word (like 0xC0DE) to the monitor.
  1310. ;           disp_cls: Clears the screen.
  1311. ;    * Floppy Drive API:
  1312. ;       This isn't much to look at right now. It has two functions:
  1313. ;           floppy_drive_block_read: Reads a sector from a floppy disk into the DCPU's RAM, and blocks until the read operation is finished.
  1314. ;           floppy_drive_block_read: Writes a sector to a floppy disk from the DCPU's RAM, and blocks until the write operation is finished.
  1315. ;    * Error Detection Code API:
  1316. ;       Has 2 functions:
  1317. ;           ecc_generate_parity: Calculates a parity code for a block of data.
  1318. ;           ecc_generate_crc: Calculates a Cyclic Redundancy Check (CRC) code for a block of data.
  1319. ;    * Random Number Generator:
  1320. ;       The kernel's RNG is implemented as a linear feedback shift register, or LFSR for short. The RNG's state is stored in kern_rng_state.
  1321. ;       To seed the RNG, simply set kern_rng_state to any value (clock ticks are a good choice).
  1322. ;       I've run one test on this data, and that is to write the data directly to screen. It looks pretty random to me. However, I'm no expert on randomness, so use this RNG at your own risk, and definitely DON'T use this for real-world encryption.
  1323. ;    * Floating Point Operations:
  1324. ;       The floating point operations included here haven't been tested yet, as I can't find any way to test them. Beware. This API has 7 functions:
  1325. ;           floating_add - Add floating point numbers
  1326. ;           floating_sub - Subtract floating point numbers
  1327. ;           floating_mul - Multiply floating point numbers
  1328. ;           floating_div - Divide floating point numbers
  1329. ;           floating_shift - Shift the exponents of floating point numbers, so that arithmetic can be done. (It's used internally.)
  1330. ;           floating_greater_than - A greater than (>) operator for floating point numbers
  1331. ;           floating_less_than - A less than (<) operator for floating point numbers
  1332. ;           All functions work with 32 bit floating point numbers.
  1333. ;    * Math API:
  1334. ;       I'll work on this some more once the Floating Point Operations API is confirmed to work. This currently has 3 functions:
  1335. ;           math_abs - Get absolute value
  1336. ;           math_flipsign - Flip a number's sign (pos --> neg / neg --> pos)
  1337. ;           math_exponent - Calculate an exponent
  1338. ;
  1339. ;   Each function has a description before its definition, describing what it does, what parameters it takes (and in what registers), and any other important info.
  1340. ;
  1341. ;   There is also a sample program included with the kernel, showing off a few features of the kernel (and is also handy for debugging)
  1342. ;          
  1343. ;   To be included:
  1344. ;       * Vector Display API (Any ideas on functions?)
  1345. ;       * FAT FS API (Maybe someday...)
  1346. ;
  1347. ; **********************************************************************************************************************************************************************************************************************************************************************
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement