Guest User

Untitled

a guest
Jun 19th, 2018
1,858
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 17.56 KB | None | 0 0
  1. import pygame
  2. pygame.init()
  3. import random
  4. from collections import OrderedDict
  5.    
  6.  
  7. class UInt:
  8.    
  9.     def __init__(self, size, value):
  10.         self._max_value = 2 ** size
  11.         self._value = value % self._max_value
  12.        
  13.     @property
  14.     def value(self):
  15.         return self._value
  16.        
  17.     @value.setter
  18.     def value(self, value):
  19.         self._value = value
  20.         self._value %= self._max_value
  21.  
  22.        
  23. class CPU:
  24.    
  25.     def __init__(self, rom, logging=False):
  26.         self._init_general_vars(logging)
  27.         self._init_registers()
  28.         self._init_gfx_ram()
  29.         self._init_keypad()
  30.         self._init_ram(rom)
  31.        
  32.     def _init_general_vars(self, logging):
  33.         self._opcode = UInt(16, 0)
  34.         self._opcode_name = "Not yet set"
  35.         #Some opcodes do not increment the PC by two, this is set to true if
  36.         #any of them are called.
  37.         self._special_opcode = False
  38.         self._cycle_count = 0
  39.         self._logging = logging
  40.         if self._logging:
  41.             dir = r"C:\Users\John\Desktop\Programming\Python\CHIP-8\log.txt"
  42.             self._log_file = open(dir, "w")
  43.    
  44.     def _init_registers(self):
  45.         self._V = [UInt(16, 0) for x in range(16)]
  46.         self._I = UInt(16, 0)
  47.         self._DT = UInt(8, 0)
  48.         self._ST = UInt(8, 0)
  49.         self._PC = UInt(16, 512)
  50.         #The SP starts at -1 as calling a subroutine increments the SP,
  51.         #so starting at -1 allows it to point to the true start(index 0)
  52.         #instead of the second element(index 1) the first time one is called.
  53.         self._SP = UInt(8, -1)
  54.         self._stack = [UInt(16, 0) for x in range(16)]
  55.        
  56.     def _init_gfx_ram(self):
  57.         self.gfx_w = 64
  58.         self.gfx_h = 32
  59.         self.gfx_ram = [[0 for y in range(self.gfx_h)]
  60.                          for x in range(self.gfx_w)]
  61.        
  62.     def _init_keypad(self):
  63.         self._keypad_state = [0 for x in range(16)]
  64.        
  65.     def _update_keypad(self):
  66.         keys = pygame.key.get_pressed()
  67.         self._keypad_state[0] = keys[pygame.K_1]
  68.         self._keypad_state[1] = keys[pygame.K_2]
  69.         self._keypad_state[2] = keys[pygame.K_3]
  70.         self._keypad_state[3] = keys[pygame.K_4]
  71.         self._keypad_state[4] = keys[pygame.K_q]
  72.         self._keypad_state[5] = keys[pygame.K_w]
  73.         self._keypad_state[6] = keys[pygame.K_e]
  74.         self._keypad_state[7] = keys[pygame.K_r]
  75.         self._keypad_state[8] = keys[pygame.K_a]
  76.         self._keypad_state[9] = keys[pygame.K_s]
  77.         self._keypad_state[10] = keys[pygame.K_d]
  78.         self._keypad_state[11] = keys[pygame.K_f]
  79.         self._keypad_state[12] = keys[pygame.K_z]
  80.         self._keypad_state[13] = keys[pygame.K_x]
  81.         self._keypad_state[14] = keys[pygame.K_c]
  82.         self._keypad_state[15] = keys[pygame.K_v]
  83.        
  84.     def _init_ram(self, rom):
  85.         self._ram = [UInt(8, 0) for x in range(4096)]
  86.         self._load_fontset()
  87.         self._load_rom(rom)
  88.        
  89.     def _load_fontset(self):
  90.         self._fontset_loc = 0
  91.         self._fontset = [[0xF0, 0x90, 0x90, 0x90, 0xF0], #0
  92.                          [0x20, 0x60, 0x20, 0x20, 0x70], #1
  93.                          [0xF0, 0x10, 0xF0, 0x80, 0xF0], #2
  94.                          [0xF0, 0x10, 0xF0, 0x10, 0xF0], #3
  95.                          [0x90, 0x90, 0xF0, 0x10, 0x10], #4
  96.                          [0xF0, 0x80, 0xF0, 0x10, 0xF0], #5
  97.                          [0xF0, 0x80, 0xF0, 0x90, 0xF0], #6
  98.                          [0xF0, 0x10, 0x20, 0x40, 0x40], #7
  99.                          [0xF0, 0x90, 0xF0, 0x90, 0xF0], #8
  100.                          [0xF0, 0x90, 0xF0, 0x10, 0xF0], #9
  101.                          [0xF0, 0x90, 0xF0, 0x90, 0x90], #A
  102.                          [0xE0, 0x90, 0xE0, 0x90, 0xE0], #B
  103.                          [0xF0, 0x80, 0x80, 0x80, 0xF0], #C
  104.                          [0xE0, 0x90, 0x90, 0x90, 0xE0], #D
  105.                          [0xF0, 0x80, 0xF0, 0x80, 0xF0], #E
  106.                          [0xF0, 0x80, 0xF0, 0x80, 0x80]] #F
  107.         for sprite_count, sprite in enumerate(self._fontset):
  108.             block = self._fontset_loc + sprite_count * 5
  109.             for byte_count, byte in enumerate(sprite):
  110.                 sub_block = block + byte_count
  111.                 self._ram[sub_block].value = byte
  112.                
  113.     def _load_rom(self, rom):
  114.         prog_space = len(self._ram) - self._PC.value
  115.         rom_stream = (byte for byte in rom.read(prog_space))
  116.         for i, byte in enumerate(rom_stream, self._PC.value):
  117.             self._ram[i].value = byte
  118.    
  119.     def _x(self):
  120.         return (self._opcode.value & 0x0F00) >> 8
  121.        
  122.     def _y(self):
  123.         return (self._opcode.value & 0x00F0) >> 4
  124.    
  125.     def _kk(self):
  126.         return self._opcode.value & 0x00FF
  127.    
  128.     def _n(self):
  129.         return self._opcode.value & 0x000F
  130.    
  131.     def _nnn(self):
  132.         return self._opcode.value & 0x0FFF
  133.    
  134.     def _log_state(self):
  135.         state = OrderedDict([("opcode name", self._opcode_name),
  136.                              ("opcode", hex(self._opcode.value)),
  137.                              ("cycle count", self._cycle_count),
  138.                              ("V", [reg.value for reg in self._V]),
  139.                              ("I", self._I.value),
  140.                              ("DT", self._DT.value),
  141.                              ("ST", self._ST.value),
  142.                              ("PC", self._PC.value),
  143.                              ("SP", self._SP.value),
  144.                              ("stack", [reg.value for reg in self._stack]),
  145.                              ("keypad_state", [value for value in
  146.                                                self._keypad_state])])
  147.         for key, value in state.items():
  148.             self._log_file.write(key)
  149.             self._log_file.write(" : ")
  150.             self._log_file.write(str(value))
  151.             self._log_file.write("\n")
  152.         self._log_file.write("\n")
  153.         for key, value in state.items():
  154.             print(key, ":", value)
  155.         print("\n")
  156.        
  157.     #Instruction set starts here
  158.     #---------------------------
  159.     def _CLS(self):
  160.         """Clears the display."""
  161.         for x in range(self.gfx_w):
  162.             for y in range(self.gfx_h):
  163.                 self.gfx_ram[x][y] = 0
  164.            
  165.     def _RET(self):
  166.         """Sets the program counter to the address at the top of the stack,
  167.         then subtracts 1 from the stack pointer."""
  168.         self._PC.value = self._stack[self._SP.value].value
  169.         self._SP.value -= 1
  170.         self._special_opcode = True
  171.        
  172.     def _JP_addr(self):
  173.         """Sets the program counter to nnn."""
  174.         self._PC.value = self._nnn()
  175.         self._special_opcode = True
  176.    
  177.     def _CALL_addr(self):
  178.         """Increments the stack pointer, then puts the current program counter
  179.         on the top of the stack. The program counter is then set to nnn"""
  180.         self._SP.value += 1
  181.         self._stack[self._SP.value].value = self._PC.value
  182.         self._PC.value = self._nnn()
  183.         self._special_opcode = True
  184.        
  185.     def _SE_Vx_byte(self):
  186.         """Compares register Vx to kk, and if they are equal, increments the
  187.         program counter by 2."""
  188.         if self._V[self._x()].value == self._kk():
  189.             self._PC.value += 2
  190.            
  191.     def _SNE_Vx_byte(self):
  192.         """Compares register Vx to kk, and if they are not equal,
  193.         increments the program counter by 2."""
  194.         if self._V[self._x()].value != self._kk():
  195.             self._PC.value += 2
  196.            
  197.     def _SE_Vx_Vy(self):
  198.         """Compares register Vx to register Vy, and if the are equal,
  199.         increments the program counter by 2."""
  200.         if self._V[self._x()].value == self._V[self._y()].value:
  201.             self._PC.value += 2
  202.    
  203.     def _LD_Vx_byte(self):
  204.         """Puts the value kk into register Vx."""
  205.         self._V[self._x()].value = self._kk()
  206.        
  207.     def _ADD_Vx_byte(self):
  208.         """Adds the value kk to the value of register Vx, then stores the
  209.         result in Vx."""
  210.         self._V[self._x()].value += self._kk()
  211.        
  212.     def _LD_Vx_Vy(self):
  213.         """Stores the value of register Vy in register Vx."""
  214.         self._V[self._x()].value = self._V[self._y()].value
  215.        
  216.     def _OR_Vx_Vy(self):
  217.         """Performs a bitwise OR on the values of Vx and Vy,
  218.         then stores the result in Vx."""
  219.         self._V[self._x()].value |= self._V[self._y()]
  220.        
  221.     def _AND_Vx_Vy(self):
  222.         """Performs a bitwise AND on the values of Vx and Vy,
  223.         then stores the result in Vx."""
  224.         self._V[self._x()].value &= self._V[self._y()].value
  225.        
  226.     def _XOR_Vx_Vy(self):
  227.         """Performs a bitwise exclusive OR on the values of Vx and Vy,
  228.         then stores the result in Vx."""
  229.         self._V[self._x()].value ^= self._V[self._y()].value
  230.        
  231.     def _ADD_Vx_Vy(self):
  232.         """The values of Vx and Vy are added together. If the result is
  233.         greater than 8 bits(255) VF is set to 1, otherwise 0. Only the lowest
  234.         8 bits of the result are kept, and stored in Vx."""
  235.         result = self._V[self._x()].value + self._V[self._y()].value
  236.         if result > 255:
  237.             self._V[15].value = 1
  238.         else:
  239.             self._V[15].value = 0
  240.         result &= 0xFF
  241.         self._V[self._x()].value = result
  242.        
  243.     def _SUB_Vx_Vy(self):
  244.         """If Vx > Vy, then VF is set to 1, otherwise 0. Then Vy is subtracted
  245.         from Vx, and the result is stored in Vx."""
  246.         if self._V[self._x()].value > self._V[self._y()].value:
  247.             self._V[15].value = 1
  248.         else:
  249.             self._V[15].value = 0
  250.         self._V[self._x()].value -= self._V[self._y()].value
  251.        
  252.     def _SHR_Vx_Vy(self):
  253.         """If the least significant bit of Vx is 1, then VF is set to 1,
  254.         otherwise 0. Then Vx is divided by 2."""
  255.         if self._V[self._x()].value & 1 == 1:
  256.             self._V[15].value = 1
  257.         else:
  258.             self._V[15].value = 0
  259.         self._V[self._x()].value /= 2
  260.        
  261.     def _SUBN_Vx_Vy(self):
  262.         """If Vy > Vx, then VF is set to 1, otherwise 0. Then Vx is subtracted
  263.         from Vy, and the result is stored in Vx."""
  264.         if self._V[self_y()].value > self._V[self._x()].value:
  265.             self.__V[15].value = 1
  266.         else:
  267.             self.__V[15].value = 0
  268.         result = self._V[self_y()].value - self._V[self._x()].value
  269.         self._V[self._x()].value = result
  270.        
  271.     def _SHL_Vx_Vy(self):
  272.         """If the most significant bit of Vx is 1, then VF is set to 1,
  273.         otherwise 0. Then Vx is multiplied by 2."""
  274.         if (self._V[self._x()].value & 0x80) >> 8 == 1:
  275.             self._V[15].value = 1
  276.         else:
  277.             self._V[15].value = 0
  278.         self._V[self._x()].value *= 2
  279.        
  280.     def _SNE_Vx_Vy(self):
  281.         """The values of Vx and Vy are compared, and if they are equal,
  282.         the program counter is incremented by 2."""
  283.         if self._V[self._x()].value == self._V[self._y()].value:
  284.             self._PC.value += 2
  285.            
  286.     def _LD_I_addr(self):
  287.         """The value of register I is set to nnn."""
  288.         self._I.value = self._nnn()
  289.        
  290.     def _JP_V0_addr(self):
  291.         """The program counter is set to nnn plus the value of V0."""
  292.         self._PC.value = self._nnn() + self._V[0].value
  293.        
  294.     def _RND_Vx_byte(self):
  295.         """Generates a random number from 0 to 255, which is then ANDed with
  296.         the value of kk. The results are stored in Vx."""
  297.         self._V[self._x()].value = random.randrange(0, 256) & self._kk()
  298.        
  299.     def _DRW_Vx_Vy_nibble(self):
  300.         """Reads n bytes from memory, starting at the address stored in I.
  301.         These bytes are then displayed as sprites on screen at the coordinates
  302.         (Vx, Vy). Sprites are XORed onto the existing screen. If this causes
  303.         any pixels to be erased, VF is set to 1, otherwise 0. If the sprite is
  304.         positioned so part of it is outside the coordinates of the display,
  305.         it wraps around to the opposite side of the screen."""
  306.         sprites = (self._ram[self._I.value+n].value for n in range(self._n()))
  307.         for sprite_count, sprite in enumerate(sprites):
  308.             for bit_count in range(8):
  309.                 #Extracts the bit in the place equal to variable bit_1.
  310.                 sprite_bit = (sprite >> bit_count) & 1
  311.                 #We use modular arithmetic to wrap the coordinates.
  312.                 x = (self._V[self._x()].value + (7 - bit_count)) % self.gfx_w
  313.                 y = (self._V[self._y()].value + sprite_count) % self.gfx_h
  314.                 if sprite_bit ^ self.gfx_ram[x][y] == 0:
  315.                     self._V[15].value = 1
  316.                 else:
  317.                     self._V[15].value = 0
  318.                 self.gfx_ram[x][y] ^= sprite_bit
  319.                
  320.     def _SKP_Vx(self):
  321.         """Checks the keyboard, and if the key corresponding to the value of
  322.         Vx is currently in the down position, the program counter is
  323.         incremented by 2."""
  324.         if self._keypad_state[self._V[self._x()].value]:
  325.             self._PC.value += 2
  326.            
  327.     def _SKNP_Vx(self):
  328.         """Checks the keyboard, and if the key corresponding to the value of
  329.         Vx is currently in the up position, the program counter is
  330.         incremented by 2."""
  331.         if not self._keypad_state[self._V[self._x()].value]:
  332.             self._PC.value += 2
  333.            
  334.     def _LD_Vx_DT(self):
  335.         """The value of DT is placed into Vx."""
  336.         self._V[self._x()].value = self._DT.value
  337.        
  338.     def _LD_Vx_K(self):
  339.         """All execution stops until a key is pressed, then the value of that
  340.         key is stored in Vx."""
  341.         while True:
  342.             for i, key in enumerate(self._keypad_state):
  343.                 if key:
  344.                     self._V[self._x()].value = i
  345.                     return
  346.             self._update_keypad()
  347.            
  348.     def _LD_DT_Vx(self):
  349.         """DT is set equal to the value of Vx."""
  350.         self._DT.value = self._V[self._x()].value
  351.        
  352.     def _LD_ST_Vx(self):
  353.         """ST is set equal to the value of Vx."""
  354.         self._ST.value = self._V[self._x()].value
  355.        
  356.     def _ADD_I_Vx(self):
  357.         """The values of I and Vx are added, and the result is stored in I."""
  358.         self._I.value += self._V[self._x()].value
  359.        
  360.     def _LD_F_Vx(self):
  361.         """The value of I is set to the location for the hexadecimal sprite
  362.         corresponding to the value of Vx."""
  363.         self._I.value = (self._V[self._x()].value * 5) + self._fontset_loc
  364.        
  365.     def _LD_B_Vx(self):
  366.         """Takes the decimal value of Vx, and places the hundreds digit in
  367.         memory at location I, the tens digit at location I+1, and the ones
  368.         digit at location I+2."""
  369.         value = self._V[self._x()].value
  370.         for i in range(3):
  371.             self._ram[self._I.value+i].value = int(value % 10)
  372.             value /= 10
  373.            
  374.     def _LD_I_Vx(self):
  375.         """Copies the values of registers V0 through Vx into memory,
  376.         starting at address I."""
  377.         for i in range(self._x()):
  378.             self._ram[self._I.value+i].value = self._V[i].value
  379.    
  380.     def _LD_Vx_I(self):
  381.         """Reads values from memory starting at I into registers V0 through
  382.         Vx."""
  383.         for i in range(self._x()):
  384.             self._V[i].value = self._ram[self._I.value+i].value
  385.     #-------------------------
  386.     #Instruction set ends here
  387.        
  388.    
  389.     def _fetch_opcode(self):
  390.         self._opcode.value = self._ram[self._PC.value].value << 8
  391.         self._opcode.value |= self._ram[self._PC.value+1].value
  392.        
  393.     def _decode_opcode(self):
  394.         if self._opcode.value & 0xFFFF == 0x00E0:
  395.             self._opcode_name = "CLS"
  396.             self._CLS()
  397.         elif self._opcode.value & 0xFFFF == 0x00EE:
  398.             self._opcode_name = "RET"
  399.             self._RET()
  400.         elif self._opcode.value & 0xF000 == 0x1000:
  401.             self._opcode_name = "JP_addr"
  402.             self._JP_addr()
  403.         elif self._opcode.value & 0xF000 == 0x2000:
  404.             self._opcode_name = "CALL_addr"
  405.             self._CALL_addr()
  406.         elif self._opcode.value & 0xF000 == 0x3000:
  407.             self._opcode_name = "SE_Vx_byte"
  408.             self._SE_Vx_byte()
  409.         elif self._opcode.value & 0xF000 == 0x4000:
  410.             self._opcode_name = "SNE_Vx_byte"
  411.             self._SNE_Vx_byte()
  412.         elif self._opcode.value & 0xF000 == 0x5000:
  413.             self._opcode_name = "SE_Vx_Vy"
  414.             self._SE_Vx_Vy()
  415.         elif self._opcode.value & 0xF000 == 0x6000:
  416.             self._opcode_name = "LD_Vx_byte"
  417.             self._LD_Vx_byte()
  418.         elif self._opcode.value & 0xF000 == 0x7000:
  419.             self._opcode_name = "ADD_Vx_byte"
  420.             self._ADD_Vx_byte()
  421.         elif self._opcode.value & 0xF00F == 0x8000:
  422.             self._opcode_name = "LD_Vx_Vy"
  423.             self._LD_Vx_Vy()
  424.         elif self._opcode.value & 0xF00F == 0x8001:
  425.             self._opcode_name = "OR_Vx_Vy"
  426.             self._OR_Vx_Vy()
  427.         elif self._opcode.value & 0xF00F == 0x8002:
  428.             self._opcode_name = "AND_Vx_Vy"
  429.             self._AND_Vx_Vy()
  430.         elif self._opcode.value & 0xF00F == 0x8003:
  431.             self._opcode_name = "XOR_Vx_Vy"
  432.             self._XOR_Vx_Vy()
  433.         elif self._opcode.value & 0xF00F == 0x8004:
  434.             self._opcode_name = "ADD_Vx_Vy"
  435.             self._ADD_Vx_Vy()
  436.         elif self._opcode.value & 0xF00F == 0x8005:
  437.             self._opcode_name = "SUB_Vx_Vy"
  438.             self._SUB_Vx_Vy()
  439.         elif self._opcode.value & 0xF00F == 0x8006:
  440.             self._opcode_name = "SHR_Vx_Vy"
  441.             self._SHR_Vx_Vy()
  442.         elif self._opcode.value & 0xF00F == 0x8007:
  443.             self._opcode_name = "SUBN_Vx_Vy"
  444.             self._SUBN_Vx_Vy()
  445.         elif self._opcode.value & 0xF00F == 0x800E:
  446.             self._opcode_name = "SHL_Vx_Vy"
  447.             self._SHL_Vx_Vy()
  448.         elif self._opcode.value & 0xF00F == 0x9000:
  449.             self._opcoe_name = "SNE_Vx_Vy"
  450.             self._SNE_Vx_Vy()
  451.         elif self._opcode.value & 0xF000 == 0xA000:
  452.             self._opcode_name = "LD_I_addr"
  453.             self._LD_I_addr()
  454.         elif self._opcode.value & 0xF000 == 0xB000:
  455.             self._opcode_name = "JP_V0_addr"
  456.             self._JP_V0_addr()
  457.         elif self._opcode.value & 0xF000 == 0xC000:
  458.             self._opcode_name = "RND_Vx_byte"
  459.             self._RND_Vx_byte()
  460.         elif self._opcode.value & 0xF000 == 0xD000:
  461.             self._opcode_name = "DRW_Vx_Vy_nibble"
  462.             self._DRW_Vx_Vy_nibble()
  463.         elif self._opcode.value & 0xF0FF == 0xE09E:
  464.             self._opcode_name = "SKP_Vx"
  465.             self._SKP_Vx()
  466.         elif self._opcode.value & 0xF0FF == 0xE0A1:
  467.             self._opcode_name = "SKNP_Vx"
  468.             self._SKNP_Vx()
  469.         elif self._opcode.value & 0xF0FF == 0xF007:
  470.             self._opcode_name = "LD_Vx_DT"
  471.             self._LD_Vx_DT()
  472.         elif self._opcode.value & 0xF0FF == 0xF00A:
  473.             self._opcode_name = "LD_Vx_K"
  474.             self._LD_Vx_K()
  475.         elif self._opcode.value & 0xF0FF == 0xF015:
  476.             self._opcode_name = "LD_DT_Vx"
  477.             self._LD_DT_Vx()
  478.         elif self._opcode.value & 0xF0FF == 0xF018:
  479.             self._opcode_name = "LD_ST_Vx"
  480.             self._LD_ST_Vx()
  481.         elif self._opcode.value & 0xF0FF == 0xF01E:
  482.             self._opcode_name = "ADD_I_Vx"
  483.             self._ADD_I_Vx()
  484.         elif self._opcode.value & 0xF0FF == 0xF029:
  485.             self._opcode_name = "LD_F_Vx"
  486.             self._LD_F_Vx()
  487.         elif self._opcode.value & 0xF0FF == 0xF033:
  488.             self._opcode_name = "LD_B_Vx"
  489.             self._LD_B_Vx()
  490.         elif self._opcode.value & 0xF0FF == 0xF055:
  491.             self._opcode_name = "LD_I_Vx"
  492.             self._LD_I_Vx()
  493.         elif self._opcode.value & 0xF0FF == 0xF065:
  494.             self._opcode_name = "LD_Vx_I"
  495.             self._LD_Vx_I()
  496.         else:
  497.             self._opcode_name = "Unknown"
  498.    
  499.     def emulate_cycle(self):
  500.         self._update_keypad()
  501.         self._fetch_opcode()
  502.         self._decode_opcode()
  503.         self._cycle_count += 1
  504.         if not self._special_opcode:
  505.             self._PC.value += 2
  506.         self._special_opcode = False
  507.         if self._logging:
  508.             self._log_state()
  509.  
  510.        
  511. def main():            
  512.     dir = r"C:\Users\John\Desktop\Programming\Python\CHIP-8\ch8.ch8"
  513.     rom = open(dir, "rb")
  514.     cpu = CPU(rom)
  515.     res = (cpu.gfx_w, cpu.gfx_h)
  516.     scale = 20
  517.     scaled_res = (res[0] * scale, res[1] * scale)
  518.     white = (255, 255, 255)
  519.     black = (0, 0, 0)
  520.     clock = pygame.time.Clock()
  521.     buf = pygame.Surface(res)
  522.     window = pygame.display.set_mode(scaled_res)
  523.     pygame.display.set_caption("CHIP-8")
  524.    
  525.     while True:
  526.         cpu.emulate_cycle()
  527.        
  528.         for x in range(cpu.gfx_w):
  529.             for y in range(cpu.gfx_h):
  530.                 if cpu.gfx_ram[x][y] == 1:
  531.                     buf.set_at((x, y), white)
  532.        
  533.         for event in pygame.event.get():
  534.             if event.type == pygame.QUIT:
  535.                 pygame.quit()
  536.                 quit()
  537.                    
  538.         pygame.transform.scale(buf, scaled_res, window)
  539.         buf.fill(black)
  540.         pygame.display.flip()
  541.         clock.tick()
  542.    
  543. if __name__ == "__main__":
  544.     main()
Advertisement
Add Comment
Please, Sign In to add comment