$bytes = [] def zero_fill(pos) while ($bytes.length <= pos) do $bytes.push(0) end end def word(i) $bytes.push((i & 0x000000ff), (i & 0x0000ff00) >> 8, (i & 0x00ff0000) >> 16, (i & 0xff000000) >> 24) end def string(s) $bytes.push *s.bytes while (($bytes.length % 4) != 0) do $bytes.push 0 end end # # # INSTRUCTIONS # # # def jmp(addr) # TODO: this probs wont show up since we have < 3mb of ram but # we can't jump to an address with a different 4 most significant bits raise "jmp addr must be 4 byte aligned" if addr % 4 != 0 op = 0b0000_1000_0000_0000_0000_0000_0000_0000 op = op | ((addr >> 2) & 0b11_11111111_11111111_11111111) word op end def jal(addr) # TODO: same problem as jmp raise "jmp addr must be 4 byte aligned" if addr % 4 != 0 op = 0b0000_1100_0000_0000_0000_0000_0000_0000 op = op | ((addr >> 2) & 0b11_11111111_11111111_11111111) word op end # load upper immediate # NOTE: val will be shifted left by 16 def lui(val, dest) # oooooo ----- ttttt iiiiiiiiiiiiiiii op = 0b001111_00000_00000_0000000000000000 op |= 0xffff & val op |= (0b11111 & dest) << 16 word op end # shift right logical def srl(src, amt, dest) # oooooo ----- sssss ddddd hhhhh oooooo op = 0b000000_00000_00000_00000_00000_000010 op |= (src & 0b11111) << 16 op |= (amt & 0b11111) << 6 op |= (dest & 0b11111) << 11 word op end # or immediate def ori(src, bits, dest) # oooooo sssss ddddd iiiiiiii iiiiiiii op = 0b001101_00000_00000_00000000_00000000 op |= (src & 0b11111) << 21 op |= (bits & 0xffff) op |= (dest & 0x11111) << 16 word op end # # # PSEUDO-INSTRUCTIONS # # # def nop word 0x00000000 end # this is a terrible idea and im doing it #$labels = {} #def method_missing(m, *args) # puts m.to_s # super #end # # # CONSTANTS # # # $base_addr = 0x80010000 # 0x10000 # 0x80010000 $file_size = 0x800 $gp0 = 0x1F801810 # # # EXE HEADER # # # string "PS-X EXE" zero_fill 0x00f word $base_addr # initial pc word 0x00000000 # initial GP/R28 word $base_addr # destintation address in RAM word $file_size # file size excluding header (must be N * 0x800) word 0x00000000 # Unknown/Unused word 0x00000000 # Unknown/Unused word 0x00000000 # Memfill start address word 0x00000000 # Memfill size in bytes word 0x801ffff0 # Initial SP/R29 & FP/R30 Base word 0x00000000 # Initial SP/R29 & FP/R30 Offs zero_fill 0x4b # Reserved for A(43h) Function # Ascii marker would go here zero_fill 0x7ff $exe_header = $bytes[0..] $bytes = [] # # # PROGRAM CODE # # # nop ; jmp $base_addr + 16 ; nop ; word 0xdeadbeef # ops should always be in format of # src [args] -> dest lui $gp0 >> 16, 1 ori 1, $gp0, 1 nop ; nop ; nop ; nop nop ; nop ; nop ; nop nop ; nop ; nop ; nop nop ; nop ; nop ; nop jmp $base_addr nop string "this is a test lol" zero_fill $file_size - 1 f = File.new "LOADTHIS.EXE", "wb" f.write $exe_header.pack("C*") f.write $bytes.pack("C*") f.close