你好 这是基于Raspberry Pi的复古游戏机。 在NES游戏机的墨盒中。 可以将集成屏幕用于游戏。 通过HDMI输出视频时,它会显示游戏封面的图像以及核心温度,请参见照片。 我建议您稍作思索,并阅读有关此类设备的组装和配置的信息。 注意,然后会有大量流量和照片。
怀旧
在童年时代,我们(年龄在25-35岁之间)喜欢玩游戏机。 然后,控制台没有新词了,所以我将其称为。 我对游戏机的了解始于Dandy(NES克隆)。 超级马里奥兄弟(Super Mario Bros),魂斗罗(Contra),鸭子故事(Ducktales),巴特蟾蜍(Battletoads)只是
当时的热门歌曲 。 然后整个院子将与我的朋友Sega(Sega Mega Drive)一起玩,如Sonic,Ultimate Mortal Combat 3,Contra Hard Corps等。 当Play Station推出时,我必须说,它并没有立即传给我们,《生化危机》系列给我们带来了真正令人恐惧的喜悦。
这张照片帮助我消除了怀旧的眼泪。 我必须说,我不是第一个在NES墨盒中配备Raspberry Pi的人。 是的,这不是我的设备。 这款墨盒小巧美观,几乎是这些目的的理想之选。 里面有很多空间。 自己判断。
在Raspberry Pi Zero内,有一个USB集线器和一对延长线。 所有的棍棒都放在热熔胶上。
组装方式
我想收集相同或相似的东西。 选择了来自NES的相同墨盒。 其他选项很小,或者看起来不是很好。 Raspberry Pi 3B是复古车的炽热心脏。 在Ali上也购买了带有方便焊接针脚的USB连接器。 仅此而已。
哦,是的,您将重复这个项目,不要带上损坏的墨盒。 他们很少。 采取一些更普遍或更鲜为人知的东西。 也可以选择与Ali一起使用墨盒,但是原装墨盒却能使人心旷神怡。 我的1986年发行。
如果将墨盒
固定在三颗螺钉上,则还需要使用特殊的螺丝刀。 也有早期的墨盒选件,带有五个螺钉;它们用普通的平头螺丝刀拧开。 我只有一个。
用办公刀和钢锯条从刀片上切下所有干扰零件,并从中锯掉。
突出的连接器焊接到Raspberry Pi。 专家说,如果您先用焊钳小心地拆下连接器,然后一次焊接一根脚,就可以不用焊台。 全部粘到热熔胶上。 在USB连接器和覆盆子之间放置了一个由非消耗性塑料制成的绝缘子。 不要忘记将GND Raspberry Pi和USB连接器的主体连接起来(上图中未显示)。 否则,某些操纵杆将无法工作。
最后一个
Retropie安装在
树莓上 。 起初有
Recalbox ,但我拒绝了它,因为它不支持Playstation 1上的操纵杆振动。但是我必须说,就开箱即用的功能而言,Recalbox更为方便,您无需进行任何配置。 在Retropie一堆设置中,您可以无休止地进行自定义。 这就是我喜欢的东西。
这是发生了什么事。 任何带有xinput的操纵杆都已连接。
萤幕
食欲与进食有关。 如何将屏幕嵌入墨盒中? 播放或显示游戏的封面图像。
这样的屏幕是有序的。 这是一个800 * 480 3.5英寸并行DPI屏幕,几乎使用了所有GPIO Raspberry Pi。 它在120 Hz模式下对我有效(但渲染仍为60 Hz),响应是即时的。 唯一的负面因素是6位矩阵。 仅262,144种颜色。 尽管总的来说,这并不是特别明显,但请自行判断。
游戏《 Comix Zone》中的屏幕截图(可点击)
屏幕和Raspberry Pi的所有支脚均已焊接。 屏幕由破旧的IDE电缆中的两根电缆焊接而成。 屏幕下方安装了5毫米抵押贷款,它不接触墨盒的底壁。 绝缘带被粘在显示器的周围,以免侧面闪烁。 一切都粘在热胶上。 在顶盖上,我切开一个窗户并粘贴了2毫米厚的玻璃。
为了开始在该屏幕上显示图像,您需要修复
/boot/config.txt配置。 我为Windows所有者推荐
WinSCP ,当通过SSH连接到Raspberry Pi时,
WinSCP可以像Total Commander中那样显示文件。 很舒服 特别是如果您在
shell模式下
sudo su-运行它,则可以访问所有文件。
不幸的是,当DPI屏幕打开时,HDMI视频输出不起作用。 因此,我在
/ boot /文件夹中创建了两个
配置文件 ,一个是
config_hdmi.txt ,另一个是
config_dpi.txt 。
config_hdmi.txt配置将分辨率设置为1080p60Hz,并删除了过扫描。
config_dpi.txt包含屏幕的DPI设置。
config_dpi.txt# uncomment if you get no picture on HDMI for a default "safe" mode #hdmi_safe=1 disable_overscan=1 # uncomment to force a specific HDMI mode (this will force VGA) #hdmi_group=1 #hdmi_mode=1 # Sound output. Set to 0 or comment for autodetect, 1 for DVI, 2 to force HDMI. #hdmi_drive=2 # Using /etc/modules is deprecated and no longer supported on 4.4 kernel # So manually enable audio dtparam=audio=on config_hdmi_boost=0 # force hdmi while the tv can take time before sending the signal on the hdmi output hdmi_force_hotplug=1 # uncomment for composite PAL #sdtv_mode=2 # uncomment for lirc-rpi #dtoverlay=lirc-rpi #3.5 HD tft screen 800x480 dtoverlay=dpi24 overscan_left=0 overscan_right=0 overscan_top=0 overscan_bottom=0 #Banggood framebuffer_width=800 framebuffer_height=480 dtparam=spi=off dtparam=i2c_arm=off enable_dpi_lcd=1 display_default_lcd=1 dpi_output_format=0x6f015 dpi_group=2 dpi_mode=87 hdmi_timings=480 0 16 16 24 800 0 4 2 2 0 0 0 120 0 46080000 6 display_rotate=3 # if you plug your tv at the same time as your rpi and that the rpi switches from the hdmi or give a low resolution because tv had no enough time to initialize it boot_delay=3 # uncomment if you don't want the rainbow at startup #disable_splash=1 # default CEC name #cec_osd_name=recalbox dtparam=spi=off # Overclock gpu_mem_256=128 gpu_mem_512=256 gpu_mem_1024=256 overscan_scale=1 gpu_mem=256 start_x=0 enable_uart=0 avoid_safe_mode=1 kernel=zImage
config_hdmi.txt # For more options and information see # http://rpf.io/configtxt # Some settings may impact device functionality. See link above for details # uncomment if you get no picture on HDMI for a default "safe" mode #hdmi_safe=1 # uncomment this if your display has a black border of unused pixels visible # and your display can output without overscan disable_overscan=1 # uncomment the following to adjust overscan. Use positive numbers if console # goes off screen, and negative if there is too much border #overscan_left=16 #overscan_right=16 #overscan_top=16 #overscan_bottom=16 # uncomment to force a console size. By default it will be display's size minus # overscan. #framebuffer_width=1280 #framebuffer_height=720 # uncomment if hdmi display is not detected and composite is being output hdmi_force_hotplug=1 # uncomment to force a specific HDMI mode (this will force VGA) hdmi_group=1 #1080p60fps hdmi_mode=16 # uncomment to force a HDMI mode rather than DVI. This can make audio work in # DMT (computer monitor) modes #hdmi_drive=2 # uncomment to increase signal to HDMI, if you have interference, blanking, or # no display #config_hdmi_boost=4 # uncomment for composite PAL #sdtv_mode=2 #uncomment to overclock the arm. 700 MHz is the default. #arm_freq=800 # Uncomment some or all of these to enable the optional hardware interfaces #dtparam=i2c_arm=on #dtparam=i2s=on dtparam=spi=off # Uncomment this to enable the lirc-rpi module #dtoverlay=lirc-rpi # Additional overlays and parameters are documented /boot/overlays/README # Enable audio (loads snd_bcm2835) dtparam=audio=on gpu_mem_256=128 gpu_mem_512=256 gpu_mem_1024=256 overscan_scale=1 gpu_mem=256 start_x=0 enable_uart=0
切换配置将是我们在网络上可用的自动脚本
\\ 192.168.x.xxx \ configs \ all \ autostart.sh或设备上的文件夹/opt/retropie/configs/all/autostart.sh
还编写了
switchscreen.sh脚本,该脚本必须放在
/ home / pi / RetroPie / retropiemenu /中 。 该脚本可手动切换配置,可从Retropie设置主菜单访问。 启动后,您需要拔出HDMI电缆,否则重新启动后,所有内容都会自动切换回原来的状态。 不要忘记注册脚本
chmod +x /home/pi/RetroPie/retropiemenu/switchscreen.sh
当HDMI打开时,
Autostart.sh显示的代码跟踪将禁用屏幕的DPI。 我将此脚本复制到了Internet上,因此无法在我们的屏幕上使用。 我们可能会与晶体管混淆以关闭屏幕电源,但为什么呢,如果我们需要显示当前正在运行的游戏的封面图像。 您只需要弄清楚什么是DPI。
并行显示接口(DPI)
如前所述,DPI是屏幕的并行接口。 此接口上的信息
一次 ,
两次且
计算错误 。 好吧,现在这里是俄语。
在HDMI操作期间,使用控制台命令启用DPI的所有尝试均失败。 也许他做错了什么。 采用了计划B:将图像显示在小屏幕上,以编程方式拉动GPIO脚。
DPI的特征在于,在时钟信号的每个时钟周期将一个像素传输到显示器。 由于我们有一个6位矩阵,因此它们是18种用于三种颜色的引脚,并且还具有显示使能(指示有效日期),h_sync(在显示控制器中将水平行地址设置为零),v_sync(在显示控制器中将垂直行地址设置为零) ) 数据捕捉发生在时钟信号的下降沿。 如果我们根据此术语从config_dpi.txt中解密“ dpi_output_format = 0x6f015”行,这是已知的。
dpi_output_format output_format = (dpi_output_format >> 0) & 0xf; rgb_order = (dpi_output_format >> 4) & 0xf; output_enable_mode = (dpi_output_format >> 8) & 0x1; invert_pixel_clock = (dpi_output_format >> 9) & 0x1; hsync_disable = (dpi_output_format >> 12) & 0x1; vsync_disable = (dpi_output_format >> 13) & 0x1; output_enable_disable = (dpi_output_format >> 14) & 0x1; hsync_polarity = (dpi_output_format >> 16) & 0x1; vsync_polarity = (dpi_output_format >> 17) & 0x1; output_enable_polarity = (dpi_output_format >> 18) & 0x1; hsync_phase = (dpi_output_format >> 20) & 0x1; vsync_phase = (dpi_output_format >> 21) & 0x1; output_enable_phase = (dpi_output_format >> 22) & 0x1; output_format: 1: DPI_OUTPUT_FORMAT_9BIT_666 2: DPI_OUTPUT_FORMAT_16BIT_565_CFG1 3: DPI_OUTPUT_FORMAT_16BIT_565_CFG2 4: DPI_OUTPUT_FORMAT_16BIT_565_CFG3 5: DPI_OUTPUT_FORMAT_18BIT_666_CFG1 6: DPI_OUTPUT_FORMAT_18BIT_666_CFG2 7: DPI_OUTPUT_FORMAT_24BIT_888 rgb_order: 1: DPI_RGB_ORDER_RGB 2: DPI_RGB_ORDER_BGR 3: DPI_RGB_ORDER_GRB 4: DPI_RGB_ORDER_BRG output_enable_mode: 0: DPI_OUTPUT_ENABLE_MODE_DATA_VALID 1: DPI_OUTPUT_ENABLE_MODE_COMBINED_SYNCS invert_pixel_clock: 0: RGB Data changes on rising edge and is stable at falling edge 1: RGB Data changes on falling edge and is stable at rising edge. hsync/vsync/output_enable_polarity: 0: default for HDMI mode 1: inverted hsync/vsync/oe phases: 0: DPI_PHASE_POSEDGE 1: DPI_PHASE_NEGEDGE

