老菜鸟要问几个BAS问题。。。
当初在高中时一直在编BAS游戏,经常到各大论坛上看,后来升大学了,由于有了手机,就把文曲星搁浅了。前几天手机丢失,英语四级考试在即,于是又拿起了文曲星,发现里面以前编的程序,突然又有做游戏的激情了,可是发现自己忘了很多东西。
于是到各论坛,想查找相关的资料,发现文曲星空间站在维修,而主站和易码都换了风格,很多附件丢失,文字也有错,根本无从查找。
=================
注:我的文曲星是NC3000
=================
1)有比较全面一点的NC3000的PEEK,CALL表吗?
2)有比较详细点的批量法或速读法的教程吗?具体如何操作能详细说说吗?
比如说我在屏幕上画了一幅画,如何才能让这个滚屏读图器读取?
10 DATA (数据)
20 DATA (数据)
30 DATA (数据)
40 FOR I=20480 TO 20529:READ A: POKE I,A:FOR I=20560 TO 20571:READ A: POKE I,A
50 NEXT GRAH
60 INPUT "START PIC NUM:";SPN:INPUT "END PIC NUM:";EPN:CLS: POKE 801,SPN: POKE 802 EPN+1
70 OPEN "L" FOR RANDOM AS#1 LEN=20
80 FIELD #1,1 AS A$:SPN=PEEK(801):EPN=PEEK(802):FOR I=704 TO 803: POKE I,O:NEXT
90 FOR K=SPN*80-79 TO EPN*80-81
100 GET #1,K:CALL 20560:CALL 20480
110 NEXT K:GET #1,80*EPN-80:CALL 20560
3)如果我把一幅图片以以上读图器能读的格式存到DAT文件中,如何在它后面继续存N幅图片?好像不能用APPEND吧?最多能存多少幅?
4)在红色激情的《我是大角》中,可以在任意指定为止显示自己画的地图块,好像是16*16的吧?那能不能在任意位置显示任意大小的图块呢?如果不行,那有哪些大小的可以?(有32*32和8*8的最好)
5)关于2和3,还有个问题,当初好像用那种方法可以在BAS上实现灰度图,应该是连续在屏幕上显示图片吧。请问那个程序该怎么编?
================================
我看了以下的文章,附加一个:
================================
GVB显图4法(总结) --shuyufeng
注:仅测试过NC2600c
地址说明:
6592~8191: (图形缓冲区)
24575~24575-N: (GVB数据存储区.N为数据长度.注:该区数据由尾至头存储)
1.直接读取: (极速显图法)
如:
10 OPEN "XXX" FOR RANDOM AS#1 LEN=100
20 POKE 26254,192: POKE 26258,25:REM 读到图片显存
30 POKE 26262,64: POKE 26267,6:REM 每次读的大小
40 P=LOF(1)/1600-1:REM 图片张数
50 FOR Q=0 TO P
60 SE=Q*1600:REM 读文件的位置.当SE以20为步长递增或递减时可以实现滚图(SE=定值*1600+N:N=N+20)
70 H=INT(SE/256): L=SE-H*256
80 POKE 47446,L: POKE 47447,H:CALL 26207
90 NEXT:GOTO 20
注:贼快的方法.简单强大.显示b16图片效果也不错.该法单图DATA文件大小:1600
2.批量法(有点难度.被我称为欺骗法)
说明:当GVB中出现A$="XXX"等语句时GVB会把A$写入缓存.并记录A$的地址.此法要做的就是改变GVB记下的A$地址.
例:
10 CLEAR:CLS
20 A$="":B$=""
30 A=47302: DS=PEEK(A)+PEEK(A+1)*256:REM DS---第20条语句中A$&B$等的开始地址
40 POKE DS+2,200:REM A$的字符串长度
50 POKE DS+3,LD: POKE DS+4,HD:REM HD*256+LD=字符串开始地址
60 POKE DS+7,200: REM B$字符串的长度
70 POKE DS+8,192: POKE DS+9,2:REM 2*256+192=704(字符缓存开始地址)
80 LEST B$=A$: POKE 914,1: PRINT: POKE 914,0:END
注: POKE 914,1(显示小字体)POKE 914,0(显示大字体.GRAPH模式下不可用)DATA文件大小1600
3.矩行作图法: (研究中...)
10 POKE 34731,9
20 POKE X+Y*256,N:REM POKE图片数据到内存.X+Y*256为地址
30 POKE 152,X: POKE 153,Y:REM 2k6c好像要POKE 146,X: POKE 147,Y
40 BOX X,Y,X+XX,Y+YY,1,0:REM XX&YY为图片宽与高
=========================
要把以上的方法改为NC3000能用的,要如何修改?
========================
[ 本帖最后由 hdjackie 于 2008-5-18 07:50 编辑 ] 对BAS+6502不熟悉的飘过
PS:应该有很多教程的啊,搜索看看,要不官网那里看看 找过了,找到了很多,可是没有我想要的呀。
谢谢你,我继续等待。 对于你说 改成NC3000能用
我想,你得先把NC3000的资料找到
比如
20 POKE 26254,192: POKE 26258,25:REM 读到图片显存
NC3000的图片显存是什么,你就把他改为对应值就可以 找了一下,找到了这个:
最近发现有些人想用NC3000的批量法,但却不知道如何得到变量储存地址,所以我发了这一帖,希望新手能看的懂。
如果对批量法不了解的,可以在空间站上看这一帖
虾米们看的批量法
关于批量法,最主要的就是找到变量储存地址,NC3000的变量储存地址在$2000(十进制的8192,也就是显存后面)+文件长度。一般的程序,用到批量法的都是把程序写完后再到资源管理里面查看长度,这样在编程序时很不方便,每修改一次都要重新查看,所以我想,是不是文件长度都在内存里面存着呢?于是就写了下面的程序:
10 K=00000:HI=INT(K/256): LO=K-HI*256 //K用来储存文件长度
20 FOR W=2000 TO 3000
30 IF PEEK(W)<>LO THEN 60
40 IF PEEK(W+1)<>HI THEN 60
50 PRINT W
60 NEXT
70 END
80 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
90 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
100 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
110 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX //用来占位置
编好后储存,再到资源管理中得到文件大小,我的是294,然后修改程序 ,把K=00000改为K=00294(前面的0不能去掉!),程序变为:
10 K=00294:HI=INT(K/256): LO=K-HI*256
20 FOR W=2000 TO 3000
30 IF PEEK(W)<>LO THEN 60
40 IF PEEK(W+1)<>HI THEN 60
50 PRINT W
60 NEXT
70 END
80 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
90 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
100 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
110 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
然后运行程序,便可得到储存文件长度的内存地址了。我运行后是显示了三个地址:2246,2276,2299。经测试, 三个地址都表示文件长度。
所以,在批量法中,就可以直接在程序中写 DZ=PEEK(2246)+PEEK(2247)*256+8192了,修改了程序也不需要重新再查看文件长度了,是不是方便多了?
顺便说一下如何在GVB 中贴图
其实贴图就是用到了系统函数 INT $CA09,而LINE则调用了INT $CA0B,并且它们参数的地址相同,于是就可以把GVB 中的$CA0B改为$CA09,如此就可以实现贴图。同样的,我们用上面类似的寻找程序中的INT $CA0B所在的位置:
10 K=00294:A=00:B=11:C=202 //INT $CA0B的机器码
20 FOR W=16384 TO 65535
30 IF PEEK(W)<>A THEN 60
40 IF PEEK(W+1)<>B THEN 60
45 IF PEEK(W+2)<>C THEN 60
50 PRINT W
60 NEXT
70 END
运行后便可得到地址34666
因此我们POKE 34667,9,然后LINE X,Y,X+HIGHT,Y+WIDTH就可以贴图了,再POKE 34667,11 便可以用LINE话直线了。图象信息的地址需要POKE到146,147。
例如,你的图片存在地址5000,长16,宽16,要显示在(10,10)的位置,则程序如下:
HI=INT(5000/256)
LO=5000-HI*256
POKE 34667,9
POKE 146,LO
POKE 147,HI
LINE 10,10,10+16,10+16
END
[ 本帖最后由 hdjackie 于 2008-5-18 10:32 编辑 ] 中断号 该页里该中断的地址 含义
0501 438C //CheckCreatSuperBlock 测试超级块
0502 439E //InitNandRam 更新物理区/逻辑区映射表
0503 415E //phyNandPageRead 读取一页nand(物理,不做ecc校验)
0504 4170 //phyNandPageSpareRead 读取一页nand(物理,做ecc校验)
0505 4182 //NandReadBytes 逻辑读取nand (输入:nand物理扇区号[$0888],nand物理地址偏移3,缓冲地址[$F0],长度[$09D2] 输出:[$F0]所指的缓冲区)
0506 4194 //NandPageRead 读取一页nand(逻辑)
0507 41A6 //NorReadByte 读取1字节nor
0508 41B8 //NorReadBytes 读取多字节nor
0509 41CA //getpwd 根据指定的inode号(0x8d2~0x8d3)找出对应的目录名(0x88d)
050A 41DC 7D3A //opendir 测试目录是否可列出(输入:$088d,输出:C==0可列出,C==1不可列出)
050B 41EE //mkdir 创建目录
050C 4200 7DAE //readdir 读取目录
050D 4212 //chdir 切换工作目录(0x88d)
050E 4224 //unlink 删除文件(文件名:0x88d)
050F 4236 //rmdir 删除目录(0x88d)
0510 4248 //rename 重命名(原名称:0x88d,新名称:0x918)
0511 425A //chmod 永久修改指定文件属性1(参数:0x8ff)
0512 426C //fchmod 暂时修改指定文件属性1
0513 427E //access 测试指定文件属性1
0514 4290 //getfilelen 获取文件长度
0515 42A2 //open 打开或创建文件
0516 42B4 //read 读文件
0517 42C6 //close 关闭文件
0518 42D8 //write 写文件
0519 42EA //lseek 更改文件读写指针位置
051A 437A //find_inode 读inode
051B 42FC //ReadOneInode 读一个inode
051C 430E //InodeReclaimAll 空间整理_释放已删除空间
051D 4320 //SectorReclaim 空间整理_删除无用的分配表信息
051E 4332 //InodeValidCheck 重启时空间整理A
051F 4344 //SectorReclaimCheck 重启时空间整理B
0520 4356 //ud_inode_in_corps
0521 4368 //find_corpse
0522 414C //stst
0523 413A //closeall 关闭所有文件
0524 4128 //NandFlashFormat
0525 40F2 //sys_open
0526 4104 //sys_read
0527 4116 //sys_lseek
0528 40E0 //explorer
0529 40CE //CheckNandId
052A 4098 //New_UpGradeNcode
052B 40AA //UpGradeNcode
052C 40BC //UpGradeInit
052D 4074 //Get_NandFlash_Block
052E 4086 //Get_p_1st_Block
094D B26C //PlaySleep 关闭声音播放
094E B551 //PlayInit 初始化播放
094F B220 //PlayStop 暂停声音播放
0950 B375 //PlayFile 播放声音文件
0951 B595 //SetVolume 设置音量($03e9)
C001 //reset 重启
C002 //clear_memory 清空特殊地址
C003 //init_port 初始化io端口
C004 //open_803_lcd 打开803lcd
C005 //wait_key 按键停顿
C006 //repeat_key 键盘延迟
C007 //unputkey
C008 //proc_sys_event 通用系统事件
C009 //if_pushed
C00A //sys_key_proc
C00B //exe_down
C00C //ReadByte 读1bytes nor flash
C00D //WriteByte 写1bytes nor flash
C00E //ReadBytes 读nor flash
C00F //WriteBytes 写nor flash
C010 //Read4K 读4K nor flash
C011 //Write4K 写4K nor flash
C012 //B4KAddrConvert 4K地址转换
C013 //ToBlockForDB 找出数据库的物理块
C014 //BusGetAllBlock 找出名片的物理块表
C015 //BlkReqForNCDB
C016 //RawBlkReqForNCDB
C017 //FormatNCDB 格式化数据库区块
C018 //GetFreeBlkCount 获取数据库的可用区块
C019 //SectorErase 擦除块
C01A //SysSectorErase 擦除系统块
C01B //io_chk_same 判断ram和flash块是否相同
C01C //FL1Read 读flash
C01D //FL1Write 写flash
C01E //FLBytesRead
C01F //FLBytesWrite
C020 //Inf_ReadBytes 读取nor flash的出厂信息
C021 //lcd_bright 屏幕亮度
C022 //my_check_bout 初始化检查
C023 //com_download
C024 //FormatSuperBlock
C025 //FormatOther
C026 //WriteBytes_sys
C701 D963 //get_16x16_font 获取16x16字模 中文(输入:[$92](汉字内码) 输出字模地址0280)
C702 D9F8 //ccg
C703 DEBB //get_8x10_font 获取8x10字模 英文(输入:A(ASCII码) 输出字模地址0280)
C704 DDB8 //get_8x16_font 获取8x16字模 英文(输入:A(ASCII码) 输出字模地址0280)
C705 DBE8 //get_12x12_font 获取12x12字模 中文(输入:[$92](汉字内码) 输出字模地址:$0280)
C706 DE56 //get_6x12_font 获取6x12字模 英文(输入:A(ASCII码) 输出字模地址:$0280)
C707 CD01 //flash_cursor 闪动光标
C708 C6AB //write_8x8_font 写8x8字模
C709 CA4A //write_8x16_code 写8x16码
C70A C6F7 //write_8x16_font 写8x16字模
C70B C743 //write_16x16_font 写16x16字模
C70C CA51 //write_16x16_code 写16x16码
C70D C838 //write_6x12_font 写6x12字模
C70E C4CA //write_6x12_code 写6x12码
C70F D125 //write_6x12_lable 写6x12标号
C710 C4D1 //write_12x12_code1 写12x12码
C711 D1AA //write_8x10_lable 写8x10标号
C712 D1DC //write_8x10_font 写8x10字模
C713 CA70 //write_ascii 写ascll码
C714 CAA8 //write_one_char 写一个字符
C715 CA88 //write_chi_code 写中文码
C716 CA58 //write_ascii_tiny 写小的ascii码
C717 CB66 //update_one_line 更新一行屏幕
C718 C198 //update_lcd 刷新屏幕
C719 C1A2 //update_lcd_0 刷新屏幕0
C71A D0D6 //update_Icon 刷新屏幕两边的数码管
C71B D120 //wefont 写英文
C71C D11B //wcfont 写中文
C71D CCA6 //convert_scr 转换
C71E CC40 //convert_nline_ser
C71F CC65 //convert_part
C720 C4F7 //get_char_index
C721 C5D9 //get_char_posi
C722 C4D8 //cal_curr_CPR_RPS
C723 CC35 //move_CharAttr_0
C724 CBA3 //clear_line 清除一行
C725 C509 //get_large_char_index
C726 C667 //check_attr
C727 C51D //get_small_char_index
C728 C8D6 //write_12x12_font 写12x12字模
C729 D71D //clrscreen 清除图形缓存
C72A D6A1 //clear_screen 清除文字缓存
C72B D6B3 //clear_nline_ser 清除某一行屏幕
C72C D5B1 //set_disp_bar
C72D D649 //disp_bcd 显示bcd码
C72E D474 //int2trf int to trf
C72F D407 //gb_int2trf
C730 D3EA //trf2int
C731 D3A0 //gb_trf2int
C732 D789 //to_number 转为数字
C733 D4A4 //bin2bcd 把数字转成字符
C734 D533 //bcd4bin
C735 D7B9 //recover_Icon
C736 D4DE //bin3bcd
C737 D73D //clr_but_icon
CA01 C9E9 //to_ascii
CA02 C8A4 //int_divd
CA03 C9B0 //mul_ax
CA04 C2BB //put_dot
CA05 C2B3 //get_dot
CA06 C1F1 //Dr_squre
CA07 C18A //Dr_block
CA08 C2F8 //Dr_line
CA09 C05F //w_block
CA0A C193 //block_draw 方块
CA0B C301 //line_draw 线
CA0C C1FA //squre_draw 方快
CA0D C031 //write_block
CA0E C524 //circle_draw 圆
CA0F C54B //ellipse_draw 椭圆
CA10 C514 //fill_circle 填充圆
CA11 C51C //fill_ellipse 填充椭圆
CA12 CA2E //Open_win 仿win信息框
CA13 CA4F //Refresh_win
CA14 D29A //rollmenu 等级棒
CA15 D5E8 //proc_menu1 通用菜单
CA16 D982 //show_in_find 正在查找
CA17 DA02 //show_no_find 没有找到
CB01 C57B //bbs_oldmon 进入系统debug
CB02 CD11 //proc_menu
CB03 D11D //offset_next_item
CB04 D1A8 //get_key_word
CB05 D674 //float
CB06 D24F //input 输入法
CB07 D27B //inputz
CB08 C894 //data_view
CB09 D7D7 //show_help 显示帮助
CB0A D83F //arrow_2
CB0B DAE3 //NCWholeToPC
CB0C DAEB //NCWholeFromPC
以上是杨家将很早以前发的NC3000中断表................的一部分,我只把常用的发上来
想要call的话,知道这些就足够了吧..
[ 本帖最后由 windybell 于 2008-6-5 07:08 编辑 ] 回答第3个问题先~
append是绝对行不通的,它只能给顺序结构的dat文件添加数据。你需要的仅仅是把存有图片数据的dat文件以随机存取模式(RANDOM)打开,设定缓冲区长度之后,从文件后面一块一块加进去罢了。依照你那个读图器的代码来看...恩,一幅图的长度是1600,可以把缓冲区设为100,然后分16次把数据PUT到文件末尾就好了。
基本上就是下面这个操作了。
OPEN "FILE" FOR RANDOM AS #1 LEN=100
FIELD #1,100 AS D$
I=LOF(1)/100
FOR J=1 TO 16
LSET D$=我也不晓得该等于啥...反正就是你的数据呗
PUT #1,I+J
NEXT
CLOSE #1 第4个问题
这个就关系到GVB的局限性了
因为显存里每字节对应屏幕上并列的8个点,想在GVB里通过POKE直接把数据写到显存里的话,每次poke都必须同时改动8个点,所以所谓的在任意位置显示图片,最小的图片大小应该是8x1(如果这么小也算是图的话......=.=),而且显示的横坐标只能是8的整数倍。
希望横坐标不是整数倍也不是不行,只要通过计算,得出显存该位置现在对应的数据就成。下面举个例子
假设我的机器是NC3K(显存开始的位置为6592)。在屏幕最上方,坐标(8,0)~(15,0)画一条长度为16的直线,这条直线就是我们最初的图形,现在它开始的横坐标还是8的整数倍。POKE 6592,0: POKE 6593,255: POKE 6594,255。
现在我希望把这幅图片(拜托把这条线想像成图片吧=.=)坐移3个坐标,那么在显存里实际应该是这样的:
由
00000000 11111111 11111111
变成
00000111 11111111 11111000
我要进行的操作是POKE 6592,7: POKE 6593,255: POKE 6594,248
看起来似乎不是很难,操作起来也不是很难,实际上根本就不难。
因为我的图片是一条黑线,背景又是单纯的白色,移动图片后那3个地址对应的数据一看就知道了,当然不会难。但是如果我的图片是个16x16的文字,就不那么好办了。数据不好算就是个大问题。
虽然不是不能算出来,不过你想要算法的话自己稍微琢磨一下也可以轻易得出,这里给出左移时计算显存中一个字节的算法(不考虑边界):
T=PEEK(A) 读取A地址处的数据
S=T*2^N 二进制中左移N个单位,其实就是乘以N个2
T=T-INT(S/256)*256 去掉上一步中多出来的部分,如果化为2进制的话,即只留最右边的8位
P=PEEK(A+1) 读取A右侧相邻的地址中的数据
T=T+INT(P/(2^(7-N))) 先右移7-N位,取整之后就是需要移过来的部分,加到T上去。
POKE A,T 算完后将数据送入该地址
这个算法中,假设要计算的地址是A(你想成上面的6593也可以),需要左移N个单位(默认N<8)。S、T、P都是临时使用的变量。
简化后的公式是T=PEEK(A):S=T*2^N: POKE A,T-INT(S/256)*256+INT(PEEK(A+1)/(2^(7-N)))
相信任何人都能看出这个算法的繁杂。需要显示到任意位置不是不可能,如果图片比较大,用GVB来计算并处理的话效率就太低了。红鸡并不是不能够做到这点,之所以只在8的整数倍处贴图,不过是因为处理起来比较简单。
真正想高效地在任意位置贴图,只用使用GVB+汇编。上面这个公式,在汇编里有专门的指令(ROL)来执行,比GVB不知道快多少倍。
作为高级语言的GVB,虽然好理解,但是在这种细节方面就没办法不输给机器语言了..
[ 本帖最后由 windybell 于 2008-6-5 08:17 编辑 ] 第5个问题
同楼上,这个也关系到GVB的局限性
LZ所说的显示灰度图片的BAS程序一定是典型的GVB+Mcode程序。不靠汇编,单以GVB的效率,根本无法保证图片的刷新率(连显示一幅图都麻烦死=.=) 大家都很积极啊。看来BAS很有希望的。:loveliness:
页:
[1]