比特序列如上图所示。 对于以VSYNC开头的每条线,都有一个完整的HSYNC线测量周期。 这是一帧。 后廊和前廊是显示屏的所谓缩进,它们位于控制器的内存中,但不在屏幕上。
现在,从我们的config_dpi.txt中解码“ hdmi_timings = 480 0 16 16 24 800 0 4 2 2 0 0 0 120 0 46080000 6”行。 这里没有什么复杂的,只需按顺序编写参数即可。
该图片显示了哪些GPIO脚用于彩色渲染。 我们有模式5。注意,这些不是按顺序排列的,即GPIO表示法! 其他信号时钟-GPIO 0,DE-GPIO 1,VSYNC-GPIO 2,HSYNC-GPIO 3。
快速安装了python,必要的GPIO库,并编写了一个hello脚本,至少将屏幕涂成蓝色。 当Windows上的Notepad ++没有显示缩进处的缩进时,我也出现了认知失调,而换行时我做了制表符,而不是空格。 顺便说一句,VSCode犯了同样的错误,如何解决它,我没有找到。
Python脚本 from gpiozero import LED from time import sleep sleep_time = 0.0 clock = LED(0) de = LED(1) vsync = LED(2) hsync = LED(3) red2 = LED(16) red3 = LED(17) red4 = LED(18) red5 = LED(19) red6 = LED(20) red7 = LED(21) green2 = LED(10) green3 = LED(11) green4 = LED(12) green5 = LED(13) green6 = LED(14) green7 = LED(15) blue2 = LED(4) blue3 = LED(5) blue4 = LED(6) blue5 = LED(7) blue6 = LED(8) blue7 = LED(9) def v_sync(frame): vsync.on() for n in range(frame): clock.on()
太慢了,Python。 令我惊讶的是,已经渲染的像素消失了。 尽管我的期望很明显。
决定用C重写所有内容。它的工作速度更快,大约每秒几帧。 屏幕像旧的CRT显示器或雷达上一样起伏不定。 您需要什么。 复古! 该代码发布在
GitHub上 。
GPIO可通过BCM2837 SoC寄存器直接访问。 我在
这里举了代码示例。
一切始于一个很小的程序,但是现在也以小滚动条的形式显示处理器和内存的负载。 处理器温度以这种字体绘制。
要运行代码,您需要将存储库的内容复制到文件夹/ home / pi / lcd_screen /(谁知道如何在nix下写相对于二进制文件的路径而不是C中的工作文件夹?因此,到目前为止只写到该文件夹)并执行以下命令。
gcc ./lcd_screen/lcd.c -o ./lcd_screen/lcd chmod +x ./lcd_screen/lcd
或立即从发行版下载二进制文件。 要开始,您需要输入以下内容。 SUDO是访问GPIO所必需的。
sudo ./lcd_screen/lcd path/file.bmp usec_per_frame
其中“ path / file.bmp”是图像文件的路径,仅适用于BMP格式,“ usec_per_frame”是指帧之间的延迟(以微秒为单位),以免徒劳地加载处理器。
我们将自动启动LCD程序,以便在游戏运行时显示所需的封面。 当然,Retropie使用内置的刮刀装载封面。
安装图像转换器。 它将所有格式转换为程序支持的bmp。 同时,并调整大小,以使图像全屏显示。
sudo apt-get install imagemagick
在
/ opt / retropie / configs / all /目录中,创建两个文件:
runcommand-onstart.sh和
runcommand-onend.sh 。 当加载/结束任何游戏时,Retropie会自动执行这些脚本。 请记住为每个文件分配chmod + x。
在开始脚本中,首先检查DPI连接的存在,然后搜索jpeg或png格式的图像,将其旋转到所需的角度,更改其大小并转换为bmp格式,然后我的程序以必要的参数开始。
冷却方式
Raspberry Pi 3B比Zero强大,并且需要良好的散热。 特别是在这种封闭的情况下。 在照片中可见一个小的散热器,在任何模拟器上玩了半个小时之后,核心温度达到80度并开始小跑。
订购了40 * 30 * 10毫米的离心风扇,但是直到它到达之前,我只是试图用3毫米的铝切成一块80 * 30毫米的小板。 到那时,我已经卸下了所有GPIO引脚,因此它们不再干扰板的安装。 另外,我还切出一块20 * 10mm的小片与芯片接触,并用板子做一个三明治。 这超出了我的所有期望,核心最高为65度。
所以它看起来在里面。
到底是什么
这是怎么玩的? 太好了! 伴随着尖叫声,击败游戏手柄,相互指责。 就像一次。
没有发现延迟或滞后。
屏幕当然很小,只有三英寸半。 五英寸智能手机宠坏了我们,但您可以玩。 文字可读,甚至很小。 我更喜欢HDMI。
您可以来找朋友,玩,便携性允许。 相关附件:电缆,电缆,操纵杆,充电装置要比控制台本身占用更多的空间。
音效
不幸的是,Raspberry Pi的标准声音令人无法满足。 带有无源滤波的PWM调制被用作声音系统。 因此,在PCM2704上购买了USB DAC。 主要是因为它的大小。
在小液晶显示屏上播放时,确实没有足够的声音输出,所以我还购买了NS8002上的3W微型放大器,并从8欧姆平板电脑上接了一个扬声器。
所有这些都适合LCD屏幕。 会来,我会放。
文件追溯
组装完成。 以下是一些不太有趣的用于娱乐阅读的Retropie设置。
着色器大多数能够模拟Raspberry Pi的控制台,其分辨率均为320x240像素。 按照今天的标准,这很小。 所有游戏在现代屏幕上均具有明显的像素化。
作为Retropie的一部分的Retroarch的创建者解决了这个问题,并增加了对着色器的支持。 例如,我真的很喜欢预装的
xbr-lv1-noblend.glslp 。 他从字面上拉出了细节。 见下文。
游戏《恶魔城:夜晚的交响曲》的屏幕截图,我建议你玩要安装着色器,请转到菜单Retropie->
Configuration editor 。 选择“
配置基本的libretro模拟器选项” ,然后选择“
为所有libretro模拟器配置默认选项” 。 然后将“
Video Shader Enable ”设置为“ true”,并将“
Video Shader File”设置为所需的着色器。 同样,将“
视频模糊度 ”也设置为“ false”,因为它只会模糊图像。 您甚至可以选择诸如扫描线着色器之类的东西来发出CRT电视的效果。 但这并不适合所有人。
渲染着色器是一项相当昂贵的操作。 分辨率等于或高于720p时,RPi 3B上会出现明显的卡纸。 因此,在同一菜单中,选择
渲染分辨率 “ 800x600”。 不用担心,如果您
之前对
/boot/config.txt文件
进行了更改(如本文中所述),HDMI电缆上的屏幕分辨率将为1080p,但是仿真器将以800x600的分辨率渲染图像并将其拉伸到全屏。 而且他做得还不错。 至少使用着色器要好于没有着色器,并且1080p渲染是无用的,因为仍然以320x240的分辨率绘制游戏的视频数据。
游戏杆设置如果您有任何xinput游戏手柄(Micro $ oft标准),它将可以。 它是在Retropie的第一次启动时配置的,也可以通过开始按钮-配置输入进行配置。 但是令人头疼。 为了不因专利诉讼而落伍,狡猾的海外人士用A和B,X和Y交换了按钮。
如果您有xbox或类似产品的游戏手柄,则需要使用反转按钮进行配置,例如NES。 然后转到Retropie->
Retropie Setup ,选择
Configuration / tools ,然后选择
emulationstation ,将“ Swapped”
放入ES中的
Swap A / B Buttons中 。 然后重新配置操纵杆。
另外,我不喜欢Retropie开发人员如何管理按钮式基金。 用于拍摄屏幕快照的按钮组合在哪里? 为什么每次按下重置按钮都需要重置按钮? 倒带和时间加速按钮在哪里?
要解决此问题,您需要在
/ opt / retropie / configs / all / retroarch-joypads /中使用操纵杆名称编辑文件。 它也可以在
\\ 192.168.x.xxx \ configs \ all \ retroarch-joypads \网络上使用。 通过更新程序对Retropie进行每次更新后,绑定的编号就会消失,因此我将不会上传整个配置。 我写道,我只更改了这些按钮。 当与热键(通常是操纵杆中间带有徽标的按钮)同时按下时,将执行它们。
按钮配置 input_screenshot_btn = "0" input_rewind_btn = "h0left" input_hold_fast_forward_btn = "h0right" input_state_slot_increase_btn = "h0up" input_state_slot_decrease_btn = "h0down"
此处分配了屏幕截图按钮,而不是重置按钮。 快进和快退(快退)在交叉按钮上配置:前进和后退。 向上和向下十字按钮更改保存槽。
必须在
/opt/retropie/configs/all/retroarch.cfg配置中启用倒带。 只是不要在psx模拟器上启用Rewind,一切都会开始缓慢地变慢。 psx配置中默认情况下禁用倒带。
我也想补充一下蓝牙。 我自己不喜欢无线操纵杆,并且总是玩电缆。 老学校了。 对于喜欢无线游戏杆的人,您需要购买蓝牙加密狗并将其插入USB端口。 会更好,不会有任何问题。 我自己没有检查,但是有知识的人写。
Xboxdrv
但这还不是全部。 在
程序包管理器的
Retropie设置中,您可以放置各种端口,例如,Openttd,Doom甚至是DOS Dosbox仿真器。 但是您将无法控制其中的操纵杆。 只有键盘和鼠标。 要解决此问题,您需要在包管理器中安装xboxdrv驱动程序,该驱动程序可以模拟击键。 只是从源头上讲,不需要执行自动运行,它不适合所有操纵杆。
我们将为游戏手柄编写启动脚本。 将以
下行添加到
/opt/retropie/configs/all/runcommand-onstart.sh中的文件
末尾 。
$ 1是xboxdrv启动的目标系统。 您可以类推添加。 --evdev-absmap --evdev-keymap行负责将轴和按钮绑定到游戏杆。 上面的脚本是为Xbox One S控制器提供的,要找出与操纵杆的编号或名称相对应的轴和按钮,您需要在控制台中键入
evtest命令。 同时,您可以看到哪个事件与我们的操纵杆相对应。 我在--evdev参数中有这个/ dev / input / event0。
--ui-axismap选项模拟鼠标轴和--ui-buttonmap键盘按钮。 在此示例中,触发器是鼠标按钮,左操纵杆是鼠标,右操纵杆是光标键。 单击开始,分别选择-输入和esc。 键盘数字附加在其余按钮上。 不幸的是,不可能使用键盘按钮下方的叉号。 由于某种原因,Xbox One S游戏杆拒绝工作。
像主题医院,OpenTTD等策略使用这种配置播放,但在射击游戏中播放情况稍差一些,但是您可以通过更改$ 1参数在同一文件中为射击游戏创建类似的启动脚本。
为了确保emulationstation中操纵杆的正常运行,您需要在退出游戏后完成xboxdrv。 为此,请将以下内容添加到
/opt/retropie/configs/all/runcommand-onend.sh文件的末尾。
runcommand-onend.sh sudo killall > /dev/null 2>&1 xboxdrv
如果更新Retropie时出现问题一次,我启动了Retropie更新,然后在解压缩内核时,内置的Wi-Fi掉线了。 设备启动,但未响应任何按钮,包括连接的键盘。 没有SSH,因为没有Wi-Fi,它无法响应键盘,因此您无法获得SD卡...
我注意到键盘在启动时可以工作。 我按了Ctrl + C很多次,哦,控制台! 但是,现在如何恢复Wi-Fi? 这个词根本没有wlan0接口。 运行更新程序无济于事,因为它会从Internet提取文件。
/opt/retropie/configs/all/autostart.sh中的第一件事评论了emulationstation的启动和重新引导。
重新启动后,控制台加载,键盘开始工作。进一步的谷歌如何返回WLAN给了这个。该命令将重新配置所有已安装的软件包。它有帮助。 sudo dpkg --configure -a
使Retropie看起来不像Linux工作站加载控制台时,我不想查看Linux启动日志。它破坏了90年代前缀的整个精神。删除Linux启动日志Linux,
/boot/cmdline.txt . .
cmdline.txt dwc_otg.lpm_enable=0 console=tty3 root=PARTUUID=f2d3cb4f-02 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait loglevel=3 consoleblank=0 plymouth.enable=0 quiet vt.global_cursor_default=0 plymouth.enable=0 plymouth.ignore-serial-consoles splash
, , , .
motd.
nano /etc/motd
.
sudo nano /etc/systemd/system/autologin@.service
ExecStart=-/sbin/agetty --autologin pi --noclear %I $TERM
ExecStart=-/sbin/agetty --skip-login --noclear --noissue --login-options "-f pi" %I $TERM
.
, — splashscreen. , . \\192.168.x.xxx\splashscreens, Retropie ->
SPLASH SCREEN ->
Append Splashscreen to list .
, , .
Retropie runcommand, . .
, ,
.
还有什么可以做的
您可以不断改善。我会给您几个可以完成的链接。写一些您可以添加的有趣的东西。谢谢您的关注。
他值得。